ar strict
[kivitendo-erp.git] / bin / mozilla / ar.pl
1 #=====================================================================
2 # LX-Office ERP
3 # Copyright (C) 2004
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
6 #
7 #=====================================================================
8 # SQL-Ledger Accounting
9 # Copyright (c) 2001
10 #
11 #  Author: Dieter Simader
12 #   Email: dsimader@sql-ledger.org
13 #     Web: http://www.sql-ledger.org
14 #
15 #
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.
20 #
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., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #======================================================================
29 #
30 # Accounts Receivables
31 #
32 #======================================================================
33
34 use POSIX qw(strftime);
35 use List::Util qw(sum first);
36
37 use SL::AR;
38 use SL::FU;
39 use SL::IS;
40 use SL::PE;
41 use SL::ReportGenerator;
42
43 require "bin/mozilla/arap.pl";
44 require "bin/mozilla/common.pl";
45 require "bin/mozilla/drafts.pl";
46 require "bin/mozilla/reportgenerator.pl";
47
48 use strict;
49 #use warnings;
50
51 1;
52
53 # end of main
54
55 # this is for our long dates
56 # $locale->text('January')
57 # $locale->text('February')
58 # $locale->text('March')
59 # $locale->text('April')
60 # $locale->text('May ')
61 # $locale->text('June')
62 # $locale->text('July')
63 # $locale->text('August')
64 # $locale->text('September')
65 # $locale->text('October')
66 # $locale->text('November')
67 # $locale->text('December')
68
69 # this is for our short month
70 # $locale->text('Jan')
71 # $locale->text('Feb')
72 # $locale->text('Mar')
73 # $locale->text('Apr')
74 # $locale->text('May')
75 # $locale->text('Jun')
76 # $locale->text('Jul')
77 # $locale->text('Aug')
78 # $locale->text('Sep')
79 # $locale->text('Oct')
80 # $locale->text('Nov')
81 # $locale->text('Dec')
82
83 my $totalpaid;
84
85 sub add {
86   $main::lxdebug->enter_sub();
87
88   $main::auth->assert('general_ledger');
89
90   my $form     = $main::form;
91   my %myconfig = %main::myconfig;
92
93   return $main::lxdebug->leave_sub() if (load_draft_maybe());
94
95   # saving the history
96   if(!exists $form->{addition} && ($form->{id} ne "")) {
97     $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
98         $form->{addition} = "ADDED";
99         $form->save_history($form->dbconnect(\%myconfig));
100   }
101   # /saving the history
102
103   $form->{title}    = "Add";
104   $form->{callback} = "ar.pl?action=add" unless $form->{callback};
105
106   AR->get_transdate(\%myconfig, $form);
107   $form->{initial_transdate} = $form->{transdate};
108   &create_links;
109   $form->{transdate} = $form->{initial_transdate};
110   &display_form;
111   $main::lxdebug->leave_sub();
112 }
113
114 sub edit {
115   $main::lxdebug->enter_sub();
116
117   $main::auth->assert('general_ledger');
118
119   my $form     = $main::form;
120
121   # show history button
122   $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
123   #/show hhistory button
124   $form->{javascript} .= qq|<script type="text/javascript" src="js/common.js"></script>|;
125   $form->{title} = "Edit";
126
127   &create_links;
128   &display_form;
129
130   $main::lxdebug->leave_sub();
131 }
132
133 sub display_form {
134   $main::lxdebug->enter_sub();
135
136   $main::auth->assert('general_ledger');
137
138   my $form     = $main::form;
139
140   &form_header;
141   &form_footer;
142
143   $main::lxdebug->leave_sub();
144 }
145
146 sub create_links {
147   $main::lxdebug->enter_sub();
148
149   $main::auth->assert('general_ledger');
150
151   my $form     = $main::form;
152   my %myconfig = %main::myconfig;
153
154   my ($duedate, $taxincluded, @curr);
155
156   $form->create_links("AR", \%myconfig, "customer");
157   $duedate = $form->{duedate};
158
159   $taxincluded = $form->{taxincluded};
160   my $id = $form->{id};
161   IS->get_customer(\%myconfig, \%$form);
162   $form->{taxincluded} = $taxincluded;
163   $form->{id} = $id;
164
165   $form->{duedate}     = $duedate if $duedate;
166   $form->{oldcustomer} = "$form->{customer}--$form->{customer_id}";
167   $form->{rowcount}    = 1;
168
169   # notes
170   $form->{notes} = $form->{intnotes} unless $form->{notes};
171
172   # currencies
173   @curr = split(/:/, $form->{currencies});
174   chomp $curr[0];
175   $form->{defaultcurrency} = $curr[0];
176
177   map { $form->{selectcurrency} .= "<option>$_\n" } @curr;
178
179   # customers
180   if (@{ $form->{all_customer} }) {
181     $form->{customer} = "$form->{customer}--$form->{customer_id}";
182     map { $form->{selectcustomer} .= "<option>$_->{name}--$_->{id}\n" }
183       (@{ $form->{all_customer} });
184   }
185
186   # departments
187   if (@{ $form->{all_departments} }) {
188     $form->{selectdepartment} = "<option>\n";
189     $form->{department}       = "$form->{department}--$form->{department_id}";
190
191     map {
192       $form->{selectdepartment} .=
193         "<option>$_->{description}--$_->{id}\n"
194     } (@{ $form->{all_departments} });
195   }
196
197   $form->{employee} = "$form->{employee}--$form->{employee_id}";
198
199   # sales staff
200   if (@{ $form->{all_employees} }) {
201     $form->{selectemployee} = "";
202     map { $form->{selectemployee} .= "<option>$_->{name}--$_->{id}\n" }
203       (@{ $form->{all_employees} });
204   }
205
206   # build the popup menus
207   $form->{taxincluded} = ($form->{id}) ? $form->{taxincluded} : "checked";
208
209   AR->setup_form($form);
210
211   $form->{locked} =
212     ($form->datetonum($form->{transdate}, \%myconfig) <=
213      $form->datetonum($form->{closedto}, \%myconfig));
214
215   $main::lxdebug->leave_sub();
216 }
217
218 sub form_header {
219   $main::lxdebug->enter_sub();
220
221   $main::auth->assert('general_ledger');
222
223   my $form     = $main::form;
224   my %myconfig = %main::myconfig;
225   my $locale   = $main::locale;
226   my $cgi      = $main::cgi;
227
228   my ($title, $readonly, $exchangerate, $rows);
229   my ($taxincluded, $notes, $department, $customer, $employee, $amount, $project);
230   my ($jsscript, $button1, $button2, $onload);
231   my ($selectAR_amount, $selectAR_paid, $ARselected, $tax);
232   my (@column_index, %column_data);
233
234
235   $title = $form->{title};
236   $form->{title} = $locale->text("$title Accounts Receivables Transaction");
237
238   $form->{taxincluded} = ($form->{taxincluded}) ? "checked" : "";
239
240   # $locale->text('Add Accounts Receivables Transaction')
241   # $locale->text('Edit Accounts Receivables Transaction')
242   $form->{javascript} = qq|<script type="text/javascript">
243   <!--
244   function setTaxkey(accno, row) {
245     var taxkey = accno.options[accno.selectedIndex].value;
246     var reg = /--([0-9]*)/;
247     var found = reg.exec(taxkey);
248     var index = found[1];
249     index = parseInt(index);
250     var tax = 'taxchart_' + row;
251     for (var i = 0; i < document.getElementById(tax).options.length; ++i) {
252       var reg2 = new RegExp("^"+ index, "");
253       if (reg2.exec(document.getElementById(tax).options[i].value)) {
254         document.getElementById(tax).options[i].selected = true;
255         break;
256       }
257     }
258   };
259   //-->
260   </script>|;
261   # show history button js
262   $form->{javascript} .= qq|<script type="text/javascript" src="js/show_history.js"></script>|;
263   #/show history button js
264   $form->{javascript} .= qq|<script type="text/javascript" src="js/common.js"></script>|;
265   $readonly = ($form->{id}) ? "readonly" : "";
266
267   $form->{radier} =
268     ($form->current_date(\%myconfig) eq $form->{gldate}) ? 1 : 0;
269   $readonly = ($form->{radier}) ? "" : $readonly;
270
271   # set option selected
272   foreach my $item (qw(customer currency department employee)) {
273     $form->{"select$item"} =~ s/ selected//;
274     $form->{"select$item"} =~
275       s/option>\Q$form->{$item}\E/option selected>$form->{$item}/;
276   }
277
278   $form->{forex}        = $form->check_exchangerate( \%myconfig, $form->{currency}, $form->{transdate}, 'buy');
279   $form->{exchangerate} = $form->{forex} if $form->{forex};
280
281   # format amounts
282   $form->{exchangerate} =
283     $form->format_amount(\%myconfig, $form->{exchangerate});
284
285   if ($form->{exchangerate} == 0) {
286     $form->{exchangerate} = "";
287   }
288
289   $form->{creditlimit} =
290     $form->format_amount(\%myconfig, $form->{creditlimit}, 0, "0");
291   $form->{creditremaining} =
292     $form->format_amount(\%myconfig, $form->{creditremaining}, 0, "0");
293
294   $exchangerate = qq|
295 <input type=hidden name=forex value=$form->{forex}>
296 |;
297   if ($form->{currency} ne $form->{defaultcurrency}) {
298     if ($form->{forex}) {
299       $exchangerate .= qq|
300         <th align=right>| . $locale->text('Exchangerate') . qq|</th>
301         <td><input type=hidden name=exchangerate value=$form->{exchangerate}>$form->{exchangerate}</td>
302 |;
303     } else {
304       $exchangerate .= qq|
305         <th align=right>| . $locale->text('Exchangerate') . qq|</th>
306         <td><input name=exchangerate size=10 value=$form->{exchangerate}></td>
307 |;
308     }
309   }
310
311   $taxincluded = qq|
312               <tr>
313                 <td align=right><input name=taxincluded class=checkbox type=checkbox value=1 $form->{taxincluded}></td>
314                 <th align=left nowrap>| . $locale->text('Tax Included') . qq|</th>
315               </tr>
316 |;
317
318   if (($rows = $form->numtextrows($form->{notes}, 50)) < 2) {
319     $rows = 2;
320   }
321   $notes =
322     qq|<textarea name=notes rows=$rows cols=50 wrap=soft>$form->{notes}</textarea>|;
323
324   $department = qq|
325               <tr>
326                 <th align="right" nowrap>| . $locale->text('Department') . qq|</th>
327                 <td colspan=3><select name=department>$form->{selectdepartment}</select>
328                 <input type=hidden name=selectdepartment value="$form->{selectdepartment}">
329                 </td>
330               </tr>
331 | if $form->{selectdepartment};
332
333   my $n = ($form->{creditremaining} =~ /-/) ? "0" : "1";
334
335   $customer = ($form->{selectcustomer})
336     ? qq|<select name="customer" onchange="document.getElementById('update_button').click();">$form->{selectcustomer}</select>|
337     : qq|<input name=customer value="$form->{customer}" size=35>|;
338
339   $employee = qq|
340                 <input type=hidden name=employee value="$form->{employee}">
341 |;
342
343   if ($form->{selectemployee}) {
344     $employee = qq|
345               <tr>
346                 <th align=right nowrap>| . $locale->text('Salesperson') . qq|</th>
347                 <td  colspan=2><select name=employee>$form->{selectemployee}</select></td>
348                 <input type=hidden name=selectemployee value="$form->{selectemployee}">
349               </tr>
350 |;
351   }
352
353   my @old_project_ids = ();
354   map({ push(@old_project_ids, $form->{"project_id_$_"})
355           if ($form->{"project_id_$_"}); } (1..$form->{"rowcount"}));
356
357   $form->get_lists("projects"  => { "key"       => "ALL_PROJECTS",
358                                     "all"       => 0,
359                                     "old_id"    => \@old_project_ids },
360                    "charts"    => { "key"       => "ALL_CHARTS",
361                                     "transdate" => $form->{transdate} },
362                    "taxcharts" => { "key"       => "ALL_TAXCHARTS",
363                                     "module"    => "AR" },);
364
365   map({ $_->{link_split} = [ split(/:/, $_->{link}) ]; }
366       @{ $form->{ALL_CHARTS} });
367
368   my %project_labels = ();
369   my @project_values = ("");
370   foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
371     push(@project_values, $item->{"id"});
372     $project_labels{$item->{"id"}} = $item->{"projectnumber"};
373   }
374
375   my (%AR_amount_labels, @AR_amount_values);
376   my (%AR_labels, @AR_values);
377   my (%AR_paid_labels, @AR_paid_values);
378   my %charts;
379   my $taxchart_init;
380
381   foreach my $item (@{ $form->{ALL_CHARTS} }) {
382     if (grep({ $_ eq "AR_amount" } @{ $item->{link_split} })) {
383       $taxchart_init = $item->{tax_id} if ($taxchart_init eq "");
384       my $key = "$item->{accno}--$item->{tax_id}";
385       push(@AR_amount_values, $key);
386       $AR_amount_labels{$key} =
387         "$item->{accno}--$item->{description}";
388
389     } elsif (grep({ $_ eq "AR" } @{ $item->{link_split} })) {
390       push(@AR_values, $item->{accno});
391       $AR_labels{$item->{accno}} = "$item->{accno}--$item->{description}";
392
393     } elsif (grep({ $_ eq "AR_paid" } @{ $item->{link_split} })) {
394       push(@AR_paid_values, $item->{accno});
395       $AR_paid_labels{$item->{accno}} =
396         "$item->{accno}--$item->{description}";
397     }
398
399     $charts{$item->{accno}} = $item;
400   }
401
402   my %taxchart_labels = ();
403   my @taxchart_values = ();
404   my %taxcharts = ();
405   foreach my $item (@{ $form->{ALL_TAXCHARTS} }) {
406     my $key = "$item->{id}--$item->{rate}";
407     $taxchart_init = $key if ($taxchart_init eq $item->{id});
408     push(@taxchart_values, $key);
409     $taxchart_labels{$key} =
410       "$item->{taxdescription} " . ($item->{rate} * 100) . ' %';
411     $taxcharts{$item->{id}} = $item;
412   }
413
414   $form->{fokus} = "arledger.customer";
415
416   # use JavaScript Calendar or not
417   $form->{jsscript} = 1;
418   $jsscript = "";
419   if ($form->{jsscript}) {
420
421     # with JavaScript Calendar
422     $button1 = qq|
423        <td><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value="$form->{transdate}" onBlur=\"check_right_date_format(this)\"></td>
424        <td><input type=button name=transdate id="trigger1" value=|
425       . $locale->text('button') . qq|></td>
426        |;
427     $button2 = qq|
428        <td><input name=duedate id=duedate size=11 title="$myconfig{dateformat}" value="$form->{duedate}" onBlur=\"check_right_date_format(this)\"></td>
429        <td><input type=button name=duedate id="trigger2" value=|
430       . $locale->text('button') . qq|></td></td>
431      |;
432
433     #write Trigger
434     $jsscript =
435       Form->write_trigger(\%myconfig, "2", "transdate", "BL", "trigger1",
436                           "duedate", "BL", "trigger2");
437   } else {
438
439     # without JavaScript Calendar
440     $button1 =
441       qq|<td><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value="$form->{transdate}" onBlur=\"check_right_date_format(this)\"></td>|;
442     $button2 =
443       qq|<td><input name=duedate id=duedate size=11 title="$myconfig{dateformat}" value="$form->{duedate}" onBlur=\"check_right_date_format(this)\"></td>|;
444   }
445
446   my $follow_up_vc         =  $form->{customer};
447   $follow_up_vc            =~ s/--.*?//;
448   my $follow_up_trans_info =  "$form->{invnumber} ($follow_up_vc)";
449
450   $form->{javascript} .=
451     qq|<script type="text/javascript" src="js/common.js"></script>| .
452     qq|<script type="text/javascript" src="js/show_vc_details.js"></script>| .
453     qq|<script type="text/javascript" src="js/follow_up.js"></script>|;
454
455   $form->header;
456   $onload = qq|focus()|;
457   $onload .= qq|;setupDateFormat('|. $myconfig{dateformat} .qq|', '|. $locale->text("Falsches Datumsformat!") .qq|')|;
458   $onload .= qq|;setupPoints('|. $myconfig{numberformat} .qq|', '|. $locale->text("wrongformat") .qq|')|;
459   print qq|
460 <body onLoad="$onload">
461
462 <form method=post name="arledger" action=$form->{script}>
463
464 <input type=hidden name=id value=$form->{id}>
465 <input type=hidden name=sort value=$form->{sort}>
466 <input type=hidden name=closedto value=$form->{closedto}>
467 <input type=hidden name=locked value=$form->{locked}>
468 <input type=hidden name=title value="$title">
469 <input type="hidden" name="follow_up_trans_id_1" value="| . H($form->{id}) . qq|">
470 <input type="hidden" name="follow_up_trans_type_1" value="ar_transaction">
471 <input type="hidden" name="follow_up_trans_info_1" value="| . H($follow_up_trans_info) . qq|">
472 <input type="hidden" name="follow_up_rowcount" value="1">
473
474 | . ($form->{saved_message} ? qq|<p>$form->{saved_message}</p>| : "") . qq|
475
476 <table width=100%>
477   <tr class=listtop>
478     <th class=listtop>$form->{title}</th>
479   </tr>
480   <tr height="5"></tr>
481   <tr valign=top>
482     <td>
483       <table width=100%>
484         <tr valign=top>
485           <td>
486             <table>
487               <tr>
488                 <th align="right" nowrap>| . $locale->text('Customer') . qq|</th>
489                 <td colspan=3>$customer <input type="button" value="| . $locale->text('Details (one letter abbreviation)') . qq|" onclick="show_vc_details('customer')"></td>
490                 <input type=hidden name=selectcustomer value="$form->{selectcustomer}">
491                 <input type=hidden name=oldcustomer value="$form->{oldcustomer}">
492                 <input type=hidden name=customer_id value="$form->{customer_id}">
493                 <input type=hidden name=terms value=$form->{terms}>
494               </tr>
495               <tr>
496                 <td></td>
497                 <td colspan=3>
498                   <table width=100%>
499                     <tr>
500                       <th align=left nowrap>| . $locale->text('Credit Limit') . qq|</th>
501                       <td>$form->{creditlimit}</td>
502                       <th align=left nowrap>| . $locale->text('Remaining') . qq|</th>
503                       <td class="plus$n">$form->{creditremaining}</td>
504                       <input type=hidden name=creditlimit value=$form->{creditlimit}>
505                       <input type=hidden name=creditremaining value=$form->{creditremaining}>
506                     </tr>
507                   </table>
508                 </td>
509               </tr>
510               <tr>
511                 <th align=right>| . $locale->text('Currency') . qq|</th>
512                 <td><select name=currency>$form->{selectcurrency}</select></td>
513                 <input type=hidden name=selectcurrency value="$form->{selectcurrency}">
514                 <input type=hidden name=defaultcurrency value=$form->{defaultcurrency}>
515                 <input type=hidden name=fxgain_accno value=$form->{fxgain_accno}>
516                 <input type=hidden name=fxloss_accno value=$form->{fxloss_accno}>
517                 $exchangerate
518               </tr>
519               $department
520               $taxincluded
521             </table>
522           </td>
523           <td align=right>
524             <table>
525               $employee
526               <tr>
527                 <th align=right nowrap>| . $locale->text('Invoice Number') . qq|</th>
528                 <td><input name=invnumber size=11 value="$form->{invnumber}"></td>
529               </tr>
530               <tr>
531                 <th align=right nowrap>| . $locale->text('Order Number') . qq|</th>
532                 <td><input name=ordnumber size=11 value="$form->{ordnumber}"></td>
533               </tr>
534               <tr>
535                 <th align=right nowrap>| . $locale->text('Invoice Date') . qq|</th>
536                 $button1
537               </tr>
538               <tr>
539                 <th align=right nowrap>| . $locale->text('Due Date') . qq|</th>
540                 $button2
541               </tr>
542      </table>
543           </td>
544         </tr>
545       </table>
546     </td>
547   </tr>
548
549 $jsscript
550   <input type=hidden name=rowcount value=$form->{rowcount}>
551   <tr>
552       <td>
553           <table width=100%>
554            <tr class=listheading>
555           <th class=listheading style="width:15%">|
556     . $locale->text('Account') . qq|</th>
557           <th class=listheading style="width:10%">|
558     . $locale->text('Amount') . qq|</th>
559           <th class=listheading style="width:10%">|
560     . $locale->text('Tax') . qq|</th>
561           <th class=listheading style="width:5%">|
562     . $locale->text('Taxkey') . qq|</th>
563           <th class=listheading style="width:10%">|
564     . $locale->text('Project') . qq|</th>
565         </tr>
566 |;
567
568   $amount  = $locale->text('Amount');
569   $project = $locale->text('Project');
570
571   for my $i (1 .. $form->{rowcount}) {
572
573     # format amounts
574     $form->{"amount_$i"} =
575       $form->format_amount(\%myconfig, $form->{"amount_$i"}, 2);
576     $form->{"tax_$i"} = $form->format_amount(\%myconfig, $form->{"tax_$i"}, 2);
577
578     my $selected_accno_full;
579     my ($accno_row) = split(/--/, $form->{"AR_amount_$i"});
580     my $item = $charts{$accno_row};
581     $selected_accno_full = "$item->{accno}--$item->{tax_id}";
582
583     my $selected_taxchart = $form->{"taxchart_$i"};
584     my ($selected_accno, $selected_tax_id) = split(/--/, $selected_accno_full);
585     my ($previous_accno, $previous_tax_id) = split(/--/, $form->{"previous_AR_amount_$i"});
586
587     if ($previous_accno &&
588         ($previous_accno eq $selected_accno) &&
589         ($previous_tax_id ne $selected_tax_id)) {
590       my $item = $taxcharts{$selected_tax_id};
591       $selected_taxchart = "$item->{id}--$item->{rate}";
592     }
593
594     if (!$form->{"taxchart_$i"}) {
595       if ($form->{"AR_amount_$i"} =~ m/.--./) {
596         $selected_taxchart = join '--', map { ($_->{id}, $_->{rate}) } first { $_->{id} == $item->{tax_id} } @{ $form->{ALL_TAXCHARTS} };
597       } else {
598         $selected_taxchart = $taxchart_init;
599       }
600     }
601
602     $selectAR_amount =
603       NTI($cgi->popup_menu('-name' => "AR_amount_$i",
604                            '-id' => "AR_amount_$i",
605                            '-style' => 'width:400px',
606                            '-onChange' => "setTaxkey(this, $i)",
607                            '-values' => \@AR_amount_values,
608                            '-labels' => \%AR_amount_labels,
609                            '-default' => $selected_accno_full))
610       . $cgi->hidden('-name' => "previous_AR_amount_$i",
611                      '-default' => $selected_accno_full);
612
613     $tax = qq|<td>| .
614       NTI($cgi->popup_menu('-name' => "taxchart_$i",
615                            '-id' => "taxchart_$i",
616                            '-style' => 'width:200px',
617                            '-values' => \@taxchart_values,
618                            '-labels' => \%taxchart_labels,
619                            '-default' => $selected_taxchart))
620       . qq|</td>|;
621
622     my $projectnumber =
623       NTI($cgi->popup_menu('-name' => "project_id_$i",
624                            '-values' => \@project_values,
625                            '-labels' => \%project_labels,
626                            '-default' => $form->{"project_id_$i"} ));
627
628     print qq|
629         <tr>
630           <td>$selectAR_amount</td>
631           <td><input name="amount_$i" size=10 value=$form->{"amount_$i"}></td>
632           <td><input type="hidden" name="tax_$i" value="$form->{"tax_$i"}">$form->{"tax_$i"}</td>
633           $tax
634           <td>$projectnumber</td>
635         </tr>
636 |;
637     $amount  = "";
638     $project = "";
639   }
640
641   $form->{invtotal_unformatted} = $form->{invtotal};
642   $form->{invtotal} = $form->format_amount(\%myconfig, $form->{invtotal}, 2);
643
644   $ARselected =
645     NTI($cgi->popup_menu('-name' => "ARselected", '-id' => "ARselected",
646                          '-style' => 'width:400px',
647                          '-values' => \@AR_values, '-labels' => \%AR_labels,
648                          '-default' => $form->{ARselected}));
649
650   print qq|
651         <tr>
652           <td colspan=6>
653             <hr noshade>
654           </td>
655         </tr>
656         <tr>
657           <td>${ARselected}</td>
658           <th align=left>$form->{invtotal}</th>
659
660           <input type=hidden name=oldinvtotal value=$form->{oldinvtotal}>
661           <input type=hidden name=oldtotalpaid value=$form->{oldtotalpaid}>
662
663           <input type=hidden name=taxaccounts value="$form->{taxaccounts}">
664
665           <td colspan=4></td>
666
667
668         </tr>
669         </table>
670         </td>
671     </tr>
672     <tr>
673       <td>
674         <table width=100%>
675         <tr>
676           <th align=left width=1%>| . $locale->text('Notes') . qq|</th>
677           <td align=left>$notes</td>
678         </tr>
679       </table>
680     </td>
681   </tr>
682   <tr>
683     <td>
684       <table width=100%>
685         <tr class=listheading>
686           <th colspan=7 class=listheading>|
687     . $locale->text('Incoming Payments') . qq|</th>
688         </tr>
689 |;
690
691   if ($form->{currency} eq $form->{defaultcurrency}) {
692     @column_index = qw(datepaid source memo paid AR_paid paid_project_id);
693   } else {
694     @column_index = qw(datepaid source memo paid exchangerate AR_paid paid_project_id);
695   }
696
697   $column_data{datepaid}     = "<th>" . $locale->text('Date') . "</th>";
698   $column_data{paid}         = "<th>" . $locale->text('Amount') . "</th>";
699   $column_data{exchangerate} = "<th>" . $locale->text('Exch') . "</th>";
700   $column_data{AR_paid}      = "<th>" . $locale->text('Account') . "</th>";
701   $column_data{source}       = "<th>" . $locale->text('Source') . "</th>";
702   $column_data{memo}         = "<th>" . $locale->text('Memo') . "</th>";
703   $column_data{paid_project_id} = "<th>" . $locale->text('Project Number') . "</th>";
704
705   print "
706         <tr>
707 ";
708   map { print "$column_data{$_}\n" } @column_index;
709   print "
710         </tr>
711 ";
712
713   my @triggers  = ();
714   my $totalpaid = 0;
715
716   $form->{paidaccounts}++ if ($form->{"paid_$form->{paidaccounts}"});
717   for my $i (1 .. $form->{paidaccounts}) {
718     print "
719         <tr>
720 ";
721
722     $selectAR_paid =
723       NTI($cgi->popup_menu('-name' => "AR_paid_$i",
724                            '-id' => "AR_paid_$i",
725                            '-values' => \@AR_paid_values,
726                            '-labels' => \%AR_paid_labels,
727                            '-default' => $form->{"AR_paid_$i"}));
728
729     $totalpaid += $form->{"paid_$i"};
730
731     # format amounts
732     if ($form->{"paid_$i"}) {
733       $form->{"paid_$i"} =
734         $form->format_amount(\%myconfig, $form->{"paid_$i"}, 2);
735     }
736     $form->{"exchangerate_$i"} =
737       $form->format_amount(\%myconfig, $form->{"exchangerate_$i"});
738
739     if ($form->{"exchangerate_$i"} == 0) {
740       $form->{"exchangerate_$i"} = "";
741     }
742
743     $exchangerate = qq|&nbsp;|;
744     if ($form->{currency} ne $form->{defaultcurrency}) {
745       if ($form->{"forex_$i"}) {
746         $exchangerate =
747           qq|<input type=hidden name="exchangerate_$i" value=$form->{"exchangerate_$i"}>$form->{"exchangerate_$i"}|;
748       } else {
749         $exchangerate =
750           qq|<input name="exchangerate_$i" size=10 value=$form->{"exchangerate_$i"}>|;
751       }
752     }
753
754     $exchangerate .= qq|
755 <input type=hidden name="forex_$i" value=$form->{"forex_$i"}>
756 |;
757
758     $column_data{paid} =
759       qq|<td align=center><input name="paid_$i" size=11 value="$form->{"paid_$i"}" onBlur=\"check_right_number_format(this)\"></td>|;
760     $column_data{AR_paid} =
761       qq|<td align=center>${selectAR_paid}</td>|;
762     $column_data{exchangerate} = qq|<td align=center>$exchangerate</td>|;
763     $column_data{datepaid}     =
764       qq|<td align=center><input name="datepaid_$i" id="datepaid_$i" size=11 value="$form->{"datepaid_$i"}" onBlur=\"check_right_date_format(this)\">
765          <input type="button" name="datepaid_$i" id="trigger_datepaid_$i" value="?"></td>|;
766     $column_data{source} =
767       qq|<td align=center><input name="source_$i" size=11 value="$form->{"source_$i"}"></td>|;
768     $column_data{memo} =
769       qq|<td align=center><input name="memo_$i" size=11 value="$form->{"memo_$i"}"></td>|;
770
771     $column_data{paid_project_id} =
772       qq|<td>|
773       . NTI($cgi->popup_menu('-name' => "paid_project_id_$i",
774                              '-values' => \@project_values,
775                              '-labels' => \%project_labels,
776                              '-default' => $form->{"paid_project_id_$i"} ))
777       . qq|</td>|;
778
779     map { print qq|$column_data{$_}\n| } @column_index;
780
781     print "
782         </tr>
783 ";
784     push(@triggers, "datepaid_$i", "BL", "trigger_datepaid_$i");
785   }
786
787   my $paid_missing = $form->{invtotal_unformatted} - $totalpaid;
788
789   print qq|
790         <tr>
791           <td></td>
792           <td></td>
793           <td align="center">| . $locale->text('Total') . qq|</td>
794           <td align="center">| . H($form->format_amount(\%myconfig, $totalpaid, 2)) . qq|</td>
795         </tr>
796         <tr>
797           <td></td>
798           <td></td>
799           <td align="center">| . $locale->text('Missing amount') . qq|</td>
800           <td align="center">| . H($form->format_amount(\%myconfig, $paid_missing, 2)) . qq|</td>
801         </tr>
802 | . $form->write_trigger(\%myconfig, scalar(@triggers) / 3, @triggers) .
803     qq|
804 <input type=hidden name=paidaccounts value=$form->{paidaccounts}>
805
806       </table>
807     </td>
808   </tr>
809   <tr>
810     <td><hr size=3 noshade></td>
811   </tr>
812 </table>
813 |;
814
815   $main::lxdebug->leave_sub();
816 }
817
818 sub form_footer {
819   $main::lxdebug->enter_sub();
820
821   $main::auth->assert('general_ledger');
822
823   my $form     = $main::form;
824   my %myconfig = %main::myconfig;
825   my $locale   = $main::locale;
826   my $cgi      = $main::cgi;
827
828   my ($transdate, $closedto);
829
830   my $follow_ups_block;
831   if ($form->{id}) {
832     my $follow_ups = FU->follow_ups('trans_id' => $form->{id});
833
834     if (@{ $follow_ups} ) {
835       my $num_due       = sum map { $_->{due} * 1 } @{ $follow_ups };
836       $follow_ups_block = qq|<p>| . $locale->text("There are #1 unfinished follow-ups of which #2 are due.", scalar @{ $follow_ups }, $num_due) . qq|</p>|;
837     }
838   }
839
840   print qq|
841
842 $follow_ups_block
843
844 <input name=gldate type=hidden value="| . Q($form->{gldate}) . qq|">
845
846 <input name=callback type=hidden value="$form->{callback}">
847 |
848 . $cgi->hidden('-name' => 'draft_id', '-default' => [$form->{draft_id}])
849 . $cgi->hidden('-name' => 'draft_description', '-default' => [$form->{draft_description}])
850 . qq|
851
852 <br>
853 |;
854
855   if (!$form->{id} && $form->{draft_id}) {
856     print(NTI($cgi->checkbox('-name' => 'remove_draft', '-id' => 'remove_draft',
857                              '-value' => 1, '-checked' => $form->{remove_draft},
858                              '-label' => '')) .
859           qq|&nbsp;<label for="remove_draft">| .
860           $locale->text("Remove draft when posting") .
861           qq|</label><br>|);
862   }
863
864   $transdate = $form->datetonum($form->{transdate}, \%myconfig);
865   $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
866
867   print qq|<input class="submit" type="submit" name="action" id="update_button" value="| . $locale->text('Update') . qq|">\n|;
868
869   # ToDO: - insert a global check for stornos, so that a storno is only possible a limited time after saving it
870   print qq| <input class=submit type=submit name=action value="| . $locale->text('Storno') . qq|"> |
871     if ($form->{id} && !IS->has_storno(\%myconfig, $form, 'ar') && !IS->is_storno(\%myconfig, $form, 'ar') && (($totalpaid == 0) || ($totalpaid eq "")));
872
873   if ($form->{id}) {
874     if ($form->{radier}) {
875       print qq|
876         <input class=submit type=submit name=action value="| . $locale->text('Post') .            qq|">
877         <input class=submit type=submit name=action value="| . $locale->text('Delete') .          qq|"> |;
878     }
879     if ($transdate > $closedto) {
880       print qq|
881         <input class=submit type=submit name=action value="| . $locale->text('Use As Template') . qq|"> |;
882     }
883     print qq|
884         <input class=submit type=submit name=action value="| . $locale->text('Post Payment') .    qq|">
885         <input type="button" class="submit" onclick="follow_up_window()" value="|
886       . $locale->text('Follow-Up')
887       . qq|"> |;
888
889   } else {
890     if ($transdate > $closedto) {
891       print qq| <input class=submit type=submit name=action value="| . $locale->text('Post') .     qq|"> | .
892         NTI($cgi->submit('-name' => 'action', '-value' => $locale->text('Save draft'), '-class' => 'submit'));
893     }
894   }
895
896   if ($form->{menubar}) {
897     require "bin/mozilla/menu.pl";
898     &menubar;
899   }
900   # button for saving history
901   if($form->{id} ne "") {
902     print qq| <input type=button class=submit onclick=set_history_window($form->{id}); name=history id=history value=| . $locale->text('history') . qq|> |;
903   }
904   # /button for saving history
905   # mark_as_paid button
906   if($form->{id} ne "") {
907     print qq|<input type="submit" class="submit" name="action" value="|
908           . $locale->text('mark as paid') . qq|">|;
909   }
910   # /mark_as_paid button
911
912   print "
913 </form>
914
915 </body>
916 </html>
917 ";
918
919   $main::lxdebug->leave_sub();
920 }
921
922 sub mark_as_paid {
923   $main::lxdebug->enter_sub();
924
925   $main::auth->assert('general_ledger');
926
927   my $form     = $main::form;
928   my %myconfig = %main::myconfig;
929
930   &mark_as_paid_common(\%myconfig,"ar");
931
932   $main::lxdebug->leave_sub();
933 }
934
935 sub update {
936   $main::lxdebug->enter_sub();
937
938   $main::auth->assert('general_ledger');
939
940   my $form     = $main::form;
941   my %myconfig = %main::myconfig;
942
943   my $display = shift;
944
945   my ($totaltax, $exchangerate);
946
947   $form->{invtotal} = 0;
948
949   delete @{ $form }{ grep { m/^tax_\d+$/ } keys %{ $form } };
950
951   map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
952     qw(exchangerate creditlimit creditremaining);
953
954   my @flds  = qw(amount AR_amount projectnumber oldprojectnumber project_id);
955   my $count = 0;
956   my @a     = ();
957
958   for my $i (1 .. $form->{rowcount}) {
959     $form->{"amount_$i"} = $form->parse_amount(\%myconfig, $form->{"amount_$i"});
960     $form->{"tax_$i"} = $form->parse_amount(\%myconfig, $form->{"tax_$i"});
961     if ($form->{"amount_$i"}) {
962       push @a, {};
963       my $j = $#a;
964       my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
965       if ($taxkey > 1) {
966         if ($form->{taxincluded}) {
967           $form->{"tax_$i"} = $form->{"amount_$i"} / ($rate + 1) * $rate;
968         } else {
969           $form->{"tax_$i"} = $form->{"amount_$i"} * $rate;
970         }
971       } else {
972         $form->{"tax_$i"} = 0;
973       }
974       $form->{"tax_$i"} = $form->round_amount($form->{"tax_$i"}, 2);
975
976       $totaltax += $form->{"tax_$i"};
977       map { $a[$j]->{$_} = $form->{"${_}_$i"} } @flds;
978       $count++;
979     }
980   }
981
982   $form->redo_rows(\@flds, \@a, $count, $form->{rowcount});
983   $form->{rowcount} = $count + 1;
984   map { $form->{invtotal} += $form->{"amount_$_"} } (1 .. $form->{rowcount});
985
986   $form->{forex}        = $form->check_exchangerate( \%myconfig, $form->{currency}, $form->{transdate}, 'buy');
987   $form->{exchangerate} = $form->{forex} if $form->{forex};
988
989   $form->{invdate} = $form->{transdate};
990
991   $form->{invdate} = $form->{transdate};
992
993   my %saved_variables = map +( $_ => $form->{$_} ), qw(AR AR_amount_1 taxchart_1);
994
995   &check_name("customer");
996
997   $form->{AR} = $saved_variables{AR};
998   if ($saved_variables{AR_amount_1} =~ m/.--./) {
999     map { $form->{$_} = $saved_variables{$_} } qw(AR_amount_1 taxchart_1);
1000   } else {
1001     delete $form->{taxchart_1};
1002   }
1003
1004   $form->{invtotal} =
1005     ($form->{taxincluded}) ? $form->{invtotal} : $form->{invtotal} + $totaltax;
1006
1007   for my $i (1 .. $form->{paidaccounts}) {
1008     if ($form->parse_amount(\%myconfig, $form->{"paid_$i"})) {
1009       map {
1010         $form->{"${_}_$i"} =
1011           $form->parse_amount(\%myconfig, $form->{"${_}_$i"})
1012       } qw(paid exchangerate);
1013
1014       $totalpaid += $form->{"paid_$i"};
1015
1016       $form->{"forex_$i"}        = $form->check_exchangerate( \%myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'buy');
1017       $form->{"exchangerate_$i"} = $form->{"forex_$i"} if $form->{"forex_$i"};
1018     }
1019   }
1020
1021   $form->{creditremaining} -=
1022     ($form->{invtotal} - $totalpaid + $form->{oldtotalpaid} -
1023      $form->{oldinvtotal});
1024   $form->{oldinvtotal}  = $form->{invtotal};
1025   $form->{oldtotalpaid} = $totalpaid;
1026
1027   &display_form;
1028
1029   $main::lxdebug->leave_sub();
1030 }
1031
1032 #
1033 # ToDO: fix $closedto and $invdate
1034 #
1035 sub post_payment {
1036   $main::lxdebug->enter_sub();
1037
1038   $main::auth->assert('general_ledger');
1039
1040   my $form     = $main::form;
1041   my %myconfig = %main::myconfig;
1042   my $locale   = $main::locale;
1043
1044   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
1045
1046   for my $i (1 .. $form->{paidaccounts}) {
1047
1048     if ($form->parse_amount(\%myconfig, $form->{"paid_$i"})) {
1049       my $datepaid = $form->datetonum($form->{"datepaid_$i"}, \%myconfig);
1050
1051       $form->isblank("datepaid_$i", $locale->text('Payment date missing!'));
1052
1053       $form->error($locale->text('Cannot post payment for a closed period!')) if ($form->date_closed($form->{"datepaid_$i"}, \%myconfig));
1054
1055       if ($form->{currency} ne $form->{defaultcurrency}) {
1056 #        $form->{"exchangerate_$i"} = $form->{exchangerate} if ($invdate == $datepaid);
1057         $form->isblank("exchangerate_$i", $locale->text('Exchangerate for payment missing!'));
1058       }
1059     }
1060   }
1061
1062   ($form->{AR})      = split /--/, $form->{AR};
1063   ($form->{AR_paid}) = split /--/, $form->{AR_paid};
1064   $form->redirect($locale->text('Payment posted!')) if (AR->post_payment(\%myconfig, \%$form));
1065   $form->error($locale->text('Cannot post payment!'));
1066
1067   $main::lxdebug->leave_sub();
1068 }
1069
1070 sub _post {
1071
1072   $main::auth->assert('general_ledger');
1073
1074   my $form     = $main::form;
1075
1076   # inline post
1077   post(1);
1078 }
1079
1080 sub post {
1081   $main::lxdebug->enter_sub();
1082
1083   $main::auth->assert('general_ledger');
1084
1085   my $form     = $main::form;
1086   my %myconfig = %main::myconfig;
1087   my $locale   = $main::locale;
1088
1089   my ($inline) = @_;
1090
1091   my ($datepaid);
1092
1093   # check if there is an invoice number, invoice and due date
1094   $form->isblank("transdate", $locale->text('Invoice Date missing!'));
1095   $form->isblank("duedate",   $locale->text('Due Date missing!'));
1096   $form->isblank("customer",  $locale->text('Customer missing!'));
1097
1098   my $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
1099   my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
1100   $form->error($locale->text('Cannot post transaction for a closed period!')) if ($form->date_closed($form->{"transdate"}, \%myconfig));
1101
1102   $form->error($locale->text('Zero amount posting!'))
1103     unless grep $_*1, map $form->parse_amount(\%myconfig, $form->{"amount_$_"}), 1..$form->{rowcount};
1104
1105   $form->isblank("exchangerate", $locale->text('Exchangerate missing!'))
1106     if ($form->{currency} ne $form->{defaultcurrency});
1107
1108   delete($form->{AR});
1109
1110   for my $i (1 .. $form->{paidaccounts}) {
1111     if ($form->parse_amount(\%myconfig, $form->{"paid_$i"})) {
1112       $datepaid = $form->datetonum($form->{"datepaid_$i"}, \%myconfig);
1113
1114       $form->isblank("datepaid_$i", $locale->text('Payment date missing!'));
1115
1116       $form->error($locale->text('Cannot post payment for a closed period!'))
1117         if ($form->date_closed($form->{"datepaid_$i"}, \%myconfig));
1118
1119       if ($form->{currency} ne $form->{defaultcurrency}) {
1120         $form->{"exchangerate_$i"} = $form->{exchangerate} if ($transdate == $datepaid);
1121         $form->isblank("exchangerate_$i", $locale->text('Exchangerate for payment missing!'));
1122       }
1123     }
1124   }
1125
1126   # if oldcustomer ne customer redo form
1127   my ($customer) = split /--/, $form->{customer};
1128   if ($form->{oldcustomer} ne "$customer--$form->{customer_id}") {
1129     update();
1130     exit;
1131   }
1132
1133   $form->{AR}{receivables} = $form->{ARselected};
1134   $form->{storno}          = 0;
1135
1136   $main::lxdebug->message(0, $form->{amount});
1137   $form->{id} = 0 if $form->{postasnew};
1138   $form->error($locale->text('Cannot post transaction!')) unless AR->post_transaction(\%myconfig, \%$form);
1139
1140   # saving the history
1141   if(!exists $form->{addition} && $form->{id} ne "") {
1142     $form->{snumbers} = "invnumber_$form->{invnumber}";
1143     $form->{addition} = "POSTED";
1144     $form->save_history($form->dbconnect(\%myconfig));
1145   }
1146   # /saving the history
1147   remove_draft() if $form->{remove_draft};
1148
1149   $form->redirect($locale->text('Transaction posted!')) unless $inline;
1150
1151   $main::lxdebug->leave_sub();
1152 }
1153
1154 sub post_as_new {
1155   $main::lxdebug->enter_sub();
1156
1157   $main::auth->assert('general_ledger');
1158
1159   my $form     = $main::form;
1160   my %myconfig = %main::myconfig;
1161
1162   $form->{postasnew} = 1;
1163   # saving the history
1164   if(!exists $form->{addition} && $form->{id} ne "") {
1165     $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
1166         $form->{addition} = "POSTED AS NEW";
1167         $form->save_history($form->dbconnect(\%myconfig));
1168   }
1169   # /saving the history
1170   &post;
1171
1172   $main::lxdebug->leave_sub();
1173 }
1174
1175 sub use_as_template {
1176   $main::lxdebug->enter_sub();
1177
1178   $main::auth->assert('general_ledger');
1179
1180   my $form     = $main::form;
1181   my %myconfig = %main::myconfig;
1182
1183   map { delete $form->{$_} } qw(printed emailed queued invnumber invdate deliverydate id datepaid_1 source_1 memo_1 paid_1 exchangerate_1 AP_paid_1 storno);
1184   $form->{paidaccounts} = 1;
1185   $form->{rowcount}--;
1186   $form->{invdate} = $form->current_date(\%myconfig);
1187   &update;
1188
1189   $main::lxdebug->leave_sub();
1190 }
1191
1192 sub delete {
1193   $main::lxdebug->enter_sub();
1194
1195   $main::auth->assert('general_ledger');
1196
1197   my $form     = $main::form;
1198   my $locale   = $main::locale;
1199
1200   $form->{title} = $locale->text('Confirm!');
1201
1202   $form->header;
1203
1204   delete $form->{header};
1205
1206   print qq|
1207 <body>
1208
1209 <form method=post action=$form->{script}>
1210 |;
1211
1212   foreach my $key (keys %$form) {
1213     next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
1214     $form->{$key} =~ s/\"/&quot;/g;
1215     print qq|<input type=hidden name=$key value="$form->{$key}">\n|;
1216   }
1217
1218   print qq|
1219 <h2 class=confirm>$form->{title}</h2>
1220
1221 <h4>|
1222     . $locale->text('Are you sure you want to delete Transaction')
1223     . qq| $form->{invnumber}</h4>
1224
1225 <input name=action class=submit type=submit value="|
1226     . $locale->text('Yes') . qq|">
1227 </form>
1228
1229 </body>
1230 </html>
1231 |;
1232
1233   $main::lxdebug->leave_sub();
1234 }
1235
1236 sub yes {
1237   $main::lxdebug->enter_sub();
1238
1239   $main::auth->assert('general_ledger');
1240
1241   my $form     = $main::form;
1242   my %myconfig = %main::myconfig;
1243   my $locale   = $main::locale;
1244
1245   if (AR->delete_transaction(\%myconfig, \%$form)) {
1246     # saving the history
1247     if(!exists $form->{addition}) {
1248       $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
1249           $form->{addition} = "DELETED";
1250           $form->save_history($form->dbconnect(\%myconfig));
1251     }
1252     # /saving the history
1253     $form->redirect($locale->text('Transaction deleted!'));
1254   }
1255   $form->error($locale->text('Cannot delete transaction!'));
1256
1257   $main::lxdebug->leave_sub();
1258 }
1259
1260 sub search {
1261   $main::lxdebug->enter_sub();
1262
1263   $main::auth->assert('general_ledger | invoice_edit');
1264
1265   my $form     = $main::form;
1266   my %myconfig = %main::myconfig;
1267   my $locale   = $main::locale;
1268   my $cgi      = $main::cgi;
1269
1270   my ($customer, $department);
1271   my ($jsscript, $button1, $button2, $onload);
1272
1273   # setup customer selection
1274   $form->all_vc(\%myconfig, "customer", "AR");
1275
1276   if (@{ $form->{all_customer} }) {
1277     map { $customer .= "<option>$_->{name}--$_->{id}\n" }
1278       @{ $form->{all_customer} };
1279     $customer = qq|<select name=customer><option>\n$customer</select>|;
1280   } else {
1281     $customer = qq|<input name=customer size=35>|;
1282   }
1283
1284   # departments
1285   if (@{ $form->{all_departments} }) {
1286     $form->{selectdepartment} = "<option>\n";
1287
1288     map {
1289       $form->{selectdepartment} .=
1290         "<option>$_->{description}--$_->{id}\n"
1291     } (@{ $form->{all_departments} });
1292   }
1293
1294   $department = qq|
1295         <tr>
1296           <th align=right nowrap>| . $locale->text('Department') . qq|</th>
1297           <td colspan=3><select name=department>$form->{selectdepartment}</select></td>
1298         </tr>
1299 | if $form->{selectdepartment};
1300
1301   $form->{title} = $locale->text('AR Transactions');
1302
1303   $form->{javascript} .= qq|<script type="text/javascript" src="js/common.js"></script>|;
1304
1305   # use JavaScript Calendar or not
1306   $form->{jsscript} = 1;
1307   $jsscript = "";
1308   if ($form->{jsscript}) {
1309
1310     # with JavaScript Calendar
1311     $button1 = qq|
1312        <td><input name=transdatefrom id=transdatefrom size=11 title="$myconfig{dateformat}" onBlur=\"check_right_date_format(this)\">
1313        <input type=button name=transdatefrom id="trigger1" value=|
1314       . $locale->text('button') . qq|></td>
1315       |;
1316     $button2 = qq|
1317        <td><input name=transdateto id=transdateto size=11 title="$myconfig{dateformat}" onBlur=\"check_right_date_format(this)\">
1318        <input type=button name=transdateto name=transdateto id="trigger2" value=|
1319       . $locale->text('button') . qq|></td>
1320      |;
1321
1322     #write Trigger
1323     $jsscript =
1324       Form->write_trigger(\%myconfig, "2", "transdatefrom", "BR", "trigger1",
1325                           "transdateto", "BL", "trigger2");
1326   } else {
1327
1328     # without JavaScript Calendar
1329     $button1 = qq|
1330                               <td><input name=transdatefrom id=transdatefrom size=11 title="$myconfig{dateformat}" onBlur=\"check_right_date_format(this)\"></td>|;
1331     $button2 = qq|
1332                               <td><input name=transdateto id=transdateto size=11 title="$myconfig{dateformat}" onBlur=\"check_right_date_format(this)\"></td>|;
1333   }
1334
1335   $form->get_lists("projects" => { "key" => "ALL_PROJECTS",
1336                                    "all" => 1 });
1337
1338   my %labels = ();
1339   my @values = ("");
1340   foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
1341     push(@values, $item->{"id"});
1342     $labels{$item->{"id"}} = $item->{"projectnumber"};
1343   }
1344   my $projectnumber =
1345     NTI($cgi->popup_menu('-name' => 'project_id', '-values' => \@values,
1346                          '-labels' => \%labels));
1347
1348   $form->{fokus} = "search.customer";
1349   $form->header;
1350   $onload = qq|focus()|;
1351   $onload .= qq|;setupDateFormat('|. $myconfig{dateformat} .qq|', '|. $locale->text("Falsches Datumsformat!") .qq|')|;
1352   $onload .= qq|;setupPoints('|. $myconfig{numberformat} .qq|', '|. $locale->text("wrongformat") .qq|')|;
1353   print qq|
1354 <body onLoad="$onload">
1355
1356 <form method=post name="search" action=$form->{script}>
1357
1358 <table width=100%>
1359   <tr><th class=listtop>$form->{title}</th></tr>
1360   <tr height="5"></tr>
1361   <tr>
1362     <td>
1363       <table>
1364         <tr>
1365           <th align=right>| . $locale->text('Customer') . qq|</th>
1366           <td colspan=3>$customer</td>
1367         </tr>
1368         $department
1369         <tr>
1370           <th align=right nowrap>| . $locale->text('Invoice Number') . qq|</th>
1371           <td colspan=3><input name=invnumber size=20></td>
1372         </tr>
1373         <tr>
1374           <th align=right nowrap>| . $locale->text('Order Number') . qq|</th>
1375           <td colspan=3><input name=ordnumber size=20></td>
1376         </tr>
1377        <tr>
1378          <th align=right nowrap>| . $locale->text('Transaction description') . qq|</th>
1379          <td colspan=3><input name=transaction_description size=40></td>
1380        </tr>
1381         <tr>
1382           <th align=right nowrap>| . $locale->text('Notes') . qq|</th>
1383           <td colspan=3><input name=notes size=40></td>
1384         </tr>
1385         <tr>
1386           <th align="right">| . $locale->text("Project Number") . qq|</th>
1387           <td colspan="3">$projectnumber</td>
1388         </tr>
1389         <tr>
1390           <th align=right nowrap>| . $locale->text('From') . qq|</th>
1391           $button1
1392           <th align=right>| . $locale->text('Bis') . qq|</th>
1393           $button2
1394         </tr>
1395         <input type=hidden name=sort value=transdate>
1396       </table>
1397     </td>
1398   </tr>
1399   <tr>
1400     <td>
1401       <table>
1402         <tr>
1403           <th align=right nowrap>| . $locale->text('Include in Report') . qq|</th>
1404           <td>
1405             <table width=100%>
1406               <tr>
1407                 <td align=right><input name=open class=checkbox type=checkbox value=Y checked></td>
1408                 <td nowrap>| . $locale->text('Open') . qq|</td>
1409                 <td align=right><input name=closed class=checkbox type=checkbox value=Y></td>
1410                 <td nowrap>| . $locale->text('Closed') . qq|</td>
1411               </tr>
1412               <tr>
1413                 <td align=right><input name="l_id" class=checkbox type=checkbox value=Y></td>
1414                 <td nowrap>| . $locale->text('ID') . qq|</td>
1415                 <td align=right><input name="l_invnumber" class=checkbox type=checkbox value=Y checked></td>
1416                 <td nowrap>| . $locale->text('Invoice Number') . qq|</td>
1417                 <td align=right><input name="l_ordnumber" class=checkbox type=checkbox value=Y></td>
1418                 <td nowrap>| . $locale->text('Order Number') . qq|</td>
1419                 <td align=right><input name="l_transdate" class=checkbox type=checkbox value=Y checked></td>
1420                 <td nowrap>| . $locale->text('Invoice Date') . qq|</td>
1421               </tr>
1422               <tr>
1423                 <td align=right><input name="l_name" class=checkbox type=checkbox value=Y checked></td>
1424                 <td nowrap>| . $locale->text('Customer') . qq|</td>
1425                 <td align=right><input name="l_netamount" class=checkbox type=checkbox value=Y></td>
1426                 <td nowrap>| . $locale->text('Amount') . qq|</td>
1427                 <td align=right><input name="l_tax" class=checkbox type=checkbox value=Y></td>
1428                 <td nowrap>| . $locale->text('Tax') . qq|</td>
1429                 <td align=right><input name="l_amount" class=checkbox type=checkbox value=Y checked></td>
1430                 <td nowrap>| . $locale->text('Total') . qq|</td>
1431               </tr>
1432               <tr>
1433                 <td align=right><input name="l_datepaid" class=checkbox type=checkbox value=Y></td>
1434                 <td nowrap>| . $locale->text('Date Paid') . qq|</td>
1435                 <td align=right><input name="l_paid" class=checkbox type=checkbox value=Y checked></td>
1436                 <td nowrap>| . $locale->text('Paid') . qq|</td>
1437                 <td align=right><input name="l_duedate" class=checkbox type=checkbox value=Y></td>
1438                 <td nowrap>| . $locale->text('Due Date') . qq|</td>
1439                 <td align=right><input name="l_due" class=checkbox type=checkbox value=Y></td>
1440                 <td nowrap>| . $locale->text('Amount Due') . qq|</td>
1441               </tr>
1442               <tr>
1443                 <td align=right><input name="l_notes" class=checkbox type=checkbox value=Y></td>
1444                 <td nowrap>| . $locale->text('Notes') . qq|</td>
1445                 <td align=right><input name="l_salesman" class=checkbox type=checkbox value=Y></td>
1446                 <td nowrap>| . $locale->text('Salesperson') . qq|</td>
1447                 <td align=right><input name="l_shippingpoint" class=checkbox type=checkbox value=Y></td>
1448                 <td nowrap>| . $locale->text('Shipping Point') . qq|</td>
1449                 <td align=right><input name="l_shipvia" class=checkbox type=checkbox value=Y></td>
1450                 <td nowrap>| . $locale->text('Ship via') . qq|</td>
1451               </tr>
1452               <tr>
1453                 <td align=right><input name="l_marge_total" class=checkbox type=checkbox value=Y></td>
1454                 <td nowrap> | . $locale->text('Ertrag') . qq|</td>
1455                 <td align=right><input name="l_marge_percent" class=checkbox type=checkbox value=Y></td>
1456                 <td nowrap> | . $locale->text('Ertrag prozentual') . qq|</td>
1457                 <td align=right><input name="l_employee" class=checkbox type=checkbox value=Y></td>
1458                 <td nowrap>| . $locale->text('Employee') . qq|</td>
1459               </tr>
1460               <tr>
1461                 <td align=right><input name="l_subtotal" class=checkbox type=checkbox value=Y></td>
1462                 <td nowrap>| . $locale->text('Subtotal') . qq|</td>
1463                 <td align=right><input name="l_globalprojectnumber" class=checkbox type=checkbox value=Y></td>
1464                 <td nowrap>| . $locale->text('Project Number') . qq|</td>
1465                 <td align=right><input name="l_transaction_description" class=checkbox type=checkbox value=Y></td>
1466                 <td nowrap>| . $locale->text('Transaction description') . qq|</td>
1467               </tr>
1468           <tr>
1469         <td colspan=4 align=left><b>| . $locale->text('Customer') . qq| </td>
1470           </tr>
1471           <tr>
1472                 <td align=right><input name="l_customernumber" class=checkbox type=checkbox value=Y></td>
1473                 <td nowrap>| . $locale->text('Customer Number') . qq|</td>
1474                 <td align=right><input name="l_country" class=checkbox type=checkbox value=Y></td>
1475                 <td nowrap>| . $locale->text('Country') . qq|</td>
1476                 <td align=right><input name="l_ustid" class=checkbox type=checkbox value=Y></td>
1477                 <td nowrap>| . $locale->text('USt-IdNr.') . qq|</td>
1478                 <td align=right><input name="l_taxzone" class=checkbox type=checkbox value=Y></td>
1479                 <td nowrap>| . $locale->text('Steuersatz') . qq|</td>
1480           </tr>
1481           <tr>
1482                 <td align=right><input name="l_payment_terms" class=checkbox type=checkbox value=Y></td>
1483                 <td nowrap>| . $locale->text('Payment Terms') . qq|</td>
1484                 <td align=right><input name="l_charts" class=checkbox type=checkbox value=Y></td>
1485                 <td nowrap>| . $locale->text('Buchungskonto') . qq|</td>
1486           </tr>
1487
1488             </table>
1489           </td>
1490         </tr>
1491       </table>
1492     </td>
1493   </tr>
1494   <tr>
1495     <td><hr size=3 noshade></td>
1496   </tr>
1497 </table>
1498
1499 <input type=hidden name=nextsub value=$form->{nextsub}>
1500
1501 <br>
1502 <input class=submit type=submit name=action value="|
1503     . $locale->text('Continue') . qq|">
1504
1505 </form>
1506
1507 </body>
1508
1509 $jsscript
1510
1511 </html>
1512 |;
1513
1514   $main::lxdebug->leave_sub();
1515 }
1516
1517 sub create_subtotal_row {
1518   $main::lxdebug->enter_sub();
1519
1520   my ($totals, $columns, $column_alignment, $subtotal_columns, $class) = @_;
1521
1522   my $form     = $main::form;
1523   my %myconfig = %main::myconfig;
1524
1525   my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
1526
1527   map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } @{ $subtotal_columns };
1528
1529   $row->{tax}->{data} = $form->format_amount(\%myconfig, $totals->{amount} - $totals->{netamount}, 2);
1530
1531   map { $totals->{$_} = 0 } @{ $subtotal_columns };
1532
1533   $main::lxdebug->leave_sub();
1534
1535   return $row;
1536 }
1537
1538 sub ar_transactions {
1539   $main::lxdebug->enter_sub();
1540
1541   $main::auth->assert('general_ledger | invoice_edit');
1542
1543   my $form     = $main::form;
1544   my %myconfig = %main::myconfig;
1545   my $locale   = $main::locale;
1546
1547   my ($callback, $href, @columns);
1548
1549   $form->{customer} = $form->unescape($form->{customer});
1550   ($form->{customer}, $form->{customer_id}) = split(/--/, $form->{customer});
1551
1552   report_generator_set_default_sort('transdate', 1);
1553
1554   AR->ar_transactions(\%myconfig, \%$form);
1555
1556   $form->{title} = $locale->text('AR Transactions');
1557
1558   my $report = SL::ReportGenerator->new(\%myconfig, $form);
1559
1560   @columns =
1561     qw(transdate id type invnumber ordnumber name netamount tax amount paid
1562        datepaid due duedate transaction_description notes salesman employee shippingpoint shipvia
1563        marge_total marge_percent globalprojectnumber customernumber country ustid taxzone payment_terms charts);
1564
1565   my @hidden_variables = map { "l_${_}" } @columns;
1566   push @hidden_variables, "l_subtotal", qw(open closed customer invnumber ordnumber transaction_description notes project_id transdatefrom transdateto);
1567
1568   $href = build_std_url('action=ar_transactions', grep { $form->{$_} } @hidden_variables);
1569
1570   my %column_defs = (
1571     'transdate'               => { 'text' => $locale->text('Date'), },
1572     'id'                      => { 'text' => $locale->text('ID'), },
1573     'type'                    => { 'text' => $locale->text('Type'), },
1574     'invnumber'               => { 'text' => $locale->text('Invoice'), },
1575     'ordnumber'               => { 'text' => $locale->text('Order'), },
1576     'name'                    => { 'text' => $locale->text('Customer'), },
1577     'netamount'               => { 'text' => $locale->text('Amount'), },
1578     'tax'                     => { 'text' => $locale->text('Tax'), },
1579     'amount'                  => { 'text' => $locale->text('Total'), },
1580     'paid'                    => { 'text' => $locale->text('Paid'), },
1581     'datepaid'                => { 'text' => $locale->text('Date Paid'), },
1582     'due'                     => { 'text' => $locale->text('Amount Due'), },
1583     'duedate'                 => { 'text' => $locale->text('Due Date'), },
1584     'transaction_description' => { 'text' => $locale->text('Transaction description'), },
1585     'notes'                   => { 'text' => $locale->text('Notes'), },
1586     'salesman'                => { 'text' => $locale->text('Salesperson'), },
1587     'employee'                => { 'text' => $locale->text('Employee'), },
1588     'shippingpoint'           => { 'text' => $locale->text('Shipping Point'), },
1589     'shipvia'                 => { 'text' => $locale->text('Ship via'), },
1590     'globalprojectnumber'     => { 'text' => $locale->text('Project Number'), },
1591     'marge_total'             => { 'text' => $locale->text('Ertrag'), },
1592     'marge_percent'           => { 'text' => $locale->text('Ertrag prozentual'), },
1593     'customernumber'          => { 'text' => $locale->text('Customer Number'), },
1594     'country'                 => { 'text' => $locale->text('Country'), },
1595     'ustid'                   => { 'text' => $locale->text('USt-IdNr.'), },
1596     'taxzone'                 => { 'text' => $locale->text('Steuersatz'), },
1597     'payment_terms'           => { 'text' => $locale->text('Payment Terms'), },
1598     'charts'                  => { 'text' => $locale->text('Buchungskonto'), },
1599   );
1600
1601   foreach my $name (qw(id transdate duedate invnumber ordnumber name datepaid employee shippingpoint shipvia transaction_description)) {
1602     my $sortdir                 = $form->{sort} eq $name ? 1 - $form->{sortdir} : $form->{sortdir};
1603     $column_defs{$name}->{link} = $href . "&sort=$name&sortdir=$sortdir";
1604   }
1605
1606   my %column_alignment = map { $_ => 'right' } qw(netamount tax amount paid due);
1607
1608   $form->{"l_type"} = "Y";
1609   map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
1610
1611   $report->set_columns(%column_defs);
1612   $report->set_column_order(@columns);
1613
1614   $report->set_export_options('ar_transactions', @hidden_variables, qw(sort sortdir));
1615
1616   $report->set_sort_indicator($form->{sort}, $form->{sortdir});
1617
1618   my @options;
1619   if ($form->{customer}) {
1620     push @options, $locale->text('Customer') . " : $form->{customer}";
1621   }
1622   if ($form->{department}) {
1623     my ($department) = split /--/, $form->{department};
1624     push @options, $locale->text('Department') . " : $department";
1625   }
1626   if ($form->{invnumber}) {
1627     push @options, $locale->text('Invoice Number') . " : $form->{invnumber}";
1628   }
1629   if ($form->{ordnumber}) {
1630     push @options, $locale->text('Order Number') . " : $form->{ordnumber}";
1631   }
1632   if ($form->{notes}) {
1633     push @options, $locale->text('Notes') . " : $form->{notes}";
1634   }
1635   if ($form->{transaction_description}) {
1636     push @options, $locale->text('Transaction description') . " : $form->{transaction_description}";
1637   }
1638   if ($form->{transdatefrom}) {
1639     push @options, $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1);
1640   }
1641   if ($form->{transdateto}) {
1642     push @options, $locale->text('Bis') . " " . $locale->date(\%myconfig, $form->{transdateto}, 1);
1643   }
1644   if ($form->{open}) {
1645     push @options, $locale->text('Open');
1646   }
1647   if ($form->{closed}) {
1648     push @options, $locale->text('Closed');
1649   }
1650
1651   $report->set_options('top_info_text'        => join("\n", @options),
1652                        'raw_bottom_info_text' => $form->parse_html_template('ar/ar_transactions_bottom'),
1653                        'output_format'        => 'HTML',
1654                        'title'                => $form->{title},
1655                        'attachment_basename'  => $locale->text('invoice_list') . strftime('_%Y%m%d', localtime time),
1656     );
1657   $report->set_options_from_form();
1658
1659   # add sort and escape callback, this one we use for the add sub
1660   $form->{callback} = $href .= "&sort=$form->{sort}";
1661
1662   # escape callback for href
1663   $callback = $form->escape($href);
1664
1665   my @subtotal_columns = qw(netamount amount paid due marge_total marge_percent);
1666
1667   my %totals    = map { $_ => 0 } @subtotal_columns;
1668   my %subtotals = map { $_ => 0 } @subtotal_columns;
1669
1670   my $idx = 0;
1671
1672   foreach my $ar (@{ $form->{AR} }) {
1673     $ar->{tax} = $ar->{amount} - $ar->{netamount};
1674     $ar->{due} = $ar->{amount} - $ar->{paid};
1675
1676     map { $subtotals{$_} += $ar->{$_};
1677           $totals{$_}    += $ar->{$_} } @subtotal_columns;
1678
1679     $subtotals{marge_percent} = $subtotals{netamount} ? ($subtotals{marge_total} * 100 / $subtotals{netamount}) : 0;
1680     $totals{marge_percent}    = $totals{netamount}    ? ($totals{marge_total}    * 100 / $totals{netamount}   ) : 0;
1681
1682     map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, 2) } qw(netamount tax amount paid due marge_total marge_percent);
1683
1684     my $is_storno  = $ar->{storno} &&  $ar->{storno_id};
1685     my $has_storno = $ar->{storno} && !$ar->{storno_id};
1686
1687     $ar->{type} =
1688       $has_storno       ? $locale->text("Invoice with Storno (abbreviation)") :
1689       $is_storno        ? $locale->text("Storno (one letter abbreviation)") :
1690       $ar->{amount} < 0 ? $locale->text("Credit note (one letter abbreviation)") :
1691       $ar->{invoice}    ? $locale->text("Invoice (one letter abbreviation)") :
1692                           $locale->text("AR Transaction (abbreviation)");
1693
1694     my $row = { };
1695
1696     foreach my $column (@columns) {
1697       $row->{$column} = {
1698         'data'  => $ar->{$column},
1699         'align' => $column_alignment{$column},
1700       };
1701     }
1702
1703     $row->{invnumber}->{link} = build_std_url("script=" . ($ar->{invoice} ? 'is.pl' : 'ar.pl'), 'action=edit')
1704       . "&id=" . E($ar->{id}) . "&callback=${callback}";
1705
1706     my $row_set = [ $row ];
1707
1708     if (($form->{l_subtotal} eq 'Y')
1709         && (($idx == (scalar @{ $form->{AR} } - 1))
1710             || ($ar->{ $form->{sort} } ne $form->{AR}->[$idx + 1]->{ $form->{sort} }))) {
1711       push @{ $row_set }, create_subtotal_row(\%subtotals, \@columns, \%column_alignment, \@subtotal_columns, 'listsubtotal');
1712     }
1713
1714     $report->add_data($row_set);
1715
1716     $idx++;
1717   }
1718
1719   $report->add_separator();
1720   $report->add_data(create_subtotal_row(\%totals, \@columns, \%column_alignment, \@subtotal_columns, 'listtotal'));
1721
1722   $report->generate_with_headers();
1723
1724   $main::lxdebug->leave_sub();
1725 }
1726
1727 sub storno {
1728   $main::lxdebug->enter_sub();
1729
1730   $main::auth->assert('general_ledger');
1731
1732   my $form     = $main::form;
1733   my %myconfig = %main::myconfig;
1734   my $locale   = $main::locale;
1735
1736   # don't cancel cancelled transactions
1737   if (IS->has_storno(\%myconfig, $form, 'ar')) {
1738     $form->{title} = $locale->text("Cancel Accounts Receivables Transaction");
1739     $form->error($locale->text("Transaction has already been cancelled!"));
1740   }
1741
1742   AR->storno($form, \%myconfig, $form->{id});
1743
1744   # saving the history
1745   if(!exists $form->{addition} && $form->{id} ne "") {
1746     $form->{snumbers} = "ordnumber_$form->{ordnumber}";
1747     $form->{addition} = "STORNO";
1748     $form->save_history($form->dbconnect(\%myconfig));
1749   }
1750   # /saving the history
1751
1752   $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
1753
1754   $main::lxdebug->leave_sub();
1755 }