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