Datentypen in der Hilfe und Beispieldatei in der richtigen Reihenfolge anzeigen.
[kivitendo-erp.git] / SL / RP.pm
1 #=====================================================================
2 # LX-Office ERP
3 # Copyright (C) 2004
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
6 #
7 #=====================================================================
8 # SQL-Ledger Accounting
9 # Copyright (C) 1998-2002
10 #
11 #  Author: Dieter Simader
12 #   Email: dsimader@sql-ledger.org
13 #     Web: http://www.sql-ledger.org
14 #
15 #  Contributors: Benjamin Lee <benjaminlee@consultant.com>
16 #
17 # This program is free software; you can redistribute it and/or modify
18 # it under the terms of the GNU General Public License as published by
19 # the Free Software Foundation; either version 2 of the License, or
20 # (at your option) any later version.
21 #
22 # This program is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 # GNU General Public License for more details.
26 # You should have received a copy of the GNU General Public License
27 # along with this program; if not, write to the Free Software
28 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #======================================================================
30 #
31 # backend code for reports
32 #
33 #======================================================================
34
35 package RP;
36
37 use SL::DBUtils;
38 use Data::Dumper;
39 use List::Util qw(sum);
40
41 # use warnings;
42 use strict;
43
44 # new implementation of balance sheet
45 # readme!
46 #
47 # stuff missing from the original implementation:
48 # - bold stuff
49 # - subdescription
50 # - proper testing for heading charts
51 # - transmission from $form to TMPL realm is not as clear as i'd like
52
53 sub get_openbalance_date {
54   my ($closedto, $target) = map { $::locale->parse_date_to_object(\%::myconfig, $_) } @_;
55
56   return unless $closedto;
57
58   $closedto->subtract(years => 1) while ($target - $closedto)->is_negative;
59   $closedto->add(days => 1);
60   return $::locale->format_date(\%::myconfig, $closedto);
61 }
62
63 sub balance_sheet {
64   $main::lxdebug->enter_sub();
65
66   my $myconfig = \%main::myconfig;
67   my $form     = $main::form;
68   my $dbh      = $::form->get_standard_dbh;
69
70   my $last_period = 0;
71   my @categories  = qw(A C L Q);
72
73   # if there are any dates construct a where
74   if ($form->{asofdate}) {
75     $form->{period} = $form->{this_period} = conv_dateq($form->{asofdate});
76   }
77
78   # get end of financial year and convert to Date format
79   my ($closedto) = selectfirst_array_query($form, $dbh, 'SELECT closedto FROM defaults');
80
81   # get date of last opening balance
82   my $startdate = get_openbalance_date($closedto, $form->{asofdate});
83
84   get_accounts($dbh, $last_period, $startdate, $form->{asofdate}, $form, \@categories);
85
86   # if there are any compare dates
87   if ($form->{compareasofdate}) {
88     $last_period = 1;
89
90     $startdate = get_openbalance_date($closedto, $form->{compareasofdate});
91
92     get_accounts($dbh, $last_period, $startdate, $form->{compareasofdate}, $form, \@categories);
93     $form->{last_period} = conv_dateq($form->{compareasofdate});
94   }
95
96   # now we got $form->{A}{accno}{ }    assets
97   # and $form->{L}{accno}{ }           liabilities
98   # and $form->{Q}{accno}{ }           equity
99   # build asset accounts
100
101   my %account = ('A' => { 'ml'     => -1 },
102                  'L' => { 'ml'     =>  1 },
103                  'Q' => { 'ml'     =>  1 });
104
105   my $TMPL_DATA = {};
106
107   foreach my $category (grep { !/C/ } @categories) {
108
109     $TMPL_DATA->{$category} = [];
110     my $ml  = $account{$category}{ml};
111
112     foreach my $key (sort keys %{ $form->{$category} }) {
113
114       my $row = { %{ $form->{$category}{$key} } };
115
116       # if charttype "heading" - calculate this entry, start a new batch of charts belonging to this heading and skip the rest bo the loop
117       # header charts are not real charts. start a sub aggregation with them, but don't calculate anything with them
118       if ($row->{charttype} eq "H") {
119         if ($account{$category}{subtotal} && $form->{l_subtotal}) {
120           $row->{subdescription} = $account{$category}{subdescription};
121           $row->{this}           = $account{$category}{subthis} * $ml;                   # format: $dec, $dash
122           $row->{last}           = $account{$category}{sublast} * $ml if $last_period;   # format: $dec, $dash
123         }
124
125         $row->{subheader} = 1;
126         $account{$category}{subthis}        = $row->{this};
127         $account{$category}{sublast}        = $row->{last};
128         $account{$category}{subdescription} = $row->{description};
129         $account{$category}{subtotal} = 1;
130
131         $row->{this} = 0;
132         $row->{last} = 0;
133
134         next unless $form->{l_heading};
135       }
136
137       for my $period (qw(this last)) {
138         next if ($period eq 'last' && !$last_period);
139         # only add assets
140         $row->{$period}                    *= $ml;
141       }
142
143       push @{ $TMPL_DATA->{$category} }, $row;
144     } # foreach
145
146     # resolve heading/subtotal
147     if ($account{$category}{subtotal} && $form->{l_subtotal}) {
148       $TMPL_DATA->{$category}[-1]{subdescription} = $account{$category}{subdescription};
149       $TMPL_DATA->{$category}[-1]{this}           = $account{$category}{subthis} * $ml;                   # format: $dec, $dash
150       $TMPL_DATA->{$category}[-1]{last}           = $account{$category}{sublast} * $ml if $last_period;   # format: $dec, $dash
151     }
152
153     $TMPL_DATA->{total}{$category}{this} = sum map { $_->{this} } @{ $TMPL_DATA->{$category} };
154     $TMPL_DATA->{total}{$category}{last} = sum map { $_->{last} } @{ $TMPL_DATA->{$category} };
155   }
156
157   for my $period (qw(this last)) {
158     next if ($period eq 'last' && !$last_period);
159
160     $form->{E}{$period}             = $TMPL_DATA->{total}{A}{$period} - $TMPL_DATA->{total}{L}{$period} - $TMPL_DATA->{total}{Q}{$period};
161     $TMPL_DATA->{total}{Q}{$period}     += $form->{E}{$period};
162     $TMPL_DATA->{total}{$period}    = $TMPL_DATA->{total}{L}{$period} + $TMPL_DATA->{total}{Q}{$period};
163   }
164     $form->{E}{description}='nicht verbuchter Gewinn/Verlust';
165   push @{ $TMPL_DATA->{Q} }, $form->{E};
166
167   $main::lxdebug->leave_sub();
168
169   return $TMPL_DATA;
170 }
171
172 sub get_accounts {
173   $main::lxdebug->enter_sub();
174
175   my ($dbh, $last_period, $fromdate, $todate, $form, $categories) = @_;
176
177   my ($null, $department_id) = split /--/, $form->{department};
178
179   my $query;
180   my $dpt_where = '';
181   my $dpt_where_without_arapgl = '';
182   my $project   = '';
183   my $where     = "1 = 1";
184   my $glwhere   = "";
185   my $subwhere  = "";
186   my $item;
187   my $sth;
188   my $dec = $form->{decimalplaces};
189
190   my $category = qq| AND (| . join(" OR ", map({ "(c.category = " . $dbh->quote($_) . ")" } @{$categories})) . qq|) |;
191
192   # get headings
193   $query =
194     qq|SELECT c.accno, c.description, c.category
195        FROM chart c
196        WHERE (c.charttype = 'H')
197          $category
198        ORDER by c.accno|;
199
200   $sth = prepare_execute_query($form, $dbh, $query);
201
202   my @headingaccounts = ();
203   while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
204     $form->{ $ref->{category} }{ $ref->{accno} }{description} =
205       "$ref->{description}";
206     $form->{ $ref->{category} }{ $ref->{accno} }{charttype} = "H";
207     $form->{ $ref->{category} }{ $ref->{accno} }{accno}     = $ref->{accno};
208
209     push @headingaccounts, $ref->{accno};
210   }
211
212   $sth->finish;
213
214   # filter for opening and closing bookings
215   # if l_ob is selected l_cb is always ignored
216   if ( $last_period ) {
217     # ob/cb-settings for "compared to" balance
218     if ( $form->{l_ob_compared} ) {
219       $where .= ' AND ac.ob_transaction is true  '
220     } elsif ( not $form->{l_cb_compared} ) {
221       $where .= ' AND ac.cb_transaction is false ';
222     };
223   } else {
224     # ob/cb-settings for "as of" balance
225     if ( $form->{l_ob} ) {
226       $where .= ' AND ac.ob_transaction is true  '
227     } elsif ( not $form->{l_cb} ) {
228       $where .= ' AND ac.cb_transaction is false ';
229     };
230   };
231
232
233   if ($fromdate) {
234     $fromdate = conv_dateq($fromdate);
235     if ($form->{method} eq 'cash') {
236       $subwhere .= " AND (transdate >= $fromdate)";
237       $glwhere = " AND (ac.transdate >= $fromdate)";
238     } else {
239       $where .= " AND (ac.transdate >= $fromdate)";
240     }
241   }
242
243   if ($todate) {
244     $todate = conv_dateq($todate);
245     $where    .= " AND (ac.transdate <= $todate)";
246     $subwhere .= " AND (transdate <= $todate)";
247   }
248
249   if ($department_id) {
250     $dpt_where = qq| AND (a.department_id = | . conv_i($department_id, 'NULL') . qq|)|;
251   }
252
253   if ($form->{project_id}) {
254     # Diese Bedingung wird derzeit niemals wahr sein, da man in Bericht->Bilanz keine
255     # Projekte auswählen kann
256     $project = qq| AND (ac.project_id = | . conv_i($form->{project_id}, 'NULL') . qq|) |;
257   }
258
259   if ($form->{method} eq 'cash') {
260     $query =
261       qq|SELECT c.accno, sum(ac.amount) AS amount, c.description, c.category
262          FROM acc_trans ac
263          JOIN chart c ON (c.id = ac.chart_id)
264          JOIN ar a ON (a.id = ac.trans_id)
265          WHERE $where
266            $dpt_where
267            $category
268            AND ac.trans_id IN
269              (
270                SELECT trans_id
271                FROM acc_trans a
272                WHERE (a.chart_link LIKE '%AR_paid%')
273                $subwhere
274              )
275            $project
276          GROUP BY c.accno, c.description, c.category
277
278          UNION ALL
279
280          SELECT c.accno, sum(ac.amount) AS amount, c.description, c.category
281          FROM acc_trans ac
282          JOIN chart c ON (c.id = ac.chart_id)
283          JOIN ap a ON (a.id = ac.trans_id)
284          WHERE $where
285            $dpt_where
286            $category
287            AND ac.trans_id IN
288              (
289                SELECT trans_id
290                FROM acc_trans a
291                WHERE (a.chart_link LIKE '%AP_paid%')
292                $subwhere
293              )
294            $project
295          GROUP BY c.accno, c.description, c.category
296
297          UNION ALL
298
299          SELECT c.accno, sum(ac.amount) AS amount, c.description, c.category
300          FROM acc_trans ac
301          JOIN chart c ON (c.id = ac.chart_id)
302          JOIN gl a ON (a.id = ac.trans_id)
303          WHERE $where
304            $glwhere
305            $dpt_where
306            $category
307              AND NOT ((ac.chart_link = 'AR') OR (ac.chart_link = 'AP'))
308            $project
309          GROUP BY c.accno, c.description, c.category |;
310
311     if ($form->{project_id}) {
312       # s.o. keine Projektauswahl in Bilanz
313       $query .=
314         qq|
315          UNION ALL
316
317          SELECT c.accno AS accno, SUM(ac.sellprice * ac.qty) AS amount, c.description AS description, c.category
318          FROM invoice ac
319          JOIN ar a ON (a.id = ac.trans_id)
320          JOIN parts p ON (ac.parts_id = p.id)
321          JOIN chart c on (p.income_accno_id = c.id)
322          -- use transdate from subwhere
323          WHERE (c.category = 'I')
324            $subwhere
325            $dpt_where
326            AND ac.trans_id IN
327              (
328                SELECT trans_id
329                FROM acc_trans a
330                WHERE (a.chart_link LIKE '%AR_paid%')
331                $subwhere
332              )
333            $project
334          GROUP BY c.accno, c.description, c.category
335
336          UNION ALL
337
338          SELECT c.accno AS accno, SUM(ac.sellprice) AS amount, c.description AS description, c.category
339          FROM invoice ac
340          JOIN ap a ON (a.id = ac.trans_id)
341          JOIN parts p ON (ac.parts_id = p.id)
342          JOIN chart c on (p.expense_accno_id = c.id)
343          WHERE (c.category = 'E')
344            $subwhere
345            $dpt_where
346            AND ac.trans_id IN
347              (
348                SELECT trans_id
349                FROM acc_trans a
350                WHERE a.chart_link LIKE '%AP_paid%'
351                $subwhere
352              )
353            $project
354          GROUP BY c.accno, c.description, c.category |;
355     }
356
357   } else {                      # if ($form->{method} eq 'cash')
358     if ($department_id) {
359       $dpt_where = qq| AND a.department_id = | . conv_i($department_id);
360       $dpt_where_without_arapgl = qq| AND COALESCE((SELECT department_id FROM ar WHERE ar.id=ac.trans_id),
361                                                    (SELECT department_id FROM gl WHERE gl.id=ac.trans_id),
362                                                    (SELECT department_id FROM ap WHERE ap.id=ac.trans_id)) = | . conv_i($department_id);
363     }
364
365     $query = qq|
366       SELECT c.accno, sum(ac.amount) AS amount, c.description, c.category
367       FROM acc_trans ac
368       JOIN chart c ON (c.id = ac.chart_id)
369       WHERE $where
370         $dpt_where_without_arapgl
371         $category
372         $project
373       GROUP BY c.accno, c.description, c.category |;
374
375     if ($form->{project_id}) {
376       # s.o. keine Projektauswahl in Bilanz
377       $query .= qq|
378       UNION ALL
379
380       SELECT c.accno AS accno, SUM(ac.sellprice * ac.qty) AS amount, c.description AS description, c.category
381       FROM invoice ac
382       JOIN ar a ON (a.id = ac.trans_id)
383       JOIN parts p ON (ac.parts_id = p.id)
384       JOIN chart c on (p.income_accno_id = c.id)
385       -- use transdate from subwhere
386       WHERE (c.category = 'I')
387         $subwhere
388         $dpt_where
389         $project
390       GROUP BY c.accno, c.description, c.category
391
392       UNION ALL
393
394       SELECT c.accno AS accno, SUM(ac.sellprice * ac.qty) * -1 AS amount, c.description AS description, c.category
395       FROM invoice ac
396       JOIN ap a ON (a.id = ac.trans_id)
397       JOIN parts p ON (ac.parts_id = p.id)
398       JOIN chart c on (p.expense_accno_id = c.id)
399       WHERE (c.category = 'E')
400         $subwhere
401         $dpt_where
402         $project
403       GROUP BY c.accno, c.description, c.category |;
404     }
405   }
406
407   my @accno;
408   my $accno;
409   my $ref;
410
411   $sth = prepare_execute_query($form, $dbh, $query);
412
413   while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
414
415     if ($ref->{category} eq 'C') {
416       $ref->{category} = 'A';
417     }
418
419     # get last heading account
420     @accno = grep { $_ le "$ref->{accno}" } @headingaccounts;
421     $accno = pop @accno;
422     if ($accno) {
423       if ($last_period) {
424         $form->{ $ref->{category} }{$accno}{last} += $ref->{amount};
425       } else {
426         $form->{ $ref->{category} }{$accno}{this} += $ref->{amount};
427       }
428     }
429
430     $form->{ $ref->{category} }{ $ref->{accno} }{accno}       = $ref->{accno};
431     $form->{ $ref->{category} }{ $ref->{accno} }{description} = $ref->{description};
432     $form->{ $ref->{category} }{ $ref->{accno} }{charttype} = "A";
433
434     if ($last_period) {
435       $form->{ $ref->{category} }{ $ref->{accno} }{last} += $ref->{amount};
436     } else {
437       $form->{ $ref->{category} }{ $ref->{accno} }{this} += $ref->{amount};
438     }
439   }
440   $sth->finish;
441
442   # remove accounts with zero balance
443   foreach $category (@{$categories}) {
444     foreach $accno (keys %{ $form->{$category} }) {
445       $form->{$category}{$accno}{last} = $form->round_amount($form->{$category}{$accno}{last}, $dec);
446       $form->{$category}{$accno}{this} = $form->round_amount($form->{$category}{$accno}{this}, $dec);
447
448       delete $form->{$category}{$accno}
449         if (   $form->{$category}{$accno}{this} == 0
450             && $form->{$category}{$accno}{last} == 0);
451     }
452   }
453
454   $main::lxdebug->leave_sub();
455 }
456
457 sub get_accounts_g {
458   $main::lxdebug->enter_sub();
459
460   my ($dbh, $last_period, $fromdate, $todate, $form, $category) = @_;
461
462   my ($null, $department_id) = split /--/, $form->{department};
463
464   my $query;
465   my $dpt_where;
466   my $dpt_where_without_arapgl;
467   my $project;
468   my $where    = "1 = 1";
469   my $glwhere  = "";
470   my $prwhere  = "";
471   my $subwhere = "";
472   my $inwhere = "";
473   my $item;
474
475   $where .= ' AND ac.cb_transaction is false ' unless $form->{l_cb};
476
477   if ($fromdate) {
478     $fromdate = conv_dateq($fromdate);
479     if ($form->{method} eq 'cash') {
480       $subwhere .= " AND (transdate    >= $fromdate)";
481       $glwhere   = " AND (ac.transdate >= $fromdate)";
482       $prwhere   = " AND (a.transdate  >= $fromdate)";
483       $inwhere   = " AND (acc.transdate >= $fromdate)";
484     } else {
485       $where    .= " AND (ac.transdate >= $fromdate)";
486     }
487   }
488
489   if ($todate) {
490     $todate = conv_dateq($todate);
491     $subwhere   .= " AND (transdate    <= $todate)";
492     $where      .= " AND (ac.transdate <= $todate)";
493     $prwhere    .= " AND (a.transdate  <= $todate)";
494     $inwhere    .= " AND (acc.transdate <= $todate)";
495   }
496
497   if ($department_id) {
498     $dpt_where = qq| AND (a.department_id = | . conv_i($department_id, 'NULL') . qq|) |;
499   }
500
501   if ($form->{project_id}) {
502     $project = qq| AND (ac.project_id = | . conv_i($form->{project_id}) . qq|) |;
503   }
504
505 #
506 # GUV patch by Ronny Rentner (Bug 1190)
507 #
508 # GUV IST-Versteuerung
509 #
510 # Alle tatsaechlichen _Zahlungseingaenge_
511 # im Zeitraum erfassen
512 # (Teilzahlungen werden prozentual auf verschiedene Steuern aufgeteilt)
513 #
514 #
515
516   if ($form->{method} eq 'cash') {
517     $query =
518       qq|
519        SELECT SUM( ac.amount * CASE WHEN COALESCE((SELECT amount FROM ar WHERE id = ac.trans_id), 0) != 0 THEN
520             /* ar amount is not zero, so we can divide by amount   */
521                     (SELECT SUM(acc.amount) * -1
522                      FROM acc_trans acc
523                      WHERE 1=1 $inwhere
524                      AND acc.trans_id = ac.trans_id
525                      AND acc.chart_link LIKE '%AR_paid%')
526                   / (SELECT amount FROM ar WHERE id = ac.trans_id)
527             ELSE 0
528             /* ar amount is zero, or we are checking with a non-ar-transaction, so we return 0 in both cases as multiplicator of ac.amount */
529             END
530                 ) AS amount, c.$category
531        FROM acc_trans ac
532        LEFT JOIN chart c ON (c.id  = ac.chart_id)
533        LEFT JOIN ar      ON (ar.id = ac.trans_id)
534       WHERE ac.trans_id IN (SELECT DISTINCT trans_id FROM acc_trans WHERE 1=1 $subwhere)
535
536       GROUP BY c.$category
537
538 /*
539        SELECT SUM(ac.amount * chart_category_to_sgn(c.category)) AS amount, c.$category
540          FROM acc_trans ac
541          JOIN chart c ON (c.id = ac.chart_id)
542          JOIN ar a ON (a.id = ac.trans_id)
543          WHERE $where $dpt_where
544            AND ac.trans_id IN ( SELECT trans_id FROM acc_trans a WHERE (a.chart_link LIKE '%AR_paid%') $subwhere)
545            $project
546          GROUP BY c.$category
547 */
548          UNION
549
550          SELECT SUM(ac.amount * chart_category_to_sgn(c.category)) AS amount, c.$category
551          FROM acc_trans ac
552          JOIN chart c ON (c.id = ac.chart_id)
553          JOIN ap a ON (a.id = ac.trans_id)
554          WHERE $where $dpt_where
555            AND ac.trans_id IN ( SELECT trans_id FROM acc_trans a WHERE (a.chart_link LIKE '%AP_paid%') $subwhere)
556            $project
557          GROUP BY c.$category
558
559          UNION
560
561          SELECT SUM(ac.amount * chart_category_to_sgn(c.category)) AS amount, c.$category
562          FROM acc_trans ac
563          JOIN chart c ON (c.id = ac.chart_id)
564          JOIN gl a ON (a.id = ac.trans_id)
565          WHERE $where $dpt_where $glwhere
566            AND NOT ((ac.chart_link = 'AR') OR (ac.chart_link = 'AP'))
567            $project
568          GROUP BY c.$category
569         |;
570
571     if ($form->{project_id}) {
572       $query .= qq|
573          UNION
574
575          SELECT SUM(ac.sellprice * ac.qty * chart_category_to_sgn(c.category)) AS amount, c.$category
576          FROM invoice ac
577          JOIN ar a ON (a.id = ac.trans_id)
578          JOIN parts p ON (ac.parts_id = p.id)
579          JOIN chart c on (p.income_accno_id = c.id)
580          WHERE (c.category = 'I') $prwhere $dpt_where
581            AND ac.trans_id IN ( SELECT trans_id FROM acc_trans a WHERE (a.chart_link LIKE '%AR_paid%') $subwhere)
582            $project
583          GROUP BY c.$category
584
585          UNION
586
587          SELECT SUM(ac.sellprice * chart_category_to_sgn(c.category)) AS amount, c.$category
588          FROM invoice ac
589          JOIN ap a ON (a.id = ac.trans_id)
590          JOIN parts p ON (ac.parts_id = p.id)
591          JOIN chart c on (p.expense_accno_id = c.id)
592          WHERE (c.category = 'E') $prwhere $dpt_where
593            AND ac.trans_id IN ( SELECT trans_id FROM acc_trans a WHERE (a.chart_link LIKE '%AP_paid%') $subwhere)
594          $project
595          GROUP BY c.$category
596          |;
597     }
598
599   } else {                      # if ($form->{method} eq 'cash')
600     if ($department_id) {
601       $dpt_where = qq| AND (a.department_id = | . conv_i($department_id, 'NULL') . qq|) |;
602       $dpt_where_without_arapgl = qq| AND COALESCE((SELECT department_id FROM ar WHERE ar.id=ac.trans_id),
603                                                    (SELECT department_id FROM gl WHERE gl.id=ac.trans_id),
604                                                    (SELECT department_id FROM ap WHERE ap.id=ac.trans_id)) = | . conv_i($department_id);
605     }
606
607     $query = qq|
608         SELECT sum(ac.amount * chart_category_to_sgn(c.category)) AS amount, c.$category
609         FROM acc_trans ac
610         JOIN chart c ON (c.id = ac.chart_id)
611         WHERE $where
612           $dpt_where_without_arapgl
613           $project
614         GROUP BY c.$category |;
615
616     if ($form->{project_id}) {
617       $query .= qq|
618         UNION
619
620         SELECT SUM(ac.sellprice * ac.qty * chart_category_to_sgn(c.category)) AS amount, c.$category
621         FROM invoice ac
622         JOIN ar a ON (a.id = ac.trans_id)
623         JOIN parts p ON (ac.parts_id = p.id)
624         JOIN chart c on (p.income_accno_id = c.id)
625         WHERE (c.category = 'I')
626           $prwhere
627           $dpt_where
628           $project
629         GROUP BY c.$category
630
631         UNION
632
633         SELECT SUM(ac.sellprice * ac.qty * chart_category_to_sgn(c.category)) AS amount, c.$category
634         FROM invoice ac
635         JOIN ap a ON (a.id = ac.trans_id)
636         JOIN parts p ON (ac.parts_id = p.id)
637         JOIN chart c on (p.expense_accno_id = c.id)
638         WHERE (c.category = 'E')
639           $prwhere
640           $dpt_where
641           $project
642         GROUP BY c.$category |;
643     }
644   }
645
646   my @accno;
647   my $accno;
648   my $ref;
649
650   foreach my $ref (selectall_hashref_query($form, $dbh, $query)) {
651     if ($category eq "pos_bwa") {
652       if ($last_period) {
653         $form->{ $ref->{$category} }{kumm} += $ref->{amount};
654       } else {
655         $form->{ $ref->{$category} }{jetzt} += $ref->{amount};
656       }
657     } else {
658       $form->{ $ref->{$category} } += $ref->{amount};
659     }
660   }
661
662   $main::lxdebug->leave_sub();
663 }
664
665 sub trial_balance {
666   $main::lxdebug->enter_sub();
667
668   my ($self, $myconfig, $form, %options) = @_;
669
670   my $dbh = $form->dbconnect($myconfig);
671
672   my ($query, $sth, $ref);
673   my %balance = ();
674   my %trb     = ();
675   my ($null, $department_id) = split /--/, $form->{department};
676   my @headingaccounts = ();
677   my $dpt_where;
678   my $dpt_where_without_arapgl;
679   my $project;
680
681   my $where    = "1 = 1";
682   my $invwhere = $where;
683
684   if ($department_id) {
685     $dpt_where = qq| AND (a.department_id = | . conv_i($department_id, 'NULL') . qq|) |;
686     $dpt_where_without_arapgl = qq| AND COALESCE((SELECT department_id FROM ar WHERE ar.id=ac.trans_id),
687                                                  (SELECT department_id FROM gl WHERE gl.id=ac.trans_id),
688                                                  (SELECT department_id FROM ap WHERE ap.id=ac.trans_id)) = | . conv_i($department_id);
689   }
690
691   # project_id only applies to getting transactions
692   # it has nothing to do with a trial balance
693   # but we use the same function to collect information
694
695   if ($form->{project_id}) {
696     $project = qq| AND (ac.project_id = | . conv_i($form->{project_id}, 'NULL') . qq|) |;
697   }
698
699   my $acc_cash_where = "";
700 #  my $ar_cash_where = "";
701 #  my $ap_cash_where = "";
702
703
704   if ($form->{method} eq "cash") {
705     $acc_cash_where =
706       qq| AND (ac.trans_id IN (
707             SELECT id
708             FROM ar
709             WHERE datepaid >= '$form->{fromdate}'
710               AND datepaid <= '$form->{todate}'
711
712             UNION
713
714             SELECT id
715             FROM ap
716             WHERE datepaid >= '$form->{fromdate}'
717               AND datepaid <= '$form->{todate}'
718
719             UNION
720
721             SELECT id
722             FROM gl
723             WHERE transdate >= '$form->{fromdate}'
724               AND transdate <= '$form->{todate}'
725           )) |;
726 #    $ar_ap_cash_where = qq| AND (a.datepaid>='$form->{fromdate}' AND a.datepaid<='$form->{todate}') |;
727   }
728
729   if ($options{beginning_balances}) {
730     foreach my $prefix (qw(from to)) {
731       next if ($form->{"${prefix}date"});
732
733       my $min_max = $prefix eq 'from' ? 'min' : 'max';
734       $query      = qq|SELECT ${min_max}(transdate)
735                        FROM acc_trans ac
736                        WHERE (1 = 1)
737                          $dpt_where_without_arapgl
738                          $project|;
739       ($form->{"${prefix}date"}) = selectfirst_array_query($form, $dbh, $query);
740     }
741
742     # get beginning balances
743     $query =
744       qq|SELECT c.accno, c.category, SUM(ac.amount) AS amount, c.description
745           FROM acc_trans ac
746           LEFT JOIN chart c ON (ac.chart_id = c.id)
747           WHERE ((select date_trunc('year', ac.transdate::date)) = (select date_trunc('year', ?::date))) AND ac.ob_transaction
748             $dpt_where_without_arapgl
749             $project
750           GROUP BY c.accno, c.category, c.description |;
751
752     $sth = prepare_execute_query($form, $dbh, $query, $form->{fromdate});
753
754     while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
755
756       if ($ref->{amount} != 0 || $form->{all_accounts}) {
757         $trb{ $ref->{accno} }{description} = $ref->{description};
758         $trb{ $ref->{accno} }{charttype}   = 'A';
759         $trb{ $ref->{accno} }{beginning_balance} = $ref->{amount};
760
761         if ($ref->{amount} > 0) {
762           $trb{ $ref->{accno} }{haben_eb}   = $ref->{amount};
763         } else {
764           $trb{ $ref->{accno} }{soll_eb}   = $ref->{amount} * -1;
765         }
766         $trb{ $ref->{accno} }{category}    = $ref->{category};
767       }
768
769     }
770     $sth->finish;
771   }
772
773   # get headings
774   $query =
775     qq|SELECT c.accno, c.description, c.category
776        FROM chart c
777        WHERE c.charttype = 'H'
778        ORDER by c.accno|;
779
780   $sth = prepare_execute_query($form, $dbh, $query);
781
782   while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
783     $trb{ $ref->{accno} }{description} = $ref->{description};
784     $trb{ $ref->{accno} }{charttype}   = 'H';
785     $trb{ $ref->{accno} }{category}    = $ref->{category};
786
787     push @headingaccounts, $ref->{accno};
788   }
789
790   $sth->finish;
791
792   $where = " 1 = 1 ";
793   my $saldowhere    = " 1 = 1 ";
794   my $sumwhere      = " 1 = 1 ";
795   my $subwhere      = '';
796   my $sumsubwhere   = '';
797   my $saldosubwhere = '';
798   my $glsaldowhere  = '';
799   my $glsubwhere    = '';
800   my $glwhere       = '';
801   my $glsumwhere    = '';
802   my $tofrom;
803   my ($fromdate, $todate);
804
805   if ($form->{fromdate} || $form->{todate}) {
806     if ($form->{fromdate}) {
807       $fromdate = conv_dateq($form->{fromdate});
808       $tofrom        .= " AND (ac.transdate >= $fromdate)";
809       $subwhere      .= " AND (ac.transdate >= $fromdate)";
810       $sumsubwhere   .= " AND (ac.transdate >= (select date_trunc('year', date $fromdate))) ";
811       $saldosubwhere .= " AND (ac,transdate>=(select date_trunc('year', date $fromdate)))  ";
812       $invwhere      .= " AND (a.transdate >= $fromdate)";
813       $glsaldowhere  .= " AND ac.transdate>=(select date_trunc('year', date $fromdate)) ";
814       $glwhere        = " AND (ac.transdate >= $fromdate)";
815       $glsumwhere     = " AND (ac.transdate >= (select date_trunc('year', date $fromdate))) ";
816     }
817     if ($form->{todate}) {
818       $todate = conv_dateq($form->{todate});
819       $tofrom        .= " AND (ac.transdate <= $todate)";
820       $invwhere      .= " AND (a.transdate <= $todate)";
821       $saldosubwhere .= " AND (ac.transdate <= $todate)";
822       $sumsubwhere   .= " AND (ac.transdate <= $todate)";
823       $subwhere      .= " AND (ac.transdate <= $todate)";
824       $glwhere       .= " AND (ac.transdate <= $todate)";
825       $glsumwhere    .= " AND (ac.transdate <= $todate) ";
826       $glsaldowhere  .= " AND (ac.transdate <= $todate) ";
827    }
828   }
829
830   if ($form->{method} eq "cash") {
831     $where .=
832       qq| AND(ac.trans_id IN (SELECT id FROM ar WHERE datepaid>= $fromdate AND datepaid<= $todate UNION SELECT id FROM ap WHERE datepaid>= $fromdate AND datepaid<= $todate UNION SELECT id FROM gl WHERE transdate>= $fromdate AND transdate<= $todate)) AND (NOT ac.ob_transaction OR ac.ob_transaction IS NULL) AND (NOT ac.cb_transaction OR ac.cb_transaction IS NULL) |;
833     $saldowhere .= qq| AND(ac.trans_id IN (SELECT id FROM ar WHERE datepaid>= $fromdate AND datepaid<= $todate UNION SELECT id FROM ap WHERE datepaid>= $fromdate AND datepaid<= $todate UNION SELECT id FROM gl WHERE transdate>= $fromdate AND transdate<= $todate))  AND (NOT ac.cb_transaction OR ac.cb_transaction IS NULL) |;
834
835     $sumwhere .= qq| AND(ac.trans_id IN (SELECT id FROM ar WHERE datepaid>= $fromdate AND datepaid<= $todate UNION SELECT id FROM ap WHERE datepaid>= $fromdate AND datepaid<= $todate UNION SELECT id FROM gl WHERE transdate>= $fromdate AND transdate<= $todate)) AND (NOT ac.ob_transaction OR ac.ob_transaction IS NULL) AND (NOT ac.cb_transaction OR ac.cb_transaction IS NULL) |;
836   } else {
837     $where .= $tofrom . " AND (NOT ac.ob_transaction OR ac.ob_transaction IS NULL) AND (NOT ac.cb_transaction OR ac.cb_transaction IS NULL)";
838     $saldowhere .= $glsaldowhere . " AND (NOT ac.cb_transaction OR ac.cb_transaction IS NULL)";
839     $sumwhere .= $glsumwhere . " AND (NOT ac.ob_transaction OR ac.ob_transaction IS NULL) AND (NOT ac.cb_transaction OR ac.cb_transaction IS NULL)";
840   }
841
842   $query = qq|
843        SELECT c.accno, c.description, c.category, SUM(ac.amount) AS amount
844        FROM acc_trans ac
845        JOIN chart c ON (c.id = ac.chart_id)
846        WHERE $where
847          $dpt_where_without_arapgl
848          $project
849        GROUP BY c.accno, c.description, c.category |;
850
851   if ($form->{project_id}) {
852     $query .= qq|
853       -- add project transactions from invoice
854
855       UNION ALL
856
857       SELECT c.accno, c.description, c.category, SUM(ac.sellprice * ac.qty) AS amount
858       FROM invoice ac
859       JOIN ar a ON (ac.trans_id = a.id)
860       JOIN parts p ON (ac.parts_id = p.id)
861       JOIN chart c ON (p.income_accno_id = c.id)
862       WHERE $invwhere
863         $dpt_where
864         $project
865       GROUP BY c.accno, c.description, c.category
866
867       UNION ALL
868
869       SELECT c.accno, c.description, c.category, SUM(ac.sellprice * ac.qty) * -1 AS amount
870       FROM invoice ac
871       JOIN ap a ON (ac.trans_id = a.id)
872       JOIN parts p ON (ac.parts_id = p.id)
873       JOIN chart c ON (p.expense_accno_id = c.id)
874       WHERE $invwhere
875         $dpt_where
876         $project
877       GROUP BY c.accno, c.description, c.category
878       |;
879     }
880
881   $query .= qq| ORDER BY accno|;
882
883   $sth = prepare_execute_query($form, $dbh, $query);
884
885   # calculate the debit and credit in the period
886   while ($ref = $sth->fetchrow_hashref("NAME_lc")) {
887     $trb{ $ref->{accno} }{description} = $ref->{description};
888     $trb{ $ref->{accno} }{charttype}   = 'A';
889     $trb{ $ref->{accno} }{category}    = $ref->{category};
890     $trb{ $ref->{accno} }{amount} += $ref->{amount};
891   }
892   $sth->finish;
893
894   # prepare query for each account
895   my ($q_drcr, $drcr, $q_project_drcr, $project_drcr);
896
897   $q_drcr =
898     qq|SELECT
899          (SELECT SUM(ac.amount) * -1
900           FROM acc_trans ac
901           JOIN chart c ON (c.id = ac.chart_id)
902           WHERE $where
903             $dpt_where_without_arapgl
904             $project
905           AND (ac.amount < 0)
906           AND (c.accno = ?)) AS debit,
907
908          (SELECT SUM(ac.amount)
909           FROM acc_trans ac
910           JOIN chart c ON (c.id = ac.chart_id)
911           WHERE $where
912             $dpt_where_without_arapgl
913             $project
914           AND ac.amount > 0
915           AND c.accno = ?) AS credit,
916         (SELECT SUM(ac.amount)
917          FROM acc_trans ac
918          JOIN chart c ON (ac.chart_id = c.id)
919          WHERE $saldowhere
920            $dpt_where_without_arapgl
921            $project
922          AND c.accno = ? AND (NOT ac.ob_transaction OR ac.ob_transaction IS NULL)) AS saldo,
923
924         (SELECT SUM(ac.amount)
925          FROM acc_trans ac
926          JOIN chart c ON (ac.chart_id = c.id)
927          WHERE $sumwhere
928            $dpt_where_without_arapgl
929            $project
930          AND amount > 0
931          AND c.accno = ?) AS sum_credit,
932
933         (SELECT SUM(ac.amount)
934          FROM acc_trans ac
935          JOIN chart c ON (ac.chart_id = c.id)
936          WHERE $sumwhere
937            $dpt_where_without_arapgl
938            $project
939          AND amount < 0
940          AND c.accno = ?) AS sum_debit,
941
942         (SELECT max(ac.transdate) FROM acc_trans ac
943         JOIN chart c ON (ac.chart_id = c.id)
944         WHERE $where
945           $dpt_where_without_arapgl
946           $project
947         AND c.accno = ?) AS last_transaction
948
949
950  |;
951
952   $drcr = prepare_query($form, $dbh, $q_drcr);
953
954   if ($form->{project_id}) {
955     # prepare query for each account
956     $q_project_drcr =
957       qq|SELECT
958           (SELECT SUM(ac.sellprice * ac.qty) * -1
959            FROM invoice ac
960            JOIN parts p ON (ac.parts_id = p.id)
961            JOIN ap a ON (ac.trans_id = a.id)
962            JOIN chart c ON (p.expense_accno_id = c.id)
963            WHERE $invwhere
964              $dpt_where
965              $project
966            AND c.accno = ?) AS debit,
967
968           (SELECT SUM(ac.sellprice * ac.qty)
969            FROM invoice ac
970            JOIN parts p ON (ac.parts_id = p.id)
971            JOIN ar a ON (ac.trans_id = a.id)
972            JOIN chart c ON (p.income_accno_id = c.id)
973            WHERE $invwhere
974              $dpt_where
975              $project
976            AND c.accno = ?) AS credit,
977
978         (SELECT SUM(ac.amount)
979          FROM acc_trans ac
980          JOIN chart c ON (ac.chart_id = c.id)
981          WHERE $saldowhere
982            $dpt_where_without_arapgl
983            $project
984          AND c.accno = ? AND (NOT ac.ob_transaction OR ac.ob_transaction IS NULL)) AS saldo,
985
986         (SELECT SUM(ac.amount)
987          FROM acc_trans ac
988          JOIN chart c ON (ac.chart_id = c.id)
989          WHERE $sumwhere
990            $dpt_where_without_arapgl
991            $project
992          AND amount > 0
993          AND c.accno = ?) AS sum_credit,
994
995         (SELECT SUM(ac.amount)
996          FROM acc_trans ac
997          JOIN chart c ON (ac.chart_id = c.id)
998          WHERE $sumwhere
999            $dpt_where_without_arapgl
1000            $project
1001          AND amount < 0
1002          AND c.accno = ?) AS sum_debit,
1003
1004
1005         (SELECT max(ac.transdate) FROM acc_trans ac
1006         JOIN chart c ON (ac.chart_id = c.id)
1007         WHERE $where
1008           $dpt_where_without_arapgl
1009           $project
1010         AND c.accno = ?) AS last_transaction
1011  |;
1012
1013     $project_drcr = prepare_query($form, $dbh, $q_project_drcr);
1014   }
1015
1016
1017   my ($debit, $credit, $saldo, $soll_saldo, $haben_saldo,$soll_kummuliert, $haben_kummuliert, $last_transaction);
1018
1019   foreach my $accno (sort keys %trb) {
1020     $ref = {};
1021
1022     $ref->{accno} = $accno;
1023     map { $ref->{$_} = $trb{$accno}{$_} }
1024       qw(description category charttype amount soll_eb haben_eb beginning_balance);
1025
1026     $ref->{balance} = $form->round_amount($balance{ $ref->{accno} }, 2);
1027
1028     if ($trb{$accno}{charttype} eq 'A') {
1029
1030       # get DR/CR
1031       do_statement($form, $drcr, $q_drcr, $ref->{accno}, $ref->{accno}, $ref->{accno}, $ref->{accno}, $ref->{accno}, $ref->{accno});
1032
1033       ($debit, $credit, $saldo, $haben_saldo, $soll_saldo) = (0, 0, 0, 0, 0);
1034       my ($soll_kumuliert, $haben_kumuliert) = (0, 0);
1035       $last_transaction = "";
1036       while (($debit, $credit, $saldo, $haben_kumuliert, $soll_kumuliert, $last_transaction) = $drcr->fetchrow_array) {
1037         $ref->{debit}  += $debit;
1038         $ref->{credit} += $credit;
1039         if ($saldo >= 0) {
1040           $ref->{haben_saldo} += $saldo;
1041         } else {
1042           $ref->{soll_saldo} += $saldo * -1;
1043         }
1044         $ref->{last_transaction} = $last_transaction;
1045         $ref->{soll_kumuliert} = $soll_kumuliert * -1;
1046         $ref->{haben_kumuliert} = $haben_kumuliert;
1047       }
1048       $drcr->finish;
1049
1050       if ($form->{project_id}) {
1051
1052         # get DR/CR
1053         do_statement($form, $project_drcr, $q_project_drcr, $ref->{accno}, $ref->{accno}, $ref->{accno}, $ref->{accno}, $ref->{accno}, $ref->{accno});
1054
1055         ($debit, $credit) = (0, 0);
1056         while (($debit, $credit, $saldo, $haben_kumuliert, $soll_kumuliert, $last_transaction) = $project_drcr->fetchrow_array) {
1057           $ref->{debit}  += $debit;
1058           $ref->{credit} += $credit;
1059           if ($saldo >= 0) {
1060             $ref->{haben_saldo} += $saldo;
1061           } else {
1062             $ref->{soll_saldo} += $saldo * -1;
1063           }
1064           $ref->{soll_kumuliert} += $soll_kumuliert * -1;
1065           $ref->{haben_kumuliert} += $haben_kumuliert;
1066         }
1067         $project_drcr->finish;
1068       }
1069
1070       $ref->{debit}  = $form->round_amount($ref->{debit},  2);
1071       $ref->{credit} = $form->round_amount($ref->{credit}, 2);
1072
1073       if ($ref->{haben_saldo} != 0) {
1074         $ref->{haben_saldo}  = $ref->{haben_saldo} + $ref->{beginning_balance};
1075         if ($ref->{haben_saldo} < 0) {
1076           $ref->{soll_saldo} = $form->round_amount(($ref->{haben_saldo} *- 1), 2);
1077           $ref->{haben_saldo} = 0;
1078         }
1079       } else {
1080         $ref->{soll_saldo} = $ref->{soll_saldo} - $ref->{beginning_balance};
1081         if ($ref->{soll_saldo} < 0) {
1082           $ref->{haben_saldo} = $form->round_amount(($ref->{soll_saldo} * -1), 2);
1083           $ref->{soll_saldo} = 0;
1084         }
1085      }
1086       $ref->{haben_saldo} = $form->round_amount($ref->{haben_saldo}, 2);
1087       $ref->{soll_saldo} = $form->round_amount($ref->{soll_saldo}, 2);
1088       $ref->{haben_kumuliert}  = $form->round_amount($ref->{haben_kumuliert},  2);
1089       $ref->{soll_kumuliert} = $form->round_amount($ref->{soll_kumuliert}, 2);
1090     }
1091
1092     # add subtotal
1093     my @accno;
1094     @accno = grep { $_ le "$ref->{accno}" } @headingaccounts;
1095     $accno = pop @accno;
1096     if ($accno) {
1097       $trb{$accno}{debit}  += $ref->{debit};
1098       $trb{$accno}{credit} += $ref->{credit};
1099       $trb{$accno}{soll_saldo}  += $ref->{soll_saldo};
1100       $trb{$accno}{haben_saldo} += $ref->{haben_saldo};
1101       $trb{$accno}{soll_kumuliert}  += $ref->{soll_kumuliert};
1102       $trb{$accno}{haben_kumuliert} += $ref->{haben_kumuliert};
1103     }
1104
1105     push @{ $form->{TB} }, $ref;
1106
1107   }
1108
1109   $dbh->disconnect;
1110
1111   # debits and credits for headings
1112   foreach my $accno (@headingaccounts) {
1113     foreach $ref (@{ $form->{TB} }) {
1114       if ($accno eq $ref->{accno}) {
1115         $ref->{debit}           = $trb{$accno}{debit};
1116         $ref->{credit}          = $trb{$accno}{credit};
1117         $ref->{soll_saldo}      = $trb{$accno}{soll_saldo};
1118         $ref->{haben_saldo}     = $trb{$accno}{haben_saldo};
1119         $ref->{soll_kumuliert}  = $trb{$accno}{soll_kumuliert};
1120         $ref->{haben_kumuliert} = $trb{$accno}{haben_kumuliert};
1121       }
1122     }
1123   }
1124
1125   $main::lxdebug->leave_sub();
1126 }
1127
1128 sub get_storno {
1129   $main::lxdebug->enter_sub();
1130   my ($self, $dbh, $form) = @_;
1131   my $arap = $form->{arap} eq "ar" ? "ar" : "ap";
1132   my $query = qq|SELECT invnumber FROM $arap WHERE invnumber LIKE "Storno zu "|;
1133   my $sth =  $dbh->prepare($query);
1134   while(my $ref = $sth->fetchrow_hashref()) {
1135     $ref->{invnumer} =~ s/Storno zu //g;
1136     $form->{storno}{$ref->{invnumber}} = 1;
1137   }
1138   $main::lxdebug->leave_sub();
1139 }
1140
1141 sub aging {
1142   $main::lxdebug->enter_sub();
1143
1144   my ($self, $myconfig, $form) = @_;
1145
1146   # connect to database
1147   my $dbh     = $form->dbconnect($myconfig);
1148
1149   my ($invoice, $arap, $buysell, $ct, $ct_id, $ml);
1150
1151   # falls customer ziehen wir die offene forderungsliste
1152   # anderfalls für die lieferanten die offenen verbindlichkeitne
1153   if ($form->{ct} eq "customer") {
1154     $invoice = "is";
1155     $arap = "ar";
1156     $buysell = "buy";
1157     $ct = "customer";
1158     $ml = -1;
1159   } else {
1160     $invoice = "ir";
1161     $arap = "ap";
1162     $buysell = "sell";
1163     $ct = "vendor";
1164     $ml = 1;
1165   }
1166   $ct_id = "${ct}_id";
1167
1168   # erweiterung um einen freien zeitraum oder einen stichtag
1169   # mit entsprechender altersstrukturliste (s.a. Bug 1842)
1170   # eine neue variable an der oberfläche eingeführt, somit ist
1171   # todate == freier zeitrau und fordate == stichtag
1172   # duedate_where == nur fällige rechnungen anzeigen
1173
1174   my ($review_of_aging_list, $todate, $fromdate, $fromwhere, $fordate,
1175       $duedate_where);
1176
1177   if ($form->{reporttype} eq 'custom') {  # altersstrukturliste, nur fällige
1178
1179     # explizit rausschmeissen was man für diesen bericht nicht braucht
1180     delete $form->{fromdate};
1181     delete $form->{todate};
1182
1183     # an der oberfläche ist das tagesaktuelle datum vorausgewählt
1184     # falls es dennoch per Benutzereingabe gelöscht wird, lieber wieder vorbelegen
1185     # ferner muss für die spätere DB-Abfrage muss todate gesetzt sein.
1186     $form->{fordate}  = $form->current_date($myconfig) unless ($form->{fordate});
1187     $fordate          = conv_dateq($form->{fordate});
1188     $todate           = $fordate;
1189
1190     if ($form->{review_of_aging_list}) { # falls die liste leer ist, alles anzeigen
1191       if ($form->{review_of_aging_list} =~ m "-") {             # ..  periode von bis
1192         my @period = split(/-/, $form->{review_of_aging_list}); # ... von periode bis periode
1193         $review_of_aging_list = " AND $period[0] <  (date $fordate) - duedate
1194                                   AND (date $fordate) - duedate  < $period[1]";
1195       } else {
1196         $form->{review_of_aging_list} =~ s/[^0-9]//g;   # größer 120 das substitute ist nur für das '>' zeichen
1197         $review_of_aging_list = " AND $form->{review_of_aging_list} < (date $fordate) - duedate";
1198       }
1199     }
1200     $duedate_where = " AND (date $fordate) - duedate >= 0 ";
1201   } else {  # freier zeitraum, nur rechnungsdatum und OHNE review_of_aging_list
1202     $form->{todate}  = $form->current_date($myconfig) unless ($form->{todate});
1203     $todate = conv_dateq($form->{todate});
1204     $fromdate = conv_dateq($form->{fromdate});
1205     $fromwhere = ($form->{fromdate} ne "") ? " AND (transdate >= (date $fromdate)) " : "";
1206   }
1207   my $where = " 1 = 1 ";
1208   my ($name, $null);
1209
1210   if ($form->{$ct_id}) {
1211     $where .= qq| AND (ct.id = | . conv_i($form->{$ct_id}) . qq|)|;
1212   } elsif ($form->{ $form->{ct} }) {
1213     $where .= qq| AND (ct.name ILIKE | . $dbh->quote('%' . $form->{$ct} . '%') . qq|)|;
1214   }
1215
1216   my $dpt_join;
1217   my $where_dpt;
1218   if ($form->{department}) {
1219     my ($null, $department_id) = split /--/, $form->{department};
1220     $dpt_join = qq| JOIN department d ON (a.department_id = d.id) |;
1221     $where .= qq| AND (a.department_id = | . conv_i($department_id, 'NULL') . qq|)|;
1222     $where_dpt = qq| AND (${arap}.department_id = | . conv_i($department_id, 'NULL') . qq|)|;
1223   }
1224  my $q_details = qq|
1225
1226     SELECT ${ct}.id AS ctid, ${ct}.name,
1227       street, zipcode, city, country, contact, email,
1228       phone as customerphone, fax as customerfax, ${ct}number,
1229       "invnumber", "transdate",
1230       (amount - COALESCE((SELECT sum(amount)*$ml FROM acc_trans WHERE chart_link ilike '%paid%' AND acc_trans.trans_id=${arap}.id AND acc_trans.transdate <= (date $todate)),0)) as "open", "amount",
1231       "duedate", invoice, ${arap}.id, date_part('days', now() - duedate) as overduedays,
1232       (SELECT $buysell
1233        FROM exchangerate
1234        WHERE (${arap}.currency_id = exchangerate.currency_id)
1235          AND (exchangerate.transdate = ${arap}.transdate)) AS exchangerate
1236     FROM ${arap}, ${ct}
1237     WHERE ((paid != amount) OR (datepaid > (date $todate) AND datepaid is not null))
1238       AND NOT COALESCE (${arap}.storno, 'f')
1239       AND (${arap}.${ct}_id = ${ct}.id)
1240       $where_dpt
1241       AND (${ct}.id = ?)
1242       AND (transdate <= (date $todate) $fromwhere )
1243       $review_of_aging_list
1244       $duedate_where
1245     ORDER BY ctid, transdate, invnumber |;
1246
1247   my $sth_details = prepare_query($form, $dbh, $q_details);
1248
1249   # select outstanding vendors or customers, depends on $ct
1250   my $query =
1251     qq|SELECT DISTINCT ct.id, ct.name
1252        FROM $ct ct, $arap a
1253        $dpt_join
1254        WHERE $where
1255          AND (a.${ct_id} = ct.id)
1256          AND ((a.paid != a.amount) OR ((a.datepaid > $todate) AND (datepaid is NOT NULL)))
1257          AND (a.transdate <= $todate $fromwhere)
1258        ORDER BY ct.name|;
1259
1260   my $sth = prepare_execute_query($form, $dbh, $query);
1261
1262   $form->{AG} = [];
1263   # for each company that has some stuff outstanding
1264   while (my ($id) = $sth->fetchrow_array) {
1265     do_statement($form, $sth_details, $q_details, $id);
1266
1267     while (my $ref = $sth_details->fetchrow_hashref("NAME_lc")) {
1268       $ref->{module} = ($ref->{invoice}) ? $invoice : $arap;
1269       $ref->{exchangerate} = 1 unless $ref->{exchangerate};
1270       push @{ $form->{AG} }, $ref;
1271     }
1272
1273     $sth_details->finish;
1274
1275   }
1276
1277   $sth->finish;
1278
1279   # disconnect
1280   $dbh->disconnect;
1281
1282   $main::lxdebug->leave_sub();
1283 }
1284
1285 sub get_customer {
1286   $main::lxdebug->enter_sub();
1287
1288   my ($self, $myconfig, $form) = @_;
1289
1290   # connect to database
1291   my $dbh = $form->dbconnect($myconfig);
1292
1293   my $ct = $form->{ct} eq "customer" ? "customer" : "vendor";
1294
1295   my $query =
1296     qq|SELECT ct.name, ct.email, ct.cc, ct.bcc
1297        FROM $ct ct
1298        WHERE ct.id = ?|;
1299   ($form->{ $form->{ct} }, $form->{email}, $form->{cc}, $form->{bcc}) =
1300     selectrow_query($form, $dbh, $query, $form->{"${ct}_id"});
1301   $dbh->disconnect;
1302
1303   $main::lxdebug->leave_sub();
1304 }
1305
1306 sub tax_report {
1307   $main::lxdebug->enter_sub();
1308
1309   my ($self, $myconfig, $form) = @_;
1310
1311   # connect to database
1312   my $dbh = $form->dbconnect($myconfig);
1313
1314   my ($null, $department_id) = split /--/, $form->{department};
1315
1316   # build WHERE
1317   my $where = "1 = 1";
1318
1319   if ($department_id) {
1320     $where .= qq| AND (a.department_id = | . conv_i($department_id, 'NULL') . qq|) |;
1321   }
1322
1323   my ($accno, $rate);
1324
1325   if ($form->{accno}) {
1326     $accno = $form->{accno};
1327     $rate  = $form->{"$form->{accno}_rate"};
1328     $accno = qq| AND (ch.accno = | . $dbh->quote($accno) . qq|)|;
1329   }
1330   $rate *= 1;
1331
1332   my ($table, $ARAP);
1333
1334   if ($form->{db} eq 'ar') {
1335     $table = "customer";
1336     $ARAP  = "AR";
1337   } else {
1338     $table = "vendor";
1339     $ARAP  = "AP";
1340   }
1341
1342   my $arap = lc($ARAP);
1343
1344   my $transdate = "a.transdate";
1345
1346   if ($form->{method} eq 'cash') {
1347     $transdate = "a.datepaid";
1348
1349     my $todate = conv_dateq($form->{todate} ? $form->{todate} : $form->current_date($myconfig));
1350
1351     $where .= qq|
1352       AND ac.trans_id IN
1353         (
1354           SELECT trans_id
1355           FROM acc_trans a
1356           WHERE (a.chart_link LIKE '%${ARAP}_paid%')
1357           AND (transdate <= $todate)
1358         )
1359       |;
1360   }
1361
1362   # if there are any dates construct a where
1363   $where .= " AND ($transdate >= " . conv_dateq($form->{fromdate}) . ") " if ($form->{fromdate});
1364   $where .= " AND ($transdate <= " . conv_dateq($form->{todate}) . ") " if ($form->{todate});
1365
1366   my $ml = ($form->{db} eq 'ar') ? 1 : -1;
1367
1368   my $sortorder = join ', ', $form->sort_columns(qw(transdate invnumber name));
1369   $sortorder = $form->{sort} if ($form->{sort} && grep({ $_ eq $form->{sort} } qw(id transdate invnumber name netamount tax)));
1370
1371   my $query =
1372       qq|SELECT a.id, '0' AS invoice, $transdate AS transdate, a.invnumber, n.name, a.netamount,
1373           ac.amount * $ml AS tax
1374          FROM acc_trans ac
1375          JOIN ${arap} a ON (a.id = ac.trans_id)
1376          JOIN chart ch ON (ch.id = ac.chart_id)
1377          JOIN $table n ON (n.id = a.${table}_id)
1378          WHERE
1379            $where
1380            $accno
1381            AND (a.invoice = '0')
1382
1383          UNION
1384
1385          SELECT a.id, '1' AS invoice, $transdate AS transdate, a.invnumber, n.name, i.sellprice * i.qty AS netamount,
1386            i.sellprice * i.qty * $rate * $ml AS tax
1387          FROM acc_trans ac
1388          JOIN ${arap} a ON (a.id = ac.trans_id)
1389          JOIN chart ch ON (ch.id = ac.chart_id)
1390          JOIN $table n ON (n.id = a.${table}_id)
1391          JOIN ${table}tax t ON (t.${table}_id = n.id)
1392          JOIN invoice i ON (i.trans_id = a.id)
1393          WHERE
1394            $where
1395            $accno
1396            AND (a.invoice = '1')
1397          ORDER BY $sortorder|;
1398
1399   $form->{TR} = selectall_hashref_query($form, $dbh, $query);
1400
1401   $dbh->disconnect;
1402
1403   $main::lxdebug->leave_sub();
1404 }
1405
1406 sub paymentaccounts {
1407   $main::lxdebug->enter_sub();
1408
1409   my ($self, $myconfig, $form) = @_;
1410
1411   # connect to database, turn AutoCommit off
1412   my $dbh = $form->dbconnect_noauto($myconfig);
1413
1414   my $ARAP = $form->{db} eq "ar" ? "AR" : "AP";
1415
1416   # get A(R|P)_paid accounts
1417   my $query =
1418     qq|SELECT accno, description
1419        FROM chart
1420        WHERE link LIKE '%${ARAP}_paid%'|;
1421   $form->{PR} = selectall_hashref_query($form, $dbh, $query);
1422
1423   $dbh->disconnect;
1424
1425   $main::lxdebug->leave_sub();
1426 }
1427
1428 sub payments {
1429   $main::lxdebug->enter_sub();
1430
1431   my ($self, $myconfig, $form) = @_;
1432
1433   # connect to database, turn AutoCommit off
1434   my $dbh = $form->dbconnect_noauto($myconfig);
1435
1436   my $ml = 1;
1437   my $arap;
1438   my $table;
1439   if ($form->{db} eq 'ar') {
1440     $table = 'customer';
1441     $ml = -1;
1442     $arap = 'ar';
1443   } else {
1444     $table = 'vendor';
1445     $arap = 'ap';
1446   }
1447
1448   my ($query, $sth);
1449   my $where;
1450
1451   if ($form->{department_id}) {
1452     $where = qq| AND (a.department_id = | . conv_i($form->{department_id}, 'NULL') . qq|) |;
1453   }
1454
1455   if ($form->{fromdate}) {
1456     $where .= " AND (ac.transdate >= " . $dbh->quote($form->{fromdate}) . ") ";
1457   }
1458   if ($form->{todate}) {
1459     $where .= " AND (ac.transdate <= " . $dbh->quote($form->{todate}) . ") ";
1460   }
1461   if (!$form->{fx_transaction}) {
1462     $where .= " AND ac.fx_transaction = '0'";
1463   }
1464
1465   my $invnumber;
1466   my $reference;
1467   if ($form->{reference}) {
1468     $reference = $dbh->quote('%' . $form->{reference} . '%');
1469     $invnumber = " AND (a.invnumber LIKE $reference)";
1470     $reference = " AND (a.reference LIKE $reference)";
1471   }
1472   if ($form->{source}) {
1473     $where .= " AND (ac.source ILIKE " . $dbh->quote('%' . $form->{source} . '%') . ") ";
1474   }
1475   if ($form->{memo}) {
1476     $where .= " AND (ac.memo ILIKE " . $dbh->quote('%' . $form->{memo} . '%') . ") ";
1477   }
1478
1479   my %sort_columns =  (
1480     'transdate'    => [ qw(transdate lower_invnumber lower_name) ],
1481     'invnumber'    => [ qw(lower_invnumber lower_name transdate) ],
1482     'name'         => [ qw(lower_name transdate)                 ],
1483     'source'       => [ qw(lower_source)                         ],
1484     'memo'         => [ qw(lower_memo)                           ],
1485     );
1486   my %lowered_columns =  (
1487     'invnumber'       => { 'gl' => 'a.reference',   'arap' => 'a.invnumber', },
1488     'memo'            => { 'gl' => 'ac.memo',       'arap' => 'ac.memo',     },
1489     'source'          => { 'gl' => 'ac.source',     'arap' => 'ac.source',   },
1490     'name'            => { 'gl' => 'a.description', 'arap' => 'c.name',      },
1491     );
1492
1493   my $sortdir   = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
1494   my $sortkey   = $sort_columns{$form->{sort}} ? $form->{sort} : 'transdate';
1495   my $sortorder = join ', ', map { "$_ $sortdir" } @{ $sort_columns{$sortkey} };
1496
1497
1498   my %columns_for_sorting = ( 'gl' => '', 'arap' => '', );
1499   foreach my $spec (@{ $sort_columns{$sortkey} }) {
1500     next if ($spec !~ m/^lower_(.*)$/);
1501
1502     my $column = $1;
1503     map { $columns_for_sorting{$_} .= sprintf(', lower(%s) AS lower_%s', $lowered_columns{$column}->{$_}, $column) } qw(gl arap);
1504   }
1505
1506   $query = qq|SELECT id, accno, description FROM chart WHERE accno = ?|;
1507   $sth = prepare_query($form, $dbh, $query);
1508
1509   my $q_details =
1510       qq|SELECT c.name, a.invnumber, a.ordnumber,
1511            ac.transdate, ac.amount * $ml AS paid, ac.source,
1512            a.invoice, a.id, ac.memo, '${arap}' AS module
1513            $columns_for_sorting{arap}
1514          FROM acc_trans ac
1515          JOIN $arap a ON (ac.trans_id = a.id)
1516          JOIN $table c ON (c.id = a.${table}_id)
1517          WHERE (ac.chart_id = ?)
1518            $where
1519            $invnumber
1520
1521          UNION
1522
1523          SELECT a.description, a.reference, NULL AS ordnumber,
1524            ac.transdate, ac.amount * $ml AS paid, ac.source,
1525            '0' as invoice, a.id, ac.memo, 'gl' AS module
1526            $columns_for_sorting{gl}
1527          FROM acc_trans ac
1528          JOIN gl a ON (a.id = ac.trans_id)
1529          WHERE (ac.chart_id = ?)
1530            $where
1531            $reference
1532            AND (ac.amount * $ml) > 0
1533
1534          ORDER BY $sortorder|;
1535   my $sth_details = prepare_query($form, $dbh, $q_details);
1536
1537   $form->{PR} = [];
1538
1539   # cycle through each id
1540   foreach my $accno (split(/ /, $form->{paymentaccounts})) {
1541     do_statement($form, $sth, $query, $accno);
1542     my $ref = $sth->fetchrow_hashref();
1543     push(@{ $form->{PR} }, $ref);
1544     $sth->finish();
1545
1546     $form->{ $ref->{id} } = [] unless ($form->{ $ref->{id} });
1547
1548     do_statement($form, $sth_details, $q_details, $ref->{id}, $ref->{id});
1549     while (my $pr = $sth_details->fetchrow_hashref()) {
1550       push(@{ $form->{ $ref->{id} } }, $pr);
1551     }
1552     $sth_details->finish();
1553   }
1554
1555   $dbh->disconnect;
1556
1557   $main::lxdebug->leave_sub();
1558 }
1559
1560 sub bwa {
1561   $main::lxdebug->enter_sub();
1562
1563   my ($self, $myconfig, $form) = @_;
1564
1565   # connect to database
1566   my $dbh = $form->dbconnect($myconfig);
1567
1568   my $last_period = 0;
1569   my $category;
1570   my @categories  =
1571     qw(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40);
1572
1573   $form->{decimalplaces} *= 1;
1574
1575   &get_accounts_g($dbh, $last_period, $form->{fromdate}, $form->{todate}, $form, "pos_bwa");
1576
1577   # if there are any compare dates
1578   my $year;
1579   if ($form->{fromdate} || $form->{todate}) {
1580     $last_period = 1;
1581     if ($form->{fromdate}) {
1582       $form->{fromdate} =~ /[0-9]*\.[0-9]*\.([0-9]*)/;
1583       $year = $1;
1584     } else {
1585       $form->{todate} =~ /[0-9]*\.[0-9]*\.([0-9]*)/;
1586       $year = $1;
1587     }
1588     my $kummfromdate = $form->{comparefromdate};
1589     my $kummtodate   = $form->{comparetodate};
1590     &get_accounts_g($dbh, $last_period, $kummfromdate, $kummtodate, $form, "pos_bwa");
1591   }
1592
1593   my @periods        = qw(jetzt kumm);
1594   my @gesamtleistung = qw(1 3);
1595   my @gesamtkosten   = qw (10 11 12 13 14 15 16 17 18 20);
1596   my @ergebnisse     =
1597     qw (rohertrag betriebrohertrag betriebsergebnis neutraleraufwand neutralerertrag ergebnisvorsteuern ergebnis gesamtleistung gesamtkosten);
1598
1599   foreach my $key (@periods) {
1600     $form->{ "$key" . "gesamtleistung" } = 0;
1601     $form->{ "$key" . "gesamtkosten" }   = 0;
1602
1603     foreach $category (@categories) {
1604
1605       if (defined($form->{$category}{$key})) {
1606         $form->{"$key$category"} =
1607           $form->format_amount($myconfig,
1608                                $form->round_amount($form->{$category}{$key}, 2
1609                                ),
1610                                $form->{decimalplaces},
1611                                '0');
1612       }
1613     }
1614     foreach my $item (@gesamtleistung) {
1615       $form->{ "$key" . "gesamtleistung" } += $form->{$item}{$key};
1616     }
1617     $form->{ "$key" . "gesamtleistung" } -= $form->{2}{$key};
1618
1619     foreach my $item (@gesamtkosten) {
1620       $form->{ "$key" . "gesamtkosten" } += $form->{$item}{$key};
1621     }
1622     $form->{ "$key" . "rohertrag" } =
1623       $form->{ "$key" . "gesamtleistung" } - $form->{4}{$key};
1624     $form->{ "$key" . "betriebrohertrag" } =
1625       $form->{ "$key" . "rohertrag" } + $form->{5}{$key};
1626     $form->{ "$key" . "betriebsergebnis" } =
1627       $form->{ "$key" . "betriebrohertrag" } -
1628       $form->{ "$key" . "gesamtkosten" };
1629     $form->{ "$key" . "neutraleraufwand" } =
1630       $form->{19}{$key} + $form->{30}{$key} + $form->{31}{$key};
1631     $form->{ "$key" . "neutralerertrag" } =
1632       $form->{32}{$key} + $form->{33}{$key} + $form->{34}{$key};
1633     $form->{ "$key" . "ergebnisvorsteuern" } =
1634       $form->{ "$key" . "betriebsergebnis" } -
1635       $form->{ "$key" . "neutraleraufwand" } +
1636       $form->{ "$key" . "neutralerertrag" };
1637     $form->{ "$key" . "ergebnis" } =
1638       $form->{ "$key" . "ergebnisvorsteuern" } - $form->{35}{$key};
1639
1640     if ($form->{ "$key" . "gesamtleistung" } > 0) {
1641       foreach $category (@categories) {
1642         if (defined($form->{$category}{$key})) {
1643           $form->{ "$key" . "gl" . "$category" } =
1644             $form->format_amount(
1645                                $myconfig,
1646                                $form->round_amount(
1647                                  ($form->{$category}{$key} /
1648                                     $form->{ "$key" . "gesamtleistung" } * 100
1649                                  ),
1650                                  $form->{decimalplaces}
1651                                ),
1652                                $form->{decimalplaces},
1653                                '0');
1654         }
1655       }
1656       foreach my $item (@ergebnisse) {
1657         $form->{ "$key" . "gl" . "$item" } =
1658           $form->format_amount($myconfig,
1659                                $form->round_amount(
1660                                  ( $form->{ "$key" . "$item" } /
1661                                      $form->{ "$key" . "gesamtleistung" } * 100
1662                                  ),
1663                                  $form->{decimalplaces}
1664                                ),
1665                                $form->{decimalplaces},
1666                                '0');
1667       }
1668     }
1669
1670     if ($form->{ "$key" . "gesamtkosten" } > 0) {
1671       foreach $category (@categories) {
1672         if (defined($form->{$category}{$key})) {
1673           $form->{ "$key" . "gk" . "$category" } =
1674             $form->format_amount($myconfig,
1675                                  $form->round_amount(
1676                                    ($form->{$category}{$key} /
1677                                       $form->{ "$key" . "gesamtkosten" } * 100
1678                                    ),
1679                                    $form->{decimalplaces}
1680                                  ),
1681                                  $form->{decimalplaces},
1682                                  '0');
1683         }
1684       }
1685       foreach my $item (@ergebnisse) {
1686         $form->{ "$key" . "gk" . "$item" } =
1687           $form->format_amount($myconfig,
1688                                $form->round_amount(
1689                                    ($form->{ "$key" . "$item" } /
1690                                       $form->{ "$key" . "gesamtkosten" } * 100
1691                                    ),
1692                                    $form->{decimalplaces}
1693                                ),
1694                                $form->{decimalplaces},
1695                                '0');
1696       }
1697     }
1698
1699     if ($form->{10}{$key} > 0) {
1700       foreach $category (@categories) {
1701         if (defined($form->{$category}{$key})) {
1702           $form->{ "$key" . "pk" . "$category" } =
1703             $form->format_amount(
1704                         $myconfig,
1705                         $form->round_amount(
1706                           ($form->{$category}{$key} / $form->{10}{$key} * 100),
1707                           $form->{decimalplaces}
1708                         ),
1709                         $form->{decimalplaces},
1710                         '0');
1711         }
1712       }
1713       foreach my $item (@ergebnisse) {
1714         $form->{ "$key" . "pk" . "$item" } =
1715           $form->format_amount($myconfig,
1716                                $form->round_amount(
1717                                                 ($form->{ "$key" . "$item" } /
1718                                                    $form->{10}{$key} * 100
1719                                                 ),
1720                                                 $form->{decimalplaces}
1721                                ),
1722                                $form->{decimalplaces},
1723                                '0');
1724       }
1725     }
1726
1727     if ($form->{4}{$key} > 0) {
1728       foreach $category (@categories) {
1729         if (defined($form->{$category}{$key})) {
1730           $form->{ "$key" . "auf" . "$category" } =
1731             $form->format_amount(
1732                          $myconfig,
1733                          $form->round_amount(
1734                            ($form->{$category}{$key} / $form->{4}{$key} * 100),
1735                            $form->{decimalplaces}
1736                          ),
1737                          $form->{decimalplaces},
1738                          '0');
1739         }
1740       }
1741       foreach my $item (@ergebnisse) {
1742         $form->{ "$key" . "auf" . "$item" } =
1743           $form->format_amount($myconfig,
1744                                $form->round_amount(
1745                                                 ($form->{ "$key" . "$item" } /
1746                                                    $form->{4}{$key} * 100
1747                                                 ),
1748                                                 $form->{decimalplaces}
1749                                ),
1750                                $form->{decimalplaces},
1751                                '0');
1752       }
1753     }
1754
1755     foreach my $item (@ergebnisse) {
1756       $form->{ "$key" . "$item" } =
1757         $form->format_amount($myconfig,
1758                              $form->round_amount($form->{ "$key" . "$item" },
1759                                                  $form->{decimalplaces}
1760                              ),
1761                              $form->{decimalplaces},
1762                              '0');
1763     }
1764
1765   }
1766   $dbh->disconnect;
1767
1768   $main::lxdebug->leave_sub();
1769 }
1770
1771 sub income_statement {
1772   $main::lxdebug->enter_sub();
1773
1774   my ($self, $myconfig, $form) = @_;
1775
1776   # connect to database
1777   my $dbh = $form->dbconnect($myconfig);
1778
1779   my $last_period          = 0;
1780   my @categories_einnahmen = qw(1 2 3 4 5 6 7);
1781   my @categories_ausgaben  =
1782     qw(8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31);
1783
1784   my @ergebnisse = qw(sumeura sumeurb guvsumme);
1785
1786   $form->{decimalplaces} *= 1;
1787
1788
1789
1790   &get_accounts_g($dbh, $last_period, $form->{fromdate}, $form->{todate},
1791                   $form, "pos_eur");
1792
1793
1794   foreach my $item (@categories_einnahmen) {
1795     $form->{"eur${item}"} =
1796       $form->format_amount($myconfig, $form->round_amount($form->{$item}, 2),2);
1797     $form->{"sumeura"} += $form->{$item};
1798   }
1799   foreach my $item (@categories_ausgaben) {
1800     $form->{"eur${item}"} =
1801       $form->format_amount($myconfig, $form->round_amount($form->{$item}, 2),2);
1802     $form->{"sumeurb"} += $form->{$item};
1803   }
1804
1805   $form->{"guvsumme"} = $form->{"sumeura"} - $form->{"sumeurb"};
1806
1807   foreach my $item (@ergebnisse) {
1808     $form->{$item} =
1809       $form->format_amount($myconfig, $form->round_amount($form->{$item}, 2),2);
1810   }
1811   $main::lxdebug->leave_sub();
1812 }
1813 1;