1 #=====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #=====================================================================
8 # SQL-Ledger Accounting
9 # Copyright (c) 1998-2002
11 # Author: Dieter Simader
12 # Email: dsimader@sql-ledger.org
13 # Web: http://www.sql-ledger.org
16 # This program is free software; you can redistribute it and/or modify
17 # it under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2 of the License, or
19 # (at your option) any later version.
21 # This program is distributed in the hope that it will be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #======================================================================
32 #======================================================================
37 use POSIX qw(strftime);
38 use List::Util qw(sum);
44 use SL::ReportGenerator;
46 require "bin/mozilla/common.pl";
47 require "bin/mozilla/drafts.pl";
48 require "bin/mozilla/reportgenerator.pl";
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')
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')
79 $main::lxdebug->enter_sub();
81 $main::auth->assert('general_ledger');
83 my $form = $main::form;
84 my %myconfig = %main::myconfig;
86 return $main::lxdebug->leave_sub() if (load_draft_maybe());
88 $form->{title} = "Add";
90 $form->{callback} = "gl.pl?action=add" unless $form->{callback};
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);
96 $form->{rowcount} = 2;
103 $form->all_departments(\%myconfig);
104 if (@{ $form->{all_departments} || [] }) {
105 $form->{selectdepartment} = "<option>\n";
108 $form->{selectdepartment} .=
109 "<option>$_->{description}--$_->{id}\n"
110 } (@{ $form->{all_departments} || [] });
113 $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
116 $main::lxdebug->leave_sub();
120 sub prepare_transaction {
121 $main::lxdebug->enter_sub();
123 $main::auth->assert('general_ledger');
125 my $form = $main::form;
126 my %myconfig = %main::myconfig;
128 GL->transaction(\%myconfig, \%$form);
130 $form->{amount} = $form->format_amount(\%myconfig, $form->{amount}, 2);
133 $form->all_departments(\%myconfig);
134 if (@{ $form->{all_departments} || [] }) {
135 $form->{selectdepartment} = "<option>\n";
138 $form->{selectdepartment} .=
139 "<option>$_->{description}--$_->{id}\n"
140 } (@{ $form->{all_departments} || [] });
146 foreach my $ref (@{ $form->{GL} }) {
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"};
155 $form->{"credit_$j"} += $form->{"tax_$j"};
158 $form->{"project_id_$j"} = $ref->{project_id};
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;
167 $form->{totalcredit} += $ref->{amount};
168 $form->{"credit_$i"} = $ref->{amount};
170 $form->{"taxchart_$i"} = "0--0.00";
171 $form->{"project_id_$i"} = $ref->{project_id};
174 if ($ref->{taxaccno} && !$tax) {
175 $taxaccno = $ref->{taxaccno};
183 $form->{rowcount} = $i;
185 ($form->datetonum($form->{transdate}, \%myconfig) <=
186 $form->datetonum($form->{closedto}, \%myconfig));
188 $main::lxdebug->leave_sub();
192 $main::lxdebug->enter_sub();
194 $main::auth->assert('general_ledger');
196 my $form = $main::form;
197 my %myconfig = %main::myconfig;
199 prepare_transaction();
201 $form->{title} = "Edit";
203 $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
209 $main::lxdebug->leave_sub();
214 $::lxdebug->enter_sub;
215 $::auth->assert('general_ledger');
217 $::form->all_departments(\%::myconfig);
219 projects => { key => "ALL_PROJECTS", all => 1 },
221 $::form->{ALL_EMPLOYEES} = SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]);
224 print $::form->parse_html_template('gl/search', {
225 department_label => sub { ("$_[0]{description}--$_[0]{id}")x2 },
226 employee_label => sub { "$_[0]{id}--$_[0]{name}" },
229 $::lxdebug->leave_sub;
232 sub create_subtotal_row {
233 $main::lxdebug->enter_sub();
235 my ($totals, $columns, $column_alignment, $subtotal_columns, $class) = @_;
237 my $form = $main::form;
238 my %myconfig = %main::myconfig;
240 my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
242 map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } @{ $subtotal_columns };
244 map { $totals->{$_} = 0 } @{ $subtotal_columns };
246 $main::lxdebug->leave_sub();
251 sub generate_report {
252 $main::lxdebug->enter_sub();
254 $main::auth->assert('general_ledger');
256 my $form = $main::form;
257 my %myconfig = %main::myconfig;
258 my $locale = $main::locale;
260 # 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
262 # <form method=post action=gl.pl>
263 # <input type=hidden name=sort value=datesort> # form->{sort} setzen
264 # <input type=hidden name=nextsub value=generate_report>
266 # anhand von neuer Variable datesort wird jetzt $form->{sort} auf transdate oder gldate gesetzt
267 # damit ist die Hidden Variable "sort" wahrscheinlich sogar überflüssig
269 # ändert man die Sortierreihenfolge per Klick auf eine der Überschriften wird die Variable "sort" per GET übergeben, z.B. id,transdate, gldate, ...
270 # 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
272 if ( $form->{sort} eq 'datesort' ) { # sollte bei einem Post (Aufruf aus Suchmaske) immer wahr sein
273 # je nachdem ob in Suchmaske "transdate" oder "gldate" ausgesucht wurde erstes Suchergebnis entsprechend sortieren
274 $form->{sort} = $form->{datesort};
278 report_generator_set_default_sort("$form->{datesort}", 1);
279 # report_generator_set_default_sort('transdate', 1);
281 GL->all_transactions(\%myconfig, \%$form);
283 my %acctype = ('A' => $locale->text('Asset'),
284 'C' => $locale->text('Contra'),
285 'L' => $locale->text('Liability'),
286 'Q' => $locale->text('Equity'),
287 'I' => $locale->text('Revenue'),
288 'E' => $locale->text('Expense'),);
290 $form->{title} = $locale->text('Journal');
291 if ($form->{category} ne 'X') {
292 $form->{title} .= " : " . $locale->text($acctype{ $form->{category} });
295 $form->{landscape} = 1;
297 my $ml = ($form->{ml} =~ /(A|E|Q)/) ? -1 : 1;
300 gldate transdate id reference description
301 notes source debit debit_accno
302 credit credit_accno debit_tax debit_tax_accno
303 credit_tax credit_tax_accno projectnumbers balance employee
306 # add employee here, so that variable is still known and passed in url when choosing a different sort order in resulting table
307 my @hidden_variables = qw(accno source reference department description notes project_id datefrom dateto employee datesort category l_subtotal);
308 push @hidden_variables, map { "l_${_}" } @columns;
309 foreach ( @hidden_variables ) {
313 my (@options, @date_options);
314 push @options, $locale->text('Account') . " : $form->{accno} $form->{account_description}" if ($form->{accno});
315 push @options, $locale->text('Source') . " : $form->{source}" if ($form->{source});
316 push @options, $locale->text('Reference') . " : $form->{reference}" if ($form->{reference});
317 push @options, $locale->text('Description') . " : $form->{description}" if ($form->{description});
318 push @options, $locale->text('Notes') . " : $form->{notes}" if ($form->{notes});
319 push @options, $locale->text('Employee') . " : $form->{employee_name}" if ($form->{employee_name});
320 my $datesorttext = $form->{datesort} eq 'transdate' ? $locale->text('Invoice Date') : $locale->text('Booking Date');
321 push @date_options, "$datesorttext" if ($form->{datesort} and ($form->{datefrom} or $form->{dateto}));
322 push @date_options, $locale->text('From'), $locale->date(\%myconfig, $form->{datefrom}, 1) if ($form->{datefrom});
323 push @date_options, $locale->text('Bis'), $locale->date(\%myconfig, $form->{dateto}, 1) if ($form->{dateto});
324 push @options, join(' ', @date_options) if (scalar @date_options);
326 if ($form->{department}) {
327 my ($department) = split /--/, $form->{department};
328 push @options, $locale->text('Department') . " : $department";
332 my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
336 $form->{l_credit_accno} = 'Y';
337 $form->{l_debit_accno} = 'Y';
338 $form->{l_credit_tax} = 'Y';
339 $form->{l_debit_tax} = 'Y';
340 # $form->{l_gldate} = 'Y'; # Spalte mit gldate immer anzeigen
341 $form->{l_credit_tax_accno} = 'Y';
342 $form->{l_datesort} = 'Y';
343 $form->{l_debit_tax_accno} = 'Y';
344 $form->{l_balance} = $form->{accno} ? 'Y' : '';
347 'id' => { 'text' => $locale->text('ID'), },
348 'transdate' => { 'text' => $locale->text('Invoice Date'), },
349 'gldate' => { 'text' => $locale->text('Booking Date'), },
350 'reference' => { 'text' => $locale->text('Reference'), },
351 'source' => { 'text' => $locale->text('Source'), },
352 'description' => { 'text' => $locale->text('Description'), },
353 'notes' => { 'text' => $locale->text('Notes'), },
354 'debit' => { 'text' => $locale->text('Debit'), },
355 'debit_accno' => { 'text' => $locale->text('Debit Account'), },
356 'credit' => { 'text' => $locale->text('Credit'), },
357 'credit_accno' => { 'text' => $locale->text('Credit Account'), },
358 'debit_tax' => { 'text' => $locale->text('Debit Tax'), },
359 'debit_tax_accno' => { 'text' => $locale->text('Debit Tax Account'), },
360 'credit_tax' => { 'text' => $locale->text('Credit Tax'), },
361 'credit_tax_accno' => { 'text' => $locale->text('Credit Tax Account'), },
362 'balance' => { 'text' => $locale->text('Balance'), },
363 'projectnumbers' => { 'text' => $locale->text('Project Numbers'), },
364 'employee' => { 'text' => $locale->text('Employee'), },
367 foreach my $name (qw(id transdate gldate reference description debit_accno credit_accno debit_tax_accno credit_tax_accno)) {
368 my $sortname = $name =~ m/accno/ ? 'accno' : $name;
369 my $sortdir = $sortname eq $form->{sort} ? 1 - $form->{sortdir} : $form->{sortdir};
370 $column_defs{$name}->{link} = $callback . "&sort=$sortname&sortdir=$sortdir";
373 map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
374 map { $column_defs{$_}->{visible} = 0 } qw(debit_accno credit_accno debit_tax_accno credit_tax_accno) if $form->{accno};
376 my %column_alignment;
377 map { $column_alignment{$_} = 'right' } qw(balance id debit credit debit_tax credit_tax balance);
378 map { $column_alignment{$_} = 'center' } qw(transdate gldate reference debit_accno credit_accno debit_tax_accno credit_tax_accno);
379 map { $column_alignment{$_} = 'left' } qw(description source notes);
380 map { $column_defs{$_}->{align} = $column_alignment{$_} } keys %column_alignment;
382 my $report = SL::ReportGenerator->new(\%myconfig, $form);
384 $report->set_columns(%column_defs);
385 $report->set_column_order(@columns);
387 $report->set_export_options('generate_report', @hidden_variables, qw(sort sortdir));
389 $report->set_sort_indicator($form->{sort} eq 'accno' ? 'debit_accno' : $form->{sort}, $form->{sortdir});
391 $report->set_options('top_info_text' => join("\n", @options),
392 'output_format' => 'HTML',
393 'title' => $form->{title},
394 'attachment_basename' => $locale->text('general_ledger_list') . strftime('_%Y%m%d', localtime time),
396 $report->set_options_from_form();
397 $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
399 # add sort to callback
400 $form->{callback} = "$callback&sort=" . E($form->{sort}) . "&sortdir=" . E($form->{sortdir});
403 my @totals_columns = qw(debit credit debit_tax credit_tax);
404 my %subtotals = map { $_ => 0 } @totals_columns;
405 my %totals = map { $_ => 0 } @totals_columns;
408 foreach my $ref (@{ $form->{GL} }) {
412 foreach my $key (qw(debit credit debit_tax credit_tax)) {
414 foreach my $idx (sort keys(%{ $ref->{$key} })) {
415 my $value = $ref->{$key}->{$idx};
416 $subtotals{$key} += $value;
417 $totals{$key} += $value;
418 if ($key =~ /debit.*/) {
423 $form->{balance} = $form->{balance} + $value * $ml;
424 push @{ $rows{$key} }, $form->format_amount(\%myconfig, $value, 2);
428 foreach my $key (qw(debit_accno credit_accno debit_tax_accno credit_tax_accno ac_transdate source)) {
429 my $col = $key eq 'ac_transdate' ? 'transdate' : $key;
430 $rows{$col} = [ map { $ref->{$key}->{$_} } sort keys(%{ $ref->{$key} }) ];
434 map { $row->{$_} = { 'data' => '', 'align' => $column_alignment{$_} } } @columns;
437 if ($form->{balance} < 0) {
440 } elsif ($form->{balance} > 0) {
444 my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
447 $row->{balance}->{data} = $data;
448 $row->{projectnumbers}->{data} = join ", ", sort { lc($a) cmp lc($b) } keys %{ $ref->{projectnumbers} };
450 map { $row->{$_}->{data} = $ref->{$_} } qw(id reference description notes gldate employee);
452 map { $row->{$_}->{data} = \@{ $rows{$_} }; } qw(transdate debit credit debit_accno credit_accno debit_tax_accno credit_tax_accno source);
454 foreach my $col (qw(debit_accno credit_accno debit_tax_accno credit_tax_accno)) {
455 $row->{$col}->{link} = [ map { "${callback}&accno=" . E($_) } @{ $rows{$col} } ];
458 map { $row->{$_}->{data} = \@{ $rows{$_} } if ($ref->{"${_}_accno"} ne "") } qw(debit_tax credit_tax);
460 $row->{reference}->{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'id=' . E($ref->{id}), 'callback');
462 my $row_set = [ $row ];
464 if ( ($form->{l_subtotal} eq 'Y' && !$form->{report_generator_csv_options_for_import} )
465 && (($idx == (scalar @{ $form->{GL} } - 1))
466 || ($ref->{ $form->{sort} } ne $form->{GL}->[$idx + 1]->{ $form->{sort} }))) {
467 push @{ $row_set }, create_subtotal_row(\%subtotals, \@columns, \%column_alignment, [ qw(debit credit) ], 'listsubtotal');
470 $report->add_data($row_set);
475 # = 0 for balanced ledger
476 my $balanced_ledger = $totals{debit} + $totals{debit_tax} - $totals{credit} - $totals{credit_tax};
478 my $row = create_subtotal_row(\%totals, \@columns, \%column_alignment, [ qw(debit credit debit_tax credit_tax) ], 'listtotal');
481 if ($form->{balance} < 0) {
484 } elsif ($form->{balance} > 0) {
488 my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
491 $row->{balance}->{data} = $data;
493 if ( !$form->{report_generator_csv_options_for_import} ) {
494 $report->add_separator();
495 $report->add_data($row);
498 my $raw_bottom_info_text;
500 if (!$form->{accno} && (abs($balanced_ledger) > 0.001)) {
501 $raw_bottom_info_text .=
502 '<p><span class="unbalanced_ledger">'
503 . $locale->text('Unbalanced Ledger')
505 . $form->format_amount(\%myconfig, $balanced_ledger, 3)
509 $raw_bottom_info_text .= $form->parse_html_template('gl/generate_report_bottom');
511 $report->set_options('raw_bottom_info_text' => $raw_bottom_info_text);
513 $report->generate_with_headers();
515 $main::lxdebug->leave_sub();
519 $main::lxdebug->enter_sub();
521 $main::auth->assert('general_ledger');
523 my $form = $main::form;
524 my %myconfig = %main::myconfig;
526 $form->{oldtransdate} = $form->{transdate};
534 my ($debitcredit, $amount);
537 qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
539 for my $i (1 .. $form->{rowcount}) {
541 unless (($form->{"debit_$i"} eq "") && ($form->{"credit_$i"} eq "")) {
542 for (qw(debit credit tax)) {
544 $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
548 $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
555 if (($debitcount >= 2) && ($creditcount == 2)) {
556 $form->{"credit_$i"} = 0;
557 $form->{"tax_$i"} = 0;
559 $form->{creditlock} = 1;
561 if (($creditcount >= 2) && ($debitcount == 2)) {
562 $form->{"debit_$i"} = 0;
563 $form->{"tax_$i"} = 0;
565 $form->{debitlock} = 1;
567 if (($creditcount == 1) && ($debitcount == 2)) {
568 $form->{creditlock} = 1;
570 if (($creditcount == 2) && ($debitcount == 1)) {
571 $form->{debitlock} = 1;
573 if ($debitcredit && $credittax) {
574 $form->{"taxchart_$i"} = "0--0.00";
576 if (!$debitcredit && $debittax) {
577 $form->{"taxchart_$i"} = "0--0.00";
580 ($form->{"debit_$i"} == 0)
581 ? $form->{"credit_$i"}
582 : $form->{"debit_$i"};
584 if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
585 $form->{"taxchart_$i"} = "0--0.00";
586 $form->{"tax_$i"} = 0;
588 my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
595 if ($form->{taxincluded}) {
596 $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
598 $form->{"tax_$i"} = $amount * $rate;
601 $form->{"tax_$i"} = 0;
604 for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
609 for my $i (1 .. $count) {
611 for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
614 for my $i ($count + 1 .. $form->{rowcount}) {
615 for (@flds) { delete $form->{"${_}_$i"} }
618 $form->{rowcount} = $count + 1;
621 $main::lxdebug->leave_sub();
627 $main::lxdebug->enter_sub();
629 $main::auth->assert('general_ledger');
631 my $form = $main::form;
632 my %myconfig = %main::myconfig;
636 # for $i (1 .. $form->{rowcount}) {
637 # $form->{totaldebit} += $form->parse_amount(\%myconfig, $form->{"debit_$i"});
638 # $form->{totalcredit} += $form->parse_amount(\%myconfig, $form->{"credit_$i"});
642 &display_rows($init);
644 $main::lxdebug->leave_sub();
650 $main::lxdebug->enter_sub();
652 $main::auth->assert('general_ledger');
654 my $form = $main::form;
655 my %myconfig = %main::myconfig;
656 my $cgi = $::request->{cgi};
658 $form->{debit_1} = 0 if !$form->{"debit_1"};
659 $form->{totaldebit} = 0;
660 $form->{totalcredit} = 0;
662 my %project_labels = ();
663 my @project_values = ("");
664 foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
665 push(@project_values, $item->{"id"});
666 $project_labels{$item->{"id"}} = $item->{"projectnumber"};
669 my %chart_labels = ();
670 my @chart_values = ();
673 foreach my $item (@{ $form->{ALL_CHARTS} }) {
674 if ($item->{charttype} eq 'H'){ #falls überschrift
675 next; #überspringen (Bug 1150)
677 my $key = $item->{accno} . "--" . $item->{tax_id};
678 $taxchart_init = $item->{tax_id} unless (@chart_values);
679 push(@chart_values, $key);
680 $chart_labels{$key} = $item->{accno} . "--" . $item->{description};
681 $charts{$item->{accno}} = $item;
684 my %taxchart_labels = ();
685 my @taxchart_values = ();
687 foreach my $item (@{ $form->{ALL_TAXCHARTS} }) {
688 my $key = $item->{id} . "--" . $item->{rate};
689 $taxchart_init = $key if ($taxchart_init == $item->{id});
690 push(@taxchart_values, $key);
691 $taxchart_labels{$key} = $item->{taxdescription} . " " . $item->{rate} * 100 . ' %';
692 $taxcharts{$item->{id}} = $item;
695 my ($source, $memo, $source_hidden, $memo_hidden);
696 for my $i (1 .. $form->{rowcount}) {
697 if ($form->{show_details}) {
699 <td><input name="source_$i" value="$form->{"source_$i"}" size="16"></td>|;
701 <td><input name="memo_$i" value="$form->{"memo_$i"}" size="16"></td>|;
704 <input type="hidden" name="source_$i" value="$form->{"source_$i"}" size="16">|;
706 <input type="hidden" name="memo_$i" value="$form->{"memo_$i"}" size="16">|;
709 my $selected_accno_full;
710 my ($accno_row) = split(/--/, $form->{"accno_$i"});
711 my $item = $charts{$accno_row};
712 $selected_accno_full = "$item->{accno}--$item->{tax_id}";
714 my $selected_taxchart = $form->{"taxchart_$i"};
715 my ($selected_accno, $selected_tax_id) = split(/--/, $selected_accno_full);
716 my ($previous_accno, $previous_tax_id) = split(/--/, $form->{"previous_accno_$i"});
718 if ($previous_accno &&
719 ($previous_accno eq $selected_accno) &&
720 ($previous_tax_id ne $selected_tax_id)) {
721 my $item = $taxcharts{$selected_tax_id};
722 $selected_taxchart = "$item->{id}--$item->{rate}";
725 $selected_accno = '' if ($init);
726 $selected_taxchart ||= $taxchart_init;
728 my $accno = qq|<td>| .
729 NTI($cgi->popup_menu('-name' => "accno_$i",
731 '-onChange' => "setTaxkey($i)",
732 '-style' => 'width:200px',
733 '-values' => \@chart_values,
734 '-labels' => \%chart_labels,
735 '-default' => $selected_accno_full))
736 . $cgi->hidden('-name' => "previous_accno_$i",
737 '-default' => $selected_accno_full)
739 my $tax_ddbox = qq|<td>| .
740 NTI($cgi->popup_menu('-name' => "taxchart_$i",
741 '-id' => "taxchart_$i",
742 '-style' => 'width:200px',
743 '-values' => \@taxchart_values,
744 '-labels' => \%taxchart_labels,
745 '-default' => $selected_taxchart))
748 my ($fx_transaction, $checked);
750 if ($form->{transfer}) {
751 $fx_transaction = qq|
752 <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
757 if ($form->{"debit_$i"} != 0) {
758 $form->{totaldebit} += $form->{"debit_$i"};
759 if (!$form->{taxincluded}) {
760 $form->{totaldebit} += $form->{"tax_$i"};
763 $form->{totalcredit} += $form->{"credit_$i"};
764 if (!$form->{taxincluded}) {
765 $form->{totalcredit} += $form->{"tax_$i"};
769 for (qw(debit credit tax)) {
772 ? $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2)
776 if ($i < $form->{rowcount}) {
777 if ($form->{transfer}) {
778 $checked = ($form->{"fx_transaction_$i"}) ? "1" : "";
779 my $x = ($checked) ? "x" : "";
780 $fx_transaction = qq|
781 <td><input type=hidden name="fx_transaction_$i" value="$checked">$x</td>
784 $form->hide_form("accno_$i");
787 if ($form->{transfer}) {
788 $fx_transaction = qq|
789 <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
794 my $debitreadonly = "";
795 my $creditreadonly = "";
796 if ($i == $form->{rowcount}) {
797 if ($form->{debitlock}) {
798 $debitreadonly = "readonly";
799 } elsif ($form->{creditlock}) {
800 $creditreadonly = "readonly";
805 NTI($cgi->popup_menu('-name' => "project_id_$i",
806 '-values' => \@project_values,
807 '-labels' => \%project_labels,
808 '-default' => $form->{"project_id_$i"} ));
809 my $projectnumber_hidden = qq|
810 <input type="hidden" name="project_id_$i" value="$form->{"project_id_$i"}">|;
812 my $copy2credit = $i == 1 ? 'onkeyup="copy_debit_to_credit()"' : '';
814 print qq|<tr valign=top>
816 <td id="chart_balance_$i" align="right"> </td>
818 <td><input name="debit_$i" size="8" value="$form->{"debit_$i"}" accesskey=$i $copy2credit $debitreadonly></td>
819 <td><input name="credit_$i" size=8 value="$form->{"credit_$i"}" $creditreadonly></td>
820 <td><input type="hidden" name="tax_$i" value="$form->{"tax_$i"}">$form->{"tax_$i"}</td>
823 if ($form->{show_details}) {
827 <td>$projectnumber</td>
833 $projectnumber_hidden
841 $form->hide_form(qw(rowcount selectaccno));
843 $main::lxdebug->leave_sub();
848 $::lxdebug->enter_sub;
849 $::auth->assert('general_ledger');
853 my @old_project_ids = grep { $_ } map{ $::form->{"project_id_$_"} } 1..$::form->{rowcount};
855 $::form->get_lists("projects" => { "key" => "ALL_PROJECTS",
857 "old_id" => \@old_project_ids },
858 "charts" => { "key" => "ALL_CHARTS",
859 "transdate" => $::form->{transdate} },
860 "taxcharts" => "ALL_TAXCHARTS");
862 GL->get_chart_balances('charts' => $::form->{ALL_CHARTS});
864 my $title = $::form->{title};
865 $::form->{title} = $::locale->text("$title General Ledger Transaction");
866 # $locale->text('Add General Ledger Transaction')
867 # $locale->text('Edit General Ledger Transaction')
869 map { $::form->{$_} =~ s/\"/"/g }
872 $::form->{selectdepartment} =~ s/ selected//;
873 $::form->{selectdepartment} =~
874 s/option>\Q$::form->{department}\E/option selected>$::form->{department}/;
877 $::form->{fokus} = "gl.reference";
878 $::form->{taxincluded} = "1";
880 $::form->{fokus} = qq|gl.accno_$::form->{rowcount}|;
883 $::form->{previous_id} ||= "--";
884 $::form->{previous_gldate} ||= "--";
887 print $::form->parse_html_template('gl/form_header', {
888 hide_title => $title,
891 $::lxdebug->leave_sub;
896 $::lxdebug->enter_sub;
897 $::auth->assert('general_ledger');
899 my ($follow_ups, $follow_ups_due);
902 $follow_ups = FU->follow_ups('trans_id' => $::form->{id});
903 $follow_ups_due = sum map { $_->{due} * 1 } @{ $follow_ups || [] };
906 my $radieren = $::form->current_date(\%::myconfig) eq $::form->{gldate};
908 print $::form->parse_html_template('gl/form_footer', {
909 radieren => $radieren,
910 follow_ups => $follow_ups,
911 follow_ups_due => $follow_ups_due,
914 $::lxdebug->leave_sub;
918 $main::lxdebug->enter_sub();
920 my $form = $main::form;
921 my $locale = $main::locale;
926 <form method=post action=gl.pl>
929 map { $form->{$_} =~ s/\"/"/g } qw(reference description);
931 delete $form->{header};
933 foreach my $key (keys %$form) {
934 next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
935 print qq|<input type="hidden" name="$key" value="$form->{$key}">\n|;
939 <h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
942 . $locale->text('Are you sure you want to delete Transaction')
943 . qq| $form->{reference}</h4>
945 <input name=action class=submit type=submit value="|
946 . $locale->text('Yes') . qq|">
949 $main::lxdebug->leave_sub();
954 $main::lxdebug->enter_sub();
956 my $form = $main::form;
957 my %myconfig = %main::myconfig;
958 my $locale = $main::locale;
960 if (GL->delete_transaction(\%myconfig, \%$form)){
962 if(!exists $form->{addition} && $form->{id} ne "") {
963 $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
964 $form->{addition} = "DELETED";
967 # /saving the history
968 $form->redirect($locale->text('Transaction deleted!'))
970 $form->error($locale->text('Cannot delete transaction!'));
971 $main::lxdebug->leave_sub();
975 sub post_transaction {
976 $main::lxdebug->enter_sub();
978 my $form = $main::form;
979 my %myconfig = %main::myconfig;
980 my $locale = $main::locale;
982 # check if there is something in reference and date
983 $form->isblank("reference", $locale->text('Reference missing!'));
984 $form->isblank("transdate", $locale->text('Transaction Date missing!'));
985 $form->isblank("description", $locale->text('Description missing!'));
987 my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
988 my $closedto = $form->datetonum($form->{closedto}, \%myconfig);
997 my %split_safety = ();
999 my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
1001 for my $i (1 .. $form->{rowcount}) {
1002 next if $form->{"debit_$i"} eq "" && $form->{"credit_$i"} eq "";
1004 for (qw(debit credit tax)) {
1005 $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
1009 $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
1011 $split_safety{ $form->{"debit_$i"} <=> 0 }++;
1012 $split_safety{ - $form->{"credit_$i"} <=> 0 }++;
1020 if (($debitcount >= 2) && ($creditcount == 2)) {
1021 $form->{"credit_$i"} = 0;
1022 $form->{"tax_$i"} = 0;
1024 $form->{creditlock} = 1;
1026 if (($creditcount >= 2) && ($debitcount == 2)) {
1027 $form->{"debit_$i"} = 0;
1028 $form->{"tax_$i"} = 0;
1030 $form->{debitlock} = 1;
1032 if (($creditcount == 1) && ($debitcount == 2)) {
1033 $form->{creditlock} = 1;
1035 if (($creditcount == 2) && ($debitcount == 1)) {
1036 $form->{debitlock} = 1;
1038 if ($debitcredit && $credittax) {
1039 $form->{"taxchart_$i"} = "0--0.00";
1041 if (!$debitcredit && $debittax) {
1042 $form->{"taxchart_$i"} = "0--0.00";
1044 my $amount = ($form->{"debit_$i"} == 0)
1045 ? $form->{"credit_$i"}
1046 : $form->{"debit_$i"};
1048 if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
1049 $form->{"taxchart_$i"} = "0--0.00";
1050 $form->{"tax_$i"} = 0;
1052 my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
1059 if ($form->{taxincluded}) {
1060 $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
1062 $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"};
1064 $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"};
1067 $form->{"tax_$i"} = $amount * $rate;
1070 $form->{"tax_$i"} = 0;
1073 for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
1077 if ($split_safety{-1} > 1 && $split_safety{1} > 1) {
1078 $::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."));
1081 for my $i (1 .. $count) {
1083 for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
1086 for my $i ($count + 1 .. $form->{rowcount}) {
1087 for (@flds) { delete $form->{"${_}_$i"} }
1090 my ($debit, $credit, $taxtotal);
1091 for my $i (1 .. $form->{rowcount}) {
1092 my $dr = $form->{"debit_$i"};
1093 my $cr = $form->{"credit_$i"};
1094 my $tax = $form->{"tax_$i"};
1096 $form->error($locale->text('Cannot post transaction with a debit and credit entry for the same account!'));
1098 $debit += $dr + $tax if $dr;
1099 $credit += $cr + $tax if $cr;
1100 $taxtotal += $tax if $form->{taxincluded}
1103 $form->{taxincluded} = 0 if !$taxtotal;
1105 # this is just for the wise guys
1106 $form->error($locale->text('Cannot post transaction for a closed period!'))
1107 if ($form->date_closed($form->{"transdate"}, \%myconfig));
1108 if ($form->round_amount($debit, 2) != $form->round_amount($credit, 2)) {
1109 $form->error($locale->text('Out of balance transaction!'));
1112 if ($form->round_amount($debit, 2) + $form->round_amount($credit, 2) == 0) {
1113 $form->error($locale->text('Empty transaction!'));
1116 if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
1119 $err[1] = $locale->text('Cannot have a value in both Debit and Credit!');
1120 $err[2] = $locale->text('Debit and credit out of balance!');
1121 $err[3] = $locale->text('Cannot post a transaction without a value!');
1123 $form->error($err[$errno]);
1125 undef($form->{callback});
1126 # saving the history
1127 if(!exists $form->{addition} && $form->{id} ne "") {
1128 $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
1129 $form->{addition} = "SAVED";
1130 $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id};
1131 $form->save_history;
1133 # /saving the history
1135 $main::lxdebug->leave_sub();
1139 $main::lxdebug->enter_sub();
1141 $main::auth->assert('general_ledger');
1143 my $form = $main::form;
1144 my $locale = $main::locale;
1146 if ($::myconfig{mandatory_departments} && !$form->{department}) {
1147 $form->{saved_message} = $::locale->text('You have to specify a department.');
1152 $form->{title} = $locale->text("$form->{title} General Ledger Transaction");
1153 $form->{storno} = 0;
1157 remove_draft() if $form->{remove_draft};
1159 $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details");
1160 $form->redirect($form->{callback});
1162 $main::lxdebug->leave_sub();
1166 $main::lxdebug->enter_sub();
1168 $main::auth->assert('general_ledger');
1170 my $form = $main::form;
1174 $main::lxdebug->leave_sub();
1179 $main::lxdebug->enter_sub();
1181 $main::auth->assert('general_ledger');
1183 my $form = $main::form;
1184 my %myconfig = %main::myconfig;
1185 my $locale = $main::locale;
1187 # don't cancel cancelled transactions
1188 if (IS->has_storno(\%myconfig, $form, 'gl')) {
1189 $form->{title} = $locale->text("Cancel Accounts Receivables Transaction");
1190 $form->error($locale->text("Transaction has already been cancelled!"));
1193 GL->storno($form, \%myconfig, $form->{id});
1195 # saving the history
1196 if(!exists $form->{addition} && $form->{id} ne "") {
1197 $form->{snumbers} = "ordnumber_$form->{ordnumber}";
1198 $form->{addition} = "STORNO";
1199 $form->save_history;
1201 # /saving the history
1203 $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
1205 $main::lxdebug->leave_sub();
1209 call_sub($main::form->{nextsub});