Merge branch 'master' of vc.linet-services.de:public/lx-office-erp
[kivitendo-erp.git] / bin / mozilla / gl.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) 1998-2002
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 # Genereal Ledger
31 #
32 #======================================================================
33
34 use utf8;
35 use strict;
36
37 use POSIX qw(strftime);
38 use List::Util qw(sum);
39
40 use SL::FU;
41 use SL::GL;
42 use SL::IS;
43 use SL::PE;
44 use SL::ReportGenerator;
45
46 require "bin/mozilla/common.pl";
47 require "bin/mozilla/drafts.pl";
48 require "bin/mozilla/reportgenerator.pl";
49
50 # this is for our long dates
51 # $locale->text('January')
52 # $locale->text('February')
53 # $locale->text('March')
54 # $locale->text('April')
55 # $locale->text('May ')
56 # $locale->text('June')
57 # $locale->text('July')
58 # $locale->text('August')
59 # $locale->text('September')
60 # $locale->text('October')
61 # $locale->text('November')
62 # $locale->text('December')
63
64 # this is for our short month
65 # $locale->text('Jan')
66 # $locale->text('Feb')
67 # $locale->text('Mar')
68 # $locale->text('Apr')
69 # $locale->text('May')
70 # $locale->text('Jun')
71 # $locale->text('Jul')
72 # $locale->text('Aug')
73 # $locale->text('Sep')
74 # $locale->text('Oct')
75 # $locale->text('Nov')
76 # $locale->text('Dec')
77
78 sub add {
79   $main::lxdebug->enter_sub();
80
81   $main::auth->assert('general_ledger');
82
83   my $form     = $main::form;
84   my %myconfig = %main::myconfig;
85
86   return $main::lxdebug->leave_sub() if (load_draft_maybe());
87
88   $form->{title} = "Add";
89
90   $form->{callback} = "gl.pl?action=add" unless $form->{callback};
91
92   # we use this only to set a default date
93   # yep. aber er holt hier auch schon ALL_CHARTS. Aufwand / Nutzen? jb
94   GL->transaction(\%myconfig, \%$form);
95
96   $form->{rowcount}  = 2;
97
98   $form->{debit}  = 0;
99   $form->{credit} = 0;
100   $form->{tax}    = 0;
101
102   # departments
103   $form->all_departments(\%myconfig);
104   if (@{ $form->{all_departments} || [] }) {
105     $form->{selectdepartment} = "<option>\n";
106
107     map {
108       $form->{selectdepartment} .=
109         "<option>$_->{description}--$_->{id}\n"
110     } (@{ $form->{all_departments} || [] });
111   }
112
113   $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
114
115   &display_form(1);
116   $main::lxdebug->leave_sub();
117
118 }
119
120 sub prepare_transaction {
121   $main::lxdebug->enter_sub();
122
123   $main::auth->assert('general_ledger');
124
125   my $form     = $main::form;
126   my %myconfig = %main::myconfig;
127
128   GL->transaction(\%myconfig, \%$form);
129
130   $form->{amount} = $form->format_amount(\%myconfig, $form->{amount}, 2);
131
132   # departments
133   $form->all_departments(\%myconfig);
134   if (@{ $form->{all_departments} || [] }) {
135     $form->{selectdepartment} = "<option>\n";
136
137     map {
138       $form->{selectdepartment} .=
139         "<option>$_->{description}--$_->{id}\n"
140     } (@{ $form->{all_departments} || [] });
141   }
142
143   my $i        = 1;
144   my $tax      = 0;
145   my $taxaccno = "";
146   foreach my $ref (@{ $form->{GL} }) {
147     my $j = $i - 1;
148     if ($tax && ($ref->{accno} eq $taxaccno)) {
149       $form->{"tax_$j"}      = abs($ref->{amount});
150       $form->{"taxchart_$j"} = $ref->{id} . "--" . $ref->{taxrate};
151       if ($form->{taxincluded}) {
152         if ($ref->{amount} < 0) {
153           $form->{"debit_$j"} += $form->{"tax_$j"};
154         } else {
155           $form->{"credit_$j"} += $form->{"tax_$j"};
156         }
157       }
158       $form->{"project_id_$j"} = $ref->{project_id};
159
160     } else {
161       $form->{"accno_$i"} = "$ref->{accno}--$ref->{tax_id}";
162       for (qw(fx_transaction source memo)) { $form->{"${_}_$i"} = $ref->{$_} }
163       if ($ref->{amount} < 0) {
164         $form->{totaldebit} -= $ref->{amount};
165         $form->{"debit_$i"} = $ref->{amount} * -1;
166       } else {
167         $form->{totalcredit} += $ref->{amount};
168         $form->{"credit_$i"} = $ref->{amount};
169       }
170       $form->{"taxchart_$i"} = "0--0.00";
171       $form->{"project_id_$i"} = $ref->{project_id};
172       $i++;
173     }
174     if ($ref->{taxaccno} && !$tax) {
175       $taxaccno = $ref->{taxaccno};
176       $tax      = 1;
177     } else {
178       $taxaccno = "";
179       $tax      = 0;
180     }
181   }
182
183   $form->{rowcount} = $i;
184   $form->{locked}   =
185     ($form->datetonum($form->{transdate}, \%myconfig) <=
186      $form->datetonum($form->{closedto}, \%myconfig));
187
188   $main::lxdebug->leave_sub();
189 }
190
191 sub edit {
192   $main::lxdebug->enter_sub();
193
194   $main::auth->assert('general_ledger');
195
196   my $form     = $main::form;
197   my %myconfig = %main::myconfig;
198
199   prepare_transaction();
200
201   $form->{title} = "Edit";
202
203   $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
204
205   form_header();
206   display_rows();
207   form_footer();
208
209   $main::lxdebug->leave_sub();
210 }
211
212
213 sub search {
214   $::lxdebug->enter_sub;
215   $::auth->assert('general_ledger');
216
217   $::form->all_departments(\%::myconfig);
218   $::form->get_lists(
219     projects  => { key => "ALL_PROJECTS", all => 1 },
220     employees => "ALL_EMPLOYEES",
221   );
222
223   my $onload = "focus()"
224              . qq|;setupDateFormat('|. $::myconfig{dateformat} . qq|', '| . $::locale->text("Falsches Datumsformat!") . qq|')|
225              . qq|;setupPoints('|. $::myconfig{numberformat} .   qq|', '| . $::locale->text("wrongformat") . qq|')|;
226
227   $::form->header;
228   print $::form->parse_html_template('gl/search', {
229     onload => $onload,
230     department_label => sub { ("$_[0]{description}--$_[0]{id}")x2 },
231     employee_label => sub { "$_[0]{id}--$_[0]{name}" },
232   });
233
234   $::lxdebug->leave_sub;
235 }
236
237 sub create_subtotal_row {
238   $main::lxdebug->enter_sub();
239
240   my ($totals, $columns, $column_alignment, $subtotal_columns, $class) = @_;
241
242   my $form     = $main::form;
243   my %myconfig = %main::myconfig;
244
245   my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
246
247   map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } @{ $subtotal_columns };
248
249   map { $totals->{$_} = 0 } @{ $subtotal_columns };
250
251   $main::lxdebug->leave_sub();
252
253   return $row;
254 }
255
256 sub generate_report {
257   $main::lxdebug->enter_sub();
258
259   $main::auth->assert('general_ledger');
260
261   my $form     = $main::form;
262   my %myconfig = %main::myconfig;
263   my $locale   = $main::locale;
264
265   # generate_report wird beim ersten Aufruf per Weiter-Knopf und POST mit der hidden Variablen sort mit Wert "datesort" (früher "transdate" als Defaultsortiervariable) übertragen
266
267   # <form method=post action=gl.pl>
268   # <input type=hidden name=sort value=datesort>    # form->{sort} setzen
269   # <input type=hidden name=nextsub value=generate_report>
270
271   # anhand von neuer Variable datesort wird jetzt $form->{sort} auf transdate oder gldate gesetzt
272   # damit ist die Hidden Variable "sort" wahrscheinlich sogar überflüssig
273
274   # ändert man die Sortierreihenfolge per Klick auf eine der Überschriften wird die Variable "sort" per GET übergeben, z.B. id,transdate, gldate, ...
275   # gl.pl?action=generate_report&employee=18383--Jan%20B%c3%bcren&datesort=transdate&category=X&l_transdate=Y&l_gldate=Y&l_id=Y&l_reference=Y&l_description=Y&l_source=Y&l_debit=Y&l_credit=Y&sort=gldate&sortdir=0
276
277   if ( $form->{sort} eq 'datesort' ) {   # sollte bei einem Post (Aufruf aus Suchmaske) immer wahr sein
278       # je nachdem ob in Suchmaske "transdate" oder "gldate" ausgesucht wurde erstes Suchergebnis entsprechend sortieren
279       $form->{sort} = $form->{datesort};
280   };
281
282   # was passiert hier?
283   report_generator_set_default_sort("$form->{datesort}", 1);
284 #  report_generator_set_default_sort('transdate', 1);
285
286   GL->all_transactions(\%myconfig, \%$form);
287
288   my %acctype = ('A' => $locale->text('Asset'),
289                  'C' => $locale->text('Contra'),
290                  'L' => $locale->text('Liability'),
291                  'Q' => $locale->text('Equity'),
292                  'I' => $locale->text('Revenue'),
293                  'E' => $locale->text('Expense'),);
294
295   $form->{title} = $locale->text('Journal');
296   if ($form->{category} ne 'X') {
297     $form->{title} .= " : " . $locale->text($acctype{ $form->{category} });
298   }
299
300   $form->{landscape} = 1;
301
302   my $ml = ($form->{ml} =~ /(A|E|Q)/) ? -1 : 1;
303
304   my @columns = qw(
305     gldate         transdate        id             reference      description
306     notes          source           debit          debit_accno
307     credit         credit_accno     debit_tax      debit_tax_accno
308     credit_tax     credit_tax_accno projectnumbers balance employee
309   );
310
311   # add employee here, so that variable is still known and passed in url when choosing a different sort order in resulting table
312   my @hidden_variables = qw(accno source reference department description notes project_id datefrom dateto employee datesort category l_subtotal);
313   push @hidden_variables, map { "l_${_}" } @columns;
314   foreach ( @hidden_variables ) {
315       print URL "$_\n";
316   };
317
318   my (@options, @date_options);
319   push @options,      $locale->text('Account')     . " : $form->{accno} $form->{account_description}" if ($form->{accno});
320   push @options,      $locale->text('Source')      . " : $form->{source}"                             if ($form->{source});
321   push @options,      $locale->text('Reference')   . " : $form->{reference}"                          if ($form->{reference});
322   push @options,      $locale->text('Description') . " : $form->{description}"                        if ($form->{description});
323   push @options,      $locale->text('Notes')       . " : $form->{notes}"                              if ($form->{notes});
324   push @options,      $locale->text('Employee')       . " : $form->{employee_name}"                              if ($form->{employee_name});
325   my $datesorttext = $form->{datesort} eq 'transdate' ? $locale->text('Invoice Date') :  $locale->text('Booking Date');
326   push @date_options,      "$datesorttext"                              if ($form->{datesort} and ($form->{datefrom} or $form->{dateto}));
327   push @date_options, $locale->text('From'), $locale->date(\%myconfig, $form->{datefrom}, 1)          if ($form->{datefrom});
328   push @date_options, $locale->text('Bis'),  $locale->date(\%myconfig, $form->{dateto},   1)          if ($form->{dateto});
329   push @options,      join(' ', @date_options)                                                        if (scalar @date_options);
330
331   if ($form->{department}) {
332     my ($department) = split /--/, $form->{department};
333     push @options, $locale->text('Department') . " : $department";
334   }
335
336
337   my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
338   print URL $callback;
339   close URL;
340
341   $form->{l_credit_accno}     = 'Y';
342   $form->{l_debit_accno}      = 'Y';
343   $form->{l_credit_tax}       = 'Y';
344   $form->{l_debit_tax}        = 'Y';
345 #  $form->{l_gldate}           = 'Y';  # Spalte mit gldate immer anzeigen
346   $form->{l_credit_tax_accno} = 'Y';
347   $form->{l_datesort} = 'Y';
348   $form->{l_debit_tax_accno}  = 'Y';
349   $form->{l_balance}          = $form->{accno} ? 'Y' : '';
350
351   my %column_defs = (
352     'id'               => { 'text' => $locale->text('ID'), },
353     'transdate'        => { 'text' => $locale->text('Invoice Date'), },
354     'gldate'           => { 'text' => $locale->text('Booking Date'), },
355     'reference'        => { 'text' => $locale->text('Reference'), },
356     'source'           => { 'text' => $locale->text('Source'), },
357     'description'      => { 'text' => $locale->text('Description'), },
358     'notes'            => { 'text' => $locale->text('Notes'), },
359     'debit'            => { 'text' => $locale->text('Debit'), },
360     'debit_accno'      => { 'text' => $locale->text('Debit Account'), },
361     'credit'           => { 'text' => $locale->text('Credit'), },
362     'credit_accno'     => { 'text' => $locale->text('Credit Account'), },
363     'debit_tax'        => { 'text' => $locale->text('Debit Tax'), },
364     'debit_tax_accno'  => { 'text' => $locale->text('Debit Tax Account'), },
365     'credit_tax'       => { 'text' => $locale->text('Credit Tax'), },
366     'credit_tax_accno' => { 'text' => $locale->text('Credit Tax Account'), },
367     'balance'          => { 'text' => $locale->text('Balance'), },
368     'projectnumbers'   => { 'text' => $locale->text('Project Numbers'), },
369     'employee'         => { 'text' => $locale->text('Employee'), },
370   );
371
372   foreach my $name (qw(id transdate gldate reference description debit_accno credit_accno debit_tax_accno credit_tax_accno)) {
373     my $sortname                = $name =~ m/accno/ ? 'accno' : $name;
374     my $sortdir                 = $sortname eq $form->{sort} ? 1 - $form->{sortdir} : $form->{sortdir};
375     $column_defs{$name}->{link} = $callback . "&sort=$sortname&sortdir=$sortdir";
376   }
377
378   map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
379   map { $column_defs{$_}->{visible} = 0 } qw(debit_accno credit_accno debit_tax_accno credit_tax_accno) if $form->{accno};
380
381   my %column_alignment;
382   map { $column_alignment{$_}     = 'right'  } qw(balance id debit credit debit_tax credit_tax balance);
383   map { $column_alignment{$_}     = 'center' } qw(transdate gldate reference debit_accno credit_accno debit_tax_accno credit_tax_accno);
384   map { $column_alignment{$_}     = 'left' } qw(description source notes);
385   map { $column_defs{$_}->{align} = $column_alignment{$_} } keys %column_alignment;
386
387   my $report = SL::ReportGenerator->new(\%myconfig, $form);
388
389   $report->set_columns(%column_defs);
390   $report->set_column_order(@columns);
391
392   $report->set_export_options('generate_report', @hidden_variables, qw(sort sortdir));
393
394   $report->set_sort_indicator($form->{sort} eq 'accno' ? 'debit_accno' : $form->{sort}, $form->{sortdir});
395
396   $report->set_options('top_info_text'        => join("\n", @options),
397                        'output_format'        => 'HTML',
398                        'title'                => $form->{title},
399                        'attachment_basename'  => $locale->text('general_ledger_list') . strftime('_%Y%m%d', localtime time),
400     );
401   $report->set_options_from_form();
402   $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
403
404   # add sort to callback
405   $form->{callback} = "$callback&sort=" . E($form->{sort}) . "&sortdir=" . E($form->{sortdir});
406
407
408   my @totals_columns = qw(debit credit debit_tax credit_tax);
409   my %subtotals      = map { $_ => 0 } @totals_columns;
410   my %totals         = map { $_ => 0 } @totals_columns;
411   my $idx            = 0;
412
413   foreach my $ref (@{ $form->{GL} }) {
414
415     my %rows;
416
417     foreach my $key (qw(debit credit debit_tax credit_tax)) {
418       $rows{$key} = [];
419       foreach my $idx (sort keys(%{ $ref->{$key} })) {
420         my $value         = $ref->{$key}->{$idx};
421         $subtotals{$key} += $value;
422         $totals{$key}    += $value;
423         if ($key =~ /debit.*/) {
424           $ml = -1;
425         } else {
426           $ml = 1;
427         }
428         $form->{balance}  = $form->{balance} + $value * $ml;
429         push @{ $rows{$key} }, $form->format_amount(\%myconfig, $value, 2);
430       }
431     }
432
433     foreach my $key (qw(debit_accno credit_accno debit_tax_accno credit_tax_accno ac_transdate source)) {
434       my $col = $key eq 'ac_transdate' ? 'transdate' : $key;
435       $rows{$col} = [ map { $ref->{$key}->{$_} } sort keys(%{ $ref->{$key} }) ];
436     }
437
438     my $row = { };
439     map { $row->{$_} = { 'data' => '', 'align' => $column_alignment{$_} } } @columns;
440
441     my $sh = "";
442     if ($form->{balance} < 0) {
443       $sh = " S";
444       $ml = -1;
445     } elsif ($form->{balance} > 0) {
446       $sh = " H";
447       $ml = 1;
448     }
449     my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
450     $data .= $sh;
451
452     $row->{balance}->{data}        = $data;
453     $row->{projectnumbers}->{data} = join ", ", sort { lc($a) cmp lc($b) } keys %{ $ref->{projectnumbers} };
454
455     map { $row->{$_}->{data} = $ref->{$_} } qw(id reference description notes gldate employee);
456
457     map { $row->{$_}->{data} = \@{ $rows{$_} }; } qw(transdate debit credit debit_accno credit_accno debit_tax_accno credit_tax_accno source);
458
459     foreach my $col (qw(debit_accno credit_accno debit_tax_accno credit_tax_accno)) {
460       $row->{$col}->{link} = [ map { "${callback}&accno=" . E($_) } @{ $rows{$col} } ];
461     }
462
463     map { $row->{$_}->{data} = \@{ $rows{$_} } if ($ref->{"${_}_accno"} ne "") } qw(debit_tax credit_tax);
464
465     $row->{reference}->{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'id=' . E($ref->{id}), 'callback');
466
467     my $row_set = [ $row ];
468
469     if (($form->{l_subtotal} eq 'Y')
470         && (($idx == (scalar @{ $form->{GL} } - 1))
471             || ($ref->{ $form->{sort} } ne $form->{GL}->[$idx + 1]->{ $form->{sort} }))) {
472       push @{ $row_set }, create_subtotal_row(\%subtotals, \@columns, \%column_alignment, [ qw(debit credit) ], 'listsubtotal');
473     }
474
475     $report->add_data($row_set);
476
477     $idx++;
478   }
479
480   $report->add_separator();
481
482   # = 0 for balanced ledger
483   my $balanced_ledger = $totals{debit} + $totals{debit_tax} - $totals{credit} - $totals{credit_tax};
484
485   my $row = create_subtotal_row(\%totals, \@columns, \%column_alignment, [ qw(debit credit debit_tax credit_tax) ], 'listtotal');
486
487   my $sh = "";
488   if ($form->{balance} < 0) {
489     $sh = " S";
490     $ml = -1;
491   } elsif ($form->{balance} > 0) {
492     $sh = " H";
493     $ml = 1;
494   }
495   my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
496   $data .= $sh;
497
498   $row->{balance}->{data}        = $data;
499
500   $report->add_data($row);
501
502   my $raw_bottom_info_text;
503
504   if (!$form->{accno} && (abs($balanced_ledger) >  0.001)) {
505     $raw_bottom_info_text .=
506         '<p><span class="unbalanced_ledger">'
507       . $locale->text('Unbalanced Ledger')
508       . ': '
509       . $form->format_amount(\%myconfig, $balanced_ledger, 3)
510       . '</span></p> ';
511   }
512
513   $raw_bottom_info_text .= $form->parse_html_template('gl/generate_report_bottom');
514
515   $report->set_options('raw_bottom_info_text' => $raw_bottom_info_text);
516
517   $report->generate_with_headers();
518
519   $main::lxdebug->leave_sub();
520 }
521
522 sub update {
523   $main::lxdebug->enter_sub();
524
525   $main::auth->assert('general_ledger');
526
527   my $form     = $main::form;
528   my %myconfig = %main::myconfig;
529
530   $form->{oldtransdate} = $form->{transdate};
531
532   my @a           = ();
533   my $count       = 0;
534   my $debittax    = 0;
535   my $credittax   = 0;
536   my $debitcount  = 0;
537   my $creditcount = 0;
538   my ($debitcredit, $amount);
539
540   my @flds =
541     qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
542
543   for my $i (1 .. $form->{rowcount}) {
544
545     unless (($form->{"debit_$i"} eq "") && ($form->{"credit_$i"} eq "")) {
546       for (qw(debit credit tax)) {
547         $form->{"${_}_$i"} =
548           $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
549       }
550
551       push @a, {};
552       $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
553       if ($debitcredit) {
554         $debitcount++;
555       } else {
556         $creditcount++;
557       }
558
559       if (($debitcount >= 2) && ($creditcount == 2)) {
560         $form->{"credit_$i"} = 0;
561         $form->{"tax_$i"}    = 0;
562         $creditcount--;
563         $form->{creditlock} = 1;
564       }
565       if (($creditcount >= 2) && ($debitcount == 2)) {
566         $form->{"debit_$i"} = 0;
567         $form->{"tax_$i"}   = 0;
568         $debitcount--;
569         $form->{debitlock} = 1;
570       }
571       if (($creditcount == 1) && ($debitcount == 2)) {
572         $form->{creditlock} = 1;
573       }
574       if (($creditcount == 2) && ($debitcount == 1)) {
575         $form->{debitlock} = 1;
576       }
577       if ($debitcredit && $credittax) {
578         $form->{"taxchart_$i"} = "0--0.00";
579       }
580       if (!$debitcredit && $debittax) {
581         $form->{"taxchart_$i"} = "0--0.00";
582       }
583       $amount =
584         ($form->{"debit_$i"} == 0)
585         ? $form->{"credit_$i"}
586         : $form->{"debit_$i"};
587       my $j = $#a;
588       if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
589         $form->{"taxchart_$i"} = "0--0.00";
590         $form->{"tax_$i"}      = 0;
591       }
592       my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
593       if ($taxkey > 1) {
594         if ($debitcredit) {
595           $debittax = 1;
596         } else {
597           $credittax = 1;
598         }
599         if ($form->{taxincluded}) {
600           $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
601         } else {
602           $form->{"tax_$i"} = $amount * $rate;
603         }
604       } else {
605         $form->{"tax_$i"} = 0;
606       }
607
608       for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
609       $count++;
610     }
611   }
612
613   for my $i (1 .. $count) {
614     my $j = $i - 1;
615     for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
616   }
617
618   for my $i ($count + 1 .. $form->{rowcount}) {
619     for (@flds) { delete $form->{"${_}_$i"} }
620   }
621
622   $form->{rowcount} = $count + 1;
623
624   &display_form;
625   $main::lxdebug->leave_sub();
626
627 }
628
629 sub display_form {
630   my ($init) = @_;
631   $main::lxdebug->enter_sub();
632
633   $main::auth->assert('general_ledger');
634
635   my $form     = $main::form;
636   my %myconfig = %main::myconfig;
637
638   &form_header($init);
639
640   #   for $i (1 .. $form->{rowcount}) {
641   #     $form->{totaldebit} += $form->parse_amount(\%myconfig, $form->{"debit_$i"});
642   #     $form->{totalcredit} += $form->parse_amount(\%myconfig, $form->{"credit_$i"});
643   #
644   #     &form_row($i);
645   #   }
646   &display_rows($init);
647   &form_footer;
648   $main::lxdebug->leave_sub();
649
650 }
651
652 sub display_rows {
653   my ($init) = @_;
654   $main::lxdebug->enter_sub();
655
656   $main::auth->assert('general_ledger');
657
658   my $form     = $main::form;
659   my %myconfig = %main::myconfig;
660   my $cgi      = $::request->{cgi};
661
662   $form->{debit_1}     = 0 if !$form->{"debit_1"};
663   $form->{totaldebit}  = 0;
664   $form->{totalcredit} = 0;
665
666   my %project_labels = ();
667   my @project_values = ("");
668   foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
669     push(@project_values, $item->{"id"});
670     $project_labels{$item->{"id"}} = $item->{"projectnumber"};
671   }
672
673   my %chart_labels = ();
674   my @chart_values = ();
675   my %charts = ();
676   my $taxchart_init;
677   foreach my $item (@{ $form->{ALL_CHARTS} }) {
678     if ($item->{charttype} eq 'H'){ #falls überschrift
679       next;                         #überspringen (Bug 1150)
680     }
681     my $key = $item->{accno} . "--" . $item->{tax_id};
682     $taxchart_init = $item->{tax_id} unless (@chart_values);
683     push(@chart_values, $key);
684     $chart_labels{$key} = $item->{accno} . "--" . $item->{description};
685     $charts{$item->{accno}} = $item;
686   }
687
688   my %taxchart_labels = ();
689   my @taxchart_values = ();
690   my %taxcharts = ();
691   foreach my $item (@{ $form->{ALL_TAXCHARTS} }) {
692     my $key = $item->{id} . "--" . $item->{rate};
693     $taxchart_init = $key if ($taxchart_init == $item->{id});
694     push(@taxchart_values, $key);
695     $taxchart_labels{$key} = $item->{taxdescription} . " " . $item->{rate} * 100 . ' %';
696     $taxcharts{$item->{id}} = $item;
697   }
698
699   my ($source, $memo, $source_hidden, $memo_hidden);
700   for my $i (1 .. $form->{rowcount}) {
701     if ($form->{show_details}) {
702       $source = qq|
703       <td><input name="source_$i" value="$form->{"source_$i"}" size="16"></td>|;
704       $memo = qq|
705       <td><input name="memo_$i" value="$form->{"memo_$i"}" size="16"></td>|;
706     } else {
707       $source_hidden = qq|
708       <input type="hidden" name="source_$i" value="$form->{"source_$i"}" size="16">|;
709       $memo_hidden = qq|
710       <input type="hidden" name="memo_$i" value="$form->{"memo_$i"}" size="16">|;
711     }
712
713     my $selected_accno_full;
714     my ($accno_row) = split(/--/, $form->{"accno_$i"});
715     my $item = $charts{$accno_row};
716     $selected_accno_full = "$item->{accno}--$item->{tax_id}";
717
718     my $selected_taxchart = $form->{"taxchart_$i"};
719     my ($selected_accno, $selected_tax_id) = split(/--/, $selected_accno_full);
720     my ($previous_accno, $previous_tax_id) = split(/--/, $form->{"previous_accno_$i"});
721
722     if ($previous_accno &&
723         ($previous_accno eq $selected_accno) &&
724         ($previous_tax_id ne $selected_tax_id)) {
725       my $item = $taxcharts{$selected_tax_id};
726       $selected_taxchart = "$item->{id}--$item->{rate}";
727     }
728
729     $selected_accno      = '' if ($init);
730     $selected_taxchart ||= $taxchart_init;
731
732     my $accno = qq|<td>| .
733       NTI($cgi->popup_menu('-name' => "accno_$i",
734                            '-id' => "accno_$i",
735                            '-onChange' => "setTaxkey($i)",
736                            '-style' => 'width:200px',
737                            '-values' => \@chart_values,
738                            '-labels' => \%chart_labels,
739                            '-default' => $selected_accno_full))
740       . $cgi->hidden('-name' => "previous_accno_$i",
741                      '-default' => $selected_accno_full)
742       . qq|</td>|;
743     my $tax_ddbox = qq|<td>| .
744       NTI($cgi->popup_menu('-name' => "taxchart_$i",
745                            '-id' => "taxchart_$i",
746                            '-style' => 'width:200px',
747                            '-values' => \@taxchart_values,
748                            '-labels' => \%taxchart_labels,
749                            '-default' => $selected_taxchart))
750       . qq|</td>|;
751
752     my ($fx_transaction, $checked);
753     if ($init) {
754       if ($form->{transfer}) {
755         $fx_transaction = qq|
756         <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
757     |;
758       }
759
760     } else {
761       if ($form->{"debit_$i"} != 0) {
762         $form->{totaldebit} += $form->{"debit_$i"};
763         if (!$form->{taxincluded}) {
764           $form->{totaldebit} += $form->{"tax_$i"};
765         }
766       } else {
767         $form->{totalcredit} += $form->{"credit_$i"};
768         if (!$form->{taxincluded}) {
769           $form->{totalcredit} += $form->{"tax_$i"};
770         }
771       }
772
773       for (qw(debit credit tax)) {
774         $form->{"${_}_$i"} =
775           ($form->{"${_}_$i"})
776           ? $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2)
777           : "";
778       }
779
780       if ($i < $form->{rowcount}) {
781         if ($form->{transfer}) {
782           $checked = ($form->{"fx_transaction_$i"}) ? "1" : "";
783           my $x = ($checked) ? "x" : "";
784           $fx_transaction = qq|
785       <td><input type=hidden name="fx_transaction_$i" value="$checked">$x</td>
786     |;
787         }
788         $form->hide_form("accno_$i");
789
790       } else {
791         if ($form->{transfer}) {
792           $fx_transaction = qq|
793       <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
794     |;
795         }
796       }
797     }
798     my $debitreadonly  = "";
799     my $creditreadonly = "";
800     if ($i == $form->{rowcount}) {
801       if ($form->{debitlock}) {
802         $debitreadonly = "readonly";
803       } elsif ($form->{creditlock}) {
804         $creditreadonly = "readonly";
805       }
806     }
807
808     my $projectnumber =
809       NTI($cgi->popup_menu('-name' => "project_id_$i",
810                            '-values' => \@project_values,
811                            '-labels' => \%project_labels,
812                            '-default' => $form->{"project_id_$i"} ));
813     my $projectnumber_hidden = qq|
814     <input type="hidden" name="project_id_$i" value="$form->{"project_id_$i"}">|;
815
816     my $copy2credit = $i == 1 ? 'onkeyup="copy_debit_to_credit()"' : '';
817
818     print qq|<tr valign=top>
819     $accno
820     <td id="chart_balance_$i" align="right">&nbsp;</td>
821     $fx_transaction
822     <td><input name="debit_$i" size="8" value="$form->{"debit_$i"}" accesskey=$i $copy2credit $debitreadonly></td>
823     <td><input name="credit_$i" size=8 value="$form->{"credit_$i"}" $creditreadonly></td>
824     <td><input type="hidden" name="tax_$i" value="$form->{"tax_$i"}">$form->{"tax_$i"}</td>
825     $tax_ddbox|;
826
827     if ($form->{show_details}) {
828       print qq|
829     $source
830     $memo
831     <td>$projectnumber</td>
832 |;
833     } else {
834     print qq|
835     $source_hidden
836     $memo_hidden
837     $projectnumber_hidden
838     |;
839     }
840     print qq|
841   </tr>
842 |;
843   }
844
845   $form->hide_form(qw(rowcount selectaccno));
846
847   $main::lxdebug->leave_sub();
848
849 }
850
851 sub form_header {
852   my ($init) = @_;
853   $main::lxdebug->enter_sub();
854
855   $main::auth->assert('general_ledger');
856
857   my $form     = $main::form;
858   my %myconfig = %main::myconfig;
859   my $locale   = $main::locale;
860
861   my @old_project_ids = ();
862   map({ push(@old_project_ids, $form->{"project_id_$_"})
863           if ($form->{"project_id_$_"}); } (1..$form->{"rowcount"}));
864
865   $form->get_lists("projects"  => { "key"       => "ALL_PROJECTS",
866                                     "all"       => 0,
867                                     "old_id"    => \@old_project_ids },
868                    "charts"    => { "key"       => "ALL_CHARTS",
869                                     "transdate" => $form->{transdate} },
870                    "taxcharts" => "ALL_TAXCHARTS");
871
872   GL->get_chart_balances('charts' => $form->{ALL_CHARTS});
873
874   my $title      = $form->{title};
875   $form->{title} = $locale->text("$title General Ledger Transaction");
876   my $readonly   = ($form->{id}) ? "readonly" : "";
877
878   my $show_details_checked   = $form->{show_details}   ? "checked" : '';
879   my $ob_transaction_checked = $form->{ob_transaction} ? "checked" : '';
880   my $cb_transaction_checked = $form->{cb_transaction} ? "checked" : '';
881
882   # $locale->text('Add General Ledger Transaction')
883   # $locale->text('Edit General Ledger Transaction')
884
885   map { $form->{$_} =~ s/\"/&quot;/g }
886     qw(reference description chart taxchart);
887
888   $form->{javascript} = qq|<script type="text/javascript">
889   <!--
890   function setTaxkey(row) {
891     var accno  = document.getElementById('accno_' + row);
892     var taxkey = accno.options[accno.selectedIndex].value;
893     var reg = /--([0-9]*)/;
894     var found = reg.exec(taxkey);
895     var index = found[1];
896     index = parseInt(index);
897     var tax = 'taxchart_' + row;
898     for (var i = 0; i < document.getElementById(tax).options.length; ++i) {
899       var reg2 = new RegExp("^"+ index, "");
900       if (reg2.exec(document.getElementById(tax).options[i].value)) {
901         document.getElementById(tax).options[i].selected = true;
902         break;
903       }
904     }
905   };
906
907   function copy_debit_to_credit() {
908     var txt = document.getElementsByName('debit_1')[0].value;
909     document.getElementsByName('credit_2')[0].value = txt;
910   };
911   //-->
912   </script>
913   <script type="text/javascript" src="js/show_form_details.js"></script>
914   <script type="text/javascript" src="js/jquery.js"></script>
915 |;
916
917   $form->{selectdepartment} =~ s/ selected//;
918   $form->{selectdepartment} =~
919     s/option>\Q$form->{department}\E/option selected>$form->{department}/;
920
921   my $description;
922   if ((my $rows = $form->numtextrows($form->{description}, 50)) > 1) {
923     $description =
924       qq|<textarea name=description rows=$rows cols=50 wrap=soft $readonly >$form->{description}</textarea>|;
925   } else {
926     $description =
927       qq|<input name=description size=50 value="$form->{description}" $readonly>|;
928   }
929
930   my $taxincluded = ($form->{taxincluded}) ? "checked" : "";
931
932   if ($init) {
933     $taxincluded = "checked";
934   }
935
936   my $department;
937   $department = qq|
938         <tr>
939           <th align=right nowrap>| . $locale->text('Department') . qq|</th>
940           <td colspan=3><select name=department>$form->{selectdepartment}</select></td>
941           <input type=hidden name=selectdepartment value="$form->{selectdepartment}">
942         </tr>
943 | if $form->{selectdepartment};
944   if ($init) {
945     $form->{fokus} = "gl.reference";
946   } else {
947     $form->{fokus} = qq|gl.accno_$form->{rowcount}|;
948   }
949
950   # use JavaScript Calendar or not
951   $form->{jsscript} = 1;
952   my $jsscript = "";
953   my ($button1, $button2);
954   if ($form->{jsscript}) {
955
956     # with JavaScript Calendar
957     $button1 = qq|
958        <td><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value="$form->{transdate}" $readonly onBlur=\"check_right_date_format(this)\">
959        <input type=button name=transdate id="trigger1" value=|
960       . $locale->text('button') . qq|></td>
961        |;
962
963     #write Trigger
964     $jsscript =
965       Form->write_trigger(\%myconfig, "1", "transdate", "BL", "trigger1");
966   } else {
967
968     # without JavaScript Calendar
969     $button1 =
970       qq|<td><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value="$form->{transdate}" $readonly onBlur=\"check_right_date_format(this)\"></td>|;
971   }
972
973   $form->{previous_id}     ||= "--";
974   $form->{previous_gldate} ||= "--";
975
976   $jsscript .= $form->parse_html_template('gl/form_header_chart_balances_js');
977
978   $form->header;
979
980   print qq|
981 <body onLoad="focus()">
982
983 <script type="text/javascript" src="js/follow_up.js"></script>
984
985 <form method=post name="gl" action=gl.pl>
986 |;
987
988   $form->hide_form(qw(id closedto locked storno storno_id previous_id previous_gldate));
989
990   print qq|
991 <input type=hidden name=title value="$title">
992
993 <input type="hidden" name="follow_up_trans_id_1" value="| . H($form->{id}) . qq|">
994 <input type="hidden" name="follow_up_trans_type_1" value="gl_transaction">
995 <input type="hidden" name="follow_up_trans_info_1" value="| . H($form->{id}) . qq|">
996 <input type="hidden" name="follow_up_rowcount" value="1">
997
998 <table width=100%>
999   <tr>
1000     <th class=listtop>$form->{title}</th>
1001   </tr>| .
1002
1003   ($form->{saved_message} ? qq|
1004   <tr>
1005     <td>$form->{saved_message}</th>
1006   </tr>| : '') .
1007
1008 qq|
1009   <tr height="5"></tr>
1010   <tr>
1011     <td>
1012       <table width=100%>
1013         <tr>
1014           <td colspan="6" align="left">|
1015     . $locale->text("Previous transnumber text")
1016     . " $form->{previous_id} "
1017     . $locale->text("Previous transdate text")
1018     . " $form->{previous_gldate}"
1019     . qq|</td>
1020         </tr>
1021         <tr>
1022           <th align=right>| . $locale->text('Reference') . qq|</th>
1023           <td><input name=reference size=20 value="$form->{reference}" $readonly></td>
1024           <td align=left>
1025             <table>
1026               <tr>
1027                 <th align=right nowrap>| . $locale->text('Date') . qq|</th>
1028                 $button1
1029               </tr>
1030             </table>
1031           </td>
1032         </tr>|;
1033   if ($form->{id}) {
1034     print qq|
1035         <tr>
1036           <th align=right>| . $locale->text('Belegnummer') . qq|</th>
1037           <td><input name=id size=20 value="$form->{id}" $readonly></td>
1038           <td align=left>
1039           <table>
1040               <tr>
1041                 <th align=right width=50%>| . $locale->text('Buchungsdatum') . qq|</th>
1042                 <td align=left><input name=gldate size=11 title="$myconfig{dateformat}" value=$form->{gldate} $readonly onBlur=\"check_right_date_format(this)\"></td>
1043               </tr>
1044             </table>
1045           </td>
1046         </tr>|;
1047   }
1048   print qq|
1049         $department|;
1050   if ($form->{id}) {
1051     print qq|
1052         <tr>
1053           <th align=right width=1%>| . $locale->text('Description') . qq|</th>
1054           <td width=1%>$description</td>
1055           <td>
1056             <table>
1057               <tr>
1058                 <th align=left>| . $locale->text('MwSt. inkl.') . qq|</th>
1059                 <td><input type=checkbox name=taxincluded value=1 $taxincluded></td>
1060               </tr>
1061             </table>
1062          </td>
1063           <td align=left>
1064             <table width=100%>
1065               <tr>
1066                 <th align=right width=50%>| . $locale->text('Mitarbeiter') . qq|</th>
1067                 <td align=left><input name=employee size=20  value="| . H($form->{employee}) . qq|" readonly></td>
1068               </tr>
1069             </table>
1070           </td>
1071         </tr>|;
1072   } else {
1073     print qq|
1074         <tr>
1075           <th align=left width=1%>| . $locale->text('Description') . qq|</th>
1076           <td width=1%>$description</td>
1077           <td>
1078             <table>
1079               <tr>
1080                 <th align=left>| . $locale->text('MwSt. inkl.') . qq|</th>
1081                 <td><input type=checkbox name=taxincluded value=1 $taxincluded></td>
1082               </tr>
1083             </table>
1084          </td>
1085         </tr>|;
1086   }
1087
1088   print qq|
1089       <tr>
1090       <tr><td colspan=4><table><tr>
1091        <td>
1092         | . $locale->text('OB Transaction') . qq|<input type="checkbox" name="ob_transaction" value="1" $ob_transaction_checked>
1093        </td>
1094        <td>
1095         | . $locale->text('CB Transaction') . qq|<input type="checkbox" name="cb_transaction" value="1" $cb_transaction_checked>
1096        </td>
1097       </tr></table></td></tr>
1098       <tr>
1099        <td width="1%" align="right" nowrap>| . $locale->text('Show details') . qq|</td>
1100        <td width="1%"><input type="checkbox" onclick="show_form_details();" name="show_details" value="1" $show_details_checked></td>
1101       </tr>|;
1102
1103   print qq|
1104       <tr>
1105       <td colspan=4>
1106           <table width=100%>
1107            <tr class=listheading>
1108           <th class=listheading style="width:15%">|
1109     . $locale->text('Account') . qq|</th>
1110           <th class=listheading style="width:10%">| . $locale->text('Chart balance') . qq|</th>
1111           <th class=listheading style="width:10%">|
1112     . $locale->text('Debit') . qq|</th>
1113           <th class=listheading style="width:10%">|
1114     . $locale->text('Credit') . qq|</th>
1115           <th class=listheading style="width:10%">|
1116     . $locale->text('Tax') . qq|</th>
1117           <th class=listheading style="width:5%">|
1118     . $locale->text('Taxkey') . qq|</th>|;
1119
1120   if ($form->{show_details}) {
1121     print qq|
1122           <th class=listheading style="width:20%">| . $locale->text('Source') . qq|</th>
1123           <th class=listheading style="width:20%">| . $locale->text('Memo') . qq|</th>
1124           <th class=listheading style="width:20%">| . $locale->text('Project Number') . qq|</th>
1125 |;
1126   }
1127
1128   print qq|
1129         </tr>
1130
1131 $jsscript
1132 |;
1133   $main::lxdebug->leave_sub();
1134
1135 }
1136
1137 sub form_footer {
1138   $main::lxdebug->enter_sub();
1139
1140   $main::auth->assert('general_ledger');
1141
1142   my $form     = $main::form;
1143   my %myconfig = %main::myconfig;
1144   my $locale   = $main::locale;
1145   my $cgi      = $::request->{cgi};
1146
1147   my $follow_ups_block;
1148   if ($form->{id}) {
1149     my $follow_ups = FU->follow_ups('trans_id' => $form->{id});
1150
1151     if (@{ $follow_ups} ) {
1152       my $num_due       = sum map { $_->{due} * 1 } @{ $follow_ups };
1153       $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>|;
1154     }
1155   }
1156
1157   my ($dec) = ($form->{totaldebit} =~ /\.(\d+)/);
1158   $dec = length $dec;
1159   my $decimalplaces = ($dec > 2) ? $dec : 2;
1160   my $radieren = ($form->current_date(\%myconfig) eq $form->{gldate}) ? 1 : 0;
1161
1162   map {
1163     $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 2, "&nbsp;")
1164   } qw(totaldebit totalcredit);
1165
1166   print qq|
1167     <tr class=listtotal>
1168     <th colspan="3" align=right class=listtotal> $form->{totaldebit}</th>
1169     <th align=right class=listtotal> $form->{totalcredit}</th>
1170     <td colspan=6></td>
1171     </tr>
1172   </table>
1173   </td>
1174   </tr>
1175 </table>
1176
1177 <input name=callback type=hidden value="$form->{callback}">
1178
1179 $follow_ups_block
1180
1181 <br>
1182 |;
1183
1184   my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
1185   my $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
1186
1187   if ($form->{id}) {
1188
1189     if (!$form->{storno}) {
1190       print qq|<input class=submit type=submit name=action value="| . $locale->text('Storno') . qq|">|;
1191     }
1192
1193     # Löschen und Ändern von Buchungen nicht mehr möglich (GoB) nur am selben Tag möglich
1194     if (!$form->{locked} && $radieren) {
1195       print qq|
1196         <input class=submit type=submit name=action value="| . $locale->text('Post') . qq|" accesskey="b">
1197         <input class=submit type=submit name=action value="| . $locale->text('Delete') . qq|">|;
1198     }
1199
1200     print qq|
1201         <input class=submit type=submit name=action id=update_button value="| . $locale->text('Update') . qq|">
1202         <input type="button" class="submit" onclick="follow_up_window()" value="|
1203       . $locale->text('Follow-Up')
1204       . qq|"> |;
1205
1206   } else {
1207     if ($form->{draft_id}) {
1208       my $remove_draft_checked = $form->{remove_draft} ? 'checked' : '';
1209       print qq|<p>\n|
1210         . qq|  <input name="remove_draft" id="remove_draft" type="checkbox" class="checkbox" ${remove_draft_checked}>|
1211         . qq|  <label for="remove_draft">| . $locale->text('Remove Draft') . qq|</label>\n|
1212         . qq|</p>\n|;
1213     }
1214
1215     print qq|
1216         <input class=submit type=submit name=action id=update_button value="| . $locale->text('Update') . qq|">
1217         <input class=submit type=submit name=action value="| . $locale->text('Post') . qq|"> |
1218         . NTI($cgi->submit('-name' => 'action', '-value' => $locale->text('Save draft'), '-class' => 'submit'))
1219         . $cgi->hidden('-name' => 'draft_id',          '-default' => [$form->{draft_id}])
1220         . $cgi->hidden('-name' => 'draft_description', '-default' => [$form->{draft_description}]);
1221   }
1222
1223   print "
1224   </form>
1225
1226 </body>
1227 </html>
1228 ";
1229   $main::lxdebug->leave_sub();
1230
1231 }
1232
1233 sub delete {
1234   $main::lxdebug->enter_sub();
1235
1236   my $form     = $main::form;
1237   my $locale   = $main::locale;
1238
1239   $form->header;
1240
1241   print qq|
1242 <body>
1243
1244 <form method=post action=gl.pl>
1245 |;
1246
1247   map { $form->{$_} =~ s/\"/&quot;/g } qw(reference description);
1248
1249   delete $form->{header};
1250
1251   foreach my $key (keys %$form) {
1252     next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
1253     print qq|<input type="hidden" name="$key" value="$form->{$key}">\n|;
1254   }
1255
1256   print qq|
1257 <h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
1258
1259 <h4>|
1260     . $locale->text('Are you sure you want to delete Transaction')
1261     . qq| $form->{reference}</h4>
1262
1263 <input name=action class=submit type=submit value="|
1264     . $locale->text('Yes') . qq|">
1265 </form>
1266 |;
1267   $main::lxdebug->leave_sub();
1268
1269 }
1270
1271 sub yes {
1272   $main::lxdebug->enter_sub();
1273
1274   my $form     = $main::form;
1275   my %myconfig = %main::myconfig;
1276   my $locale   = $main::locale;
1277
1278   if (GL->delete_transaction(\%myconfig, \%$form)){
1279     # saving the history
1280       if(!exists $form->{addition} && $form->{id} ne "") {
1281         $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
1282         $form->{addition} = "DELETED";
1283         $form->save_history;
1284       }
1285     # /saving the history
1286     $form->redirect($locale->text('Transaction deleted!'))
1287   }
1288   $form->error($locale->text('Cannot delete transaction!'));
1289   $main::lxdebug->leave_sub();
1290
1291 }
1292
1293 sub post_transaction {
1294   $main::lxdebug->enter_sub();
1295
1296   my $form     = $main::form;
1297   my %myconfig = %main::myconfig;
1298   my $locale   = $main::locale;
1299
1300   # check if there is something in reference and date
1301   $form->isblank("reference",   $locale->text('Reference missing!'));
1302   $form->isblank("transdate",   $locale->text('Transaction Date missing!'));
1303   $form->isblank("description", $locale->text('Description missing!'));
1304
1305   my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
1306   my $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
1307
1308   my @a           = ();
1309   my $count       = 0;
1310   my $debittax    = 0;
1311   my $credittax   = 0;
1312   my $debitcount  = 0;
1313   my $creditcount = 0;
1314   my $debitcredit;
1315   my %split_safety = ();
1316
1317   my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
1318
1319   for my $i (1 .. $form->{rowcount}) {
1320     next if $form->{"debit_$i"} eq "" && $form->{"credit_$i"} eq "";
1321
1322     for (qw(debit credit tax)) {
1323       $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
1324     }
1325
1326     push @a, {};
1327     $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
1328
1329     $split_safety{   $form->{"debit_$i"}  <=> 0 }++;
1330     $split_safety{ - $form->{"credit_$i"} <=> 0 }++;
1331
1332     if ($debitcredit) {
1333       $debitcount++;
1334     } else {
1335       $creditcount++;
1336     }
1337
1338     if (($debitcount >= 2) && ($creditcount == 2)) {
1339       $form->{"credit_$i"} = 0;
1340       $form->{"tax_$i"}    = 0;
1341       $creditcount--;
1342       $form->{creditlock} = 1;
1343     }
1344     if (($creditcount >= 2) && ($debitcount == 2)) {
1345       $form->{"debit_$i"} = 0;
1346       $form->{"tax_$i"}   = 0;
1347       $debitcount--;
1348       $form->{debitlock} = 1;
1349     }
1350     if (($creditcount == 1) && ($debitcount == 2)) {
1351       $form->{creditlock} = 1;
1352     }
1353     if (($creditcount == 2) && ($debitcount == 1)) {
1354       $form->{debitlock} = 1;
1355     }
1356     if ($debitcredit && $credittax) {
1357       $form->{"taxchart_$i"} = "0--0.00";
1358     }
1359     if (!$debitcredit && $debittax) {
1360       $form->{"taxchart_$i"} = "0--0.00";
1361     }
1362     my $amount = ($form->{"debit_$i"} == 0)
1363             ? $form->{"credit_$i"}
1364             : $form->{"debit_$i"};
1365     my $j = $#a;
1366     if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
1367       $form->{"taxchart_$i"} = "0--0.00";
1368       $form->{"tax_$i"}      = 0;
1369     }
1370     my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
1371     if ($taxkey > 1) {
1372       if ($debitcredit) {
1373         $debittax = 1;
1374       } else {
1375         $credittax = 1;
1376       }
1377       if ($form->{taxincluded}) {
1378         $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
1379         if ($debitcredit) {
1380           $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"};
1381         } else {
1382           $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"};
1383         }
1384       } else {
1385         $form->{"tax_$i"} = $amount * $rate;
1386       }
1387     } else {
1388       $form->{"tax_$i"} = 0;
1389     }
1390
1391     for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
1392     $count++;
1393   }
1394
1395   if ($split_safety{-1} > 1 && $split_safety{1} > 1) {
1396     $::form->error($::locale->text("Split entry detected. The values you have entered will result in an entry with more than one position on both debit and credit. Due to known problems involving accounting software Lx-Office does not allow these."));
1397   }
1398
1399   for my $i (1 .. $count) {
1400     my $j = $i - 1;
1401     for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
1402   }
1403
1404   for my $i ($count + 1 .. $form->{rowcount}) {
1405     for (@flds) { delete $form->{"${_}_$i"} }
1406   }
1407
1408   my ($debit, $credit, $taxtotal);
1409   for my $i (1 .. $form->{rowcount}) {
1410     my $dr  = $form->{"debit_$i"};
1411     my $cr  = $form->{"credit_$i"};
1412     my $tax = $form->{"tax_$i"};
1413     if ($dr && $cr) {
1414       $form->error($locale->text('Cannot post transaction with a debit and credit entry for the same account!'));
1415     }
1416     $debit    += $dr + $tax if $dr;
1417     $credit   += $cr + $tax if $cr;
1418     $taxtotal += $tax if $form->{taxincluded}
1419   }
1420
1421   $form->{taxincluded} = 0 if !$taxtotal;
1422
1423   # this is just for the wise guys
1424   $form->error($locale->text('Cannot post transaction for a closed period!'))
1425     if ($form->date_closed($form->{"transdate"}, \%myconfig));
1426   if ($form->round_amount($debit, 2) != $form->round_amount($credit, 2)) {
1427     $form->error($locale->text('Out of balance transaction!'));
1428   }
1429
1430   if ($form->round_amount($debit, 2) + $form->round_amount($credit, 2) == 0) {
1431     $form->error($locale->text('Empty transaction!'));
1432   }
1433
1434   if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
1435     $errno *= -1;
1436     my @err;
1437     $err[1] = $locale->text('Cannot have a value in both Debit and Credit!');
1438     $err[2] = $locale->text('Debit and credit out of balance!');
1439     $err[3] = $locale->text('Cannot post a transaction without a value!');
1440
1441     $form->error($err[$errno]);
1442   }
1443   undef($form->{callback});
1444   # saving the history
1445   if(!exists $form->{addition} && $form->{id} ne "") {
1446     $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
1447     $form->{addition} = "SAVED";
1448     $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id};
1449     $form->save_history;
1450   }
1451   # /saving the history
1452
1453   $main::lxdebug->leave_sub();
1454 }
1455
1456 sub post {
1457   $main::lxdebug->enter_sub();
1458
1459   $main::auth->assert('general_ledger');
1460
1461   my $form     = $main::form;
1462   my $locale   = $main::locale;
1463
1464   if ($::myconfig{mandatory_departments} && !$form->{department}) {
1465     $form->{saved_message} = $::locale->text('You have to specify a department.');
1466     update();
1467     exit;
1468   }
1469
1470   $form->{title}  = $locale->text("$form->{title} General Ledger Transaction");
1471   $form->{storno} = 0;
1472
1473   post_transaction();
1474
1475   remove_draft() if $form->{remove_draft};
1476
1477   $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details");
1478   $form->redirect($form->{callback});
1479
1480   $main::lxdebug->leave_sub();
1481 }
1482
1483 sub post_as_new {
1484   $main::lxdebug->enter_sub();
1485
1486   $main::auth->assert('general_ledger');
1487
1488   my $form     = $main::form;
1489
1490   $form->{id} = 0;
1491   &add;
1492   $main::lxdebug->leave_sub();
1493
1494 }
1495
1496 sub storno {
1497   $main::lxdebug->enter_sub();
1498
1499   $main::auth->assert('general_ledger');
1500
1501   my $form     = $main::form;
1502   my %myconfig = %main::myconfig;
1503   my $locale   = $main::locale;
1504
1505   # don't cancel cancelled transactions
1506   if (IS->has_storno(\%myconfig, $form, 'gl')) {
1507     $form->{title} = $locale->text("Cancel Accounts Receivables Transaction");
1508     $form->error($locale->text("Transaction has already been cancelled!"));
1509   }
1510
1511   GL->storno($form, \%myconfig, $form->{id});
1512
1513   # saving the history
1514   if(!exists $form->{addition} && $form->{id} ne "") {
1515     $form->{snumbers} = "ordnumber_$form->{ordnumber}";
1516     $form->{addition} = "STORNO";
1517     $form->save_history;
1518   }
1519   # /saving the history
1520
1521   $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
1522
1523   $main::lxdebug->leave_sub();
1524 }
1525
1526 sub continue {
1527   call_sub($main::form->{nextsub});
1528 }
1529
1530 1;