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