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