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