1 #=====================================================================
 
   4 # Based on SQL-Ledger Version 2.1.9
 
   5 # Web http://www.lx-office.org
 
   7 #=====================================================================
 
   8 # SQL-Ledger Accounting
 
   9 # Copyright (C) 1998-2002
 
  11 #  Author: Dieter Simader
 
  12 #   Email: dsimader@sql-ledger.org
 
  13 #     Web: http://www.sql-ledger.org
 
  17 # This program is free software; you can redistribute it and/or modify
 
  18 # it under the terms of the GNU General Public License as published by
 
  19 # the Free Software Foundation; either version 2 of the License, or
 
  20 # (at your option) any later version.
 
  22 # This program is distributed in the hope that it will be useful,
 
  23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  25 # GNU General Public License for more details.
 
  26 # You should have received a copy of the GNU General Public License
 
  27 # along with this program; if not, write to the Free Software
 
  28 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
  29 #======================================================================
 
  31 # Inventory invoicing module
 
  33 #======================================================================
 
  39 use List::Util qw(max);
 
  52   $main::lxdebug->enter_sub();
 
  54   my ($self, $myconfig, $form, $locale) = @_;
 
  56   $form->{duedate} ||= $form->{invdate};
 
  59   my $dbh = $form->dbconnect($myconfig);
 
  62   my $query = qq|SELECT date | . conv_dateq($form->{duedate}) . qq| - date | . conv_dateq($form->{invdate}) . qq| AS terms|;
 
  63   ($form->{terms}) = selectrow_query($form, $dbh, $query);
 
  65   my (@project_ids, %projectnumbers);
 
  67   push(@project_ids, $form->{"globalproject_id"}) if ($form->{"globalproject_id"});
 
  69   $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
 
  72   foreach my $pfac (@{ $form->{ALL_PRICE_FACTORS} }) {
 
  73     $price_factors{$pfac->{id}}  = $pfac;
 
  75     $pfac->{formatted_factor}    = $form->format_amount($myconfig, $pfac->{factor});
 
  78   # sort items by partsgroup
 
  79   for my $i (1 .. $form->{rowcount}) {
 
  81 #    if ($form->{"partsgroup_$i"} && $form->{groupitems}) {
 
  82 #      $partsgroup = $form->{"partsgroup_$i"};
 
  84 #    push @partsgroup, [$i, $partsgroup];
 
  85     push(@project_ids, $form->{"project_id_$i"}) if ($form->{"project_id_$i"});
 
  89     $query = "SELECT id, projectnumber FROM project WHERE id IN (" .
 
  90       join(", ", map({ "?" } @project_ids)) . ")";
 
  91     $sth = $dbh->prepare($query);
 
  92     $sth->execute(@project_ids) ||
 
  93       $form->dberror($query . " (" . join(", ", @project_ids) . ")");
 
  94     while (my $ref = $sth->fetchrow_hashref()) {
 
  95       $projectnumbers{$ref->{id}} = $ref->{projectnumber};
 
 100   $form->{"globalprojectnumber"} =
 
 101     $projectnumbers{$form->{"globalproject_id"}};
 
 108   my %oid = ('Pg'     => 'oid',
 
 109              'Oracle' => 'rowid');
 
 111   # sort items by partsgroup
 
 112   for $i (1 .. $form->{rowcount}) {
 
 114     if ($form->{"partsgroup_$i"} && $form->{groupitems}) {
 
 115       $partsgroup = $form->{"partsgroup_$i"};
 
 117     push @partsgroup, [$i, $partsgroup];
 
 130   my $nodiscount_subtotal = 0;
 
 131   my $discount_subtotal = 0;
 
 133   my $subtotal_header = 0;
 
 136   $form->{discount} = [];
 
 138   IC->prepare_parts_for_printing();
 
 141     qw(runningnumber number description longdescription qty ship unit bin
 
 142        deliverydate_oe ordnumber_oe transdate_oe licensenumber validuntil
 
 143        partnotes serialnumber reqdate sellprice listprice netprice
 
 144        discount p_discount discount_sub nodiscount_sub
 
 145        linetotal  nodiscount_linetotal tax_rate projectnumber
 
 146        price_factor price_factor_name partsgroup);
 
 149     qw(taxbase tax taxdescription taxrate taxnumber);
 
 151   foreach $item (sort { $a->[1] cmp $b->[1] } @partsgroup) {
 
 154     if ($item->[1] ne $sameitem) {
 
 155       push(@{ $form->{description} }, qq|$item->[1]|);
 
 156       $sameitem = $item->[1];
 
 158       map({ push(@{ $form->{$_} }, "") } grep({ $_ ne "description" } @arrays));
 
 161     $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
 
 163     if ($form->{"id_$i"} != 0) {
 
 165       # add number, description and qty to $form->{number},
 
 166       if ($form->{"subtotal_$i"} && !$subtotal_header) {
 
 167         $subtotal_header = $i;
 
 168         $position = int($position);
 
 171       } elsif ($subtotal_header) {
 
 173         $position = int($position);
 
 174         $position = $position.".".$subposition;
 
 176         $position = int($position);
 
 180       my $price_factor = $price_factors{$form->{"price_factor_id_$i"}} || { 'factor' => 1 };
 
 182       push @{ $form->{runningnumber} },     $position;
 
 183       push @{ $form->{number} },            $form->{"partnumber_$i"};
 
 184       push @{ $form->{serialnumber} },      $form->{"serialnumber_$i"};
 
 185       push @{ $form->{bin} },               $form->{"bin_$i"};
 
 186       push @{ $form->{"partnotes"} },       $form->{"partnotes_$i"};
 
 187       push @{ $form->{description} },       $form->{"description_$i"};
 
 188       push @{ $form->{longdescription} },   $form->{"longdescription_$i"};
 
 189       push @{ $form->{qty} },               $form->format_amount($myconfig, $form->{"qty_$i"});
 
 190       push @{ $form->{unit} },              $form->{"unit_$i"};
 
 191       push @{ $form->{deliverydate_oe} },   $form->{"deliverydate_$i"};
 
 192       push @{ $form->{sellprice} },         $form->{"sellprice_$i"};
 
 193       push @{ $form->{ordnumber_oe} },      $form->{"ordnumber_$i"};
 
 194       push @{ $form->{transdate_oe} },      $form->{"transdate_$i"};
 
 195       push @{ $form->{invnumber} },         $form->{"invnumber"};
 
 196       push @{ $form->{invdate} },           $form->{"invdate"};
 
 197       push @{ $form->{price_factor} },      $price_factor->{formatted_factor};
 
 198       push @{ $form->{price_factor_name} }, $price_factor->{description};
 
 199       push @{ $form->{partsgroup} },        $form->{"partsgroup_$i"};
 
 201       if ($form->{lizenzen}) {
 
 202         if ($form->{"licensenumber_$i"}) {
 
 203           $query = qq|SELECT licensenumber, validuntil FROM license WHERE id = ?|;
 
 204           my ($licensenumber, $validuntil) = selectrow_query($form, $dbh, $query, conv_i($form->{"licensenumber_$i"}));
 
 205           push(@{ $form->{licensenumber} }, $licensenumber);
 
 206           push(@{ $form->{validuntil} }, $locale->date($myconfig, $validuntil, 0));
 
 209           push(@{ $form->{licensenumber} }, "");
 
 210           push(@{ $form->{validuntil} },    "");
 
 215       push(@{ $form->{listprice} }, $form->{"listprice_$i"});
 
 217       my $sellprice     = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
 
 218       my ($dec)         = ($sellprice =~ /\.(\d+)/);
 
 219       my $decimalplaces = max 2, length($dec);
 
 221       my $parsed_discount      = $form->parse_amount($myconfig, $form->{"discount_$i"});
 
 222       my $linetotal_exact      =                     $form->{"qty_$i"} * $sellprice * (100 - $parsed_discount) / 100 / $price_factor->{factor};
 
 223       my $linetotal            = $form->round_amount($linetotal_exact, 2);
 
 224       my $discount             = $form->round_amount($form->{"qty_$i"} * $sellprice * $parsed_discount / 100 / $price_factor->{factor} - ($linetotal - $linetotal_exact),
 
 226       my $nodiscount_linetotal = $form->round_amount($form->{"qty_$i"} * $sellprice / $price_factor->{factor}, 2);
 
 227       $form->{"netprice_$i"}   = $form->round_amount($form->{"qty_$i"} ? ($linetotal / $form->{"qty_$i"}) : 0, 2);
 
 229       push @{ $form->{netprice} }, ($form->{"netprice_$i"} != 0) ? $form->format_amount($myconfig, $form->{"netprice_$i"}, $decimalplaces) : '';
 
 231       $linetotal = ($linetotal != 0) ? $linetotal : '';
 
 233       push @{ $form->{discount} },   ($discount  != 0) ? $form->format_amount($myconfig, $discount * -1, 2) : '';
 
 234       push @{ $form->{p_discount} }, $form->{"discount_$i"};
 
 236       $form->{total}            += $linetotal;
 
 237       $form->{nodiscount_total} += $nodiscount_linetotal;
 
 238       $form->{discount_total}   += $discount;
 
 240       if ($subtotal_header) {
 
 241         $discount_subtotal   += $linetotal;
 
 242         $nodiscount_subtotal += $nodiscount_linetotal;
 
 245       if ($form->{"subtotal_$i"} && $subtotal_header && ($subtotal_header != $i)) {
 
 246         push @{ $form->{discount_sub} },   $form->format_amount($myconfig, $discount_subtotal,   2);
 
 247         push @{ $form->{nodiscount_sub} }, $form->format_amount($myconfig, $nodiscount_subtotal, 2);
 
 249         $discount_subtotal   = 0;
 
 250         $nodiscount_subtotal = 0;
 
 251         $subtotal_header     = 0;
 
 254         push @{ $form->{discount_sub} },   "";
 
 255         push @{ $form->{nodiscount_sub} }, "";
 
 258       if (!$form->{"discount_$i"}) {
 
 259         $nodiscount += $linetotal;
 
 262       push @{ $form->{linetotal} }, $form->format_amount($myconfig, $linetotal, 2);
 
 263       push @{ $form->{nodiscount_linetotal} }, $form->format_amount($myconfig, $nodiscount_linetotal, 2);
 
 265       push(@{ $form->{projectnumber} }, $projectnumbers{$form->{"project_id_$i"}});
 
 267       @taxaccounts = split(/ /, $form->{"taxaccounts_$i"});
 
 271       map { $taxrate += $form->{"${_}_rate"} } @taxaccounts;
 
 273       if ($form->{taxincluded}) {
 
 276         $taxamount = $linetotal * $taxrate / (1 + $taxrate);
 
 277         $taxbase = $linetotal - $taxamount;
 
 279         $taxamount = $linetotal * $taxrate;
 
 280         $taxbase   = $linetotal;
 
 283       if ($form->round_amount($taxrate, 7) == 0) {
 
 284         if ($form->{taxincluded}) {
 
 285           foreach my $accno (@taxaccounts) {
 
 286             $taxamount            = $form->round_amount($linetotal * $form->{"${accno}_rate"} / (1 + abs($form->{"${accno}_rate"})), 2);
 
 288             $taxaccounts{$accno} += $taxamount;
 
 289             $taxdiff             += $taxamount;
 
 291             $taxbase{$accno}     += $taxbase;
 
 293           $taxaccounts{ $taxaccounts[0] } += $taxdiff;
 
 295           foreach my $accno (@taxaccounts) {
 
 296             $taxaccounts{$accno} += $linetotal * $form->{"${accno}_rate"};
 
 297             $taxbase{$accno}     += $taxbase;
 
 301         foreach my $accno (@taxaccounts) {
 
 302           $taxaccounts{$accno} += $taxamount * $form->{"${accno}_rate"} / $taxrate;
 
 303           $taxbase{$accno}     += $taxbase;
 
 306       my $tax_rate = $taxrate * 100;
 
 307       push(@{ $form->{tax_rate} }, qq|$tax_rate|);
 
 308       if ($form->{"assembly_$i"}) {
 
 311         # get parts and push them onto the stack
 
 313         if ($form->{groupitems}) {
 
 315             qq|ORDER BY pg.partsgroup, a.$oid{$myconfig->{dbdriver}}|;
 
 317           $sortorder = qq|ORDER BY a.$oid{$myconfig->{dbdriver}}|;
 
 321           qq|SELECT p.partnumber, p.description, p.unit, a.qty, pg.partsgroup
 
 323              JOIN parts p ON (a.parts_id = p.id)
 
 324              LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
 325              WHERE (a.bom = '1') AND (a.id = ?) $sortorder|;
 
 326         $sth = prepare_execute_query($form, $dbh, $query, conv_i($form->{"id_$i"}));
 
 328         while (my $ref = $sth->fetchrow_hashref('NAME_lc')) {
 
 329           if ($form->{groupitems} && $ref->{partsgroup} ne $sameitem) {
 
 330             map({ push(@{ $form->{$_} }, "") } grep({ $_ ne "description" } @arrays));
 
 331             $sameitem = ($ref->{partsgroup}) ? $ref->{partsgroup} : "--";
 
 332             push(@{ $form->{description} }, $sameitem);
 
 335           map { $form->{"a_$_"} = $ref->{$_} } qw(partnumber description);
 
 337           push(@{ $form->{description} },
 
 338                $form->format_amount($myconfig, $ref->{qty} * $form->{"qty_$i"}
 
 340                  . qq| -- $form->{"a_partnumber"}, $form->{"a_description"}|);
 
 341           map({ push(@{ $form->{$_} }, "") } grep({ $_ ne "description" } @arrays));
 
 349   foreach my $item (sort keys %taxaccounts) {
 
 350     push(@{ $form->{taxbase} },
 
 351           $form->format_amount($myconfig, $taxbase{$item}, 2));
 
 353     $tax += $taxamount = $form->round_amount($taxaccounts{$item}, 2);
 
 355     push(@{ $form->{tax} }, $form->format_amount($myconfig, $taxamount, 2));
 
 356     push(@{ $form->{taxdescription} }, $form->{"${item}_description"}  . q{ } . 100 * $form->{"${item}_rate"} . q{%});
 
 357     push(@{ $form->{taxrate} },
 
 358           $form->format_amount($myconfig, $form->{"${item}_rate"} * 100));
 
 359     push(@{ $form->{taxnumber} }, $form->{"${item}_taxnumber"});
 
 362   for my $i (1 .. $form->{paidaccounts}) {
 
 363     if ($form->{"paid_$i"}) {
 
 364       push(@{ $form->{payment} }, $form->{"paid_$i"});
 
 365       my ($accno, $description) = split(/--/, $form->{"AR_paid_$i"});
 
 366       push(@{ $form->{paymentaccount} }, $description);
 
 367       push(@{ $form->{paymentdate} },    $form->{"datepaid_$i"});
 
 368       push(@{ $form->{paymentsource} },  $form->{"source_$i"});
 
 370       $form->{paid} += $form->parse_amount($myconfig, $form->{"paid_$i"});
 
 373   if($form->{taxincluded}) {
 
 374     $form->{subtotal} = $form->format_amount($myconfig, $form->{total} - $tax, 2);
 
 377     $form->{subtotal} = $form->format_amount($myconfig, $form->{total}, 2);
 
 380   $form->{nodiscount_subtotal} = $form->format_amount($myconfig, $form->{nodiscount_total}, 2);
 
 381   $form->{discount_total}      = $form->format_amount($myconfig, $form->{discount_total}, 2);
 
 382   $form->{nodiscount}          = $form->format_amount($myconfig, $nodiscount, 2);
 
 383   $form->{yesdiscount}         = $form->format_amount($myconfig, $form->{nodiscount_total} - $nodiscount, 2);
 
 385   $form->{invtotal} = ($form->{taxincluded}) ? $form->{total} : $form->{total} + $tax;
 
 386   $form->{total}    = $form->format_amount($myconfig, $form->{invtotal} - $form->{paid}, 2);
 
 388   $form->{invtotal} = $form->format_amount($myconfig, $form->{invtotal}, 2);
 
 389   $form->{paid}     = $form->format_amount($myconfig, $form->{paid}, 2);
 
 391   $form->set_payment_options($myconfig, $form->{invdate});
 
 393   $form->{username} = $myconfig->{name};
 
 397   $main::lxdebug->leave_sub();
 
 400 sub project_description {
 
 401   $main::lxdebug->enter_sub();
 
 403   my ($self, $dbh, $id) = @_;
 
 404   my $form = \%main::form;
 
 406   my $query = qq|SELECT description FROM project WHERE id = ?|;
 
 407   my ($description) = selectrow_query($form, $dbh, $query, conv_i($id));
 
 409   $main::lxdebug->leave_sub();
 
 414 sub customer_details {
 
 415   $main::lxdebug->enter_sub();
 
 417   my ($self, $myconfig, $form, @wanted_vars) = @_;
 
 419   # connect to database
 
 420   my $dbh = $form->dbconnect($myconfig);
 
 422   # get contact id, set it if nessessary
 
 425   my @values =  (conv_i($form->{customer_id}));
 
 428   if ($form->{cp_id}) {
 
 429     $where = qq| AND (cp.cp_id = ?) |;
 
 430     push(@values, conv_i($form->{cp_id}));
 
 433   # get rest for the customer
 
 435     qq|SELECT ct.*, cp.*, ct.notes as customernotes,
 
 436          ct.phone AS customerphone, ct.fax AS customerfax, ct.email AS customeremail
 
 438        LEFT JOIN contacts cp on ct.id = cp.cp_cv_id
 
 439        WHERE (ct.id = ?) $where
 
 442   my $ref = selectfirst_hashref_query($form, $dbh, $query, @values);
 
 444   # remove id and taxincluded before copy back
 
 445   delete @$ref{qw(id taxincluded)};
 
 447   @wanted_vars = grep({ $_ } @wanted_vars);
 
 448   if (scalar(@wanted_vars) > 0) {
 
 450     map({ $h_wanted_vars{$_} = 1; } @wanted_vars);
 
 451     map({ delete($ref->{$_}) unless ($h_wanted_vars{$_}); } keys(%{$ref}));
 
 454   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
 456   if ($form->{delivery_customer_id}) {
 
 458       qq|SELECT *, notes as customernotes
 
 462     $ref = selectfirst_hashref_query($form, $dbh, $query, conv_i($form->{delivery_customer_id}));
 
 464     map { $form->{"dc_$_"} = $ref->{$_} } keys %$ref;
 
 467   if ($form->{delivery_vendor_id}) {
 
 469       qq|SELECT *, notes as customernotes
 
 473     $ref = selectfirst_hashref_query($form, $dbh, $query, conv_i($form->{delivery_vendor_id}));
 
 475     map { $form->{"dv_$_"} = $ref->{$_} } keys %$ref;
 
 478   my $custom_variables = CVar->get_custom_variables('dbh'      => $dbh,
 
 480                                                     'trans_id' => $form->{customer_id});
 
 481   map { $form->{"vc_cvar_$_->{name}"} = $_->{value} } @{ $custom_variables };
 
 485   $main::lxdebug->leave_sub();
 
 489   $main::lxdebug->enter_sub();
 
 491   my ($self, $myconfig, $form, $provided_dbh, $payments_only) = @_;
 
 493   # connect to database, turn off autocommit
 
 494   my $dbh = $provided_dbh ? $provided_dbh : $form->dbconnect_noauto($myconfig);
 
 496   my ($query, $sth, $null, $project_id, @values);
 
 497   my $exchangerate = 0;
 
 499   if (!$form->{employee_id}) {
 
 500     $form->get_employee($dbh);
 
 503   $form->{defaultcurrency} = $form->get_default_currency($myconfig);
 
 505   ($null, $form->{department_id}) = split(/--/, $form->{department});
 
 507   my $all_units = AM->retrieve_units($myconfig, $form);
 
 509   if (!$payments_only) {
 
 511       &reverse_invoice($dbh, $form);
 
 514       $query = qq|SELECT nextval('glid')|;
 
 515       ($form->{"id"}) = selectrow_query($form, $dbh, $query);
 
 517       $query = qq|INSERT INTO ar (id, invnumber) VALUES (?, ?)|;
 
 518       do_query($form, $dbh, $query, $form->{"id"}, $form->{"id"});
 
 520       if (!$form->{invnumber}) {
 
 522           $form->update_defaults($myconfig, $form->{type} eq "credit_note" ?
 
 523                                  "cnnumber" : "invnumber", $dbh);
 
 528   my ($netamount, $invoicediff) = (0, 0);
 
 529   my ($amount, $linetotal, $lastincomeaccno);
 
 531   my ($currencies)    = selectfirst_array_query($form, $dbh, qq|SELECT curr FROM defaults|);
 
 532   my $defaultcurrency = (split m/:/, $currencies)[0];
 
 534   if ($form->{currency} eq $defaultcurrency) {
 
 535     $form->{exchangerate} = 1;
 
 537     $exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, 'buy');
 
 540   $form->{exchangerate} =
 
 543     : $form->parse_amount($myconfig, $form->{exchangerate});
 
 545   $form->{expense_inventory} = "";
 
 549   $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS');
 
 550   my %price_factors = map { $_->{id} => $_->{factor} } @{ $form->{ALL_PRICE_FACTORS} };
 
 553   $form->{amount_cogs} = {};
 
 555   foreach my $i (1 .. $form->{rowcount}) {
 
 556     if ($form->{type} eq "credit_note") {
 
 557       $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"}) * -1;
 
 558       $form->{shipped} = 1;
 
 560       $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
 
 565     $form->{"marge_percent_$i"} = $form->parse_amount($myconfig, $form->{"marge_percent_$i"}) * 1;
 
 566     $form->{"marge_total_$i"} = $form->parse_amount($myconfig, $form->{"marge_total_$i"}) * 1;
 
 567     $form->{"lastcost_$i"} = $form->{"lastcost_$i"} * 1;
 
 569     if ($form->{storno}) {
 
 570       $form->{"qty_$i"} *= -1;
 
 573     if ($form->{"id_$i"}) {
 
 576       if (defined($baseunits{$form->{"id_$i"}})) {
 
 577         $item_unit = $baseunits{$form->{"id_$i"}};
 
 580         $query = qq|SELECT unit FROM parts WHERE id = ?|;
 
 581         ($item_unit) = selectrow_query($form, $dbh, $query, conv_i($form->{"id_$i"}));
 
 582         $baseunits{$form->{"id_$i"}} = $item_unit;
 
 585       if (defined($all_units->{$item_unit}->{factor})
 
 586           && ($all_units->{$item_unit}->{factor} ne '')
 
 587           && ($all_units->{$item_unit}->{factor} != 0)) {
 
 588         $basefactor = $all_units->{$form->{"unit_$i"}}->{factor} / $all_units->{$item_unit}->{factor};
 
 592       $baseqty = $form->{"qty_$i"} * $basefactor;
 
 594       my ($allocated, $taxrate) = (0, 0);
 
 598       map { $taxrate += $form->{"${_}_rate"} } split(/ /, $form->{"taxaccounts_$i"});
 
 600       # keep entered selling price
 
 602         $form->parse_amount($myconfig, $form->{"sellprice_$i"});
 
 604       my ($dec) = ($fxsellprice =~ /\.(\d+)/);
 
 606       my $decimalplaces = ($dec > 2) ? $dec : 2;
 
 608       # undo discount formatting
 
 609       $form->{"discount_$i"} = $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100;
 
 612       $form->{"sellprice_$i"} = $fxsellprice * (1 - $form->{"discount_$i"});
 
 614       # round linetotal to 2 decimal places
 
 615       $price_factor = $price_factors{ $form->{"price_factor_id_$i"} } || 1;
 
 616       $linetotal    = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor, 2);
 
 618       if ($form->{taxincluded}) {
 
 619         $taxamount = $linetotal * ($taxrate / (1 + $taxrate));
 
 620         $form->{"sellprice_$i"} =
 
 621           $form->{"sellprice_$i"} * (1 / (1 + $taxrate));
 
 623         $taxamount = $linetotal * $taxrate;
 
 626       $netamount += $linetotal;
 
 628       if ($taxamount != 0) {
 
 630           $form->{amount}{ $form->{id} }{$_} +=
 
 631             $taxamount * $form->{"${_}_rate"} / $taxrate
 
 632         } split(/ /, $form->{"taxaccounts_$i"});
 
 635       # add amount to income, $form->{amount}{trans_id}{accno}
 
 636       $amount = $form->{"sellprice_$i"} * $form->{"qty_$i"} * $form->{exchangerate} / $price_factor;
 
 638       $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"} / $price_factor, 2) * $form->{exchangerate};
 
 639       $linetotal = $form->round_amount($linetotal, 2);
 
 641       # this is the difference from the inventory
 
 642       $invoicediff += ($amount - $linetotal);
 
 644       $form->{amount}{ $form->{id} }{ $form->{"income_accno_$i"} } +=
 
 647       $lastincomeaccno = $form->{"income_accno_$i"};
 
 649       # adjust and round sellprice
 
 650       $form->{"sellprice_$i"} =
 
 651         $form->round_amount($form->{"sellprice_$i"} * $form->{exchangerate},
 
 654       next if $payments_only;
 
 656       if ($form->{"inventory_accno_$i"} || $form->{"assembly_$i"}) {
 
 658         if ($form->{"assembly_$i"}) {
 
 659           # record assembly item as allocated
 
 660           &process_assembly($dbh, $form, $form->{"id_$i"}, $baseqty);
 
 663           $allocated = &cogs($dbh, $form, $form->{"id_$i"}, $baseqty, $basefactor, $i);
 
 667       # get pricegroup_id and save it
 
 668       ($null, my $pricegroup_id) = split(/--/, $form->{"sellprice_pg_$i"});
 
 671       # save detail record in invoice table
 
 673         qq|INSERT INTO invoice (trans_id, parts_id, description, longdescription, qty,
 
 674                                 sellprice, fxsellprice, discount, allocated, assemblyitem,
 
 675                                 unit, deliverydate, project_id, serialnumber, pricegroup_id,
 
 676                                 ordnumber, transdate, cusordnumber, base_qty, subtotal,
 
 677                                 marge_percent, marge_total, lastcost,
 
 678                                 price_factor_id, price_factor, marge_price_factor)
 
 679            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
 
 680                    (SELECT factor FROM price_factors WHERE id = ?), ?)|;
 
 682       @values = (conv_i($form->{id}), conv_i($form->{"id_$i"}),
 
 683                  $form->{"description_$i"}, $form->{"longdescription_$i"}, $form->{"qty_$i"},
 
 684                  $form->{"sellprice_$i"}, $fxsellprice,
 
 685                  $form->{"discount_$i"}, $allocated, 'f',
 
 686                  $form->{"unit_$i"}, conv_date($form->{"reqdate_$i"}), conv_i($form->{"project_id_$i"}),
 
 687                  $form->{"serialnumber_$i"}, conv_i($pricegroup_id),
 
 688                  $form->{"ordnumber_$i"}, conv_date($form->{"transdate_$i"}),
 
 689                  $form->{"cusordnumber_$i"}, $baseqty, $form->{"subtotal_$i"} ? 't' : 'f',
 
 690                  $form->{"marge_percent_$i"}, $form->{"marge_total_$i"},
 
 691                  $form->{"lastcost_$i"},
 
 692                  conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
 
 693                  conv_i($form->{"marge_price_factor_$i"}));
 
 694       do_query($form, $dbh, $query, @values);
 
 696       if ($form->{lizenzen} && $form->{"licensenumber_$i"}) {
 
 698           qq|INSERT INTO licenseinvoice (trans_id, license_id)
 
 699              VALUES ((SELECT id FROM invoice WHERE trans_id = ? ORDER BY oid DESC LIMIT 1), ?)|;
 
 700         @values = (conv_i($form->{"id"}), conv_i($form->{"licensenumber_$i"}));
 
 701         do_query($form, $dbh, $query, @values);
 
 706   $form->{datepaid} = $form->{invdate};
 
 708   # total payments, don't move we need it here
 
 709   for my $i (1 .. $form->{paidaccounts}) {
 
 710     if ($form->{type} eq "credit_note") {
 
 711       $form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"}) * -1;
 
 713       $form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"});
 
 715     $form->{paid} += $form->{"paid_$i"};
 
 716     $form->{datepaid} = $form->{"datepaid_$i"} if ($form->{"datepaid_$i"});
 
 719   my ($tax, $diff) = (0, 0);
 
 721   $netamount = $form->round_amount($netamount, 2);
 
 723   # figure out rounding errors for total amount vs netamount + taxes
 
 724   if ($form->{taxincluded}) {
 
 726     $amount = $form->round_amount($netamount * $form->{exchangerate}, 2);
 
 727     $diff += $amount - $netamount * $form->{exchangerate};
 
 728     $netamount = $amount;
 
 730     foreach my $item (split(/ /, $form->{taxaccounts})) {
 
 731       $amount = $form->{amount}{ $form->{id} }{$item} * $form->{exchangerate};
 
 732       $form->{amount}{ $form->{id} }{$item} = $form->round_amount($amount, 2);
 
 733       $tax += $form->{amount}{ $form->{id} }{$item};
 
 734       $netamount -= $form->{amount}{ $form->{id} }{$item};
 
 737     $invoicediff += $diff;
 
 738     ######## this only applies to tax included
 
 739     if ($lastincomeaccno) {
 
 740       $form->{amount}{ $form->{id} }{$lastincomeaccno} += $invoicediff;
 
 744     $amount    = $form->round_amount($netamount * $form->{exchangerate}, 2);
 
 745     $diff      = $amount - $netamount * $form->{exchangerate};
 
 746     $netamount = $amount;
 
 747     foreach my $item (split(/ /, $form->{taxaccounts})) {
 
 748       $form->{amount}{ $form->{id} }{$item} =
 
 749         $form->round_amount($form->{amount}{ $form->{id} }{$item}, 2);
 
 752                  $form->{amount}{ $form->{id} }{$item} * $form->{exchangerate},
 
 755         $amount - $form->{amount}{ $form->{id} }{$item} *
 
 756         $form->{exchangerate};
 
 757       $form->{amount}{ $form->{id} }{$item} = $form->round_amount($amount, 2);
 
 758       $tax += $form->{amount}{ $form->{id} }{$item};
 
 762   $form->{amount}{ $form->{id} }{ $form->{AR} } = $netamount + $tax;
 
 764     $form->round_amount($form->{paid} * $form->{exchangerate} + $diff, 2);
 
 767   $form->{amount}{ $form->{id} }{ $form->{AR} } *= -1;
 
 769   # update exchangerate
 
 770   if (($form->{currency} ne $defaultcurrency) && !$exchangerate) {
 
 771     $form->update_exchangerate($dbh, $form->{currency}, $form->{invdate},
 
 772                                $form->{exchangerate}, 0);
 
 775   $project_id = conv_i($form->{"globalproject_id"});
 
 777   foreach my $trans_id (keys %{ $form->{amount_cogs} }) {
 
 778     foreach my $accno (keys %{ $form->{amount_cogs}{$trans_id} }) {
 
 779       next unless ($form->{expense_inventory} =~ /\Q$accno\E/);
 
 781       $form->{amount_cogs}{$trans_id}{$accno} = $form->round_amount($form->{amount_cogs}{$trans_id}{$accno}, 2);
 
 783       if (!$payments_only && ($form->{amount_cogs}{$trans_id}{$accno} != 0)) {
 
 785           qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id)
 
 786                VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, 0, ?)|;
 
 787         @values = (conv_i($trans_id), $accno, $form->{amount_cogs}{$trans_id}{$accno}, conv_date($form->{invdate}), conv_i($project_id));
 
 788         do_query($form, $dbh, $query, @values);
 
 789         $form->{amount_cogs}{$trans_id}{$accno} = 0;
 
 793     foreach my $accno (keys %{ $form->{amount_cogs}{$trans_id} }) {
 
 794       $form->{amount_cogs}{$trans_id}{$accno} = $form->round_amount($form->{amount_cogs}{$trans_id}{$accno}, 2);
 
 796       if (!$payments_only && ($form->{amount_cogs}{$trans_id}{$accno} != 0)) {
 
 798           qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id)
 
 799                VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, 0, ?)|;
 
 800         @values = (conv_i($trans_id), $accno, $form->{amount_cogs}{$trans_id}{$accno}, conv_date($form->{invdate}), conv_i($project_id));
 
 801         do_query($form, $dbh, $query, @values);
 
 806   foreach my $trans_id (keys %{ $form->{amount} }) {
 
 807     foreach my $accno (keys %{ $form->{amount}{$trans_id} }) {
 
 808       next unless ($form->{expense_inventory} =~ /\Q$accno\E/);
 
 810       $form->{amount}{$trans_id}{$accno} = $form->round_amount($form->{amount}{$trans_id}{$accno}, 2);
 
 812       if (!$payments_only && ($form->{amount}{$trans_id}{$accno} != 0)) {
 
 814           qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id)
 
 815              VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?,
 
 816                      (SELECT taxkey_id  FROM chart WHERE accno = ?), ?)|;
 
 817         @values = (conv_i($trans_id), $accno, $form->{amount}{$trans_id}{$accno}, conv_date($form->{invdate}), $accno, conv_i($project_id));
 
 818         do_query($form, $dbh, $query, @values);
 
 819         $form->{amount}{$trans_id}{$accno} = 0;
 
 823     foreach my $accno (keys %{ $form->{amount}{$trans_id} }) {
 
 824       $form->{amount}{$trans_id}{$accno} = $form->round_amount($form->{amount}{$trans_id}{$accno}, 2);
 
 826       if (!$payments_only && ($form->{amount}{$trans_id}{$accno} != 0)) {
 
 828           qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id)
 
 829              VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?,
 
 830                      (SELECT taxkey_id FROM chart WHERE accno = ?), ?)|;
 
 831         @values = (conv_i($trans_id), $accno, $form->{amount}{$trans_id}{$accno}, conv_date($form->{invdate}), $accno, conv_i($project_id));
 
 832         do_query($form, $dbh, $query, @values);
 
 837   # deduct payment differences from diff
 
 838   for my $i (1 .. $form->{paidaccounts}) {
 
 839     if ($form->{"paid_$i"} != 0) {
 
 841         $form->round_amount($form->{"paid_$i"} * $form->{exchangerate}, 2);
 
 842       $diff -= $amount - $form->{"paid_$i"} * $form->{exchangerate};
 
 846   # record payments and offsetting AR
 
 847   if (!$form->{storno}) {
 
 848     for my $i (1 .. $form->{paidaccounts}) {
 
 850       next if ($form->{"paid_$i"} == 0);
 
 852       my ($accno) = split(/--/, $form->{"AR_paid_$i"});
 
 853       $form->{"datepaid_$i"} = $form->{invdate}
 
 854       unless ($form->{"datepaid_$i"});
 
 855       $form->{datepaid} = $form->{"datepaid_$i"};
 
 859       if ($form->{currency} eq $defaultcurrency) {
 
 860         $form->{"exchangerate_$i"} = 1;
 
 862         $exchangerate              = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'buy');
 
 863         $form->{"exchangerate_$i"} = $exchangerate || $form->parse_amount($myconfig, $form->{"exchangerate_$i"});
 
 867       $amount = $form->round_amount($form->{"paid_$i"} * $form->{exchangerate} + $diff, 2);
 
 869       if ($form->{amount}{ $form->{id} }{ $form->{AR} } != 0) {
 
 871         qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id)
 
 872            VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?,
 
 873                    (SELECT taxkey_id FROM chart WHERE accno = ?), ?)|;
 
 874         @values = (conv_i($form->{"id"}), $form->{AR}, $amount, $form->{"datepaid_$i"}, $form->{AR}, $project_id);
 
 875         do_query($form, $dbh, $query, @values);
 
 879       $form->{"paid_$i"} *= -1;
 
 882       qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, source, memo, taxkey, project_id)
 
 883          VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, ?, ?,
 
 884                  (SELECT taxkey_id FROM chart WHERE accno = ?), ?)|;
 
 885       @values = (conv_i($form->{"id"}), $accno, $form->{"paid_$i"}, $form->{"datepaid_$i"},
 
 886                  $form->{"source_$i"}, $form->{"memo_$i"}, $accno, $project_id);
 
 887       do_query($form, $dbh, $query, @values);
 
 889       # exchangerate difference
 
 890       $form->{fx}{$accno}{ $form->{"datepaid_$i"} } +=
 
 891       $form->{"paid_$i"} * ($form->{"exchangerate_$i"} - 1) + $diff;
 
 895       $form->{"paid_$i"} * $form->{exchangerate} - $form->{"paid_$i"} *
 
 896       $form->{"exchangerate_$i"};
 
 898         $form->{fx}{ $form->{fxgain_accno} }{ $form->{"datepaid_$i"} } +=
 
 901         $form->{fx}{ $form->{fxloss_accno} }{ $form->{"datepaid_$i"} } +=
 
 907       # update exchange rate
 
 908       if (($form->{currency} ne $defaultcurrency) && !$exchangerate) {
 
 909         $form->update_exchangerate($dbh, $form->{currency},
 
 910                                    $form->{"datepaid_$i"},
 
 911                                    $form->{"exchangerate_$i"}, 0);
 
 915   } else {                      # if (!$form->{storno})
 
 916     $form->{marge_total} *= -1;
 
 919   if ($payments_only) {
 
 920     $query = qq|UPDATE ar SET paid = ?, datepaid = ? WHERE id = ?|;
 
 921     do_query($form, $dbh, $query,  $form->{paid}, $form->{paid} ? conv_date($form->{datepaid}) : undef, conv_i($form->{id}));
 
 923     if (!$provided_dbh) {
 
 928     $main::lxdebug->leave_sub();
 
 932   # record exchange rate differences and gains/losses
 
 933   foreach my $accno (keys %{ $form->{fx} }) {
 
 934     foreach my $transdate (keys %{ $form->{fx}{$accno} }) {
 
 936           ($form->{fx}{$accno}{$transdate} =
 
 937            $form->round_amount($form->{fx}{$accno}{$transdate}, 2)
 
 942           qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, cleared, fx_transaction, taxkey, project_id)
 
 943              VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, '0', '1',
 
 944              (SELECT taxkey_id FROM chart WHERE accno = ?), ?)|;
 
 945         @values = (conv_i($form->{"id"}), $accno, $form->{fx}{$accno}{$transdate}, conv_date($transdate), $accno, $project_id);
 
 946         do_query($form, $dbh, $query, @values);
 
 951   $amount = $netamount + $tax;
 
 954   #erweiterung fuer lieferscheinnummer (donumber) 12.02.09 jb
 
 956   $query = qq|UPDATE ar set
 
 957                 invnumber   = ?, ordnumber     = ?, quonumber     = ?, cusordnumber  = ?,
 
 958                 transdate   = ?, orddate       = ?, quodate       = ?, customer_id   = ?,
 
 959                 amount      = ?, netamount     = ?, paid          = ?, datepaid      = ?,
 
 960                 duedate     = ?, deliverydate  = ?, invoice       = ?, shippingpoint = ?,
 
 961                 shipvia     = ?, terms         = ?, notes         = ?, intnotes      = ?,
 
 962                 curr        = ?, department_id = ?, payment_id    = ?, taxincluded   = ?,
 
 963                 type        = ?, language_id   = ?, taxzone_id    = ?, shipto_id     = ?,
 
 964                 employee_id = ?, salesman_id   = ?, storno_id     = ?, storno        = ?,
 
 965                 cp_id       = ?, marge_total   = ?, marge_percent = ?, 
 
 966                 globalproject_id               = ?, delivery_customer_id             = ?,
 
 967                 transaction_description        = ?, delivery_vendor_id               = ?,
 
 970   @values = (          $form->{"invnumber"},           $form->{"ordnumber"},             $form->{"quonumber"},          $form->{"cusordnumber"},
 
 971              conv_date($form->{"invdate"}),  conv_date($form->{"orddate"}),    conv_date($form->{"quodate"}),    conv_i($form->{"customer_id"}), 
 
 972                        $amount,                        $netamount,                       $form->{"paid"},     conv_date($form->{"datepaid"}), 
 
 973              conv_date($form->{"duedate"}),  conv_date($form->{"deliverydate"}),    '1',                                $form->{"shippingpoint"},
 
 974                        $form->{"shipvia"},      conv_i($form->{"terms"}),                $form->{"notes"},              $form->{"intnotes"},
 
 975                        $form->{"currency"},     conv_i($form->{"department_id"}), conv_i($form->{"payment_id"}),        $form->{"taxincluded"} ? 't' : 'f',
 
 976                        $form->{"type"},         conv_i($form->{"language_id"}),   conv_i($form->{"taxzone_id"}), conv_i($form->{"shipto_id"}),
 
 977                 conv_i($form->{"employee_id"}), conv_i($form->{"salesman_id"}),   conv_i($form->{storno_id}),           $form->{"storno"} ? 't' : 'f', 
 
 978                 conv_i($form->{"cp_id"}),            1 * $form->{marge_total} ,      1 * $form->{marge_percent},
 
 979                 conv_i($form->{"globalproject_id"}),                              conv_i($form->{"delivery_customer_id"}), 
 
 980                        $form->{transaction_description},                          conv_i($form->{"delivery_vendor_id"}),
 
 981                        $form->{"donumber"}, #das entsprechende feld lieferscheinnummer aus der html-form 12.02.09 jb
 
 982                 conv_i($form->{"id"}));
 
 983   do_query($form, $dbh, $query, @values);
 
 985   if($form->{"formname"} eq "credit_note") {
 
 986     for my $i (1 .. $form->{rowcount}) {
 
 987       $query = qq|UPDATE parts SET onhand = onhand - ? WHERE id = ?|;
 
 988       @values = (conv_i($form->{"qty_$i"}), conv_i($form->{"id_$i"}));
 
 989       do_query($form, $dbh, $query, @values);
 
 993   if ($form->{storno}) {
 
 996            paid = paid + amount,
 
 998            intnotes = ? || intnotes
 
1000     do_query($form, $dbh, $query, "Rechnung storniert am $form->{invdate} ", conv_i($form->{"storno_id"}));
 
1001     do_query($form, $dbh, qq|UPDATE ar SET paid = amount WHERE id = ?|, conv_i($form->{"id"}));
 
1005   $form->{name} = $form->{customer};
 
1006   $form->{name} =~ s/--\Q$form->{customer_id}\E//;
 
1008   if (!$form->{shipto_id}) {
 
1009     $form->add_shipto($dbh, $form->{id}, "AR");
 
1012   # save printed, emailed and queued
 
1013   $form->save_status($dbh);
 
1015   Common::webdav_folder($form) if ($main::webdav);
 
1017   # Link this record to the records it was created from.
 
1018   RecordLinks->create_links('dbh'        => $dbh,
 
1020                             'from_table' => 'oe',
 
1021                             'from_ids'   => $form->{convert_from_oe_ids},
 
1023                             'to_id'      => $form->{id},
 
1025   delete $form->{convert_from_oe_ids};
 
1027   my @convert_from_do_ids = map { $_ * 1 } grep { $_ } split m/\s+/, $form->{convert_from_do_ids};
 
1029   if (scalar @convert_from_do_ids) {
 
1030     DO->close_orders('dbh' => $dbh,
 
1031                      'ids' => \@convert_from_do_ids);
 
1033     RecordLinks->create_links('dbh'        => $dbh,
 
1035                               'from_table' => 'delivery_orders',
 
1036                               'from_ids'   => \@convert_from_do_ids,
 
1038                               'to_id'      => $form->{id},
 
1041   delete $form->{convert_from_do_ids};
 
1043   ARAP->close_orders_if_billed('dbh'     => $dbh,
 
1044                                'arap_id' => $form->{id},
 
1048   if (!$provided_dbh) {
 
1053   $main::lxdebug->leave_sub();
 
1058 sub _delete_payments {
 
1059   $main::lxdebug->enter_sub();
 
1061   my ($self, $form, $dbh) = @_;
 
1065   # Delete old payment entries from acc_trans.
 
1069        WHERE (trans_id = ?) AND fx_transaction
 
1075        LEFT JOIN chart c ON (at.chart_id = c.id)
 
1076        WHERE (trans_id = ?) AND (c.link LIKE '%AR_paid%')|;
 
1077   push @delete_oids, selectall_array_query($form, $dbh, $query, conv_i($form->{id}), conv_i($form->{id}));
 
1082        LEFT JOIN chart c ON (at.chart_id = c.id)
 
1083        WHERE (trans_id = ?)
 
1084          AND ((c.link = 'AR') OR (c.link LIKE '%:AR') OR (c.link LIKE 'AR:%'))
 
1087   push @delete_oids, selectall_array_query($form, $dbh, $query, conv_i($form->{id}));
 
1090     $query = qq|DELETE FROM acc_trans WHERE oid IN (| . join(", ", @delete_oids) . qq|)|;
 
1091     do_query($form, $dbh, $query);
 
1094   $main::lxdebug->leave_sub();
 
1098   $main::lxdebug->enter_sub();
 
1100   my ($self, $myconfig, $form, $locale) = @_;
 
1102   # connect to database, turn off autocommit
 
1103   my $dbh = $form->dbconnect_noauto($myconfig);
 
1105   my (%payments, $old_form, $row, $item, $query, %keep_vars);
 
1107   $old_form = save_form();
 
1109   # Delete all entries in acc_trans from prior payments.
 
1110   $self->_delete_payments($form, $dbh);
 
1112   # Save the new payments the user made before cleaning up $form.
 
1113   map { $payments{$_} = $form->{$_} } grep m/^datepaid_\d+$|^memo_\d+$|^source_\d+$|^exchangerate_\d+$|^paid_\d+$|^AR_paid_\d+$|^paidaccounts$/, keys %{ $form };
 
1115   # Clean up $form so that old content won't tamper the results.
 
1116   %keep_vars = map { $_, 1 } qw(login password id);
 
1117   map { delete $form->{$_} unless $keep_vars{$_} } keys %{ $form };
 
1119   # Retrieve the invoice from the database.
 
1120   $self->retrieve_invoice($myconfig, $form);
 
1122   # Set up the content of $form in the way that IS::post_invoice() expects.
 
1123   $form->{exchangerate} = $form->format_amount($myconfig, $form->{exchangerate});
 
1125   for $row (1 .. scalar @{ $form->{invoice_details} }) {
 
1126     $item = $form->{invoice_details}->[$row - 1];
 
1128     map { $item->{$_} = $form->format_amount($myconfig, $item->{$_}) } qw(qty sellprice discount);
 
1130     map { $form->{"${_}_${row}"} = $item->{$_} } keys %{ $item };
 
1133   $form->{rowcount} = scalar @{ $form->{invoice_details} };
 
1135   delete @{$form}{qw(invoice_details paidaccounts storno paid)};
 
1137   # Restore the payment options from the user input.
 
1138   map { $form->{$_} = $payments{$_} } keys %payments;
 
1140   # Get the AR accno (which is normally done by Form::create_links()).
 
1144        LEFT JOIN chart c ON (at.chart_id = c.id)
 
1145        WHERE (trans_id = ?)
 
1146          AND ((c.link = 'AR') OR (c.link LIKE '%:AR') OR (c.link LIKE 'AR:%'))
 
1150   ($form->{AR}) = selectfirst_array_query($form, $dbh, $query, conv_i($form->{id}));
 
1152   # Post the new payments.
 
1153   $self->post_invoice($myconfig, $form, $dbh, 1);
 
1155   restore_form($old_form);
 
1157   my $rc = $dbh->commit();
 
1160   $main::lxdebug->leave_sub();
 
1165 sub process_assembly {
 
1166   $main::lxdebug->enter_sub();
 
1168   my ($dbh, $form, $id, $totalqty) = @_;
 
1171     qq|SELECT a.parts_id, a.qty, p.assembly, p.partnumber, p.description, p.unit,
 
1172          p.inventory_accno_id, p.income_accno_id, p.expense_accno_id
 
1174        JOIN parts p ON (a.parts_id = p.id)
 
1176   my $sth = prepare_execute_query($form, $dbh, $query, conv_i($id));
 
1178   while (my $ref = $sth->fetchrow_hashref('NAME_lc')) {
 
1182     $ref->{inventory_accno_id} *= 1;
 
1183     $ref->{expense_accno_id}   *= 1;
 
1185     # multiply by number of assemblies
 
1186     $ref->{qty} *= $totalqty;
 
1188     if ($ref->{assembly}) {
 
1189       &process_assembly($dbh, $form, $ref->{parts_id}, $ref->{qty});
 
1192       if ($ref->{inventory_accno_id}) {
 
1193         $allocated = &cogs($dbh, $form, $ref->{parts_id}, $ref->{qty});
 
1197     # save detail record for individual assembly item in invoice table
 
1199       qq|INSERT INTO invoice (trans_id, description, parts_id, qty, sellprice, fxsellprice, allocated, assemblyitem, unit)
 
1200          VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)|;
 
1201     my @values = (conv_i($form->{id}), $ref->{description}, conv_i($ref->{parts_id}), $ref->{qty}, 0, 0, $allocated, 't', $ref->{unit});
 
1202     do_query($form, $dbh, $query, @values);
 
1208   $main::lxdebug->leave_sub();
 
1212   $main::lxdebug->enter_sub();
 
1214   my ($dbh, $form, $id, $totalqty, $basefactor, $row) = @_;
 
1215   $form->{taxzone_id} *=1;
 
1216   my $transdate  = $form->{invdate} ? $dbh->quote($form->{invdate}) : "current_date";
 
1217   my $taxzone_id = $form->{"taxzone_id"} * 1;
 
1219     qq|SELECT i.id, i.trans_id, i.base_qty, i.allocated, i.sellprice,
 
1220          c1.accno AS inventory_accno, c1.new_chart_id AS inventory_new_chart, date($transdate) - c1.valid_from AS inventory_valid,
 
1221          c2.accno AS    income_accno, c2.new_chart_id AS    income_new_chart, date($transdate) - c2.valid_from AS    income_valid,
 
1222          c3.accno AS   expense_accno, c3.new_chart_id AS   expense_new_chart, date($transdate) - c3.valid_from AS   expense_valid
 
1223        FROM invoice i, parts p
 
1224        LEFT JOIN chart c1 ON ((SELECT inventory_accno_id FROM buchungsgruppen WHERE id = p.buchungsgruppen_id) = c1.id)
 
1225        LEFT JOIN chart c2 ON ((SELECT income_accno_id_${taxzone_id} FROM buchungsgruppen WHERE id = p.buchungsgruppen_id) = c2.id)
 
1226        LEFT JOIN chart c3 ON ((select expense_accno_id_${taxzone_id} FROM buchungsgruppen WHERE id = p.buchungsgruppen_id) = c3.id)
 
1227        WHERE (i.parts_id = p.id)
 
1228          AND (i.parts_id = ?)
 
1229          AND ((i.base_qty + i.allocated) < 0)
 
1231   my $sth = prepare_execute_query($form, $dbh, $query, conv_i($id));
 
1236   while (my $ref = $sth->fetchrow_hashref('NAME_lc')) {
 
1237     if (($qty = (($ref->{base_qty} * -1) - $ref->{allocated})) > $totalqty) {
 
1241     $form->update_balance($dbh, "invoice", "allocated", qq|id = $ref->{id}|, $qty);
 
1243     # total expenses and inventory
 
1244     # sellprice is the cost of the item
 
1245     my $linetotal = $form->round_amount(($ref->{sellprice} * $qty) / $basefactor, 2);
 
1248       $ref->{expense_accno} = ($form->{"expense_accno_$row"}) ? $form->{"expense_accno_$row"} : $ref->{expense_accno};
 
1250       $form->{amount_cogs}{ $form->{id} }{ $ref->{expense_accno} } += -$linetotal;
 
1251       $form->{expense_inventory} .= " " . $ref->{expense_accno};
 
1252       $ref->{inventory_accno} = ($form->{"inventory_accno_$row"}) ? $form->{"inventory_accno_$row"} : $ref->{inventory_accno};
 
1254       $form->{amount_cogs}{ $form->{id} }{ $ref->{inventory_accno} } -= -$linetotal;
 
1255       $form->{expense_inventory} .= " " . $ref->{inventory_accno};
 
1261     last if (($totalqty -= $qty) <= 0);
 
1266   $main::lxdebug->leave_sub();
 
1271 sub reverse_invoice {
 
1272   $main::lxdebug->enter_sub();
 
1274   my ($dbh, $form) = @_;
 
1276   # reverse inventory items
 
1278     qq|SELECT i.id, i.parts_id, i.qty, i.assemblyitem, p.assembly, p.inventory_accno_id
 
1280        JOIN parts p ON (i.parts_id = p.id)
 
1281        WHERE i.trans_id = ?|;
 
1282   my $sth = prepare_execute_query($form, $dbh, $query, conv_i($form->{"id"}));
 
1284   while (my $ref = $sth->fetchrow_hashref('NAME_lc')) {
 
1286     if ($ref->{inventory_accno_id}) {
 
1287       # de-allocated purchases
 
1289         qq|SELECT i.id, i.trans_id, i.allocated
 
1291            WHERE (i.parts_id = ?) AND (i.allocated > 0)
 
1292            ORDER BY i.trans_id DESC|;
 
1293       my $sth2 = prepare_execute_query($form, $dbh, $query, conv_i($ref->{"parts_id"}));
 
1295       while (my $inhref = $sth2->fetchrow_hashref('NAME_lc')) {
 
1296         my $qty = $ref->{qty};
 
1297         if (($ref->{qty} - $inhref->{allocated}) > 0) {
 
1298           $qty = $inhref->{allocated};
 
1302         $form->update_balance($dbh, "invoice", "allocated", qq|id = $inhref->{id}|, $qty * -1);
 
1304         last if (($ref->{qty} -= $qty) <= 0);
 
1313   my @values = (conv_i($form->{id}));
 
1314   do_query($form, $dbh, qq|DELETE FROM acc_trans WHERE trans_id = ?|, @values);
 
1315   do_query($form, $dbh, qq|DELETE FROM invoice WHERE trans_id = ?|, @values);
 
1317   if ($form->{lizenzen}) {
 
1319       qq|DELETE FROM licenseinvoice
 
1320          WHERE trans_id in (SELECT id FROM invoice WHERE trans_id = ?)|;
 
1321     do_query($form, $dbh, $query, @values);
 
1324   do_query($form, $dbh, qq|DELETE FROM shipto WHERE (trans_id = ?) AND (module = 'AR')|, @values);
 
1326   $main::lxdebug->leave_sub();
 
1329 sub delete_invoice {
 
1330   $main::lxdebug->enter_sub();
 
1332   my ($self, $myconfig, $form, $spool) = @_;
 
1334   # connect to database
 
1335   my $dbh = $form->dbconnect_noauto($myconfig);
 
1337   &reverse_invoice($dbh, $form);
 
1339   my @values = (conv_i($form->{id}));
 
1342   do_query($form, $dbh, qq|DELETE FROM ar WHERE id = ?|, @values);
 
1344   # delete spool files
 
1345   my @spoolfiles = selectall_array_query($form, $dbh, qq|SELECT spoolfile FROM status WHERE trans_id = ?|, @values);
 
1347   # delete status entries
 
1348   do_query($form, $dbh, qq|DELETE FROM status WHERE trans_id = ?|, @values);
 
1350   my $rc = $dbh->commit;
 
1354     map { unlink "$spool/$_" if -f "$spool/$_"; } @spoolfiles;
 
1357   $main::lxdebug->leave_sub();
 
1362 sub retrieve_invoice {
 
1363   $main::lxdebug->enter_sub();
 
1365   my ($self, $myconfig, $form) = @_;
 
1367   # connect to database
 
1368   my $dbh = $form->dbconnect_noauto($myconfig);
 
1370   my ($sth, $ref, $query);
 
1372   my $query_transdate = ", current_date AS invdate" if !$form->{id};
 
1376          (SELECT c.accno FROM chart c WHERE d.inventory_accno_id = c.id) AS inventory_accno,
 
1377          (SELECT c.accno FROM chart c WHERE d.income_accno_id = c.id)    AS income_accno,
 
1378          (SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id)   AS expense_accno,
 
1379          (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id)    AS fxgain_accno,
 
1380          (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id)    AS fxloss_accno,
 
1381          d.curr AS currencies
 
1385   $ref = selectfirst_hashref_query($form, $dbh, $query);
 
1386   map { $form->{$_} = $ref->{$_} } keys %{ $ref };
 
1389     my $id = conv_i($form->{id});
 
1392     #erweiterung um das entsprechende feld lieferscheinnummer (a.donumber) in der html-maske anzuzeigen 12.02.2009 jb
 
1396            a.invnumber, a.ordnumber, a.quonumber, a.cusordnumber,
 
1397            a.orddate, a.quodate, a.globalproject_id,
 
1398            a.transdate AS invdate, a.deliverydate, a.paid, a.storno, a.gldate,
 
1399            a.shippingpoint, a.shipvia, a.terms, a.notes, a.intnotes, a.taxzone_id,
 
1400            a.duedate, a.taxincluded, a.curr AS currency, a.shipto_id, a.cp_id,
 
1401            a.employee_id, a.salesman_id, a.payment_id,
 
1402            a.language_id, a.delivery_customer_id, a.delivery_vendor_id, a.type,
 
1403            a.transaction_description,
 
1404            a.marge_total, a.marge_percent,
 
1405            e.name AS employee, a.donumber
 
1407          LEFT JOIN employee e ON (e.id = a.employee_id)
 
1409     $ref = selectfirst_hashref_query($form, $dbh, $query, $id);
 
1410     map { $form->{$_} = $ref->{$_} } keys %{ $ref };
 
1413     $form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{invdate}, "buy");
 
1416     $query = qq|SELECT * FROM shipto WHERE (trans_id = ?) AND (module = 'AR')|;
 
1417     $ref = selectfirst_hashref_query($form, $dbh, $query, $id);
 
1419     map { $form->{$_} = $ref->{$_} } keys %{ $ref };
 
1421     foreach my $vc (qw(customer vendor)) {
 
1422       next if !$form->{"delivery_${vc}_id"};
 
1423       ($form->{"delivery_${vc}_string"}) = selectrow_query($form, $dbh, qq|SELECT name FROM customer WHERE id = ?|, $id);
 
1426     # get printed, emailed
 
1427     $query = qq|SELECT printed, emailed, spoolfile, formname FROM status WHERE trans_id = ?|;
 
1428     $sth = prepare_execute_query($form, $dbh, $query, $id);
 
1430     while ($ref = $sth->fetchrow_hashref('NAME_lc')) {
 
1431       $form->{printed} .= "$ref->{formname} " if $ref->{printed};
 
1432       $form->{emailed} .= "$ref->{formname} " if $ref->{emailed};
 
1433       $form->{queued} .= "$ref->{formname} $ref->{spoolfile} " if $ref->{spoolfile};
 
1436     map { $form->{$_} =~ s/ +$//g } qw(printed emailed queued);
 
1438     my $transdate = $form->{deliverydate} ? $dbh->quote($form->{deliverydate})
 
1439                   : $form->{invdate}      ? $dbh->quote($form->{invdate})
 
1443     my $taxzone_id = $form->{taxzone_id} *= 1;
 
1444     $taxzone_id = 0 if (0 > $taxzone_id) || (3 < $taxzone_id);
 
1446     # retrieve individual items
 
1449            c1.accno AS inventory_accno, c1.new_chart_id AS inventory_new_chart, date($transdate) - c1.valid_from AS inventory_valid,
 
1450            c2.accno AS income_accno,    c2.new_chart_id AS income_new_chart,    date($transdate) - c2.valid_from as income_valid,
 
1451            c3.accno AS expense_accno,   c3.new_chart_id AS expense_new_chart,   date($transdate) - c3.valid_from AS expense_valid,
 
1453            i.description, i.longdescription, i.qty, i.fxsellprice AS sellprice, i.discount, i.parts_id AS id, i.unit, i.deliverydate AS reqdate,
 
1454            i.project_id, i.serialnumber, i.id AS invoice_pos, i.pricegroup_id, i.ordnumber, i.transdate, i.cusordnumber, i.subtotal, i.lastcost,
 
1455            i.price_factor_id, i.price_factor, i.marge_price_factor,
 
1456            p.partnumber, p.assembly, p.bin, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id, p.formel,
 
1457            pr.projectnumber, pg.partsgroup, prg.pricegroup
 
1460          LEFT JOIN parts p ON (i.parts_id = p.id)
 
1461          LEFT JOIN project pr ON (i.project_id = pr.id)
 
1462          LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1463          LEFT JOIN pricegroup prg ON (i.pricegroup_id = prg.id)
 
1465          LEFT JOIN chart c1 ON ((SELECT inventory_accno_id             FROM buchungsgruppen WHERE id = p.buchungsgruppen_id) = c1.id)
 
1466          LEFT JOIN chart c2 ON ((SELECT income_accno_id_${taxzone_id}  FROM buchungsgruppen WHERE id = p.buchungsgruppen_id) = c2.id)
 
1467          LEFT JOIN chart c3 ON ((SELECT expense_accno_id_${taxzone_id} FROM buchungsgruppen WHERE id = p.buchungsgruppen_id) = c3.id)
 
1469          WHERE (i.trans_id = ?) AND NOT (i.assemblyitem = '1') ORDER BY i.id|;
 
1471     $sth = prepare_execute_query($form, $dbh, $query, $id);
 
1473     while (my $ref = $sth->fetchrow_hashref('NAME_lc')) {
 
1474       map({ delete($ref->{$_}); } qw(inventory_accno inventory_new_chart inventory_valid)) if !$ref->{"part_inventory_accno_id"};
 
1475       delete($ref->{"part_inventory_accno_id"});
 
1477       foreach my $type (qw(inventory income expense)) {
 
1478         while ($ref->{"${type}_new_chart"} && ($ref->{"${type}_valid"} >=0)) {
 
1479           my $query = qq|SELECT accno, new_chart_id, date($transdate) - valid_from FROM chart WHERE id = ?|;
 
1480           @$ref{ map $type.$_, qw(_accno _new_chart _valid) } = selectrow_query($form, $dbh, $query, $ref->{"${type}_new_chart"});
 
1484       # get tax rates and description
 
1485       my $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno};
 
1487         qq|SELECT c.accno, t.taxdescription, t.rate, t.taxnumber FROM tax t
 
1488            LEFT JOIN chart c ON (c.id = t.chart_id)
 
1490              (SELECT tk.tax_id FROM taxkeys tk
 
1491               WHERE tk.chart_id = (SELECT id FROM chart WHERE accno = ?) 
 
1492                 AND startdate <= date($transdate)
 
1493               ORDER BY startdate DESC LIMIT 1)
 
1495       my $stw = prepare_execute_query($form, $dbh, $query, $accno_id);
 
1496       $ref->{taxaccounts} = "";
 
1498       while (my $ptr = $stw->fetchrow_hashref('NAME_lc')) {
 
1500         if (($ptr->{accno} eq "") && ($ptr->{rate} == 0)) {
 
1504         $ref->{taxaccounts} .= "$ptr->{accno} ";
 
1506         if (!($form->{taxaccounts} =~ /\Q$ptr->{accno}\E/)) {
 
1507           $form->{"$ptr->{accno}_rate"}        = $ptr->{rate};
 
1508           $form->{"$ptr->{accno}_description"} = $ptr->{taxdescription};
 
1509           $form->{"$ptr->{accno}_taxnumber"}   = $ptr->{taxnumber};
 
1510           $form->{taxaccounts} .= "$ptr->{accno} ";
 
1515       if ($form->{lizenzen}) {
 
1516         $query = qq|SELECT l.licensenumber, l.id AS licenseid FROM license l, licenseinvoice li WHERE l.id = li.license_id AND li.trans_id = ?|;
 
1517         my ($licensenumber, $licenseid) = selectrow_query($form, $dbh, $query, conv_i($ref->{invoice_pos}));
 
1518         $ref->{lizenzen} = "<option value=\"$licenseid\">$licensenumber</option>";
 
1521       $ref->{qty} *= -1 if $form->{type} eq "credit_note";
 
1523       chop $ref->{taxaccounts};
 
1524       push @{ $form->{invoice_details} }, $ref;
 
1529     Common::webdav_folder($form) if ($main::webdav);
 
1532   my $rc = $dbh->commit;
 
1535   $main::lxdebug->leave_sub();
 
1541   $main::lxdebug->enter_sub();
 
1543   my ($self, $myconfig, $form) = @_;
 
1545   # connect to database
 
1546   my $dbh = $form->dbconnect($myconfig);
 
1548   my $dateformat = $myconfig->{dateformat};
 
1549   $dateformat .= "yy" if $myconfig->{dateformat} !~ /^y/;
 
1551   my (@values, $duedate, $ref, $query);
 
1553   if ($form->{invdate}) {
 
1554     $duedate = "to_date(?, '$dateformat')";
 
1555     push @values, $form->{invdate};
 
1557     $duedate = "current_date";
 
1560   my $cid = conv_i($form->{customer_id});
 
1563   if ($form->{payment_id}) {
 
1564     $payment_id = "(pt.id = ?) OR";
 
1565     push @values, conv_i($form->{payment_id});
 
1571          c.id AS customer_id, c.name AS customer, c.discount, c.creditlimit, c.terms,
 
1572          c.email, c.cc, c.bcc, c.language_id, c.payment_id,
 
1573          c.street, c.zipcode, c.city, c.country,
 
1574          c.notes AS intnotes, c.klass as customer_klass, c.taxzone_id, c.salesman_id,
 
1575          $duedate + COALESCE(pt.terms_netto, 0) AS duedate,
 
1576          b.discount AS tradediscount, b.description AS business
 
1578        LEFT JOIN business b ON (b.id = c.business_id)
 
1579        LEFT JOIN payment_terms pt ON ($payment_id (c.payment_id = pt.id))
 
1582   $ref = selectfirst_hashref_query($form, $dbh, $query, @values);
 
1583   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
1586     qq|SELECT sum(amount - paid) AS dunning_amount
 
1588        WHERE (paid < amount)
 
1589          AND (customer_id = ?)
 
1590          AND (dunning_config_id IS NOT NULL)|;
 
1591   $ref = selectfirst_hashref_query($form, $dbh, $query, $cid);
 
1592   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
1595     qq|SELECT dnn.dunning_description AS max_dunning_level
 
1596        FROM dunning_config dnn
 
1597        WHERE id IN (SELECT dunning_config_id
 
1599                     WHERE (paid < amount) AND (customer_id = ?) AND (dunning_config_id IS NOT NULL))
 
1600        ORDER BY dunning_level DESC LIMIT 1|;
 
1601   $ref = selectfirst_hashref_query($form, $dbh, $query, $cid);
 
1602   map { $form->{$_} = $ref->{$_} } keys %$ref;
 
1604   $form->{creditremaining} = $form->{creditlimit};
 
1605   $query = qq|SELECT SUM(amount - paid) FROM ar WHERE customer_id = ?|;
 
1606   my ($value) = selectrow_query($form, $dbh, $query, $cid);
 
1607   $form->{creditremaining} -= $value;
 
1611          (SELECT e.buy FROM exchangerate e
 
1612           WHERE e.curr = o.curr
 
1613             AND e.transdate = o.transdate)
 
1615        WHERE o.customer_id = ?
 
1616          AND o.quotation = '0'
 
1617          AND o.closed = '0'|;
 
1618   my $sth = prepare_execute_query($form, $dbh, $query, $cid);
 
1620   while (my ($amount, $exch) = $sth->fetchrow_array) {
 
1621     $exch = 1 unless $exch;
 
1622     $form->{creditremaining} -= $amount * $exch;
 
1626   # get shipto if we did not converted an order or invoice
 
1627   if (!$form->{shipto}) {
 
1628     map { delete $form->{$_} }
 
1629       qw(shiptoname shiptodepartment_1 shiptodepartment_2
 
1630          shiptostreet shiptozipcode shiptocity shiptocountry
 
1631          shiptocontact shiptophone shiptofax shiptoemail);
 
1633     $query = qq|SELECT * FROM shipto WHERE trans_id = ? AND module = 'CT'|;
 
1634     $ref = selectfirst_hashref_query($form, $dbh, $query, $cid);
 
1636     map { $form->{$_} = $ref->{$_} } keys %$ref;
 
1639   # setup last accounts used for this customer
 
1640   if (!$form->{id} && $form->{type} !~ /_(order|quotation)/) {
 
1642       qq|SELECT c.id, c.accno, c.description, c.link, c.category
 
1644          JOIN acc_trans ac ON (ac.chart_id = c.id)
 
1645          JOIN ar a ON (a.id = ac.trans_id)
 
1646          WHERE a.customer_id = ?
 
1647            AND NOT (c.link LIKE '%_tax%' OR c.link LIKE '%_paid%')
 
1648            AND a.id IN (SELECT max(a2.id) FROM ar a2 WHERE a2.customer_id = ?)|;
 
1649     $sth = prepare_execute_query($form, $dbh, $query, $cid, $cid);
 
1652     while ($ref = $sth->fetchrow_hashref('NAME_lc')) {
 
1653       if ($ref->{category} eq 'I') {
 
1655         $form->{"AR_amount_$i"} = "$ref->{accno}--$ref->{description}";
 
1657         if ($form->{initial_transdate}) {
 
1659             qq|SELECT tk.tax_id, t.rate
 
1661                LEFT JOIN tax t ON tk.tax_id = t.id
 
1662                WHERE (tk.chart_id = ?) AND (startdate <= date(?))
 
1663                ORDER BY tk.startdate DESC
 
1665           my ($tax_id, $rate) =
 
1666             selectrow_query($form, $dbh, $tax_query, $ref->{id},
 
1667                             $form->{initial_transdate});
 
1668           $form->{"taxchart_$i"} = "${tax_id}--${rate}";
 
1671       if ($ref->{category} eq 'A') {
 
1672         $form->{ARselected} = $form->{AR_1} = $ref->{accno};
 
1676     $form->{rowcount} = $i if ($i && !$form->{type});
 
1681   $main::lxdebug->leave_sub();
 
1685   $main::lxdebug->enter_sub();
 
1687   my ($self, $myconfig, $form) = @_;
 
1689   # connect to database
 
1690   my $dbh = $form->dbconnect($myconfig);
 
1692   my $i = $form->{rowcount};
 
1694   my $where = qq|NOT p.obsolete = '1'|;
 
1697   foreach my $column (qw(p.partnumber p.description pgpartsgroup)) {
 
1698     my ($table, $field) = split m/\./, $column;
 
1699     next if !$form->{"${field}_${i}"};
 
1700     $where .= qq| AND lower(${column}) ILIKE ?|;
 
1701     push @values, '%' . $form->{"${field}_${i}"} . '%';
 
1704   if ($form->{"description_$i"}) {
 
1705     $where .= qq| ORDER BY p.description|;
 
1707     $where .= qq| ORDER BY p.partnumber|;
 
1711   if ($form->{type} eq "invoice") {
 
1713       $form->{deliverydate} ? $dbh->quote($form->{deliverydate}) :
 
1714       $form->{invdate}      ? $dbh->quote($form->{invdate}) :
 
1718       $form->{transdate}    ? $dbh->quote($form->{transdate}) :
 
1722   my $taxzone_id = $form->{taxzone_id} * 1;
 
1723   $taxzone_id = 0 if (0 > $taxzone_id) || (3 < $taxzone_id);
 
1727          p.id, p.partnumber, p.description, p.sellprice,
 
1728          p.listprice, p.inventory_accno_id, p.lastcost,
 
1730          c1.accno AS inventory_accno,
 
1731          c1.new_chart_id AS inventory_new_chart,
 
1732          date($transdate) - c1.valid_from AS inventory_valid,
 
1734          c2.accno AS income_accno,
 
1735          c2.new_chart_id AS income_new_chart,
 
1736          date($transdate)  - c2.valid_from AS income_valid,
 
1738          c3.accno AS expense_accno,
 
1739          c3.new_chart_id AS expense_new_chart,
 
1740          date($transdate) - c3.valid_from AS expense_valid,
 
1742          p.unit, p.assembly, p.bin, p.onhand,
 
1743          p.notes AS partnotes, p.notes AS longdescription,
 
1744          p.not_discountable, p.formel, p.payment_id AS part_payment_id,
 
1747          pfac.factor AS price_factor,
 
1752        LEFT JOIN chart c1 ON
 
1753          ((SELECT inventory_accno_id
 
1754            FROM buchungsgruppen
 
1755            WHERE id = p.buchungsgruppen_id) = c1.id)
 
1756        LEFT JOIN chart c2 ON
 
1757          ((SELECT income_accno_id_${taxzone_id}
 
1758            FROM buchungsgruppen
 
1759            WHERE id = p.buchungsgruppen_id) = c2.id)
 
1760        LEFT JOIN chart c3 ON
 
1761          ((SELECT expense_accno_id_${taxzone_id}
 
1762            FROM buchungsgruppen
 
1763            WHERE id = p.buchungsgruppen_id) = c3.id)
 
1764        LEFT JOIN partsgroup pg ON (pg.id = p.partsgroup_id)
 
1765        LEFT JOIN price_factors pfac ON (pfac.id = p.price_factor_id)
 
1767   my $sth = prepare_execute_query($form, $dbh, $query, @values);
 
1769   while (my $ref = $sth->fetchrow_hashref('NAME_lc')) {
 
1771     # In der Buchungsgruppe ist immer ein Bestandskonto verknuepft, auch wenn
 
1772     # es sich um eine Dienstleistung handelt. Bei Dienstleistungen muss das
 
1773     # Buchungskonto also aus dem Ergebnis rausgenommen werden.
 
1774     if (!$ref->{inventory_accno_id}) {
 
1775       map({ delete($ref->{"inventory_${_}"}); } qw(accno new_chart valid));
 
1777     delete($ref->{inventory_accno_id});
 
1779     foreach my $type (qw(inventory income expense)) {
 
1780       while ($ref->{"${type}_new_chart"} && ($ref->{"${type}_valid"} >=0)) {
 
1782           qq|SELECT accno, new_chart_id, date($transdate) - valid_from
 
1785         ($ref->{"${type}_accno"},
 
1786          $ref->{"${type}_new_chart"},
 
1787          $ref->{"${type}_valid"})
 
1788           = selectrow_query($form, $dbh, $query, $ref->{"${type}_new_chart"});
 
1792     if ($form->{payment_id} eq "") {
 
1793       $form->{payment_id} = $form->{part_payment_id};
 
1796     # get tax rates and description
 
1797     my $accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{expense_accno};
 
1799       qq|SELECT c.accno, t.taxdescription, t.rate, t.taxnumber
 
1801          LEFT JOIN chart c ON (c.id = t.chart_id)
 
1805             WHERE tk.chart_id = (SELECT id from chart WHERE accno = ?)
 
1807             ORDER BY startdate DESC
 
1810     @values = ($accno_id, $transdate eq "current_date" ? "now" : $transdate);
 
1811     my $stw = $dbh->prepare($query);
 
1812     $stw->execute(@values) || $form->dberror($query);
 
1814     $ref->{taxaccounts} = "";
 
1816     while (my $ptr = $stw->fetchrow_hashref('NAME_lc')) {
 
1818       #    if ($customertax{$ref->{accno}}) 
 
1819       if (($ptr->{accno} eq "") && ($ptr->{rate} == 0)) {
 
1823       $ref->{taxaccounts} .= "$ptr->{accno} ";
 
1825       if (!($form->{taxaccounts} =~ /\Q$ptr->{accno}\E/)) {
 
1826         $form->{"$ptr->{accno}_rate"}        = $ptr->{rate};
 
1827         $form->{"$ptr->{accno}_description"} = $ptr->{taxdescription};
 
1828         $form->{"$ptr->{accno}_taxnumber"}   = $ptr->{taxnumber};
 
1829         $form->{taxaccounts} .= "$ptr->{accno} ";
 
1835     chop $ref->{taxaccounts};
 
1836     if ($form->{language_id}) {
 
1838         qq|SELECT tr.translation, tr.longdescription
 
1840            WHERE tr.language_id = ? AND tr.parts_id = ?|;
 
1841       @values = (conv_i($form->{language_id}), conv_i($ref->{id}));
 
1842       my ($translation, $longdescription) = selectrow_query($form, $dbh, $query, @values);
 
1843       if ($translation ne "") {
 
1844         $ref->{description} = $translation;
 
1845         $ref->{longdescription} = $longdescription;
 
1849           qq|SELECT tr.translation, tr.longdescription
 
1851              WHERE tr.language_id IN
 
1854                 WHERE article_code = (SELECT article_code FROM language WHERE id = ?))
 
1857         @values = (conv_i($form->{language_id}), conv_i($ref->{id}));
 
1858         my ($translation, $longdescription) = selectrow_query($form, $dbh, $query, @values);
 
1859         if ($translation ne "") {
 
1860           $ref->{description} = $translation;
 
1861           $ref->{longdescription} = $longdescription;
 
1866     $ref->{onhand} *= 1;
 
1868     push @{ $form->{item_list} }, $ref;
 
1870     if ($form->{lizenzen}) {
 
1871       if ($ref->{inventory_accno} > 0) {
 
1875              WHERE l.parts_id = ? AND NOT l.id IN (SELECT li.license_id FROM licenseinvoice li)|;
 
1876         my $stw = prepare_execute_query($form, $dbh, $query, conv_i($ref->{id}));
 
1877         while (my $ptr = $stw->fetchrow_hashref('NAME_lc')) {
 
1878           push @{ $form->{LIZENZEN}{ $ref->{id} } }, $ptr;
 
1887   $main::lxdebug->leave_sub();
 
1890 ##########################
 
1891 # get pricegroups from database
 
1892 # build up selected pricegroup
 
1893 # if an exchange rate - change price
 
1896 sub get_pricegroups_for_parts {
 
1898   $main::lxdebug->enter_sub();
 
1900   my ($self, $myconfig, $form) = @_;
 
1902   my $dbh = $form->dbconnect($myconfig);
 
1904   $form->{"PRICES"} = {};
 
1908   my $all_units = AM->retrieve_units($myconfig, $form);
 
1909   while (($form->{"id_$i"}) or ($form->{"new_id_$i"})) {
 
1910     $form->{"PRICES"}{$i} = [];
 
1912     $id = $form->{"id_$i"};
 
1914     if (!($form->{"id_$i"}) and $form->{"new_id_$i"}) {
 
1916       $id = $form->{"new_id_$i"};
 
1919     my ($price, $selectedpricegroup_id) = split(/--/,
 
1920       $form->{"sellprice_pg_$i"});
 
1922     my $pricegroup_old = $form->{"pricegroup_old_$i"};
 
1923     $form->{"new_pricegroup_$i"} = $selectedpricegroup_id;
 
1924     $form->{"old_pricegroup_$i"} = $pricegroup_old;
 
1926     my $price_new = $form->{"price_new_$i"};
 
1927     my $price_old = $form->{"price_old_$i"};
 
1929     if (!$form->{"unit_old_$i"}) {
 
1930       # Neue Ware aus der Datenbank. In diesem Fall ist unit_$i die
 
1931       # Einheit, wie sie in den Stammdaten hinterlegt wurde.
 
1932       # Es sollte also angenommen werden, dass diese ausgewaehlt war.
 
1933       $form->{"unit_old_$i"} = $form->{"unit_$i"};
 
1936     # Die zuletzt ausgewaehlte mit der aktuell ausgewaehlten Einheit
 
1937     # vergleichen und bei Unterschied den Preis entsprechend umrechnen.
 
1938     $form->{"selected_unit_$i"} = $form->{"unit_$i"} unless ($form->{"selected_unit_$i"});
 
1940     if (!$all_units->{$form->{"selected_unit_$i"}} ||
 
1941         ($all_units->{$form->{"selected_unit_$i"}}->{"base_unit"} ne
 
1942          $all_units->{$form->{"unit_old_$i"}}->{"base_unit"})) {
 
1943       # Die ausgewaehlte Einheit ist fuer diesen Artikel nicht gueltig
 
1944       # (z.B. Dimensionseinheit war ausgewaehlt, es handelt sich aber
 
1945       # um eine Dienstleistung). Dann keinerlei Umrechnung vornehmen.
 
1946       $form->{"unit_old_$i"} = $form->{"selected_unit_$i"} = $form->{"unit_$i"};
 
1951     if ($form->{"unit_old_$i"} ne $form->{"selected_unit_$i"}) {
 
1952       if (defined($all_units->{$form->{"unit_old_$i"}}->{"factor"}) &&
 
1953           $all_units->{$form->{"unit_old_$i"}}->{"factor"}) {
 
1954         $basefactor = $all_units->{$form->{"selected_unit_$i"}}->{"factor"} /
 
1955           $all_units->{$form->{"unit_old_$i"}}->{"factor"};
 
1959     if (!$form->{"basefactor_$i"}) {
 
1960       $form->{"basefactor_$i"} = 1;
 
1966            (SELECT p.sellprice FROM parts p WHERE p.id = ?) AS default_sellprice,
 
1967            (SELECT pg.pricegroup FROM pricegroup pg WHERE id = pricegroup_id) AS pricegroup,
 
1977             (SELECT sellprice FROM parts WHERE id = ?) AS default_sellprice,
 
1979             (SELECT DISTINCT sellprice FROM parts where id = ?) AS price,
 
1980             'selected' AS selected
 
1983           ORDER BY pricegroup|;
 
1984     my @values = (conv_i($id), conv_i($id), conv_i($id), conv_i($id));
 
1985     my $pkq = prepare_execute_query($form, $dbh, $query, @values);
 
1987     while (my $pkr = $pkq->fetchrow_hashref('NAME_lc')) {
 
1989       $pkr->{selected} = '';
 
1991       # if there is an exchange rate change price
 
1992       if (($form->{exchangerate} * 1) != 0) {
 
1994         $pkr->{price} /= $form->{exchangerate};
 
1997       $pkr->{price} *= $form->{"basefactor_$i"};
 
1999       $pkr->{price} *= $basefactor;
 
2001       $pkr->{price} = $form->format_amount($myconfig, $pkr->{price}, 5);
 
2003       if ($selectedpricegroup_id eq undef) {
 
2004         if ($pkr->{pricegroup_id} eq $form->{customer_klass}) {
 
2006           $pkr->{selected}  = ' selected';
 
2008           # no customer pricesgroup set
 
2009           if ($pkr->{price} == $pkr->{default_sellprice}) {
 
2011             $pkr->{price} = $form->{"sellprice_$i"};
 
2015             $form->{"sellprice_$i"} = $pkr->{price};
 
2018         } elsif ($pkr->{price} == $pkr->{default_sellprice}) {
 
2019           $pkr->{price}    = $form->{"sellprice_$i"};
 
2020           $pkr->{selected} = ' selected';
 
2024       if ($selectedpricegroup_id or $selectedpricegroup_id == 0) {
 
2025         if ($selectedpricegroup_id ne $pricegroup_old) {
 
2026           if ($pkr->{pricegroup_id} eq $selectedpricegroup_id) {
 
2027             $pkr->{selected}  = ' selected';
 
2029         } elsif (($price_new != $form->{"sellprice_$i"}) and ($price_new ne 0)) {
 
2030           if ($pkr->{pricegroup_id} == 0) {
 
2031             $pkr->{price}     = $form->{"sellprice_$i"};
 
2032             $pkr->{selected}  = ' selected';
 
2034         } elsif ($pkr->{pricegroup_id} eq $selectedpricegroup_id) {
 
2035           $pkr->{selected}  = ' selected';
 
2036           if (    ($pkr->{pricegroup_id} == 0)
 
2037               and ($pkr->{price} == $form->{"sellprice_$i"})) {
 
2038             # $pkr->{price}                         = $form->{"sellprice_$i"};
 
2040             $pkr->{price} = $form->{"sellprice_$i"};
 
2044       push @{ $form->{PRICES}{$i} }, $pkr;
 
2047     $form->{"basefactor_$i"} *= $basefactor;
 
2056   $main::lxdebug->leave_sub();
 
2060   $main::lxdebug->enter_sub();
 
2062   my ($self, $myconfig, $form, $table) = @_;
 
2064   $main::lxdebug->leave_sub() and return 0 unless ($form->{id});
 
2066   # make sure there's no funny stuff in $table
 
2067   # ToDO: die when this happens and throw an error
 
2068   $main::lxdebug->leave_sub() and return 0 if ($table =~ /\W/);
 
2070   my $dbh = $form->dbconnect($myconfig);
 
2072   my $query = qq|SELECT storno FROM $table WHERE storno_id = ?|;
 
2073   my ($result) = selectrow_query($form, $dbh, $query, $form->{id});
 
2077   $main::lxdebug->leave_sub();
 
2083   $main::lxdebug->enter_sub();
 
2085   my ($self, $myconfig, $form, $table, $id) = @_;
 
2087   $main::lxdebug->leave_sub() and return 0 unless ($id);
 
2089   # make sure there's no funny stuff in $table
 
2090   # ToDO: die when this happens and throw an error
 
2091   $main::lxdebug->leave_sub() and return 0 if ($table =~ /\W/);
 
2093   my $dbh = $form->dbconnect($myconfig);
 
2095   my $query = qq|SELECT storno FROM $table WHERE id = ?|;
 
2096   my ($result) = selectrow_query($form, $dbh, $query, $id);
 
2100   $main::lxdebug->leave_sub();