1 #=====================================================================
 
   4 # Based on SQL-Ledger Version 2.1.9
 
   5 # Web http://www.lx-office.org
 
   7 #=====================================================================
 
   8 # SQL-Ledger Accounting
 
  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 Control backend
 
  33 #======================================================================
 
  40   $main::lxdebug->enter_sub();
 
  42   my ($self, $myconfig, $form) = @_;
 
  45   my $dbh = $form->dbconnect($myconfig);
 
  47   my $query = qq|SELECT p.*,
 
  48                  c1.accno AS inventory_accno,
 
  49                  c2.accno AS income_accno,
 
  50                  c3.accno AS expense_accno,
 
  53                  LEFT JOIN chart c1 ON (p.inventory_accno_id = c1.id)
 
  54                  LEFT JOIN chart c2 ON (p.income_accno_id = c2.id)
 
  55                  LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id)
 
  56                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
  58   my @vars = ($form->{id});
 
  59   my $sth = $dbh->prepare($query);
 
  60   $sth->execute(@vars) || $form->dberror("$query (" . join(', ', @vars) . ")");
 
  61   my $ref = $sth->fetchrow_hashref(NAME_lc);
 
  63   # copy to $form variables
 
  64   map { $form->{$_} = $ref->{$_} } (keys %{$ref});
 
  68   my %oid = ('Pg'     => 'a.oid',
 
  69              'Oracle' => 'a.rowid');
 
  71   # part or service item
 
  72   $form->{item} = ($form->{inventory_accno}) ? 'part' : 'service';
 
  73   if ($form->{assembly}) {
 
  74     $form->{item} = 'assembly';
 
  76     # retrieve assembly items
 
  77     $query = qq|SELECT p.id, p.partnumber, p.description,
 
  78                 p.sellprice, p.weight, a.qty, a.bom, p.unit,
 
  81                 JOIN assembly a ON (a.parts_id = p.id)
 
  82                 LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
  85     @vars = ($form->{id}, $oid{$myconfig->{dbdriver}});
 
  86     $sth = $dbh->prepare($query);
 
  87     $sth->execute(@vars) || $form->dberror("$query (" . join(', ', @vars) . ")");
 
  89     $form->{assembly_rows} = 0;
 
  90     while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
  91       $form->{assembly_rows}++;
 
  92       foreach my $key (keys %{$ref}) {
 
  93         $form->{"${key}_$form->{assembly_rows}"} = $ref->{$key};
 
 100   # setup accno hash for <option checked> {amount} is used in create_links
 
 101   $form->{amount}{IC}         = $form->{inventory_accno};
 
 102   $form->{amount}{IC_income}  = $form->{income_accno};
 
 103   $form->{amount}{IC_sale}    = $form->{income_accno};
 
 104   $form->{amount}{IC_expense} = $form->{expense_accno};
 
 105   $form->{amount}{IC_cogs}    = $form->{expense_accno};
 
 109     qq|SELECT p.parts_id, p.pricegroup_id, p.price, (SELECT pg.pricegroup FROM pricegroup pg WHERE pg.id=p.pricegroup_id) AS pricegroup FROM prices p
 
 111               ORDER by pricegroup|;
 
 113   @vars = ($form->{id});
 
 114   $sth = $dbh->prepare($query);
 
 115   $sth->execute(@vars) || $form->dberror("$query (" . join(', ', @vars) . ")");
 
 118   @pricegroups_not_used = ();
 
 123          ($form->{"klass_$i"}, $form->{"pricegroup_id_$i"},
 
 124           $form->{"price_$i"}, $form->{"pricegroup_$i"})
 
 125          = $sth->fetchrow_array
 
 127     $form->{"price_$i"} = $form->round_amount($form->{"price_$i"}, 5);
 
 128     $form->{"price_$i"} =
 
 129       $form->format_amount($myconfig, $form->{"price_$i"}, 5);
 
 130     push @pricegroups, $form->{"pricegroup_id_$i"};
 
 137   $query = qq|SELECT p.id, p.pricegroup FROM pricegroup p|;
 
 139   $pkq = $dbh->prepare($query);
 
 140   $pkq->execute || $form->dberror($query);
 
 141   while ($pkr = $pkq->fetchrow_hashref(NAME_lc)) {
 
 142     push @{ $form->{PRICEGROUPS} }, $pkr;
 
 146   #find not used pricegroups
 
 147   while ($tmp = pop @{ $form->{PRICEGROUPS} }) {
 
 149     foreach $item (@pricegroups) {
 
 150       if ($item eq $tmp->{id}) {
 
 157       push @pricegroups_not_used, $tmp;
 
 161   # if not used pricegroups are avaible
 
 162   if (@pricegroups_not_used) {
 
 164     foreach $name (@pricegroups_not_used) {
 
 165       $form->{"klass_$i"} = "$name->{id}";
 
 166       $form->{"price_$i"} = $form->round_amount($form->{sellprice}, 5);
 
 167       $form->{"price_$i"} =
 
 168         $form->format_amount($myconfig, $form->{"price_$i"}, 5);
 
 169       $form->{"pricegroup_id_$i"} = "$name->{id}";
 
 170       $form->{"pricegroup_$i"}    = "$name->{pricegroup}";
 
 176   $form->{price_rows} = $i - 1;
 
 178   unless ($form->{item} eq 'service') {
 
 181     if ($form->{makemodel}) {
 
 182       $query = qq|SELECT m.make, m.model FROM makemodel m
 
 183                   WHERE m.parts_id = ?|;
 
 184       @vars = ($form->{id});
 
 185       $sth = $dbh->prepare($query);
 
 186       $sth->execute(@vars) || $form->dberror("$query (" . join(', ', @vars) . ")");
 
 189       while (($form->{"make_$i"}, $form->{"model_$i"}) = $sth->fetchrow_array)
 
 194       $form->{makemodel_rows} = $i - 1;
 
 200   $form->{language_values} = "";
 
 201   $query = qq|SELECT language_id, translation FROM translation WHERE parts_id = ?|;
 
 202   @vars = ($form->{id});
 
 203   $trq = $dbh->prepare($query);
 
 204   $trq->execute(@vars) || $form->dberror("$query (" . join(', ', @vars) . ")");
 
 205   while ($tr = $trq->fetchrow_hashref(NAME_lc)) {
 
 206     $form->{language_values} .= "---+++---".$tr->{language_id}."--++--".$tr->{translation};
 
 210   # now get accno for taxes
 
 211   $query = qq|SELECT c.accno
 
 212               FROM chart c, partstax pt
 
 213               WHERE pt.chart_id = c.id
 
 214               AND pt.parts_id = $form->{id}|;
 
 216   $sth = $dbh->prepare($query);
 
 217   $sth->execute || $form->dberror($query);
 
 219   while (($key) = $sth->fetchrow_array) {
 
 220     $form->{amount}{$key} = $key;
 
 226   $query = qq|SELECT i.parts_id
 
 228               WHERE i.parts_id = $form->{id}
 
 232               WHERE o.parts_id = $form->{id}
 
 236               WHERE a.parts_id = $form->{id}|;
 
 237   $sth = $dbh->prepare($query);
 
 238   $sth->execute || $form->dberror($query);
 
 240   ($form->{orphaned}) = $sth->fetchrow_array;
 
 241   $form->{orphaned} = !$form->{orphaned};
 
 244   $form->{"unit_changeable"} = 1;
 
 245   foreach my $table (qw(invoice assembly orderitems inventory license)) {
 
 246     $query = "SELECT COUNT(*) FROM $table WHERE parts_id = ?";
 
 247     my ($count) = $dbh->selectrow_array($query, undef, $form->{"id"});
 
 248     $form->dberror($query . " (" . $form->{"id"} . ")") if ($dbh->err);
 
 251       $form->{"unit_changeable"} = 0;
 
 258   $main::lxdebug->leave_sub();
 
 261 sub get_pricegroups {
 
 262   $main::lxdebug->enter_sub();
 
 264   my ($self, $myconfig, $form) = @_;
 
 265   my $dbh                  = $form->dbconnect($myconfig);
 
 267   my @pricegroups_not_used = ();
 
 270   my $query = qq|SELECT p.id, p.pricegroup FROM pricegroup p|;
 
 272   my $pkq = $dbh->prepare($query);
 
 273   $pkq->execute || $form->dberror($query);
 
 274   while ($pkr = $pkq->fetchrow_hashref(NAME_lc)) {
 
 275     push @{ $form->{PRICEGROUPS} }, $pkr;
 
 279   #find not used pricegroups
 
 280   while ($tmp = pop @{ $form->{PRICEGROUPS} }) {
 
 281     push @pricegroups_not_used, $tmp;
 
 284   # if not used pricegroups are avaible
 
 285   if (@pricegroups_not_used) {
 
 287     foreach $name (@pricegroups_not_used) {
 
 288       $form->{"klass_$i"} = "$name->{id}";
 
 289       $form->{"price_$i"} = $form->round_amount($form->{sellprice}, 5);
 
 290       $form->{"price_$i"} =
 
 291         $form->format_amount($myconfig, $form->{"price_$i"}, 5);
 
 292       $form->{"pricegroup_id_$i"} = "$name->{id}";
 
 293       $form->{"pricegroup_$i"}    = "$name->{pricegroup}";
 
 299   $form->{price_rows} = $i - 1;
 
 303   $main::lxdebug->leave_sub();
 
 306 sub retrieve_buchungsgruppen {
 
 307   $main::lxdebug->enter_sub();
 
 309   my ($self, $myconfig, $form) = @_;
 
 313   my $dbh = $form->dbconnect($myconfig);
 
 315   # get buchungsgruppen
 
 316   $query = qq|SELECT id, description
 
 319   $sth = $dbh->prepare($query);
 
 320   $sth->execute || $form->dberror($query);
 
 322   $form->{BUCHUNGSGRUPPEN} = [];
 
 323   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
 324     push(@{ $form->{BUCHUNGSGRUPPEN} }, $ref);
 
 328   $main::lxdebug->leave_sub();
 
 332   $main::lxdebug->enter_sub();
 
 334   my ($self, $myconfig, $form) = @_;
 
 336   # connect to database, turn off AutoCommit
 
 337   my $dbh = $form->dbconnect_noauto($myconfig);
 
 340   # make up a unique handle and store in partnumber field
 
 341   # then retrieve the record based on the unique handle to get the id
 
 342   # replace the partnumber field with the actual variable
 
 343   # add records for makemodel
 
 345   # if there is a $form->{id} then replace the old entry
 
 346   # delete all makemodel entries and add the new ones
 
 349   map { $form->{$_} =~ s/\'/\'\'/g } qw(partnumber description notes unit);
 
 351   # undo amount formatting
 
 352   map { $form->{$_} = $form->parse_amount($myconfig, $form->{$_}) }
 
 353     qw(rop weight listprice sellprice gv lastcost stock);
 
 355   # set date to NULL if nothing entered
 
 356   $form->{priceupdate} =
 
 357     ($form->{priceupdate}) ? qq|'$form->{priceupdate}'| : "NULL";
 
 359   $form->{makemodel} = (($form->{make_1}) || ($form->{model_1})) ? 1 : 0;
 
 361   $form->{alternate} = 0;
 
 362   $form->{assembly} = ($form->{item} eq 'assembly') ? 1 : 0;
 
 363   $form->{obsolete} *= 1;
 
 365   $form->{onhand}   *= 1;
 
 368   $form->{buchungsgruppen_id}       *= 1;
 
 369   $form->{not_discountable}       *= 1;
 
 370   $form->{payment_id}       *= 1;
 
 377     $query = qq|SELECT p.sellprice, p.weight
 
 379                 WHERE p.id = $form->{id}|;
 
 380     $sth = $dbh->prepare($query);
 
 381     $sth->execute || $form->dberror($query);
 
 382     my ($sellprice, $weight) = $sth->fetchrow_array;
 
 385     # if item is part of an assembly adjust all assemblies
 
 386     $query = qq|SELECT a.id, a.qty
 
 388                 WHERE a.parts_id = $form->{id}|;
 
 389     $sth = $dbh->prepare($query);
 
 390     $sth->execute || $form->dberror($query);
 
 391     while (my ($id, $qty) = $sth->fetchrow_array) {
 
 392       &update_assembly($dbh, $form, $id, $qty, $sellprice * 1, $weight * 1);
 
 396     if ($form->{item} ne 'service') {
 
 398       # delete makemodel records
 
 399       $query = qq|DELETE FROM makemodel
 
 400                   WHERE parts_id = $form->{id}|;
 
 401       $dbh->do($query) || $form->dberror($query);
 
 404     if ($form->{item} eq 'assembly') {
 
 405       if ($form->{onhand} != 0) {
 
 406         &adjust_inventory($dbh, $form, $form->{id}, $form->{onhand} * -1);
 
 409       # delete assembly records
 
 410       $query = qq|DELETE FROM assembly
 
 411                   WHERE id = $form->{id}|;
 
 412       $dbh->do($query) || $form->dberror($query);
 
 414       $form->{onhand} += $form->{stock};
 
 418     $query = qq|DELETE FROM partstax
 
 419                 WHERE parts_id = $form->{id}|;
 
 420     $dbh->do($query) || $form->dberror($query);
 
 422     # delete translations
 
 423     $query = qq|DELETE FROM translation
 
 424                 WHERE parts_id = $form->{id}|;
 
 425     $dbh->do($query) || $form->dberror($query);
 
 428     my $uid = rand() . time;
 
 429     $uid .= $form->{login};
 
 431     $query = qq|SELECT p.id FROM parts p
 
 432                 WHERE p.partnumber = '$form->{partnumber}'|;
 
 433     $sth = $dbh->prepare($query);
 
 434     $sth->execute || $form->dberror($query);
 
 435     ($form->{id}) = $sth->fetchrow_array;
 
 438     if ($form->{id} ne "") {
 
 439       $main::lxdebug->leave_sub();
 
 442     $query = qq|INSERT INTO parts (partnumber, description)
 
 443                 VALUES ('$uid', 'dummy')|;
 
 444     $dbh->do($query) || $form->dberror($query);
 
 446     $query = qq|SELECT p.id FROM parts p
 
 447                 WHERE p.partnumber = '$uid'|;
 
 448     $sth = $dbh->prepare($query);
 
 449     $sth->execute || $form->dberror($query);
 
 451     ($form->{id}) = $sth->fetchrow_array;
 
 454     $form->{orphaned} = 1;
 
 455     $form->{onhand} = $form->{stock} if $form->{item} eq 'assembly';
 
 456     if ($form->{partnumber} eq "" && $form->{"item"} eq "service") {
 
 457       $form->{partnumber} = $form->update_defaults($myconfig, "servicenumber");
 
 459     if ($form->{partnumber} eq "" && $form->{"item"} ne "service") {
 
 460       $form->{partnumber} = $form->update_defaults($myconfig, "articlenumber");
 
 464   my $partsgroup_id = 0;
 
 466   if ($form->{partsgroup}) {
 
 467     ($partsgroup, $partsgroup_id) = split /--/, $form->{partsgroup};
 
 470   my ($subq_inventory, $subq_expense, $subq_income);
 
 471   if ($form->{"item"} eq "part") {
 
 473       qq|(SELECT bg.inventory_accno_id | .
 
 474       qq| FROM buchungsgruppen bg | .
 
 475       qq| WHERE bg.id = | . $dbh->quote($form->{"buchungsgruppen_id"}) . qq|)|;
 
 477     $subq_inventory = "NULL";
 
 480   if ($form->{"item"} ne "assembly") {
 
 482       qq|(SELECT bg.expense_accno_id_0 | .
 
 483       qq| FROM buchungsgruppen bg | .
 
 484       qq| WHERE bg.id = | . $dbh->quote($form->{"buchungsgruppen_id"}) . qq|)|;
 
 486     $subq_expense = "NULL";
 
 490     qq|(SELECT bg.income_accno_id_0 | .
 
 491     qq| FROM buchungsgruppen bg | .
 
 492     qq| WHERE bg.id = | . $dbh->quote($form->{"buchungsgruppen_id"}) . qq|)|;
 
 494   $query = qq|UPDATE parts SET
 
 495               partnumber = '$form->{partnumber}',
 
 496               description = '$form->{description}',
 
 497               makemodel = '$form->{makemodel}',
 
 498               alternate = '$form->{alternate}',
 
 499               assembly = '$form->{assembly}',
 
 500               listprice = $form->{listprice},
 
 501               sellprice = $form->{sellprice},
 
 502               lastcost = $form->{lastcost},
 
 503               weight = $form->{weight},
 
 504               priceupdate = $form->{priceupdate},
 
 505               unit = '$form->{unit}',
 
 506               notes = '$form->{notes}',
 
 507               formel = '$form->{formel}',
 
 509               bin = '$form->{bin}',
 
 510               buchungsgruppen_id = '$form->{buchungsgruppen_id}',
 
 511               payment_id = '$form->{payment_id}',
 
 512               inventory_accno_id = $subq_inventory,
 
 513               income_accno_id = $subq_income,
 
 514               expense_accno_id = $subq_expense,
 
 515               obsolete = '$form->{obsolete}',
 
 516               image = '$form->{image}',
 
 517               drawing = '$form->{drawing}',
 
 518               shop = '$form->{shop}',
 
 521               ean = '$form->{ean}',
 
 522               not_discountable = '$form->{not_discountable}',
 
 523               microfiche = '$form->{microfiche}',
 
 524               partsgroup_id = $partsgroup_id
 
 525               WHERE id = $form->{id}|;
 
 526   $dbh->do($query) || $form->dberror($query);
 
 528   # delete translation records
 
 529   $query = qq|DELETE FROM translation
 
 530               WHERE parts_id = $form->{id}|;
 
 531   $dbh->do($query) || $form->dberror($query);
 
 533   if ($form->{language_values} ne "") {
 
 534     split /---\+\+\+---/,$form->{language_values};
 
 536       my ($language_id, $translation, $longdescription) = split /--\+\+--/, $item;
 
 537       if ($translation ne "") {
 
 538         $query = qq|INSERT into translation (parts_id, language_id, translation, longdescription) VALUES
 
 539                     ($form->{id}, $language_id, | . $dbh->quote($translation) . qq|, | . $dbh->quote($longdescription) . qq| )|;
 
 540         $dbh->do($query) || $form->dberror($query);
 
 544   # delete price records
 
 545   $query = qq|DELETE FROM prices
 
 546               WHERE parts_id = $form->{id}|;
 
 547   $dbh->do($query) || $form->dberror($query);
 
 548   # insert price records only if different to sellprice
 
 549   for my $i (1 .. $form->{price_rows}) {
 
 550     if ($form->{"price_$i"} eq "0") {
 
 551       $form->{"price_$i"} = $form->{sellprice};
 
 554         (   $form->{"price_$i"}
 
 555          || $form->{"klass_$i"}
 
 556          || $form->{"pricegroup_id_$i"})
 
 557         and $form->{"price_$i"} != $form->{sellprice}
 
 559       $klass = $form->parse_amount($myconfig, $form->{"klass_$i"});
 
 560       $price = $form->parse_amount($myconfig, $form->{"price_$i"});
 
 562         $form->parse_amount($myconfig, $form->{"pricegroup_id_$i"});
 
 563       $query = qq|INSERT INTO prices (parts_id, pricegroup_id, price)
 
 564                   VALUES($form->{id},$pricegroup_id,$price)|;
 
 565       $dbh->do($query) || $form->dberror($query);
 
 569   # insert makemodel records
 
 570   unless ($form->{item} eq 'service') {
 
 571     for my $i (1 .. $form->{makemodel_rows}) {
 
 572       if (($form->{"make_$i"}) || ($form->{"model_$i"})) {
 
 573         map { $form->{"${_}_$i"} =~ s/\'/\'\'/g } qw(make model);
 
 575         $query = qq|INSERT INTO makemodel (parts_id, make, model)
 
 577                     '$form->{"make_$i"}', '$form->{"model_$i"}')|;
 
 578         $dbh->do($query) || $form->dberror($query);
 
 584   foreach $item (split / /, $form->{taxaccounts}) {
 
 585     if ($form->{"IC_tax_$item"}) {
 
 586       $query = qq|INSERT INTO partstax (parts_id, chart_id)
 
 590                            WHERE c.accno = '$item'))|;
 
 591       $dbh->do($query) || $form->dberror($query);
 
 595   # add assembly records
 
 596   if ($form->{item} eq 'assembly') {
 
 598     for my $i (1 .. $form->{assembly_rows}) {
 
 599       $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
 
 601       if ($form->{"qty_$i"} != 0) {
 
 602         $form->{"bom_$i"} *= 1;
 
 603         $query = qq|INSERT INTO assembly (id, parts_id, qty, bom)
 
 604                     VALUES ($form->{id}, $form->{"id_$i"},
 
 605                     $form->{"qty_$i"}, '$form->{"bom_$i"}')|;
 
 606         $dbh->do($query) || $form->dberror($query);
 
 610     # adjust onhand for the parts
 
 611     if ($form->{onhand} != 0) {
 
 612       &adjust_inventory($dbh, $form, $form->{id}, $form->{onhand});
 
 618     my $shippingdate = "$a[5]-$a[4]-$a[3]";
 
 620     $form->get_employee($dbh);
 
 622     # add inventory record
 
 623     $query = qq|INSERT INTO inventory (warehouse_id, parts_id, qty,
 
 624                 shippingdate, employee_id) VALUES (
 
 625                 0, $form->{id}, $form->{stock}, '$shippingdate',
 
 626                 $form->{employee_id})|;
 
 627     $dbh->do($query) || $form->dberror($query);
 
 631   #set expense_accno=inventory_accno if they are different => bilanz
 
 633     ($form->{expense_accno} != $form->{inventory_accno})
 
 634     ? $form->{inventory_accno}
 
 635     : $form->{expense_accno};
 
 637   # get tax rates and description
 
 639     ($form->{vc} eq "customer") ? $form->{income_accno} : $vendor_accno;
 
 640   $query = qq|SELECT c.accno, c.description, t.rate, t.taxnumber
 
 642               WHERE c.id=t.chart_id AND t.taxkey in (SELECT taxkey_id from chart where accno = '$accno_id')
 
 644   $stw = $dbh->prepare($query);
 
 646   $stw->execute || $form->dberror($query);
 
 648   $form->{taxaccount} = "";
 
 649   while ($ptr = $stw->fetchrow_hashref(NAME_lc)) {
 
 651     #    if ($customertax{$ref->{accno}}) {
 
 652     $form->{taxaccount} .= "$ptr->{accno} ";
 
 653     if (!($form->{taxaccount2} =~ /$ptr->{accno}/)) {
 
 654       $form->{"$ptr->{accno}_rate"}        = $ptr->{rate};
 
 655       $form->{"$ptr->{accno}_description"} = $ptr->{description};
 
 656       $form->{"$ptr->{accno}_taxnumber"}   = $ptr->{taxnumber};
 
 657       $form->{taxaccount2} .= " $ptr->{accno} ";
 
 663   my $rc = $dbh->commit;
 
 666   $main::lxdebug->leave_sub();
 
 671 sub update_assembly {
 
 672   $main::lxdebug->enter_sub();
 
 674   my ($dbh, $form, $id, $qty, $sellprice, $weight) = @_;
 
 676   my $query = qq|SELECT a.id, a.qty
 
 678                  WHERE a.parts_id = $id|;
 
 679   my $sth = $dbh->prepare($query);
 
 680   $sth->execute || $form->dberror($query);
 
 682   while (my ($pid, $aqty) = $sth->fetchrow_array) {
 
 683     &update_assembly($dbh, $form, $pid, $aqty * $qty, $sellprice, $weight);
 
 687   $query = qq|UPDATE parts
 
 688               SET sellprice = sellprice +
 
 689                   $qty * ($form->{sellprice} - $sellprice),
 
 691                   $qty * ($form->{weight} - $weight)
 
 693   $dbh->do($query) || $form->dberror($query);
 
 695   $main::lxdebug->leave_sub();
 
 698 sub retrieve_assemblies {
 
 699   $main::lxdebug->enter_sub();
 
 701   my ($self, $myconfig, $form) = @_;
 
 703   # connect to database
 
 704   my $dbh = $form->dbconnect($myconfig);
 
 708   if ($form->{partnumber}) {
 
 709     my $partnumber = $form->like(lc $form->{partnumber});
 
 710     $where .= " AND lower(p.partnumber) LIKE '$partnumber'";
 
 713   if ($form->{description}) {
 
 714     my $description = $form->like(lc $form->{description});
 
 715     $where .= " AND lower(p.description) LIKE '$description'";
 
 717   $where .= " AND NOT p.obsolete = '1'";
 
 719   # retrieve assembly items
 
 720   my $query = qq|SELECT p.id, p.partnumber, p.description,
 
 721                  p.bin, p.onhand, p.rop,
 
 722                    (SELECT sum(p2.inventory_accno_id)
 
 723                     FROM parts p2, assembly a
 
 724                     WHERE p2.id = a.parts_id
 
 725                     AND a.id = p.id) AS inventory
 
 730   my $sth = $dbh->prepare($query);
 
 731   $sth->execute || $form->dberror($query);
 
 733   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
 734     push @{ $form->{assembly_items} }, $ref if $ref->{inventory};
 
 740   $main::lxdebug->leave_sub();
 
 743 sub restock_assemblies {
 
 744   $main::lxdebug->enter_sub();
 
 746   my ($self, $myconfig, $form) = @_;
 
 748   # connect to database
 
 749   my $dbh = $form->dbconnect_noauto($myconfig);
 
 751   for my $i (1 .. $form->{rowcount}) {
 
 753     $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
 
 755     if ($form->{"qty_$i"} != 0) {
 
 756       &adjust_inventory($dbh, $form, $form->{"id_$i"}, $form->{"qty_$i"});
 
 761   my $rc = $dbh->commit;
 
 764   $main::lxdebug->leave_sub();
 
 769 sub adjust_inventory {
 
 770   $main::lxdebug->enter_sub();
 
 772   my ($dbh, $form, $id, $qty) = @_;
 
 774   my $query = qq|SELECT p.id, p.inventory_accno_id, p.assembly, a.qty
 
 775                  FROM parts p, assembly a
 
 776                  WHERE a.parts_id = p.id
 
 778   my $sth = $dbh->prepare($query);
 
 779   $sth->execute || $form->dberror($query);
 
 781   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
 783     my $allocate = $qty * $ref->{qty};
 
 785     # is it a service item, then loop
 
 786     $ref->{inventory_accno_id} *= 1;
 
 787     next if (($ref->{inventory_accno_id} == 0) && !$ref->{assembly});
 
 789     # adjust parts onhand
 
 790     $form->update_balance($dbh, "parts", "onhand",
 
 798   my $rc = $form->update_balance($dbh, "parts", "onhand", qq|id = $id|, $qty);
 
 800   $main::lxdebug->leave_sub();
 
 806   $main::lxdebug->enter_sub();
 
 808   my ($self, $myconfig, $form) = @_;
 
 810   # connect to database, turn off AutoCommit
 
 811   my $dbh = $form->dbconnect_noauto($myconfig);
 
 813   # first delete prices of pricegroup 
 
 814   my $query = qq|DELETE FROM prices
 
 815            WHERE parts_id = $form->{id}|;
 
 816   $dbh->do($query) || $form->dberror($query);
 
 818   my $query = qq|DELETE FROM parts
 
 819                  WHERE id = $form->{id}|;
 
 820   $dbh->do($query) || $form->dberror($query);
 
 822   $query = qq|DELETE FROM partstax
 
 823               WHERE parts_id = $form->{id}|;
 
 824   $dbh->do($query) || $form->dberror($query);
 
 826   # check if it is a part, assembly or service
 
 827   if ($form->{item} ne 'service') {
 
 828     $query = qq|DELETE FROM makemodel
 
 829                 WHERE parts_id = $form->{id}|;
 
 830     $dbh->do($query) || $form->dberror($query);
 
 833   if ($form->{item} eq 'assembly') {
 
 836     $query = qq|DELETE FROM inventory
 
 837                 WHERE parts_id = $form->{id}|;
 
 838     $dbh->do($query) || $form->dberror($query);
 
 840     $query = qq|DELETE FROM assembly
 
 841                 WHERE id = $form->{id}|;
 
 842     $dbh->do($query) || $form->dberror($query);
 
 845   if ($form->{item} eq 'alternate') {
 
 846     $query = qq|DELETE FROM alternate
 
 847                 WHERE id = $form->{id}|;
 
 848     $dbh->do($query) || $form->dberror($query);
 
 852   my $rc = $dbh->commit;
 
 855   $main::lxdebug->leave_sub();
 
 861   $main::lxdebug->enter_sub();
 
 863   my ($self, $myconfig, $form) = @_;
 
 865   my $i = $form->{assembly_rows};
 
 869   if ($form->{"partnumber_$i"}) {
 
 870     $var = $form->like(lc $form->{"partnumber_$i"});
 
 871     $where .= " AND lower(p.partnumber) LIKE '$var'";
 
 873   if ($form->{"description_$i"}) {
 
 874     $var = $form->like(lc $form->{"description_$i"});
 
 875     $where .= " AND lower(p.description) LIKE '$var'";
 
 877   if ($form->{"partsgroup_$i"}) {
 
 878     $var = $form->like(lc $form->{"partsgroup_$i"});
 
 879     $where .= " AND lower(pg.partsgroup) LIKE '$var'";
 
 883     $where .= " AND NOT p.id = $form->{id}";
 
 887     $where .= " ORDER BY p.partnumber";
 
 889     $where .= " ORDER BY p.description";
 
 892   # connect to database
 
 893   my $dbh = $form->dbconnect($myconfig);
 
 895   my $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
 
 896                  p.weight, p.onhand, p.unit,
 
 899                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
 901   my $sth = $dbh->prepare($query);
 
 902   $sth->execute || $form->dberror($query);
 
 904   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
 905     push @{ $form->{item_list} }, $ref;
 
 911   $main::lxdebug->leave_sub();
 
 915   $main::lxdebug->enter_sub();
 
 917   my ($self, $myconfig, $form) = @_;
 
 925   foreach my $item (qw(partnumber drawing microfiche)) {
 
 926     if ($form->{$item}) {
 
 927       $var = $form->like(lc $form->{$item});
 
 928       $where .= " AND lower(p.$item) LIKE '$var'";
 
 932   # special case for description
 
 933   if ($form->{description}) {
 
 934     unless (   $form->{bought}
 
 939             || $form->{quoted}) {
 
 940       $var = $form->like(lc $form->{description});
 
 941       $where .= " AND lower(p.description) LIKE '$var'";
 
 945   # special case for serialnumber
 
 946   if ($form->{l_serialnumber}) {
 
 947     if ($form->{serialnumber}) {
 
 948       $var = $form->like(lc $form->{serialnumber});
 
 949       $where .= " AND lower(serialnumber) LIKE '$var'";
 
 954     $var = $form->like(lc $form->{ean});
 
 955     $where .= " AND lower(ean) LIKE '$var'";
 
 958   if ($form->{searchitems} eq 'part') {
 
 959     $where .= " AND p.inventory_accno_id > 0";
 
 961   if ($form->{searchitems} eq 'assembly') {
 
 962     $form->{bought} = "";
 
 963     $where .= " AND p.assembly = '1'";
 
 965   if ($form->{searchitems} eq 'service') {
 
 966     $where .= " AND p.inventory_accno_id IS NULL AND NOT p.assembly = '1'";
 
 968     # irrelevant for services
 
 969     $form->{make} = $form->{model} = "";
 
 972   # items which were never bought, sold or on an order
 
 973   if ($form->{itemstatus} eq 'orphaned') {
 
 974     $form->{onhand}  = $form->{short}   = 0;
 
 975     $form->{bought}  = $form->{sold}    = 0;
 
 976     $form->{onorder} = $form->{ordered} = 0;
 
 977     $form->{rfq}     = $form->{quoted}  = 0;
 
 979     $form->{transdatefrom} = $form->{transdateto} = "";
 
 981     $where .= " AND p.onhand = 0
 
 982                 AND p.id NOT IN (SELECT p.id FROM parts p, invoice i
 
 983                                  WHERE p.id = i.parts_id)
 
 984                 AND p.id NOT IN (SELECT p.id FROM parts p, assembly a
 
 985                                  WHERE p.id = a.parts_id)
 
 986                 AND p.id NOT IN (SELECT p.id FROM parts p, orderitems o
 
 987                                  WHERE p.id = o.parts_id)";
 
 990   if ($form->{itemstatus} eq 'active') {
 
 991     $where .= " AND p.obsolete = '0'";
 
 993   if ($form->{itemstatus} eq 'obsolete') {
 
 994     $where .= " AND p.obsolete = '1'";
 
 995     $form->{onhand} = $form->{short} = 0;
 
 997   if ($form->{itemstatus} eq 'onhand') {
 
 998     $where .= " AND p.onhand > 0";
 
1000   if ($form->{itemstatus} eq 'short') {
 
1001     $where .= " AND p.onhand < p.rop";
 
1003   if ($form->{make}) {
 
1004     $var = $form->like(lc $form->{make});
 
1005     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
 
1006                            FROM makemodel m WHERE lower(m.make) LIKE '$var')";
 
1008   if ($form->{model}) {
 
1009     $var = $form->like(lc $form->{model});
 
1010     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
 
1011                            FROM makemodel m WHERE lower(m.model) LIKE '$var')";
 
1013   if ($form->{partsgroup}) {
 
1014     $var = $form->like(lc $form->{partsgroup});
 
1015     $where .= " AND lower(pg.partsgroup) LIKE '$var'";
 
1017   if ($form->{l_soldtotal}) {
 
1018     $where .= " AND p.id=i.parts_id AND  i.qty >= 0";
 
1020       " GROUP BY  p.id,p.partnumber,p.description,p.onhand,p.unit,p.bin, p.sellprice,p.listprice,p.lastcost,p.priceupdate,pg.partsgroup";
 
1022   if ($form->{top100}) {
 
1023     $limit = " LIMIT 100";
 
1027   if ($form->{revers} == 1) {
 
1028     $form->{desc} = " DESC";
 
1033   # connect to database
 
1034   my $dbh = $form->dbconnect($myconfig);
 
1036   my $sortorder = $form->{sort};
 
1037   $sortorder .= $form->{desc};
 
1038   $sortorder = $form->{sort} if $form->{sort};
 
1042   if ($form->{l_soldtotal}) {
 
1043     $form->{soldtotal} = 'soldtotal';
 
1045       qq|SELECT p.id,p.partnumber,p.description,p.onhand,p.unit,p.bin,p.sellprice,p.listprice,
 
1046                 p.lastcost,p.priceupdate,pg.partsgroup,sum(i.qty) as soldtotal FROM parts
 
1047                 p LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id), invoice i
 
1053     $query = qq|SELECT p.id, p.partnumber, p.description, p.onhand, p.unit,
 
1054                  p.bin, p.sellprice, p.listprice, p.lastcost, p.rop, p.weight,
 
1055                  p.priceupdate, p.image, p.drawing, p.microfiche,
 
1058                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1061                  ORDER BY $sortorder|;
 
1064   # rebuild query for bought and sold items
 
1065   if (   $form->{bought}
 
1070       || $form->{quoted}) {
 
1072     my @a = qw(partnumber description bin priceupdate name);
 
1074     push @a, qw(invnumber serialnumber) if ($form->{bought} || $form->{sold});
 
1075     push @a, "ordnumber" if ($form->{onorder} || $form->{ordered});
 
1076     push @a, "quonumber" if ($form->{rfq}     || $form->{quoted});
 
1081     if ($form->{bought} || $form->{sold}) {
 
1083       my $invwhere = "$where";
 
1084       $invwhere .= " AND i.assemblyitem = '0'";
 
1085       $invwhere .= " AND a.transdate >= '$form->{transdatefrom}'"
 
1086         if $form->{transdatefrom};
 
1087       $invwhere .= " AND a.transdate <= '$form->{transdateto}'"
 
1088         if $form->{transdateto};
 
1090       if ($form->{description}) {
 
1091         $var = $form->like(lc $form->{description});
 
1092         $invwhere .= " AND lower(i.description) LIKE '$var'";
 
1095       my $flds = qq|p.id, p.partnumber, i.description, i.serialnumber,
 
1096                     i.qty AS onhand, i.unit, p.bin, i.sellprice,
 
1097                     p.listprice, p.lastcost, p.rop, p.weight,
 
1098                     p.priceupdate, p.image, p.drawing, p.microfiche,
 
1100                     a.invnumber, a.ordnumber, a.quonumber, i.trans_id,
 
1101                     ct.name, i.deliverydate|;
 
1103       if ($form->{bought}) {
 
1105                     SELECT $flds, 'ir' AS module, '' AS type,
 
1108                     JOIN parts p ON (p.id = i.parts_id)
 
1109                     JOIN ap a ON (a.id = i.trans_id)
 
1110                     JOIN vendor ct ON (a.vendor_id = ct.id)
 
1111                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1117       if ($form->{sold}) {
 
1119                      SELECT $flds, 'is' AS module, '' AS type,
 
1122                      JOIN parts p ON (p.id = i.parts_id)
 
1123                      JOIN ar a ON (a.id = i.trans_id)
 
1124                      JOIN customer ct ON (a.customer_id = ct.id)
 
1125                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1132     if ($form->{onorder} || $form->{ordered}) {
 
1133       my $ordwhere = "$where
 
1134                      AND o.quotation = '0'";
 
1135       $ordwhere .= " AND o.transdate >= '$form->{transdatefrom}'"
 
1136         if $form->{transdatefrom};
 
1137       $ordwhere .= " AND o.transdate <= '$form->{transdateto}'"
 
1138         if $form->{transdateto};
 
1140       if ($form->{description}) {
 
1141         $var = $form->like(lc $form->{description});
 
1142         $ordwhere .= " AND lower(oi.description) LIKE '$var'";
 
1146         qq|p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber,
 
1147                  oi.qty AS onhand, oi.unit, p.bin, oi.sellprice,
 
1148                  p.listprice, p.lastcost, p.rop, p.weight,
 
1149                  p.priceupdate, p.image, p.drawing, p.microfiche,
 
1151                  '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
 
1152                  ct.name, NULL AS deliverydate|;
 
1154       if ($form->{ordered}) {
 
1156                      SELECT $flds, 'oe' AS module, 'sales_order' AS type,
 
1157                     (SELECT buy FROM exchangerate ex
 
1158                      WHERE ex.curr = o.curr
 
1159                      AND ex.transdate = o.transdate) AS exchangerate
 
1161                      JOIN parts p ON (oi.parts_id = p.id)
 
1162                      JOIN oe o ON (oi.trans_id = o.id)
 
1163                      JOIN customer ct ON (o.customer_id = ct.id)
 
1164                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1166                      AND o.customer_id > 0|;
 
1171       if ($form->{onorder}) {
 
1173           qq|p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber,
 
1174                    oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice,
 
1175                    p.listprice, p.lastcost, p.rop, p.weight,
 
1176                    p.priceupdate, p.image, p.drawing, p.microfiche,
 
1178                    '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
 
1179                    ct.name, NULL AS deliverydate|;
 
1182                     SELECT $flds, 'oe' AS module, 'purchase_order' AS type,
 
1183                     (SELECT sell FROM exchangerate ex
 
1184                      WHERE ex.curr = o.curr
 
1185                      AND ex.transdate = o.transdate) AS exchangerate
 
1187                     JOIN parts p ON (oi.parts_id = p.id)
 
1188                     JOIN oe o ON (oi.trans_id = o.id)
 
1189                     JOIN vendor ct ON (o.vendor_id = ct.id)
 
1190                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1192                     AND o.vendor_id > 0|;
 
1197     if ($form->{rfq} || $form->{quoted}) {
 
1198       my $quowhere = "$where
 
1199                      AND o.quotation = '1'";
 
1200       $quowhere .= " AND o.transdate >= '$form->{transdatefrom}'"
 
1201         if $form->{transdatefrom};
 
1202       $quowhere .= " AND o.transdate <= '$form->{transdateto}'"
 
1203         if $form->{transdateto};
 
1205       if ($form->{description}) {
 
1206         $var = $form->like(lc $form->{description});
 
1207         $quowhere .= " AND lower(oi.description) LIKE '$var'";
 
1211         qq|p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber,
 
1212                  oi.qty AS onhand, oi.unit, p.bin, oi.sellprice,
 
1213                  p.listprice, p.lastcost, p.rop, p.weight,
 
1214                  p.priceupdate, p.image, p.drawing, p.microfiche,
 
1216                  '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
 
1217                  ct.name, NULL AS deliverydate|;
 
1219       if ($form->{quoted}) {
 
1221                      SELECT $flds, 'oe' AS module, 'sales_quotation' AS type,
 
1222                     (SELECT buy FROM exchangerate ex
 
1223                      WHERE ex.curr = o.curr
 
1224                      AND ex.transdate = o.transdate) AS exchangerate
 
1226                      JOIN parts p ON (oi.parts_id = p.id)
 
1227                      JOIN oe o ON (oi.trans_id = o.id)
 
1228                      JOIN customer ct ON (o.customer_id = ct.id)
 
1229                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1231                      AND o.customer_id > 0|;
 
1238           qq|p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber,
 
1239                    oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice,
 
1240                    p.listprice, p.lastcost, p.rop, p.weight,
 
1241                    p.priceupdate, p.image, p.drawing, p.microfiche,
 
1243                    '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
 
1244                    ct.name, NULL AS deliverydate|;
 
1247                     SELECT $flds, 'oe' AS module, 'request_quotation' AS type,
 
1248                     (SELECT sell FROM exchangerate ex
 
1249                      WHERE ex.curr = o.curr
 
1250                      AND ex.transdate = o.transdate) AS exchangerate
 
1252                     JOIN parts p ON (oi.parts_id = p.id)
 
1253                     JOIN oe o ON (oi.trans_id = o.id)
 
1254                     JOIN vendor ct ON (o.vendor_id = ct.id)
 
1255                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1257                     AND o.vendor_id > 0|;
 
1262                  ORDER BY $sortorder|;
 
1265   my $sth = $dbh->prepare($query);
 
1266   $sth->execute || $form->dberror($query);
 
1268   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1269     push @{ $form->{parts} }, $ref;
 
1274   # include individual items for assemblies
 
1275   if ($form->{searchitems} eq 'assembly' && $form->{bom}) {
 
1276     foreach $item (@{ $form->{parts} }) {
 
1277       push @assemblies, $item;
 
1278       $query = qq|SELECT p.id, p.partnumber, p.description, a.qty AS onhand,
 
1280                   p.sellprice, p.listprice, p.lastcost,
 
1281                   p.rop, p.weight, p.priceupdate,
 
1282                   p.image, p.drawing, p.microfiche
 
1283                   FROM parts p, assembly a
 
1284                   WHERE p.id = a.parts_id
 
1285                   AND a.id = $item->{id}|;
 
1287       $sth = $dbh->prepare($query);
 
1288       $sth->execute || $form->dberror($query);
 
1290       while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1291         $ref->{assemblyitem} = 1;
 
1292         push @assemblies, $ref;
 
1296       push @assemblies, { id => $item->{id} };
 
1300     # copy assemblies to $form->{parts}
 
1301     @{ $form->{parts} } = @assemblies;
 
1305   $main::lxdebug->leave_sub();
 
1309   $main::lxdebug->enter_sub();
 
1311   my ($self, $myconfig, $form) = @_;
 
1313   my $where = '1 = 1';
 
1319   foreach my $item (qw(partnumber drawing microfiche make model)) {
 
1320     if ($form->{$item}) {
 
1321       $var = $form->like(lc $form->{$item});
 
1323       # make will build later Bugfix 145
 
1324       if ($item ne 'make') {
 
1325         $where .= " AND lower(p.$item) LIKE '$var'";
 
1330   # special case for description
 
1331   if ($form->{description}) {
 
1332     unless (   $form->{bought}
 
1337             || $form->{quoted}) {
 
1338       $var = $form->like(lc $form->{description});
 
1339       $where .= " AND lower(p.description) LIKE '$var'";
 
1343   # special case for serialnumber
 
1344   if ($form->{l_serialnumber}) {
 
1345     if ($form->{serialnumber}) {
 
1346       $var = $form->like(lc $form->{serialnumber});
 
1347       $where .= " AND lower(serialnumber) LIKE '$var'";
 
1352   # items which were never bought, sold or on an order
 
1353   if ($form->{itemstatus} eq 'orphaned') {
 
1354     $form->{onhand}  = $form->{short}   = 0;
 
1355     $form->{bought}  = $form->{sold}    = 0;
 
1356     $form->{onorder} = $form->{ordered} = 0;
 
1357     $form->{rfq}     = $form->{quoted}  = 0;
 
1359     $form->{transdatefrom} = $form->{transdateto} = "";
 
1361     $where .= " AND p.onhand = 0
 
1362                 AND p.id NOT IN (SELECT p.id FROM parts p, invoice i
 
1363                                  WHERE p.id = i.parts_id)
 
1364                 AND p.id NOT IN (SELECT p.id FROM parts p, assembly a
 
1365                                  WHERE p.id = a.parts_id)
 
1366                 AND p.id NOT IN (SELECT p.id FROM parts p, orderitems o
 
1367                                  WHERE p.id = o.parts_id)";
 
1370   if ($form->{itemstatus} eq 'active') {
 
1371     $where .= " AND p.obsolete = '0'";
 
1373   if ($form->{itemstatus} eq 'obsolete') {
 
1374     $where .= " AND p.obsolete = '1'";
 
1375     $form->{onhand} = $form->{short} = 0;
 
1377   if ($form->{itemstatus} eq 'onhand') {
 
1378     $where .= " AND p.onhand > 0";
 
1380   if ($form->{itemstatus} eq 'short') {
 
1381     $where .= " AND p.onhand < p.rop";
 
1383   if ($form->{make}) {
 
1384     $var = $form->like(lc $form->{make});
 
1385     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
 
1386                            FROM makemodel m WHERE lower(m.make) LIKE '$var')";
 
1388   if ($form->{model}) {
 
1389     $var = $form->like(lc $form->{model});
 
1390     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
 
1391                            FROM makemodel m WHERE lower(m.model) LIKE '$var')";
 
1393   if ($form->{partsgroup}) {
 
1394     $var = $form->like(lc $form->{partsgroup});
 
1395     $where .= " AND lower(pg.partsgroup) LIKE '$var'";
 
1399   # connect to database
 
1400   my $dbh = $form->dbconnect_noauto($myconfig);
 
1402   if ($form->{"sellprice"} ne "") {
 
1404     my $faktor = $form->parse_amount($myconfig,$form->{"sellprice"});
 
1405     if ($form->{"sellprice_type"} eq "percent") {
 
1406       my $faktor = $form->parse_amount($myconfig,$form->{"sellprice"})/100 +1;
 
1407       $update = "sellprice* $faktor";
 
1409       $update = "sellprice+$faktor";
 
1412     $query = qq|UPDATE parts set sellprice=$update WHERE id IN (SELECT p.id
 
1414                   LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1419   if ($form->{"listprice"} ne "") {
 
1421     my $faktor = $form->parse_amount($myconfig,$form->{"listprice"});
 
1422     if ($form->{"listprice_type"} eq "percent") {
 
1423       my $faktor = $form->parse_amount($myconfig,$form->{"sellprice"})/100 +1;
 
1424       $update = "listprice* $faktor";
 
1426       $update = "listprice+$faktor";
 
1429     $query = qq|UPDATE parts set listprice=$update WHERE id IN (SELECT p.id
 
1431                   LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1440   for my $i (1 .. $form->{price_rows}) {
 
1445     if ($form->{"price_$i"} ne "") {
 
1447       my $faktor = $form->parse_amount($myconfig,$form->{"price_$i"});
 
1448       if ($form->{"pricegroup_type_$i"} eq "percent") {
 
1449         my $faktor = $form->parse_amount($myconfig,$form->{"sellprice"})/100 +1;
 
1450         $update = "price* $faktor";
 
1452         $update = "price+$faktor";
 
1455       $query = qq|UPDATE prices set price=$update WHERE parts_id IN (SELECT p.id
 
1457                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1458                     WHERE $where) AND pricegroup_id=$form->{"pricegroup_id_$i"}|;
 
1466   my $rc= $dbh->commit;
 
1468   $main::lxdebug->leave_sub();
 
1474   $main::lxdebug->enter_sub();
 
1476   my ($self, $module, $myconfig, $form) = @_;
 
1478   # connect to database
 
1479   my $dbh = $form->dbconnect($myconfig);
 
1482     $query = qq|SELECT c.accno, c.description, c.link, c.id,
 
1483                         p.inventory_accno_id, p.income_accno_id, p.expense_accno_id
 
1484                         FROM chart c, parts p
 
1485                         WHERE c.link LIKE '%$module%'
 
1486                         AND p.id = $form->{id}
 
1489     $query = qq|SELECT c.accno, c.description, c.link, c.id,
 
1490                 d.inventory_accno_id, d.income_accno_id, d.expense_accno_id
 
1491                 FROM chart c, defaults d
 
1492                 WHERE c.link LIKE '%$module%'
 
1496   my $sth = $dbh->prepare($query);
 
1497   $sth->execute || $form->dberror($query);
 
1498   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1499     foreach my $key (split /:/, $ref->{link}) {
 
1500       if ($key =~ /$module/) {
 
1501         if (   ($ref->{id} eq $ref->{inventory_accno_id})
 
1502             || ($ref->{id} eq $ref->{income_accno_id})
 
1503             || ($ref->{id} eq $ref->{expense_accno_id})) {
 
1504           push @{ $form->{"${module}_links"}{$key} },
 
1505             { accno       => $ref->{accno},
 
1506               description => $ref->{description},
 
1507               selected    => "selected" };
 
1508           $form->{"${key}_default"} = "$ref->{accno}--$ref->{description}";
 
1510           push @{ $form->{"${module}_links"}{$key} },
 
1511             { accno       => $ref->{accno},
 
1512               description => $ref->{description},
 
1520   # get buchungsgruppen
 
1521   $query = qq|SELECT id, description
 
1522               FROM buchungsgruppen|;
 
1523   $sth = $dbh->prepare($query);
 
1524   $sth->execute || $form->dberror($query);
 
1526   $form->{BUCHUNGSGRUPPEN} = [];
 
1527   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1528     push @{ $form->{BUCHUNGSGRUPPEN} }, $ref;
 
1533   $query = qq|SELECT id, description
 
1536   $sth = $dbh->prepare($query);
 
1537   $sth->execute || $form->dberror($query);
 
1539   while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1540     push @{ $self->{payment_terms} }, $ref;
 
1545     $query = qq|SELECT current_date FROM defaults|;
 
1546     $sth = $dbh->prepare($query);
 
1547     $sth->execute || $form->dberror($query);
 
1549     ($form->{priceupdate}) = $sth->fetchrow_array;
 
1554   $main::lxdebug->leave_sub();
 
1557 # get partnumber, description, unit, sellprice and soldtotal with choice through $sortorder for Top100
 
1559   $main::lxdebug->enter_sub();
 
1561   my ($self, $myconfig, $form, $sortorder) = @_;
 
1562   my $dbh   = $form->dbconnect($myconfig);
 
1563   my $order = " p.partnumber";
 
1564   my $where = "1 = 1";
 
1566   if ($sortorder eq "all") {
 
1567     $where .= " AND p.partnumber LIKE '%$form->{partnumber}%'";
 
1568     $where .= " AND p.description LIKE '%$form->{description}%'";
 
1570     if ($sortorder eq "partnumber") {
 
1571       $where .= " AND p.partnumber LIKE '%$form->{partnumber}%'";
 
1572       $order = qq|p.$sortorder|;
 
1574     if ($sortorder eq "description") {
 
1575       $where .= " AND p.description LIKE '%$form->{description}%'";
 
1580     qq|SELECT p.id, p.partnumber, p.description, p.unit, p.sellprice FROM parts p WHERE $where ORDER BY $order|;
 
1581   my $sth = $dbh->prepare($query);
 
1582   $sth->execute || $self->dberror($query);
 
1584   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1585     if (($ref->{partnumber} eq "*") && ($ref->{description} eq "")) {
 
1588       $form->{"id_$j"}          = $ref->{id};
 
1589       $form->{"partnumber_$j"}  = $ref->{partnumber};
 
1590       $form->{"description_$j"} = $ref->{description};
 
1591       $form->{"unit_$j"}        = $ref->{unit};
 
1592       $form->{"sellprice_$j"}   = $ref->{sellprice};
 
1593       $form->{"soldtotal_$j"}   = get_soldtotal($dbh, $ref->{id});
 
1600   $main::lxdebug->leave_sub();
 
1605 # gets sum of sold part with part_id
 
1607   $main::lxdebug->enter_sub();
 
1609   my ($dbh, $id) = @_;
 
1612     qq|SELECT sum(i.qty) as totalsold FROM invoice i WHERE i.parts_id = $id|;
 
1614   my $sth = $dbh->prepare($query);
 
1615   $sth->execute || $form->dberror($query);
 
1618   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1620     $sum = $ref->{totalsold};
 
1624   if ($sum eq undef) {
 
1628   $main::lxdebug->leave_sub();
 
1631 }    #end get_soldtotal
 
1634   $main::lxdebug->enter_sub();
 
1636   my ($self, $myconfig, $form) = @_;
 
1637   my $i     = $form->{rowcount};
 
1638   my $where = "NOT p.obsolete = '1'";
 
1640   if ($form->{"partnumber_$i"}) {
 
1641     my $partnumber = $form->like(lc $form->{"partnumber_$i"});
 
1642     $where .= " AND lower(p.partnumber) LIKE '$partnumber'";
 
1644   if ($form->{"description_$i"}) {
 
1645     my $description = $form->like(lc $form->{"description_$i"});
 
1646     $where .= " AND lower(p.description) LIKE '$description'";
 
1649   if ($form->{"partsgroup_$i"}) {
 
1650     my $partsgroup = $form->like(lc $form->{"partsgroup_$i"});
 
1651     $where .= " AND lower(pg.partsgroup) LIKE '$partsgroup'";
 
1654   if ($form->{"description_$i"}) {
 
1655     $where .= " ORDER BY description";
 
1657     $where .= " ORDER BY partnumber";
 
1660   # connect to database
 
1661   my $dbh = $form->dbconnect($myconfig);
 
1663   my $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
 
1665                         c1.accno AS inventory_accno,
 
1666                         c2.accno AS income_accno,
 
1667                         c3.accno AS expense_accno,
 
1668                  p.unit, p.assembly, p.bin, p.onhand, p.notes AS partnotes,
 
1671                  LEFT JOIN chart c1 ON (p.inventory_accno_id = c1.id)
 
1672                  LEFT JOIN chart c2 ON (p.income_accno_id = c2.id)
 
1673                  LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id)
 
1674                  LEFT JOIN partsgroup pg ON (pg.id = p.partsgroup_id)
 
1676   my $sth = $dbh->prepare($query);
 
1677   $sth->execute || $form->dberror($query);
 
1679   #while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1681   # get tax rates and description
 
1682   #$accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{inventory_accno};
 
1683   #$query = qq|SELECT c.accno, c.description, t.rate, t.taxnumber
 
1684   #           FROM chart c, tax t
 
1685   #           WHERE c.id=t.chart_id AND t.taxkey in (SELECT taxkey_id from chart where accno = '$accno_id')
 
1687   # $stw = $dbh->prepare($query);
 
1688   #$stw->execute || $form->dberror($query);
 
1690   #$ref->{taxaccounts} = "";
 
1691   #while ($ptr = $stw->fetchrow_hashref(NAME_lc)) {
 
1693   #   $form->{"$ptr->{accno}_rate"} = $ptr->{rate};
 
1694   #  $form->{"$ptr->{accno}_description"} = $ptr->{description};
 
1695   #   $form->{"$ptr->{accno}_taxnumber"} = $ptr->{taxnumber};
 
1696   #   $form->{taxaccounts} .= "$ptr->{accno} ";
 
1697   #   $ref->{taxaccounts} .= "$ptr->{accno} ";
 
1702   #chop $ref->{taxaccounts};
 
1704   push @{ $form->{item_list} }, $ref;
 
1710   $main::lxdebug->leave_sub();
 
1713 sub retrieve_languages {
 
1714   $main::lxdebug->enter_sub();
 
1716   my ($self, $myconfig, $form) = @_;
 
1718   # connect to database
 
1719   my $dbh = $form->dbconnect($myconfig);
 
1722     $where .= "tr.parts_id=$form->{id}";
 
1726   if ($form->{language_values} ne "") {
 
1727   $query = qq|SELECT l.id, l.description, tr.translation, tr.longdescription
 
1728                  FROM language l LEFT OUTER JOIN translation tr ON (tr.language_id=l.id AND $where)|;
 
1730   $query = qq|SELECT l.id, l.description
 
1733   my $sth = $dbh->prepare($query);
 
1734   $sth->execute || $form->dberror($query);
 
1736   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1737     push(@{$languages}, $ref);
 
1743   $main::lxdebug->leave_sub();
 
1748 sub follow_account_chain {
 
1749   $main::lxdebug->enter_sub(2);
 
1751   my ($self, $form, $dbh, $transdate, $accno_id, $accno) = @_;
 
1753   my @visited_accno_ids = ($accno_id);
 
1758     "SELECT c.new_chart_id, date($transdate) >= c.valid_from AS is_valid, " .
 
1761     "LEFT JOIN chart cnew ON c.new_chart_id = cnew.id " .
 
1762     "WHERE (c.id = ?) AND NOT c.new_chart_id ISNULL AND (c.new_chart_id > 0)";
 
1763   $sth = $dbh->prepare($query);
 
1766     $sth->execute($accno_id) || $form->dberror($query . " ($accno_id)");
 
1767     $ref = $sth->fetchrow_hashref();
 
1768     last unless ($ref && $ref->{"is_valid"} &&
 
1769                  !grep({ $_ == $ref->{"new_chart_id"} } @visited_accno_ids));
 
1770     $accno_id = $ref->{"new_chart_id"};
 
1771     $accno = $ref->{"accno"};
 
1772     push(@visited_accno_ids, $accno_id);
 
1775   $main::lxdebug->leave_sub(2);
 
1777   return ($accno_id, $accno);
 
1780 sub retrieve_accounts {
 
1781   $main::lxdebug->enter_sub(2);
 
1783   my ($self, $myconfig, $form, $parts_id, $index, $copy_accnos) = @_;
 
1785   my ($query, $sth, $dbh);
 
1787   $form->{"taxzone_id"} *= 1;
 
1789   $dbh = $form->dbconnect($myconfig);
 
1792   if ($form->{type} eq "invoice") {
 
1793     if (($form->{vc} eq "vendor") || !$form->{deliverydate}) {
 
1794       $transdate = $form->{invdate};
 
1796       $transdate = $form->{deliverydate};
 
1798   } elsif ($form->{type} eq "credit_note") {
 
1799     $transdate = $form->{invdate};
 
1801     $transdate = $form->{transdate};
 
1804   if ($transdate eq "") {
 
1805     $transdate = "current_date";
 
1807     $transdate = $dbh->quote($transdate);
 
1812     "  p.inventory_accno_id AS is_part, " .
 
1813     "  bg.inventory_accno_id, " .
 
1814     "  bg.income_accno_id_$form->{taxzone_id} AS income_accno_id, " .
 
1815     "  bg.expense_accno_id_$form->{taxzone_id} AS expense_accno_id, " .
 
1816     "  c1.accno AS inventory_accno, " .
 
1817     "  c2.accno AS income_accno, " .
 
1818     "  c3.accno AS expense_accno " .
 
1820     "LEFT JOIN buchungsgruppen bg ON p.buchungsgruppen_id = bg.id " .
 
1821     "LEFT JOIN chart c1 ON bg.inventory_accno_id = c1.id " .
 
1822     "LEFT JOIN chart c2 ON bg.income_accno_id_$form->{taxzone_id} = c2.id " .
 
1823     "LEFT JOIN chart c3 ON bg.expense_accno_id_$form->{taxzone_id} = c3.id " .
 
1825   $sth = $dbh->prepare($query);
 
1826   $sth->execute($parts_id) || $form->dberror($query . " ($parts_id)");
 
1827   my $ref = $sth->fetchrow_hashref();
 
1830 #   $main::lxdebug->message(0, "q $query");
 
1834     return $main::lxdebug->leave_sub(2);
 
1837   $ref->{"inventory_accno_id"} = undef unless ($ref->{"is_part"});
 
1840   foreach my $type (qw(inventory income expense)) {
 
1841     next unless ($ref->{"${type}_accno_id"});
 
1842     ($accounts{"${type}_accno_id"}, $accounts{"${type}_accno"}) =
 
1843       $self->follow_account_chain($form, $dbh, $transdate,
 
1844                                   $ref->{"${type}_accno_id"},
 
1845                                   $ref->{"${type}_accno"});
 
1848   map({ $form->{"${_}_accno_$index"} = $accounts{"${_}_accno"} }
 
1849       qw(inventory income expense));
 
1851   my $inc_exp = $form->{"vc"} eq "customer" ? "income" : "expense";
 
1852   my $accno_id = $accounts{"${inc_exp}_accno_id"};
 
1855     "SELECT c.accno, t.taxdescription AS description, t.rate, t.taxnumber " .
 
1857     "LEFT JOIN chart c ON c.id = t.chart_id " .
 
1859     "  (SELECT tk.tax_id " .
 
1860     "   FROM taxkeys tk " .
 
1861     "   WHERE tk.chart_id = ? AND startdate <= " . quote_db_date($transdate) .
 
1862     "   ORDER BY startdate DESC LIMIT 1) ";
 
1863   @vars = ($accno_id);
 
1864   $sth = $dbh->prepare($query);
 
1865   $sth->execute(@vars) || $form->dberror("$query (" . join(', ', @vars) . ")");
 
1866   $ref = $sth->fetchrow_hashref();
 
1871     $main::lxdebug->leave_sub(2);
 
1875   $form->{"taxaccounts_$index"} = $ref->{"accno"};
 
1876   if ($form->{"taxaccounts"} !~ /$ref->{accno}/) {
 
1877     $form->{"taxaccounts"} .= "$ref->{accno} ";
 
1879   map({ $form->{"$ref->{accno}_${_}"} = $ref->{$_}; }
 
1880       qw(rate description taxnumber));
 
1882 #   $main::lxdebug->message(0, "formvars: rate " . $form->{"$ref->{accno}_rate"} .
 
1883 #                           " description " . $form->{"$ref->{accno}_description"} .
 
1884 #                           " taxnumber " . $form->{"$ref->{accno}_taxnumber"} .
 
1885 #                           " || taxaccounts_$index " . $form->{"taxaccounts_$index"} .
 
1886 #                           " || taxaccounts " . $form->{"taxaccounts"});
 
1888   $main::lxdebug->leave_sub(2);