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 ]);
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|')|;
228 print $::form->parse_html_template('gl/search', {
230 department_label => sub { ("$_[0]{description}--$_[0]{id}")x2 },
231 employee_label => sub { "$_[0]{id}--$_[0]{name}" },
234 $::lxdebug->leave_sub;
237 sub create_subtotal_row {
238 $main::lxdebug->enter_sub();
240 my ($totals, $columns, $column_alignment, $subtotal_columns, $class) = @_;
242 my $form = $main::form;
243 my %myconfig = %main::myconfig;
245 my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
247 map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } @{ $subtotal_columns };
249 map { $totals->{$_} = 0 } @{ $subtotal_columns };
251 $main::lxdebug->leave_sub();
256 sub generate_report {
257 $main::lxdebug->enter_sub();
259 $main::auth->assert('general_ledger');
261 my $form = $main::form;
262 my %myconfig = %main::myconfig;
263 my $locale = $main::locale;
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
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>
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
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
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};
283 report_generator_set_default_sort("$form->{datesort}", 1);
284 # report_generator_set_default_sort('transdate', 1);
286 GL->all_transactions(\%myconfig, \%$form);
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'),);
295 $form->{title} = $locale->text('Journal');
296 if ($form->{category} ne 'X') {
297 $form->{title} .= " : " . $locale->text($acctype{ $form->{category} });
300 $form->{landscape} = 1;
302 my $ml = ($form->{ml} =~ /(A|E|Q)/) ? -1 : 1;
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
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 ) {
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);
331 if ($form->{department}) {
332 my ($department) = split /--/, $form->{department};
333 push @options, $locale->text('Department') . " : $department";
337 my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
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' : '';
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'), },
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";
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};
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;
387 my $report = SL::ReportGenerator->new(\%myconfig, $form);
389 $report->set_columns(%column_defs);
390 $report->set_column_order(@columns);
392 $report->set_export_options('generate_report', @hidden_variables, qw(sort sortdir));
394 $report->set_sort_indicator($form->{sort} eq 'accno' ? 'debit_accno' : $form->{sort}, $form->{sortdir});
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),
401 $report->set_options_from_form();
402 $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
404 # add sort to callback
405 $form->{callback} = "$callback&sort=" . E($form->{sort}) . "&sortdir=" . E($form->{sortdir});
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;
413 foreach my $ref (@{ $form->{GL} }) {
417 foreach my $key (qw(debit credit debit_tax credit_tax)) {
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.*/) {
428 $form->{balance} = $form->{balance} + $value * $ml;
429 push @{ $rows{$key} }, $form->format_amount(\%myconfig, $value, 2);
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} }) ];
439 map { $row->{$_} = { 'data' => '', 'align' => $column_alignment{$_} } } @columns;
442 if ($form->{balance} < 0) {
445 } elsif ($form->{balance} > 0) {
449 my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
452 $row->{balance}->{data} = $data;
453 $row->{projectnumbers}->{data} = join ", ", sort { lc($a) cmp lc($b) } keys %{ $ref->{projectnumbers} };
455 map { $row->{$_}->{data} = $ref->{$_} } qw(id reference description notes gldate employee);
457 map { $row->{$_}->{data} = \@{ $rows{$_} }; } qw(transdate debit credit debit_accno credit_accno debit_tax_accno credit_tax_accno source);
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} } ];
463 map { $row->{$_}->{data} = \@{ $rows{$_} } if ($ref->{"${_}_accno"} ne "") } qw(debit_tax credit_tax);
465 $row->{reference}->{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'id=' . E($ref->{id}), 'callback');
467 my $row_set = [ $row ];
469 if ( ($form->{l_subtotal} eq 'Y' && !$form->{report_generator_csv_options_for_import} )
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');
475 $report->add_data($row_set);
480 # = 0 for balanced ledger
481 my $balanced_ledger = $totals{debit} + $totals{debit_tax} - $totals{credit} - $totals{credit_tax};
483 my $row = create_subtotal_row(\%totals, \@columns, \%column_alignment, [ qw(debit credit debit_tax credit_tax) ], 'listtotal');
486 if ($form->{balance} < 0) {
489 } elsif ($form->{balance} > 0) {
493 my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
496 $row->{balance}->{data} = $data;
498 if ( !$form->{report_generator_csv_options_for_import} ) {
499 $report->add_separator();
500 $report->add_data($row);
503 my $raw_bottom_info_text;
505 if (!$form->{accno} && (abs($balanced_ledger) > 0.001)) {
506 $raw_bottom_info_text .=
507 '<p><span class="unbalanced_ledger">'
508 . $locale->text('Unbalanced Ledger')
510 . $form->format_amount(\%myconfig, $balanced_ledger, 3)
514 $raw_bottom_info_text .= $form->parse_html_template('gl/generate_report_bottom');
516 $report->set_options('raw_bottom_info_text' => $raw_bottom_info_text);
518 $report->generate_with_headers();
520 $main::lxdebug->leave_sub();
524 $main::lxdebug->enter_sub();
526 $main::auth->assert('general_ledger');
528 my $form = $main::form;
529 my %myconfig = %main::myconfig;
531 $form->{oldtransdate} = $form->{transdate};
539 my ($debitcredit, $amount);
542 qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
544 for my $i (1 .. $form->{rowcount}) {
546 unless (($form->{"debit_$i"} eq "") && ($form->{"credit_$i"} eq "")) {
547 for (qw(debit credit tax)) {
549 $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
553 $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
560 if (($debitcount >= 2) && ($creditcount == 2)) {
561 $form->{"credit_$i"} = 0;
562 $form->{"tax_$i"} = 0;
564 $form->{creditlock} = 1;
566 if (($creditcount >= 2) && ($debitcount == 2)) {
567 $form->{"debit_$i"} = 0;
568 $form->{"tax_$i"} = 0;
570 $form->{debitlock} = 1;
572 if (($creditcount == 1) && ($debitcount == 2)) {
573 $form->{creditlock} = 1;
575 if (($creditcount == 2) && ($debitcount == 1)) {
576 $form->{debitlock} = 1;
578 if ($debitcredit && $credittax) {
579 $form->{"taxchart_$i"} = "0--0.00";
581 if (!$debitcredit && $debittax) {
582 $form->{"taxchart_$i"} = "0--0.00";
585 ($form->{"debit_$i"} == 0)
586 ? $form->{"credit_$i"}
587 : $form->{"debit_$i"};
589 if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
590 $form->{"taxchart_$i"} = "0--0.00";
591 $form->{"tax_$i"} = 0;
593 my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
600 if ($form->{taxincluded}) {
601 $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
603 $form->{"tax_$i"} = $amount * $rate;
606 $form->{"tax_$i"} = 0;
609 for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
614 for my $i (1 .. $count) {
616 for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
619 for my $i ($count + 1 .. $form->{rowcount}) {
620 for (@flds) { delete $form->{"${_}_$i"} }
623 $form->{rowcount} = $count + 1;
626 $main::lxdebug->leave_sub();
632 $main::lxdebug->enter_sub();
634 $main::auth->assert('general_ledger');
636 my $form = $main::form;
637 my %myconfig = %main::myconfig;
641 # for $i (1 .. $form->{rowcount}) {
642 # $form->{totaldebit} += $form->parse_amount(\%myconfig, $form->{"debit_$i"});
643 # $form->{totalcredit} += $form->parse_amount(\%myconfig, $form->{"credit_$i"});
647 &display_rows($init);
649 $main::lxdebug->leave_sub();
655 $main::lxdebug->enter_sub();
657 $main::auth->assert('general_ledger');
659 my $form = $main::form;
660 my %myconfig = %main::myconfig;
661 my $cgi = $::request->{cgi};
663 $form->{debit_1} = 0 if !$form->{"debit_1"};
664 $form->{totaldebit} = 0;
665 $form->{totalcredit} = 0;
667 my %project_labels = ();
668 my @project_values = ("");
669 foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
670 push(@project_values, $item->{"id"});
671 $project_labels{$item->{"id"}} = $item->{"projectnumber"};
674 my %chart_labels = ();
675 my @chart_values = ();
678 foreach my $item (@{ $form->{ALL_CHARTS} }) {
679 if ($item->{charttype} eq 'H'){ #falls überschrift
680 next; #überspringen (Bug 1150)
682 my $key = $item->{accno} . "--" . $item->{tax_id};
683 $taxchart_init = $item->{tax_id} unless (@chart_values);
684 push(@chart_values, $key);
685 $chart_labels{$key} = $item->{accno} . "--" . $item->{description};
686 $charts{$item->{accno}} = $item;
689 my %taxchart_labels = ();
690 my @taxchart_values = ();
692 foreach my $item (@{ $form->{ALL_TAXCHARTS} }) {
693 my $key = $item->{id} . "--" . $item->{rate};
694 $taxchart_init = $key if ($taxchart_init == $item->{id});
695 push(@taxchart_values, $key);
696 $taxchart_labels{$key} = $item->{taxdescription} . " " . $item->{rate} * 100 . ' %';
697 $taxcharts{$item->{id}} = $item;
700 my ($source, $memo, $source_hidden, $memo_hidden);
701 for my $i (1 .. $form->{rowcount}) {
702 if ($form->{show_details}) {
704 <td><input name="source_$i" value="$form->{"source_$i"}" size="16"></td>|;
706 <td><input name="memo_$i" value="$form->{"memo_$i"}" size="16"></td>|;
709 <input type="hidden" name="source_$i" value="$form->{"source_$i"}" size="16">|;
711 <input type="hidden" name="memo_$i" value="$form->{"memo_$i"}" size="16">|;
714 my $selected_accno_full;
715 my ($accno_row) = split(/--/, $form->{"accno_$i"});
716 my $item = $charts{$accno_row};
717 $selected_accno_full = "$item->{accno}--$item->{tax_id}";
719 my $selected_taxchart = $form->{"taxchart_$i"};
720 my ($selected_accno, $selected_tax_id) = split(/--/, $selected_accno_full);
721 my ($previous_accno, $previous_tax_id) = split(/--/, $form->{"previous_accno_$i"});
723 if ($previous_accno &&
724 ($previous_accno eq $selected_accno) &&
725 ($previous_tax_id ne $selected_tax_id)) {
726 my $item = $taxcharts{$selected_tax_id};
727 $selected_taxchart = "$item->{id}--$item->{rate}";
730 $selected_accno = '' if ($init);
731 $selected_taxchart ||= $taxchart_init;
733 my $accno = qq|<td>| .
734 NTI($cgi->popup_menu('-name' => "accno_$i",
736 '-onChange' => "setTaxkey($i)",
737 '-style' => 'width:200px',
738 '-values' => \@chart_values,
739 '-labels' => \%chart_labels,
740 '-default' => $selected_accno_full))
741 . $cgi->hidden('-name' => "previous_accno_$i",
742 '-default' => $selected_accno_full)
744 my $tax_ddbox = qq|<td>| .
745 NTI($cgi->popup_menu('-name' => "taxchart_$i",
746 '-id' => "taxchart_$i",
747 '-style' => 'width:200px',
748 '-values' => \@taxchart_values,
749 '-labels' => \%taxchart_labels,
750 '-default' => $selected_taxchart))
753 my ($fx_transaction, $checked);
755 if ($form->{transfer}) {
756 $fx_transaction = qq|
757 <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
762 if ($form->{"debit_$i"} != 0) {
763 $form->{totaldebit} += $form->{"debit_$i"};
764 if (!$form->{taxincluded}) {
765 $form->{totaldebit} += $form->{"tax_$i"};
768 $form->{totalcredit} += $form->{"credit_$i"};
769 if (!$form->{taxincluded}) {
770 $form->{totalcredit} += $form->{"tax_$i"};
774 for (qw(debit credit tax)) {
777 ? $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2)
781 if ($i < $form->{rowcount}) {
782 if ($form->{transfer}) {
783 $checked = ($form->{"fx_transaction_$i"}) ? "1" : "";
784 my $x = ($checked) ? "x" : "";
785 $fx_transaction = qq|
786 <td><input type=hidden name="fx_transaction_$i" value="$checked">$x</td>
789 $form->hide_form("accno_$i");
792 if ($form->{transfer}) {
793 $fx_transaction = qq|
794 <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
799 my $debitreadonly = "";
800 my $creditreadonly = "";
801 if ($i == $form->{rowcount}) {
802 if ($form->{debitlock}) {
803 $debitreadonly = "readonly";
804 } elsif ($form->{creditlock}) {
805 $creditreadonly = "readonly";
810 NTI($cgi->popup_menu('-name' => "project_id_$i",
811 '-values' => \@project_values,
812 '-labels' => \%project_labels,
813 '-default' => $form->{"project_id_$i"} ));
814 my $projectnumber_hidden = qq|
815 <input type="hidden" name="project_id_$i" value="$form->{"project_id_$i"}">|;
817 my $copy2credit = $i == 1 ? 'onkeyup="copy_debit_to_credit()"' : '';
819 print qq|<tr valign=top>
821 <td id="chart_balance_$i" align="right"> </td>
823 <td><input name="debit_$i" size="8" value="$form->{"debit_$i"}" accesskey=$i $copy2credit $debitreadonly></td>
824 <td><input name="credit_$i" size=8 value="$form->{"credit_$i"}" $creditreadonly></td>
825 <td><input type="hidden" name="tax_$i" value="$form->{"tax_$i"}">$form->{"tax_$i"}</td>
828 if ($form->{show_details}) {
832 <td>$projectnumber</td>
838 $projectnumber_hidden
846 $form->hide_form(qw(rowcount selectaccno));
848 $main::lxdebug->leave_sub();
853 $::lxdebug->enter_sub;
854 $::auth->assert('general_ledger');
858 my @old_project_ids = grep { $_ } map{ $::form->{"project_id_$_"} } 1..$::form->{rowcount};
860 $::form->get_lists("projects" => { "key" => "ALL_PROJECTS",
862 "old_id" => \@old_project_ids },
863 "charts" => { "key" => "ALL_CHARTS",
864 "transdate" => $::form->{transdate} },
865 "taxcharts" => "ALL_TAXCHARTS");
867 GL->get_chart_balances('charts' => $::form->{ALL_CHARTS});
869 my $title = $::form->{title};
870 $::form->{title} = $::locale->text("$title General Ledger Transaction");
871 # $locale->text('Add General Ledger Transaction')
872 # $locale->text('Edit General Ledger Transaction')
874 map { $::form->{$_} =~ s/\"/"/g }
877 $::form->{selectdepartment} =~ s/ selected//;
878 $::form->{selectdepartment} =~
879 s/option>\Q$::form->{department}\E/option selected>$::form->{department}/;
882 $::form->{fokus} = "gl.reference";
883 $::form->{taxincluded} = "1";
885 $::form->{fokus} = qq|gl.accno_$::form->{rowcount}|;
888 $::form->{previous_id} ||= "--";
889 $::form->{previous_gldate} ||= "--";
892 print $::form->parse_html_template('gl/form_header', {
893 hide_title => $title,
896 $::lxdebug->leave_sub;
901 $::lxdebug->enter_sub;
902 $::auth->assert('general_ledger');
904 my ($follow_ups, $follow_ups_due);
907 $follow_ups = FU->follow_ups('trans_id' => $::form->{id});
908 $follow_ups_due = sum map { $_->{due} * 1 } @{ $follow_ups || [] };
911 my $radieren = $::form->current_date(\%::myconfig) eq $::form->{gldate};
913 print $::form->parse_html_template('gl/form_footer', {
914 radieren => $radieren,
915 follow_ups => $follow_ups,
916 follow_ups_due => $follow_ups_due,
919 $::lxdebug->leave_sub;
923 $main::lxdebug->enter_sub();
925 my $form = $main::form;
926 my $locale = $main::locale;
933 <form method=post action=gl.pl>
936 map { $form->{$_} =~ s/\"/"/g } qw(reference description);
938 delete $form->{header};
940 foreach my $key (keys %$form) {
941 next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
942 print qq|<input type="hidden" name="$key" value="$form->{$key}">\n|;
946 <h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
949 . $locale->text('Are you sure you want to delete Transaction')
950 . qq| $form->{reference}</h4>
952 <input name=action class=submit type=submit value="|
953 . $locale->text('Yes') . qq|">
956 $main::lxdebug->leave_sub();
961 $main::lxdebug->enter_sub();
963 my $form = $main::form;
964 my %myconfig = %main::myconfig;
965 my $locale = $main::locale;
967 if (GL->delete_transaction(\%myconfig, \%$form)){
969 if(!exists $form->{addition} && $form->{id} ne "") {
970 $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
971 $form->{addition} = "DELETED";
974 # /saving the history
975 $form->redirect($locale->text('Transaction deleted!'))
977 $form->error($locale->text('Cannot delete transaction!'));
978 $main::lxdebug->leave_sub();
982 sub post_transaction {
983 $main::lxdebug->enter_sub();
985 my $form = $main::form;
986 my %myconfig = %main::myconfig;
987 my $locale = $main::locale;
989 # check if there is something in reference and date
990 $form->isblank("reference", $locale->text('Reference missing!'));
991 $form->isblank("transdate", $locale->text('Transaction Date missing!'));
992 $form->isblank("description", $locale->text('Description missing!'));
994 my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
995 my $closedto = $form->datetonum($form->{closedto}, \%myconfig);
1002 my $creditcount = 0;
1004 my %split_safety = ();
1006 my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
1008 for my $i (1 .. $form->{rowcount}) {
1009 next if $form->{"debit_$i"} eq "" && $form->{"credit_$i"} eq "";
1011 for (qw(debit credit tax)) {
1012 $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
1016 $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
1018 $split_safety{ $form->{"debit_$i"} <=> 0 }++;
1019 $split_safety{ - $form->{"credit_$i"} <=> 0 }++;
1027 if (($debitcount >= 2) && ($creditcount == 2)) {
1028 $form->{"credit_$i"} = 0;
1029 $form->{"tax_$i"} = 0;
1031 $form->{creditlock} = 1;
1033 if (($creditcount >= 2) && ($debitcount == 2)) {
1034 $form->{"debit_$i"} = 0;
1035 $form->{"tax_$i"} = 0;
1037 $form->{debitlock} = 1;
1039 if (($creditcount == 1) && ($debitcount == 2)) {
1040 $form->{creditlock} = 1;
1042 if (($creditcount == 2) && ($debitcount == 1)) {
1043 $form->{debitlock} = 1;
1045 if ($debitcredit && $credittax) {
1046 $form->{"taxchart_$i"} = "0--0.00";
1048 if (!$debitcredit && $debittax) {
1049 $form->{"taxchart_$i"} = "0--0.00";
1051 my $amount = ($form->{"debit_$i"} == 0)
1052 ? $form->{"credit_$i"}
1053 : $form->{"debit_$i"};
1055 if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
1056 $form->{"taxchart_$i"} = "0--0.00";
1057 $form->{"tax_$i"} = 0;
1059 my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
1066 if ($form->{taxincluded}) {
1067 $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
1069 $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"};
1071 $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"};
1074 $form->{"tax_$i"} = $amount * $rate;
1077 $form->{"tax_$i"} = 0;
1080 for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
1084 if ($split_safety{-1} > 1 && $split_safety{1} > 1) {
1085 $::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."));
1088 for my $i (1 .. $count) {
1090 for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
1093 for my $i ($count + 1 .. $form->{rowcount}) {
1094 for (@flds) { delete $form->{"${_}_$i"} }
1097 my ($debit, $credit, $taxtotal);
1098 for my $i (1 .. $form->{rowcount}) {
1099 my $dr = $form->{"debit_$i"};
1100 my $cr = $form->{"credit_$i"};
1101 my $tax = $form->{"tax_$i"};
1103 $form->error($locale->text('Cannot post transaction with a debit and credit entry for the same account!'));
1105 $debit += $dr + $tax if $dr;
1106 $credit += $cr + $tax if $cr;
1107 $taxtotal += $tax if $form->{taxincluded}
1110 $form->{taxincluded} = 0 if !$taxtotal;
1112 # this is just for the wise guys
1113 $form->error($locale->text('Cannot post transaction for a closed period!'))
1114 if ($form->date_closed($form->{"transdate"}, \%myconfig));
1115 if ($form->round_amount($debit, 2) != $form->round_amount($credit, 2)) {
1116 $form->error($locale->text('Out of balance transaction!'));
1119 if ($form->round_amount($debit, 2) + $form->round_amount($credit, 2) == 0) {
1120 $form->error($locale->text('Empty transaction!'));
1123 if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
1126 $err[1] = $locale->text('Cannot have a value in both Debit and Credit!');
1127 $err[2] = $locale->text('Debit and credit out of balance!');
1128 $err[3] = $locale->text('Cannot post a transaction without a value!');
1130 $form->error($err[$errno]);
1132 undef($form->{callback});
1133 # saving the history
1134 if(!exists $form->{addition} && $form->{id} ne "") {
1135 $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
1136 $form->{addition} = "SAVED";
1137 $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id};
1138 $form->save_history;
1140 # /saving the history
1142 $main::lxdebug->leave_sub();
1146 $main::lxdebug->enter_sub();
1148 $main::auth->assert('general_ledger');
1150 my $form = $main::form;
1151 my $locale = $main::locale;
1153 if ($::myconfig{mandatory_departments} && !$form->{department}) {
1154 $form->{saved_message} = $::locale->text('You have to specify a department.');
1159 $form->{title} = $locale->text("$form->{title} General Ledger Transaction");
1160 $form->{storno} = 0;
1164 remove_draft() if $form->{remove_draft};
1166 $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details");
1167 $form->redirect($form->{callback});
1169 $main::lxdebug->leave_sub();
1173 $main::lxdebug->enter_sub();
1175 $main::auth->assert('general_ledger');
1177 my $form = $main::form;
1181 $main::lxdebug->leave_sub();
1186 $main::lxdebug->enter_sub();
1188 $main::auth->assert('general_ledger');
1190 my $form = $main::form;
1191 my %myconfig = %main::myconfig;
1192 my $locale = $main::locale;
1194 # don't cancel cancelled transactions
1195 if (IS->has_storno(\%myconfig, $form, 'gl')) {
1196 $form->{title} = $locale->text("Cancel Accounts Receivables Transaction");
1197 $form->error($locale->text("Transaction has already been cancelled!"));
1200 GL->storno($form, \%myconfig, $form->{id});
1202 # saving the history
1203 if(!exists $form->{addition} && $form->{id} ne "") {
1204 $form->{snumbers} = "ordnumber_$form->{ordnumber}";
1205 $form->{addition} = "STORNO";
1206 $form->save_history;
1208 # /saving the history
1210 $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
1212 $main::lxdebug->leave_sub();
1216 call_sub($main::form->{nextsub});