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