]> wagnertech.de Git - mfinanz.git/blobdiff - SL/IS.pm
Anzahlungs-Rg.: Druckvariblen: offenen Betrag jeder Anzahlungs-Rg. und Summe
[mfinanz.git] / SL / IS.pm
index 3bcc0daddf8807bf21f4faddf41e14e7285f66db..8b79376d2e06c5bb62055e97a60291da34e3b6e8 100644 (file)
--- a/SL/IS.pm
+++ b/SL/IS.pm
@@ -36,6 +36,7 @@
 package IS;
 
 use List::Util qw(max sum0);
+use List::MoreUtils qw(any);
 
 use Carp;
 use SL::AM;
@@ -578,21 +579,31 @@ sub invoice_details {
   $form->{$_} = $form->format_amount($myconfig, $form->{$_}, 2) for @separate_totals;
 
   foreach my $invoice_for_advance_payment (@{$self->_get_invoices_for_advance_payment($form->{convert_from_ar_ids} || $form->{id})}) {
+    # Collect VAT of invoices for advance payment.
+    # Set sellprices to fxsellprices for items, because
+    # the PriceTaxCalculator sets fxsellprice from sellprice before calculating.
+    $_->sellprice($_->fxsellprice) for @{$invoice_for_advance_payment->items};
     my %pat       = $invoice_for_advance_payment->calculate_prices_and_taxes;
     my $taxamount = sum0 values %{ $pat{taxes_by_tax_id} };
 
-    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_$_"} },              $invoice_for_advance_payment->$_) for qw(invnumber transdate);
-    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_amount_nofmt"} },    $invoice_for_advance_payment->amount);
-    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_amount"} },          $invoice_for_advance_payment->amount_as_number);
-    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_taxamount_nofmt"} }, $taxamount);
-    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_taxamount"} },       $form->format_amount($myconfig, $taxamount, 2));
+    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_$_"} },                $invoice_for_advance_payment->$_) for qw(invnumber transdate);
+    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_amount_nofmt"} },      $invoice_for_advance_payment->amount);
+    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_amount"} },            $invoice_for_advance_payment->amount_as_number);
+    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_taxamount_nofmt"} },   $taxamount);
+    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_taxamount"} },         $form->format_amount($myconfig, $taxamount, 2));
 
-    $form->{iap_amount_nofmt}    += $invoice_for_advance_payment->amount;
-    $form->{iap_taxamount_nofmt} += $taxamount;
-    $form->{iap_existing}         = 1;
+    my $open_amount = $form->round_amount($invoice_for_advance_payment->open_amount, 2);
+    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_open_amount_nofmt"} }, $open_amount);
+    push(@{ $form->{TEMPLATE_ARRAYS}->{"iap_open_amount"} },       $form->format_amount($myconfig, $open_amount, 2));
+
+    $form->{iap_amount_nofmt}      += $invoice_for_advance_payment->amount;
+    $form->{iap_taxamount_nofmt}   += $taxamount;
+    $form->{iap_open_amount_nofmt} += $open_amount;
+    $form->{iap_existing}           = 1;
   }
-  $form->{iap_amount}    = $form->format_amount($myconfig, $form->{iap_amount_nofmt},    2);
-  $form->{iap_taxamount} = $form->format_amount($myconfig, $form->{iap_taxamount_nofmt}, 2);
+  $form->{iap_amount}      = $form->format_amount($myconfig, $form->{iap_amount_nofmt},      2);
+  $form->{iap_taxamount}   = $form->format_amount($myconfig, $form->{iap_taxamount_nofmt},   2);
+  $form->{iap_open_amount} = $form->format_amount($myconfig, $form->{iap_open_amount_nofmt}, 2);
 
   $main::lxdebug->leave_sub();
 }
