From: Moritz Bunkus Date: Thu, 3 May 2007 10:08:04 +0000 (+0000) Subject: Große Teile des Mahncodes neu geschrieben bzw. umgeschrieben. Mehrere Fehler behoben: X-Git-Tag: release-2.4.3^2~408 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=fd6900cca59ac4a35d5fa4c20db91165f9310ea3;p=kivitendo-erp.git Große Teile des Mahncodes neu geschrieben bzw. umgeschrieben. Mehrere Fehler behoben: 1. Rechnungen, die bereits gemahnt wurden, wurden zu früh erneut zur Mahnung angeboten, weil der Mahnzeitraum auf das ursprüngliche Fälligkeitsdatum der Rechnung bezogen wurde und nicht auf das Fälligkeitsdatum der vorhergehenden Mahnstufe. 2. Wurden gleichzeitig Mahnungen für mehrere Mahnstufen generiert, so wurden die falschen Vorlagen benutzt. 3. Die kummulierten Mahnkosten und die Zinsen wurden in der Liste der neu zu erstellenden Mahnungen falsch angezeigt. Weiterhin wurde die Dokumentation für die Vorlagenvariablen um eine Sektion über Mahnungen erweitert. --- diff --git a/SL/DN.pm b/SL/DN.pm index 008a538f1..2566cbed7 100644 --- a/SL/DN.pm +++ b/SL/DN.pm @@ -56,7 +56,7 @@ sub get_config { foreach my $ref (@{ $form->{DUNNING} }) { $ref->{fee} = $form->format_amount($myconfig, $ref->{fee}, 2); - $ref->{interest} = $form->format_amount($myconfig, ($ref->{interest} * 100)); + $ref->{interest_rate} = $form->format_amount($myconfig, ($ref->{interest_rate} * 100)); } $dbh->disconnect(); @@ -76,13 +76,13 @@ sub save_config { for my $i (1 .. $form->{rowcount}) { $form->{"fee_$i"} = $form->parse_amount($myconfig, $form->{"fee_$i"}) * 1; - $form->{"interest_$i"} = $form->parse_amount($myconfig, $form->{"interest_$i"}) / 100; + $form->{"interest_rate_$i"} = $form->parse_amount($myconfig, $form->{"interest_rate_$i"}) / 100; if (($form->{"dunning_level_$i"} ne "") && ($form->{"dunning_description_$i"} ne "")) { @values = (conv_i($form->{"dunning_level_$i"}), $form->{"dunning_description_$i"}, $form->{"email_subject_$i"}, $form->{"email_body_$i"}, - $form->{"template_$i"}, $form->{"fee_$i"}, $form->{"interest_$i"}, + $form->{"template_$i"}, $form->{"fee_$i"}, $form->{"interest_rate_$i"}, $form->{"active_$i"} ? 't' : 'f', $form->{"auto_$i"} ? 't' : 'f', $form->{"email_$i"} ? 't' : 'f', $form->{"email_attachment_$i"} ? 't' : 'f', conv_i($form->{"payment_terms_$i"}), conv_i($form->{"terms_$i"})); if ($form->{"id_$i"}) { @@ -90,7 +90,7 @@ sub save_config { qq|UPDATE dunning_config SET dunning_level = ?, dunning_description = ?, email_subject = ?, email_body = ?, - template = ?, fee = ?, interest = ?, + template = ?, fee = ?, interest_rate = ?, active = ?, auto = ?, email = ?, email_attachment = ?, payment_terms = ?, terms = ? WHERE id = ?|; @@ -99,7 +99,7 @@ sub save_config { $query = qq|INSERT INTO dunning_config (dunning_level, dunning_description, email_subject, email_body, - template, fee, interest, active, auto, email, + template, fee, interest_rate, active, auto, email, email_attachment, payment_terms, terms) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)|; } @@ -129,66 +129,114 @@ sub save_dunning { my ($dunning_id) = selectrow_query($form, $dbh, qq|SELECT nextval('id')|); + my $q_update_ar = qq|UPDATE ar SET dunning_config_id = ? WHERE id = ?|; + my $h_update_ar = prepare_query($form, $dbh, $q_update_ar); + + my $q_insert_dunning = + qq|INSERT INTO dunning (dunning_id, dunning_config_id, dunning_level, + trans_id, fee, interest, transdate, duedate) + VALUES (?, ?, + (SELECT dunning_level FROM dunning_config WHERE id = ?), + ?, + (SELECT SUM(fee) + FROM dunning_config + WHERE dunning_level <= (SELECT dunning_level FROM dunning_config WHERE id = ?)), + (SELECT (amount - paid) * (current_date - transdate) FROM ar WHERE id = ?) + * (SELECT interest_rate FROM dunning_config WHERE id = ?) + / 360, + current_date, + current_date + (SELECT payment_terms FROM dunning_config WHERE id = ?))|; + my $h_insert_dunning = prepare_query($form, $dbh, $q_insert_dunning); + + my @invoice_ids; + my ($next_dunning_config_id, $customer_id); + my $send_email = 0; + foreach my $row (@{ $rows }) { + push @invoice_ids, $row->{invoice_id}; + $next_dunning_config_id = $row->{next_dunning_config_id}; + $customer_id = $row->{customer_id}; + + @values = ($row->{next_dunning_config_id}, $row->{invoice_id}); + do_statement($form, $h_update_ar, $q_update_ar, @values); + + $send_email |= $row->{email}; - $form->{"interest_$row"} = $form->parse_amount($myconfig,$form->{"interest_$row"}); - $form->{"fee_$row"} = $form->parse_amount($myconfig,$form->{"fee_$row"}); - $form->{send_email} = $form->{"email_$row"}; - - $query = qq|UPDATE ar SET dunning_config_id = ? WHERE id = ?|; - @values = ($form->{"next_dunning_config_id_$row"}, - $form->{"inv_id_$row"}); - do_query($form, $dbh, $query, @values); - - $query = - qq|INSERT INTO dunning (dunning_id, dunning_config_id, dunning_level, - trans_id, fee, interest, transdate, duedate) - VALUES (?, ?, (SELECT dunning_level FROM dunning_config WHERE id = ?), - ?, ?, ?, current_date, ?)|; - @values = ($dunning_id, - conv_i($form->{"next_dunning_config_id_$row"}), - conv_i($form->{"next_dunning_config_id_$row"}), - conv_i($form->{"inv_id_$row"}), $form->{"fee_$row"}, - $form->{"interest_$row"}, - conv_date($form->{"next_duedate_$row"})); - do_query($form, $dbh, $query, @values); + my $next_config_id = conv_i($row->{next_dunning_config_id}); + my $invoice_id = conv_i($row->{invoice_id}); + + @values = ($dunning_id, $next_config_id, $next_config_id, + $invoice_id, $next_config_id, $invoice_id, + $next_config_id, $next_config_id); + do_statement($form, $h_insert_dunning, $q_insert_dunning, @values); } + $h_update_ar->finish(); + $h_insert_dunning->finish(); + my $query = - qq|SELECT invnumber, ordnumber, customer_id, amount, netamount, - ar.transdate, ar.duedate, paid, amount - paid AS open_amount, - template AS formname, email_subject, email_body, email_attachment, - da.fee, da.interest, da.transdate AS dunning_date, - da.duedate AS dunning_duedate, - c.name, c.street, c.zipcode, c.city, c.country, c.department_1, c.department_2 + qq|SELECT + ar.invnumber, ar.ordnumber, ar.amount, ar.netamount, + ar.transdate, ar.duedate, ar.paid, ar.amount - ar.paid AS open_amount, + da.fee, da.interest, da.transdate AS dunning_date, da.duedate AS dunning_duedate FROM ar - LEFT JOIN dunning_config ON (dunning_config.id = ar.dunning_config_id) - LEFT JOIN dunning da ON (ar.id = da.trans_id AND dunning_config.dunning_level = da.dunning_level) - LEFT JOIN customer c ON (ar.customer_id = c.id) + LEFT JOIN dunning_config cfg ON (cfg.id = ar.dunning_config_id) + LEFT JOIN dunning da ON (ar.id = da.trans_id AND cfg.dunning_level = da.dunning_level) WHERE ar.id IN (| - . join(", ", map("?", @{ $form->{"inv_ids"} })) . qq|)|; + . join(", ", map { "?" } @invoice_ids) . qq|)|; - my $sth = prepare_execute_query($form, $dbh, $query, @{ $form->{"inv_ids"} }); + my $sth = prepare_execute_query($form, $dbh, $query, @invoice_ids); my $first = 1; while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { if ($first) { map({ $form->{"dn_$_"} = []; } keys(%{$ref})); $first = 0; } + + $ref->{interest_rate} = $form->format_amount($myconfig, $ref->{interest_rate} * 100); map { $ref->{$_} = $form->format_amount($myconfig, $ref->{$_}, 2) } qw(amount netamount paid open_amount fee interest); - map { $form->{$_} = $ref->{$_} } keys %$ref; - #print(STDERR Dumper($ref)); map { push(@{ $form->{"dn_$_"} }, $ref->{$_})} keys %$ref; + map { $form->{$_} = $ref->{$_} } keys %{ $ref }; } $sth->finish; - IS->customer_details($myconfig,$form); - #print(STDERR Dumper($form->{dn_invnumber})); - $form->{templates} = "$myconfig->{templates}"; - - + $query = + qq|SELECT id AS customer_id, name, street, zipcode, city, country, department_1, department_2, email + FROM customer + WHERE id = ?|; + $ref = selectfirst_hashref_query($form, $dbh, $query, $customer_id); + map { $form->{$_} = $ref->{$_} } keys %{ $ref }; - $form->{language} = $form->get_template_language(\%myconfig); + $query = + qq|SELECT + cfg.interest_rate, cfg.template AS formname, + cfg.email_subject, cfg.email_body, cfg.email_attachment, + (SELECT fee + FROM dunning + WHERE dunning_id = ? + LIMIT 1) + AS fee, + (SELECT SUM(interest) + FROM dunning + WHERE dunning_id = ?) + AS total_interest, + (SELECT SUM(amount) - SUM(paid) + FROM ar + WHERE id IN (| . join(", ", map { "?" } @invoice_ids) . qq|)) + AS total_open_amount + FROM dunning_config cfg + WHERE id = ?|; + $ref = selectfirst_hashref_query($form, $dbh, $query, $dunning_id, $dunning_id, @invoice_ids, $next_dunning_config_id); + map { $form->{$_} = $ref->{$_} } keys %{ $ref }; + + $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); + + $form->{templates} = "$myconfig->{templates}"; + $form->{language} = $form->get_template_language(\%myconfig); $form->{printer_code} = $form->get_printer_code(\%myconfig); if ($form->{language} ne "") { @@ -215,7 +263,7 @@ sub save_dunning { $form->{"IN"} =~ s/html$/odt/; } - if ($form->{"send_email"} && ($form->{email} ne "")) { + if ($send_email && ($form->{email} ne "")) { $form->{media} = 'email'; } @@ -259,24 +307,7 @@ sub get_invoices { # connect to database my $dbh = $form->dbconnect($myconfig); - my $where = - qq| WHERE (a.paid < a.amount) - AND (a.duedate < current_date) - AND (dnn.id = - (SELECT id FROM dunning_config - WHERE dunning_level > - (SELECT - CASE - WHEN a.dunning_config_id IS NULL - THEN 0 - ELSE (SELECT dunning_level - FROM dunning_config - WHERE id = a.dunning_config_id - ORDER BY dunning_level - LIMIT 1) - END - FROM dunning_config LIMIT 1) - LIMIT 1)) |; + my $where; my @values; $form->{customer_id} = $1 if ($form->{customer} =~ /--(\d+)$/); @@ -312,37 +343,57 @@ sub get_invoices { push(@values, $form->{minamount}); } - $paymentdate = $form->{paymentuntil} ? $dbh->quote($form->{paymentuntil}) : - "current_date"; - $query = - qq|SELECT a.id, a.ordnumber, a.transdate, a.invnumber, a.amount, + qq|SELECT + a.id, a.ordnumber, a.transdate, a.invnumber, a.amount, ct.name AS customername, a.customer_id, a.duedate, - da.fee AS old_fee, dnn.active, dnn.email, dnn.fee + da.fee AS fee, - dn.dunning_description, da.transdate AS dunning_date, da.duedate AS dunning_duedate, - a.duedate + dnn.terms - current_date AS nextlevel, - $paymentdate - a.duedate AS pastdue, dn.dunning_level, - current_date + dnn.payment_terms AS next_duedate, - dnn.dunning_description AS next_dunning_description, dnn.id AS next_dunning_config_id, - dnn.interest AS interest_rate, dnn.terms - FROM dunning_config dnn, ar a - JOIN customer ct ON (a.customer_id = ct.id) - LEFT JOIN dunning_config dn ON (dn.id = a.dunning_config_id) - LEFT JOIN dunning da ON ((da.trans_id = a.id) AND (dn.dunning_level = da.dunning_level)) + + cfg.dunning_description, cfg.dunning_level, + + d.transdate AS dunning_date, d.duedate AS dunning_duedate, + d.fee, d.interest, + + a.duedate + cfg.terms - current_date AS nextlevel, + current_date - COALESCE(d.duedate, a.duedate) AS pastdue, + current_date + cfg.payment_terms AS next_duedate, + + nextcfg.dunning_description AS next_dunning_description, + nextcfg.id AS next_dunning_config_id, + nextcfg.terms, nextcfg.active, nextcfg.email + + FROM ar a + + LEFT JOIN customer ct ON (a.customer_id = ct.id) + LEFT JOIN dunning_config cfg ON (a.dunning_config_id = cfg.id) + LEFT JOIN dunning_config nextcfg ON + (nextcfg.id = + (SELECT id + FROM dunning_config + WHERE dunning_level > + COALESCE((SELECT dunning_level + FROM dunning_config + WHERE id = a.dunning_config_id + ORDER BY dunning_level DESC + LIMIT 1), + 0) + LIMIT 1)) + LEFT JOIN dunning d ON ((d.trans_id = a.id) AND (cfg.dunning_level = d.dunning_level)) + + WHERE (a.paid < a.amount) + AND (a.duedate < current_date) + $where - ORDER BY a.id, transdate, duedate, name|; + ORDER BY a.id, transdate, duedate, name|; my $sth = prepare_execute_query($form, $dbh, $query, @values); $form->{DUNNINGS} = []; while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { - $ref->{interest} = ($ref->{amount} * $ref->{pastdue} * $ref->{interest_rate}) / 360; + next if !$ref->{terms} || ($ref->{pastdue} < $ref->{terms}); + $ref->{interest} = $form->round_amount($ref->{interest}, 2); - map({ $ref->{$_} = $form->format_amount($myconfig, $ref->{$_}, 2)} qw(amount fee interest)); - if ($ref->{pastdue} >= $ref->{terms}) { - push(@{ $form->{DUNNINGS} }, $ref); - } + push(@{ $form->{DUNNINGS} }, $ref); } $sth->finish; @@ -555,7 +606,7 @@ Content-Length: $numbytes sub print_dunning { $main::lxdebug->enter_sub(); - my ($self, $myconfig, $form, $dunning_id, $userspath,$spool, $sendmail) = @_; + my ($self, $myconfig, $form, $dunning_id, $userspath, $spool, $sendmail) = @_; # connect to database my $dbh = $form->dbconnect_noauto($myconfig); @@ -582,7 +633,47 @@ sub print_dunning { } $sth->finish; - IS->customer_details($myconfig,$form); + $query = + qq|SELECT id AS customer_id, name, street, zipcode, city, country, department_1, department_2, email + FROM customer + WHERE id = + (SELECT customer_id + FROM dunning d + LEFT JOIN ar ON (d.trans_id = ar.id) + WHERE d.id = ?)|; + $ref = selectfirst_hashref_query($form, $dbh, $query, $dunning_id); + map { $form->{$_} = $ref->{$_} } keys %{ $ref }; + + $query = + qq|SELECT + cfg.interest_rate, cfg.template AS formname, + cfg.email_subject, cfg.email_body, cfg.email_attachment, + d.fee, d.dunning_date, + (SELECT SUM(interest) + FROM dunning + WHERE dunning_id = ?) + AS total_interest, + (SELECT SUM(amount) - SUM(paid) + FROM ar + WHERE id IN + (SELECT trans_id + FROM dunning + WHERE dunning_id = ?)) + AS total_open_amount + FROM dunning d + LEFT JOIN dunning_config cfg ON (d.dunning_config_id = cfg.id) + WHERE d.dunning_id = ? + LIMIT 1|; + $ref = selectfirst_hashref_query($form, $dbh, $query, $dunning_id, $dunning_id, $dunning_id); + map { $form->{$_} = $ref->{$_} } keys %{ $ref }; + + $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); + + $form->{templates} = "$myconfig->{templates}"; $form->{language} = $form->get_template_language(\%myconfig); diff --git a/bin/mozilla/dn.pl b/bin/mozilla/dn.pl index 844abf5b5..ee77c8224 100644 --- a/bin/mozilla/dn.pl +++ b/bin/mozilla/dn.pl @@ -54,7 +54,7 @@ sub edit_config { "$form->{script}?action=edit_config&login=$form->{login}&password=$form->{password}" unless $form->{callback}; - @column_index = qw(dunning_level dunning_description active auto email payment_terms terms fee interest template); + @column_index = qw(dunning_level dunning_description active auto email payment_terms terms fee interest_rate template); $column_header{dunning_level} = qq|| @@ -88,7 +88,7 @@ sub edit_config { qq|| . $locale->text('Fee') . qq||; - $column_header{interest} = + $column_header{interest_rate} = qq|| . $locale->text('Interest Rate') . qq||; @@ -141,7 +141,7 @@ sub edit_config { $column_data{payment_terms} = qq||; $column_data{terms} = qq||; $column_data{fee} = qq||; - $column_data{interest} = qq|%|; + $column_data{interest_rate} = qq|%|; $column_data{template} = qq||; @@ -174,7 +174,7 @@ sub edit_config { $column_data{payment_terms} = qq||; $column_data{terms} = qq||; $column_data{fee} = qq||; - $column_data{interest} = qq|%|; + $column_data{interest_rate} = qq|%|; $column_data{template} = qq||; @@ -260,36 +260,19 @@ sub add { | if $form->{selectdepartment}; - $form->{title} = $locale->text('Start Dunning Process'); - $form->{nextsub} = "show_invoices"; - - # use JavaScript Calendar or not - $form->{jsscript} = $jscalendar; - $jsscript = ""; - if ($form->{jsscript}) { - - # with JavaScript Calendar - $button1 = qq| - - text('button') . qq|> - |; - #write Trigger - $jsscript = - Form->write_trigger(\%myconfig, "1", "paymentuntil", "BR", "trigger1"); - } else { + $form->{title} = $locale->text('Start Dunning Process'); + $form->{nextsub} = "show_invoices"; - # without JavaScript Calendar - $button1 = - qq||; - } - $form->{fokus} = "search.customer"; + $form->{jsscript} = 1; + $form->{fokus} = "search.customer"; $form->{javascript} .= qq||; - $form->header; + $form->header(); + $onload = qq|focus()|; $onload .= qq|;setupDateFormat('|. $myconfig{dateformat} .qq|', '|. $locale->text("Falsches Datumsformat!") .qq|')|; $onload .= qq|;setupPoints('|. $myconfig{numberformat} .qq|', '|. $locale->text("wrongformat") .qq|')|; + print qq| @@ -319,10 +302,6 @@ sub add { | . $locale->text('Notes') . qq| - - | . $locale->text('Payment until') . qq| - $button1 - @@ -390,17 +369,17 @@ sub show_invoices { "$form->{script}?action=show_invoices&login=$form->{login}&password=$form->{password}&customer=$form->{customer}&invnumber=$form->{invnumber}&ordnumber=$form->{ordnumber}&paymentuntil=$form->{paymentuntil}&groupinvoices=$form->{groupinvoices}&minamount=$form->{minamount}&dunning_level=$form->{dunning_level}¬es=$form->{notes}" unless $form->{callback}; - @column_index = qw(dunning_description active email customername invnumber invdate inv_duedate invamount next_duedate fee interest ); + @column_index = qw(dunning_description dunning_description_next active email customername invnumber invdate inv_duedate amount next_duedate fee interest ); $column_header{dunning_description} = - qq|| + qq|| . $locale->text('Current / Next Level') . qq||; $column_header{active} = qq|| . NTI($cgi->checkbox('-name' => 'selectall_active', '-label' => $locale->text('Active?'), - '-checked' => 1, + '-checked' => 0, '-onclick' => "checkbox_check_all('selectall_active', 'active_', 1, " . scalar(@{ $form->{DUNNINGS} }) . ")")) . qq||; $column_header{email} = @@ -430,7 +409,7 @@ sub show_invoices { qq|| . $locale->text('Invdate') . qq||; - $column_header{invamount} = + $column_header{amount} = qq|| . $locale->text('Amount') . qq||; @@ -440,7 +419,7 @@ sub show_invoices { . qq||; $column_header{interest} = qq|| - . $locale->text('Total Interest') + . $locale->text('Interest') . qq||; $form->header; @@ -455,11 +434,11 @@ sub show_invoices { - + |; - map { print "$column_header{$_}\n" } @column_index; + map { print "$column_header{$_}\n" if $column_header{$_}; } @column_index; print qq| @@ -474,33 +453,39 @@ sub show_invoices { |; - $form->{selectdunning} =~ s/ selected//g; - if ($ref->{next_dunning_config_id} ne "") { - $form->{selectdunning} =~ s/value=$ref->{next_dunning_config_id}/value=$ref->{next_dunning_config_id} selected/; - } - - - $dunning = qq||; - + $form->{selectdunning} =~ s/ selected//g; + if ($ref->{next_dunning_config_id} ne "") { + $form->{selectdunning} =~ s/value=$ref->{next_dunning_config_id}/value=$ref->{next_dunning_config_id} selected/; + } - $column_data{dunning_description} = qq||; + $column_data{dunning_description} = + qq||; + $column_data{dunning_description_next} = + qq||; my $active = ($ref->{active}) ? "checked" : ""; $column_data{active} = qq||; my $email = ($ref->{email}) ? "checked" : ""; - $column_data{email} = - qq||; - $column_data{next_duedate} = qq||; + $column_data{email} = + qq||; + $column_data{next_duedate} = qq||; $column_data{inv_duedate} = qq||; $column_data{invdate} = qq||; $column_data{invnumber} = qq||; $column_data{customername} = qq||; - $column_data{invamount} = qq||; - $column_data{fee} = qq||; - $column_data{interest} = qq||; - + map { $column_data{$_} = + qq|| + } qw(amount fee interest); map { print "$column_data{$_}\n" } @column_index; @@ -578,55 +563,64 @@ sub save_dunning { my $active=1; my @rows = (); undef($form->{DUNNING_PDFS}); + if ($form->{groupinvoices}) { - while ($active) { - $lastcustomer = 0; - $form->{inv_ids} = []; - $active = 0; - @rows = (); - for my $i (1 .. $form->{rowcount}) { - $form->{"active_$i"} *= 1; - $lastcustomer = $form->{"customer_id_$i"} unless ($lastcustomer); - if ($form->{"active_$i"} && ($form->{"customer_id_$i"} == $lastcustomer)) { - push(@{ $form->{inv_ids} }, $form->{"inv_id_$i"}); - $form->{"active_$i"} = 0; - $form->{"customer_id_$i"} = 0; - push(@rows, $i); - } elsif ($form->{"active_$i"}) { - $active = 1; - } else { - $form->{"customer_id_$i"} = 0; - } - } - if (scalar(@{ $form->{inv_ids} }) != 0) { - DN->save_dunning(\%myconfig, \%$form, \@rows, $userspath, $spool, $sendmail); + my %dunnings_for; + + for my $i (1 .. $form->{rowcount}) { + next unless ($form->{"active_$i"}); + + $dunnings_for{$form->{"customer_id_$i"}} ||= {}; + my $dunning_levels = $dunnings_for{$form->{"customer_id_$i"}}; + + $dunning_levels->{$form->{"next_dunning_config_id_$i"}} ||= []; + my $level = $dunning_levels->{$form->{"next_dunning_config_id_$i"}}; + + push @{ $level }, { "row" => $i, + "invoice_id" => $form->{"inv_id_$i"}, + "customer_id" => $form->{"customer_id_$i"}, + "next_dunning_config_id" => $form->{"next_dunning_config_id_$i"}, + "email" => $form->{"email_$i"}, }; + } + + foreach my $levels (values %dunnings_for) { + foreach my $level (values %{ $levels }) { + next unless scalar @{ $level }; + + DN->save_dunning(\%myconfig, \%$form, $level, $userspath, $spool, $sendmail); } } + } else { for my $i (1 .. $form->{rowcount}) { - if ($form->{"active_$i"}) { - @rows = (); - $form->{inv_ids} = [ $form->{"inv_id_$i"} ]; - push(@rows, $i); - DN->save_dunning(\%myconfig, \%$form, \@rows, $userspath, $spool, $sendmail); - } + next unless $form->{"active_$i"}; + + my $level = [ { "row" => $i, + "invoice_id" => $form->{"inv_id_$i"}, + "customer_id" => $form->{"customer_id_$i"}, + "next_dunning_config_id" => $form->{"next_dunning_config_id_$i"}, + "email" => $form->{"email_$i"}, } ]; + DN->save_dunning(\%myconfig, \%$form, $level, $userspath, $spool, $sendmail); } } + if($form->{DUNNING_PDFS}) { DN->melt_pdfs(\%myconfig, \%$form,$spool); } + # saving the history if(!exists $form->{addition} && $form->{id} ne "") { $form->{snumbers} = qq|dunning_id_| . $form->{"dunning_id"}; $form->{addition} = "DUNNING STARTED"; $form->save_history($form->dbconnect(\%myconfig)); } - # /saving the history + # /saving the history + $form->redirect($locale->text('Dunning Process started for selected invoices!')); $lxdebug->leave_sub(); } - + sub set_email { $lxdebug->enter_sub(); @@ -878,7 +872,7 @@ sub show_dunning { . qq||; $column_header{interest} = qq||; $form->header; @@ -931,8 +925,7 @@ sub show_dunning { - foreach (qw(dunning_date dunning_duedate duedate transdate customername - amount fee interest)) { + foreach (qw(dunning_date dunning_duedate duedate transdate customername amount fee interest)) { my $col = $columns{$_} ? $columns{$_} : $_; $column_data{$col} = ""; } diff --git a/doc/dokumentenvorlagen-und-variablen.html b/doc/dokumentenvorlagen-und-variablen.html index cb2dd6870..986ae971c 100644 --- a/doc/dokumentenvorlagen-und-variablen.html +++ b/doc/dokumentenvorlagen-und-variablen.html @@ -81,6 +81,18 @@ td { +
  • + Variablen in Mahnungen + +
      +
    1. + Allgemeine Variablen
    2. + +
    3. + Variablen für jede gemahnte Rechnung
    4. +
    +
  • +
  • Variablen in anderen Vorlagen
  • @@ -758,6 +770,111 @@ td { zum Inhaltsverzeichnis

    +

    Variablen in Mahnungen

    + +

    Allgemeine Variablen:

    + +

    Die Variablen des Verkäufers stehen wie gewohnt + als employee_... zur Verfügung. Die Adressdaten des + Kunden stehen als Variablen name, street, + zipcode, city, country, + department_1, department_2, und + email zur Verfügung. +

    + +

    Weitere Variablen beinhalten:

    + +

    +

    $form->{title}$form->{title}
    $ref->{dunning_level}: $dunning| + . qq|| + . qq|| + . ($ref->{dunning_level} ? $ref->{dunning_level} : " ") + . qq|| + . qq|| + . qq|$ref->{next_duedate}$ref->{next_duedate}$ref->{duedate}$ref->{transdate}$ref->{invnumber}$ref->{customername}$ref->{amount}$ref->{fee}$ref->{interest}| + . H($form->format_amount(\%myconfig, $ref->{$_} * 1, -2)) + . qq|| - . $locale->text('Total Interest') + . $locale->text('Interest') . qq|" . H($ref->{$_}) . "
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    VariablennameBedeutung
    dunning_dateDatum der Mahnung
    dunning_duedateFälligkeitsdatum für diese Mahhnung
    feeKummulative Mahngebühren
    interest_rateZinssatz per anno in Prozent
    total_amountGesamter noch zu zahlender Betrag als fee + total_interest + total_open_amount
    total_interestZinsen per anno über alle Rechnungen
    total_open_amountSumme über alle offene Beträge der Rechnungen
    +

    + +

    + Variablen für jede gemahnte Rechnung:

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    VariablennameBedeutung
    dn_amountRechnungssumme (brutto)
    dn_duedateOriginales Fälligkeitsdatum der Rechnung
    dn_dunning_dateDatum der Mahnung
    dn_dunning_duedateFälligkeitsdatum der Mahnung
    dn_feeKummulative Mahngebühr (ist die gleiche wie für die ganze Mahnung, da die Gebühr nur einmal pro Mahnung erhoben wird)
    dn_interestZinsen per anno f&uum;r diese Rechnung
    dn_invnumberRechnungsnummer
    dn_netamountRechnungssumme (netto)
    dn_open_amountOffener Rechnungsbetrag
    dn_ordnumberBestellnummer
    dn_transdateRechnungsdatum
    +

    + + + zum Inhaltsverzeichnis
    +
    +

    Variablen in anderen Vorlagen

    diff --git a/locale/de/all b/locale/de/all index 8d5a96e50..061081279 100644 --- a/locale/de/all +++ b/locale/de/all @@ -557,6 +557,7 @@ gestartet', 'Increase' => 'Erhöhen', 'Individual Items' => 'Einzelteile', 'Information' => 'Information', + 'Interest' => 'Zinsen', 'Interest Rate' => 'Zinssatz', 'Internal Notes' => 'interne Bemerkungen', 'International' => 'Ausland', @@ -792,7 +793,6 @@ gestartet', 'Payment date missing!' => 'Tag der Zahlung fehlt!', 'Payment posted!' => 'Zahlung gebucht!', 'Payment terms deleted!' => 'Zahlungskonditionen gelöscht!', - 'Payment until' => 'Zahlungseingänge bis', 'Payments' => 'Zahlungsausgänge', 'Pg Database Administration' => 'Datenbankadministration', 'Phone' => 'Telefon', @@ -1018,7 +1018,6 @@ gestartet', 'Tax number' => 'Steuernummer', 'Tax paid' => 'Vorsteuer', 'Tax-o-matic Account' => 'Automatikbuchung auf Konto', - 'Tax-o-matic Account: ' => '', 'Taxaccount_coa' => 'Automatikkonto', 'Taxation' => 'Versteuerungs Verfahren', 'Taxdescription_coa' => 'Steuer', @@ -1086,7 +1085,6 @@ gestartet', 'Top Level' => 'Hauptartikelbezeichnung', 'Total' => 'Summe', 'Total Fees' => 'Kumulierte Gebühren', - 'Total Interest' => 'Kumulierte Zinsen', 'Trade Discount' => 'Rabatt', 'Transaction Date missing!' => 'Buchungsdatum fehlt!', 'Transaction deleted!' => 'Buchung gelöscht!', diff --git a/locale/de/am b/locale/de/am index 8c44ebe12..6a7dc4c7f 100644 --- a/locale/de/am +++ b/locale/de/am @@ -11,8 +11,6 @@ $self->{texts} = { '<%total%> -- Amount payable' => '<%total%> -- Noch zu bezahlender Betrag', 'A unit with this name does already exist.' => 'Eine Einheit mit diesem Namen existiert bereits.', 'ADDED' => 'Hinzugefügt', - 'AP' => 'Einkauf', - 'AR' => 'Verkauf', 'Account' => 'Konto', 'Account Category A' => 'Aktiva/Mittelverwendung', 'Account Category C' => 'Kosten', @@ -21,6 +19,7 @@ $self->{texts} = { 'Account Category I' => 'Erlöskonto', 'Account Category L' => 'Passiva/Mittelherkunft', 'Account Category Q' => 'Passiva', + 'Account Description missing!' => 'Beschreibung fehlt!', 'Account Link AP' => 'Einkauf', 'Account Link AP_amount' => 'Verbindlichkeiten Aufwand/Anlagen', 'Account Link AP_paid' => 'Verbindlichkeiten Zahlungsausgang', @@ -37,9 +36,7 @@ $self->{texts} = { 'Account Link IC_sale' => 'Warenliste Erlöskonto', 'Account Link IC_taxpart' => 'Warenliste Steuer', 'Account Link IC_taxservice' => 'Dienstleistungen Steuer', - 'Account Number' => 'Kontonummer', 'Account Number missing!' => 'Kontonummer fehlt!', - 'Account Type' => 'Kontoart', 'Account Type missing!' => 'Kontoart fehlt!', 'Account deleted!' => 'Konto gelöscht!', 'Account saved!' => 'Konto gespeichert!', @@ -64,9 +61,7 @@ $self->{texts} = { 'Aufwand EU m. UStId' => 'Aufwand EU m. UStId', 'Aufwand EU o. UStId' => 'Aufwand EU o. UStId', 'Aufwand Inland' => 'Aufwand Inland', - 'BWA' => 'BWA', 'Bestandskonto' => 'Bestandskonto', - 'Bilanz' => 'Bilanz', 'Books are open' => 'Die Bücher sind geöffnet.', 'Buchungsgruppe' => 'Buchungsgruppe', 'Buchungsgruppe bearbeiten' => 'Buchungsgruppe bearbeiten', @@ -109,7 +104,6 @@ $self->{texts} = { 'Dropdown Limit' => 'Auswahllistenbegrenzung', 'E-mail' => 'eMail', 'ELSE' => 'Zusatz', - 'EUER' => 'Einnahmen-/Überschussrechnung', 'Edit Account' => 'Kontodaten bearbeiten', 'Edit Buchungsgruppe' => 'Buchungsgruppe bearbeiten', 'Edit Business' => 'Kunden-/Lieferantentyp bearbeiten', @@ -130,21 +124,16 @@ $self->{texts} = { 'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s', 'Expense' => 'Aufwandskonto', 'Expense Account' => 'Aufwandskonto', - 'Expense/Asset' => 'Aufwand/Anlagen', 'Fax' => 'Fax', - 'Folgekonto' => 'Folgekonto', 'Foreign Exchange Gain' => 'Wechselkurserträge', 'Foreign Exchange Loss' => 'Wechselkursaufwendungen', 'Form details (second row)' => 'Formulardetails (zweite Positionszeile)', - 'Gültig ab' => 'Gültig ab', - 'Heading' => 'Überschrift', + 'Header' => 'Überschrift', 'Hide by default' => 'Standardmäßig verstecken', 'History' => 'Historie', 'History Search' => 'Historien Suche', - 'Include in drop-down menus' => 'In Aufklappmenü aufnehmen', 'Inventory' => 'Inventar', 'Inventory Account' => 'Warenbestand', - 'Is this a summary account to record' => 'Buchungskonto in', 'Language' => 'Sprache', 'Language deleted!' => 'Sprache gelöscht!', 'Language missing!' => 'Sprache fehlt!', @@ -177,9 +166,11 @@ $self->{texts} = { 'No employee was found matching the search parameters.' => 'Es wurde kein Angestellter gefunden, auf den die Suchparameter zutreffen.', 'No part was found matching the search parameters.' => 'Es wurde kein Artikel gefunden, auf den die Suchparameter zutreffen.', 'No project was found matching the search parameters.' => 'Es wurde kein Projekt gefunden, auf das die Suchparameter zutreffen.', + 'None' => 'Kein', 'Number' => 'Nummer', 'Number Format' => 'Zahlenformat', 'Number of copies' => 'Anzahl Kopien', + 'Off' => 'Aus', 'Old (on the side)' => 'Alt (seitlich)', 'On' => 'An', 'OpenDocument/OASIS' => 'OpenDocument/OASIS', @@ -192,10 +183,7 @@ $self->{texts} = { 'PRINTED' => 'Gedruckt', 'Part Number' => 'Artikelnummer', 'Part description' => 'Artikelbeschreibung', - 'Parts Inventory' => 'Warenliste', 'Password' => 'Passwort', - 'Payables' => 'Verbindlichkeiten', - 'Payment' => 'Zahlungsausgang', 'Payment Terms' => 'Zahlungskonditionen', 'Payment Terms saved!' => 'Zahlungskonditionen gespeichert!', 'Payment terms deleted!' => 'Zahlungskonditionen gelöscht!', @@ -215,8 +203,6 @@ $self->{texts} = { 'Project description' => 'Projektbeschreibung', 'Queue' => 'Warteschlange', 'Rate' => 'Rate', - 'Receipt' => 'Zahlungseingang', - 'Receivables' => 'Forderungen', 'Revenue' => 'Erlöskonto', 'Revenue Account' => 'Erlöskonto', 'SAVED' => 'Gespeichert', @@ -228,16 +214,14 @@ $self->{texts} = { 'Select a part' => 'Artikel auswählen', 'Select a project' => 'Projekt auswählen', 'Select an employee' => 'Angestellten auswählen', - 'Service Items' => 'Dienstleistungen', 'Setup Menu' => 'Menüsetup', 'Show by default' => 'Standardmäßig anzeigen', 'Signature' => 'Unterschrift', 'Skonto' => 'Skonto', 'Skonto Terms' => 'Zahlungsziel Skonto', - 'Steuersatz' => 'Steuersatz', 'Stylesheet' => 'Stilvorlage', - 'Tax' => 'Steuer', 'Tax Accounts' => 'Steuerkonto', + 'Tax-o-matic Account' => 'Automatikbuchung auf Konto', 'Template Code' => 'Vorlagenkürzel', 'Template Code missing!' => 'Vorlagenkürzel fehlt!', 'The \'tag\' field must only consist of alphanumeric characters or the carachters - _ ( )' => 'Das Feld \'tag\' darf nur aus alphanumerischen Zeichen und den Zeichen - _ ( ) bestehen.', @@ -260,53 +244,6 @@ $self->{texts} = { 'Translation (%s)' => 'Übersetzung (%s)', 'Trying to call a sub without a name' => 'Es wurde versucht, eine Unterfunktion ohne Namen aufzurufen.', 'Type of Business' => 'Kunden-/Lieferantentyp', - 'UStVA-Nr. 35' => 'Kz. 35', - 'UStVA-Nr. 36' => 'Kz. 36', - 'UStVA-Nr. 39' => 'Kz. 37', - 'UStVA-Nr. 41' => 'Kz. 41', - 'UStVA-Nr. 42' => 'Kz. 42', - 'UStVA-Nr. 43' => 'Kz. 43', - 'UStVA-Nr. 44' => 'Kz. 44', - 'UStVA-Nr. 45' => 'Kz. 45', - 'UStVA-Nr. 48' => 'Kz. 48', - 'UStVA-Nr. 49' => 'Kz. 49', - 'UStVA-Nr. 51 left' => 'Kz. 51 links', - 'UStVA-Nr. 51 right' => 'Kz. 51 rechts', - 'UStVA-Nr. 52' => 'Kz. 52', - 'UStVA-Nr. 53' => 'Kz. 53', - 'UStVA-Nr. 59' => 'Kz. 59', - 'UStVA-Nr. 60' => 'Kz. 60', - 'UStVA-Nr. 61' => 'Kz. 61', - 'UStVA-Nr. 62' => 'Kz. 62', - 'UStVA-Nr. 63' => 'Kz. 63', - 'UStVA-Nr. 64' => 'Kz. 64', - 'UStVA-Nr. 65' => 'Kz. 65', - 'UStVA-Nr. 66' => 'Kz. 66', - 'UStVA-Nr. 67' => 'Kz. 67', - 'UStVA-Nr. 69' => 'Kz. 69', - 'UStVA-Nr. 73' => 'Kz. 73', - 'UStVA-Nr. 74' => 'Kz. 74', - 'UStVA-Nr. 76' => 'Kz. 76', - 'UStVA-Nr. 77' => 'Kz. 77', - 'UStVA-Nr. 80' => 'Kz. 80', - 'UStVA-Nr. 81 left' => 'UStVA-Nr. 81 left', - 'UStVA-Nr. 81 right' => 'UStVA-Nr. 81 right', - 'UStVA-Nr. 84' => 'Kz. 84', - 'UStVA-Nr. 85' => 'Kz. 85', - 'UStVA-Nr. 86 left' => 'Kz. 86 links', - 'UStVA-Nr. 86 right' => 'Kz. 86 rechts', - 'UStVA-Nr. 89 left' => 'UStVA-Nr. 89 left', - 'UStVA-Nr. 89 right' => 'UStVA-Nr. 89 right', - 'UStVA-Nr. 91' => 'Kz. 91', - 'UStVA-Nr. 93 left' => 'Kz. 93 left', - 'UStVA-Nr. 93 right' => 'Kz. 93 right', - 'UStVA-Nr. 94' => 'Kz. 94', - 'UStVA-Nr. 95' => 'Kz. 95', - 'UStVA-Nr. 96' => 'Kz. 96', - 'UStVA-Nr. 97 links' => 'Kz. 97 links', - 'UStVA-Nr. 97 rechts' => 'Kz. 97 rechts', - 'UStVA-Nr. 98' => 'Kz. 98', - 'Umsatzsteuervoranmeldung' => 'Umsatzsteuervoranmeldung', 'Unit' => 'Einheit', 'Unknown Category' => 'Unbekannte Kategorie', 'Unknown Link' => 'Unbekannte Verknüpfung', @@ -387,6 +324,7 @@ $self->{subs} = { 'language_header' => 'language_header', 'lead_header' => 'lead_header', 'list_account' => 'list_account', + 'list_account_details' => 'list_account_details', 'list_buchungsgruppe' => 'list_buchungsgruppe', 'list_business' => 'list_business', 'list_department' => 'list_department', diff --git a/locale/de/dn b/locale/de/dn index eee5e7140..62096fd43 100644 --- a/locale/de/dn +++ b/locale/de/dn @@ -73,6 +73,7 @@ gestartet', 'Group Invoices' => 'Rechnungen zusammenfassen', 'History' => 'Historie', 'In-line' => 'im Text', + 'Interest' => 'Zinsen', 'Interest Rate' => 'Zinssatz', 'Inv. Duedate' => 'Rg. Fälligkeit', 'Invdate' => 'Rechnungsdatum', @@ -135,7 +136,6 @@ gestartet', 'Part Number' => 'Artikelnummer', 'Part description' => 'Artikelbeschreibung', 'Payment Terms missing in row ' => 'Zahlungsfrist fehlt in Zeile ', - 'Payment until' => 'Zahlungseingänge bis', 'Phone' => 'Telefon', 'Pick List' => 'Sammelliste', 'Please enter values' => 'Bitte Werte eingeben', @@ -194,7 +194,6 @@ gestartet', 'The dunning process started' => 'Der Mahnprozess ist gestartet.', 'To' => 'An', 'Total Fees' => 'Kumulierte Gebühren', - 'Total Interest' => 'Kumulierte Zinsen', 'Trying to call a sub without a name' => 'Es wurde versucht, eine Unterfunktion ohne Namen aufzurufen.', 'Unit' => 'Einheit', 'Unknown dependency \'%s\'.' => 'Unbekannte Abhängigkeit \'%s\'.', diff --git a/locale/de/ir b/locale/de/ir index cca849a41..760d7ba56 100644 --- a/locale/de/ir +++ b/locale/de/ir @@ -61,6 +61,7 @@ $self->{texts} = { 'E-mail address missing!' => 'E-Mail-Adresse fehlt!', 'ELSE' => 'Zusatz', 'Edit Vendor Invoice' => 'Einkaufsrechnung bearbeiten', + 'Employee' => 'Bearbeiter', 'Enter longdescription' => 'Langtext eingeben', 'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s', 'Exch' => 'Wechselkurs.', diff --git a/sql/Pg-upgrade2/dunning_config_interest_rate.sql b/sql/Pg-upgrade2/dunning_config_interest_rate.sql new file mode 100644 index 000000000..94e06d3c3 --- /dev/null +++ b/sql/Pg-upgrade2/dunning_config_interest_rate.sql @@ -0,0 +1,4 @@ +-- @tag: dunning_config_interest_rate +-- @description: In der Tabelle dunning_config ist interest falsch benannt. +-- @depends: release_2_4_2 +ALTER TABLE dunning_config RENAME interest TO interest_rate;