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