2 Fehler im USTVA Modul beseitigt. Zwei Steuerkonten wurden nicht beruecksichtigt...
[kivitendo-erp.git] / SL / USTVA.pm
1 #=====================================================================
2 # Lx-Office ERP
3 # Copyright (c) 2004 by Udo Spallek, Aachen
4 #
5 #  Author: Udo Spallek
6 #   Email: udono@gmx.net
7 #     Web: http://www.lx-office.org
8 #
9 #
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #======================================================================
23 # Utilities for ustva
24 #=====================================================================
25
26 package USTVA;
27
28 sub create_steuernummer {
29   $main::lxdebug->enter_sub();
30
31   $part           = $form->{part};
32   $patterncount   = $form->{patterncount};
33   $delimiter      = $form->{delimiter};
34   $elster_pattern = $form->{elster_pattern};
35
36   # rebuild steuernummer and elstersteuernummer
37   # es gibt eine gespeicherte steuernummer $form->{steuernummer}
38   # und die parts und delimiter
39
40   my $h = 0;
41   my $i = 0;
42
43   $steuernummer_new       = $part;
44   $elstersteuernummer_new = $elster_FFFF;
45   $elstersteuernummer_new .= '0';
46
47   for ($h = 1; $h < $patterncount; $h++) {
48     $steuernummer_new .= qq|$delimiter|;
49     for ($i = 1; $i <= length($elster_pattern); $i++) {
50       $steuernummer_new       .= $form->{"part_$h\_$i"};
51       $elstersteuernummer_new .= $form->{"part_$h\_$i"};
52     }
53   }
54   if ($form->{steuernummer} ne $steuernummer_new) {
55     $form->{steuernummer}       = $steuernummer_new;
56     $form->{elstersteuernummer} = $elstersteuernummer_new;
57     $form->{steuernummer_new}   = $steuernummer_new;
58   }
59   $main::lxdebug->leave_sub();
60   return ($steuernummer_new, $elstersteuernummer_new);
61 }
62
63 sub steuernummer_input {
64   $main::lxdebug->enter_sub();
65
66   my ($self, $elsterland, $elsterFFFF, $steuernummer) = @_;
67
68   my $steuernummer_input = '';
69   
70   $elster_land  = $elsterland;
71   $elster_FFFF  = $elsterFFFF;
72   $steuernummer = '0000000000' if ($steuernummer eq '');
73
74   # $steuernummer formatieren (nur Zahlen) -> $stnr
75   my $stnr = $steuernummer;
76   $stnr =~ s/\D+//g;
77
78   #Pattern description Elstersteuernummer
79   my %elster_STNRformat = (
80       'Mecklenburg Vorpommern' => 'FFF/BBB/UUUUP',    # '/' 3
81       'Hessen'                 => '0FF BBB UUUUP',    # ' ' 3
82       'Nordrhein Westfalen'    => 'FFF/BBBB/UUUP',    # '/' 3
83       'Schleswig Holstein'     => 'FF BBB UUUUP',     # ' ' 2
84       'Berlin'                 => 'FF/BBB/UUUUP',     # '/' 3
85       'Thüringen'              => 'FFF/BBB/UUUUP',    # '/' 3
86       'Sachsen'                => 'FFF/BBB/UUUUP',    # '/' 3
87       'Hamburg'                => 'FF/BBB/UUUUP',     # '/' 3
88       'Baden Würtemberg'       => 'FF/BBB/UUUUP',     # '/' 2
89       'Sachsen Anhalt'         => 'FFF/BBB/UUUUP',    # '/' 3
90       'Saarland'               => 'FFF/BBB/UUUUP',    # '/' 3
91       'Bremen'                 => 'FF BBB UUUUP',     # ' ' 3
92       'Bayern'                 => 'FFF/BBB/UUUUP',    # '/' 3
93       'Rheinland Pfalz'        => 'FF/BBB/UUUU/P',    # '/' 4
94       'Niedersachsen'          => 'FF/BBB/UUUUP',     # '/' 3
95       'Brandenburg'            => 'FFF/BBB/UUUUP',    # '/' 3
96   );
97
98   #split the pattern
99   my $elster_pattern = $elster_STNRformat{$elster_land};
100   my @elster_pattern = split(' ', $elster_pattern);
101   my $delimiter      = '&nbsp;';
102   my $patterncount   = @elster_pattern;
103   if ($patterncount < 2) {
104     @elster_pattern = ();
105     @elster_pattern = split('/', $elster_pattern);
106     $delimiter      = '/';
107     $patterncount   = @elster_pattern;
108   }
109
110   # no we have an array of patternparts and a delimiter
111   # create the first automated and fixed part and delimiter
112
113   $steuernummer_input .= qq|<b><font size="+1">|;
114   my $part = '';
115 SWITCH: {
116     $elster_pattern[0] eq 'FFF' && do {
117       $part = substr($elster_FFFF, 1, 4);
118       $steuernummer_input .= qq|$part|;
119       last SWITCH;
120     };
121     $elster_pattern[0] eq '0FF' && do {
122       $part = '0' . substr($elster_FFFF, 2, 4);
123       $steuernummer_input .= qq|$part|;
124       last SWITCH;
125     };
126     $elster_pattern[0] eq 'FF' && do {
127       $part = substr($elster_FFFF, 2, 4);
128       $steuernummer_input .= qq|$part|;
129       last SWITCH;
130     };
131     1 == 1 && do {
132       $steuernummer_input .= qq|Fehler!|;
133       last SWITCH;
134     };
135   }
136
137   #now the rest of the Steuernummer ...
138   $steuernummer_input .= qq|</b></font>|;
139   $steuernummer_input .= qq|\n
140            <input type=hidden name="elster_pattern" value="$elster_pattern">
141            <input type=hidden name="patterncount" value="$patterncount">
142            <input type=hidden name="patternlength" value="$patterncount">
143            <input type=hidden name="delimiter" value="$delimiter">
144            <input type=hidden name="part" value="$part">
145   |;
146
147   my $k = 0;
148
149   for (my $h = 1; $h < $patterncount; $h++) {
150     $steuernummer_input .= qq|&nbsp;$delimiter&nbsp;\n|;
151     for (my $i = 1; $i <= length($elster_pattern[$h]); $i++) {
152       $steuernummer_input .= qq|<select name="part_$h\_$i">\n|;
153
154       for (my $j = 0; $j <= 9; $j++) {
155         $steuernummer_input .= qq|      <option value="$j"|;
156         if ($steuernummer ne '') {
157           if ($j eq substr($stnr, length($part) + $k, 1)) {
158             $steuernummer_input .= qq| selected|;
159           }
160         }
161         $steuernummer_input .= qq|>$j</option>\n|;
162       }
163       $k++;
164       $steuernummer_input .= qq|</select>\n|;
165     }
166   }
167   
168   $main::lxdebug->leave_sub();
169   
170   return $steuernummer_input;
171 }
172
173 sub fa_auswahl {
174   $main::lxdebug->enter_sub();
175
176 #  use SL::Form;
177
178   # Referenz wird übergeben, hash of hash wird nicht
179   # in neues  Hash kopiert, sondern direkt über die Referenz verändert
180   # Prototyp für diese Konstruktion
181
182   my ($self, $land, $elsterFFFF, $elster_init) = @_;
183   
184   my $terminal = '';
185   my $FFFF     = $elsterFFFF;
186   my $ffff     = '';
187   my $checked  = '';
188   $checked = 'checked' if ($elsterFFFF eq '' and $land eq '');
189
190   #if ($ENV{HTTP_USER_AGENT} =~ /(mozilla|opera|w3m)/i){
191   #$terminal='mozilla';
192   #} elsif ($ENV{HTTP_USER_AGENT} =~ /(links|lynx)/i){
193   #$terminal = 'lynx';
194   #}
195
196   #if ( $terminal eq 'mozilla' or $terminal eq 'js' ) {
197   my $fa_auswahl = qq|
198         <script language="Javascript">
199         function update_auswahl()
200         {
201                 var elsterBLAuswahl = document.verzeichnis.elsterland_new;
202                 var elsterFAAuswahl = document.verzeichnis.elsterFFFF_new;
203
204                 elsterFAAuswahl.options.length = 0; // dropdown aufräumen
205                 |;
206
207   foreach $elster_land (sort keys %$elster_init) {
208     $fa_auswahl .= qq|
209                if (elsterBLAuswahl.options[elsterBLAuswahl.selectedIndex].
210                value == "$elster_land")
211                {
212                |;
213     my $j              = 0;
214     my %elster_land_fa = ();
215     $FFFF = '';
216     for $FFFF (keys %{ $elster_init->{$elster_land} }) {
217       $elster_land_fa{$FFFF} = $elster_init->{$elster_land}->{$FFFF}->[0];
218     }
219     foreach $ffff (sort { $elster_land_fa{$a} cmp $elster_land_fa{$b} }
220                    keys(%elster_land_fa)
221       ) {
222       $fa_auswahl .= qq|
223                    elsterFAAuswahl.options[$j] = new Option("$elster_land_fa{$ffff} ($ffff)","$ffff");|;
224       $j++;
225     }
226     $fa_auswahl .= qq|
227                }|;
228   }
229   $fa_auswahl .= qq|
230         }
231         </script>
232
233         <table width="100%">
234           <tr>
235             <td>
236                Bundesland
237             </td>
238             <td>
239               <select size="1" name="elsterland_new" onchange="update_auswahl()">|;
240   if ($land eq '') {
241     $fa_auswahl .= qq|<option value="Auswahl" $checked>hier auswählen...</option>\n|;
242   }
243   foreach $elster_land (sort keys %$elster_init) {
244     $fa_auswahl .= qq|
245                   <option value="$elster_land"|;
246     if ($elster_land eq $land and $checked eq '') {
247       $fa_auswahl .= qq| selected|;
248     }
249     $fa_auswahl .= qq|>$elster_land</option>
250              |;
251   }
252   $fa_auswahl .= qq|
253             </td>
254           </tr>
255           |;
256
257   my $elster_land = '';
258   $elster_land = ($land ne '') ? $land : '';
259   %elster_land_fa = ();
260   for $FFFF (keys %{ $elster_init->{$elster_land} }) {
261     $elster_land_fa{$FFFF} = $elster_init->{$elster_land}->{$FFFF}->[0];
262   }
263
264   $fa_auswahl .= qq|
265            <tr>
266               <td>Finanzamt
267               </td>
268               <td>
269                  <select size="1" name="elsterFFFF_new">|;
270   if ($elsterFFFF eq '') {
271     $fa_auswahl .= qq|<option value="Auswahl" $checked>hier auswählen...</option>|;
272   } else {
273     foreach $ffff (sort { $elster_land_fa{$a} cmp $elster_land_fa{$b} }
274                    keys(%elster_land_fa)
275       ) {
276
277       $fa_auswahl .= qq|
278                         <option value="$ffff"|;
279       if ($ffff eq $elsterFFFF and $checked eq '') {
280         $fa_auswahl .= qq| selected|;
281       }
282       $fa_auswahl .= qq|>$elster_land_fa{$ffff} ($ffff)</option>|;
283     }
284   }
285   $fa_auswahl .= qq|
286                  </td>
287               </tr>
288             </table>
289             </select>|;
290
291   $main::lxdebug->leave_sub();
292   return $fa_auswahl;
293 }
294
295 sub info {
296   $main::lxdebug->enter_sub();
297
298   my $msg = $_[0];
299
300   if ($ENV{HTTP_USER_AGENT}) {
301     $msg =~ s/\n/<br>/g;
302
303     print qq|<body><h2 class=info>Hinweis</h2>
304
305     <p><b>$msg</b>
306     <br>
307     <br>
308     <hr>
309     <input type=button value="zurück" onClick="history.go(-1)">
310     </body>
311     |;
312
313     exit;
314
315   } else {
316
317     if ($form->{error_function}) {
318       &{ $form->{error_function} }($msg);
319     } else {
320       die "Hinweis: $msg\n";
321     }
322   }
323
324   $main::lxdebug->leave_sub();
325 }
326
327 sub stichtag {
328   $main::lxdebug->enter_sub();
329
330   # noch nicht fertig
331   # soll mal eine Erinnerungsfunktion für USTVA Abgaben werden, die automatisch
332   # den Termin der nächsten USTVA anzeigt.
333   #
334   #
335   my ($today, $FA_dauerfrist, $FA_voranmeld) = @_;
336
337   #$today zerlegen:
338
339   #$today =today * 1;
340   $today =~ /(\d\d\d\d)(\d\d)(\d\d)/;
341   $year     = $1;
342   $month    = $2;
343   $day      = $3;
344   $yy       = $year;
345   $mm       = $month;
346   $yymmdd   = "$year$month$day" * 1;
347   $mmdd     = "$month$day" * 1;
348   $stichtag = '';
349
350   #$tage_bis = '1234';
351   #$ical = '...vcal format';
352
353   #if ($FA_voranmeld eq 'month'){
354
355   %liste = ("0110" => 'December',
356             "0210" => 'January',
357             "0310" => 'February',
358             "0410" => 'March',
359             "0510" => 'April',
360             "0610" => 'May',
361             "0710" => 'June',
362             "0810" => 'July',
363             "0910" => 'August',
364             "1010" => 'September',
365             "1110" => 'October',
366             "1210" => 'November');
367
368   #$mm += $dauerfrist
369   #$month *= 1;
370   $month += 1 if ($day > 10);
371   $month    = sprintf("%02d", $month);
372   $stichtag = $year . $month . "10";
373   $ust_va   = $month . "10";
374
375   foreach $date (%liste) {
376     $ust_va = $liste{$date} if ($date eq $stichtag);
377   }
378
379   #} elsif ($FA_voranmeld eq 'quarter'){
380   #1;
381
382   #}
383
384   #@stichtag = ('10.04.2004', '10.05.2004');
385
386   #@liste = ['0110', '0210', '0310', '0410', '0510', '0610', '0710', '0810', '0910',
387   #          '1010', '1110', '1210', ];
388   #
389   #foreach $key (@liste){
390   #  #if ($ddmm < ('0110' * 1));
391   #  if ($ddmm ){}
392   #  $stichtag = $liste[$key - 1] if ($ddmm > $key);
393   #
394   #}
395   #
396   #$stichtag =~ /([\d]\d)(\d\d)$/
397   #$stichtag = "$1.$2.$yy"
398   #$stichtag=$1;
399   $main::lxdebug->leave_sub();
400   return ($stichtag, $description, $tage_bis, $ical);
401 }
402
403 sub query_finanzamt {
404   $main::lxdebug->enter_sub();
405
406   my ($self, $myconfig, $form) = @_;
407
408   my $dbh = $form->dbconnect($myconfig) or $self->error(DBI->errstr);
409
410   #Test, if table finanzamt exist
411   my $table    = 'finanzamt';
412   my $filename = "sql/$table.sql";
413
414   my $tst = $dbh->prepare("SELECT * FROM $table");
415   $tst->execute;
416   if ($DBI::err) {
417
418     #There is no table, read the table from sql/finanzamt.sql
419     print qq|<p>Bitte warten, Tabelle $table wird einmalig in Datenbank:
420     $myconfig->{dbname} als Benutzer: $myconfig->{dbuser} hinzugefügt...</p>|;
421     process_query($form, $dbh, $filename) || $self->error(DBI->errstr);
422
423     #execute second last call
424     my $dbh = $form->dbconnect($myconfig) or $self->error(DBI->errstr);
425     $dbh->disconnect();
426   }
427   $tst->finish();
428
429   #$dbh->disconnect();
430
431   my @vars = (
432     'FA_Land_Nr',             #  0
433     'FA_BUFA_Nr',             #  1
434                               #'FA_Verteiler',                          #  2
435     'FA_Name',                #  3
436     'FA_Strasse',             #  4
437     'FA_PLZ',                 #  5
438     'FA_Ort',                 #  6
439     'FA_Telefon',             #  7
440     'FA_Fax',                 #  8
441     'FA_PLZ_Grosskunden',     #  9
442     'FA_PLZ_Postfach',        # 10
443     'FA_Postfach',            # 11
444     'FA_BLZ_1',               # 12
445     'FA_Kontonummer_1',       # 13
446     'FA_Bankbezeichnung_1',   # 14
447                               #'FA_BankIBAN_1',                         # 15
448                               #'FA_BankBIC_1',                          # 16
449                               #'FA_BankInhaber_BUFA_Nr_1',                      # 17
450     'FA_BLZ_2',               # 18
451     'FA_Kontonummer_2',       # 19
452     'FA_Bankbezeichnung_2',   # 20
453                               #'FA_BankIBAN_2',                         # 21
454                               #'FA_BankBIC_2',                          # 22
455                               #'FA_BankInhaber_BUFA_Nr_2',                      # 23
456     'FA_Oeffnungszeiten',     # 24
457     'FA_Email',               # 25
458     'FA_Internet'             # 26
459                               #'FA_zustaendige_Hauptstelle_BUFA_Nr',            # 27
460                               #'FA_zustaendige_vorgesetzte_Finanzbehoerde'      # 28
461   );
462
463   my $field = join(', ', @vars);
464
465   my $query = "SELECT $field FROM finanzamt ORDER BY FA_Land_nr";
466   my $sth = $dbh->prepare($query) or $self->error($dbh->errstr);
467   $sth->execute || $form->dberror($query);
468   my $array_ref = $sth->fetchall_arrayref();
469   my $land      = '';
470   foreach my $row (@$array_ref) {
471     my $FA_finanzamt = $row;
472     $land = 'Schleswig Holstein'     if (@$FA_finanzamt[0] eq '1');
473     $land = 'Hamburg'                if (@$FA_finanzamt[0] eq '2');
474     $land = 'Niedersachsen'          if (@$FA_finanzamt[0] eq '3');
475     $land = 'Bremen'                 if (@$FA_finanzamt[0] eq '4');
476     $land = 'Nordrhein Westfalen'    if (@$FA_finanzamt[0] eq '5');
477     $land = 'Hessen'                 if (@$FA_finanzamt[0] eq '6');
478     $land = 'Rheinland Pfalz'        if (@$FA_finanzamt[0] eq '7');
479     $land = 'Baden Würtemberg'       if (@$FA_finanzamt[0] eq '8');
480     $land = 'Bayern'                 if (@$FA_finanzamt[0] eq '9');
481     $land = 'Saarland'               if (@$FA_finanzamt[0] eq '10');
482     $land = 'Berlin'                 if (@$FA_finanzamt[0] eq '11');
483     $land = 'Brandenburg'            if (@$FA_finanzamt[0] eq '12');
484     $land = 'Mecklenburg Vorpommern' if (@$FA_finanzamt[0] eq '13');
485     $land = 'Sachsen'                if (@$FA_finanzamt[0] eq '14');
486     $land = 'Sachsen Anhalt'         if (@$FA_finanzamt[0] eq '15');
487     $land = 'Thüringen'              if (@$FA_finanzamt[0] eq '16');
488
489     my $ffff = @$FA_finanzamt[1];
490
491     my $rec = {};
492     $rec->{$land} = $ffff;
493
494     shift @$row;
495     shift @$row;
496
497     $finanzamt{$land}{$ffff} = [@$FA_finanzamt];
498   }
499
500   $sth->finish();
501   $dbh->disconnect();
502
503   $main::lxdebug->leave_sub();
504
505   return \%finanzamt;
506 }
507
508 sub process_query {
509   $main::lxdebug->enter_sub();
510
511   # Copyright D. Simander -> SL::Form under Gnu GPL.
512   my ($form, $dbh, $filename) = @_;
513
514   #  return unless (-f $filename);
515
516   open(FH, "$filename") or $form->error("$filename : $!\n");
517   my $query = "";
518   my $sth;
519   my @quote_chars;
520
521   while (<FH>) {
522
523     # Remove DOS and Unix style line endings.
524     s/[\r\n]//g;
525
526     # don't add comments or empty lines
527     next if /^(--.*|\s+)$/;
528
529     for (my $i = 0; $i < length($_); $i++) {
530       my $char = substr($_, $i, 1);
531
532       # Are we inside a string?
533       if (@quote_chars) {
534         if ($char eq $quote_chars[-1]) {
535           pop(@quote_chars);
536         }
537         $query .= $char;
538
539       } else {
540         if (($char eq "'") || ($char eq "\"")) {
541           push(@quote_chars, $char);
542
543         } elsif ($char eq ";") {
544
545           # Query is complete. Send it.
546
547           $sth = $dbh->prepare($query);
548           $sth->execute || $form->dberror($query);
549           $sth->finish;
550
551           $char  = "";
552           $query = "";
553         }
554
555         $query .= $char;
556       }
557     }
558   }
559
560   close FH;
561
562   $main::lxdebug->leave_sub();
563 }
564
565 sub ustva {
566   $main::lxdebug->enter_sub();
567
568   my ($self, $myconfig, $form) = @_;
569
570   # connect to database
571   my $dbh = $form->dbconnect($myconfig);
572
573   my $last_period     = 0;
574   my $category        = "pos_ustva";
575   my @category_cent = qw(
576      511  861  36   80   971  931  98   96   53   74
577      85   65   66   61   62   67   63   64   59   69 
578      39   83   811  891  Z43  Z45  Z53  Z62  Z65  Z67
579   );
580
581   my @category_euro = qw(
582      41 44 49 43 48 51 
583      86 35 77 76 91 97 
584      93 95 94 42 60 45 
585      52 73 84 81 89
586   );
587
588   $form->{decimalplaces} *= 1;
589
590   foreach $item (@category_cent) {
591     $form->{"$item"} = 0;
592   }
593   foreach $item (@category_euro) {
594     $form->{"$item"} = 0;
595   }
596
597   &get_accounts_ustva($dbh, $last_period, $form->{fromdate}, $form->{todate},
598                       $form, $category);
599
600
601   # 16%/19% Umstellung
602   # Umordnen der Kennziffern
603   if ( $form->{year} < 2007) {
604     $form->{35} += $form->{81};
605     $form->{36} += $form->{811};
606     $form->{95} += $form->{89};
607     $form->{98} += $form->{891};
608     map { delete $form->{$_} } qw(81 811 89 891);
609   } else {
610     $form->{35} += $form->{51};
611     $form->{36} += $form->{511};
612     $form->{95} += $form->{97};
613     $form->{98} += $form->{971};
614     map { delete $form->{$_} } qw(51 511 97 971);
615   }
616
617
618   #
619   # Berechnung der USTVA Formularfelder laut Bogen 207
620   #
621
622   $form->{"51r"} = $form->{"511"};
623   $form->{"86r"} = $form->{"861"};
624   $form->{"97r"} = $form->{"971"};
625   $form->{"93r"} = $form->{"931"};
626
627   $form->{"Z43"} = $form->{"511"}     + $form->{"811"} + $form->{"861"} 
628                      + $form->{"36"}  + $form->{"80"}  + $form->{"971"} 
629                      + $form->{"891"} + $form->{"931"} + $form->{"96"} 
630                      + $form->{"98"};
631
632   $form->{"Z45"} = $form->{"Z43"};
633
634   $form->{"Z53"} = $form->{"Z45"}     + $form->{"53"}  + $form->{"74"}  
635                      + $form->{"85"}  + $form->{"65"};
636                      
637   $form->{"Z62"} = $form->{"Z43"}     - $form->{"66"}  - $form->{"61"} 
638                      - $form->{"62"}  - $form->{"67"}  - $form->{"63"}  
639                      - $form->{"64"}  - $form->{"59"};
640                       
641   $form->{"Z65"} = $form->{"Z62"}     - $form->{"69"};
642   $form->{"83"}  = $form->{"Z65"}     - $form->{"39"};
643   
644   $dbh->disconnect;
645
646   $main::lxdebug->leave_sub();
647 }
648
649 sub get_accounts_ustva {
650   $main::lxdebug->enter_sub();
651
652   my ($dbh, $last_period, $fromdate, $todate, $form, $category) = @_;
653
654   my ($null, $department_id) = split /--/, $form->{department};
655
656   my $query;
657   my $dpt_where;
658   my $dpt_join;
659   my $project;
660   my $where    = "";
661   my $glwhere  = "";
662   my $subwhere = "";
663   my $ARwhere  = "";
664   my $APwhere  = '';
665   my $arwhere  = "";
666   my $item;
667   my $gltaxkey_where = "(tk.pos_ustva>=59 AND tk.pos_ustva<=66)";
668
669   if ($fromdate) {
670     if ($form->{method} eq 'cash') {
671       $subwhere .= " AND transdate >= '$fromdate'";
672       $glwhere = " AND ac.transdate >= '$fromdate'";
673       $ARwhere .= " AND acc.transdate >= '$fromdate'"; 
674     }
675     $APwhere .= " AND AP.transdate >= '$fromdate'";
676     $where .= " AND ac.transdate >= '$fromdate'";
677   }
678
679   if ($todate) {
680     $where    .= " AND ac.transdate <= '$todate'";
681     $ARwhere  .= " AND acc.transdate <= '$todate'";
682     $subwhere .= " AND transdate <= '$todate'";
683     $APwhere  .= " AND AP.transdate <= '$todate'";     
684   }
685
686   if ($department_id) {
687     $dpt_join = qq|
688                JOIN department t ON (a.department_id = t.id)
689                   |;
690     $dpt_where = qq|
691                AND t.id = $department_id
692                    |;
693   }
694
695   if ($form->{project_id}) {
696     $project = qq|
697                  AND ac.project_id = $form->{project_id}
698                  |;
699   }
700   ############################################
701   # Method eq 'cash' = IST Versteuerung
702   ############################################
703   # Betrifft nur die eingenommene Umsatzsteuer
704   #
705   ############################################
706
707   if ($form->{method} eq 'cash') {  
708
709     $query = qq|
710        SELECT
711          -- USTVA IST-Versteuerung
712          -- 
713          -- Alle tatsaechlichen _Zahlungseingaenge_ 
714          -- im Voranmeldezeitraum erfassen 
715          -- (Teilzahlungen werden prozentual auf verschiedene Steuern aufgeteilt)
716          SUM( ac.amount * 
717             -- Bezahlt / Rechnungssumme
718            ( 
719              SELECT SUM(acc.amount)
720              FROM acc_trans acc
721              INNER JOIN chart c ON (acc.chart_id   =   c.id 
722                                     AND c.link   like  '%AR_paid%')
723              WHERE
724               1=1 
725               $ARwhere
726               AND acc.trans_id = ac.trans_id
727               )
728            / 
729            ( 
730             SELECT amount FROM ar WHERE id = ac.trans_id  
731            )
732          ) AS amount,
733          tk.pos_ustva
734        FROM acc_trans ac
735        LEFT JOIN chart c ON (c.id  = ac.chart_id)
736        LEFT JOIN ar      ON (ar.id = ac.trans_id)
737        LEFT JOIN taxkeys tk ON (
738          tk.id = (
739            SELECT id FROM taxkeys 
740            WHERE chart_id   = ac.chart_id 
741              -- AND taxkey_id  = ac.taxkey 
742              AND startdate <= COALESCE(ar.transdate)
743            ORDER BY startdate DESC LIMIT 1
744          )
745        )
746        WHERE 
747        1=1 
748        -- Here no where, please. All Transactions ever should be
749        -- testet if they are paied in the USTVA report period.
750        GROUP BY tk.pos_ustva
751     |;
752    
753   } elsif ($form->{method} eq 'accrual') {
754     #########################################
755     # Method eq 'accrual' = Soll Versteuerung
756     #########################################
757
758     if ($department_id) {
759       $dpt_join = qq|
760               JOIN dpt_trans t ON (t.trans_id = ac.trans_id)
761               |;
762       $dpt_where = qq|
763                AND t.department_id = $department_id
764               |;
765     }
766
767
768     $query = qq|
769        -- Alle Einnahmen AR und pos_ustva erfassen
770        SELECT
771          - sum(ac.amount) AS amount, 
772          tk.pos_ustva
773        FROM acc_trans ac 
774        JOIN chart c ON (c.id = ac.chart_id) 
775        JOIN ar ON (ar.id = ac.trans_id)
776        JOIN taxkeys tk ON (
777          tk.id = (
778            SELECT id FROM taxkeys 
779            WHERE chart_id   = ac.chart_id 
780              AND startdate <= COALESCE(ar.transdate)
781            ORDER BY startdate DESC LIMIT 1
782          )
783        )
784        $dpt_join
785        WHERE 1 = 1
786        $where
787        $dpt_where
788        $project
789        GROUP BY tk.pos_ustva
790   |;
791    
792   } else {
793   
794     $self->error("Unknown tax method: $form->{method}")
795
796   }
797   
798   #########################################
799   # Ausgaben und Gl Buchungen sind gleich
800   # für Ist- und Soll-Versteuerung
801   #########################################
802   $query .= qq| 
803      UNION -- alle Ausgaben AP erfassen
804
805        SELECT
806          sum(ac.amount) AS amount, 
807          tk.pos_ustva
808        FROM acc_trans ac
809        JOIN AP ON (AP.id = ac.trans_id )
810        JOIN chart c ON (c.id = ac.chart_id)
811        LEFT JOIN taxkeys tk ON (
812            tk.id = (
813              SELECT id FROM taxkeys 
814              WHERE chart_id=ac.chart_id 
815                --AND taxkey_id=ac.taxkey 
816                AND startdate <= COALESCE(AP.transdate)
817              ORDER BY startdate DESC LIMIT 1
818            )
819        )
820        WHERE
821        1=1
822        $APwhere
823        $dpt_where
824        $project
825        GROUP BY tk.pos_ustva
826
827      UNION -- Einnahmen direkter gl Buchungen erfassen
828
829        SELECT sum
830          ( - ac.amount) AS amount, 
831          tk.pos_ustva
832        FROM acc_trans ac
833        JOIN chart c ON (c.id = ac.chart_id)
834        JOIN gl a ON (a.id = ac.trans_id)
835        LEFT JOIN taxkeys tk ON (
836          tk.id = (
837            SELECT id FROM taxkeys 
838            WHERE chart_id=ac.chart_id 
839              --AND taxkey_id=ac.taxkey
840              AND NOT $gltaxkey_where  
841              AND startdate <= COALESCE(ac.transdate)
842            ORDER BY startdate DESC LIMIT 1
843          )
844        )
845
846        $dpt_join
847        WHERE 1 = 1
848        $where
849        $dpt_from
850        $project
851        GROUP BY tk.pos_ustva
852
853
854      UNION -- Ausgaben direkter gl Buchungen erfassen
855
856        SELECT sum
857          (ac.amount) AS amount, 
858          tk.pos_ustva
859        FROM acc_trans ac
860        JOIN chart c ON (c.id = ac.chart_id)
861        JOIN gl a ON (a.id = ac.trans_id)
862        LEFT JOIN taxkeys tk ON (
863          tk.id = (
864            SELECT id FROM taxkeys 
865            WHERE chart_id=ac.chart_id 
866              --AND taxkey_id=ac.taxkey
867              AND $gltaxkey_where 
868              AND startdate <= COALESCE(ac.transdate)
869            ORDER BY startdate DESC LIMIT 1
870          )
871        )
872
873        $dpt_join
874        WHERE 1 = 1
875        $where
876        $dpt_from
877        $project
878        GROUP BY tk.pos_ustva
879
880   |;
881
882   my @accno;
883   my $accno;
884   my $ref;
885
886   # Show all $query in Debuglevel LXDebug::QUERY
887   $callingdetails = (caller (0))[3];
888   $main::lxdebug->message(LXDebug::QUERY, "$callingdetails \$query=\n $query");
889               
890   my $sth = $dbh->prepare($query);
891   
892   $sth->execute || $form->dberror($query);
893
894   while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
895     # Bug 365 solved?!
896     $ref->{amount} *= -1;
897     if ($category eq "pos_bwa") {
898       if ($last_period) {
899         $form->{ $ref->{$category} }{kumm} += $ref->{amount};
900       } else {
901         $form->{ $ref->{$category} }{jetzt} += $ref->{amount};
902       }
903     } else {
904       $form->{ $ref->{$category} } += $ref->{amount};
905     }
906   }
907
908   $sth->finish;
909
910   $main::lxdebug->leave_sub();
911
912 }
913
914
915
916 1;