@@ -734,6 +745,8 @@ sub _post_invoice {
 
   my $all_units = AM->retrieve_units($myconfig, $form);
 
+  my $already_booked = !!$form->{id};
+
   if (!$payments_only) {
     if ($form->{storno}) {
       _delete_transfers($dbh, $form, $form->{storno_id});
@@ -1059,20 +1072,31 @@ SQL
   # entsprechend auch beim Bestimmen des Steuerschlüssels in Taxkey.pm berücksichtigen
   my $taxdate = $form->{tax_point} ||$form->{deliverydate} || $form->{invdate};
 
-  # better type? maybe define Invoice->invoice_type
-  if ($form->{type} ne 'invoice_for_advance_payment') {
+  # Sanity checks for invoices for advance payment and final invoices
+  my $advance_payment_clearing_chart;
+  if (any { $_ eq $form->{type} } qw(invoice_for_advance_payment final_invoice)) {
+    $advance_payment_clearing_chart = SL::DB::Chart->new(id => $::instance_conf->get_advance_payment_clearing_chart_id)->load;
+    die "No Clearing Chart for Advance Payment" unless ref $advance_payment_clearing_chart eq 'SL::DB::Chart';
+
+    my @current_taxaccounts = (split(/ /, $form->{taxaccounts}));
+    die 'Wrong call: Cannot post invoice for advance payment or final invoice with more than one tax' if (scalar @current_taxaccounts > 1);
+
+    my @trans_ids = keys %{ $form->{amount} };
+    if (scalar @trans_ids > 1) {
+      require Data::Dumper;
+      die "Invalid state for advance payment more than one trans_id " . Dumper($form->{amount});
+    }
+  }
+
+  my $iap_amounts;
+  if ($form->{type} eq 'final_invoice') {
     my $invoices_for_advance_payment = $self->_get_invoices_for_advance_payment($form->{convert_from_ar_ids} || $form->{id});
     if (scalar @$invoices_for_advance_payment > 0) {
       # reverse booking for invoices for advance payment
-      my $clearing_chart = SL::DB::Chart->new(id => $::instance_conf->get_advance_payment_clearing_chart_id)->load;
-      die "No Clearing Chart for Advance Payment" unless ref $clearing_chart eq 'SL::DB::Chart';
       foreach my $invoice_for_advance_payment (@$invoices_for_advance_payment) {
         # delete ?
         # --> is implemented below (bookings are marked in memo field)
         #
-        # post twice case ?
-        # ?
-        #
         # TODO: helper table acc_trans_advance_payment
         # trans_id for final invoice connects to acc_trans_id here
         # my $booking = SL::DB::AccTrans->new( ...)
@@ -1084,36 +1108,47 @@ SQL
         #     if deletion of final invoice is allowed, reverting bookings in invoices
         #     for advance payment are allowed, too.
         # $booking->id, $self->id in helper table
-        $form->{amount}->{$invoice_for_advance_payment->id}->{$clearing_chart->accno} = -1 * $invoice_for_advance_payment->netamount;
-        $form->{memo}  ->{$invoice_for_advance_payment->id}->{$clearing_chart->accno} = 'reverse booking by final invoice';
-        # AR
-        $form->{amount}->{$invoice_for_advance_payment->id}->{$form->{AR}} = $invoice_for_advance_payment->netamount;
-        $form->{memo}  ->{$invoice_for_advance_payment->id}->{$form->{AR}} = 'reverse booking by final invoice';
-      }
-    }
-  }
-  if ($form->{type} eq 'invoice_for_advance_payment') {
-    # sanity and decomplex, allow only one tax rate
-    my $clearing_chart = SL::DB::Chart->new(id => $::instance_conf->get_advance_payment_clearing_chart_id)->load;
-    die "No Clearing Chart for Advance Payment" unless ref $clearing_chart eq 'SL::DB::Chart';
+        if (!$already_booked) {
+          $form->{amount}->{$invoice_for_advance_payment->id}->{$advance_payment_clearing_chart->accno} = -1 * $invoice_for_advance_payment->netamount;
+          $form->{memo}  ->{$invoice_for_advance_payment->id}->{$advance_payment_clearing_chart->accno} = 'reverse booking by final invoice';
+          # AR
+          $form->{amount}->{$invoice_for_advance_payment->id}->{$form->{AR}} = $invoice_for_advance_payment->netamount;
+          $form->{memo}  ->{$invoice_for_advance_payment->id}->{$form->{AR}} = 'reverse booking by final invoice';
+        }
 
-    my @current_taxaccounts = (split(/ /, $form->{taxaccounts}));
-    die 'Wrong Call, cannot post invoice for advance payment with more than one tax' if (scalar @current_taxaccounts > 1);
+        # VAT for invoices for advance payment is booked on payment of these. So do not book this VAT for final invoice.
+        # And book the amount of the invoices for advance payment with taxkey 0 (see below).
+        # Collect amounts and VAT of invoices for advance payment.
 
-    my @trans_ids = keys %{ $form->{amount} };
-    if (scalar @trans_ids > 1) {
-      require Data::Dumper;
-      die "Invalid state for advance payment more than one trans_id " . Dumper($form->{amount});
+        # Set sellprices to fxsellprices for items, because
+        # the PriceTaxCalculator sets fxsellprice from sellprice before calculating.
+        $_->sellprice($_->fxsellprice) for @{$invoice_for_advance_payment->items};
+        my %pat = $invoice_for_advance_payment->calculate_prices_and_taxes;
+
+        foreach my $tax_chart_id (keys %{ $pat{taxes_by_chart_id} }) {
+          my $tax_accno = SL::DB::Chart->load_cached($tax_chart_id)->accno;
+          $form->{amount}{ $form->{id} }{$tax_accno}  -= $pat{taxes_by_chart_id}->{$tax_chart_id};
+          $form->{amount}{ $form->{id} }{$form->{AR}} += $pat{taxes_by_chart_id}->{$tax_chart_id};
+        }
+
+        foreach my $amount_chart_id (keys %{ $pat{amounts} }) {
+          my $amount_accno = SL::DB::Chart->load_cached($amount_chart_id)->accno;
+          $iap_amounts->{$amount_accno}                 += $pat{amounts}->{$amount_chart_id}->{amount};
+          $form->{amount}{ $form->{id} }{$amount_accno} -= $pat{amounts}->{$amount_chart_id}->{amount};
+        }
+      }
     }
+  }
 
+  if ($form->{type} eq 'invoice_for_advance_payment') {
     # get gross and move to clearing chart - delete everything else
     # 1. gross
-    my $gross = $form->{amount}{$trans_ids[0]}{$form->{AR}};
+    my $gross = $form->{amount}{ $form->{id} }{$form->{AR}};
     # 2. destroy
-    undef $form->{amount}{$trans_ids[0]};
+    undef $form->{amount}{ $form->{id} };
     # 3. rebuild
-    $form->{amount}{$trans_ids[0]}{$form->{AR}}            = $gross;
-    $form->{amount}{$trans_ids[0]}{$clearing_chart->accno} = $gross * -1;
+    $form->{amount}{ $form->{id} }{$form->{AR}}            = $gross;
+    $form->{amount}{ $form->{id} }{$advance_payment_clearing_chart->accno} = $gross * -1;
     # 4. no cogs, hopefully not commonly used at all
     undef $form->{amount_cogs};
   }
@@ -1218,6 +1253,17 @@ SQL
     }
   }
 
+  # Book the amount of the invoices for advance payment with taxkey 0 (see below).
+  if ($form->{type} eq 'final_invoice' && $iap_amounts) {
+    foreach my $accno (keys %$iap_amounts) {
+      $query =
+        qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, tax_id, taxkey, project_id, chart_link)
+        VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, (SELECT id FROM tax WHERE taxkey=0), 0, ?, (SELECT link FROM chart WHERE accno = ?))|;
+      @values = (conv_i($form->{id}), $accno, $iap_amounts->{$accno}, conv_date($form->{invdate}), conv_i($project_id), $accno);
+      do_query($form, $dbh, $query, @values);
+    }
+  }
+
   # deduct payment differences from diff
   for my $i (1 .. $form->{paidaccounts}) {
     if ($form->{"paid_$i"} != 0) {