Revision c56ba186
Von Sven Schöling vor etwa 4 Jahren hinzugefügt
SL/Helper/Inventory.pm | ||
---|---|---|
62 | 62 |
push @values, $params{date}; |
63 | 63 |
} |
64 | 64 |
|
65 |
if (!$params{bestbefore} && $onhand_mode && default_show_bestbefore()) { |
|
66 |
$params{bestbefore} = DateTime->now_local; |
|
67 |
} |
|
68 |
|
|
65 | 69 |
if ($params{bestbefore}) { |
66 | 70 |
Carp::croak("not DateTime ".$params{date}) unless ref($params{bestbefore}) eq 'DateTime'; |
67 |
push @where, sprintf "bestbefore >= ?";
|
|
71 |
push @where, sprintf "(bestbefore IS NULL OR bestbefore >= ?)";
|
|
68 | 72 |
push @values, $params{bestbefore}; |
69 | 73 |
} |
70 | 74 |
|
... | ... | |
96 | 100 |
LEFT JOIN warehouse ON bin.warehouse_id = warehouse.id |
97 | 101 |
$where |
98 | 102 |
$group_by |
99 |
HAVING SUM(qty) > 0 |
|
103 |
|
|
104 |
if ($onhand_mode) { |
|
105 |
$query .= ' HAVING SUM(qty) > 0'; |
|
106 |
} |
|
100 | 107 |
|
101 | 108 |
my $results = selectall_hashref_query($::form, SL::DB->client->dbh, $query, @values); |
102 | 109 |
|
... | ... | |
175 | 182 |
|
176 | 183 |
for my $chunk (@sorted_results) { |
177 | 184 |
my $qty = min($chunk->{qty}, $rest_qty); |
185 |
|
|
186 |
# since allocate operates on stock, this also ensures that no negative stock results are used |
|
178 | 187 |
if ($qty > 0) { |
179 | 188 |
push @allocations, SL::Helper::Inventory::Allocation->new( |
180 | 189 |
parts_id => $chunk->{parts_id}, |
... | ... | |
363 | 372 |
@transfers; |
364 | 373 |
} |
365 | 374 |
|
375 |
sub default_show_bestbefore { |
|
376 |
$::instance_conf->get_show_bestbefore |
|
377 |
} |
|
378 |
|
|
366 | 379 |
package SL::Helper::Inventory::Allocation { |
367 | 380 |
my @attributes = qw(parts_id qty bin_id warehouse_id chargenumber bestbefore comment for_object_id); |
368 | 381 |
my %attributes = map { $_ => 1 } @attributes; |
... | ... | |
471 | 484 |
|
472 | 485 |
The first problem has spawned several dozen small functions in the program that |
473 | 486 |
try to implement that, and those usually miss some details. They may ignore |
474 |
reservations, or bestbefore times.
|
|
487 |
bestbefore times, comments, ignore negative quantities etc.
|
|
475 | 488 |
|
476 | 489 |
To get this cleaned up a bit this code introduces two concepts: stock and onhand. |
477 | 490 |
|
478 |
Stock is defined as the actual contents of the inventory, everything that is |
|
479 |
there. Onhand is what is available, which means things that are stocked |
|
480 |
and not expired. |
|
491 |
=over 4 |
|
492 |
|
|
493 |
=item * Stock is defined as the actual contents of the inventory, everything that is |
|
494 |
there. |
|
495 |
|
|
496 |
=item * Onhand is what is available, which means things that are stocked, |
|
497 |
not expired and not reserved for other uses. |
|
498 |
|
|
499 |
=back |
|
481 | 500 |
|
482 | 501 |
The two new functions C<get_stock> and C<get_onhand> encapsulate these principles and |
483 | 502 |
allow simple access with some optional filters for chargenumbers or warehouses. |
... | ... | |
488 | 507 |
C<allocate> will try to find the requested quantity of a part in the inventory |
489 | 508 |
and will return allocations of it which can then be used to create the |
490 | 509 |
assembly. Allocation will happen with the C<onhand> semantics defined above, |
491 |
meaning that by default no reservations or expired goods will be used. The
|
|
492 |
caller can supply hints of what shold be used and in those cases chargenumber
|
|
493 |
and reservations will be used up as much as possible first. C<allocate> will
|
|
494 |
always try to fulfil the request even beyond those. Should the required amount
|
|
495 |
not be stocked, allocate will throw an exception.
|
|
510 |
meaning that by default no expired goods will be used. The caller can supply
|
|
511 |
hints of what shold be used and in those cases chargenumbers will be used up as
|
|
512 |
much as possible first. C<allocate> will always try to fulfil the request even
|
|
513 |
beyond those. Should the required amount not be stocked, allocate will throw an
|
|
514 |
exception. |
|
496 | 515 |
|
497 | 516 |
C<produce_assembly> has been rewritten to only accept parameters about the |
498 | 517 |
target of the production, and requires allocations to complete the request. The |
... | ... | |
510 | 529 |
|
511 | 530 |
=item * |
512 | 531 |
|
513 |
If you need actual inventory objects because of record links, prod_id links or
|
|
514 |
something like that load them directly. And strongly consider redesigning that,
|
|
515 |
because it's really fragile.
|
|
532 |
If you need actual inventory objects because of record links or something like
|
|
533 |
that load them directly. And strongly consider redesigning that, because it's
|
|
534 |
really fragile. |
|
516 | 535 |
|
517 | 536 |
=item * |
518 | 537 |
|
... | ... | |
576 | 595 |
Returns for single parts how much is available in the inventory. That excludes |
577 | 596 |
stock with expired bestbefore. |
578 | 597 |
|
579 |
It takes all options of L</get_stock> and has some additional ones:
|
|
598 |
It takes the same options as L</get_stock>.
|
|
580 | 599 |
|
581 | 600 |
=over 4 |
582 | 601 |
|
583 | 602 |
=item * bestbefore |
584 | 603 |
|
604 |
If given, will only return stock with a bestbefore at or after the given date. |
|
605 |
Optional. Must be L<DateTime> object. |
|
606 |
|
|
585 | 607 |
=back |
586 | 608 |
|
587 | 609 |
=item * allocate PARAMS |
... | ... | |
756 | 778 |
not be completed. The usual reason will be insufficient onhand to allocate, or |
757 | 779 |
insufficient allocations to process the request. |
758 | 780 |
|
781 |
=head1 KNOWN PROBLEMS |
|
782 |
|
|
783 |
* It's not currently possible to identify allocations between requests, for |
|
784 |
example for presenting the user possible allocations and then actually using |
|
785 |
them on the next request. |
|
786 |
* It's not currently possible to give C<allocate> prior constraints. |
|
787 |
Currently all constraints are treated as hints (and will be preferred) but |
|
788 |
the internal ordering of the hints is fixed and more complex preferentials |
|
789 |
are not supported. |
|
790 |
* bestbefore handling is untested |
|
791 |
|
|
759 | 792 |
=head1 TODO |
760 | 793 |
|
761 | 794 |
* define and describe error classes |
762 | 795 |
* define wrapper classes for stock/onhand batch mode return values |
763 |
* handle extra arguments in produce: shippingdate, project, oe
|
|
796 |
* handle extra arguments in produce: shippingdate, project |
|
764 | 797 |
* clean up allocation helper class |
765 |
* with objects for reservations |
|
766 | 798 |
* document no_ check |
767 | 799 |
* tests |
768 | 800 |
|
Auch abrufbar als: Unified diff
Inventory: bestbefore handling