Revision 83914eeb
Von Moritz Bunkus vor fast 17 Jahren hinzugefügt
SL/AM.pm | ||
---|---|---|
2407 | 2407 |
$main::lxdebug->leave_sub(); |
2408 | 2408 |
} |
2409 | 2409 |
|
2410 |
sub save_warehouse { |
|
2411 |
$main::lxdebug->enter_sub(); |
|
2412 |
|
|
2413 |
my ($self, $myconfig, $form) = @_; |
|
2414 |
|
|
2415 |
# connect to database |
|
2416 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
2417 |
|
|
2418 |
my ($query, @values, $sth); |
|
2419 |
|
|
2420 |
if (!$form->{id}) { |
|
2421 |
$query = qq|SELECT nextval('id')|; |
|
2422 |
($form->{id}) = selectrow_query($form, $dbh, $query); |
|
2423 |
|
|
2424 |
$query = qq|INSERT INTO warehouse (id, sortkey) VALUES (?, (SELECT COALESCE(MAX(sortkey), 0) + 1 FROM warehouse))|; |
|
2425 |
do_query($form, $dbh, $query, $form->{id}); |
|
2426 |
} |
|
2427 |
|
|
2428 |
do_query($form, $dbh, qq|UPDATE warehouse SET description = ?, invalid = ? WHERE id = ?|, |
|
2429 |
$form->{description}, $form->{invalid} ? 't' : 'f', conv_i($form->{id})); |
|
2430 |
|
|
2431 |
if (0 < $form->{number_of_new_bins}) { |
|
2432 |
$query = qq|INSERT INTO bin (warehouse_id, description) VALUES (?, ?)|; |
|
2433 |
$sth = prepare_query($form, $dbh, $query); |
|
2434 |
|
|
2435 |
foreach my $i (1..$form->{number_of_new_bins}) { |
|
2436 |
do_statement($form, $sth, $query, conv_i($form->{id}), "$form->{prefix}${i}"); |
|
2437 |
} |
|
2438 |
|
|
2439 |
$sth->finish(); |
|
2440 |
} |
|
2441 |
|
|
2442 |
$dbh->commit(); |
|
2443 |
|
|
2444 |
$main::lxdebug->leave_sub(); |
|
2445 |
} |
|
2446 |
|
|
2447 |
sub save_bins { |
|
2448 |
$main::lxdebug->enter_sub(); |
|
2449 |
|
|
2450 |
my ($self, $myconfig, $form) = @_; |
|
2451 |
|
|
2452 |
# connect to database |
|
2453 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
2454 |
|
|
2455 |
my ($query, @values, $commit_necessary, $sth); |
|
2456 |
|
|
2457 |
@values = map { $form->{"id_${_}"} } grep { $form->{"delete_${_}"} } (1..$form->{rowcount}); |
|
2458 |
|
|
2459 |
if (@values) { |
|
2460 |
$query = qq|DELETE FROM bin WHERE id IN (| . join(', ', ('?') x scalar(@values)) . qq|)|; |
|
2461 |
do_query($form, $dbh, $query, @values); |
|
2462 |
|
|
2463 |
$commit_necessary = 1; |
|
2464 |
} |
|
2465 |
|
|
2466 |
$query = qq|UPDATE bin SET description = ? WHERE id = ?|; |
|
2467 |
$sth = prepare_query($form, $dbh, $query); |
|
2468 |
|
|
2469 |
foreach my $row (1..$form->{rowcount}) { |
|
2470 |
next if ($form->{"delete_${row}"}); |
|
2471 |
|
|
2472 |
do_statement($form, $sth, $query, $form->{"description_${row}"}, conv_i($form->{"id_${row}"})); |
|
2473 |
|
|
2474 |
$commit_necessary = 1; |
|
2475 |
} |
|
2476 |
|
|
2477 |
$sth->finish(); |
|
2478 |
|
|
2479 |
$dbh->commit() if ($commit_necessary); |
|
2480 |
|
|
2481 |
$main::lxdebug->leave_sub(); |
|
2482 |
} |
|
2483 |
|
|
2484 |
sub delete_warehouse { |
|
2485 |
$main::lxdebug->enter_sub(); |
|
2486 |
|
|
2487 |
my ($self, $myconfig, $form) = @_; |
|
2488 |
|
|
2489 |
# connect to database |
|
2490 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
2491 |
|
|
2492 |
my $id = conv_i($form->{id}); |
|
2493 |
my $query = qq|SELECT i.bin_id FROM inventory i WHERE i.bin_id IN (SELECT b.id FROM bin b WHERE b.warehouse_id = ?) LIMIT 1|; |
|
2494 |
my ($count) = selectrow_query($form, $dbh, $query, $id); |
|
2495 |
|
|
2496 |
if ($count) { |
|
2497 |
$main::lxdebug->leave_sub(); |
|
2498 |
return 0; |
|
2499 |
} |
|
2500 |
|
|
2501 |
do_query($form, $dbh, qq|DELETE FROM warehouse_access WHERE warehouse_id = ?|, conv_i($form->{id})); |
|
2502 |
do_query($form, $dbh, qq|DELETE FROM bin WHERE warehouse_id = ?|, conv_i($form->{id})); |
|
2503 |
do_query($form, $dbh, qq|DELETE FROM warehouse WHERE id = ?|, conv_i($form->{id})); |
|
2504 |
|
|
2505 |
$dbh->commit(); |
|
2506 |
|
|
2507 |
$main::lxdebug->leave_sub(); |
|
2508 |
|
|
2509 |
return 1; |
|
2510 |
} |
|
2511 |
|
|
2512 |
sub get_all_warehouses { |
|
2513 |
$main::lxdebug->enter_sub(); |
|
2514 |
|
|
2515 |
my ($self, $myconfig, $form) = @_; |
|
2516 |
|
|
2517 |
# connect to database |
|
2518 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
2519 |
|
|
2520 |
my $query = qq|SELECT w.id, w.description, w.invalid |
|
2521 |
FROM warehouse w |
|
2522 |
ORDER BY w.sortkey|; |
|
2523 |
|
|
2524 |
$form->{WAREHOUSES} = selectall_hashref_query($form, $dbh, $query); |
|
2525 |
|
|
2526 |
$main::lxdebug->leave_sub(); |
|
2527 |
} |
|
2528 |
|
|
2529 |
sub get_warehouse { |
|
2530 |
$main::lxdebug->enter_sub(); |
|
2531 |
|
|
2532 |
my ($self, $myconfig, $form) = @_; |
|
2533 |
|
|
2534 |
# connect to database |
|
2535 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
2536 |
|
|
2537 |
my $id = conv_i($form->{id}); |
|
2538 |
my $query = qq|SELECT w.description, w.invalid |
|
2539 |
FROM warehouse w |
|
2540 |
WHERE w.id = ?|; |
|
2541 |
|
|
2542 |
my $ref = selectfirst_hashref_query($form, $dbh, $query, $id, $id); |
|
2543 |
|
|
2544 |
map { $form->{$_} = $ref->{$_} } keys %{ $ref }; |
|
2545 |
|
|
2546 |
$query = qq|SELECT b.*, EXISTS |
|
2547 |
(SELECT i.warehouse_id |
|
2548 |
FROM inventory i |
|
2549 |
WHERE i.bin_id = b.id |
|
2550 |
LIMIT 1) |
|
2551 |
AS in_use |
|
2552 |
FROM bin b |
|
2553 |
WHERE b.warehouse_id = ?|; |
|
2554 |
|
|
2555 |
$form->{BINS} = selectall_hashref_query($form, $dbh, $query, conv_i($form->{id})); |
|
2556 |
|
|
2557 |
$main::lxdebug->leave_sub(); |
|
2558 |
} |
|
2410 | 2559 |
|
2411 | 2560 |
1; |
SL/Auth.pm | ||
---|---|---|
636 | 636 |
["purchase_order_edit", $locale->text("Create and edit purchase orders")], |
637 | 637 |
["purchase_delivery_order_edit", $locale->text("Create and edit purchase delivery orders")], |
638 | 638 |
["vendor_invoice_edit", $locale->text("Create and edit vendor invoices")], |
639 |
["--warehouse_management", $locale->text("Warehouse management")], |
|
640 |
["warehouse_contents", $locale->text("View warehouse content")], |
|
641 |
["warehouse_management", $locale->text("Warehouse management")], |
|
639 | 642 |
["--general_ledger_cash", $locale->text("General ledger and cash")], |
640 | 643 |
["general_ledger", $locale->text("Transactions, AR transactions, AP transactions")], |
641 | 644 |
["datev_export", $locale->text("DATEV Export")], |
SL/IC.pm | ||
---|---|---|
325 | 325 |
} |
326 | 326 |
|
327 | 327 |
if ($form->{item} eq 'assembly') { |
328 |
if ($form->{onhand} != 0) { |
|
329 |
&adjust_inventory($dbh, $form, $form->{id}, $form->{onhand} * -1); |
|
330 |
} |
|
331 |
|
|
332 | 328 |
# delete assembly records |
333 | 329 |
do_query($form, $dbh, qq|DELETE FROM assembly WHERE id = ?|, conv_i($form->{id})); |
334 |
|
|
335 |
$form->{onhand} += $form->{stock}; |
|
336 | 330 |
} |
337 | 331 |
|
338 | 332 |
# delete tax records |
... | ... | |
352 | 346 |
do_query($form, $dbh, qq|INSERT INTO parts (id, partnumber) VALUES (?, '')|, $form->{id}); |
353 | 347 |
|
354 | 348 |
$form->{orphaned} = 1; |
355 |
$form->{onhand} = $form->{stock} if $form->{item} eq 'assembly'; |
|
356 | 349 |
if ($form->{partnumber} eq "" && $form->{"item"} eq "service") { |
357 | 350 |
$form->{partnumber} = $form->update_defaults($myconfig, "servicenumber"); |
358 | 351 |
} |
... | ... | |
532 | 525 |
} |
533 | 526 |
} |
534 | 527 |
|
535 |
# adjust onhand for the parts |
|
536 |
if ($form->{onhand} != 0) { |
|
537 |
&adjust_inventory($dbh, $form, $form->{id}, $form->{onhand}); |
|
538 |
} |
|
539 |
|
|
540 | 528 |
@a = localtime; |
541 | 529 |
$a[5] += 1900; |
542 | 530 |
$a[4]++; |
... | ... | |
544 | 532 |
|
545 | 533 |
$form->get_employee($dbh); |
546 | 534 |
|
547 |
# add inventory record |
|
548 |
$query = |
|
549 |
qq|INSERT INTO inventory (warehouse_id, parts_id, qty, shippingdate, employee_id) |
|
550 |
VALUES (0, ?, ?, '$shippingdate', ?)|; |
|
551 |
@values = (conv_i($form->{id}), $form->{stock}, conv_i($form->{employee_id})); |
|
552 |
do_query($form, $dbh, $query, @values); |
|
553 |
|
|
554 | 535 |
} |
555 | 536 |
|
556 | 537 |
#set expense_accno=inventory_accno if they are different => bilanz |
... | ... | |
650 | 631 |
$main::lxdebug->leave_sub(); |
651 | 632 |
} |
652 | 633 |
|
653 |
sub restock_assemblies { |
|
654 |
$main::lxdebug->enter_sub(); |
|
655 |
|
|
656 |
my ($self, $myconfig, $form) = @_; |
|
657 |
|
|
658 |
# connect to database |
|
659 |
my $dbh = $form->dbconnect_noauto($myconfig); |
|
660 |
|
|
661 |
for my $i (1 .. $form->{rowcount}) { |
|
662 |
|
|
663 |
$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"}); |
|
664 |
|
|
665 |
if ($form->{"qty_$i"} != 0) { |
|
666 |
&adjust_inventory($dbh, $form, $form->{"id_$i"}, $form->{"qty_$i"}); |
|
667 |
} |
|
668 |
|
|
669 |
} |
|
670 |
|
|
671 |
my $rc = $dbh->commit; |
|
672 |
$dbh->disconnect; |
|
673 |
|
|
674 |
$main::lxdebug->leave_sub(); |
|
675 |
|
|
676 |
return $rc; |
|
677 |
} |
|
678 |
|
|
679 |
sub adjust_inventory { |
|
680 |
$main::lxdebug->enter_sub(); |
|
681 |
|
|
682 |
my ($dbh, $form, $id, $qty) = @_; |
|
683 |
|
|
684 |
my $query = |
|
685 |
qq|SELECT p.id, p.inventory_accno_id, p.assembly, a.qty |
|
686 |
FROM parts p, assembly a |
|
687 |
WHERE (a.parts_id = p.id) AND (a.id = ?)|; |
|
688 |
my $sth = prepare_execute_query($form, $dbh, $query, conv_i($id)); |
|
689 |
|
|
690 |
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { |
|
691 |
|
|
692 |
my $allocate = $qty * $ref->{qty}; |
|
693 |
|
|
694 |
# is it a service item, then loop |
|
695 |
$ref->{inventory_accno_id} *= 1; |
|
696 |
next if (($ref->{inventory_accno_id} == 0) && !$ref->{assembly}); |
|
697 |
|
|
698 |
# adjust parts onhand |
|
699 |
$form->update_balance($dbh, "parts", "onhand", |
|
700 |
qq|id = $ref->{id}|, |
|
701 |
$allocate * -1); |
|
702 |
} |
|
703 |
|
|
704 |
$sth->finish; |
|
705 |
|
|
706 |
# update assembly |
|
707 |
my $rc = $form->update_balance($dbh, "parts", "onhand", qq|id = ?|, $qty, $id); |
|
708 |
|
|
709 |
$main::lxdebug->leave_sub(); |
|
710 |
|
|
711 |
return $rc; |
|
712 |
} |
|
713 |
|
|
714 | 634 |
sub delete { |
715 | 635 |
$main::lxdebug->enter_sub(); |
716 | 636 |
|
... | ... | |
1014 | 934 |
|
1015 | 935 |
$form->{parts} = selectall_hashref_query($form, $dbh, $query, @bind_vars); |
1016 | 936 |
|
937 |
map { $_->{onhand} *= 1 } @{ $form->{parts} }; |
|
938 |
|
|
1017 | 939 |
## my $where = qq|1 = 1|; |
1018 | 940 |
## my (@values, $var, $flds, $group, $limit); |
1019 | 941 |
## |
SL/IR.pm | ||
---|---|---|
178 | 178 |
@values = ($form->{"sellprice_$i"}, conv_i($form->{"id_$i"})); |
179 | 179 |
do_query($form, $dbh, $query, @values); |
180 | 180 |
|
181 |
$form->update_balance($dbh, "parts", "onhand", qq|id = ?|, $baseqty, $form->{"id_$i"}) if !$form->{shipped}; |
|
182 |
|
|
183 | 181 |
# check if we sold the item already and |
184 | 182 |
# make an entry for the expense and inventory |
185 | 183 |
$query = |
... | ... | |
572 | 570 |
|
573 | 571 |
next unless $ref->{inventory_accno_id}; |
574 | 572 |
|
575 |
# update onhand |
|
576 |
$form->update_balance($dbh, "parts", "onhand", qq|id = $ref->{parts_id}|, $ref->{qty}); |
|
577 |
|
|
578 | 573 |
# if $ref->{allocated} > 0 than we sold that many items |
579 | 574 |
next if ($ref->{allocated} <= 0); |
580 | 575 |
|
... | ... | |
1057 | 1052 |
$stw->finish(); |
1058 | 1053 |
chop $ref->{taxaccounts}; |
1059 | 1054 |
|
1055 |
$ref->{onhand} *= 1; |
|
1056 |
|
|
1060 | 1057 |
push @{ $form->{item_list} }, $ref; |
1061 | 1058 |
|
1062 | 1059 |
} |
SL/IS.pm | ||
---|---|---|
645 | 645 |
|
646 | 646 |
if ($form->{"inventory_accno_$i"} || $form->{"assembly_$i"}) { |
647 | 647 |
|
648 |
# adjust parts onhand quantity |
|
649 |
|
|
650 | 648 |
if ($form->{"assembly_$i"}) { |
651 |
|
|
652 |
# do not update if assembly consists of all services |
|
653 |
$query = |
|
654 |
qq|SELECT sum(p.inventory_accno_id) |
|
655 |
FROM parts p |
|
656 |
JOIN assembly a ON (a.parts_id = p.id) |
|
657 |
WHERE a.id = ?|; |
|
658 |
$sth = prepare_execute_query($form, $dbh, $query, conv_i($form->{"id_$i"})); |
|
659 |
|
|
660 |
if ($sth->fetchrow_array) { |
|
661 |
$form->update_balance($dbh, "parts", "onhand", qq|id = ?|, |
|
662 |
$baseqty * -1, $form->{"id_$i"}) |
|
663 |
unless $form->{shipped}; |
|
664 |
} |
|
665 |
$sth->finish; |
|
666 |
|
|
667 | 649 |
# record assembly item as allocated |
668 | 650 |
&process_assembly($dbh, $form, $form->{"id_$i"}, $baseqty); |
669 | 651 |
} else { |
670 |
$form->update_balance($dbh, "parts", "onhand", qq|id = ?|, |
|
671 |
$baseqty * -1, $form->{"id_$i"}) |
|
672 |
unless $form->{shipped}; |
|
673 |
|
|
674 | 652 |
$allocated = &cogs($dbh, $form, $form->{"id_$i"}, $baseqty, $basefactor, $i); |
675 | 653 |
} |
676 | 654 |
} |
... | ... | |
1236 | 1214 |
|
1237 | 1215 |
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { |
1238 | 1216 |
|
1239 |
if ($ref->{inventory_accno_id} || $ref->{assembly}) { |
|
1240 |
|
|
1241 |
# if the invoice item is not an assemblyitem adjust parts onhand |
|
1242 |
if (!$ref->{assemblyitem}) { |
|
1243 |
|
|
1244 |
# adjust onhand in parts table |
|
1245 |
$form->update_balance($dbh, "parts", "onhand", qq|id = $ref->{parts_id}|, $ref->{qty}); |
|
1246 |
} |
|
1247 |
|
|
1248 |
# loop if it is an assembly |
|
1249 |
next if ($ref->{assembly}); |
|
1250 |
|
|
1217 |
if ($ref->{inventory_accno_id}) { |
|
1251 | 1218 |
# de-allocated purchases |
1252 | 1219 |
$query = |
1253 | 1220 |
qq|SELECT i.id, i.trans_id, i.allocated |
... | ... | |
1825 | 1792 |
} |
1826 | 1793 |
} |
1827 | 1794 |
|
1795 |
$ref->{onhand} *= 1; |
|
1796 |
|
|
1828 | 1797 |
push @{ $form->{item_list} }, $ref; |
1829 | 1798 |
|
1830 | 1799 |
if ($form->{lizenzen}) { |
SL/LICENSES.pm | ||
---|---|---|
68 | 68 |
$sth->execute || $form->dberror($query); |
69 | 69 |
$sth->finish(); |
70 | 70 |
|
71 |
if ($form->{own_product}) { |
|
72 |
$form->update_balance($dbh, "parts", "onhand", qq|id = ?|, |
|
73 |
1, $form->{parts_id}); |
|
74 |
} |
|
75 |
|
|
76 | 71 |
$dbh->disconnect(); |
77 | 72 |
|
78 | 73 |
$main::lxdebug->leave_sub(); |
SL/OE.pm | ||
---|---|---|
242 | 242 |
|
243 | 243 |
if ($form->{id}) { |
244 | 244 |
|
245 |
&adj_onhand($dbh, $form, $ml) if $form->{type} =~ /_order$/; |
|
246 |
|
|
247 | 245 |
$query = qq|DELETE FROM orderitems WHERE trans_id = ?|; |
248 | 246 |
do_query($form, $dbh, $query, $form->{id}); |
249 | 247 |
|
... | ... | |
382 | 380 |
} |
383 | 381 |
$query .= qq|?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, |
384 | 382 |
(SELECT factor FROM price_factors WHERE id = ?), ?)|; |
385 |
push(@values,
|
|
383 |
push(@values, |
|
386 | 384 |
conv_i($form->{id}), conv_i($form->{"id_$i"}), |
387 | 385 |
$form->{"description_$i"}, $form->{"longdescription_$i"}, |
388 | 386 |
$form->{"qty_$i"}, $baseqty, |
... | ... | |
476 | 474 |
} |
477 | 475 |
} |
478 | 476 |
|
479 |
if ($form->{type} =~ /_order$/) { |
|
480 |
|
|
481 |
# adjust onhand |
|
482 |
&adj_onhand($dbh, $form, $ml * -1); |
|
483 |
} |
|
484 |
|
|
485 | 477 |
$form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ? |
486 | 478 |
"quonumber" : "ordnumber"}; |
487 | 479 |
|
... | ... | |
556 | 548 |
} |
557 | 549 |
$sth->finish; |
558 | 550 |
|
559 |
$query = qq|SELECT o.parts_id, o.ship FROM orderitems o | . |
|
560 |
qq|WHERE o.trans_id = ?|; |
|
561 |
@values = (conv_i($form->{id})); |
|
562 |
$sth = $dbh->prepare($query); |
|
563 |
$sth->execute(@values) || $self->dberror($query); |
|
564 |
|
|
565 |
while (my ($id, $ship) = $sth->fetchrow_array) { |
|
566 |
$form->update_balance($dbh, "parts", "onhand", qq|id = $id|, $ship * -1); |
|
567 |
} |
|
568 |
$sth->finish; |
|
569 |
|
|
570 | 551 |
# delete-values |
571 | 552 |
@values = (conv_i($form->{id})); |
572 | 553 |
|
573 |
# delete inventory |
|
574 |
$query = qq|DELETE FROM inventory | . |
|
575 |
qq|WHERE oe_id = ?|; |
|
576 |
do_query($form, $dbh, $query, @values); |
|
577 |
|
|
578 | 554 |
# delete status entries |
579 | 555 |
$query = qq|DELETE FROM status | . |
580 | 556 |
qq|WHERE trans_id = ?|; |
... | ... | |
1153 | 1129 |
return $value; |
1154 | 1130 |
} |
1155 | 1131 |
|
1156 |
sub adj_onhand { |
|
1157 |
$main::lxdebug->enter_sub(); |
|
1158 |
|
|
1159 |
my ($dbh, $form, $ml) = @_; |
|
1160 |
|
|
1161 |
my $all_units = $form->{all_units}; |
|
1162 |
|
|
1163 |
my $query = |
|
1164 |
qq|SELECT oi.parts_id, oi.ship, oi.unit, p.inventory_accno_id, p.assembly | . |
|
1165 |
qq| FROM orderitems oi | . |
|
1166 |
qq| JOIN parts p ON (p.id = oi.parts_id) | . |
|
1167 |
qq| WHERE oi.trans_id = ?|; |
|
1168 |
my @values = ($form->{id}); |
|
1169 |
my $sth = $dbh->prepare($query); |
|
1170 |
$sth->execute(@values) || $form->dberror($query); |
|
1171 |
|
|
1172 |
$query = |
|
1173 |
qq|SELECT sum(p.inventory_accno_id) | . |
|
1174 |
qq|FROM parts p | . |
|
1175 |
qq|JOIN assembly a ON (a.parts_id = p.id) | . |
|
1176 |
qq|WHERE a.id = ?|; |
|
1177 |
my $ath = $dbh->prepare($query) || $form->dberror($query); |
|
1178 |
|
|
1179 |
my $ispa; |
|
1180 |
|
|
1181 |
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { |
|
1182 |
if ($ref->{inventory_accno_id} || $ref->{assembly}) { |
|
1183 |
|
|
1184 |
# do not update if assembly consists of all services |
|
1185 |
if ($ref->{assembly}) { |
|
1186 |
$ath->execute($ref->{parts_id}) || $form->dberror($query); |
|
1187 |
|
|
1188 |
($ispa) = $sth->fetchrow_array; |
|
1189 |
$ath->finish; |
|
1190 |
|
|
1191 |
next unless $ispa; |
|
1192 |
|
|
1193 |
} |
|
1194 |
|
|
1195 |
# get item baseunit |
|
1196 |
$query = qq|SELECT unit FROM parts WHERE id = ?|; |
|
1197 |
my ($item_unit) = selectrow_query($form, $dbh, $query, $ref->{parts_id}); |
|
1198 |
|
|
1199 |
my $basefactor = 1; |
|
1200 |
if (defined($all_units->{$item_unit}->{factor}) && (($all_units->{$item_unit}->{factor} * 1) != 0)) { |
|
1201 |
$basefactor = $all_units->{$ref->{unit}}->{factor} / $all_units->{$item_unit}->{factor}; |
|
1202 |
} |
|
1203 |
my $baseqty = $ref->{ship} * $basefactor; |
|
1204 |
|
|
1205 |
# adjust onhand in parts table |
|
1206 |
$form->update_balance($dbh, "parts", "onhand", qq|id = $ref->{parts_id}|, $baseqty * $ml); |
|
1207 |
} |
|
1208 |
} |
|
1209 |
|
|
1210 |
$sth->finish; |
|
1211 |
|
|
1212 |
$main::lxdebug->leave_sub(); |
|
1213 |
} |
|
1214 |
|
|
1215 | 1132 |
1; |
SL/WH.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) 1999-2003 |
|
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 |
# Warehouse module |
|
32 |
# |
|
33 |
#====================================================================== |
|
34 |
|
|
35 |
package WH; |
|
36 |
|
|
37 |
use SL::AM; |
|
38 |
use SL::DBUtils; |
|
39 |
use SL::Form; |
|
40 |
|
|
41 |
sub transfer { |
|
42 |
$main::lxdebug->enter_sub(); |
|
43 |
|
|
44 |
my $self = shift; |
|
45 |
|
|
46 |
if (!@_) { |
|
47 |
$main::lxdebug->leave_sub(); |
|
48 |
return; |
|
49 |
} |
|
50 |
|
|
51 |
my $myconfig = \%main::myconfig; |
|
52 |
my $form = $main::form; |
|
53 |
|
|
54 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
55 |
|
|
56 |
my $units = AM->retrieve_units($myconfig, $form); |
|
57 |
|
|
58 |
my $query = qq|SELECT * FROM transfer_type|; |
|
59 |
my $sth = prepare_execute_query($form, $dbh, $query); |
|
60 |
|
|
61 |
my %transfer_types; |
|
62 |
|
|
63 |
while (my $ref = $sth->fetchrow_hashref()) { |
|
64 |
$transfer_types{$ref->{direction}} ||= { }; |
|
65 |
$transfer_types{$ref->{direction}}->{$ref->{description}} = $ref->{id}; |
|
66 |
} |
|
67 |
|
|
68 |
my @part_ids = map { $_->{parts_id} } @_; |
|
69 |
my %partunits = selectall_as_map($form, $dbh, qq|SELECT id, unit FROM parts WHERE id IN (| . join(', ', map { '?' } @part_ids ) . qq|)|, 'id', 'unit', @part_ids); |
|
70 |
|
|
71 |
my ($now) = selectrow_query($form, $dbh, qq|SELECT current_date|); |
|
72 |
|
|
73 |
$query = qq|INSERT INTO inventory (warehouse_id, bin_id, parts_id, chargenumber, oe_id, orderitems_id, shippingdate, |
|
74 |
employee_id, project_id, trans_id, trans_type_id, comment, qty) |
|
75 |
VALUES (?, ?, ?, ?, ?, ?, ?, (SELECT id FROM employee WHERE login = ?), ?, ?, ?, ?, ?)|; |
|
76 |
|
|
77 |
$sth = prepare_query($form, $dbh, $query); |
|
78 |
|
|
79 |
my @directions = (undef, 'out', 'in', 'transfer'); |
|
80 |
|
|
81 |
while (@_) { |
|
82 |
my $transfer = shift; |
|
83 |
my ($trans_id) = selectrow_query($form, $dbh, qq|SELECT nextval('id')|); |
|
84 |
|
|
85 |
my ($direction, @values) = (0); |
|
86 |
|
|
87 |
$direction |= 1 if ($transfer->{src_warehouse_id} && $transfer->{src_bin_id}); |
|
88 |
$direction |= 2 if ($transfer->{dst_warehouse_id} && $transfer->{dst_bin_id}); |
|
89 |
|
|
90 |
push @values, conv_i($transfer->{parts_id}), "$transfer->{chargenumber}", conv_i($transfer->{oe_id}), conv_i($transfer->{orderitems_id}); |
|
91 |
push @values, $transfer->{shippingdate} eq 'current_date' ? $now : conv_date($transfer->{shippingdate}), $form->{login}, conv_i($transfer->{project_id}), $trans_id; |
|
92 |
|
|
93 |
if ($transfer->{transfer_type_id}) { |
|
94 |
push @values, $transfer->{transfer_type_id}; |
|
95 |
} else { |
|
96 |
push @values, $transfer_types{$directions[$direction]}->{$transfer->{transfer_type}}; |
|
97 |
} |
|
98 |
|
|
99 |
push @values, "$transfer->{comment}"; |
|
100 |
|
|
101 |
$qty = $transfer->{qty}; |
|
102 |
|
|
103 |
if ($transfer->{unit}) { |
|
104 |
my $partunit = $partunits{$transfer->{parts_id}}; |
|
105 |
|
|
106 |
$qty *= $units->{$transfer->{unit}}->{factor}; |
|
107 |
$qty /= $units->{$partunit}->{factor} || 1 if ($partunit); |
|
108 |
} |
|
109 |
|
|
110 |
if ($direction & 1) { |
|
111 |
do_statement($form, $sth, $query, conv_i($transfer->{src_warehouse_id}), conv_i($transfer->{src_bin_id}), @values, $qty * -1); |
|
112 |
} |
|
113 |
|
|
114 |
if ($direction & 2) { |
|
115 |
do_statement($form, $sth, $query, conv_i($transfer->{dst_warehouse_id}), conv_i($transfer->{dst_bin_id}), @values, $qty); |
|
116 |
} |
|
117 |
} |
|
118 |
|
|
119 |
$sth->finish(); |
|
120 |
|
|
121 |
$dbh->commit(); |
|
122 |
|
|
123 |
$main::lxdebug->leave_sub(); |
|
124 |
} |
|
125 |
|
|
126 |
sub get_warehouse_journal { |
|
127 |
$main::lxdebug->enter_sub(); |
|
128 |
|
|
129 |
my $self = shift; |
|
130 |
my %filter = @_; |
|
131 |
|
|
132 |
my $myconfig = \%main::myconfig; |
|
133 |
my $form = $main::form; |
|
134 |
|
|
135 |
my $all_units = AM->retrieve_units($myconfig, $form); |
|
136 |
|
|
137 |
# connect to database |
|
138 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
139 |
|
|
140 |
# filters |
|
141 |
my (@filter_ary, @filter_vars, $joins); |
|
142 |
|
|
143 |
if ($filter{warehouse_id} ne '') { |
|
144 |
push @filter_ary, "w1.id = ? OR w2.id = ?"; |
|
145 |
push @filter_vars, $filter{warehouse_id}, $filter{warehouse_id}; |
|
146 |
} |
|
147 |
|
|
148 |
if ($filter{bin_id} ne '') { |
|
149 |
push @filter_ary, "b1.id = ? OR b2.id = ?"; |
|
150 |
push @filter_vars, $filter{bin_id}, $filter{bin_id}; |
|
151 |
} |
|
152 |
|
|
153 |
if ($filter{partnumber}) { |
|
154 |
push @filter_ary, "p.partnumber ILIKE ?"; |
|
155 |
push @filter_vars, '%' . $filter{partnumber} . '%'; |
|
156 |
} |
|
157 |
|
|
158 |
if ($filter{description}) { |
|
159 |
push @filter_ary, "(p.description ILIKE ?)"; |
|
160 |
push @filter_vars, '%' . $filter{description} . '%'; |
|
161 |
} |
|
162 |
|
|
163 |
if ($filter{chargenumber}) { |
|
164 |
push @filter_ary, "w1.chargenumber ILIKE ?"; |
|
165 |
push @filter_vars, '%' . $filter{chargenumber} . '%'; |
|
166 |
} |
|
167 |
|
|
168 |
if ($form->{fromdate}) { |
|
169 |
push @filter_ary, "?::DATE <= i1.itime::DATE"; |
|
170 |
push @filter_vars, $form->{fromdate}; |
|
171 |
} |
|
172 |
|
|
173 |
if ($form->{todate}) { |
|
174 |
push @filter_ary, "?::DATE >= i1.itime::DATE"; |
|
175 |
push @filter_vars, $form->{todate}; |
|
176 |
} |
|
177 |
|
|
178 |
if ($form->{l_employee}) { |
|
179 |
$joins .= ""; |
|
180 |
} |
|
181 |
|
|
182 |
# prepare qty comparison for later filtering |
|
183 |
my ($f_qty_op, $f_qty, $f_qty_base_unit); |
|
184 |
if ($filter{qty_op} && defined($filter{qty}) && $filter{qty_unit} && $all_units->{$filter{qty_unit}}) { |
|
185 |
$f_qty_op = $filter{qty_op}; |
|
186 |
$f_qty = $filter{qty} * $all_units->{$filter{qty_unit}}->{factor}; |
|
187 |
$f_qty_base_unit = $all_units->{$filter{qty_unit}}->{base_unit}; |
|
188 |
} |
|
189 |
|
|
190 |
map { $_ = "(${_})"; } @filter_ary; |
|
191 |
|
|
192 |
# if of a property number or description is requested, |
|
193 |
# automatically check the matching id too. |
|
194 |
map { $form->{"l_${_}id"} = "Y" if ($form->{"l_${_}description"} || $form->{"l_${_}number"}); } qw(warehouse bin); |
|
195 |
|
|
196 |
# customize shown entry for not available fields. |
|
197 |
$filter{na} = '-' unless $filter{na}; |
|
198 |
|
|
199 |
# make order, search in $filter and $form |
|
200 |
$form->{sort} = $filter{sort} unless $form->{sort}; |
|
201 |
$form->{order} = ($form->{sort} = 'itime') unless $form->{sort}; |
|
202 |
$form->{sort} = 'itime' if $form->{sort} eq "date"; |
|
203 |
$form->{order} = $filter{order} unless $form->{order}; |
|
204 |
$form->{sort} .= (($form->{order}) ? " DESC" : " ASC"); |
|
205 |
|
|
206 |
my $where_clause = join(" AND ", @filter_ary) . " AND " if (@filter_ary); |
|
207 |
|
|
208 |
$select_tokens{'trans'} = { |
|
209 |
"parts_id" => "i1.parts_id", |
|
210 |
"qty" => "ABS(SUM(i1.qty))", |
|
211 |
"partnumber" => "p.partnumber", |
|
212 |
"partdescription" => "p.description", |
|
213 |
"bindescription" => "b.description", |
|
214 |
"chargenumber" => "i1.chargenumber", |
|
215 |
"warehousedescription" => "w.description", |
|
216 |
"partunit" => "p.unit", |
|
217 |
"bin_from" => "b1.description", |
|
218 |
"bin_to" => "b2.description", |
|
219 |
"warehouse_from" => "w1.description", |
|
220 |
"warehouse_to" => "w2.description", |
|
221 |
"comment" => "i1.comment", |
|
222 |
"trans_type" => "tt.description", |
|
223 |
"trans_id" => "i1.trans_id", |
|
224 |
"date" => "i1.itime::DATE", |
|
225 |
"itime" => "i1.itime", |
|
226 |
"employee" => "e.name", |
|
227 |
"projectnumber" => "COALESCE(pr.projectnumber, '$filter{na}')", |
|
228 |
}; |
|
229 |
|
|
230 |
$select_tokens{'out'} = { |
|
231 |
"bin_to" => "'$filter{na}'", |
|
232 |
"warehouse_to" => "'$filter{na}'", |
|
233 |
}; |
|
234 |
|
|
235 |
$select_tokens{'in'} = { |
|
236 |
"bin_from" => "'$filter{na}'", |
|
237 |
"warehouse_from" => "'$filter{na}'", |
|
238 |
}; |
|
239 |
|
|
240 |
# build the select clauses. |
|
241 |
# take all the requested ones from the first hash and overwrite them from the out/in hashes if present. |
|
242 |
for my $i ('trans', 'out', 'in') { |
|
243 |
$select{$i} = join ', ', map { +/l_/; ($select_tokens{$i}{"$'"} || $select_tokens{'trans'}{"$'"}) . " AS r_$'" } |
|
244 |
( grep( { !/qty$/ and /l_/ and $form->{$_} eq 'Y' } keys %$form), qw(l_parts_id l_qty l_partunit l_itime) ); |
|
245 |
} |
|
246 |
|
|
247 |
my $group_clause = join ", ", map { +/^l_/; "r_$'" } |
|
248 |
( grep( { !/qty$/ and /l_/ and $form->{$_} eq 'Y' } keys %$form), qw(l_parts_id l_partunit l_itime) ); |
|
249 |
|
|
250 |
my $query = |
|
251 |
qq|SELECT DISTINCT $select{trans} |
|
252 |
FROM inventory i1 |
|
253 |
LEFT JOIN inventory i2 ON i1.trans_id = i2.trans_id |
|
254 |
LEFT JOIN parts p ON i1.parts_id = p.id |
|
255 |
LEFT JOIN bin b1 ON i1.bin_id = b1.id |
|
256 |
LEFT JOIN bin b2 ON i2.bin_id = b2.id |
|
257 |
LEFT JOIN warehouse w1 ON i1.warehouse_id = w1.id |
|
258 |
LEFT JOIN warehouse w2 ON i2.warehouse_id = w2.id |
|
259 |
LEFT JOIN transfer_type tt ON i1.trans_type_id = tt.id |
|
260 |
LEFT JOIN project pr ON i1.project_id = pr.id |
|
261 |
LEFT JOIN employee e ON i1.employee_id = e.id |
|
262 |
WHERE $where_clause i2.qty = -i1.qty AND i2.qty > 0 AND |
|
263 |
i1.trans_id IN ( SELECT i.trans_id FROM inventory i GROUP BY i.trans_id HAVING COUNT(i.trans_id) = 2 ) |
|
264 |
GROUP BY $group_clause |
|
265 |
|
|
266 |
UNION |
|
267 |
|
|
268 |
SELECT DISTINCT $select{out} |
|
269 |
FROM inventory i1 |
|
270 |
LEFT JOIN inventory i2 ON i1.trans_id = i2.trans_id |
|
271 |
LEFT JOIN parts p ON i1.parts_id = p.id |
|
272 |
LEFT JOIN bin b1 ON i1.bin_id = b1.id |
|
273 |
LEFT JOIN bin b2 ON i2.bin_id = b2.id |
|
274 |
LEFT JOIN warehouse w1 ON i1.warehouse_id = w1.id |
|
275 |
LEFT JOIN warehouse w2 ON i2.warehouse_id = w2.id |
|
276 |
LEFT JOIN transfer_type tt ON i1.trans_type_id = tt.id |
|
277 |
LEFT JOIN project pr ON i1.project_id = pr.id |
|
278 |
LEFT JOIN employee e ON i1.employee_id = e.id |
|
279 |
WHERE $where_clause i1.qty < 0 AND |
|
280 |
i1.trans_id IN ( SELECT i.trans_id FROM inventory i GROUP BY i.trans_id HAVING COUNT(i.trans_id) = 1 ) |
|
281 |
GROUP BY $group_clause |
|
282 |
|
|
283 |
UNION |
|
284 |
|
|
285 |
SELECT DISTINCT $select{in} |
|
286 |
FROM inventory i1 |
|
287 |
LEFT JOIN inventory i2 ON i1.trans_id = i2.trans_id |
|
288 |
LEFT JOIN parts p ON i1.parts_id = p.id |
|
289 |
LEFT JOIN bin b1 ON i1.bin_id = b1.id |
|
290 |
LEFT JOIN bin b2 ON i2.bin_id = b2.id |
|
291 |
LEFT JOIN warehouse w1 ON i1.warehouse_id = w1.id |
|
292 |
LEFT JOIN warehouse w2 ON i2.warehouse_id = w2.id |
|
293 |
LEFT JOIN transfer_type tt ON i1.trans_type_id = tt.id |
|
294 |
LEFT JOIN project pr ON i1.project_id = pr.id |
|
295 |
LEFT JOIN employee e ON i1.employee_id = e.id |
|
296 |
WHERE $where_clause i1.qty > 0 AND |
|
297 |
i1.trans_id IN ( SELECT i.trans_id FROM inventory i GROUP BY i.trans_id HAVING COUNT(i.trans_id) = 1 ) |
|
298 |
GROUP BY $group_clause |
|
299 |
ORDER BY r_$form->{sort}|; |
|
300 |
|
|
301 |
my $sth = prepare_execute_query($form, $dbh, $query, @filter_vars, @filter_vars, @filter_vars); |
|
302 |
|
|
303 |
my @contents = (); |
|
304 |
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { |
|
305 |
map { /^r_/; $ref->{"$'"} = $ref->{$_} } keys %$ref; |
|
306 |
my $qty = $ref->{"qty"} * 1; |
|
307 |
|
|
308 |
next unless ($qty > 0); |
|
309 |
|
|
310 |
if ($f_qty_op) { |
|
311 |
my $part_unit = $all_units->{$ref->{"partunit"}}; |
|
312 |
next unless ($part_unit && ($part_unit->{"base_unit"} eq $f_qty_base_unit)); |
|
313 |
$qty *= $part_unit->{"factor"}; |
|
314 |
next if (('=' eq $f_qty_op) && ($qty != $f_qty)); |
|
315 |
next if (('>=' eq $f_qty_op) && ($qty < $f_qty)); |
|
316 |
next if (('<=' eq $f_qty_op) && ($qty > $f_qty)); |
|
317 |
} |
|
318 |
|
|
319 |
push @contents, $ref; |
|
320 |
} |
|
321 |
|
|
322 |
$sth->finish(); |
|
323 |
|
|
324 |
$main::lxdebug->leave_sub(); |
|
325 |
|
|
326 |
return @contents; |
|
327 |
} |
|
328 |
|
|
329 |
# |
|
330 |
# This sub is the primary function to retrieve information about items in warehouses. |
|
331 |
# $filter is a hashref and supports the following keys: |
|
332 |
# - warehouse_id - will return matches with this warehouse_id only |
|
333 |
# - partnumber - will return only matches where the given string is a substring of the partnumber |
|
334 |
# - partsid - will return matches with this parts_id only |
|
335 |
# - description - will return only matches where the given string is a substring of the description |
|
336 |
# - chargenumber - will return only matches where the given string is a substring of the chargenumber |
|
337 |
# - charge_ids - must be an arrayref. will return contents with these ids only |
|
338 |
# - expires_in - will only return matches that expire within the given number of days |
|
339 |
# will also add a column named 'has_expired' containing if the match has already expired or not |
|
340 |
# - hazardous - will return matches with the flag hazardous only |
|
341 |
# - oil - will return matches with the flag oil only |
|
342 |
# - qty, qty_op - quantity filter (more info to come) |
|
343 |
# - sort, order_by - sorting (more to come) |
|
344 |
# - reservation - will provide an extra column containing the amount reserved of this match |
|
345 |
# note: reservation flag turns off warehouse_* or bin_* information. both together don't make sense, since reserved info is stored separately |
|
346 |
# |
|
347 |
sub get_warehouse_report { |
|
348 |
$main::lxdebug->enter_sub(); |
|
349 |
|
|
350 |
my $self = shift; |
|
351 |
my %filter = @_; |
|
352 |
|
|
353 |
my $myconfig = \%main::myconfig; |
|
354 |
my $form = $main::form; |
|
355 |
|
|
356 |
my $all_units = AM->retrieve_units($myconfig, $form); |
|
357 |
|
|
358 |
# connect to database |
|
359 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
360 |
|
|
361 |
# filters |
|
362 |
my (@filter_ary, @filter_vars, @wh_bin_filter_ary, @wh_bin_filter_vars, $columns, $group_by); |
|
363 |
|
|
364 |
delete $form->{include_empty_bins} unless ($form->{l_warehousedescription} || $form->{l_bindescription}); |
|
365 |
|
|
366 |
if ($filter{warehouse_id}) { |
|
367 |
push @wh_bin_filter_ary, "w.id = ?"; |
|
368 |
push @wh_bin_filter_vars, $filter{warehouse_id}; |
|
369 |
} |
|
370 |
|
|
371 |
if ($filter{bin_id}) { |
|
372 |
push @wh_bin_filter_ary, "b.id = ?"; |
|
373 |
push @wh_bin_filter_vars, $filter{bin_id}; |
|
374 |
} |
|
375 |
|
|
376 |
push @filter_ary, @wh_bin_filter_ary; |
|
377 |
push @filter_vars, @wh_bin_filter_vars; |
|
378 |
|
|
379 |
if ($filter{partnumber}) { |
|
380 |
push @filter_ary, "p.partnumber ILIKE ?"; |
|
381 |
push @filter_vars, '%' . $filter{partnumber} . '%'; |
|
382 |
} |
|
383 |
|
|
384 |
if ($filter{description}) { |
|
385 |
push @filter_ary, "p.description ILIKE ?"; |
|
386 |
push @filter_vars, '%' . $filter{description} . '%'; |
|
387 |
} |
|
388 |
|
|
389 |
if ($filter{partsid}) { |
|
390 |
push @filter_ary, "p.id = ?"; |
|
391 |
push @filter_vars, $filter{partsid}; |
|
392 |
} |
|
393 |
|
|
394 |
if ($filter{chargenumber}) { |
|
395 |
push @filter_ary, "i.chargenumber ILIKE ?"; |
|
396 |
push @filter_vars, '%' . $filter{chargenumber} . '%'; |
|
397 |
} |
|
398 |
|
|
399 |
# prepare qty comparison for later filtering |
|
400 |
my ($f_qty_op, $f_qty, $f_qty_base_unit); |
|
401 |
|
|
402 |
if ($filter{qty_op} && defined $filter{qty} && $filter{qty_unit} && $all_units->{$filter{qty_unit}}) { |
|
403 |
$f_qty_op = $filter{qty_op}; |
|
404 |
$f_qty = $filter{qty} * $all_units->{$filter{qty_unit}}->{factor}; |
|
405 |
$f_qty_base_unit = $all_units->{$filter{qty_unit}}->{base_unit}; |
|
406 |
} |
|
407 |
|
|
408 |
map { $_ = "(${_})"; } @filter_ary; |
|
409 |
|
|
410 |
# if of a property number or description is requested, |
|
411 |
# automatically check the matching id too. |
|
412 |
map { $form->{"l_${_}id"} = "Y" if ($form->{"l_${_}description"} || $form->{"l_${_}number"}); } qw(warehouse bin); |
|
413 |
|
|
414 |
# make order, search in $filter and $form |
|
415 |
$form->{sort} = $filter{sort} unless $form->{sort}; |
|
416 |
$form->{sort} = "parts_id" unless $form->{sort}; |
|
417 |
$form->{order} = $filter{order} unless $form->{order}; |
|
418 |
$form->{sort} =~ s/ASC|DESC//; # kill stuff left in from previous queries |
|
419 |
my $orderby = $form->{sort}; |
|
420 |
$form->{sort} .= (($form->{order}) ? " DESC" : " ASC"); |
|
421 |
|
|
422 |
my $where_clause = join " AND ", ("1=1", @filter_ary); |
|
423 |
|
|
424 |
my %select_tokens = ( |
|
425 |
"parts_id" => "i.parts_id", |
|
426 |
"qty" => "SUM(i.qty)", |
|
427 |
"warehouseid" => "i.warehouse_id", |
|
428 |
"partnumber" => "p.partnumber", |
|
429 |
"partdescription" => "p.description", |
|
430 |
"bindescription" => "b.description", |
|
431 |
"binid" => "b.id", |
|
432 |
"chargenumber" => "i.chargenumber", |
|
433 |
"chargeid" => "c.id", |
|
434 |
"warehousedescription" => "w.description", |
|
435 |
"partunit" => "p.unit", |
|
436 |
); |
|
437 |
my $select_clause = join ', ', map { +/l_/; "$select_tokens{$'} AS $'" } |
|
438 |
( grep( { !/qty/ and /l_/ and $form->{$_} eq 'Y' } keys %$form), |
|
439 |
qw(l_parts_id l_qty l_partunit) ); |
|
440 |
|
|
441 |
my $group_clause = join ", ", map { +/^l_/; "$'" } |
|
442 |
( grep( { !/qty/ and /l_/ and $form->{$_} eq 'Y' } keys %$form), |
|
443 |
qw(l_parts_id l_partunit) ); |
|
444 |
|
|
445 |
my $query = |
|
446 |
qq|SELECT $select_clause |
|
447 |
$columns |
|
448 |
FROM inventory i |
|
449 |
LEFT JOIN parts p ON i.parts_id = p.id |
|
450 |
LEFT JOIN bin b ON i.bin_id = b.id |
|
451 |
LEFT JOIN warehouse w ON i.warehouse_id = w.id |
|
452 |
WHERE $where_clause |
|
453 |
GROUP BY $group_clause $group_by |
|
454 |
ORDER BY $form->{sort}|; |
|
455 |
|
|
456 |
my $sth = prepare_execute_query($form, $dbh, $query, @filter_vars); |
|
457 |
|
|
458 |
my (%non_empty_bins, @all_fields, @contents); |
|
459 |
|
|
460 |
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { |
|
461 |
$ref->{qty} *= 1; |
|
462 |
my $qty = $ref->{qty}; |
|
463 |
|
|
464 |
next unless ($qty > 0); |
|
465 |
|
|
466 |
if ($f_qty_op) { |
|
467 |
my $part_unit = $all_units->{$ref->{partunit}}; |
|
468 |
next if (!$part_unit || ($part_unit->{base_unit} ne $f_qty_base_unit)); |
|
469 |
$qty *= $part_unit->{factor}; |
|
470 |
next if (('=' eq $f_qty_op) && ($qty != $f_qty)); |
|
471 |
next if (('>=' eq $f_qty_op) && ($qty < $f_qty)); |
|
472 |
next if (('<=' eq $f_qty_op) && ($qty > $f_qty)); |
|
473 |
} |
|
474 |
|
|
475 |
if ($form->{include_empty_bins}) { |
|
476 |
$non_empty_bins{$ref->{binid}} = 1; |
|
477 |
@all_fields = keys %{ $ref } unless (@all_fields); |
|
478 |
} |
|
479 |
|
|
480 |
push @contents, $ref; |
|
481 |
} |
|
482 |
|
|
483 |
$sth->finish(); |
|
484 |
|
|
485 |
if ($form->{include_empty_bins}) { |
|
486 |
$query = |
|
487 |
qq|SELECT |
|
488 |
w.id AS warehouseid, w.description AS warehousedescription, |
|
489 |
b.id AS binid, b.description AS bindescription |
|
490 |
FROM bin b |
|
491 |
LEFT JOIN warehouse w ON (b.warehouse_id = w.id)|; |
|
492 |
|
|
493 |
@filter_ary = @wh_bin_filter_ary; |
|
494 |
@filter_vars = @wh_bin_filter_vars; |
|
495 |
|
|
496 |
my @non_empty_bin_ids = keys %non_empty_bins; |
|
497 |
if (@non_empty_bin_ids) { |
|
498 |
push @filter_ary, qq|NOT b.id IN (| . join(', ', map { '?' } @non_empty_bin_ids) . qq|)|; |
|
499 |
push @filter_vars, @non_empty_bin_ids; |
|
500 |
} |
|
501 |
|
|
502 |
$query .= qq| WHERE | . join(' AND ', map { "($_)" } @filter_ary) if (@filter_ary); |
|
503 |
|
|
504 |
$sth = prepare_execute_query($form, $dbh, $query, @filter_vars); |
|
505 |
|
|
506 |
while ($ref = $sth->fetchrow_hashref()) { |
|
507 |
map { $ref->{$_} ||= "" } @all_fields; |
|
508 |
push @contents, $ref; |
|
509 |
} |
|
510 |
$sth->finish(); |
|
511 |
|
|
512 |
if (grep { $orderby eq $_ } qw(bindescription warehousedescription)) { |
|
513 |
@contents = sort { ($a->{$orderby} cmp $b->{$orderby}) * (($form->{order}) ? 1 : -1) } @contents; |
|
514 |
} |
|
515 |
} |
|
516 |
|
|
517 |
$main::lxdebug->leave_sub(); |
|
518 |
|
|
519 |
return @contents; |
|
520 |
} |
|
521 |
|
|
522 |
sub convert_qty_op { |
|
523 |
$main::lxdebug->enter_sub(); |
|
524 |
|
|
525 |
my ($self, $qty_op) = @_; |
|
526 |
|
|
527 |
if (!$qty_op || ($qty_op eq "dontcare")) { |
|
528 |
$main::lxdebug->leave_sub(); |
|
529 |
return undef; |
|
530 |
} |
|
531 |
|
|
532 |
if ($qty_op eq "atleast") { |
|
533 |
$qty_op = '>='; |
|
534 |
} elsif ($qty_op eq "atmost") { |
|
535 |
$qty_op = '<='; |
|
536 |
} else { |
|
537 |
$qty_op = '='; |
|
538 |
} |
|
539 |
|
|
540 |
$main::lxdebug->leave_sub(); |
|
541 |
|
|
542 |
return $qty_op; |
|
543 |
} |
|
544 |
|
|
545 |
sub retrieve_transfer_types { |
|
546 |
$main::lxdebug->enter_sub(); |
|
547 |
|
|
548 |
my $self = shift; |
|
549 |
my $direction = shift; |
|
550 |
|
|
551 |
my $myconfig = \%main::myconfig; |
|
552 |
my $form = $main::form; |
|
553 |
|
|
554 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
555 |
|
|
556 |
my $types = selectall_hashref_query($form, $dbh, qq|SELECT * FROM transfer_type WHERE direction = ? ORDER BY sortkey|, $direction); |
|
557 |
|
|
558 |
$main::lxdebug->leave_sub(); |
|
559 |
|
|
560 |
return $types; |
|
561 |
} |
|
562 |
|
|
563 |
sub get_basic_bin_info { |
|
564 |
$main::lxdebug->enter_sub(); |
|
565 |
|
|
566 |
my $self = shift; |
|
567 |
my %params = @_; |
|
568 |
|
|
569 |
Common::check_params(\%params, qw(id)); |
|
570 |
|
|
571 |
my $myconfig = \%main::myconfig; |
|
572 |
my $form = $main::form; |
|
573 |
|
|
574 |
my $dbh = $params{dbh} || $form->get_standard_dbh(); |
|
575 |
|
|
576 |
my @ids = 'ARRAY' eq ref $params{id} ? @{ $params{id} } : ($params{id}); |
|
577 |
|
|
578 |
my $query = |
|
579 |
qq|SELECT b.id AS bin_id, b.description AS bin_description, |
|
580 |
w.id AS warehouse_id, w.description AS warehouse_description |
|
581 |
FROM bin b |
|
582 |
LEFT JOIN warehouse w ON (b.warehouse_id = w.id) |
|
583 |
WHERE b.id IN (| . join(', ', ('?') x scalar(@ids)) . qq|)|; |
|
584 |
|
|
585 |
my $result = selectall_hashref_query($form, $dbh, $query, map { conv_i($_) } @ids); |
|
586 |
|
|
587 |
if ('' eq ref $params{id}) { |
|
588 |
$result = $result->[0] || { }; |
|
589 |
$main::lxdebug->leave_sub(); |
|
590 |
|
|
591 |
return $result; |
|
592 |
} |
|
593 |
|
|
594 |
$main::lxdebug->leave_sub(); |
|
595 |
|
|
596 |
return map { $_->{bin_id} => $_ } @{ $result }; |
|
597 |
} |
|
598 |
|
|
599 |
|
|
600 |
1; |
bin/mozilla/am.pl | ||
---|---|---|
3136 | 3136 |
$lxdebug->leave_sub(); |
3137 | 3137 |
} |
3138 | 3138 |
|
3139 |
sub add_warehouse { |
|
3140 |
$lxdebug->enter_sub(); |
|
3141 |
|
|
3142 |
$auth->assert('config'); |
|
3143 |
|
|
3144 |
$form->{title} = $locale->text('Add Warehouse'); |
|
3145 |
$form->{callback} ||= build_std_url('action=add_warehouse'); |
|
3146 |
$form->{fokus} = 'description'; |
|
3147 |
|
|
3148 |
$form->header(); |
|
3149 |
print $form->parse_html_template('am/edit_warehouse'); |
|
3150 |
|
|
3151 |
$lxdebug->leave_sub(); |
|
3152 |
} |
|
3153 |
|
|
3154 |
sub edit_warehouse { |
|
3155 |
$lxdebug->enter_sub(); |
|
3156 |
|
|
3157 |
$auth->assert('config'); |
|
3158 |
|
|
3159 |
AM->get_warehouse(\%myconfig, $form); |
|
3160 |
|
|
3161 |
$form->get_lists('employees' => 'EMPLOYEES'); |
|
3162 |
|
|
3163 |
$form->{title} = $locale->text('Edit Warehouse'); |
|
3164 |
$form->{callback} ||= build_std_url('action=list_warehouses'); |
|
3165 |
$form->{fokus} = 'description'; |
|
3166 |
|
|
3167 |
$form->header(); |
|
3168 |
print $form->parse_html_template('am/edit_warehouse'); |
|
3169 |
|
|
3170 |
$lxdebug->leave_sub(); |
|
3171 |
} |
|
3172 |
|
|
3173 |
sub list_warehouses { |
|
3174 |
$lxdebug->enter_sub(); |
|
3175 |
|
|
3176 |
$auth->assert('config'); |
|
3177 |
|
|
3178 |
AM->get_all_warehouses(\%myconfig, $form); |
|
3179 |
|
|
3180 |
my $previous; |
|
3181 |
foreach my $current (@{ $form->{WAREHOUSES} }) { |
|
3182 |
if ($previous) { |
|
3183 |
$previous->{next_id} = $current->{id}; |
|
3184 |
$current->{previous_id} = $previous->{id}; |
|
3185 |
} |
|
3186 |
|
|
3187 |
$previous = $current; |
|
3188 |
} |
|
3189 |
|
|
3190 |
$form->{callback} = build_std_url('action=list_warehouses'); |
|
3191 |
$form->{title} = $locale->text('Warehouses'); |
|
3192 |
$form->{url_base} = build_std_url('callback'); |
|
3193 |
|
|
3194 |
$form->header(); |
|
3195 |
print $form->parse_html_template('am/list_warehouses'); |
|
3196 |
|
|
3197 |
$lxdebug->leave_sub(); |
|
3198 |
} |
|
3199 |
|
|
3200 |
sub save_warehouse { |
|
3201 |
$lxdebug->enter_sub(); |
|
3202 |
|
|
3203 |
$auth->assert('config'); |
|
3204 |
|
|
3205 |
$form->isblank("description", $locale->text('Description missing!')); |
|
3206 |
|
|
3207 |
$form->{number_of_new_bins} = $form->parse_amount(\%myconfig, $form->{number_of_new_bins}); |
|
3208 |
|
|
3209 |
AM->save_warehouse(\%myconfig, $form); |
|
3210 |
|
|
3211 |
$form->{callback} .= '&saved_message=' . E($locale->text('Warehouse saved.')) if ($form->{callback}); |
|
3212 |
|
|
3213 |
$form->redirect($locale->text('Warehouse saved.')); |
|
3214 |
|
|
3215 |
$lxdebug->leave_sub(); |
|
3216 |
} |
|
3217 |
|
|
3218 |
sub swap_warehouses { |
|
3219 |
$lxdebug->enter_sub(); |
|
3220 |
|
|
3221 |
$auth->assert('config'); |
|
3222 |
|
|
3223 |
AM->swap_sortkeys(\%myconfig, $form, 'warehouse'); |
|
3224 |
list_warehouses(); |
|
3225 |
|
|
3226 |
$lxdebug->leave_sub(); |
|
3227 |
} |
|
3228 |
|
|
3229 |
sub delete_warehouse { |
|
3230 |
$lxdebug->enter_sub(); |
|
3231 |
|
|
3232 |
$auth->assert('config'); |
|
3233 |
|
|
3234 |
if (!$form->{confirmed}) { |
|
3235 |
$form->{title} = $locale->text('Confirmation'); |
|
3236 |
|
|
3237 |
$form->header(); |
|
3238 |
print $form->parse_html_template('am/confirm_delete_warehouse'); |
|
3239 |
exit 0; |
|
3240 |
} |
|
3241 |
|
|
3242 |
if (AM->delete_warehouse(\%myconfig, $form)) { |
|
3243 |
$form->{callback} .= '&saved_message=' . E($locale->text('Warehouse deleted.')) if ($form->{callback}); |
|
3244 |
$form->redirect($locale->text('Warehouse deleted.')); |
|
3245 |
|
|
3246 |
} else { |
|
3247 |
$form->error($locale->text('The warehouse could not be deleted because it has already been used.')); |
|
3248 |
} |
|
3249 |
|
|
3250 |
$lxdebug->leave_sub(); |
|
3251 |
} |
|
3252 |
|
|
3253 |
sub save_bin { |
|
3254 |
$lxdebug->enter_sub(); |
|
3255 |
|
|
3256 |
$auth->assert('config'); |
|
3257 |
|
|
3258 |
AM->save_bins(\%myconfig, $form); |
|
3259 |
|
|
3260 |
$form->{callback} .= '&saved_message=' . E($locale->text('Bins saved.')) if ($form->{callback}); |
|
3261 |
|
|
3262 |
$form->redirect($locale->text('Bins saved.')); |
|
3263 |
|
|
3264 |
$lxdebug->leave_sub(); |
|
3265 |
} |
|
3266 |
|
bin/mozilla/common.pl | ||
---|---|---|
47 | 47 |
|
48 | 48 |
# ------------------------------------------------------------------------- |
49 | 49 |
|
50 |
sub select_part { |
|
51 |
$lxdebug->enter_sub(); |
|
52 |
|
|
53 |
my ($callback_sub, @parts) = @_; |
|
54 |
|
|
55 |
my $remap_parts_id = 0; |
|
56 |
if (defined($parts[0]->{parts_id}) && !defined($parts[0]->{id})) { |
|
57 |
$remap_parts_id = 1; |
|
58 |
map { $_->{id} = $_->{parts_id}; } @parts; |
|
59 |
} |
|
60 |
|
|
61 |
my $remap_partnumber = 0; |
|
62 |
if (defined($parts[0]->{partnumber}) && !defined($parts[0]->{number})) { |
|
63 |
$remap_partnumber = 1; |
|
64 |
map { $_->{number} = $_->{partnumber}; } @parts; |
|
65 |
} |
|
66 |
|
|
67 |
my $has_charge = 0; |
|
68 |
if (defined($parts[0]->{chargenumber})) { |
|
69 |
$has_charge = 1; |
|
70 |
map { $_->{has_charge} = 1; } @parts; |
|
71 |
} |
|
72 |
|
|
73 |
my $old_form = save_form(); |
|
74 |
|
|
75 |
$form->header(); |
|
76 |
print $form->parse_html_template("generic/select_part", |
|
77 |
{ "PARTS" => \@parts, |
|
78 |
"old_form" => $old_form, |
|
79 |
"title" => $locale->text("Select a part"), |
|
80 |
"nextsub" => "select_part_internal", |
|
81 |
"callback_sub" => $callback_sub, |
|
82 |
"has_charge" => $has_charge, |
|
83 |
"remap_parts_id" => $remap_parts_id, |
|
84 |
"remap_partnumber" => $remap_partnumber }); |
|
85 |
|
|
86 |
$lxdebug->leave_sub(); |
|
87 |
} |
|
88 |
|
|
89 |
sub select_part_internal { |
|
90 |
$lxdebug->enter_sub(); |
|
91 |
|
|
92 |
my ($new_item, $callback_sub); |
|
93 |
|
|
94 |
my $re = "^new_.*_" . $form->{selection}; |
|
95 |
|
|
96 |
foreach (grep /$re/, keys %{ $form }) { |
|
97 |
my $new_key = $_; |
|
98 |
$new_key =~ s/^new_//; |
|
99 |
$new_key =~ s/_\d+$//; |
|
100 |
$new_item->{$new_key} = $form->{$_}; |
|
101 |
} |
|
102 |
|
|
103 |
if ($form->{remap_parts_id}) { |
|
104 |
$new_item->{parts_id} = $new_item->{id}; |
|
105 |
delete $new_item->{id}; |
|
106 |
} |
|
107 |
|
|
108 |
if ($form->{remap_partnumber}) { |
|
109 |
$new_item->{partnumber} = $new_item->{number}; |
|
110 |
delete $new_item->{number}; |
|
111 |
} |
|
112 |
|
|
113 |
my $callback_sub = $form->{callback_sub}; |
|
114 |
|
|
115 |
restore_form($form->{old_form}); |
|
116 |
|
|
117 |
call_sub($callback_sub, $new_item); |
|
118 |
|
|
119 |
$lxdebug->leave_sub(); |
|
120 |
} |
|
121 |
|
|
122 |
sub part_selection_internal { |
|
123 |
$lxdebug->enter_sub(); |
|
124 |
|
|
125 |
$order_by = "description"; |
|
126 |
$order_by = $form->{"order_by"} if (defined($form->{"order_by"})); |
|
127 |
$order_dir = 1; |
|
128 |
$order_dir = $form->{"order_dir"} if (defined($form->{"order_dir"})); |
|
129 |
|
|
130 |
%options = map { $_ => 1 } split m/:/, $form->{options}; |
|
131 |
|
|
132 |
map { $form->{$_} = 1 if ($options{$_}) } qw(no_services no_assemblies stockable); |
|
133 |
|
|
134 |
$parts = Common->retrieve_parts(\%myconfig, $form, $order_by, $order_dir); |
|
135 |
|
|
136 |
if (0 == scalar(@{$parts})) { |
|
137 |
$form->show_generic_information($locale->text("No part was found matching the search parameters.")); |
|
138 |
} elsif (1 == scalar(@{$parts})) { |
|
139 |
$onload = "part_selected('1')"; |
|
140 |
} |
|
141 |
|
|
142 |
map { $parts->[$_]->{selected} = $_ ? 0 : 1; } (0..$#{$parts}); |
|
143 |
|
|
144 |
my $callback = build_std_url('action=part_selection_internal', qw(partnumber description input_partnumber input_description input_partsid), |
|
145 |
grep({ /^[fl]_/ } keys %{ $form })); |
|
146 |
|
|
147 |
my @header_sort = qw(partnumber description); |
|
148 |
my %header_title = ( "partnumber" => $locale->text("Part Number"), |
|
149 |
"description" => $locale->text("Part description"), |
|
150 |
); |
|
151 |
|
|
152 |
my @header = |
|
153 |
map(+{ "column_title" => $header_title{$_}, |
|
154 |
"column" => $_, |
|
155 |
"callback" => $callback . "order_by=${_}&order_dir=" . ($order_by eq $_ ? 1 - $order_dir : $order_dir), |
|
156 |
}, |
|
157 |
@header_sort); |
|
158 |
|
|
159 |
$form->{title} = $locale->text("Select a part"); |
|
160 |
$form->header(); |
|
161 |
print $form->parse_html_template("generic/part_selection", { "HEADER" => \@header, |
|
162 |
"PARTS" => $parts, |
|
163 |
"onload" => $onload }); |
|
164 |
|
|
165 |
$lxdebug->leave_sub(); |
|
166 |
} |
|
167 |
|
|
168 |
# ------------------------------------------------------------------------- |
|
169 |
|
|
50 | 170 |
sub delivery_customer_selection { |
51 | 171 |
$lxdebug->enter_sub(); |
52 | 172 |
|
bin/mozilla/wh.pl | ||
---|---|---|
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 |
# SQL-Ledger, Accounting |
|
8 |
# Copyright (c) 1998-2002 |
|
9 |
# |
|
10 |
# Author: Dieter Simader |
|
11 |
# Email: dsimader@sql-ledger.org |
|
12 |
# Web: http://www.sql-ledger.org |
|
13 |
# |
|
14 |
# |
|
15 |
# This program is free software; you can redistribute it and/or modify |
|
16 |
# it under the terms of the GNU General Public License as published by |
|
17 |
# the Free Software Foundation; either version 2 of the License, or |
|
18 |
# (at your option) any later version. |
|
19 |
# |
|
20 |
# This program is distributed in the hope that it will be useful, |
|
21 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
22 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
23 |
# GNU General Public License for more details. |
|
24 |
# You should have received a copy of the GNU General Public License |
|
25 |
# along with this program; if not, write to the Free Software |
|
26 |
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
27 |
# |
|
28 |
####################################################################### |
|
29 |
# |
|
30 |
# warehouse and packinglist |
|
31 |
# |
|
32 |
####################################################################### |
|
33 |
|
|
34 |
use List::Util qw(min max first); |
|
35 |
use POSIX qw(strftime); |
|
36 |
|
|
37 |
use SL::Form; |
|
38 |
use SL::User; |
|
39 |
|
|
40 |
use SL::AM; |
|
41 |
use SL::CT; |
|
42 |
use SL::IC; |
|
43 |
use SL::WH; |
|
44 |
use SL::OE; |
|
45 |
use SL::ReportGenerator; |
|
46 |
|
|
47 |
use Data::Dumper; |
|
48 |
|
|
49 |
require "bin/mozilla/common.pl"; |
|
50 |
require "bin/mozilla/reportgenerator.pl"; |
|
51 |
|
|
52 |
# parserhappy(R): |
|
53 |
|
|
54 |
# contents of the "transfer_type" table: |
|
55 |
# $locale->text('back') |
|
56 |
# $locale->text('correction') |
|
57 |
# $locale->text('disposed') |
|
58 |
# $locale->text('found') |
|
59 |
# $locale->text('missing') |
|
60 |
# $locale->text('stock') |
|
61 |
# $locale->text('transfer') |
|
62 |
# $locale->text('used') |
|
63 |
# $locale->text('return_material') |
|
64 |
# $locale->text('release_material') |
|
65 |
|
|
66 |
# -------------------------------------------------------------------- |
|
67 |
# Transfer |
|
68 |
# -------------------------------------------------------------------- |
|
69 |
|
|
70 |
sub transfer_warehouse_selection { |
|
71 |
$lxdebug->enter_sub(); |
|
72 |
|
|
73 |
$auth->assert('warehouse_management'); |
|
74 |
|
Auch abrufbar als: Unified diff
Lagerverwaltung implementiert.