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')
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 $report->add_separator();
482 # = 0 for balanced ledger
483 my $balanced_ledger = $totals{debit} + $totals{debit_tax} - $totals{credit} - $totals{credit_tax};
485 my $row = create_subtotal_row(\%totals, \@columns, \%column_alignment, [ qw(debit credit debit_tax credit_tax) ], 'listtotal');
488 if ($form->{balance} < 0) {
491 } elsif ($form->{balance} > 0) {
495 my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
498 $row->{balance}->{data} = $data;
500 $report->add_data($row);
502 my $raw_bottom_info_text;
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')
509 . $form->format_amount(\%myconfig, $balanced_ledger, 3)
513 $raw_bottom_info_text .= $form->parse_html_template('gl/generate_report_bottom');
515 $report->set_options('raw_bottom_info_text' => $raw_bottom_info_text);
517 $report->generate_with_headers();
519 $main::lxdebug->leave_sub();
523 $main::lxdebug->enter_sub();
525 $main::auth->assert('general_ledger');
527 my $form = $main::form;
528 my %myconfig = %main::myconfig;
530 $form->{oldtransdate} = $form->{transdate};
538 my ($debitcredit, $amount);
541 qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
543 for my $i (1 .. $form->{rowcount}) {
545 unless (($form->{"debit_$i"} eq "") && ($form->{"credit_$i"} eq "")) {
546 for (qw(debit credit tax)) {
548 $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
552 $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
559 if (($debitcount >= 2) && ($creditcount == 2)) {
560 $form->{"credit_$i"} = 0;
561 $form->{"tax_$i"} = 0;
563 $form->{creditlock} = 1;
565 if (($creditcount >= 2) && ($debitcount == 2)) {
566 $form->{"debit_$i"} = 0;
567 $form->{"tax_$i"} = 0;
569 $form->{debitlock} = 1;
571 if (($creditcount == 1) && ($debitcount == 2)) {
572 $form->{creditlock} = 1;
574 if (($creditcount == 2) && ($debitcount == 1)) {
575 $form->{debitlock} = 1;
577 if ($debitcredit && $credittax) {
578 $form->{"taxchart_$i"} = "0--0.00";
580 if (!$debitcredit && $debittax) {
581 $form->{"taxchart_$i"} = "0--0.00";
584 ($form->{"debit_$i"} == 0)
585 ? $form->{"credit_$i"}
586 : $form->{"debit_$i"};
588 if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
589 $form->{"taxchart_$i"} = "0--0.00";
590 $form->{"tax_$i"} = 0;
592 my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
599 if ($form->{taxincluded}) {
600 $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
602 $form->{"tax_$i"} = $amount * $rate;
605 $form->{"tax_$i"} = 0;
608 for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
613 for my $i (1 .. $count) {
615 for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
618 for my $i ($count + 1 .. $form->{rowcount}) {
619 for (@flds) { delete $form->{"${_}_$i"} }
622 $form->{rowcount} = $count + 1;
625 $main::lxdebug->leave_sub();
631 $main::lxdebug->enter_sub();
633 $main::auth->assert('general_ledger');
635 my $form = $main::form;
636 my %myconfig = %main::myconfig;
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"});
646 &display_rows($init);
648 $main::lxdebug->leave_sub();
654 $main::lxdebug->enter_sub();
656 $main::auth->assert('general_ledger');
658 my $form = $main::form;
659 my %myconfig = %main::myconfig;
660 my $cgi = $::request->{cgi};
662 $form->{debit_1} = 0 if !$form->{"debit_1"};
663 $form->{totaldebit} = 0;
664 $form->{totalcredit} = 0;
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"};
673 my %chart_labels = ();
674 my @chart_values = ();
677 foreach my $item (@{ $form->{ALL_CHARTS} }) {
678 if ($item->{charttype} eq 'H'){ #falls überschrift
679 next; #überspringen (Bug 1150)
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;
688 my %taxchart_labels = ();
689 my @taxchart_values = ();
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;
699 my ($source, $memo, $source_hidden, $memo_hidden);
700 for my $i (1 .. $form->{rowcount}) {
701 if ($form->{show_details}) {
703 <td><input name="source_$i" value="$form->{"source_$i"}" size="16"></td>|;
705 <td><input name="memo_$i" value="$form->{"memo_$i"}" size="16"></td>|;
708 <input type="hidden" name="source_$i" value="$form->{"source_$i"}" size="16">|;
710 <input type="hidden" name="memo_$i" value="$form->{"memo_$i"}" size="16">|;
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}";
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"});
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}";
729 $selected_accno = '' if ($init);
730 $selected_taxchart ||= $taxchart_init;
732 my $accno = qq|<td>| .
733 NTI($cgi->popup_menu('-name' => "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)
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))
752 my ($fx_transaction, $checked);
754 if ($form->{transfer}) {
755 $fx_transaction = qq|
756 <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
761 if ($form->{"debit_$i"} != 0) {
762 $form->{totaldebit} += $form->{"debit_$i"};
763 if (!$form->{taxincluded}) {
764 $form->{totaldebit} += $form->{"tax_$i"};
767 $form->{totalcredit} += $form->{"credit_$i"};
768 if (!$form->{taxincluded}) {
769 $form->{totalcredit} += $form->{"tax_$i"};
773 for (qw(debit credit tax)) {
776 ? $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2)
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>
788 $form->hide_form("accno_$i");
791 if ($form->{transfer}) {
792 $fx_transaction = qq|
793 <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
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";
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"}">|;
816 my $copy2credit = $i == 1 ? 'onkeyup="copy_debit_to_credit()"' : '';
818 print qq|<tr valign=top>
820 <td id="chart_balance_$i" align="right"> </td>
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>
827 if ($form->{show_details}) {
831 <td>$projectnumber</td>
837 $projectnumber_hidden
845 $form->hide_form(qw(rowcount selectaccno));
847 $main::lxdebug->leave_sub();
852 $::lxdebug->enter_sub;
853 $::auth->assert('general_ledger');
857 my @old_project_ids = grep { $_ } map{ $::form->{"project_id_$_"} } 1..$::form->{rowcount};
859 $::form->get_lists("projects" => { "key" => "ALL_PROJECTS",
861 "old_id" => \@old_project_ids },
862 "charts" => { "key" => "ALL_CHARTS",
863 "transdate" => $::form->{transdate} },
864 "taxcharts" => "ALL_TAXCHARTS");
866 GL->get_chart_balances('charts' => $::form->{ALL_CHARTS});
868 my $title = $::form->{title};
869 $::form->{title} = $::locale->text("$title General Ledger Transaction");
870 # $locale->text('Add General Ledger Transaction')
871 # $locale->text('Edit General Ledger Transaction')
873 map { $::form->{$_} =~ s/\"/"/g }
876 $::form->{selectdepartment} =~ s/ selected//;
877 $::form->{selectdepartment} =~
878 s/option>\Q$::form->{department}\E/option selected>$::form->{department}/;
881 $::form->{fokus} = "gl.reference";
882 $::form->{taxincluded} = "1";
884 $::form->{fokus} = qq|gl.accno_$::form->{rowcount}|;
887 $::form->{previous_id} ||= "--";
888 $::form->{previous_gldate} ||= "--";
891 print $::form->parse_html_template('gl/form_header', {
892 hide_title => $title,
895 $::lxdebug->leave_sub;
900 $::lxdebug->enter_sub;
901 $::auth->assert('general_ledger');
903 my ($follow_ups, $follow_ups_due);
906 $follow_ups = FU->follow_ups('trans_id' => $::form->{id});
907 $follow_ups_due = sum map { $_->{due} * 1 } @{ $follow_ups || [] };
910 my $radieren = $::form->current_date(\%::myconfig) eq $::form->{gldate};
912 print $::form->parse_html_template('gl/form_footer', {
913 radieren => $radieren,
914 follow_ups => $follow_ups,
915 follow_ups_due => $follow_ups_due,
918 $::lxdebug->leave_sub;
922 $main::lxdebug->enter_sub();
924 my $form = $main::form;
925 my $locale = $main::locale;
932 <form method=post action=gl.pl>
935 map { $form->{$_} =~ s/\"/"/g } qw(reference description);
937 delete $form->{header};
939 foreach my $key (keys %$form) {
940 next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
941 print qq|<input type="hidden" name="$key" value="$form->{$key}">\n|;
945 <h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
948 . $locale->text('Are you sure you want to delete Transaction')
949 . qq| $form->{reference}</h4>
951 <input name=action class=submit type=submit value="|
952 . $locale->text('Yes') . qq|">
955 $main::lxdebug->leave_sub();
960 $main::lxdebug->enter_sub();
962 my $form = $main::form;
963 my %myconfig = %main::myconfig;
964 my $locale = $main::locale;
966 if (GL->delete_transaction(\%myconfig, \%$form)){
968 if(!exists $form->{addition} && $form->{id} ne "") {
969 $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
970 $form->{addition} = "DELETED";
973 # /saving the history
974 $form->redirect($locale->text('Transaction deleted!'))
976 $form->error($locale->text('Cannot delete transaction!'));
977 $main::lxdebug->leave_sub();
981 sub post_transaction {
982 $main::lxdebug->enter_sub();
984 my $form = $main::form;
985 my %myconfig = %main::myconfig;
986 my $locale = $main::locale;
988 # check if there is something in reference and date
989 $form->isblank("reference", $locale->text('Reference missing!'));
990 $form->isblank("transdate", $locale->text('Transaction Date missing!'));
991 $form->isblank("description", $locale->text('Description missing!'));
993 my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
994 my $closedto = $form->datetonum($form->{closedto}, \%myconfig);
1001 my $creditcount = 0;
1003 my %split_safety = ();
1005 my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
1007 for my $i (1 .. $form->{rowcount}) {
1008 next if $form->{"debit_$i"} eq "" && $form->{"credit_$i"} eq "";
1010 for (qw(debit credit tax)) {
1011 $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
1015 $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
1017 $split_safety{ $form->{"debit_$i"} <=> 0 }++;
1018 $split_safety{ - $form->{"credit_$i"} <=> 0 }++;
1026 if (($debitcount >= 2) && ($creditcount == 2)) {
1027 $form->{"credit_$i"} = 0;
1028 $form->{"tax_$i"} = 0;
1030 $form->{creditlock} = 1;
1032 if (($creditcount >= 2) && ($debitcount == 2)) {
1033 $form->{"debit_$i"} = 0;
1034 $form->{"tax_$i"} = 0;
1036 $form->{debitlock} = 1;
1038 if (($creditcount == 1) && ($debitcount == 2)) {
1039 $form->{creditlock} = 1;
1041 if (($creditcount == 2) && ($debitcount == 1)) {
1042 $form->{debitlock} = 1;
1044 if ($debitcredit && $credittax) {
1045 $form->{"taxchart_$i"} = "0--0.00";
1047 if (!$debitcredit && $debittax) {
1048 $form->{"taxchart_$i"} = "0--0.00";
1050 my $amount = ($form->{"debit_$i"} == 0)
1051 ? $form->{"credit_$i"}
1052 : $form->{"debit_$i"};
1054 if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
1055 $form->{"taxchart_$i"} = "0--0.00";
1056 $form->{"tax_$i"} = 0;
1058 my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
1065 if ($form->{taxincluded}) {
1066 $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
1068 $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"};
1070 $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"};
1073 $form->{"tax_$i"} = $amount * $rate;
1076 $form->{"tax_$i"} = 0;
1079 for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
1083 if ($split_safety{-1} > 1 && $split_safety{1} > 1) {
1084 $::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."));
1087 for my $i (1 .. $count) {
1089 for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
1092 for my $i ($count + 1 .. $form->{rowcount}) {
1093 for (@flds) { delete $form->{"${_}_$i"} }
1096 my ($debit, $credit, $taxtotal);
1097 for my $i (1 .. $form->{rowcount}) {
1098 my $dr = $form->{"debit_$i"};
1099 my $cr = $form->{"credit_$i"};
1100 my $tax = $form->{"tax_$i"};
1102 $form->error($locale->text('Cannot post transaction with a debit and credit entry for the same account!'));
1104 $debit += $dr + $tax if $dr;
1105 $credit += $cr + $tax if $cr;
1106 $taxtotal += $tax if $form->{taxincluded}
1109 $form->{taxincluded} = 0 if !$taxtotal;
1111 # this is just for the wise guys
1112 $form->error($locale->text('Cannot post transaction for a closed period!'))
1113 if ($form->date_closed($form->{"transdate"}, \%myconfig));
1114 if ($form->round_amount($debit, 2) != $form->round_amount($credit, 2)) {
1115 $form->error($locale->text('Out of balance transaction!'));
1118 if ($form->round_amount($debit, 2) + $form->round_amount($credit, 2) == 0) {
1119 $form->error($locale->text('Empty transaction!'));
1122 if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
1125 $err[1] = $locale->text('Cannot have a value in both Debit and Credit!');
1126 $err[2] = $locale->text('Debit and credit out of balance!');
1127 $err[3] = $locale->text('Cannot post a transaction without a value!');
1129 $form->error($err[$errno]);
1131 undef($form->{callback});
1132 # saving the history
1133 if(!exists $form->{addition} && $form->{id} ne "") {
1134 $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
1135 $form->{addition} = "SAVED";
1136 $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id};
1137 $form->save_history;
1139 # /saving the history
1141 $main::lxdebug->leave_sub();
1145 $main::lxdebug->enter_sub();
1147 $main::auth->assert('general_ledger');
1149 my $form = $main::form;
1150 my $locale = $main::locale;
1152 if ($::myconfig{mandatory_departments} && !$form->{department}) {
1153 $form->{saved_message} = $::locale->text('You have to specify a department.');
1158 $form->{title} = $locale->text("$form->{title} General Ledger Transaction");
1159 $form->{storno} = 0;
1163 remove_draft() if $form->{remove_draft};
1165 $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details");
1166 $form->redirect($form->{callback});
1168 $main::lxdebug->leave_sub();
1172 $main::lxdebug->enter_sub();
1174 $main::auth->assert('general_ledger');
1176 my $form = $main::form;
1180 $main::lxdebug->leave_sub();
1185 $main::lxdebug->enter_sub();
1187 $main::auth->assert('general_ledger');
1189 my $form = $main::form;
1190 my %myconfig = %main::myconfig;
1191 my $locale = $main::locale;
1193 # don't cancel cancelled transactions
1194 if (IS->has_storno(\%myconfig, $form, 'gl')) {
1195 $form->{title} = $locale->text("Cancel Accounts Receivables Transaction");
1196 $form->error($locale->text("Transaction has already been cancelled!"));
1199 GL->storno($form, \%myconfig, $form->{id});
1201 # saving the history
1202 if(!exists $form->{addition} && $form->{id} ne "") {
1203 $form->{snumbers} = "ordnumber_$form->{ordnumber}";
1204 $form->{addition} = "STORNO";
1205 $form->save_history;
1207 # /saving the history
1209 $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
1211 $main::lxdebug->leave_sub();
1215 call_sub($main::form->{nextsub});