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 #======================================================================
 
  39   $main::lxdebug->enter_sub();
 
  41   my ($self, $myconfig, $form) = @_;
 
  44   my $dbh = $form->dbconnect($myconfig);
 
  46   my $query = qq|SELECT p.*,
 
  47                  c1.accno AS inventory_accno,
 
  48                  c2.accno AS income_accno,
 
  49                  c3.accno AS expense_accno,
 
  52                  LEFT JOIN chart c1 ON (p.inventory_accno_id = c1.id)
 
  53                  LEFT JOIN chart c2 ON (p.income_accno_id = c2.id)
 
  54                  LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id)
 
  55                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
  56                  WHERE p.id = $form->{id}|;
 
  57   my $sth = $dbh->prepare($query);
 
  58   $sth->execute || $form->dberror($query);
 
  59   my $ref = $sth->fetchrow_hashref(NAME_lc);
 
  61   # copy to $form variables
 
  62   map { $form->{$_} = $ref->{$_} } (keys %{$ref});
 
  66   my %oid = ('Pg'     => 'a.oid',
 
  67              'Oracle' => 'a.rowid');
 
  69   # part or service item
 
  70   $form->{item} = ($form->{inventory_accno}) ? 'part' : 'service';
 
  71   if ($form->{assembly}) {
 
  72     $form->{item} = 'assembly';
 
  74     # retrieve assembly items
 
  75     $query = qq|SELECT p.id, p.partnumber, p.description,
 
  76                 p.sellprice, p.weight, a.qty, a.bom, p.unit,
 
  79                 JOIN assembly a ON (a.parts_id = p.id)
 
  80                 LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
  81                 WHERE a.id = $form->{id}
 
  82                 ORDER BY $oid{$myconfig->{dbdriver}}|;
 
  84     $sth = $dbh->prepare($query);
 
  85     $sth->execute || $form->dberror($query);
 
  87     $form->{assembly_rows} = 0;
 
  88     while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
  89       $form->{assembly_rows}++;
 
  90       foreach my $key (keys %{$ref}) {
 
  91         $form->{"${key}_$form->{assembly_rows}"} = $ref->{$key};
 
  98   # setup accno hash for <option checked> {amount} is used in create_links
 
  99   $form->{amount}{IC}         = $form->{inventory_accno};
 
 100   $form->{amount}{IC_income}  = $form->{income_accno};
 
 101   $form->{amount}{IC_sale}    = $form->{income_accno};
 
 102   $form->{amount}{IC_expense} = $form->{expense_accno};
 
 103   $form->{amount}{IC_cogs}    = $form->{expense_accno};
 
 107     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
 
 108               WHERE parts_id = $form->{id}
 
 109               ORDER by pricegroup|;
 
 111   $sth = $dbh->prepare($query);
 
 112   $sth->execute || $form->dberror($query);
 
 115   @pricegroups_not_used = ();
 
 120          ($form->{"klass_$i"}, $form->{"pricegroup_id_$i"},
 
 121           $form->{"price_$i"}, $form->{"pricegroup_$i"})
 
 122          = $sth->fetchrow_array
 
 124     $form->{"price_$i"} = $form->round_amount($form->{"price_$i"}, 5);
 
 125     $form->{"price_$i"} =
 
 126       $form->format_amount($myconfig, $form->{"price_$i"}, 5);
 
 127     push @pricegroups, $form->{"pricegroup_id_$i"};
 
 134   $query = qq|SELECT p.id, p.pricegroup FROM pricegroup p|;
 
 136   $pkq = $dbh->prepare($query);
 
 137   $pkq->execute || $form->dberror($query);
 
 138   while ($pkr = $pkq->fetchrow_hashref(NAME_lc)) {
 
 139     push @{ $form->{PRICEGROUPS} }, $pkr;
 
 143   #find not used pricegroups
 
 144   while ($tmp = pop @{ $form->{PRICEGROUPS} }) {
 
 146     foreach $item (@pricegroups) {
 
 147       if ($item eq $tmp->{id}) {
 
 154       push @pricegroups_not_used, $tmp;
 
 158   # if not used pricegroups are avaible
 
 159   if (@pricegroups_not_used) {
 
 161     foreach $name (@pricegroups_not_used) {
 
 162       $form->{"klass_$i"} = "$name->{id}";
 
 163       $form->{"price_$i"} = $form->round_amount($form->{sellprice}, 5);
 
 164       $form->{"price_$i"} =
 
 165         $form->format_amount($myconfig, $form->{"price_$i"}, 5);
 
 166       $form->{"pricegroup_id_$i"} = "$name->{id}";
 
 167       $form->{"pricegroup_$i"}    = "$name->{pricegroup}";
 
 173   $form->{price_rows} = $i - 1;
 
 175   unless ($form->{item} eq 'service') {
 
 178     if ($form->{makemodel}) {
 
 179       $query = qq|SELECT m.make, m.model FROM makemodel m
 
 180                   WHERE m.parts_id = $form->{id}|;
 
 182       $sth = $dbh->prepare($query);
 
 183       $sth->execute || $form->dberror($query);
 
 186       while (($form->{"make_$i"}, $form->{"model_$i"}) = $sth->fetchrow_array)
 
 191       $form->{makemodel_rows} = $i - 1;
 
 197   $form->{language_values} = "";
 
 198   $query = qq|SELECT language_id, translation FROM translation WHERE parts_id = $form->{id}|;
 
 199   $trq = $dbh->prepare($query);
 
 200   $trq->execute || $form->dberror($query);
 
 201   while ($tr = $trq->fetchrow_hashref(NAME_lc)) {
 
 202     $form->{language_values} .= "---+++---".$tr->{language_id}."--++--".$tr->{translation};
 
 206   # now get accno for taxes
 
 207   $query = qq|SELECT c.accno
 
 208               FROM chart c, partstax pt
 
 209               WHERE pt.chart_id = c.id
 
 210               AND pt.parts_id = $form->{id}|;
 
 212   $sth = $dbh->prepare($query);
 
 213   $sth->execute || $form->dberror($query);
 
 215   while (($key) = $sth->fetchrow_array) {
 
 216     $form->{amount}{$key} = $key;
 
 222   $query = qq|SELECT i.parts_id
 
 224               WHERE i.parts_id = $form->{id}
 
 228               WHERE o.parts_id = $form->{id}
 
 232               WHERE a.parts_id = $form->{id}|;
 
 233   $sth = $dbh->prepare($query);
 
 234   $sth->execute || $form->dberror($query);
 
 236   ($form->{orphaned}) = $sth->fetchrow_array;
 
 237   $form->{orphaned} = !$form->{orphaned};
 
 240   $form->{"unit_changeable"} = 1;
 
 241   foreach my $table (qw(invoice assembly orderitems inventory license)) {
 
 242     $query = "SELECT COUNT(*) FROM $table WHERE parts_id = ?";
 
 243     my ($count) = $dbh->selectrow_array($query, undef, $form->{"id"});
 
 244     $form->dberror($query . " (" . $form->{"id"} . ")") if ($dbh->err);
 
 247       $form->{"unit_changeable"} = 0;
 
 254   $main::lxdebug->leave_sub();
 
 257 sub get_pricegroups {
 
 258   $main::lxdebug->enter_sub();
 
 260   my ($self, $myconfig, $form) = @_;
 
 261   my $dbh                  = $form->dbconnect($myconfig);
 
 263   my @pricegroups_not_used = ();
 
 266   my $query = qq|SELECT p.id, p.pricegroup FROM pricegroup p|;
 
 268   my $pkq = $dbh->prepare($query);
 
 269   $pkq->execute || $form->dberror($query);
 
 270   while ($pkr = $pkq->fetchrow_hashref(NAME_lc)) {
 
 271     push @{ $form->{PRICEGROUPS} }, $pkr;
 
 275   #find not used pricegroups
 
 276   while ($tmp = pop @{ $form->{PRICEGROUPS} }) {
 
 277     push @pricegroups_not_used, $tmp;
 
 280   # if not used pricegroups are avaible
 
 281   if (@pricegroups_not_used) {
 
 283     foreach $name (@pricegroups_not_used) {
 
 284       $form->{"klass_$i"} = "$name->{id}";
 
 285       $form->{"price_$i"} = $form->round_amount($form->{sellprice}, 5);
 
 286       $form->{"price_$i"} =
 
 287         $form->format_amount($myconfig, $form->{"price_$i"}, 5);
 
 288       $form->{"pricegroup_id_$i"} = "$name->{id}";
 
 289       $form->{"pricegroup_$i"}    = "$name->{pricegroup}";
 
 295   $form->{price_rows} = $i - 1;
 
 299   $main::lxdebug->leave_sub();
 
 302 sub retrieve_buchungsgruppen {
 
 303   $main::lxdebug->enter_sub();
 
 305   my ($self, $myconfig, $form) = @_;
 
 309   my $dbh = $form->dbconnect($myconfig);
 
 311   # get buchungsgruppen
 
 312   $query = qq|SELECT id, description
 
 315   $sth = $dbh->prepare($query);
 
 316   $sth->execute || $form->dberror($query);
 
 318   $form->{BUCHUNGSGRUPPEN} = [];
 
 319   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
 320     push(@{ $form->{BUCHUNGSGRUPPEN} }, $ref);
 
 324   $main::lxdebug->leave_sub();
 
 328   $main::lxdebug->enter_sub();
 
 330   my ($self, $myconfig, $form) = @_;
 
 332   # connect to database, turn off AutoCommit
 
 333   my $dbh = $form->dbconnect_noauto($myconfig);
 
 336   # make up a unique handle and store in partnumber field
 
 337   # then retrieve the record based on the unique handle to get the id
 
 338   # replace the partnumber field with the actual variable
 
 339   # add records for makemodel
 
 341   # if there is a $form->{id} then replace the old entry
 
 342   # delete all makemodel entries and add the new ones
 
 345   map { $form->{$_} =~ s/\'/\'\'/g } qw(partnumber description notes unit);
 
 347   # undo amount formatting
 
 348   map { $form->{$_} = $form->parse_amount($myconfig, $form->{$_}) }
 
 349     qw(rop weight listprice sellprice gv lastcost stock);
 
 351   # set date to NULL if nothing entered
 
 352   $form->{priceupdate} =
 
 353     ($form->{priceupdate}) ? qq|'$form->{priceupdate}'| : "NULL";
 
 355   $form->{makemodel} = (($form->{make_1}) || ($form->{model_1})) ? 1 : 0;
 
 357   $form->{alternate} = 0;
 
 358   $form->{assembly} = ($form->{item} eq 'assembly') ? 1 : 0;
 
 359   $form->{obsolete} *= 1;
 
 361   $form->{onhand}   *= 1;
 
 364   $form->{buchungsgruppen_id}       *= 1;
 
 365   $form->{not_discountable}       *= 1;
 
 366   $form->{payment_id}       *= 1;
 
 373     $query = qq|SELECT p.sellprice, p.weight
 
 375                 WHERE p.id = $form->{id}|;
 
 376     $sth = $dbh->prepare($query);
 
 377     $sth->execute || $form->dberror($query);
 
 378     my ($sellprice, $weight) = $sth->fetchrow_array;
 
 381     # if item is part of an assembly adjust all assemblies
 
 382     $query = qq|SELECT a.id, a.qty
 
 384                 WHERE a.parts_id = $form->{id}|;
 
 385     $sth = $dbh->prepare($query);
 
 386     $sth->execute || $form->dberror($query);
 
 387     while (my ($id, $qty) = $sth->fetchrow_array) {
 
 388       &update_assembly($dbh, $form, $id, $qty, $sellprice * 1, $weight * 1);
 
 392     if ($form->{item} ne 'service') {
 
 394       # delete makemodel records
 
 395       $query = qq|DELETE FROM makemodel
 
 396                   WHERE parts_id = $form->{id}|;
 
 397       $dbh->do($query) || $form->dberror($query);
 
 400     if ($form->{item} eq 'assembly') {
 
 401       if ($form->{onhand} != 0) {
 
 402         &adjust_inventory($dbh, $form, $form->{id}, $form->{onhand} * -1);
 
 405       # delete assembly records
 
 406       $query = qq|DELETE FROM assembly
 
 407                   WHERE id = $form->{id}|;
 
 408       $dbh->do($query) || $form->dberror($query);
 
 410       $form->{onhand} += $form->{stock};
 
 414     $query = qq|DELETE FROM partstax
 
 415                 WHERE parts_id = $form->{id}|;
 
 416     $dbh->do($query) || $form->dberror($query);
 
 418     # delete translations
 
 419     $query = qq|DELETE FROM translation
 
 420                 WHERE parts_id = $form->{id}|;
 
 421     $dbh->do($query) || $form->dberror($query);
 
 424     my $uid = rand() . time;
 
 425     $uid .= $form->{login};
 
 427     $query = qq|SELECT p.id FROM parts p
 
 428                 WHERE p.partnumber = '$form->{partnumber}'|;
 
 429     $sth = $dbh->prepare($query);
 
 430     $sth->execute || $form->dberror($query);
 
 431     ($form->{id}) = $sth->fetchrow_array;
 
 434     if ($form->{id} ne "") {
 
 435       $main::lxdebug->leave_sub();
 
 438     $query = qq|INSERT INTO parts (partnumber, description)
 
 439                 VALUES ('$uid', 'dummy')|;
 
 440     $dbh->do($query) || $form->dberror($query);
 
 442     $query = qq|SELECT p.id FROM parts p
 
 443                 WHERE p.partnumber = '$uid'|;
 
 444     $sth = $dbh->prepare($query);
 
 445     $sth->execute || $form->dberror($query);
 
 447     ($form->{id}) = $sth->fetchrow_array;
 
 450     $form->{orphaned} = 1;
 
 451     $form->{onhand} = $form->{stock} if $form->{item} eq 'assembly';
 
 452     if ($form->{partnumber} eq "" && $form->{"item"} eq "service") {
 
 453       $form->{partnumber} = $form->update_defaults($myconfig, "servicenumber");
 
 455     if ($form->{partnumber} eq "" && $form->{"item"} ne "service") {
 
 456       $form->{partnumber} = $form->update_defaults($myconfig, "articlenumber");
 
 460   my $partsgroup_id = 0;
 
 462   if ($form->{partsgroup}) {
 
 463     ($partsgroup, $partsgroup_id) = split /--/, $form->{partsgroup};
 
 466   my ($subq_inventory, $subq_expense, $subq_income);
 
 467   if ($form->{"item"} eq "part") {
 
 469       qq|(SELECT bg.inventory_accno_id | .
 
 470       qq| FROM buchungsgruppen bg | .
 
 471       qq| WHERE bg.id = | . $dbh->quote($form->{"buchungsgruppen_id"}) . qq|)|;
 
 473     $subq_inventory = "NULL";
 
 476   if ($form->{"item"} ne "assembly") {
 
 478       qq|(SELECT bg.expense_accno_id_0 | .
 
 479       qq| FROM buchungsgruppen bg | .
 
 480       qq| WHERE bg.id = | . $dbh->quote($form->{"buchungsgruppen_id"}) . qq|)|;
 
 482     $subq_expense = "NULL";
 
 486     qq|(SELECT bg.income_accno_id_0 | .
 
 487     qq| FROM buchungsgruppen bg | .
 
 488     qq| WHERE bg.id = | . $dbh->quote($form->{"buchungsgruppen_id"}) . qq|)|;
 
 490   $query = qq|UPDATE parts SET
 
 491               partnumber = '$form->{partnumber}',
 
 492               description = '$form->{description}',
 
 493               makemodel = '$form->{makemodel}',
 
 494               alternate = '$form->{alternate}',
 
 495               assembly = '$form->{assembly}',
 
 496               listprice = $form->{listprice},
 
 497               sellprice = $form->{sellprice},
 
 498               lastcost = $form->{lastcost},
 
 499               weight = $form->{weight},
 
 500               priceupdate = $form->{priceupdate},
 
 501               unit = '$form->{unit}',
 
 502               notes = '$form->{notes}',
 
 503               formel = '$form->{formel}',
 
 505               bin = '$form->{bin}',
 
 506               buchungsgruppen_id = '$form->{buchungsgruppen_id}',
 
 507               payment_id = '$form->{payment_id}',
 
 508               inventory_accno_id = $subq_inventory,
 
 509               income_accno_id = $subq_income,
 
 510               expense_accno_id = $subq_expense,
 
 511               obsolete = '$form->{obsolete}',
 
 512               image = '$form->{image}',
 
 513               drawing = '$form->{drawing}',
 
 514               shop = '$form->{shop}',
 
 517               ean = '$form->{ean}',
 
 518               not_discountable = '$form->{not_discountable}',
 
 519               microfiche = '$form->{microfiche}',
 
 520               partsgroup_id = $partsgroup_id
 
 521               WHERE id = $form->{id}|;
 
 522   $dbh->do($query) || $form->dberror($query);
 
 524   # delete translation records
 
 525   $query = qq|DELETE FROM translation
 
 526               WHERE parts_id = $form->{id}|;
 
 527   $dbh->do($query) || $form->dberror($query);
 
 529   if ($form->{language_values} ne "") {
 
 530     split /---\+\+\+---/,$form->{language_values};
 
 532       my ($language_id, $translation, $longdescription) = split /--\+\+--/, $item;
 
 533       if ($translation ne "") {
 
 534         $query = qq|INSERT into translation (parts_id, language_id, translation, longdescription) VALUES
 
 535                     ($form->{id}, $language_id, | . $dbh->quote($translation) . qq|, | . $dbh->quote($longdescription) . qq| )|;
 
 536         $dbh->do($query) || $form->dberror($query);
 
 540   # delete price records
 
 541   $query = qq|DELETE FROM prices
 
 542               WHERE parts_id = $form->{id}|;
 
 543   $dbh->do($query) || $form->dberror($query);
 
 544   # insert price records only if different to sellprice
 
 545   for my $i (1 .. $form->{price_rows}) {
 
 546     if ($form->{"price_$i"} eq "0") {
 
 547       $form->{"price_$i"} = $form->{sellprice};
 
 550         (   $form->{"price_$i"}
 
 551          || $form->{"klass_$i"}
 
 552          || $form->{"pricegroup_id_$i"})
 
 553         and $form->{"price_$i"} != $form->{sellprice}
 
 555       $klass = $form->parse_amount($myconfig, $form->{"klass_$i"});
 
 556       $price = $form->parse_amount($myconfig, $form->{"price_$i"});
 
 558         $form->parse_amount($myconfig, $form->{"pricegroup_id_$i"});
 
 559       $query = qq|INSERT INTO prices (parts_id, pricegroup_id, price)
 
 560                   VALUES($form->{id},$pricegroup_id,$price)|;
 
 561       $dbh->do($query) || $form->dberror($query);
 
 565   # insert makemodel records
 
 566   unless ($form->{item} eq 'service') {
 
 567     for my $i (1 .. $form->{makemodel_rows}) {
 
 568       if (($form->{"make_$i"}) || ($form->{"model_$i"})) {
 
 569         map { $form->{"${_}_$i"} =~ s/\'/\'\'/g } qw(make model);
 
 571         $query = qq|INSERT INTO makemodel (parts_id, make, model)
 
 573                     '$form->{"make_$i"}', '$form->{"model_$i"}')|;
 
 574         $dbh->do($query) || $form->dberror($query);
 
 580   foreach $item (split / /, $form->{taxaccounts}) {
 
 581     if ($form->{"IC_tax_$item"}) {
 
 582       $query = qq|INSERT INTO partstax (parts_id, chart_id)
 
 586                            WHERE c.accno = '$item'))|;
 
 587       $dbh->do($query) || $form->dberror($query);
 
 591   # add assembly records
 
 592   if ($form->{item} eq 'assembly') {
 
 594     for my $i (1 .. $form->{assembly_rows}) {
 
 595       $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
 
 597       if ($form->{"qty_$i"} != 0) {
 
 598         $form->{"bom_$i"} *= 1;
 
 599         $query = qq|INSERT INTO assembly (id, parts_id, qty, bom)
 
 600                     VALUES ($form->{id}, $form->{"id_$i"},
 
 601                     $form->{"qty_$i"}, '$form->{"bom_$i"}')|;
 
 602         $dbh->do($query) || $form->dberror($query);
 
 606     # adjust onhand for the parts
 
 607     if ($form->{onhand} != 0) {
 
 608       &adjust_inventory($dbh, $form, $form->{id}, $form->{onhand});
 
 614     my $shippingdate = "$a[5]-$a[4]-$a[3]";
 
 616     $form->get_employee($dbh);
 
 618     # add inventory record
 
 619     $query = qq|INSERT INTO inventory (warehouse_id, parts_id, qty,
 
 620                 shippingdate, employee_id) VALUES (
 
 621                 0, $form->{id}, $form->{stock}, '$shippingdate',
 
 622                 $form->{employee_id})|;
 
 623     $dbh->do($query) || $form->dberror($query);
 
 627   #set expense_accno=inventory_accno if they are different => bilanz
 
 629     ($form->{expense_accno} != $form->{inventory_accno})
 
 630     ? $form->{inventory_accno}
 
 631     : $form->{expense_accno};
 
 633   # get tax rates and description
 
 635     ($form->{vc} eq "customer") ? $form->{income_accno} : $vendor_accno;
 
 636   $query = qq|SELECT c.accno, c.description, t.rate, t.taxnumber
 
 638               WHERE c.id=t.chart_id AND t.taxkey in (SELECT taxkey_id from chart where accno = '$accno_id')
 
 640   $stw = $dbh->prepare($query);
 
 642   $stw->execute || $form->dberror($query);
 
 644   $form->{taxaccount} = "";
 
 645   while ($ptr = $stw->fetchrow_hashref(NAME_lc)) {
 
 647     #    if ($customertax{$ref->{accno}}) {
 
 648     $form->{taxaccount} .= "$ptr->{accno} ";
 
 649     if (!($form->{taxaccount2} =~ /$ptr->{accno}/)) {
 
 650       $form->{"$ptr->{accno}_rate"}        = $ptr->{rate};
 
 651       $form->{"$ptr->{accno}_description"} = $ptr->{description};
 
 652       $form->{"$ptr->{accno}_taxnumber"}   = $ptr->{taxnumber};
 
 653       $form->{taxaccount2} .= " $ptr->{accno} ";
 
 659   my $rc = $dbh->commit;
 
 662   $main::lxdebug->leave_sub();
 
 667 sub update_assembly {
 
 668   $main::lxdebug->enter_sub();
 
 670   my ($dbh, $form, $id, $qty, $sellprice, $weight) = @_;
 
 672   my $query = qq|SELECT a.id, a.qty
 
 674                  WHERE a.parts_id = $id|;
 
 675   my $sth = $dbh->prepare($query);
 
 676   $sth->execute || $form->dberror($query);
 
 678   while (my ($pid, $aqty) = $sth->fetchrow_array) {
 
 679     &update_assembly($dbh, $form, $pid, $aqty * $qty, $sellprice, $weight);
 
 683   $query = qq|UPDATE parts
 
 684               SET sellprice = sellprice +
 
 685                   $qty * ($form->{sellprice} - $sellprice),
 
 687                   $qty * ($form->{weight} - $weight)
 
 689   $dbh->do($query) || $form->dberror($query);
 
 691   $main::lxdebug->leave_sub();
 
 694 sub retrieve_assemblies {
 
 695   $main::lxdebug->enter_sub();
 
 697   my ($self, $myconfig, $form) = @_;
 
 699   # connect to database
 
 700   my $dbh = $form->dbconnect($myconfig);
 
 704   if ($form->{partnumber}) {
 
 705     my $partnumber = $form->like(lc $form->{partnumber});
 
 706     $where .= " AND lower(p.partnumber) LIKE '$partnumber'";
 
 709   if ($form->{description}) {
 
 710     my $description = $form->like(lc $form->{description});
 
 711     $where .= " AND lower(p.description) LIKE '$description'";
 
 713   $where .= " AND NOT p.obsolete = '1'";
 
 715   # retrieve assembly items
 
 716   my $query = qq|SELECT p.id, p.partnumber, p.description,
 
 717                  p.bin, p.onhand, p.rop,
 
 718                    (SELECT sum(p2.inventory_accno_id)
 
 719                     FROM parts p2, assembly a
 
 720                     WHERE p2.id = a.parts_id
 
 721                     AND a.id = p.id) AS inventory
 
 726   my $sth = $dbh->prepare($query);
 
 727   $sth->execute || $form->dberror($query);
 
 729   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
 730     push @{ $form->{assembly_items} }, $ref if $ref->{inventory};
 
 736   $main::lxdebug->leave_sub();
 
 739 sub restock_assemblies {
 
 740   $main::lxdebug->enter_sub();
 
 742   my ($self, $myconfig, $form) = @_;
 
 744   # connect to database
 
 745   my $dbh = $form->dbconnect_noauto($myconfig);
 
 747   for my $i (1 .. $form->{rowcount}) {
 
 749     $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
 
 751     if ($form->{"qty_$i"} != 0) {
 
 752       &adjust_inventory($dbh, $form, $form->{"id_$i"}, $form->{"qty_$i"});
 
 757   my $rc = $dbh->commit;
 
 760   $main::lxdebug->leave_sub();
 
 765 sub adjust_inventory {
 
 766   $main::lxdebug->enter_sub();
 
 768   my ($dbh, $form, $id, $qty) = @_;
 
 770   my $query = qq|SELECT p.id, p.inventory_accno_id, p.assembly, a.qty
 
 771                  FROM parts p, assembly a
 
 772                  WHERE a.parts_id = p.id
 
 774   my $sth = $dbh->prepare($query);
 
 775   $sth->execute || $form->dberror($query);
 
 777   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
 779     my $allocate = $qty * $ref->{qty};
 
 781     # is it a service item, then loop
 
 782     $ref->{inventory_accno_id} *= 1;
 
 783     next if (($ref->{inventory_accno_id} == 0) && !$ref->{assembly});
 
 785     # adjust parts onhand
 
 786     $form->update_balance($dbh, "parts", "onhand",
 
 794   my $rc = $form->update_balance($dbh, "parts", "onhand", qq|id = $id|, $qty);
 
 796   $main::lxdebug->leave_sub();
 
 802   $main::lxdebug->enter_sub();
 
 804   my ($self, $myconfig, $form) = @_;
 
 806   # connect to database, turn off AutoCommit
 
 807   my $dbh = $form->dbconnect_noauto($myconfig);
 
 809   # first delete prices of pricegroup 
 
 810   my $query = qq|DELETE FROM prices
 
 811            WHERE parts_id = $form->{id}|;
 
 812   $dbh->do($query) || $form->dberror($query);
 
 814   my $query = qq|DELETE FROM parts
 
 815                  WHERE id = $form->{id}|;
 
 816   $dbh->do($query) || $form->dberror($query);
 
 818   $query = qq|DELETE FROM partstax
 
 819               WHERE parts_id = $form->{id}|;
 
 820   $dbh->do($query) || $form->dberror($query);
 
 822   # check if it is a part, assembly or service
 
 823   if ($form->{item} ne 'service') {
 
 824     $query = qq|DELETE FROM makemodel
 
 825                 WHERE parts_id = $form->{id}|;
 
 826     $dbh->do($query) || $form->dberror($query);
 
 829   if ($form->{item} eq 'assembly') {
 
 832     $query = qq|DELETE FROM inventory
 
 833                 WHERE parts_id = $form->{id}|;
 
 834     $dbh->do($query) || $form->dberror($query);
 
 836     $query = qq|DELETE FROM assembly
 
 837                 WHERE id = $form->{id}|;
 
 838     $dbh->do($query) || $form->dberror($query);
 
 841   if ($form->{item} eq 'alternate') {
 
 842     $query = qq|DELETE FROM alternate
 
 843                 WHERE id = $form->{id}|;
 
 844     $dbh->do($query) || $form->dberror($query);
 
 848   my $rc = $dbh->commit;
 
 851   $main::lxdebug->leave_sub();
 
 857   $main::lxdebug->enter_sub();
 
 859   my ($self, $myconfig, $form) = @_;
 
 861   my $i = $form->{assembly_rows};
 
 865   if ($form->{"partnumber_$i"}) {
 
 866     $var = $form->like(lc $form->{"partnumber_$i"});
 
 867     $where .= " AND lower(p.partnumber) LIKE '$var'";
 
 869   if ($form->{"description_$i"}) {
 
 870     $var = $form->like(lc $form->{"description_$i"});
 
 871     $where .= " AND lower(p.description) LIKE '$var'";
 
 873   if ($form->{"partsgroup_$i"}) {
 
 874     $var = $form->like(lc $form->{"partsgroup_$i"});
 
 875     $where .= " AND lower(pg.partsgroup) LIKE '$var'";
 
 879     $where .= " AND NOT p.id = $form->{id}";
 
 883     $where .= " ORDER BY p.partnumber";
 
 885     $where .= " ORDER BY p.description";
 
 888   # connect to database
 
 889   my $dbh = $form->dbconnect($myconfig);
 
 891   my $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
 
 892                  p.weight, p.onhand, p.unit,
 
 895                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
 897   my $sth = $dbh->prepare($query);
 
 898   $sth->execute || $form->dberror($query);
 
 900   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
 901     push @{ $form->{item_list} }, $ref;
 
 907   $main::lxdebug->leave_sub();
 
 911   $main::lxdebug->enter_sub();
 
 913   my ($self, $myconfig, $form) = @_;
 
 921   foreach my $item (qw(partnumber drawing microfiche)) {
 
 922     if ($form->{$item}) {
 
 923       $var = $form->like(lc $form->{$item});
 
 924       $where .= " AND lower(p.$item) LIKE '$var'";
 
 928   # special case for description
 
 929   if ($form->{description}) {
 
 930     unless (   $form->{bought}
 
 935             || $form->{quoted}) {
 
 936       $var = $form->like(lc $form->{description});
 
 937       $where .= " AND lower(p.description) LIKE '$var'";
 
 941   # special case for serialnumber
 
 942   if ($form->{l_serialnumber}) {
 
 943     if ($form->{serialnumber}) {
 
 944       $var = $form->like(lc $form->{serialnumber});
 
 945       $where .= " AND lower(serialnumber) LIKE '$var'";
 
 950     $var = $form->like(lc $form->{ean});
 
 951     $where .= " AND lower(ean) LIKE '$var'";
 
 954   if ($form->{searchitems} eq 'part') {
 
 955     $where .= " AND p.inventory_accno_id > 0";
 
 957   if ($form->{searchitems} eq 'assembly') {
 
 958     $form->{bought} = "";
 
 959     $where .= " AND p.assembly = '1'";
 
 961   if ($form->{searchitems} eq 'service') {
 
 962     $where .= " AND p.inventory_accno_id IS NULL AND NOT p.assembly = '1'";
 
 964     # irrelevant for services
 
 965     $form->{make} = $form->{model} = "";
 
 968   # items which were never bought, sold or on an order
 
 969   if ($form->{itemstatus} eq 'orphaned') {
 
 970     $form->{onhand}  = $form->{short}   = 0;
 
 971     $form->{bought}  = $form->{sold}    = 0;
 
 972     $form->{onorder} = $form->{ordered} = 0;
 
 973     $form->{rfq}     = $form->{quoted}  = 0;
 
 975     $form->{transdatefrom} = $form->{transdateto} = "";
 
 977     $where .= " AND p.onhand = 0
 
 978                 AND p.id NOT IN (SELECT p.id FROM parts p, invoice i
 
 979                                  WHERE p.id = i.parts_id)
 
 980                 AND p.id NOT IN (SELECT p.id FROM parts p, assembly a
 
 981                                  WHERE p.id = a.parts_id)
 
 982                 AND p.id NOT IN (SELECT p.id FROM parts p, orderitems o
 
 983                                  WHERE p.id = o.parts_id)";
 
 986   if ($form->{itemstatus} eq 'active') {
 
 987     $where .= " AND p.obsolete = '0'";
 
 989   if ($form->{itemstatus} eq 'obsolete') {
 
 990     $where .= " AND p.obsolete = '1'";
 
 991     $form->{onhand} = $form->{short} = 0;
 
 993   if ($form->{itemstatus} eq 'onhand') {
 
 994     $where .= " AND p.onhand > 0";
 
 996   if ($form->{itemstatus} eq 'short') {
 
 997     $where .= " AND p.onhand < p.rop";
 
1000     $var = $form->like(lc $form->{make});
 
1001     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
 
1002                            FROM makemodel m WHERE lower(m.make) LIKE '$var')";
 
1004   if ($form->{model}) {
 
1005     $var = $form->like(lc $form->{model});
 
1006     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
 
1007                            FROM makemodel m WHERE lower(m.model) LIKE '$var')";
 
1009   if ($form->{partsgroup}) {
 
1010     $var = $form->like(lc $form->{partsgroup});
 
1011     $where .= " AND lower(pg.partsgroup) LIKE '$var'";
 
1013   if ($form->{l_soldtotal}) {
 
1014     $where .= " AND p.id=i.parts_id AND  i.qty >= 0";
 
1016       " GROUP BY  p.id,p.partnumber,p.description,p.onhand,p.unit,p.bin, p.sellprice,p.listprice,p.lastcost,p.priceupdate,pg.partsgroup";
 
1018   if ($form->{top100}) {
 
1019     $limit = " LIMIT 100";
 
1023   if ($form->{revers} == 1) {
 
1024     $form->{desc} = " DESC";
 
1029   # connect to database
 
1030   my $dbh = $form->dbconnect($myconfig);
 
1032   my $sortorder = $form->{sort};
 
1033   $sortorder .= $form->{desc};
 
1034   $sortorder = $form->{sort} if $form->{sort};
 
1038   if ($form->{l_soldtotal}) {
 
1039     $form->{soldtotal} = 'soldtotal';
 
1041       qq|SELECT p.id,p.partnumber,p.description,p.onhand,p.unit,p.bin,p.sellprice,p.listprice,
 
1042                 p.lastcost,p.priceupdate,pg.partsgroup,sum(i.qty) as soldtotal FROM parts
 
1043                 p LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id), invoice i
 
1049     $query = qq|SELECT p.id, p.partnumber, p.description, p.onhand, p.unit,
 
1050                  p.bin, p.sellprice, p.listprice, p.lastcost, p.rop, p.weight,
 
1051                  p.priceupdate, p.image, p.drawing, p.microfiche,
 
1054                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1057                  ORDER BY $sortorder|;
 
1060   # rebuild query for bought and sold items
 
1061   if (   $form->{bought}
 
1066       || $form->{quoted}) {
 
1068     my @a = qw(partnumber description bin priceupdate name);
 
1070     push @a, qw(invnumber serialnumber) if ($form->{bought} || $form->{sold});
 
1071     push @a, "ordnumber" if ($form->{onorder} || $form->{ordered});
 
1072     push @a, "quonumber" if ($form->{rfq}     || $form->{quoted});
 
1077     if ($form->{bought} || $form->{sold}) {
 
1079       my $invwhere = "$where";
 
1080       $invwhere .= " AND i.assemblyitem = '0'";
 
1081       $invwhere .= " AND a.transdate >= '$form->{transdatefrom}'"
 
1082         if $form->{transdatefrom};
 
1083       $invwhere .= " AND a.transdate <= '$form->{transdateto}'"
 
1084         if $form->{transdateto};
 
1086       if ($form->{description}) {
 
1087         $var = $form->like(lc $form->{description});
 
1088         $invwhere .= " AND lower(i.description) LIKE '$var'";
 
1091       my $flds = qq|p.id, p.partnumber, i.description, i.serialnumber,
 
1092                     i.qty AS onhand, i.unit, p.bin, i.sellprice,
 
1093                     p.listprice, p.lastcost, p.rop, p.weight,
 
1094                     p.priceupdate, p.image, p.drawing, p.microfiche,
 
1096                     a.invnumber, a.ordnumber, a.quonumber, i.trans_id,
 
1097                     ct.name, i.deliverydate|;
 
1099       if ($form->{bought}) {
 
1101                     SELECT $flds, 'ir' AS module, '' AS type,
 
1104                     JOIN parts p ON (p.id = i.parts_id)
 
1105                     JOIN ap a ON (a.id = i.trans_id)
 
1106                     JOIN vendor ct ON (a.vendor_id = ct.id)
 
1107                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1113       if ($form->{sold}) {
 
1115                      SELECT $flds, 'is' AS module, '' AS type,
 
1118                      JOIN parts p ON (p.id = i.parts_id)
 
1119                      JOIN ar a ON (a.id = i.trans_id)
 
1120                      JOIN customer ct ON (a.customer_id = ct.id)
 
1121                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1128     if ($form->{onorder} || $form->{ordered}) {
 
1129       my $ordwhere = "$where
 
1130                      AND o.quotation = '0'";
 
1131       $ordwhere .= " AND o.transdate >= '$form->{transdatefrom}'"
 
1132         if $form->{transdatefrom};
 
1133       $ordwhere .= " AND o.transdate <= '$form->{transdateto}'"
 
1134         if $form->{transdateto};
 
1136       if ($form->{description}) {
 
1137         $var = $form->like(lc $form->{description});
 
1138         $ordwhere .= " AND lower(oi.description) LIKE '$var'";
 
1142         qq|p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber,
 
1143                  oi.qty AS onhand, oi.unit, p.bin, oi.sellprice,
 
1144                  p.listprice, p.lastcost, p.rop, p.weight,
 
1145                  p.priceupdate, p.image, p.drawing, p.microfiche,
 
1147                  '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
 
1148                  ct.name, NULL AS deliverydate|;
 
1150       if ($form->{ordered}) {
 
1152                      SELECT $flds, 'oe' AS module, 'sales_order' AS type,
 
1153                     (SELECT buy FROM exchangerate ex
 
1154                      WHERE ex.curr = o.curr
 
1155                      AND ex.transdate = o.transdate) AS exchangerate
 
1157                      JOIN parts p ON (oi.parts_id = p.id)
 
1158                      JOIN oe o ON (oi.trans_id = o.id)
 
1159                      JOIN customer ct ON (o.customer_id = ct.id)
 
1160                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1162                      AND o.customer_id > 0|;
 
1167       if ($form->{onorder}) {
 
1169           qq|p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber,
 
1170                    oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice,
 
1171                    p.listprice, p.lastcost, p.rop, p.weight,
 
1172                    p.priceupdate, p.image, p.drawing, p.microfiche,
 
1174                    '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
 
1175                    ct.name, NULL AS deliverydate|;
 
1178                     SELECT $flds, 'oe' AS module, 'purchase_order' AS type,
 
1179                     (SELECT sell FROM exchangerate ex
 
1180                      WHERE ex.curr = o.curr
 
1181                      AND ex.transdate = o.transdate) AS exchangerate
 
1183                     JOIN parts p ON (oi.parts_id = p.id)
 
1184                     JOIN oe o ON (oi.trans_id = o.id)
 
1185                     JOIN vendor ct ON (o.vendor_id = ct.id)
 
1186                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1188                     AND o.vendor_id > 0|;
 
1193     if ($form->{rfq} || $form->{quoted}) {
 
1194       my $quowhere = "$where
 
1195                      AND o.quotation = '1'";
 
1196       $quowhere .= " AND o.transdate >= '$form->{transdatefrom}'"
 
1197         if $form->{transdatefrom};
 
1198       $quowhere .= " AND o.transdate <= '$form->{transdateto}'"
 
1199         if $form->{transdateto};
 
1201       if ($form->{description}) {
 
1202         $var = $form->like(lc $form->{description});
 
1203         $quowhere .= " AND lower(oi.description) LIKE '$var'";
 
1207         qq|p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber,
 
1208                  oi.qty AS onhand, oi.unit, p.bin, oi.sellprice,
 
1209                  p.listprice, p.lastcost, p.rop, p.weight,
 
1210                  p.priceupdate, p.image, p.drawing, p.microfiche,
 
1212                  '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
 
1213                  ct.name, NULL AS deliverydate|;
 
1215       if ($form->{quoted}) {
 
1217                      SELECT $flds, 'oe' AS module, 'sales_quotation' AS type,
 
1218                     (SELECT buy FROM exchangerate ex
 
1219                      WHERE ex.curr = o.curr
 
1220                      AND ex.transdate = o.transdate) AS exchangerate
 
1222                      JOIN parts p ON (oi.parts_id = p.id)
 
1223                      JOIN oe o ON (oi.trans_id = o.id)
 
1224                      JOIN customer ct ON (o.customer_id = ct.id)
 
1225                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1227                      AND o.customer_id > 0|;
 
1234           qq|p.id, p.partnumber, oi.description, oi.serialnumber AS serialnumber,
 
1235                    oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice,
 
1236                    p.listprice, p.lastcost, p.rop, p.weight,
 
1237                    p.priceupdate, p.image, p.drawing, p.microfiche,
 
1239                    '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
 
1240                    ct.name, NULL AS deliverydate|;
 
1243                     SELECT $flds, 'oe' AS module, 'request_quotation' AS type,
 
1244                     (SELECT sell FROM exchangerate ex
 
1245                      WHERE ex.curr = o.curr
 
1246                      AND ex.transdate = o.transdate) AS exchangerate
 
1248                     JOIN parts p ON (oi.parts_id = p.id)
 
1249                     JOIN oe o ON (oi.trans_id = o.id)
 
1250                     JOIN vendor ct ON (o.vendor_id = ct.id)
 
1251                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1253                     AND o.vendor_id > 0|;
 
1258                  ORDER BY $sortorder|;
 
1261   my $sth = $dbh->prepare($query);
 
1262   $sth->execute || $form->dberror($query);
 
1264   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1265     push @{ $form->{parts} }, $ref;
 
1270   # include individual items for assemblies
 
1271   if ($form->{searchitems} eq 'assembly' && $form->{bom}) {
 
1272     foreach $item (@{ $form->{parts} }) {
 
1273       push @assemblies, $item;
 
1274       $query = qq|SELECT p.id, p.partnumber, p.description, a.qty AS onhand,
 
1276                   p.sellprice, p.listprice, p.lastcost,
 
1277                   p.rop, p.weight, p.priceupdate,
 
1278                   p.image, p.drawing, p.microfiche
 
1279                   FROM parts p, assembly a
 
1280                   WHERE p.id = a.parts_id
 
1281                   AND a.id = $item->{id}|;
 
1283       $sth = $dbh->prepare($query);
 
1284       $sth->execute || $form->dberror($query);
 
1286       while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1287         $ref->{assemblyitem} = 1;
 
1288         push @assemblies, $ref;
 
1292       push @assemblies, { id => $item->{id} };
 
1296     # copy assemblies to $form->{parts}
 
1297     @{ $form->{parts} } = @assemblies;
 
1301   $main::lxdebug->leave_sub();
 
1305   $main::lxdebug->enter_sub();
 
1307   my ($self, $myconfig, $form) = @_;
 
1309   my $where = '1 = 1';
 
1315   foreach my $item (qw(partnumber drawing microfiche make model)) {
 
1316     if ($form->{$item}) {
 
1317       $var = $form->like(lc $form->{$item});
 
1319       # make will build later Bugfix 145
 
1320       if ($item ne 'make') {
 
1321         $where .= " AND lower(p.$item) LIKE '$var'";
 
1326   # special case for description
 
1327   if ($form->{description}) {
 
1328     unless (   $form->{bought}
 
1333             || $form->{quoted}) {
 
1334       $var = $form->like(lc $form->{description});
 
1335       $where .= " AND lower(p.description) LIKE '$var'";
 
1339   # special case for serialnumber
 
1340   if ($form->{l_serialnumber}) {
 
1341     if ($form->{serialnumber}) {
 
1342       $var = $form->like(lc $form->{serialnumber});
 
1343       $where .= " AND lower(serialnumber) LIKE '$var'";
 
1348   # items which were never bought, sold or on an order
 
1349   if ($form->{itemstatus} eq 'orphaned') {
 
1350     $form->{onhand}  = $form->{short}   = 0;
 
1351     $form->{bought}  = $form->{sold}    = 0;
 
1352     $form->{onorder} = $form->{ordered} = 0;
 
1353     $form->{rfq}     = $form->{quoted}  = 0;
 
1355     $form->{transdatefrom} = $form->{transdateto} = "";
 
1357     $where .= " AND p.onhand = 0
 
1358                 AND p.id NOT IN (SELECT p.id FROM parts p, invoice i
 
1359                                  WHERE p.id = i.parts_id)
 
1360                 AND p.id NOT IN (SELECT p.id FROM parts p, assembly a
 
1361                                  WHERE p.id = a.parts_id)
 
1362                 AND p.id NOT IN (SELECT p.id FROM parts p, orderitems o
 
1363                                  WHERE p.id = o.parts_id)";
 
1366   if ($form->{itemstatus} eq 'active') {
 
1367     $where .= " AND p.obsolete = '0'";
 
1369   if ($form->{itemstatus} eq 'obsolete') {
 
1370     $where .= " AND p.obsolete = '1'";
 
1371     $form->{onhand} = $form->{short} = 0;
 
1373   if ($form->{itemstatus} eq 'onhand') {
 
1374     $where .= " AND p.onhand > 0";
 
1376   if ($form->{itemstatus} eq 'short') {
 
1377     $where .= " AND p.onhand < p.rop";
 
1379   if ($form->{make}) {
 
1380     $var = $form->like(lc $form->{make});
 
1381     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
 
1382                            FROM makemodel m WHERE lower(m.make) LIKE '$var')";
 
1384   if ($form->{model}) {
 
1385     $var = $form->like(lc $form->{model});
 
1386     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
 
1387                            FROM makemodel m WHERE lower(m.model) LIKE '$var')";
 
1389   if ($form->{partsgroup}) {
 
1390     $var = $form->like(lc $form->{partsgroup});
 
1391     $where .= " AND lower(pg.partsgroup) LIKE '$var'";
 
1395   # connect to database
 
1396   my $dbh = $form->dbconnect_noauto($myconfig);
 
1398   if ($form->{"sellprice"} ne "") {
 
1400     my $faktor = $form->parse_amount($myconfig,$form->{"sellprice"});
 
1401     if ($form->{"sellprice_type"} eq "percent") {
 
1402       my $faktor = $form->parse_amount($myconfig,$form->{"sellprice"})/100 +1;
 
1403       $update = "sellprice* $faktor";
 
1405       $update = "sellprice+$faktor";
 
1408     $query = qq|UPDATE parts set sellprice=$update WHERE id IN (SELECT p.id
 
1410                   LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1415   if ($form->{"listprice"} ne "") {
 
1417     my $faktor = $form->parse_amount($myconfig,$form->{"listprice"});
 
1418     if ($form->{"listprice_type"} eq "percent") {
 
1419       my $faktor = $form->parse_amount($myconfig,$form->{"sellprice"})/100 +1;
 
1420       $update = "listprice* $faktor";
 
1422       $update = "listprice+$faktor";
 
1425     $query = qq|UPDATE parts set listprice=$update WHERE id IN (SELECT p.id
 
1427                   LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1436   for my $i (1 .. $form->{price_rows}) {
 
1441     if ($form->{"price_$i"} ne "") {
 
1443       my $faktor = $form->parse_amount($myconfig,$form->{"price_$i"});
 
1444       if ($form->{"pricegroup_type_$i"} eq "percent") {
 
1445         my $faktor = $form->parse_amount($myconfig,$form->{"sellprice"})/100 +1;
 
1446         $update = "price* $faktor";
 
1448         $update = "price+$faktor";
 
1451       $query = qq|UPDATE prices set price=$update WHERE parts_id IN (SELECT p.id
 
1453                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
 
1454                     WHERE $where) AND pricegroup_id=$form->{"pricegroup_id_$i"}|;
 
1462   my $rc= $dbh->commit;
 
1464   $main::lxdebug->leave_sub();
 
1470   $main::lxdebug->enter_sub();
 
1472   my ($self, $module, $myconfig, $form) = @_;
 
1474   # connect to database
 
1475   my $dbh = $form->dbconnect($myconfig);
 
1478     $query = qq|SELECT c.accno, c.description, c.link, c.id,
 
1479                         p.inventory_accno_id, p.income_accno_id, p.expense_accno_id
 
1480                         FROM chart c, parts p
 
1481                         WHERE c.link LIKE '%$module%'
 
1482                         AND p.id = $form->{id}
 
1485     $query = qq|SELECT c.accno, c.description, c.link, c.id,
 
1486                 d.inventory_accno_id, d.income_accno_id, d.expense_accno_id
 
1487                 FROM chart c, defaults d
 
1488                 WHERE c.link LIKE '%$module%'
 
1492   my $sth = $dbh->prepare($query);
 
1493   $sth->execute || $form->dberror($query);
 
1494   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1495     foreach my $key (split /:/, $ref->{link}) {
 
1496       if ($key =~ /$module/) {
 
1497         if (   ($ref->{id} eq $ref->{inventory_accno_id})
 
1498             || ($ref->{id} eq $ref->{income_accno_id})
 
1499             || ($ref->{id} eq $ref->{expense_accno_id})) {
 
1500           push @{ $form->{"${module}_links"}{$key} },
 
1501             { accno       => $ref->{accno},
 
1502               description => $ref->{description},
 
1503               selected    => "selected" };
 
1504           $form->{"${key}_default"} = "$ref->{accno}--$ref->{description}";
 
1506           push @{ $form->{"${module}_links"}{$key} },
 
1507             { accno       => $ref->{accno},
 
1508               description => $ref->{description},
 
1516   # get buchungsgruppen
 
1517   $query = qq|SELECT id, description
 
1518               FROM buchungsgruppen|;
 
1519   $sth = $dbh->prepare($query);
 
1520   $sth->execute || $form->dberror($query);
 
1522   $form->{BUCHUNGSGRUPPEN} = [];
 
1523   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1524     push @{ $form->{BUCHUNGSGRUPPEN} }, $ref;
 
1529   $query = qq|SELECT id, description
 
1532   $sth = $dbh->prepare($query);
 
1533   $sth->execute || $form->dberror($query);
 
1535   while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1536     push @{ $self->{payment_terms} }, $ref;
 
1541     $query = qq|SELECT current_date FROM defaults|;
 
1542     $sth = $dbh->prepare($query);
 
1543     $sth->execute || $form->dberror($query);
 
1545     ($form->{priceupdate}) = $sth->fetchrow_array;
 
1550   $main::lxdebug->leave_sub();
 
1553 # get partnumber, description, unit, sellprice and soldtotal with choice through $sortorder for Top100
 
1555   $main::lxdebug->enter_sub();
 
1557   my ($self, $myconfig, $form, $sortorder) = @_;
 
1558   my $dbh   = $form->dbconnect($myconfig);
 
1559   my $order = " p.partnumber";
 
1560   my $where = "1 = 1";
 
1562   if ($sortorder eq "all") {
 
1563     $where .= " AND p.partnumber LIKE '%$form->{partnumber}%'";
 
1564     $where .= " AND p.description LIKE '%$form->{description}%'";
 
1566     if ($sortorder eq "partnumber") {
 
1567       $where .= " AND p.partnumber LIKE '%$form->{partnumber}%'";
 
1568       $order = qq|p.$sortorder|;
 
1570     if ($sortorder eq "description") {
 
1571       $where .= " AND p.description LIKE '%$form->{description}%'";
 
1576     qq|SELECT p.id, p.partnumber, p.description, p.unit, p.sellprice FROM parts p WHERE $where ORDER BY $order|;
 
1577   my $sth = $dbh->prepare($query);
 
1578   $sth->execute || $self->dberror($query);
 
1580   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1581     if (($ref->{partnumber} eq "*") && ($ref->{description} eq "")) {
 
1584       $form->{"id_$j"}          = $ref->{id};
 
1585       $form->{"partnumber_$j"}  = $ref->{partnumber};
 
1586       $form->{"description_$j"} = $ref->{description};
 
1587       $form->{"unit_$j"}        = $ref->{unit};
 
1588       $form->{"sellprice_$j"}   = $ref->{sellprice};
 
1589       $form->{"soldtotal_$j"}   = get_soldtotal($dbh, $ref->{id});
 
1596   $main::lxdebug->leave_sub();
 
1601 # gets sum of sold part with part_id
 
1603   $main::lxdebug->enter_sub();
 
1605   my ($dbh, $id) = @_;
 
1608     qq|SELECT sum(i.qty) as totalsold FROM invoice i WHERE i.parts_id = $id|;
 
1610   my $sth = $dbh->prepare($query);
 
1611   $sth->execute || $form->dberror($query);
 
1614   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1616     $sum = $ref->{totalsold};
 
1620   if ($sum eq undef) {
 
1624   $main::lxdebug->leave_sub();
 
1627 }    #end get_soldtotal
 
1630   $main::lxdebug->enter_sub();
 
1632   my ($self, $myconfig, $form) = @_;
 
1633   my $i     = $form->{rowcount};
 
1634   my $where = "NOT p.obsolete = '1'";
 
1636   if ($form->{"partnumber_$i"}) {
 
1637     my $partnumber = $form->like(lc $form->{"partnumber_$i"});
 
1638     $where .= " AND lower(p.partnumber) LIKE '$partnumber'";
 
1640   if ($form->{"description_$i"}) {
 
1641     my $description = $form->like(lc $form->{"description_$i"});
 
1642     $where .= " AND lower(p.description) LIKE '$description'";
 
1645   if ($form->{"partsgroup_$i"}) {
 
1646     my $partsgroup = $form->like(lc $form->{"partsgroup_$i"});
 
1647     $where .= " AND lower(pg.partsgroup) LIKE '$partsgroup'";
 
1650   if ($form->{"description_$i"}) {
 
1651     $where .= " ORDER BY description";
 
1653     $where .= " ORDER BY partnumber";
 
1656   # connect to database
 
1657   my $dbh = $form->dbconnect($myconfig);
 
1659   my $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
 
1661                         c1.accno AS inventory_accno,
 
1662                         c2.accno AS income_accno,
 
1663                         c3.accno AS expense_accno,
 
1664                  p.unit, p.assembly, p.bin, p.onhand, p.notes AS partnotes,
 
1667                  LEFT JOIN chart c1 ON (p.inventory_accno_id = c1.id)
 
1668                  LEFT JOIN chart c2 ON (p.income_accno_id = c2.id)
 
1669                  LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id)
 
1670                  LEFT JOIN partsgroup pg ON (pg.id = p.partsgroup_id)
 
1672   my $sth = $dbh->prepare($query);
 
1673   $sth->execute || $form->dberror($query);
 
1675   #while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1677   # get tax rates and description
 
1678   #$accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{inventory_accno};
 
1679   #$query = qq|SELECT c.accno, c.description, t.rate, t.taxnumber
 
1680   #           FROM chart c, tax t
 
1681   #           WHERE c.id=t.chart_id AND t.taxkey in (SELECT taxkey_id from chart where accno = '$accno_id')
 
1683   # $stw = $dbh->prepare($query);
 
1684   #$stw->execute || $form->dberror($query);
 
1686   #$ref->{taxaccounts} = "";
 
1687   #while ($ptr = $stw->fetchrow_hashref(NAME_lc)) {
 
1689   #   $form->{"$ptr->{accno}_rate"} = $ptr->{rate};
 
1690   #  $form->{"$ptr->{accno}_description"} = $ptr->{description};
 
1691   #   $form->{"$ptr->{accno}_taxnumber"} = $ptr->{taxnumber};
 
1692   #   $form->{taxaccounts} .= "$ptr->{accno} ";
 
1693   #   $ref->{taxaccounts} .= "$ptr->{accno} ";
 
1698   #chop $ref->{taxaccounts};
 
1700   push @{ $form->{item_list} }, $ref;
 
1706   $main::lxdebug->leave_sub();
 
1709 sub retrieve_languages {
 
1710   $main::lxdebug->enter_sub();
 
1712   my ($self, $myconfig, $form) = @_;
 
1714   # connect to database
 
1715   my $dbh = $form->dbconnect($myconfig);
 
1718     $where .= "tr.parts_id=$form->{id}";
 
1722   if ($form->{language_values} ne "") {
 
1723   $query = qq|SELECT l.id, l.description, tr.translation, tr.longdescription
 
1724                  FROM language l LEFT OUTER JOIN translation tr ON (tr.language_id=l.id AND $where)|;
 
1726   $query = qq|SELECT l.id, l.description
 
1729   my $sth = $dbh->prepare($query);
 
1730   $sth->execute || $form->dberror($query);
 
1732   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
1733     push(@{$languages}, $ref);
 
1739   $main::lxdebug->leave_sub();
 
1744 sub follow_account_chain {
 
1745   $main::lxdebug->enter_sub();
 
1747   my ($self, $form, $dbh, $transdate, $accno_id, $accno) = @_;
 
1749   my @visited_accno_ids = ($accno_id);
 
1754     "SELECT c.new_chart_id, date($transdate) >= c.valid_from AS is_valid, " .
 
1757     "LEFT JOIN chart cnew ON c.new_chart_id = cnew.id " .
 
1758     "WHERE (c.id = ?) AND NOT c.new_chart_id ISNULL AND (c.new_chart_id > 0)";
 
1759   $sth = $dbh->prepare($query);
 
1762     $sth->execute($accno_id) || $form->dberror($query . " ($accno_id)");
 
1763     $ref = $sth->fetchrow_hashref();
 
1764     last unless ($ref && $ref->{"is_valid"} &&
 
1765                  !grep({ $_ == $ref->{"new_chart_id"} } @visited_accno_ids));
 
1766     $accno_id = $ref->{"new_chart_id"};
 
1767     $accno = $ref->{"accno"};
 
1768     push(@visited_accno_ids, $accno_id);
 
1771   $main::lxdebug->leave_sub();
 
1773   return ($accno_id, $accno);
 
1776 sub retrieve_accounts {
 
1777   $main::lxdebug->enter_sub();
 
1779   my ($self, $myconfig, $form, $parts_id, $index, $copy_accnos) = @_;
 
1781   my ($query, $sth, $dbh);
 
1783   $form->{"taxzone_id"} *= 1;
 
1785   $dbh = $form->dbconnect($myconfig);
 
1788   if ($form->{type} eq "invoice") {
 
1789     if (($form->{vc} eq "vendor") || !$form->{deliverydate}) {
 
1790       $transdate = $form->{invdate};
 
1792       $transdate = $form->{deliverydate};
 
1794   } elsif ($form->{type} eq "credit_note") {
 
1795     $transdate = $form->{invdate};
 
1797     $transdate = $form->{transdate};
 
1800   if ($transdate eq "") {
 
1801     $transdate = "current_date";
 
1803     $transdate = $dbh->quote($transdate);
 
1808     "  p.inventory_accno_id AS is_part, " .
 
1809     "  bg.inventory_accno_id, " .
 
1810     "  bg.income_accno_id_$form->{taxzone_id} AS income_accno_id, " .
 
1811     "  bg.expense_accno_id_$form->{taxzone_id} AS expense_accno_id, " .
 
1812     "  c1.accno AS inventory_accno, " .
 
1813     "  c2.accno AS income_accno, " .
 
1814     "  c3.accno AS expense_accno " .
 
1816     "LEFT JOIN buchungsgruppen bg ON p.buchungsgruppen_id = bg.id " .
 
1817     "LEFT JOIN chart c1 ON bg.inventory_accno_id = c1.id " .
 
1818     "LEFT JOIN chart c2 ON bg.income_accno_id_$form->{taxzone_id} = c2.id " .
 
1819     "LEFT JOIN chart c3 ON bg.expense_accno_id_$form->{taxzone_id} = c3.id " .
 
1821   $sth = $dbh->prepare($query);
 
1822   $sth->execute($parts_id) || $form->dberror($query . " ($parts_id)");
 
1823   my $ref = $sth->fetchrow_hashref();
 
1826 #   $main::lxdebug->message(0, "q $query");
 
1830     return $main::lxdebug->leave_sub();
 
1833   $ref->{"inventory_accno_id"} = undef unless ($ref->{"is_part"});
 
1836   foreach my $type (qw(inventory income expense)) {
 
1837     next unless ($ref->{"${type}_accno_id"});
 
1838     ($accounts{"${type}_accno_id"}, $accounts{"${type}_accno"}) =
 
1839       $self->follow_account_chain($form, $dbh, $transdate,
 
1840                                   $ref->{"${type}_accno_id"},
 
1841                                   $ref->{"${type}_accno"});
 
1844   map({ $form->{"${_}_accno_$index"} = $accounts{"${_}_accno"} }
 
1845       qw(inventory income expense));
 
1847   my $inc_exp = $form->{"vc"} eq "customer" ? "income" : "expense";
 
1848   my $accno_id = $accounts{"${inc_exp}_accno_id"};
 
1851     "SELECT c.accno, t.taxdescription AS description, t.rate, t.taxnumber " .
 
1853     "LEFT JOIN chart c ON c.id = t.chart_id " .
 
1855     "  (SELECT tk.tax_id " .
 
1856     "   FROM taxkeys tk " .
 
1857     "   WHERE tk.chart_id = $accno_id AND startdate <= $transdate " .
 
1858     "   ORDER BY startdate DESC LIMIT 1) ";
 
1859   $sth = $dbh->prepare($query);
 
1860   $sth->execute() || $form->dberror($query);
 
1861   $ref = $sth->fetchrow_hashref();
 
1866     $main::lxdebug->leave_sub();
 
1870   $form->{"taxaccounts_$index"} = $ref->{"accno"};
 
1871   if ($form->{"taxaccounts"} !~ /$ref->{accno}/) {
 
1872     $form->{"taxaccounts"} .= "$ref->{accno} ";
 
1874   map({ $form->{"$ref->{accno}_${_}"} = $ref->{$_}; }
 
1875       qw(rate description taxnumber));
 
1877 #   $main::lxdebug->message(0, "formvars: rate " . $form->{"$ref->{accno}_rate"} .
 
1878 #                           " description " . $form->{"$ref->{accno}_description"} .
 
1879 #                           " taxnumber " . $form->{"$ref->{accno}_taxnumber"} .
 
1880 #                           " || taxaccounts_$index " . $form->{"taxaccounts_$index"} .
 
1881 #                           " || taxaccounts " . $form->{"taxaccounts"});
 
1883   $main::lxdebug->leave_sub();