Warnung bei fehlendem Lieferschein als Vorgänger zur Rechnung
authorJan Büren <jan@kivitendo.de>
Thu, 14 Oct 2021 16:01:11 +0000 (18:01 +0200)
committerJan Büren <jan@kivitendo.de>
Thu, 14 Oct 2021 16:01:11 +0000 (18:01 +0200)
SL/DB/MetaSetup/Default.pm
bin/mozilla/is.pl
doc/changelog
locale/de/all
sql/Pg-upgrade2/defaults_invoice_warn_no_delivery_order.sql [new file with mode: 0644]
templates/webpages/client_config/_features.html

index 4af7d91..7da1ce5 100644 (file)
@@ -189,6 +189,7 @@ __PACKAGE__->meta->columns(
   vertreter                                 => { type => 'boolean', default => 'false' },
   warehouse_id                              => { type => 'integer' },
   warehouse_id_ignore_onhand                => { type => 'integer' },
   vertreter                                 => { type => 'boolean', default => 'false' },
   warehouse_id                              => { type => 'integer' },
   warehouse_id_ignore_onhand                => { type => 'integer' },
+  warn_no_delivery_order_for_invoice        => { type => 'boolean', default => 'false' },
   webdav                                    => { type => 'boolean', default => 'false' },
   webdav_documents                          => { type => 'boolean', default => 'false' },
   weightunit                                => { type => 'varchar', length => 5 },
   webdav                                    => { type => 'boolean', default => 'false' },
   webdav_documents                          => { type => 'boolean', default => 'false' },
   weightunit                                => { type => 'varchar', length => 5 },
index 39bfcf8..551c1d8 100644 (file)
@@ -279,14 +279,16 @@ sub setup_is_action_bar {
   my $payments_balanced       = ($::form->{oldtotalpaid} == 0);
   my $has_storno              = ($::form->{storno} && !$::form->{storno_id});
   my $may_edit_create         = $::auth->assert('invoice_edit', 1);
   my $payments_balanced       = ($::form->{oldtotalpaid} == 0);
   my $has_storno              = ($::form->{storno} && !$::form->{storno_id});
   my $may_edit_create         = $::auth->assert('invoice_edit', 1);
-  my $is_linked_bank_transaction;
+  my ($is_linked_bank_transaction, $warn_unlinked_delivery_order);
     if ($::form->{id}
         && SL::DB::Default->get->payments_changeable != 0
         && SL::DB::Manager::BankTransactionAccTrans->find_by(ar_id => $::form->{id})) {
 
       $is_linked_bank_transaction = 1;
     }
     if ($::form->{id}
         && SL::DB::Default->get->payments_changeable != 0
         && SL::DB::Manager::BankTransactionAccTrans->find_by(ar_id => $::form->{id})) {
 
       $is_linked_bank_transaction = 1;
     }
-
+  if ($::instance_conf->get_warn_no_delivery_order_for_invoice && !$form->{id}) {
+    $warn_unlinked_delivery_order = 1 unless $form->{convert_from_do_ids};
+  }
   for my $bar ($::request->layout->get('actionbar')) {
     $bar->add(
       action => [
   for my $bar ($::request->layout->get('actionbar')) {
     $bar->add(
       action => [
@@ -304,6 +306,7 @@ sub setup_is_action_bar {
           t8('Post'),
           submit   => [ '#form', { action => "post" } ],
           checks   => [ 'kivi.validate_form' ],
           t8('Post'),
           submit   => [ '#form', { action => "post" } ],
           checks   => [ 'kivi.validate_form' ],
+          confirm  => t8('The invoice is not linked with a sales delivery order. Post anyway?') x !!$warn_unlinked_delivery_order,
           disabled => !$may_edit_create                         ? t8('You must not change this invoice.')
                     : $form->{locked}                           ? t8('The billing period has already been locked.')
                     : $form->{storno}                           ? t8('A canceled invoice cannot be posted.')
           disabled => !$may_edit_create                         ? t8('You must not change this invoice.')
                     : $form->{locked}                           ? t8('The billing period has already been locked.')
                     : $form->{storno}                           ? t8('A canceled invoice cannot be posted.')
@@ -400,6 +403,7 @@ sub setup_is_action_bar {
         action => [ t8('Print and Post'),
           call     => [ 'kivi.SalesPurchase.show_print_dialog', 'print_and_post' ],
           checks   => [ 'kivi.validate_form' ],
         action => [ t8('Print and Post'),
           call     => [ 'kivi.SalesPurchase.show_print_dialog', 'print_and_post' ],
           checks   => [ 'kivi.validate_form' ],
+          confirm  => t8('The invoice is not linked with a sales delivery order. Post anyway?') x !!$warn_unlinked_delivery_order,
           disabled => !$may_edit_create                         ? t8('You must not change this invoice.')
                     : $form->{locked}                           ? t8('The billing period has already been locked.')
                     : $form->{storno}                           ? t8('A canceled invoice cannot be posted.')
           disabled => !$may_edit_create                         ? t8('You must not change this invoice.')
                     : $form->{locked}                           ? t8('The billing period has already been locked.')
                     : $form->{storno}                           ? t8('A canceled invoice cannot be posted.')
index 3661646..25ceec7 100644 (file)
@@ -23,6 +23,8 @@ Kleinere neue Features und Detailverbesserungen:
   markieren unbekannte Worte (Tippfehler) mit einer roten gewellten Linie
 - Prüfung, ob Kundenbestellnummer in Verkaufsaufträgen vorhanden ist, kann in der
   Mandantenkonfiguration eingestellt werden
   markieren unbekannte Worte (Tippfehler) mit einer roten gewellten Linie
 - Prüfung, ob Kundenbestellnummer in Verkaufsaufträgen vorhanden ist, kann in der
   Mandantenkonfiguration eingestellt werden
+- Optionale Warnung falls eine Verkaufsrechnung nicht aus einem Lieferschein
+  erzeugt wurde (Konfigurierbar in der Mandantenkonfiguration)
 
 Bugfixes (Tracker: https://www.kivitendo.de/redmine):
 
 
 Bugfixes (Tracker: https://www.kivitendo.de/redmine):
 
index 365c18c..cf42752 100755 (executable)
@@ -1561,6 +1561,7 @@ $self->{texts} = {
   'For part "#1" there is no default warehouse and bin for ignoring onhand defined.' => 'Für Artikel "#1" ist kein Standardlager/-lagerplatz für das Auslagern ohne Bestandsprüfung angegeben.',
   'For purchase delivery orders, warn on workflow to invoice if not stocked in' => 'Warnung in Einkaufslieferscheinen beim Workflow zur Rechnung ausgeben, wenn nicht eingelagert',
   'For sales delivery orders, warn on workflow to invoice if not stocked out' => 'Warnung in Verkaufslieferscheinen beim Workflow zur Rechnung ausgeben, wenn nicht ausgelagert',
   'For part "#1" there is no default warehouse and bin for ignoring onhand defined.' => 'Für Artikel "#1" ist kein Standardlager/-lagerplatz für das Auslagern ohne Bestandsprüfung angegeben.',
   'For purchase delivery orders, warn on workflow to invoice if not stocked in' => 'Warnung in Einkaufslieferscheinen beim Workflow zur Rechnung ausgeben, wenn nicht eingelagert',
   'For sales delivery orders, warn on workflow to invoice if not stocked out' => 'Warnung in Verkaufslieferscheinen beim Workflow zur Rechnung ausgeben, wenn nicht ausgelagert',
+  'For sales invoices, warn if invoice has no delivery order as a predecessor' => 'Bei Verkaufsrechnungen warnen, dass die Rechnung nicht aus einem Lieferschein generiert wurde.',
   'For type "customer" the perl module JSON is required. Please check this on system level: $ ./scripts/installation_check.pl' => 'Für den Typ "Kunde" wird das Perl Module JSON benötigt. Überprüfbar im Installationspfad mit: $ ./scripts/installation_check.pl',
   'Foreign Exchange Gain'       => 'Wechselkurserträge',
   'Foreign Exchange Loss'       => 'Wechselkursaufwendungen',
   'For type "customer" the perl module JSON is required. Please check this on system level: $ ./scripts/installation_check.pl' => 'Für den Typ "Kunde" wird das Perl Module JSON benötigt. Überprüfbar im Installationspfad mit: $ ./scripts/installation_check.pl',
   'Foreign Exchange Gain'       => 'Wechselkurserträge',
   'Foreign Exchange Loss'       => 'Wechselkursaufwendungen',
@@ -1691,6 +1692,7 @@ $self->{texts} = {
   'If disabled sales quotations cannot be converted into sales invoices directly.' => 'Falls deaktiviert, so können Verkaufsangebote nicht direkt in Verkaufsrechnungen umgewandelt werden.',
   'If enabled Factur-X/ZUGFeRD conformant sales invoice PDFs will be created.' => 'Falls aktiviert, werden Factur-X-/ZUGFeRD-konforme PDFs für Verkaufsrechnungen erzeugt.',
   'If enabled a column will be shown in sales and purchase orders that lists both the amount and the value not shipped yet for each item.' => 'Falls eingeschaltet, wird für jede Position in Auftragsbestätigungen und Lieferantenaufträgen eine Spalte mit noch nicht gelieferter Menge und Wert angezeigt.',
   'If disabled sales quotations cannot be converted into sales invoices directly.' => 'Falls deaktiviert, so können Verkaufsangebote nicht direkt in Verkaufsrechnungen umgewandelt werden.',
   'If enabled Factur-X/ZUGFeRD conformant sales invoice PDFs will be created.' => 'Falls aktiviert, werden Factur-X-/ZUGFeRD-konforme PDFs für Verkaufsrechnungen erzeugt.',
   'If enabled a column will be shown in sales and purchase orders that lists both the amount and the value not shipped yet for each item.' => 'Falls eingeschaltet, wird für jede Position in Auftragsbestätigungen und Lieferantenaufträgen eine Spalte mit noch nicht gelieferter Menge und Wert angezeigt.',
+  'If enabled a warning will be shown if a sales invoices is created without having a sales delivery order as a predecessor.' => 'Falls aktiv, wird eine Warnung beim Buchen einer Verkaufsrechnung angezeigt, falls es keinen Lieferschein als Vorgänger gibt.',
   'If enabled a warning will be shown in purchase delivery orders on workflow to invoices if positions are not stocked in.' => 'Falls aktiviert, wird eine Warnung beim Workflow von Einkaufslieferscheinen zu Rechnungen ausgegeben, wenn die Positionen noch nicht eingelagert sind.',
   'If enabled a warning will be shown in sales and purchase orders if there are two or more positions of the same part (new controller only).' => 'Falls eingeschaltet, wird eine Warnung angezeigt, wenn der Auftrag mehrere gleiche Artikel enthält (nur neuer Controller).',
   'If enabled a warning will be shown in sales and purchase orders if there the delivery date is empty.' => 'Falls aktiviert, Warnungen ausgeben sobald Aufträge (Einkauf- und Verkauf) keinen Liefertermin haben.',
   'If enabled a warning will be shown in purchase delivery orders on workflow to invoices if positions are not stocked in.' => 'Falls aktiviert, wird eine Warnung beim Workflow von Einkaufslieferscheinen zu Rechnungen ausgegeben, wenn die Positionen noch nicht eingelagert sind.',
   'If enabled a warning will be shown in sales and purchase orders if there are two or more positions of the same part (new controller only).' => 'Falls eingeschaltet, wird eine Warnung angezeigt, wenn der Auftrag mehrere gleiche Artikel enthält (nur neuer Controller).',
   'If enabled a warning will be shown in sales and purchase orders if there the delivery date is empty.' => 'Falls aktiviert, Warnungen ausgeben sobald Aufträge (Einkauf- und Verkauf) keinen Liefertermin haben.',
@@ -3526,6 +3528,7 @@ $self->{texts} = {
   'The greetings have been saved.' => 'Die Anreden wurden gespeichert',
   'The installation is currently locked.' => 'Die Installation ist momentan gesperrt.',
   'The installation is currently unlocked.' => 'Die Installation ist momentan entsperrt.',
   'The greetings have been saved.' => 'Die Anreden wurden gespeichert',
   'The installation is currently locked.' => 'Die Installation ist momentan gesperrt.',
   'The installation is currently unlocked.' => 'Die Installation ist momentan entsperrt.',
+  'The invoice is not linked with a sales delivery order. Post anyway?' => 'Diese Rechnung ist mit keinem Lieferschein verknüpft. Dennoch Buchen?',
   'The invoice recipient can either be a selected contact person (default) or the email adress set in the master data of the customer. Additionally a contact persons mail and the company\'s invoicing mail can be combined.' => 'Der E-Mail-Rechnungsempfänger ist entweder mit dem Ansprechpartner des Belegs vorbelegt (Standard) oder mit der E-Mail-Rechnungsadresse aus den Stammdaten. Alternativ können beide (Ansprechpartner in CC) vorbelegt werden.',
   'The invoices have been created. They\'re pre-selected below.' => 'Die Rechnungen wurden erzeugt. Sie sind unten vorausgewählt.',
   'The item couldn\'t be deleted!' => 'Der Artikel konnte nicht gelöscht werden!',
   'The invoice recipient can either be a selected contact person (default) or the email adress set in the master data of the customer. Additionally a contact persons mail and the company\'s invoicing mail can be combined.' => 'Der E-Mail-Rechnungsempfänger ist entweder mit dem Ansprechpartner des Belegs vorbelegt (Standard) oder mit der E-Mail-Rechnungsadresse aus den Stammdaten. Alternativ können beide (Ansprechpartner in CC) vorbelegt werden.',
   'The invoices have been created. They\'re pre-selected below.' => 'Die Rechnungen wurden erzeugt. Sie sind unten vorausgewählt.',
   'The item couldn\'t be deleted!' => 'Der Artikel konnte nicht gelöscht werden!',
diff --git a/sql/Pg-upgrade2/defaults_invoice_warn_no_delivery_order.sql b/sql/Pg-upgrade2/defaults_invoice_warn_no_delivery_order.sql
new file mode 100644 (file)
index 0000000..0038cab
--- /dev/null
@@ -0,0 +1,5 @@
+-- @tag: defaults_invoice_warn_no_delivery_order
+-- @description: Mandantenkonfiguration: Warnung bei fehlendem Lieferschein als Vorgänger zur Rechnung
+-- @depends: release_3_5_8
+
+ALTER TABLE defaults ADD COLUMN warn_no_delivery_order_for_invoice BOOLEAN DEFAULT FALSE;
index 2b9adee..1585eba 100644 (file)
    <td>[% L.yes_no_tag("defaults.sales_delivery_order_check_stocked", SELF.defaults.sales_delivery_order_check_stocked) %]</td>
    <td>[% LxERP.t8("If enabled a warning will be shown in sales delivery orders on workflow to invoices if positions are not stocked out.") %]</td>
   </tr>
    <td>[% L.yes_no_tag("defaults.sales_delivery_order_check_stocked", SELF.defaults.sales_delivery_order_check_stocked) %]</td>
    <td>[% LxERP.t8("If enabled a warning will be shown in sales delivery orders on workflow to invoices if positions are not stocked out.") %]</td>
   </tr>
-  <tr>
   <tr>
    <td align="right">[% LxERP.t8("For purchase delivery orders, warn on workflow to invoice if not stocked in") %]</td>
    <td>[% L.yes_no_tag("defaults.purchase_delivery_order_check_stocked", SELF.defaults.purchase_delivery_order_check_stocked) %]</td>
    <td>[% LxERP.t8("If enabled a warning will be shown in purchase delivery orders on workflow to invoices if positions are not stocked in.") %]</td>
   </tr>
   <tr>
   <tr>
    <td align="right">[% LxERP.t8("For purchase delivery orders, warn on workflow to invoice if not stocked in") %]</td>
    <td>[% L.yes_no_tag("defaults.purchase_delivery_order_check_stocked", SELF.defaults.purchase_delivery_order_check_stocked) %]</td>
    <td>[% LxERP.t8("If enabled a warning will be shown in purchase delivery orders on workflow to invoices if positions are not stocked in.") %]</td>
   </tr>
   <tr>
+   <td align="right">[% LxERP.t8("For sales invoices, warn if invoice has no delivery order as a predecessor") %]</td>
+   <td>[% L.yes_no_tag("defaults.warn_no_delivery_order_for_invoice", SELF.defaults.warn_no_delivery_order_for_invoice ) %]</td>
+   <td>[% LxERP.t8("If enabled a warning will be shown if a sales invoices is created without having a sales delivery order as a predecessor.") %]</td>
+  </tr>
   <tr>
    <td align="right">[% LxERP.t8("Create sales invoices with Factur-X/ZUGFeRD data") %]</td>
    <td>[% L.select_tag("defaults.create_zugferd_invoices", SELF.zugferd_settings, default=SELF.defaults.create_zugferd_invoices) %]</td>
   <tr>
    <td align="right">[% LxERP.t8("Create sales invoices with Factur-X/ZUGFeRD data") %]</td>
    <td>[% L.select_tag("defaults.create_zugferd_invoices", SELF.zugferd_settings, default=SELF.defaults.create_zugferd_invoices) %]</td>