Mahnungen: Offene Gutschriften anzeigen und bei Auswahl gegen Offene Posten rechnen
authorJan Büren <jan@kivitendo.de>
Fri, 1 May 2020 09:39:21 +0000 (11:39 +0200)
committerJan Büren <jan@kivitendo.de>
Fri, 1 May 2020 09:39:21 +0000 (11:39 +0200)
Falls der Haken in der Übersicht gemacht wird, werden alle offenen
Gutschriften für den jeweiligen Kunden angezeigt. Wenn diese aktiviert
werden, werden diese Gutschriften für die jeweilige Mahnstufe ausgegeben.
Entsprechend wird die Summe der offenen Zahlung reduziert.
Offen: Im Mahnungsbericht werden die Mahnungen dann allerdings ohne
die Gutschriften angezeigt

SL/DN.pm
bin/mozilla/dn.pl
locale/de/all
templates/webpages/dunning/add.html
templates/webpages/dunning/show_invoices.html

index ee06cd8..976b6aa 100644 (file)
--- a/SL/DN.pm
+++ b/SL/DN.pm
@@ -346,6 +346,16 @@ sub _save_dunning {
   my ($send_email, $print_invoice) = (0, 0);
 
   foreach my $row (@{ $rows }) {
+    if ($row->{credit_note}) {
+      my $i = $row->{row};
+      %{ $form->{LIST_CREDIT_NOTES}{$row->{customer_id}}{$row->{invoice_id}} } = (
+        open_amount => $form->{"open_amount_$i"},
+        amount      => $form->{"amount_$i"},
+        invnumber   => $form->{"invnumber_$i"},
+        invdate     => $form->{"invdate_$i"},
+      );
+      next;
+    }
     push @invoice_ids, $row->{invoice_id};
     $next_dunning_config_id = $row->{next_dunning_config_id};
     $customer_id            = $row->{customer_id};
@@ -364,6 +374,9 @@ sub _save_dunning {
                $next_config_id, $next_config_id);
     do_statement($form, $h_insert_dunning, $q_insert_dunning, @values);
   }
+  # die this transaction, because for this customer only credit notes are
+  # selected ...
+  return unless $customer_id;
 
   $h_update_ar->finish();
   $h_insert_dunning->finish();
@@ -580,6 +593,7 @@ sub get_invoices {
   if (!$form->{l_include_direct_debit}) {
     $where .= qq| AND NOT COALESCE(a.direct_debit, FALSE) |;
   }
+  my $paid = ($form->{l_include_credit_notes}) ? "WHERE (a.paid <> a.amount)" : "WHERE (a.paid < a.amount)";
 
   $query =
     qq|SELECT
@@ -628,9 +642,8 @@ sub get_invoices {
          WHERE (d2.trans_id      = a.id)
            AND (d2.dunning_level = cfg.dunning_level)
        ))
-
-       WHERE (a.paid < a.amount)
-         AND (a.duedate < current_date)
+        $paid
+        AND (a.duedate < current_date)
 
        $where
 
@@ -641,7 +654,7 @@ sub get_invoices {
 
   while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
     next if ($ref->{pastdue} < $ref->{terms});
-
+    $ref->{credit_note} = 1 if ($ref->{amount} < 0 && $form->{l_include_credit_notes});
     $ref->{interest} = $form->round_amount($ref->{interest}, 2);
     push(@{ $form->{DUNNINGS} }, $ref);
   }
@@ -869,6 +882,14 @@ sub print_dunning {
   }
   $sth->finish();
 
+  # if we have some credit notes to add, do a safety check on the first customer id
+  # and add one entry for each credit note
+  if ($form->{LIST_CREDIT_NOTES} && $form->{LIST_CREDIT_NOTES}->{$form->{TEMPLATE_ARRAYS}->{"dn_customer_id"}[0]}) {
+    my $first_customer_id = $form->{TEMPLATE_ARRAYS}->{"dn_customer_id"}[0];
+    while ( my ($cred_id, $value) = each(%{ $form->{LIST_CREDIT_NOTES}->{$first_customer_id} } ) ) {
+      map { push @{ $form->{TEMPLATE_ARRAYS}->{"dn_$_"} }, $value->{$_} } keys %{ $value };
+    }
+  }
   $query =
     qq|SELECT
          c.id AS customer_id, c.name,         c.street,       c.zipcode,   c.city,
@@ -918,8 +939,16 @@ sub print_dunning {
   $form->{interest_rate}     = $form->format_amount($myconfig, $ref->{interest_rate} * 100);
   $form->{fee}               = $form->format_amount($myconfig, $ref->{fee}, 2);
   $form->{total_interest}    = $form->format_amount($myconfig, $form->round_amount($ref->{total_interest}, 2), 2);
-  $form->{total_open_amount} = $form->format_amount($myconfig, $form->round_amount($ref->{total_open_amount}, 2), 2);
-  $form->{total_amount}      = $form->format_amount($myconfig, $form->round_amount($ref->{fee} + $ref->{total_interest} + $ref->{total_open_amount}, 2), 2);
+  my $total_open_amount      = $ref->{total_open_amount};
+  if ($form->{l_include_credit_notes}) {
+    # a bit stupid, but redo calc because of credit notes
+    $total_open_amount      = 0;
+    foreach my $amount (@{ $form->{TEMPLATE_ARRAYS}->{dn_open_amount} }) {
+      $total_open_amount += $form->parse_amount($myconfig, $amount, 2);
+    }
+  }
+  $form->{total_open_amount} = $form->format_amount($myconfig, $form->round_amount($total_open_amount, 2), 2);
+  $form->{total_amount}      = $form->format_amount($myconfig, $form->round_amount($ref->{fee} + $ref->{total_interest} + $total_open_amount, 2), 2);
 
   $::form->format_dates($output_dateformat, $output_longdates,
     qw(dn_dunning_date dn_dunning_duedate dn_transdate dn_duedate
index 3bc7029..3124362 100644 (file)
@@ -209,7 +209,7 @@ sub save_dunning {
 
   my $saved_language_id = $form->{language_id};
 
-  if ($form->{groupinvoices}) {
+  if ($form->{groupinvoices} || $form->{l_include_credit_notes}) {
     my %dunnings_for;
 
     for my $i (1 .. $form->{rowcount}) {
@@ -223,6 +223,7 @@ sub save_dunning {
 
       push @{ $level }, { "row"                    => $i,
                           "invoice_id"             => $form->{"inv_id_$i"},
+                          "credit_note"            => $form->{"credit_note_$i"},
                           "customer_id"            => $form->{"customer_id_$i"},
                           "language_id"            => $form->{"language_id_$i"},
                           "next_dunning_config_id" => $form->{"next_dunning_config_id_$i"},
index e188831..d7dd349 100755 (executable)
@@ -161,6 +161,7 @@ $self->{texts} = {
   'Add Assortment'              => 'Sortiment erfassen',
   'Add Client'                  => 'Neuer Mandant',
   'Add Credit Note'             => 'Gutschrift erfassen',
+  'Add Credit Note for this dunning level:' => 'Diese Gutschrift für untenstehende Mahnstufe anzeigen',
   'Add Customer'                => 'Kunde erfassen',
   'Add Customer/Vendor Number as a reference add-on for SEPA export.' => 'Kunden- Lieferantennummer im Verwendungszweck bei SEPA-Überweisungen anhängen',
   'Add Delivery Note'           => 'Lieferschein erfassen',
@@ -216,6 +217,7 @@ $self->{texts} = {
   'Add new price rule item'     => 'Neue Bedingung hinzufügen',
   'Add new record template'     => 'Neue Belegvorlage hinzufügen',
   'Add note'                    => 'Notiz erfassen',
+  'Add open Credit Notes'       => 'Offene Gutschriften hinzufügen',
   'Add part'                    => 'Artikel hinzufügen',
   'Add part classification'     => 'Artikel-Klassifizierung hinzufügen',
   'Add partsgroup'              => 'Warengruppe hinzufügen',
index 1451e02..d061d2c 100644 (file)
@@ -68,5 +68,9 @@
     <th align="right" nowrap><label for="l_include_direct_debit">[% 'Include invoices with direct debit' | $T8 %]</label></th>
     <td><input type="checkbox" value="1" id="l_include_direct_debit" name="l_include_direct_debit"></td>
    </tr>
+   <tr>
+    <th align="right" nowrap><label for="l_include_credit_notes">[% 'Add open Credit Notes' | $T8 %]</label></th>
+    <td><input type="checkbox" value="1" id="l_include_credit_notes" name="l_include_credit_notes"></td>
+   </tr>
   </table>
  </form>
index 75c7703..bfa979d 100644 (file)
      </td>
 
      <td>
+      [% IF row.credit_note %]
+        [% LxERP.t8("Add Credit Note for this dunning level:") %]
+        <input type="hidden" name="credit_note_[% loop.count %]" value="1">
+      [% END %]
       <select name="next_dunning_config_id_[% loop.count %]">
        [% FOREACH cfg_row = row.DUNNING_CONFIG %]<option value="[% HTML.escape(cfg_row.id) %]" [% IF cfg_row.SELECTED %]selected[% END %]>[% HTML.escape(cfg_row.dunning_description) %]</option>[% END %]
       </select>
@@ -94,6 +98,6 @@
 
   <input name="rowcount" type="hidden" value="[% HTML.escape(rowcount) %]">
   <input name="groupinvoices" type="hidden" value="[% HTML.escape(groupinvoices) %]">
-
+  <input name="l_include_credit_notes" type="hidden" value="[% HTML.escape(l_include_credit_notes) %]">
   <input name="callback" type="hidden" value="[% HTML.escape(callback) %]">
  </form>