Preisgruppenerweiterung auf Basis von Andres Patch - Thanks
[kivitendo-erp.git] / SL / IC.pm
1 #=====================================================================
2 # LX-Office ERP
3 # Copyright (C) 2004
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
6 #
7 #=====================================================================
8 # SQL-Ledger Accounting
9 # Copyright (C) 2001
10 #
11 #  Author: Dieter Simader
12 #   Email: dsimader@sql-ledger.org
13 #     Web: http://www.sql-ledger.org
14 #
15 #  Contributors:
16 #
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.
21 #
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 #======================================================================
30 #
31 # Inventory Control backend
32 #
33 #======================================================================
34
35 package IC;
36 use Data::Dumper;
37 sub get_part {
38   $main::lxdebug->enter_sub();
39
40   my ($self, $myconfig, $form) = @_;
41
42   # connect to db
43   my $dbh = $form->dbconnect($myconfig);
44
45   my $query = qq|SELECT p.*,
46                  c1.accno AS inventory_accno,
47                  c2.accno AS income_accno,
48                  c3.accno AS expense_accno,
49                  pg.partsgroup
50                  FROM parts p
51                  LEFT JOIN chart c1 ON (p.inventory_accno_id = c1.id)
52                  LEFT JOIN chart c2 ON (p.income_accno_id = c2.id)
53                  LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id)
54                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
55                  WHERE p.id = $form->{id}|;
56   my $sth = $dbh->prepare($query);
57   $sth->execute || $form->dberror($query);
58   my $ref = $sth->fetchrow_hashref(NAME_lc);
59
60   # copy to $form variables
61   map { $form->{$_} = $ref->{$_} } (keys %{$ref});
62
63   $sth->finish;
64
65   my %oid = ('Pg'     => 'a.oid',
66              'Oracle' => 'a.rowid');
67
68   # part or service item
69   $form->{item} = ($form->{inventory_accno}) ? 'part' : 'service';
70   if ($form->{assembly}) {
71     $form->{item} = 'assembly';
72
73     # retrieve assembly items
74     $query = qq|SELECT p.id, p.partnumber, p.description,
75                 p.sellprice, p.weight, a.qty, a.bom, p.unit,
76                 pg.partsgroup
77                 FROM parts p
78                 JOIN assembly a ON (a.parts_id = p.id)
79                 LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
80                 WHERE a.id = $form->{id}
81                 ORDER BY $oid{$myconfig->{dbdriver}}|;
82
83     $sth = $dbh->prepare($query);
84     $sth->execute || $form->dberror($query);
85
86     $form->{assembly_rows} = 0;
87     while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
88       $form->{assembly_rows}++;
89       foreach my $key (keys %{$ref}) {
90         $form->{"${key}_$form->{assembly_rows}"} = $ref->{$key};
91       }
92     }
93     $sth->finish;
94
95   }
96
97   # setup accno hash for <option checked> {amount} is used in create_links
98   $form->{amount}{IC}         = $form->{inventory_accno};
99   $form->{amount}{IC_income}  = $form->{income_accno};
100   $form->{amount}{IC_sale}    = $form->{income_accno};
101   $form->{amount}{IC_expense} = $form->{expense_accno};
102   $form->{amount}{IC_cogs}    = $form->{expense_accno};
103
104   # get prices
105   $query =
106     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
107               WHERE parts_id = $form->{id}
108               ORDER by pricegroup|;
109
110   $sth = $dbh->prepare($query);
111   $sth->execute || $form->dberror($query);
112
113   @pricegroups          = ();
114   @pricegroups_not_used = ();
115
116   #for pricegroups
117   my $i = 1;
118   while (
119          ($form->{"klass_$i"}, $form->{"pricegroup_id_$i"},
120           $form->{"price_$i"}, $form->{"pricegroup_$i"})
121          = $sth->fetchrow_array
122     ) {
123     $form->{"price_$i"} = $form->round_amount($form->{"price_$i"}, 5);
124     $form->{"price_$i"} =
125       $form->format_amount($myconfig, $form->{"price_$i"}, 5);
126     push @pricegroups, $form->{"pricegroup_id_$i"};
127     $i++;
128   }
129
130   $sth->finish;
131
132   # get pricegroups
133   $query = qq|SELECT p.id, p.pricegroup FROM pricegroup p|;
134
135   $pkq = $dbh->prepare($query);
136   $pkq->execute || $form->dberror($query);
137   while ($pkr = $pkq->fetchrow_hashref(NAME_lc)) {
138     push @{ $form->{PRICEGROUPS} }, $pkr;
139   }
140   $pkq->finish;
141
142   #find not used pricegroups
143   while ($tmp = pop @{ $form->{PRICEGROUPS} }) {
144     my $insert = 0;
145     foreach $item (@pricegroups) {
146       if ($item eq $tmp->{id}) {
147
148         #drop
149         $insert = 1;
150       }
151     }
152     if ($insert == 0) {
153       push @pricegroups_not_used, $tmp;
154     }
155   }
156
157   # if not used pricegroups are avaible
158   if (@pricegroups_not_used) {
159
160     foreach $name (@pricegroups_not_used) {
161       $form->{"klass_$i"} = "$name->{id}";
162       $form->{"price_$i"} = $form->round_amount($form->{sellprice}, 5);
163       $form->{"price_$i"} =
164         $form->format_amount($myconfig, $form->{"price_$i"}, 5);
165       $form->{"pricegroup_id_$i"} = "$name->{id}";
166       $form->{"pricegroup_$i"}    = "$name->{pricegroup}\n";
167       $i++;
168     }
169   }
170
171   #correct rows
172   $form->{price_rows} = $i - 1;
173
174   unless ($form->{item} eq 'service') {
175
176     # get makes
177     if ($form->{makemodel}) {
178       $query = qq|SELECT m.make, m.model FROM makemodel m
179                   WHERE m.parts_id = $form->{id}|;
180
181       $sth = $dbh->prepare($query);
182       $sth->execute || $form->dberror($query);
183
184       my $i = 1;
185       while (($form->{"make_$i"}, $form->{"model_$i"}) = $sth->fetchrow_array)
186       {
187         $i++;
188       }
189       $sth->finish;
190       $form->{makemodel_rows} = $i - 1;
191
192     }
193   }
194
195   # now get accno for taxes
196   $query = qq|SELECT c.accno
197               FROM chart c, partstax pt
198               WHERE pt.chart_id = c.id
199               AND pt.parts_id = $form->{id}|;
200
201   $sth = $dbh->prepare($query);
202   $sth->execute || $form->dberror($query);
203
204   while (($key) = $sth->fetchrow_array) {
205     $form->{amount}{$key} = $key;
206   }
207
208   $sth->finish;
209
210   # is it an orphan
211   $query = qq|SELECT i.parts_id
212               FROM invoice i
213               WHERE i.parts_id = $form->{id}
214             UNION
215               SELECT o.parts_id
216               FROM orderitems o
217               WHERE o.parts_id = $form->{id}
218             UNION
219               SELECT a.parts_id
220               FROM assembly a
221               WHERE a.parts_id = $form->{id}|;
222   $sth = $dbh->prepare($query);
223   $sth->execute || $form->dberror($query);
224
225   ($form->{orphaned}) = $sth->fetchrow_array;
226   $form->{orphaned} = !$form->{orphaned};
227   $sth->finish;
228
229   $dbh->disconnect;
230
231   $main::lxdebug->leave_sub();
232 }
233
234 sub save {
235   $main::lxdebug->enter_sub();
236
237   my ($self, $myconfig, $form) = @_;
238
239   if ($form->{eur} && ($form->{item} ne 'service')) {
240     $form->{IC} = $form->{IC_expense};
241   }
242
243   ($form->{inventory_accno}) = split(/--/, $form->{IC});
244   ($form->{expense_accno})   = split(/--/, $form->{IC_expense});
245   ($form->{income_accno})    = split(/--/, $form->{IC_income});
246
247   # connect to database, turn off AutoCommit
248   my $dbh = $form->dbconnect_noauto($myconfig);
249
250   # save the part
251   # make up a unique handle and store in partnumber field
252   # then retrieve the record based on the unique handle to get the id
253   # replace the partnumber field with the actual variable
254   # add records for makemodel
255
256   # if there is a $form->{id} then replace the old entry
257   # delete all makemodel entries and add the new ones
258
259   # escape '
260   map { $form->{$_} =~ s/\'/\'\'/g } qw(partnumber description notes unit);
261
262   # undo amount formatting
263   map { $form->{$_} = $form->parse_amount($myconfig, $form->{$_}) }
264     qw(rop weight listprice sellprice gv lastcost stock);
265
266   # set date to NULL if nothing entered
267   $form->{priceupdate} =
268     ($form->{priceupdate}) ? qq|'$form->{priceupdate}'| : "NULL";
269
270   $form->{makemodel} = (($form->{make_1}) || ($form->{model_1})) ? 1 : 0;
271
272   $form->{alternate} = 0;
273   $form->{assembly} = ($form->{item} eq 'assembly') ? 1 : 0;
274   $form->{obsolete} *= 1;
275   $form->{shop}     *= 1;
276   $form->{onhand}   *= 1;
277   $form->{ve}       *= 1;
278   $form->{ge}       *= 1;
279
280   my ($query, $sth);
281
282   if ($form->{id}) {
283
284     # get old price
285     $query = qq|SELECT p.sellprice, p.weight
286                 FROM parts p
287                 WHERE p.id = $form->{id}|;
288     $sth = $dbh->prepare($query);
289     $sth->execute || $form->dberror($query);
290     my ($sellprice, $weight) = $sth->fetchrow_array;
291     $sth->finish;
292
293     # if item is part of an assembly adjust all assemblies
294     $query = qq|SELECT a.id, a.qty
295                 FROM assembly a
296                 WHERE a.parts_id = $form->{id}|;
297     $sth = $dbh->prepare($query);
298     $sth->execute || $form->dberror($query);
299     while (my ($id, $qty) = $sth->fetchrow_array) {
300       &update_assembly($dbh, $form, $id, $qty, $sellprice * 1, $weight * 1);
301     }
302     $sth->finish;
303
304     if ($form->{item} ne 'service') {
305
306       # delete makemodel records
307       $query = qq|DELETE FROM makemodel
308                   WHERE parts_id = $form->{id}|;
309       $dbh->do($query) || $form->dberror($query);
310     }
311
312     if ($form->{item} eq 'assembly') {
313       if ($form->{onhand} != 0) {
314         &adjust_inventory($dbh, $form, $form->{id}, $form->{onhand} * -1);
315       }
316
317       # delete assembly records
318       $query = qq|DELETE FROM assembly
319                   WHERE id = $form->{id}|;
320       $dbh->do($query) || $form->dberror($query);
321
322       $form->{onhand} += $form->{stock};
323     }
324
325     # delete tax records
326     $query = qq|DELETE FROM partstax
327                 WHERE parts_id = $form->{id}|;
328     $dbh->do($query) || $form->dberror($query);
329
330   } else {
331     my $uid = rand() . time;
332     $uid .= $form->{login};
333
334     $query = qq|SELECT p.id FROM parts p
335                 WHERE p.partnumber = '$form->{partnumber}'|;
336     $sth = $dbh->prepare($query);
337     $sth->execute || $form->dberror($query);
338     ($form->{id}) = $sth->fetchrow_array;
339     $sth->finish;
340
341     if ($form->{id} ne "") {
342       $main::lxdebug->leave_sub();
343       return 3;
344     }
345     $query = qq|INSERT INTO parts (partnumber, description)
346                 VALUES ('$uid', 'dummy')|;
347     $dbh->do($query) || $form->dberror($query);
348
349     $query = qq|SELECT p.id FROM parts p
350                 WHERE p.partnumber = '$uid'|;
351     $sth = $dbh->prepare($query);
352     $sth->execute || $form->dberror($query);
353
354     ($form->{id}) = $sth->fetchrow_array;
355     $sth->finish;
356
357     $form->{orphaned} = 1;
358     $form->{onhand} = $form->{stock} if $form->{item} eq 'assembly';
359     if ($form->{partnumber} eq "" && $form->{inventory_accno} eq "") {
360       $form->{partnumber} = $form->update_defaults($myconfig, "servicenumber");
361     }
362     if ($form->{partnumber} eq "" && $form->{inventory_accno} ne "") {
363       $form->{partnumber} = $form->update_defaults($myconfig, "articlenumber");
364     }
365
366   }
367   my $partsgroup_id = 0;
368
369   if ($form->{partsgroup}) {
370     ($partsgroup, $partsgroup_id) = split /--/, $form->{partsgroup};
371   }
372
373   $query = qq|UPDATE parts SET
374               partnumber = '$form->{partnumber}',
375               description = '$form->{description}',
376               makemodel = '$form->{makemodel}',
377               alternate = '$form->{alternate}',
378               assembly = '$form->{assembly}',
379               listprice = $form->{listprice},
380               sellprice = $form->{sellprice},
381               lastcost = $form->{lastcost},
382               weight = $form->{weight},
383               priceupdate = $form->{priceupdate},
384               unit = '$form->{unit}',
385               notes = '$form->{notes}',
386               rop = $form->{rop},
387               bin = '$form->{bin}',
388               inventory_accno_id = (SELECT c.id FROM chart c
389                                     WHERE c.accno = '$form->{inventory_accno}'),
390               income_accno_id = (SELECT c.id FROM chart c
391                                  WHERE c.accno = '$form->{income_accno}'),
392               expense_accno_id = (SELECT c.id FROM chart c
393                                   WHERE c.accno = '$form->{expense_accno}'),
394               obsolete = '$form->{obsolete}',
395               image = '$form->{image}',
396               drawing = '$form->{drawing}',
397               shop = '$form->{shop}',
398               ve = '$form->{ve}',
399               gv = '$form->{gv}',
400               microfiche = '$form->{microfiche}',
401               partsgroup_id = $partsgroup_id
402               WHERE id = $form->{id}|;
403   $dbh->do($query) || $form->dberror($query);
404
405   # delete price records
406   $query = qq|DELETE FROM prices
407               WHERE parts_id = $form->{id}|;
408   $dbh->do($query) || $form->dberror($query);
409
410   # insert price records only if different to sellprice
411   for my $i (1 .. $form->{price_rows}) {
412     if ((   $form->{"price_$i"} 
413         || $form->{"klass_$i"}
414         || $form->{"pricegroup_id_$i"}) and $form->{"price_$i"} != $form->{sellprice}) {
415       $klass = $form->parse_amount($myconfig, $form->{"klass_$i"});
416       $price = $form->parse_amount($myconfig, $form->{"price_$i"});
417       $pricegroup_id =
418         $form->parse_amount($myconfig, $form->{"pricegroup_id_$i"});
419       $query = qq|INSERT INTO prices (parts_id, pricegroup_id, price)
420                   VALUES($form->{id},$pricegroup_id,$price)|;
421       $dbh->do($query) || $form->dberror($query);
422     }
423   }
424
425   # insert makemodel records
426   unless ($form->{item} eq 'service') {
427     for my $i (1 .. $form->{makemodel_rows}) {
428       if (($form->{"make_$i"}) || ($form->{"model_$i"})) {
429         map { $form->{"${_}_$i"} =~ s/\'/\'\'/g } qw(make model);
430
431         $query = qq|INSERT INTO makemodel (parts_id, make, model)
432                     VALUES ($form->{id},
433                     '$form->{"make_$i"}', '$form->{"model_$i"}')|;
434         $dbh->do($query) || $form->dberror($query);
435       }
436     }
437   }
438
439   # insert taxes
440   foreach $item (split / /, $form->{taxaccounts}) {
441     if ($form->{"IC_tax_$item"}) {
442       $query = qq|INSERT INTO partstax (parts_id, chart_id)
443                   VALUES ($form->{id},
444                           (SELECT c.id
445                            FROM chart c
446                            WHERE c.accno = '$item'))|;
447       $dbh->do($query) || $form->dberror($query);
448     }
449   }
450
451   # add assembly records
452   if ($form->{item} eq 'assembly') {
453
454     for my $i (1 .. $form->{assembly_rows}) {
455       $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
456
457       if ($form->{"qty_$i"} != 0) {
458         $form->{"bom_$i"} *= 1;
459         $query = qq|INSERT INTO assembly (id, parts_id, qty, bom)
460                     VALUES ($form->{id}, $form->{"id_$i"},
461                     $form->{"qty_$i"}, '$form->{"bom_$i"}')|;
462         $dbh->do($query) || $form->dberror($query);
463       }
464     }
465
466     # adjust onhand for the parts
467     if ($form->{onhand} != 0) {
468       &adjust_inventory($dbh, $form, $form->{id}, $form->{onhand});
469     }
470
471     @a = localtime;
472     $a[5] += 1900;
473     $a[4]++;
474     my $shippingdate = "$a[5]-$a[4]-$a[3]";
475
476     $form->get_employee($dbh);
477
478     # add inventory record
479     $query = qq|INSERT INTO inventory (warehouse_id, parts_id, qty,
480                 shippingdate, employee_id) VALUES (
481                 0, $form->{id}, $form->{stock}, '$shippingdate',
482                 $form->{employee_id})|;
483     $dbh->do($query) || $form->dberror($query);
484
485   }
486
487   #set expense_accno=inventory_accno if they are different => bilanz
488   $vendor_accno =
489     ($form->{expense_accno} != $form->{inventory_accno})
490     ? $form->{inventory_accno}
491     : $form->{expense_accno};
492
493   # get tax rates and description
494   $accno_id =
495     ($form->{vc} eq "customer") ? $form->{income_accno} : $vendor_accno;
496   $query = qq|SELECT c.accno, c.description, t.rate, t.taxnumber
497               FROM chart c, tax t
498               WHERE c.id=t.chart_id AND t.taxkey in (SELECT taxkey_id from chart where accno = '$accno_id')
499               ORDER BY c.accno|;
500   $stw = $dbh->prepare($query);
501
502   $stw->execute || $form->dberror($query);
503
504   $form->{taxaccount} = "";
505   while ($ptr = $stw->fetchrow_hashref(NAME_lc)) {
506
507     #    if ($customertax{$ref->{accno}}) {
508     $form->{taxaccount} .= "$ptr->{accno} ";
509     if (!($form->{taxaccount2} =~ /$ptr->{accno}/)) {
510       $form->{"$ptr->{accno}_rate"}        = $ptr->{rate};
511       $form->{"$ptr->{accno}_description"} = $ptr->{description};
512       $form->{"$ptr->{accno}_taxnumber"}   = $ptr->{taxnumber};
513       $form->{taxaccount2} .= " $ptr->{accno} ";
514     }
515
516   }
517
518   # commit
519   my $rc = $dbh->commit;
520   $dbh->disconnect;
521
522   $main::lxdebug->leave_sub();
523
524   return $rc;
525 }
526
527 sub update_assembly {
528   $main::lxdebug->enter_sub();
529
530   my ($dbh, $form, $id, $qty, $sellprice, $weight) = @_;
531
532   my $query = qq|SELECT a.id, a.qty
533                  FROM assembly a
534                  WHERE a.parts_id = $id|;
535   my $sth = $dbh->prepare($query);
536   $sth->execute || $form->dberror($query);
537
538   while (my ($pid, $aqty) = $sth->fetchrow_array) {
539     &update_assembly($dbh, $form, $pid, $aqty * $qty, $sellprice, $weight);
540   }
541   $sth->finish;
542
543   $query = qq|UPDATE parts
544               SET sellprice = sellprice +
545                   $qty * ($form->{sellprice} - $sellprice),
546                   weight = weight +
547                   $qty * ($form->{weight} - $weight)
548               WHERE id = $id|;
549   $dbh->do($query) || $form->dberror($query);
550
551   $main::lxdebug->leave_sub();
552 }
553
554 sub retrieve_assemblies {
555   $main::lxdebug->enter_sub();
556
557   my ($self, $myconfig, $form) = @_;
558
559   # connect to database
560   my $dbh = $form->dbconnect($myconfig);
561
562   my $where = '1 = 1';
563
564   if ($form->{partnumber}) {
565     my $partnumber = $form->like(lc $form->{partnumber});
566     $where .= " AND lower(p.partnumber) LIKE '$partnumber'";
567   }
568
569   if ($form->{description}) {
570     my $description = $form->like(lc $form->{description});
571     $where .= " AND lower(p.description) LIKE '$description'";
572   }
573   $where .= " AND NOT p.obsolete = '1'";
574
575   # retrieve assembly items
576   my $query = qq|SELECT p.id, p.partnumber, p.description,
577                  p.bin, p.onhand, p.rop,
578                    (SELECT sum(p2.inventory_accno_id)
579                     FROM parts p2, assembly a
580                     WHERE p2.id = a.parts_id
581                     AND a.id = p.id) AS inventory
582                  FROM parts p
583                  WHERE $where
584                  AND assembly = '1'|;
585
586   my $sth = $dbh->prepare($query);
587   $sth->execute || $form->dberror($query);
588
589   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
590     push @{ $form->{assembly_items} }, $ref if $ref->{inventory};
591   }
592   $sth->finish;
593
594   $dbh->disconnect;
595
596   $main::lxdebug->leave_sub();
597 }
598
599 sub restock_assemblies {
600   $main::lxdebug->enter_sub();
601
602   my ($self, $myconfig, $form) = @_;
603
604   # connect to database
605   my $dbh = $form->dbconnect_noauto($myconfig);
606
607   for my $i (1 .. $form->{rowcount}) {
608
609     $form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
610
611     if ($form->{"qty_$i"} != 0) {
612       &adjust_inventory($dbh, $form, $form->{"id_$i"}, $form->{"qty_$i"});
613     }
614
615   }
616
617   my $rc = $dbh->commit;
618   $dbh->disconnect;
619
620   $main::lxdebug->leave_sub();
621
622   return $rc;
623 }
624
625 sub adjust_inventory {
626   $main::lxdebug->enter_sub();
627
628   my ($dbh, $form, $id, $qty) = @_;
629
630   my $query = qq|SELECT p.id, p.inventory_accno_id, p.assembly, a.qty
631                  FROM parts p, assembly a
632                  WHERE a.parts_id = p.id
633                  AND a.id = $id|;
634   my $sth = $dbh->prepare($query);
635   $sth->execute || $form->dberror($query);
636
637   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
638
639     my $allocate = $qty * $ref->{qty};
640
641     # is it a service item, then loop
642     $ref->{inventory_accno_id} *= 1;
643     next if (($ref->{inventory_accno_id} == 0) && !$ref->{assembly});
644
645     # adjust parts onhand
646     $form->update_balance($dbh, "parts", "onhand",
647                           qq|id = $ref->{id}|,
648                           $allocate * -1);
649   }
650
651   $sth->finish;
652
653   # update assembly
654   my $rc = $form->update_balance($dbh, "parts", "onhand", qq|id = $id|, $qty);
655
656   $main::lxdebug->leave_sub();
657
658   return $rc;
659 }
660
661 sub delete {
662   $main::lxdebug->enter_sub();
663
664   my ($self, $myconfig, $form) = @_;
665
666   # connect to database, turn off AutoCommit
667   my $dbh = $form->dbconnect_noauto($myconfig);
668
669   my $query = qq|DELETE FROM parts
670                  WHERE id = $form->{id}|;
671   $dbh->do($query) || $form->dberror($query);
672
673   $query = qq|DELETE FROM partstax
674               WHERE parts_id = $form->{id}|;
675   $dbh->do($query) || $form->dberror($query);
676
677   # check if it is a part, assembly or service
678   if ($form->{item} ne 'service') {
679     $query = qq|DELETE FROM makemodel
680                 WHERE parts_id = $form->{id}|;
681     $dbh->do($query) || $form->dberror($query);
682   }
683
684   if ($form->{item} eq 'assembly') {
685
686     # delete inventory
687     $query = qq|DELETE FROM inventory
688                 WHERE parts_id = $form->{id}|;
689     $dbh->do($query) || $form->dberror($query);
690
691     $query = qq|DELETE FROM assembly
692                 WHERE id = $form->{id}|;
693     $dbh->do($query) || $form->dberror($query);
694   }
695
696   if ($form->{item} eq 'alternate') {
697     $query = qq|DELETE FROM alternate
698                 WHERE id = $form->{id}|;
699     $dbh->do($query) || $form->dberror($query);
700   }
701
702   # commit
703   my $rc = $dbh->commit;
704   $dbh->disconnect;
705
706   $main::lxdebug->leave_sub();
707
708   return $rc;
709 }
710
711 sub assembly_item {
712   $main::lxdebug->enter_sub();
713
714   my ($self, $myconfig, $form) = @_;
715
716   my $i = $form->{assembly_rows};
717   my $var;
718   my $where = "1 = 1";
719
720   if ($form->{"partnumber_$i"}) {
721     $var = $form->like(lc $form->{"partnumber_$i"});
722     $where .= " AND lower(p.partnumber) LIKE '$var'";
723   }
724   if ($form->{"description_$i"}) {
725     $var = $form->like(lc $form->{"description_$i"});
726     $where .= " AND lower(p.description) LIKE '$var'";
727   }
728   if ($form->{"partsgroup_$i"}) {
729     $var = $form->like(lc $form->{"partsgroup_$i"});
730     $where .= " AND lower(pg.partsgroup) LIKE '$var'";
731   }
732
733   if ($form->{id}) {
734     $where .= " AND NOT p.id = $form->{id}";
735   }
736
737   if ($partnumber) {
738     $where .= " ORDER BY p.partnumber";
739   } else {
740     $where .= " ORDER BY p.description";
741   }
742
743   # connect to database
744   my $dbh = $form->dbconnect($myconfig);
745
746   my $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
747                  p.weight, p.onhand, p.unit,
748                  pg.partsgroup
749                  FROM parts p
750                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
751                  WHERE $where|;
752   my $sth = $dbh->prepare($query);
753   $sth->execute || $form->dberror($query);
754
755   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
756     push @{ $form->{item_list} }, $ref;
757   }
758
759   $sth->finish;
760   $dbh->disconnect;
761
762   $main::lxdebug->leave_sub();
763 }
764
765 sub all_parts {
766   $main::lxdebug->enter_sub();
767
768   my ($self, $myconfig, $form) = @_;
769
770   my $where = '1 = 1';
771   my $var;
772
773   my $group;
774   my $limit;
775
776   foreach my $item (qw(partnumber drawing microfiche make model)) {
777     if ($form->{$item}) {
778       $var = $form->like(lc $form->{$item});
779
780       # make will build later Bugfix 145
781       if ($item ne 'make') {
782         $where .= " AND lower(p.$item) LIKE '$var'";
783       }
784     }
785   }
786
787   # special case for description
788   if ($form->{description}) {
789     unless (   $form->{bought}
790             || $form->{sold}
791             || $form->{onorder}
792             || $form->{ordered}
793             || $form->{rfq}
794             || $form->{quoted}) {
795       $var = $form->like(lc $form->{description});
796       $where .= " AND lower(p.description) LIKE '$var'";
797     }
798   }
799
800   # special case for serialnumber
801   if ($form->{l_serialnumber}) {
802     if ($form->{serialnumber}) {
803       $var = $form->like(lc $form->{serialnumber});
804       $where .= " AND lower(serialnumber) LIKE '$var'";
805     }
806   }
807
808   if ($form->{searchitems} eq 'part') {
809     $where .= " AND p.inventory_accno_id > 0";
810   }
811   if ($form->{searchitems} eq 'assembly') {
812     $form->{bought} = "";
813     $where .= " AND p.assembly = '1'";
814   }
815   if ($form->{searchitems} eq 'service') {
816     $where .= " AND p.inventory_accno_id IS NULL AND NOT p.assembly = '1'";
817
818     # irrelevant for services
819     $form->{make} = $form->{model} = "";
820   }
821
822   # items which were never bought, sold or on an order
823   if ($form->{itemstatus} eq 'orphaned') {
824     $form->{onhand}  = $form->{short}   = 0;
825     $form->{bought}  = $form->{sold}    = 0;
826     $form->{onorder} = $form->{ordered} = 0;
827     $form->{rfq}     = $form->{quoted}  = 0;
828
829     $form->{transdatefrom} = $form->{transdateto} = "";
830
831     $where .= " AND p.onhand = 0
832                 AND p.id NOT IN (SELECT p.id FROM parts p, invoice i
833                                  WHERE p.id = i.parts_id)
834                 AND p.id NOT IN (SELECT p.id FROM parts p, assembly a
835                                  WHERE p.id = a.parts_id)
836                 AND p.id NOT IN (SELECT p.id FROM parts p, orderitems o
837                                  WHERE p.id = o.parts_id)";
838   }
839
840   if ($form->{itemstatus} eq 'active') {
841     $where .= " AND p.obsolete = '0'";
842   }
843   if ($form->{itemstatus} eq 'obsolete') {
844     $where .= " AND p.obsolete = '1'";
845     $form->{onhand} = $form->{short} = 0;
846   }
847   if ($form->{itemstatus} eq 'onhand') {
848     $where .= " AND p.onhand > 0";
849   }
850   if ($form->{itemstatus} eq 'short') {
851     $where .= " AND p.onhand < p.rop";
852   }
853   if ($form->{make}) {
854     $var = $form->like(lc $form->{make});
855     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
856                            FROM makemodel m WHERE lower(m.make) LIKE '$var')";
857   }
858   if ($form->{model}) {
859     $var = $form->like(lc $form->{model});
860     $where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
861                            FROM makemodel m WHERE lower(m.model) LIKE '$var')";
862   }
863   if ($form->{partsgroup}) {
864     $var = $form->like(lc $form->{partsgroup});
865     $where .= " AND lower(pg.partsgroup) LIKE '$var'";
866   }
867   if ($form->{l_soldtotal}) {
868     $where .= " AND p.id=i.parts_id AND  i.qty >= 0";
869     $group =
870       " GROUP BY  p.id,p.partnumber,p.description,p.onhand,p.unit,p.bin, p.sellprice,p.listprice,p.lastcost,p.priceupdate,pg.partsgroup";
871   }
872   if ($form->{top100}) {
873     $limit = " LIMIT 100";
874   }
875
876   # tables revers?
877   if ($form->{revers} == 1) {
878     $form->{desc} = " DESC";
879   } else {
880     $form->{desc} = "";
881   }
882
883   # connect to database
884   my $dbh = $form->dbconnect($myconfig);
885
886   my $sortorder = $form->{sort};
887   $sortorder .= $form->{desc};
888   $sortorder = $form->{sort} unless $sortorder;
889
890   my $query = "";
891
892   if ($form->{l_soldtotal}) {
893     $form->{soldtotal} = 'soldtotal';
894     $query =
895       qq|SELECT p.id,p.partnumber,p.description,p.onhand,p.unit,p.bin,p.sellprice,p.listprice,
896                 p.lastcost,p.priceupdate,pg.partsgroup,sum(i.qty) as soldtotal FROM parts
897                 p LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id), invoice i
898                 WHERE $where
899                 $group
900                 ORDER BY $sortorder
901                 $limit|;
902   } else {
903     $query = qq|SELECT p.id, p.partnumber, p.description, p.onhand, p.unit,
904                  p.bin, p.sellprice, p.listprice, p.lastcost, p.rop, p.weight,
905                  p.priceupdate, p.image, p.drawing, p.microfiche,
906                  pg.partsgroup
907                  FROM parts p
908                  LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
909                  WHERE $where
910                  $group
911                  ORDER BY $sortorder|;
912   }
913
914   # rebuild query for bought and sold items
915   if (   $form->{bought}
916       || $form->{sold}
917       || $form->{onorder}
918       || $form->{ordered}
919       || $form->{rfq}
920       || $form->{quoted}) {
921
922     my @a = qw(partnumber description bin priceupdate name);
923
924     push @a, qw(invnumber serialnumber) if ($form->{bought} || $form->{sold});
925     push @a, "ordnumber" if ($form->{onorder} || $form->{ordered});
926     push @a, "quonumber" if ($form->{rfq}     || $form->{quoted});
927
928     my $union = "";
929     $query = "";
930
931     if ($form->{bought} || $form->{sold}) {
932
933       my $invwhere = "$where";
934       $invwhere .= " AND i.assemblyitem = '0'";
935       $invwhere .= " AND a.transdate >= '$form->{transdatefrom}'"
936         if $form->{transdatefrom};
937       $invwhere .= " AND a.transdate <= '$form->{transdateto}'"
938         if $form->{transdateto};
939
940       if ($form->{description}) {
941         $var = $form->like(lc $form->{description});
942         $invwhere .= " AND lower(i.description) LIKE '$var'";
943       }
944
945       my $flds = qq|p.id, p.partnumber, i.description, i.serialnumber,
946                     i.qty AS onhand, i.unit, p.bin, i.sellprice,
947                     p.listprice, p.lastcost, p.rop, p.weight,
948                     p.priceupdate, p.image, p.drawing, p.microfiche,
949                     pg.partsgroup,
950                     a.invnumber, a.ordnumber, a.quonumber, i.trans_id,
951                     ct.name|;
952
953       if ($form->{bought}) {
954         $query = qq|
955                     SELECT $flds, 'ir' AS module, '' AS type,
956                     1 AS exchangerate
957                     FROM invoice i
958                     JOIN parts p ON (p.id = i.parts_id)
959                     JOIN ap a ON (a.id = i.trans_id)
960                     JOIN vendor ct ON (a.vendor_id = ct.id)
961                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
962                     WHERE $invwhere|;
963         $union = "
964                   UNION";
965       }
966
967       if ($form->{sold}) {
968         $query .= qq|$union
969                      SELECT $flds, 'is' AS module, '' AS type,
970                      1 As exchangerate
971                      FROM invoice i
972                      JOIN parts p ON (p.id = i.parts_id)
973                      JOIN ar a ON (a.id = i.trans_id)
974                      JOIN customer ct ON (a.customer_id = ct.id)
975                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
976                      WHERE $invwhere|;
977         $union = "
978                   UNION";
979       }
980     }
981
982     if ($form->{onorder} || $form->{ordered}) {
983       my $ordwhere = "$where
984                      AND o.quotation = '0'";
985       $ordwhere .= " AND o.transdate >= '$form->{transdatefrom}'"
986         if $form->{transdatefrom};
987       $ordwhere .= " AND o.transdate <= '$form->{transdateto}'"
988         if $form->{transdateto};
989
990       if ($form->{description}) {
991         $var = $form->like(lc $form->{description});
992         $ordwhere .= " AND lower(oi.description) LIKE '$var'";
993       }
994
995       $flds = qq|p.id, p.partnumber, oi.description, '' AS serialnumber,
996                  oi.qty AS onhand, oi.unit, p.bin, oi.sellprice,
997                  p.listprice, p.lastcost, p.rop, p.weight,
998                  p.priceupdate, p.image, p.drawing, p.microfiche,
999                  pg.partsgroup,
1000                  '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
1001                  ct.name|;
1002
1003       if ($form->{ordered}) {
1004         $query .= qq|$union
1005                      SELECT $flds, 'oe' AS module, 'sales_order' AS type,
1006                     (SELECT buy FROM exchangerate ex
1007                      WHERE ex.curr = o.curr
1008                      AND ex.transdate = o.transdate) AS exchangerate
1009                      FROM orderitems oi
1010                      JOIN parts p ON (oi.parts_id = p.id)
1011                      JOIN oe o ON (oi.trans_id = o.id)
1012                      JOIN customer ct ON (o.customer_id = ct.id)
1013                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
1014                      WHERE $ordwhere
1015                      AND o.customer_id > 0|;
1016         $union = "
1017                   UNION";
1018       }
1019
1020       if ($form->{onorder}) {
1021         $flds = qq|p.id, p.partnumber, oi.description, '' AS serialnumber,
1022                    oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice,
1023                    p.listprice, p.lastcost, p.rop, p.weight,
1024                    p.priceupdate, p.image, p.drawing, p.microfiche,
1025                    pg.partsgroup,
1026                    '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
1027                    ct.name|;
1028
1029         $query .= qq|$union
1030                     SELECT $flds, 'oe' AS module, 'purchase_order' AS type,
1031                     (SELECT sell FROM exchangerate ex
1032                      WHERE ex.curr = o.curr
1033                      AND ex.transdate = o.transdate) AS exchangerate
1034                     FROM orderitems oi
1035                     JOIN parts p ON (oi.parts_id = p.id)
1036                     JOIN oe o ON (oi.trans_id = o.id)
1037                     JOIN vendor ct ON (o.vendor_id = ct.id)
1038                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
1039                     WHERE $ordwhere
1040                     AND o.vendor_id > 0|;
1041       }
1042
1043     }
1044
1045     if ($form->{rfq} || $form->{quoted}) {
1046       my $quowhere = "$where
1047                      AND o.quotation = '1'";
1048       $quowhere .= " AND o.transdate >= '$form->{transdatefrom}'"
1049         if $form->{transdatefrom};
1050       $quowhere .= " AND o.transdate <= '$form->{transdateto}'"
1051         if $form->{transdateto};
1052
1053       if ($form->{description}) {
1054         $var = $form->like(lc $form->{description});
1055         $quowhere .= " AND lower(oi.description) LIKE '$var'";
1056       }
1057
1058       $flds = qq|p.id, p.partnumber, oi.description, '' AS serialnumber,
1059                  oi.qty AS onhand, oi.unit, p.bin, oi.sellprice,
1060                  p.listprice, p.lastcost, p.rop, p.weight,
1061                  p.priceupdate, p.image, p.drawing, p.microfiche,
1062                  pg.partsgroup,
1063                  '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
1064                  ct.name|;
1065
1066       if ($form->{quoted}) {
1067         $query .= qq|$union
1068                      SELECT $flds, 'oe' AS module, 'sales_quotation' AS type,
1069                     (SELECT buy FROM exchangerate ex
1070                      WHERE ex.curr = o.curr
1071                      AND ex.transdate = o.transdate) AS exchangerate
1072                      FROM orderitems oi
1073                      JOIN parts p ON (oi.parts_id = p.id)
1074                      JOIN oe o ON (oi.trans_id = o.id)
1075                      JOIN customer ct ON (o.customer_id = ct.id)
1076                      LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
1077                      WHERE $quowhere
1078                      AND o.customer_id > 0|;
1079         $union = "
1080                   UNION";
1081       }
1082
1083       if ($form->{rfq}) {
1084         $flds = qq|p.id, p.partnumber, oi.description, '' AS serialnumber,
1085                    oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice,
1086                    p.listprice, p.lastcost, p.rop, p.weight,
1087                    p.priceupdate, p.image, p.drawing, p.microfiche,
1088                    pg.partsgroup,
1089                    '' AS invnumber, o.ordnumber, o.quonumber, oi.trans_id,
1090                    ct.name|;
1091
1092         $query .= qq|$union
1093                     SELECT $flds, 'oe' AS module, 'request_quotation' AS type,
1094                     (SELECT sell FROM exchangerate ex
1095                      WHERE ex.curr = o.curr
1096                      AND ex.transdate = o.transdate) AS exchangerate
1097                     FROM orderitems oi
1098                     JOIN parts p ON (oi.parts_id = p.id)
1099                     JOIN oe o ON (oi.trans_id = o.id)
1100                     JOIN vendor ct ON (o.vendor_id = ct.id)
1101                     LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
1102                     WHERE $quowhere
1103                     AND o.vendor_id > 0|;
1104       }
1105
1106     }
1107     $query .= qq|
1108                  ORDER BY $sortorder|;
1109
1110   }
1111   my $sth = $dbh->prepare($query);
1112   $sth->execute || $form->dberror($query);
1113
1114   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
1115     push @{ $form->{parts} }, $ref;
1116   }
1117
1118   $sth->finish;
1119
1120   # include individual items for assemblies
1121   if ($form->{searchitems} eq 'assembly' && $form->{bom}) {
1122     foreach $item (@{ $form->{parts} }) {
1123       push @assemblies, $item;
1124       $query = qq|SELECT p.id, p.partnumber, p.description, a.qty AS onhand,
1125                   p.unit, p.bin,
1126                   p.sellprice, p.listprice, p.lastcost,
1127                   p.rop, p.weight, p.priceupdate,
1128                   p.image, p.drawing, p.microfiche
1129                   FROM parts p, assembly a
1130                   WHERE p.id = a.parts_id
1131                   AND a.id = $item->{id}|;
1132
1133       $sth = $dbh->prepare($query);
1134       $sth->execute || $form->dberror($query);
1135
1136       while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
1137         $ref->{assemblyitem} = 1;
1138         push @assemblies, $ref;
1139       }
1140       $sth->finish;
1141
1142       push @assemblies, { id => $item->{id} };
1143
1144     }
1145
1146     # copy assemblies to $form->{parts}
1147     @{ $form->{parts} } = @assemblies;
1148   }
1149
1150   $dbh->disconnect;
1151   $main::lxdebug->leave_sub();
1152 }
1153
1154 sub create_links {
1155   $main::lxdebug->enter_sub();
1156
1157   my ($self, $module, $myconfig, $form) = @_;
1158
1159   # connect to database
1160   my $dbh = $form->dbconnect($myconfig);
1161
1162   if ($form->{id}) {
1163     $query = qq|SELECT c.accno, c.description, c.link, c.id,
1164                         p.inventory_accno_id, p.income_accno_id, p.expense_accno_id
1165                         FROM chart c, parts p
1166                         WHERE c.link LIKE '%$module%'
1167                         AND p.id = $form->{id}
1168                         ORDER BY c.accno|;
1169   } else {
1170     $query = qq|SELECT c.accno, c.description, c.link, c.id,
1171                 d.inventory_accno_id, d.income_accno_id, d.expense_accno_id
1172                 FROM chart c, defaults d
1173                 WHERE c.link LIKE '%$module%'
1174                 ORDER BY c.accno|;
1175   }
1176
1177   my $sth = $dbh->prepare($query);
1178   $sth->execute || $form->dberror($query);
1179   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
1180     foreach my $key (split /:/, $ref->{link}) {
1181       if ($key =~ /$module/) {
1182         if (   ($ref->{id} eq $ref->{inventory_accno_id})
1183             || ($ref->{id} eq $ref->{income_accno_id})
1184             || ($ref->{id} eq $ref->{expense_accno_id})) {
1185           push @{ $form->{"${module}_links"}{$key} },
1186             { accno       => $ref->{accno},
1187               description => $ref->{description},
1188               selected    => "selected" };
1189             } else {
1190           push @{ $form->{"${module}_links"}{$key} },
1191             { accno       => $ref->{accno},
1192               description => $ref->{description},
1193               selected    => "" };
1194         }
1195       }
1196     }
1197   }
1198   $sth->finish;
1199
1200   if ($form->{id}) {
1201     $query = qq|SELECT weightunit
1202                 FROM defaults|;
1203     $sth = $dbh->prepare($query);
1204     $sth->execute || $form->dberror($query);
1205
1206     ($form->{weightunit}) = $sth->fetchrow_array;
1207     $sth->finish;
1208
1209   } else {
1210     $query = qq|SELECT weightunit, current_date
1211                 FROM defaults|;
1212     $sth = $dbh->prepare($query);
1213     $sth->execute || $form->dberror($query);
1214
1215     ($form->{weightunit}, $form->{priceupdate}) = $sth->fetchrow_array;
1216     $sth->finish;
1217   }
1218
1219   $dbh->disconnect;
1220   $main::lxdebug->leave_sub();
1221 }
1222
1223 # get partnumber, description, unit, sellprice and soldtotal with choice through $sortorder for Top100
1224 sub get_parts {
1225   $main::lxdebug->enter_sub();
1226
1227   my ($self, $myconfig, $form, $sortorder) = @_;
1228   my $dbh   = $form->dbconnect($myconfig);
1229   my $order = " p.partnumber";
1230   my $where = "1 = 1";
1231
1232   if ($sortorder eq "all") {
1233     $where .= " AND p.partnumber LIKE '%$form->{partnumber}%'";
1234     $where .= " AND p.description LIKE '%$form->{description}%'";
1235   } else {
1236     if ($sortorder eq "partnumber") {
1237       $where .= " AND p.partnumber LIKE '%$form->{partnumber}%'";
1238       $order = qq|p.$sortorder|;
1239     }
1240     if ($sortorder eq "description") {
1241       $where .= " AND p.description LIKE '%$form->{description}%'";
1242     }
1243   }
1244
1245   my $query =
1246     qq|SELECT p.id, p.partnumber, p.description, p.unit, p.sellprice FROM parts p WHERE $where ORDER BY $order|;
1247   my $sth = $dbh->prepare($query);
1248   $sth->execute || $self->dberror($query);
1249   my $j = 0;
1250   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
1251     if (($ref->{partnumber} eq "*") && ($ref->{description} eq "")) {
1252     } else {
1253       $j++;
1254       $form->{"id_$j"}          = $ref->{id};
1255       $form->{"partnumber_$j"}  = $ref->{partnumber};
1256       $form->{"description_$j"} = $ref->{description};
1257       $form->{"unit_$j"}        = $ref->{unit};
1258       $form->{"sellprice_$j"}   = $ref->{sellprice};
1259       $form->{"soldtotal_$j"}   = get_soldtotal($dbh, $ref->{id});
1260     }    #fi
1261   }    #while
1262   $form->{rows} = $j;
1263   $sth->finish;
1264   $dbh->disconnect;
1265
1266   $main::lxdebug->leave_sub();
1267
1268   return $self;
1269 }    #end get_parts()
1270
1271 # gets sum of sold part with part_id
1272 sub get_soldtotal {
1273   $main::lxdebug->enter_sub();
1274
1275   my ($dbh, $id) = @_;
1276
1277   my $query =
1278     qq|SELECT sum(i.qty) as totalsold FROM invoice i WHERE i.parts_id = $id|;
1279
1280   my $sth = $dbh->prepare($query);
1281   $sth->execute || $form->dberror($query);
1282
1283   my $sum = 0;
1284   while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
1285
1286     $sum = $ref->{totalsold};
1287   }    #while
1288   $sth->finish;
1289
1290   if ($sum eq undef) {
1291     $sum = 0;
1292   }    #fi
1293
1294   $main::lxdebug->leave_sub();
1295
1296   return $sum;
1297 }    #end get_soldtotal
1298
1299 sub retrieve_item {
1300   $main::lxdebug->enter_sub();
1301
1302   my ($self, $myconfig, $form) = @_;
1303   my $i     = $form->{rowcount};
1304   my $where = "NOT p.obsolete = '1'";
1305
1306   if ($form->{"partnumber_$i"}) {
1307     my $partnumber = $form->like(lc $form->{"partnumber_$i"});
1308     $where .= " AND lower(p.partnumber) LIKE '$partnumber'";
1309   }
1310   if ($form->{"description_$i"}) {
1311     my $description = $form->like(lc $form->{"description_$i"});
1312     $where .= " AND lower(p.description) LIKE '$description'";
1313   }
1314
1315   if ($form->{"partsgroup_$i"}) {
1316     my $partsgroup = $form->like(lc $form->{"partsgroup_$i"});
1317     $where .= " AND lower(pg.partsgroup) LIKE '$partsgroup'";
1318   }
1319
1320   if ($form->{"description_$i"}) {
1321     $where .= " ORDER BY description";
1322   } else {
1323     $where .= " ORDER BY partnumber";
1324   }
1325
1326   # connect to database
1327   my $dbh = $form->dbconnect($myconfig);
1328
1329   my $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
1330                         p.listprice,
1331                         c1.accno AS inventory_accno,
1332                         c2.accno AS income_accno,
1333                         c3.accno AS expense_accno,
1334                  p.unit, p.assembly, p.bin, p.onhand, p.notes AS partnotes,
1335                  pg.partsgroup
1336                  FROM parts p
1337                  LEFT JOIN chart c1 ON (p.inventory_accno_id = c1.id)
1338                  LEFT JOIN chart c2 ON (p.income_accno_id = c2.id)
1339                  LEFT JOIN chart c3 ON (p.expense_accno_id = c3.id)
1340                  LEFT JOIN partsgroup pg ON (pg.id = p.partsgroup_id)
1341                  WHERE $where|;
1342   my $sth = $dbh->prepare($query);
1343   $sth->execute || $form->dberror($query);
1344
1345   #while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
1346
1347   # get tax rates and description
1348   #$accno_id = ($form->{vc} eq "customer") ? $ref->{income_accno} : $ref->{inventory_accno};
1349   #$query = qq|SELECT c.accno, c.description, t.rate, t.taxnumber
1350   #           FROM chart c, tax t
1351   #           WHERE c.id=t.chart_id AND t.taxkey in (SELECT taxkey_id from chart where accno = '$accno_id')
1352   #           ORDER BY accno|;
1353   # $stw = $dbh->prepare($query);
1354   #$stw->execute || $form->dberror($query);
1355
1356   #$ref->{taxaccounts} = "";
1357   #while ($ptr = $stw->fetchrow_hashref(NAME_lc)) {
1358
1359   #   $form->{"$ptr->{accno}_rate"} = $ptr->{rate};
1360   #  $form->{"$ptr->{accno}_description"} = $ptr->{description};
1361   #   $form->{"$ptr->{accno}_taxnumber"} = $ptr->{taxnumber};
1362   #   $form->{taxaccounts} .= "$ptr->{accno} ";
1363   #   $ref->{taxaccounts} .= "$ptr->{accno} ";
1364
1365   #}
1366
1367   #$stw->finish;
1368   #chop $ref->{taxaccounts};
1369
1370   push @{ $form->{item_list} }, $ref;
1371
1372   #}
1373   $sth->finish;
1374   $dbh->disconnect;
1375
1376   $main::lxdebug->leave_sub();
1377 }
1378
1379 1;