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