Unterstützung von UTF-8 bei der UStVA-Konfiguration.
[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ürttemberg'      => '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>| . $main::locale->text('Select federal state...') . qq|</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>| . $main::locale->text('Select tax office...') . qq|</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
365   return $fa_auswahl;
366 }
367
368 sub info {
369   $main::lxdebug->enter_sub();
370
371   my $msg = $_[0];
372
373   if ($ENV{HTTP_USER_AGENT}) {
374     $msg =~ s/\n/<br>/g;
375
376     print qq|<body><h2 class=info>Hinweis</h2>
377
378     <p><b>$msg</b>
379     <br>
380     <br>
381     <hr>
382     <input type=button value="| . $main::locale->text('Back') . qq|" onClick="history.go(-1)">
383     </body>
384     |;
385
386     exit;
387
388   } else {
389
390     die "Hinweis: $msg\n";
391   }
392
393   $main::lxdebug->leave_sub();
394 }
395
396 sub stichtag {
397   $main::lxdebug->enter_sub();
398
399   # noch nicht fertig
400   # soll mal eine Erinnerungsfunktion für USTVA Abgaben werden, die automatisch
401   # den Termin der nächsten USTVA anzeigt.
402   #
403   #
404   my ($today, $FA_dauerfrist, $FA_voranmeld) = @_;
405
406   #$today zerlegen:
407
408   #$today =today * 1;
409   $today =~ /(\d\d\d\d)(\d\d)(\d\d)/;
410   $year     = $1;
411   $month    = $2;
412   $day      = $3;
413   $yy       = $year;
414   $mm       = $month;
415   $yymmdd   = "$year$month$day" * 1;
416   $mmdd     = "$month$day" * 1;
417   $stichtag = '';
418
419   #$tage_bis = '1234';
420   #$ical = '...vcal format';
421
422   #if ($FA_voranmeld eq 'month'){
423
424   %liste = ("0110" => 'December',
425             "0210" => 'January',
426             "0310" => 'February',
427             "0410" => 'March',
428             "0510" => 'April',
429             "0610" => 'May',
430             "0710" => 'June',
431             "0810" => 'July',
432             "0910" => 'August',
433             "1010" => 'September',
434             "1110" => 'October',
435             "1210" => 'November');
436
437   #$mm += $dauerfrist
438   #$month *= 1;
439   $month += 1 if ($day > 10);
440   $month    = sprintf("%02d", $month);
441   $stichtag = $year . $month . "10";
442   $ust_va   = $month . "10";
443
444   foreach $date (%liste) {
445     $ust_va = $liste{$date} if ($date eq $stichtag);
446   }
447
448   #} elsif ($FA_voranmeld eq 'quarter'){
449   #1;
450
451   #}
452
453   #@stichtag = ('10.04.2004', '10.05.2004');
454
455   #@liste = ['0110', '0210', '0310', '0410', '0510', '0610', '0710', '0810', '0910',
456   #          '1010', '1110', '1210', ];
457   #
458   #foreach $key (@liste){
459   #  #if ($ddmm < ('0110' * 1));
460   #  if ($ddmm ){}
461   #  $stichtag = $liste[$key - 1] if ($ddmm > $key);
462   #
463   #}
464   #
465   #$stichtag =~ /([\d]\d)(\d\d)$/
466   #$stichtag = "$1.$2.$yy"
467   #$stichtag=$1;
468   $main::lxdebug->leave_sub();
469   return ($stichtag, $description, $tage_bis, $ical);
470 }
471
472 sub query_finanzamt {
473   $main::lxdebug->enter_sub();
474
475   my ($self, $myconfig, $form) = @_;
476
477   my $dbh = $form->dbconnect($myconfig) or $self->error(DBI->errstr);
478
479   #Test, if table finanzamt exist
480   my $table    = 'finanzamt';
481   my $filename = "sql/$table.sql";
482
483   my $tst = $dbh->prepare("SELECT * FROM $table");
484   $tst->execute;
485   if ($DBI::err) {
486
487     #There is no table, read the table from sql/finanzamt.sql
488     print qq|<p>Bitte warten, Tabelle $table wird einmalig in Datenbank:
489     $myconfig->{dbname} als Benutzer: $myconfig->{dbuser} hinzugefügt...</p>|;
490     process_query($form, $dbh, $filename) || $self->error(DBI->errstr);
491
492     #execute second last call
493     my $dbh = $form->dbconnect($myconfig) or $self->error(DBI->errstr);
494     $dbh->disconnect();
495   }
496   $tst->finish();
497
498   #$dbh->disconnect();
499
500   my @vars = (
501     'FA_Land_Nr',             #  0
502     'FA_BUFA_Nr',             #  1
503                               #'FA_Verteiler',                          #  2
504     'FA_Name',                #  3
505     'FA_Strasse',             #  4
506     'FA_PLZ',                 #  5
507     'FA_Ort',                 #  6
508     'FA_Telefon',             #  7
509     'FA_Fax',                 #  8
510     'FA_PLZ_Grosskunden',     #  9
511     'FA_PLZ_Postfach',        # 10
512     'FA_Postfach',            # 11
513     'FA_BLZ_1',               # 12
514     'FA_Kontonummer_1',       # 13
515     'FA_Bankbezeichnung_1',   # 14
516                               #'FA_BankIBAN_1',                         # 15
517                               #'FA_BankBIC_1',                          # 16
518                               #'FA_BankInhaber_BUFA_Nr_1',                      # 17
519     'FA_BLZ_2',               # 18
520     'FA_Kontonummer_2',       # 19
521     'FA_Bankbezeichnung_2',   # 20
522                               #'FA_BankIBAN_2',                         # 21
523                               #'FA_BankBIC_2',                          # 22
524                               #'FA_BankInhaber_BUFA_Nr_2',                      # 23
525     'FA_Oeffnungszeiten',     # 24
526     'FA_Email',               # 25
527     'FA_Internet'             # 26
528                               #'FA_zustaendige_Hauptstelle_BUFA_Nr',            # 27
529                               #'FA_zustaendige_vorgesetzte_Finanzbehoerde'      # 28
530   );
531
532   my $field = join(', ', @vars);
533
534   my $query = "SELECT $field FROM finanzamt ORDER BY FA_Land_nr";
535   my $sth = $dbh->prepare($query) or $self->error($dbh->errstr);
536   $sth->execute || $form->dberror($query);
537   my $array_ref = $sth->fetchall_arrayref();
538   my $land      = '';
539   foreach my $row (@$array_ref) {
540     my $FA_finanzamt = $row;
541     $land = 'Schleswig Holstein'     if (@$FA_finanzamt[0] eq '1');
542     $land = 'Hamburg'                if (@$FA_finanzamt[0] eq '2');
543     $land = 'Niedersachsen'          if (@$FA_finanzamt[0] eq '3');
544     $land = 'Bremen'                 if (@$FA_finanzamt[0] eq '4');
545     $land = 'Nordrhein Westfalen'    if (@$FA_finanzamt[0] eq '5');
546     $land = 'Hessen'                 if (@$FA_finanzamt[0] eq '6');
547     $land = 'Rheinland Pfalz'        if (@$FA_finanzamt[0] eq '7');
548     $land = 'Baden Württemberg'      if (@$FA_finanzamt[0] eq '8');
549     $land = 'Bayern'                 if (@$FA_finanzamt[0] eq '9');
550     $land = 'Saarland'               if (@$FA_finanzamt[0] eq '10');
551     $land = 'Berlin'                 if (@$FA_finanzamt[0] eq '11');
552     $land = 'Brandenburg'            if (@$FA_finanzamt[0] eq '12');
553     $land = 'Mecklenburg Vorpommern' if (@$FA_finanzamt[0] eq '13');
554     $land = 'Sachsen'                if (@$FA_finanzamt[0] eq '14');
555     $land = 'Sachsen Anhalt'         if (@$FA_finanzamt[0] eq '15');
556     $land = 'Thüringen'              if (@$FA_finanzamt[0] eq '16');
557
558     $land = $main::locale->{iconv}->convert($land);
559
560     my $ffff = @$FA_finanzamt[1];
561
562     my $rec = {};
563     $rec->{$land} = $ffff;
564
565     shift @$row;
566     shift @$row;
567
568     $finanzamt{$land}{$ffff} = [@$FA_finanzamt];
569   }
570
571   $sth->finish();
572   $dbh->disconnect();
573
574   $main::lxdebug->leave_sub();
575
576   return \%finanzamt;
577 }
578
579 sub process_query {
580   $main::lxdebug->enter_sub();
581
582   # Copyright D. Simander -> SL::Form under Gnu GPL.
583   my ($form, $dbh, $filename) = @_;
584
585   #  return unless (-f $filename);
586
587   open my $FH, "<", "$filename" or $form->error("$filename : $!\n");
588   my $query = "";
589   my $sth;
590   my @quote_chars;
591
592   while (<$FH>) {
593
594     # Remove DOS and Unix style line endings.
595     s/[\r\n]//g;
596
597     # don't add comments or empty lines
598     next if /^(--.*|\s+)$/;
599
600     for (my $i = 0; $i < length($_); $i++) {
601       my $char = substr($_, $i, 1);
602
603       # Are we inside a string?
604       if (@quote_chars) {
605         if ($char eq $quote_chars[-1]) {
606           pop(@quote_chars);
607         }
608         $query .= $char;
609
610       } else {
611         if (($char eq "'") || ($char eq "\"")) {
612           push(@quote_chars, $char);
613
614         } elsif ($char eq ";") {
615
616           # Query is complete. Send it.
617
618           $sth = $dbh->prepare($query);
619           $sth->execute || $form->dberror($query);
620           $sth->finish;
621
622           $char  = "";
623           $query = "";
624         }
625
626         $query .= $char;
627       }
628     }
629   }
630
631   close $FH;
632
633   $main::lxdebug->leave_sub();
634 }
635
636 sub ustva {
637   $main::lxdebug->enter_sub();
638
639   my ($self, $myconfig, $form) = @_;
640
641   # connect to database
642   my $dbh = $form->dbconnect($myconfig);
643
644   my $last_period     = 0;
645   my $category        = "pos_ustva";
646
647   my @category_cent = USTVA->report_variables({
648       myconfig    => $myconfig,
649       form        => $form,
650       type        => '',
651       attribute   => 'position',
652       dec_places  => '2',
653   });
654   
655   push @category_cent, qw(83  Z43  Z45  Z53  Z62  Z65  Z67);
656   
657   my @category_euro = USTVA->report_variables({
658       myconfig    => $myconfig,
659       form        => $form,
660       type        => '',
661       attribute   => 'position',
662       dec_places  => '0',
663   });
664                            
665   push @category_euro, USTVA->report_variables({
666       myconfig    => $myconfig,
667       form        => $form,
668       type        => '',
669       attribute   => 'position',
670       dec_places  => '0',
671   });
672
673   $form->{decimalplaces} *= 1;
674
675   foreach $item (@category_cent) {
676     $form->{"$item"} = 0;
677   }
678   foreach $item (@category_euro) {
679     $form->{"$item"} = 0;
680   }
681   my $coa_name = coa_get($dbh);
682   $form->{coa} = $coa_name;
683   
684   # Controlvariable for templates
685   $form->{"$coa_name"} = '1';
686
687   $main::lxdebug->message(LXDebug::DEBUG2, "COA: '$form->{coa}',  \$form->{$coa_name} = 1");
688
689   &get_accounts_ustva($dbh, $last_period, $form->{fromdate}, $form->{todate},
690                       $form, $category);
691
692   ###########################################
693   #
694   # Nationspecific Modfications
695   #
696   ###########################################
697   
698   # Germany
699   
700   if ( $form->{coa} eq 'Germany-DATEV-SKR03EU' or $form->{coa} eq 'Germany-DATEV-SKR04EU'){
701   
702     # 16%/19% Umstellung
703     # Umordnen der Kennziffern
704     if ( $form->{year} < 2007) {
705       $form->{35} += $form->{81};
706       $form->{36} += $form->{811};
707       $form->{95} += $form->{89};
708       $form->{98} += $form->{891};
709       map { delete $form->{$_} } qw(81 811 89 891);
710     } else {
711       $form->{35} += $form->{51};
712       $form->{36} += $form->{511};
713       $form->{95} += $form->{97};
714       $form->{98} += $form->{971};
715       map { delete $form->{$_} } qw(51 511 97 971);
716     }
717
718   }
719
720
721   # Fixme: Wird auch noch für Oesterreich gebraucht, 
722   # weil kein eigenes Ausgabeformular
723   # sotte aber aus der allgeméinen Steuerberechnung verschwinden
724   #
725   # Berechnung der USTVA Formularfelder laut Bogen 207
726   #
727
728   $form->{"51r"} = $form->{"511"};
729   $form->{"86r"} = $form->{"861"};
730   $form->{"97r"} = $form->{"971"};
731   $form->{"93r"} = $form->{"931"};
732
733   $form->{"Z43"} = $form->{"511"}     + $form->{"811"} + $form->{"861"} 
734                      + $form->{"36"}  + $form->{"80"}  + $form->{"971"} 
735                      + $form->{"891"} + $form->{"931"} + $form->{"96"} 
736                      + $form->{"98"};
737
738   $form->{"Z45"} = $form->{"Z43"};
739
740   $form->{"Z53"} = $form->{"Z45"}     + $form->{"53"}  + $form->{"74"}  
741                      + $form->{"85"}  + $form->{"65"};
742                      
743   $form->{"Z62"} = $form->{"Z43"}     - $form->{"66"}  - $form->{"61"} 
744                      - $form->{"62"}  - $form->{"67"}  - $form->{"63"}  
745                      - $form->{"64"}  - $form->{"59"};
746                       
747   $form->{"Z65"} = $form->{"Z62"}     - $form->{"69"};
748   $form->{"83"}  = $form->{"Z65"}     - $form->{"39"};
749   
750   $dbh->disconnect;
751
752   $main::lxdebug->leave_sub();
753 }
754
755 sub coa_get {
756
757   my ($dbh) = @_;
758   
759   my $query= qq|SELECT coa FROM defaults|;
760
761   my $sth = $dbh->prepare($query);
762   
763   $sth->execute || $form->dberror($query);
764     
765   ($ref) = $sth->fetchrow_array;
766   
767   return $ref;
768
769 };
770
771 sub get_accounts_ustva {
772   $main::lxdebug->enter_sub();
773
774   my ($dbh, $last_period, $fromdate, $todate, $form, $category) = @_;
775
776   my $query;
777   my $where    = "";
778   my $glwhere  = "";
779   my $subwhere = "";
780   my $ARwhere  = "";
781   my $APwhere  = '';
782   my $arwhere  = "";
783   my $item;
784
785     my $gltaxkey_where = "(tk.pos_ustva>=59 AND tk.pos_ustva<=66)";
786
787   if ($fromdate) {
788     if ($form->{method} eq 'cash') {
789       $subwhere .= " AND transdate >= '$fromdate'";
790       $glwhere = " AND ac.transdate >= '$fromdate'";
791       $ARwhere .= " AND acc.transdate >= '$fromdate'"; 
792     }
793     $APwhere .= " AND AP.transdate >= '$fromdate'";
794     $where .= " AND ac.transdate >= '$fromdate'";
795   }
796
797   if ($todate) {
798     $where    .= " AND ac.transdate <= '$todate'";
799     $ARwhere  .= " AND acc.transdate <= '$todate'";
800   }
801
802   my $acc_trans_where = '1=1';
803   if ($fromdate || $todate) {
804     $acc_trans_where = "ac.trans_id IN (SELECT DISTINCT trans_id FROM acc_trans WHERE ";
805
806     if ($fromdate) {
807       $acc_trans_where .= "transdate >= '$fromdate'";
808     }
809     if ($todate) {
810       $acc_trans_where .= " AND " if ($fromdate);
811       $acc_trans_where .= "transdate <= '$todate'";
812     }
813
814     $acc_trans_where .= ")";
815   }
816
817   ############################################
818   # Method eq 'cash' = IST Versteuerung
819   ############################################
820   # Betrifft nur die eingenommene Umsatzsteuer
821   #
822   ############################################
823
824   if ($form->{method} eq 'cash') {  
825
826     $query = qq|
827        SELECT
828          -- USTVA IST-Versteuerung
829          -- 
830          -- Alle tatsaechlichen _Zahlungseingaenge_ 
831          -- im Voranmeldezeitraum erfassen 
832          -- (Teilzahlungen werden prozentual auf verschiedene Steuern aufgeteilt)
833          SUM( ac.amount * 
834             -- Bezahlt / Rechnungssumme
835            ( 
836              SELECT SUM(acc.amount)
837              FROM acc_trans acc
838              INNER JOIN chart c ON (acc.chart_id   =   c.id 
839                                     AND c.link   like  '%AR_paid%')
840              WHERE
841               1=1 
842               $ARwhere
843               AND acc.trans_id = ac.trans_id
844               )
845            / 
846            ( 
847             SELECT amount FROM ar WHERE id = ac.trans_id  
848            )
849          ) AS amount,
850          tk.pos_ustva
851        FROM acc_trans ac
852        LEFT JOIN chart c ON (c.id  = ac.chart_id)
853        LEFT JOIN ar      ON (ar.id = ac.trans_id)
854        LEFT JOIN taxkeys tk ON (
855          tk.id = (
856            SELECT id FROM taxkeys 
857            WHERE chart_id   = ac.chart_id 
858              -- AND taxkey_id  = ac.taxkey 
859              AND startdate <= COALESCE(ar.deliverydate,ar.transdate)
860            ORDER BY startdate DESC LIMIT 1
861          )
862        )
863        WHERE 
864        $acc_trans_where
865        GROUP BY tk.pos_ustva
866     |;
867    
868   } elsif ($form->{method} eq 'accrual') {
869     #########################################
870     # Method eq 'accrual' = Soll Versteuerung
871     #########################################
872
873     $query = qq|
874        -- Alle Einnahmen AR und pos_ustva erfassen
875        SELECT
876          - sum(ac.amount) AS amount, 
877          tk.pos_ustva
878        FROM acc_trans ac 
879        JOIN chart c ON (c.id = ac.chart_id) 
880        JOIN ar ON (ar.id = ac.trans_id)
881        JOIN taxkeys tk ON (
882          tk.id = (
883            SELECT id FROM taxkeys 
884            WHERE chart_id   = ac.chart_id 
885              AND startdate <= COALESCE(ar.deliverydate,ar.transdate)
886            ORDER BY startdate DESC LIMIT 1
887          )
888        )
889        $dpt_join
890        WHERE 1 = 1
891        $where
892        GROUP BY tk.pos_ustva
893   |;
894    
895   } else {
896   
897     $form->error("Unknown tax method: $form->{method}")
898
899   }
900   
901   #########################################
902   # Ausgaben und Gl Buchungen sind gleich
903   # für Ist- und Soll-Versteuerung
904   #########################################
905   $query .= qq| 
906      UNION -- alle Ausgaben AP erfassen
907
908        SELECT
909          sum(ac.amount) AS amount, 
910          tk.pos_ustva
911        FROM acc_trans ac
912        JOIN ap ON (ap.id = ac.trans_id )
913        JOIN chart c ON (c.id = ac.chart_id)
914        LEFT JOIN taxkeys tk ON (
915            tk.id = (
916              SELECT id FROM taxkeys 
917              WHERE 1=1
918                AND chart_id=ac.chart_id 
919                --AND taxkey_id = ac.taxkey 
920                AND startdate <= COALESCE(AP.transdate)
921              ORDER BY startdate DESC LIMIT 1
922            )
923        )
924        WHERE
925        1=1
926        $where
927        GROUP BY tk.pos_ustva
928
929      UNION -- Einnahmen direkter gl Buchungen erfassen
930
931        SELECT sum
932          ( - ac.amount) AS amount, 
933          tk.pos_ustva
934        FROM acc_trans ac
935        JOIN chart c ON (c.id = ac.chart_id)
936        JOIN gl a ON (a.id = ac.trans_id)
937        LEFT JOIN taxkeys tk ON (
938          tk.id = (
939            SELECT id FROM taxkeys 
940            WHERE chart_id=ac.chart_id 
941              AND NOT $gltaxkey_where  
942              AND startdate <= COALESCE(ac.transdate)
943            ORDER BY startdate DESC LIMIT 1
944          )
945        )
946
947        $dpt_join
948        WHERE 1 = 1
949        $where
950        GROUP BY tk.pos_ustva
951
952
953      UNION -- Ausgaben direkter gl Buchungen erfassen
954
955        SELECT sum
956          (ac.amount) AS amount, 
957          tk.pos_ustva
958        FROM acc_trans ac
959        JOIN chart c ON (c.id = ac.chart_id)
960        JOIN gl a ON (a.id = ac.trans_id)
961        LEFT JOIN taxkeys tk ON (
962          tk.id = (
963            SELECT id FROM taxkeys 
964            WHERE chart_id=ac.chart_id 
965              AND $gltaxkey_where 
966              AND startdate <= COALESCE(ac.transdate)
967            ORDER BY startdate DESC LIMIT 1
968          )
969        )
970
971        $dpt_join
972        WHERE 1 = 1
973        $where
974        GROUP BY tk.pos_ustva
975
976   |;
977
978   my @accno;
979   my $accno;
980   my $ref;
981
982   # Show all $query in Debuglevel LXDebug::QUERY
983   $callingdetails = (caller (0))[3];
984   $main::lxdebug->message(LXDebug::QUERY, "$callingdetails \$query=\n $query");
985               
986   my $sth = $dbh->prepare($query);
987   
988   $sth->execute || $form->dberror($query);
989
990   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
991     # Bug 365 solved?!
992     $ref->{amount} *= -1;
993     $form->{ $ref->{$category} } += $ref->{amount};
994   }
995
996   $sth->finish;
997
998   $main::lxdebug->leave_sub();
999
1000 }
1001
1002 sub get_config {
1003   $main::lxdebug->enter_sub();
1004
1005   my ($self, $userspath, $filename) = @_;
1006
1007   $form->error("Missing Parameter: @_") if !$userspath || !$filename;
1008
1009   my $form = $main::form;
1010
1011   $filename = "$form->{login}_$filename";
1012   $filename =~ s|.*/||;
1013   $filename = "$userspath/$filename";
1014   open my $FACONF, "<", $filename or sub {# Annon Sub
1015     # catch open error
1016     # create file if file does not exist
1017     open my $FANEW, ">", $filename  or $form->error("CREATE: $filename : $!");
1018     close $FANEW                    or $form->error("CLOSE: $filename : $!");
1019     
1020     #try again open file
1021     open my $FACONF, "<", $filename or $form->error("OPEN: $filename : $!");
1022   };
1023
1024   while (<$FACONF>) {
1025     last if (/^\[/);
1026     next if (/^(\#|\s)/);
1027
1028     # remove comments
1029     s/\s#.*//g;
1030
1031     # remove any trailing whitespace
1032     s/^\s*(.*?)\s*$/$1/;
1033     my ($key, $value) = split(/=/, $_, 2);
1034
1035     $form->{$key} = "$value";
1036
1037   }
1038
1039   close $FACONF;
1040
1041   $main::lxdebug->leave_sub();
1042 }
1043
1044
1045 1;