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