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 },
220 employees => "ALL_EMPLOYEES",
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 $main::lxdebug->enter_sub();
902 $main::auth->assert('general_ledger');
904 my $form = $main::form;
905 my %myconfig = %main::myconfig;
906 my $locale = $main::locale;
907 my $cgi = $::request->{cgi};
909 my $follow_ups_block;
911 my $follow_ups = FU->follow_ups('trans_id' => $form->{id});
913 if (@{ $follow_ups} ) {
914 my $num_due = sum map { $_->{due} * 1 } @{ $follow_ups };
915 $follow_ups_block = qq|<p>| . $locale->text("There are #1 unfinished follow-ups of which #2 are due.", scalar @{ $follow_ups }, $num_due) . qq|</p>|;
919 my ($dec) = ($form->{totaldebit} =~ /\.(\d+)/);
921 my $decimalplaces = ($dec > 2) ? $dec : 2;
922 my $radieren = ($form->current_date(\%myconfig) eq $form->{gldate}) ? 1 : 0;
925 $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 2, " ")
926 } qw(totaldebit totalcredit);
930 <th colspan="3" align=right class=listtotal> $form->{totaldebit}</th>
931 <th align=right class=listtotal> $form->{totalcredit}</th>
939 <input name=callback type=hidden value="$form->{callback}">
946 my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
947 my $closedto = $form->datetonum($form->{closedto}, \%myconfig);
951 if (!$form->{storno}) {
952 print qq|<input class=submit type=submit name=action value="| . $locale->text('Storno') . qq|">|;
955 # Löschen und Ändern von Buchungen nicht mehr möglich (GoB) nur am selben Tag möglich
956 if (!$form->{locked} && $radieren) {
958 <input class=submit type=submit name=action value="| . $locale->text('Post') . qq|" accesskey="b">
959 <input class=submit type=submit name=action value="| . $locale->text('Delete') . qq|">|;
963 <input class=submit type=submit name=action id=update_button value="| . $locale->text('Update') . qq|">
964 <input type="button" class="submit" onclick="follow_up_window()" value="|
965 . $locale->text('Follow-Up')
969 if ($form->{draft_id}) {
970 my $remove_draft_checked = $form->{remove_draft} ? 'checked' : '';
972 . qq| <input name="remove_draft" id="remove_draft" type="checkbox" class="checkbox" ${remove_draft_checked}>|
973 . qq| <label for="remove_draft">| . $locale->text('Remove Draft') . qq|</label>\n|
978 <input class=submit type=submit name=action id=update_button value="| . $locale->text('Update') . qq|">
979 <input class=submit type=submit name=action value="| . $locale->text('Post') . qq|"> |
980 . NTI($cgi->submit('-name' => 'action', '-value' => $locale->text('Save draft'), '-class' => 'submit'))
981 . $cgi->hidden('-name' => 'draft_id', '-default' => [$form->{draft_id}])
982 . $cgi->hidden('-name' => 'draft_description', '-default' => [$form->{draft_description}]);
991 $main::lxdebug->leave_sub();
996 $main::lxdebug->enter_sub();
998 my $form = $main::form;
999 my $locale = $main::locale;
1006 <form method=post action=gl.pl>
1009 map { $form->{$_} =~ s/\"/"/g } qw(reference description);
1011 delete $form->{header};
1013 foreach my $key (keys %$form) {
1014 next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
1015 print qq|<input type="hidden" name="$key" value="$form->{$key}">\n|;
1019 <h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
1022 . $locale->text('Are you sure you want to delete Transaction')
1023 . qq| $form->{reference}</h4>
1025 <input name=action class=submit type=submit value="|
1026 . $locale->text('Yes') . qq|">
1029 $main::lxdebug->leave_sub();
1034 $main::lxdebug->enter_sub();
1036 my $form = $main::form;
1037 my %myconfig = %main::myconfig;
1038 my $locale = $main::locale;
1040 if (GL->delete_transaction(\%myconfig, \%$form)){
1041 # saving the history
1042 if(!exists $form->{addition} && $form->{id} ne "") {
1043 $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
1044 $form->{addition} = "DELETED";
1045 $form->save_history;
1047 # /saving the history
1048 $form->redirect($locale->text('Transaction deleted!'))
1050 $form->error($locale->text('Cannot delete transaction!'));
1051 $main::lxdebug->leave_sub();
1055 sub post_transaction {
1056 $main::lxdebug->enter_sub();
1058 my $form = $main::form;
1059 my %myconfig = %main::myconfig;
1060 my $locale = $main::locale;
1062 # check if there is something in reference and date
1063 $form->isblank("reference", $locale->text('Reference missing!'));
1064 $form->isblank("transdate", $locale->text('Transaction Date missing!'));
1065 $form->isblank("description", $locale->text('Description missing!'));
1067 my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
1068 my $closedto = $form->datetonum($form->{closedto}, \%myconfig);
1075 my $creditcount = 0;
1077 my %split_safety = ();
1079 my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
1081 for my $i (1 .. $form->{rowcount}) {
1082 next if $form->{"debit_$i"} eq "" && $form->{"credit_$i"} eq "";
1084 for (qw(debit credit tax)) {
1085 $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
1089 $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
1091 $split_safety{ $form->{"debit_$i"} <=> 0 }++;
1092 $split_safety{ - $form->{"credit_$i"} <=> 0 }++;
1100 if (($debitcount >= 2) && ($creditcount == 2)) {
1101 $form->{"credit_$i"} = 0;
1102 $form->{"tax_$i"} = 0;
1104 $form->{creditlock} = 1;
1106 if (($creditcount >= 2) && ($debitcount == 2)) {
1107 $form->{"debit_$i"} = 0;
1108 $form->{"tax_$i"} = 0;
1110 $form->{debitlock} = 1;
1112 if (($creditcount == 1) && ($debitcount == 2)) {
1113 $form->{creditlock} = 1;
1115 if (($creditcount == 2) && ($debitcount == 1)) {
1116 $form->{debitlock} = 1;
1118 if ($debitcredit && $credittax) {
1119 $form->{"taxchart_$i"} = "0--0.00";
1121 if (!$debitcredit && $debittax) {
1122 $form->{"taxchart_$i"} = "0--0.00";
1124 my $amount = ($form->{"debit_$i"} == 0)
1125 ? $form->{"credit_$i"}
1126 : $form->{"debit_$i"};
1128 if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
1129 $form->{"taxchart_$i"} = "0--0.00";
1130 $form->{"tax_$i"} = 0;
1132 my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
1139 if ($form->{taxincluded}) {
1140 $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
1142 $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"};
1144 $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"};
1147 $form->{"tax_$i"} = $amount * $rate;
1150 $form->{"tax_$i"} = 0;
1153 for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
1157 if ($split_safety{-1} > 1 && $split_safety{1} > 1) {
1158 $::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."));
1161 for my $i (1 .. $count) {
1163 for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
1166 for my $i ($count + 1 .. $form->{rowcount}) {
1167 for (@flds) { delete $form->{"${_}_$i"} }
1170 my ($debit, $credit, $taxtotal);
1171 for my $i (1 .. $form->{rowcount}) {
1172 my $dr = $form->{"debit_$i"};
1173 my $cr = $form->{"credit_$i"};
1174 my $tax = $form->{"tax_$i"};
1176 $form->error($locale->text('Cannot post transaction with a debit and credit entry for the same account!'));
1178 $debit += $dr + $tax if $dr;
1179 $credit += $cr + $tax if $cr;
1180 $taxtotal += $tax if $form->{taxincluded}
1183 $form->{taxincluded} = 0 if !$taxtotal;
1185 # this is just for the wise guys
1186 $form->error($locale->text('Cannot post transaction for a closed period!'))
1187 if ($form->date_closed($form->{"transdate"}, \%myconfig));
1188 if ($form->round_amount($debit, 2) != $form->round_amount($credit, 2)) {
1189 $form->error($locale->text('Out of balance transaction!'));
1192 if ($form->round_amount($debit, 2) + $form->round_amount($credit, 2) == 0) {
1193 $form->error($locale->text('Empty transaction!'));
1196 if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
1199 $err[1] = $locale->text('Cannot have a value in both Debit and Credit!');
1200 $err[2] = $locale->text('Debit and credit out of balance!');
1201 $err[3] = $locale->text('Cannot post a transaction without a value!');
1203 $form->error($err[$errno]);
1205 undef($form->{callback});
1206 # saving the history
1207 if(!exists $form->{addition} && $form->{id} ne "") {
1208 $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
1209 $form->{addition} = "SAVED";
1210 $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id};
1211 $form->save_history;
1213 # /saving the history
1215 $main::lxdebug->leave_sub();
1219 $main::lxdebug->enter_sub();
1221 $main::auth->assert('general_ledger');
1223 my $form = $main::form;
1224 my $locale = $main::locale;
1226 if ($::myconfig{mandatory_departments} && !$form->{department}) {
1227 $form->{saved_message} = $::locale->text('You have to specify a department.');
1232 $form->{title} = $locale->text("$form->{title} General Ledger Transaction");
1233 $form->{storno} = 0;
1237 remove_draft() if $form->{remove_draft};
1239 $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details");
1240 $form->redirect($form->{callback});
1242 $main::lxdebug->leave_sub();
1246 $main::lxdebug->enter_sub();
1248 $main::auth->assert('general_ledger');
1250 my $form = $main::form;
1254 $main::lxdebug->leave_sub();
1259 $main::lxdebug->enter_sub();
1261 $main::auth->assert('general_ledger');
1263 my $form = $main::form;
1264 my %myconfig = %main::myconfig;
1265 my $locale = $main::locale;
1267 # don't cancel cancelled transactions
1268 if (IS->has_storno(\%myconfig, $form, 'gl')) {
1269 $form->{title} = $locale->text("Cancel Accounts Receivables Transaction");
1270 $form->error($locale->text("Transaction has already been cancelled!"));
1273 GL->storno($form, \%myconfig, $form->{id});
1275 # saving the history
1276 if(!exists $form->{addition} && $form->{id} ne "") {
1277 $form->{snumbers} = "ordnumber_$form->{ordnumber}";
1278 $form->{addition} = "STORNO";
1279 $form->save_history;
1281 # /saving the history
1283 $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
1285 $main::lxdebug->leave_sub();
1289 call_sub($main::form->{nextsub});