Merge remote branch 'origin/master'
[kivitendo-erp.git] / SL / RP.pm
index 1ee3984..a319cf5 100644 (file)
--- a/SL/RP.pm
+++ b/SL/RP.pm
@@ -49,12 +49,23 @@ use strict;
 # - subdescription
 # - proper testing for heading charts
 # - transmission from $form to TMPL realm is not as clear as i'd like
+
+sub get_openbalance_date {
+  my ($closedto, $target) = map { $::locale->parse_date_to_object(\%::myconfig, $_) } @_;
+
+  return unless $closedto;
+
+  $closedto->subtract(years => 1) while ($target - $closedto)->is_negative;
+  $closedto->add(days => 1);
+  return $::locale->format_date(\%::myconfig, $closedto);
+}
+
 sub balance_sheet {
   $main::lxdebug->enter_sub();
 
   my $myconfig = \%main::myconfig;
   my $form     = $main::form;
-  my $dbh      = $form->get_standard_dbh($myconfig);
+  my $dbh      = $::form->get_standard_dbh;
 
   my $last_period = 0;
   my @categories  = qw(A C L Q);
@@ -64,12 +75,21 @@ sub balance_sheet {
     $form->{period} = $form->{this_period} = conv_dateq($form->{asofdate});
   }
 
-  get_accounts($dbh, $last_period, "", $form->{asofdate}, $form, \@categories);
+  # get end of financial year and convert to Date format
+  my ($closedto) = selectfirst_array_query($form, $dbh, 'SELECT closedto FROM defaults');
+
+  # get date of last opening balance
+  my $startdate = get_openbalance_date($closedto, $form->{asofdate});
+
+  get_accounts($dbh, $last_period, $startdate, $form->{asofdate}, $form, \@categories);
 
   # if there are any compare dates
   if ($form->{compareasofdate}) {
     $last_period = 1;
-    get_accounts($dbh, $last_period, "", $form->{compareasofdate}, $form, \@categories);
+
+    $startdate = get_openbalance_date($closedto, $form->{compareasofdate});
+
+    get_accounts($dbh, $last_period, $startdate, $form->{compareasofdate}, $form, \@categories);
     $form->{last_period} = conv_dateq($form->{compareasofdate});
   }
 
@@ -118,7 +138,6 @@ sub balance_sheet {
         next if ($period eq 'last' && !$last_period);
         # only add assets
         $row->{$period}                    *= $ml;
-        $form->{total}{$category}{$period} += $row->{$period};      #      if ($row->{charttype} eq 'A') {   # why??
       }
 
       push @{ $TMPL_DATA->{$category} }, $row;
@@ -138,12 +157,11 @@ sub balance_sheet {
   for my $period (qw(this last)) {
     next if ($period eq 'last' && !$last_period);
 
-    $form->{E}{$period}             = $form->{total}{A}{$period} - $form->{total}{L}{$period} - $form->{total}{Q}{$period};
-    $form->{total}{Q}{$period}     += $form->{E}{$period};
-    $TMPL_DATA->{total}{Q}{$period} = $form->{total}{Q}{$period};
-    $TMPL_DATA->{total}{$period}    = $form->{total}{L}{$period} + $form->{total}{Q}{$period};
+    $form->{E}{$period}             = $TMPL_DATA->{total}{A}{$period} - $TMPL_DATA->{total}{L}{$period} - $TMPL_DATA->{total}{Q}{$period};
+    $TMPL_DATA->{total}{Q}{$period}     += $form->{E}{$period};
+    $TMPL_DATA->{total}{$period}    = $TMPL_DATA->{total}{L}{$period} + $TMPL_DATA->{total}{Q}{$period};
   }
-
+    $form->{E}{description}='nicht verbuchter Gewinn/Verlust';
   push @{ $TMPL_DATA->{Q} }, $form->{E};
 
   $main::lxdebug->leave_sub();
@@ -193,6 +211,13 @@ sub get_accounts {
 
   $sth->finish;
 
+  # if l_ob is selected l_cb is always ignored
+  if ( $form->{l_ob} ) {
+    $where .= ' AND ac.ob_transaction is true  '
+  } elsif ( not $form->{l_cb} ) {
+    $where .= ' AND ac.cb_transaction is false ';
+  };
+
   if ($fromdate) {
     $fromdate = conv_dateq($fromdate);
     if ($form->{method} eq 'cash') {
@@ -328,12 +353,10 @@ sub get_accounts {
     }
 
   } else {                      # if ($form->{method} eq 'cash')
-    # ich sehe keinen sinn das nochmal explizit ohne conv_i aufzurufen
-    # bitte prüfen und löschen jan 15.11.2009
-  #  if ($department_id) {
-  #    $dpt_join = qq| JOIN dpt_trans t ON (t.trans_id = ac.trans_id) |;
-  #    $dpt_where = qq| AND t.department_id = $department_id |;
-  #  }
+    if ($department_id) {
+      $dpt_join = qq| JOIN dpt_trans t ON (t.trans_id = ac.trans_id) |;
+      $dpt_where = qq| AND t.department_id = | . conv_i($department_id);
+    }
 
     $query = qq|
       SELECT c.accno, sum(ac.amount) AS amount, c.description, c.category
@@ -448,6 +471,8 @@ sub get_accounts_g {
   my $inwhere = "";
   my $item;
 
+  $where .= ' AND ac.cb_transaction is false ' unless $form->{l_cb};
+
   if ($fromdate) {
     $fromdate = conv_dateq($fromdate);
     if ($form->{method} eq 'cash') {
@@ -491,13 +516,13 @@ sub get_accounts_g {
   if ($form->{method} eq 'cash') {
     $query =
       qq|
-       SELECT SUM( ac.amount *
+       SELECT SUM( ac.amount * CASE WHEN COALESCE((SELECT amount FROM ar WHERE id = ac.trans_id and amount != 0 ), 0) != 0 THEN
                     (SELECT SUM(acc.amount) * -1
                      FROM acc_trans acc
                      INNER JOIN chart c ON (acc.chart_id = c.id AND c.link LIKE '%AR_paid%')
                      WHERE 1=1 $inwhere AND acc.trans_id = ac.trans_id)
-                  / (SELECT amount FROM ar WHERE id = ac.trans_id)
-                ) AS amount, c.pos_eur
+                  / (SELECT amount FROM ar WHERE id = ac.trans_id and amount != 0 ) ELSE 1 END
+                ) AS amount, c.$category
        FROM acc_trans ac
        LEFT JOIN chart c ON (c.id  = ac.chart_id)
        LEFT JOIN ar      ON (ar.id = ac.trans_id)
@@ -510,7 +535,7 @@ sub get_accounts_g {
                                 )
       WHERE ac.trans_id IN (SELECT DISTINCT trans_id FROM acc_trans WHERE 1=1 $subwhere)
 
-      GROUP BY c.pos_eur
+      GROUP BY c.$category
 
 /*
        SELECT SUM(ac.amount * chart_category_to_sgn(c.category)) AS amount, c.$category
@@ -579,10 +604,10 @@ sub get_accounts_g {
     }
 
   } else {                      # if ($form->{method} eq 'cash')
-    # s.o. jan 15.11.2009
-#    if ($department_id) {
-#      ($dpt_join, $dpt_where) = sql_department($department_id);
-#    }
+    if ($department_id) {
+      $dpt_join = qq| JOIN dpt_trans t ON (t.trans_id = ac.trans_id) |;
+      $dpt_where = qq| AND (t.department_id = | . conv_i($department_id, 'NULL') . qq|) |;
+    }
 
     $query = qq|
         SELECT sum(ac.amount * chart_category_to_sgn(c.category)) AS amount, c.$category
@@ -1146,6 +1171,8 @@ sub aging {
 
   my ($invoice, $arap, $buysell, $ct, $ct_id, $ml);
 
+  # falls customer ziehen wir die offene forderungsliste
+  # anderfalls für die lieferanten die offenen verbindlichkeitne
   if ($form->{ct} eq "customer") {
     $invoice = "is";
     $arap = "ar";
@@ -1161,12 +1188,42 @@ sub aging {
   }
   $ct_id = "${ct}_id";
 
-  $form->{todate} = $form->current_date($myconfig) unless ($form->{todate});
-  my $todate = conv_dateq($form->{todate});
-  my $fromdate = conv_dateq($form->{fromdate});
+  # erweiterung um einen freien zeitraum oder einen stichtag
+  # mit entsprechender altersstrukturliste (s.a. Bug 1842)
+  # eine neue variable an der oberfläche eingeführt, somit ist
+  # todate == freier zeitrau und fordate == stichtag
+
+  my ($review_of_aging_list, $todate, $fromdate, $fromwhere, $fordate);
 
-  my $fromwhere = ($form->{fromdate} ne "") ? " AND (transdate >= (date $fromdate)) " : "";
+  if ($form->{reporttype} eq 'custom') {  # altersstrukturliste
 
+    # explizit rausschmeissen was man für diesen bericht nicht braucht
+    delete $form->{fromdate};
+    delete $form->{todate};
+
+    # an der oberfläche ist das tagesaktuelle datum vorausgewählt
+    # falls es dennoch per Benutzereingabe gelöscht wird, lieber wieder vorbelegen
+    # ferner muss für die spätere DB-Abfrage muss todate gesetzt sein.
+    $form->{fordate}  = $form->current_date($myconfig) unless ($form->{fordate});
+    $fordate          = conv_dateq($form->{fordate});
+    $todate           = $fordate;
+
+    if ($form->{review_of_aging_list}) { # falls die liste leer ist, alles anzeigen
+      if ($form->{review_of_aging_list} =~ m "-") {             # ..  periode von bis
+        my @period = split(/-/, $form->{review_of_aging_list}); # ... von periode bis periode
+        $review_of_aging_list = " AND $period[0] <  (date $fordate) - duedate
+                                  AND (date $fordate) - duedate  < $period[1]";
+      } else {
+        $form->{review_of_aging_list} =~ s/[^0-9]//g;   # größer 120 das substitute ist nur für das '>' zeichen
+        $review_of_aging_list = " AND $form->{review_of_aging_list} < (date $fordate) - duedate";
+      }
+    }
+  } else {  # freier zeitraum OHNE review_of_aging_list
+    $form->{todate}  = $form->current_date($myconfig) unless ($form->{todate});
+    $todate = conv_dateq($form->{todate});
+    $fromdate = conv_dateq($form->{fromdate});
+    $fromwhere = ($form->{fromdate} ne "") ? " AND (transdate >= (date $fromdate)) " : "";
+  }
   my $where = " 1 = 1 ";
   my ($name, $null);
 
@@ -1177,21 +1234,21 @@ sub aging {
   }
 
   my $dpt_join;
+  my $where_dpt;
   if ($form->{department}) {
     my ($null, $department_id) = split /--/, $form->{department};
     $dpt_join = qq| JOIN department d ON (a.department_id = d.id) |;
     $where .= qq| AND (a.department_id = | . conv_i($department_id, 'NULL') . qq|)|;
+    $where_dpt = qq| AND (${arap}.department_id = | . conv_i($department_id, 'NULL') . qq|)|;
   }
-
-  my $q_details = qq|
-    -- between 0-30 days
+ my $q_details = qq|
 
     SELECT ${ct}.id AS ctid, ${ct}.name,
       street, zipcode, city, country, contact, email,
       phone as customerphone, fax as customerfax, ${ct}number,
       "invnumber", "transdate",
       (amount - COALESCE((SELECT sum(amount)*$ml FROM acc_trans LEFT JOIN chart ON (acc_trans.chart_id=chart.id) WHERE link ilike '%paid%' AND acc_trans.trans_id=${arap}.id AND acc_trans.transdate <= (date $todate)),0)) as "open", "amount",
-      "duedate", invoice, ${arap}.id,
+      "duedate", invoice, ${arap}.id, date_part('days', now() - duedate) as overduedays,
       (SELECT $buysell
        FROM exchangerate
        WHERE (${arap}.curr = exchangerate.curr)
@@ -1200,9 +1257,10 @@ sub aging {
     WHERE ((paid != amount) OR (datepaid > (date $todate) AND datepaid is not null))
       AND NOT COALESCE (${arap}.storno, 'f')
       AND (${arap}.${ct}_id = ${ct}.id)
+      $where_dpt
       AND (${ct}.id = ?)
       AND (transdate <= (date $todate) $fromwhere )
-
+      $review_of_aging_list
     ORDER BY ctid, transdate, invnumber |;
 
   my $sth_details = prepare_query($form, $dbh, $q_details);
@@ -1264,27 +1322,6 @@ sub get_customer {
   $main::lxdebug->leave_sub();
 }
 
-sub get_taxaccounts {
-  $main::lxdebug->enter_sub();
-
-  my ($self, $myconfig, $form) = @_;
-
-  # connect to database
-  my $dbh = $form->dbconnect($myconfig);
-
-  # get tax accounts
-  my $query =
-    qq|SELECT c.accno, c.description, t.rate
-       FROM chart c, tax t
-       WHERE (c.link LIKE '%CT_tax%') AND (c.id = t.chart_id)
-       ORDER BY c.accno|;
-  $form->{taxaccounts} = selectall_hashref_quert($form, $dbh, $query);
-
-  $dbh->disconnect;
-
-  $main::lxdebug->leave_sub();
-}
-
 sub tax_report {
   $main::lxdebug->enter_sub();
 
@@ -1612,7 +1649,7 @@ sub bwa {
 
   my @periods        = qw(jetzt kumm);
   my @gesamtleistung = qw(1 3);
-  my @gesamtkosten   = qw (10 11 12 13 14 15 16 17 18 19 20);
+  my @gesamtkosten   = qw (10 11 12 13 14 15 16 17 18 20);
   my @ergebnisse     =
     qw (rohertrag betriebrohertrag betriebsergebnis neutraleraufwand neutralerertrag ergebnisvorsteuern ergebnis gesamtleistung gesamtkosten);
 
@@ -1647,13 +1684,13 @@ sub bwa {
       $form->{ "$key" . "betriebrohertrag" } -
       $form->{ "$key" . "gesamtkosten" };
     $form->{ "$key" . "neutraleraufwand" } =
-      $form->{30}{$key} + $form->{31}{$key};
-    $form->{ "$key" . "neutralertrag" } =
+      $form->{19}{$key} + $form->{30}{$key} + $form->{31}{$key};
+    $form->{ "$key" . "neutralerertrag" } =
       $form->{32}{$key} + $form->{33}{$key} + $form->{34}{$key};
     $form->{ "$key" . "ergebnisvorsteuern" } =
       $form->{ "$key" . "betriebsergebnis" } -
       $form->{ "$key" . "neutraleraufwand" } +
-      $form->{ "$key" . "neutralertrag" };
+      $form->{ "$key" . "neutralerertrag" };
     $form->{ "$key" . "ergebnis" } =
       $form->{ "$key" . "ergebnisvorsteuern" } - $form->{35}{$key};