1 #=====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #=====================================================================
8 # SQL-Ledger Accounting
11 # Author: Dieter Simader
12 # Email: dsimader@sql-ledger.org
13 # Web: http://www.sql-ledger.org
16 # This program is free software; you can redistribute it and/or modify
17 # it under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2 of the License, or
19 # (at your option) any later version.
21 # This program is distributed in the hope that it will be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
29 #======================================================================
33 #======================================================================
41 use SL::Locale::String qw(t8);
45 require "bin/mozilla/common.pl";
47 our ($form, %myconfig, $lxdebug, $locale, $auth);
54 $lxdebug->enter_sub();
56 $auth->assert('cash');
60 $form->{ARAP} = ($form->{type} eq 'receipt') ? "AR" : "AP";
61 $form->{arap} = lc $form->{ARAP};
63 CP->paymentaccounts(\%myconfig, \%$form);
65 # Standard Konto für Umlaufvermögen
66 my $accno_arap = IS->get_standard_accno_current_assets(\%myconfig, \%$form);
67 # Entsprechend präventiv die Auswahlliste für Kontonummer
68 # auch mit value= zusammenbauen (s.a. oben bugfix 1771)
69 # Wichtig: Auch das Template anpassen, damit hidden input korrekt die "
71 $form->{selectaccount} = "";
72 $form->{"select$form->{ARAP}"} = "";
74 map { $form->{selectaccount} .= "<option value=\"$_->{accno}--$_->{description}\">$_->{accno}--$_->{description}</option>\n";
75 $form->{account} = "$_->{accno}--$_->{description}" if ($_->{accno} eq $accno_arap) } @{ $form->{PR}{"$form->{ARAP}_paid"} };
78 # oldcurrency ist zwar noch hier als fragment enthalten, wird aber bei
79 # der aktualisierung der form auch nicht mitübernommen. das konzept
80 # old_$FOO habe ich auch noch nicht verstanden ...
81 # Ok. Wenn currency übernommen werden, dann in callback-string über-
82 # geben und hier reinparsen, oder besser multibox oder html auslagern?
83 # Antwort: form->currency wird mit oldcurrency oder curr[0] überschrieben
84 # Wofür macht das Sinn?
85 @curr = $form->get_all_currencies();
86 $form->{defaultcurrency} = $form->{currency} = $form->{oldcurrency} =
87 $form->get_default_currency(\%myconfig);
89 # Entsprechend präventiv die Auswahlliste für Währungen
90 # auch mit value= zusammenbauen (s.a. oben bugfix 1771)
91 $form->{selectcurrency} = "";
92 map { $form->{selectcurrency} .= "<option value=\"$_\">$_</option>\n" } @curr;
98 $lxdebug->leave_sub();
104 $auth->assert('cash');
106 $::request->layout->add_javascripts("kivi.CustomerVendor.js");
108 my ($arap, $exchangerate);
110 if (!$form->{ $form->{vc} . '_id' }) {
111 map { $form->{"addr$_"} = "" } (1 .. 4);
115 # geändert von <option>asdf--2929
117 # <option value="asdf--2929">asdf--2929</option>
118 # offen: $form->{ARAP} kann raus?
119 for my $item ("account", "currency", $form->{ARAP}) {
120 $form->{$item} = H($form->{$item});
121 $form->{"select$item"} =~ s/ selected//;
122 $form->{"select$item"} =~ s/option value="\Q$form->{$item}\E">\Q$form->{$item}\E/option selected value="$form->{$item}">$form->{$item}/;
125 $form->{openinvoices} = 1;
127 # $locale->text('AR')
128 # $locale->text('AP')
130 setup_cp_form_action_bar(can_post => !!$form->{rowcount});
134 $arap = lc $form->{ARAP};
136 print $::form->parse_html_template('cp/form_header', {
137 is_customer => $form->{vc} eq 'customer',
138 is_receipt => $form->{type} eq 'receipt',
146 $::lxdebug->enter_sub;
147 $::auth->assert('cash');
149 my @columns = qw(amount due paid invnumber id transdate checked);
150 my (@invoices, %total);
151 for my $i (1 .. $::form->{rowcount}) {
152 push @invoices, +{ map { $_ => $::form->{"$_\_$i"} } @columns };
153 $total{$_} += $invoices[-1]{$_} = $::form->parse_amount(\%::myconfig, $invoices[-1]{$_}) for qw(amount due paid);
156 print $::form->parse_html_template('cp/invoices', {
157 invoices => \@invoices,
161 $::lxdebug->leave_sub;
165 $::lxdebug->enter_sub;
166 $::auth->assert('cash');
168 print $::form->parse_html_template('cp/form_footer');
170 $::lxdebug->leave_sub;
174 $lxdebug->enter_sub();
176 $auth->assert('cash');
178 my ($buysell, $updated, $exchangerate, $amount);
180 if ($form->{vc} eq 'customer') {
186 # search by invoicenumber,
187 if ($form->{invnumber}) {
188 $form->{open} ='Y'; # only open invoices
189 if ($form->{ARAP} eq 'AR'){
190 # ar_transactions automatically searches by $form->{customer_id} or else
191 # $form->{customer} if available, and these variables will always be set
192 # so we have to empty these values first
193 $form->{customer_id} = '';
194 $form->{customer} = '';
195 AR->ar_transactions(\%myconfig, \%$form);
197 # if you search for invoice '11' ar_transactions will also match invoices
198 # 112, 211, ... due to the LIKE
200 # so there is now an extra loop that tries to match the invoice number
201 # exactly among all returned results, and then passes the customer_id instead of the name
202 # because the name may not be unique
204 my $found_exact_invnumber_match = 0;
205 foreach my $i ( @{ $form->{AR} } ) {
206 next unless $i->{invnumber} eq $form->{invnumber};
207 # found exactly matching invnumber
208 $form->{customer_id} = $i->{customer_id};
209 $found_exact_invnumber_match = 1;
212 unless ( $found_exact_invnumber_match ) {
213 # use first returned entry, may not be the correct one if invnumber doesn't
215 $form->{customer_id} = $form->{AR}[0]{customer_id};
218 # s.o. nur für zahlungsausgang
219 AP->ap_transactions(\%myconfig, \%$form);
220 $form->{vendor_id} = $form->{AP}[0]{vendor_id};
224 # determine customer/vendor
225 my $vc = $form->{vc};
226 if (($form->{"previous_${vc}_id"} || $form->{"${vc}_id"}) != $form->{"${vc}_id"}) {
227 IS->get_customer(\%myconfig, \%$form);
230 $form->{oldcurrency} = $form->{currency};
232 # get open invoices from ar/ap using a.${vc}_id, i.e. customer_id
233 CP->get_openinvoices(\%myconfig, \%$form) if $form->{"${vc}_id"};
235 if (!$form->{forex}) { # read exchangerate from input field (not hidden)
236 $form->{exchangerate} = $form->parse_amount(\%myconfig, $form->{exchangerate});
238 $form->{forex} = $form->check_exchangerate( \%myconfig, $form->{currency}, $form->{datepaid}, $buysell);
239 $form->{exchangerate} = $form->{forex} if $form->{forex};
241 $amount = $form->{amount} = $form->parse_amount(\%myconfig, $form->{amount});
243 if ($form->{"${vc}_id"}) {
244 $form->{rowcount} = 0;
246 $form->{queued} = "";
249 foreach my $ref (@{ $form->{PR} }) {
251 $form->{"id_$i"} = $ref->{id};
252 $form->{"invnumber_$i"} = $ref->{invnumber};
253 $form->{"transdate_$i"} = $ref->{transdate};
254 $ref->{exchangerate} = 1 unless $ref->{exchangerate};
255 $form->{"amount_$i"} = $ref->{amount} / $ref->{exchangerate};
257 ($ref->{amount} - $ref->{paid}) / $ref->{exchangerate};
262 $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2)
266 $form->{rowcount} = $i;
271 # Modified from $amount = $form->{amount} by J.Zach to update amount to total
272 # payment amount in Zahlungsausgang
274 for my $i (1 .. $form->{rowcount}) {
278 $form->parse_amount(\%myconfig, $form->{"${_}_$i"})
279 } qw(amount due paid);
281 if ($form->{"checked_$i"}) {
284 if (!$form->{"paid_$i"}) {
285 $form->{"paid_$i"} = $form->{"due_$i"};
288 # Modified by J.Zach, see abovev
289 $amount += $form->{"paid_$i"};
292 $form->{"paid_$i"} = "";
297 $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2)
298 } qw(amount due paid);
302 # Line added by J.Zach, see above
303 $form->{amount}=$amount;
306 list_invoices() if $form->{"${vc}_id"};
309 $lxdebug->leave_sub();
313 $lxdebug->enter_sub();
315 $auth->assert('cash');
319 if ($form->{currency} ne $form->{defaultcurrency}) {
320 $form->error($locale->text('Exchangerate missing!'))
321 unless $form->{exchangerate};
324 # Beim Aktualisieren wird das Konto übernommen
325 # und jetzt auch Beleg und Datum
326 $form->{callback} = "cp.pl?action=payment&vc=$form->{vc}&type=$form->{type}&account=$form->{account}&$form->{currency}" .
327 "&datepaid=$form->{datepaid}&source=$form->{source}";
329 my $msg1 = $::form->{type} eq 'receipt' ? $::locale->text("Receipt posted!") : $::locale->text("Payment posted!");
330 my $msg2 = $::form->{type} eq 'receipt' ? $::locale->text("Cannot post Receipt!") : $::locale->text("Cannot post Payment!");
332 # Die Nachrichten (Receipt posted!) werden nicht angezeigt.
333 # Entweder wieder aktivieren oder komplett rausnehmen
334 $form->redirect($msg1) if (CP->process_payment(\%::myconfig, $::form));
337 $lxdebug->leave_sub();
341 $lxdebug->enter_sub();
343 $auth->assert('cash');
345 my ($closedto, $datepaid, $amount);
347 my $vc = $form->{vc};
348 if (($form->{"previous_${vc}_id"} || $form->{"${vc}_id"}) != $form->{"${vc}_id"}) {
349 IS->get_customer(\%myconfig, $form) if $vc eq 'customer';
350 IR->get_vendor(\%myconfig, $form) if $vc eq 'vendor';
353 if ($form->{currency} ne $form->{oldcurrency}) {
355 $::dispatcher->end_request;
357 $form->error($locale->text('Date missing!')) unless $form->{datepaid};
358 my $selected_check = 1;
359 for my $i (1 .. $form->{rowcount}) {
360 next unless $form->{"checked_$i"};
361 if (abs($form->parse_amount(\%myconfig, $form->{"paid_$i"}, 2)) < 0.01) {
362 $form->error($locale->text('Row #1: amount has to be different from zero.', $i));
364 undef $selected_check;
366 $form->error($locale->text('No transaction selected!')) if $selected_check;
368 $closedto = $form->datetonum($form->{closedto}, \%myconfig);
369 $datepaid = $form->datetonum($form->{datepaid}, \%myconfig);
371 $form->error($locale->text('Cannot process payment for a closed period!'))
372 if ($form->date_closed($form->{"datepaid"}, \%myconfig));
374 $amount = $form->parse_amount(\%myconfig, $form->{amount});
375 $form->{amount} = $amount;
377 for my $i (1 .. $form->{rowcount}) {
378 if ($form->parse_amount(\%myconfig, $form->{"paid_$i"})) {
379 $amount -= $form->parse_amount(\%myconfig, $form->{"paid_$i"});
381 push(@{ $form->{paid} ||= [] }, $form->{"paid_$i"});
382 push(@{ $form->{due} ||= [] }, $form->{"due_$i"});
383 push(@{ $form->{invnumber} ||= [] }, $form->{"invnumber_$i"});
384 push(@{ $form->{invdate} ||= [] }, $form->{"transdate_$i"});
388 if ($form->round_amount($amount, 2) != 0) {
389 push(@{ $form->{paid} }, $form->format_amount(\%myconfig, $amount, 2));
390 push(@{ $form->{due} }, $form->format_amount(\%myconfig, 0, "0"));
391 push(@{ $form->{invnumber} },
392 ($form->{ARAP} eq 'AR')
393 ? $locale->text('Deposit')
394 : $locale->text('Prepayment'));
395 push(@{ $form->{invdate} }, $form->{datepaid});
398 $lxdebug->leave_sub();
401 sub setup_cp_form_action_bar {
404 for my $bar ($::request->layout->get('actionbar')) {
408 submit => [ '#form', { action => "update" } ],
409 accesskey => 'enter',
413 submit => [ '#form', { action => "post" } ],