14 |
14 |
use SL::DB::TransferType;
|
15 |
15 |
use SL::X;
|
16 |
16 |
|
17 |
|
our @EXPORT_OK = qw(get_stock get_onhand allocate allocate_for_assembly produce_assembly);
|
|
17 |
our @EXPORT_OK = qw(get_stock get_onhand allocate allocate_for_assembly produce_assembly check_constraints);
|
18 |
18 |
our %EXPORT_TAGS = (ALL => \@EXPORT_OK);
|
19 |
19 |
|
20 |
20 |
sub _get_stock_onhand {
|
... | ... | |
191 |
191 |
|| $bin_whitelist{$b->{bin_id}} <=> $bin_whitelist{$a->{bin_id}} # then prefer wanted bins
|
192 |
192 |
|| $wh_whitelist{$b->{warehouse_id}} <=> $wh_whitelist{$a->{warehouse_id}} # then prefer wanted bins
|
193 |
193 |
} @filtered_results;
|
194 |
|
|
195 |
194 |
my @allocations;
|
196 |
195 |
my $rest_qty = $qty;
|
197 |
196 |
|
... | ... | |
220 |
219 |
msg => t8("can not allocate #1 units of #2, missing #3 units", $qty, $part->displayable_name, $rest_qty),
|
221 |
220 |
);
|
222 |
221 |
} else {
|
|
222 |
if ($params{constraints}) {
|
|
223 |
check_constraints($params{constraints},\@allocations);
|
|
224 |
}
|
223 |
225 |
return @allocations;
|
224 |
226 |
}
|
225 |
227 |
}
|
... | ... | |
249 |
251 |
@allocations;
|
250 |
252 |
}
|
251 |
253 |
|
|
254 |
sub check_constraints {
|
|
255 |
my ($constraints, $allocations) = @_;
|
|
256 |
if ('CODE' eq ref $constraints) {
|
|
257 |
if (!$constraints->(@$allocations)) {
|
|
258 |
die SL::X::Inventory::Allocation->new(
|
|
259 |
error => 'allocation constraints failure',
|
|
260 |
msg => t8("Allocations didn't pass constraints"),
|
|
261 |
);
|
|
262 |
}
|
|
263 |
} else {
|
|
264 |
croak 'constraints needs to be a hashref' unless 'HASH' eq ref $constraints;
|
|
265 |
|
|
266 |
my %supported_constraints = (
|
|
267 |
bin_id => 'bin_id',
|
|
268 |
warehouse_id => 'warehouse_id',
|
|
269 |
chargenumber => 'chargenumber',
|
|
270 |
);
|
|
271 |
|
|
272 |
for (keys %$constraints ) {
|
|
273 |
croak "unsupported constraint '$_'" unless $supported_constraints{$_};
|
|
274 |
|
|
275 |
my %whitelist = map { (ref $_ ? $_->id : $_) => 1 } listify($constraints->{$_});
|
|
276 |
my $accessor = $supported_constraints{$_};
|
|
277 |
|
|
278 |
if (any { !$whitelist{$_->$accessor} } @$allocations) {
|
|
279 |
my %error_constraints = (
|
|
280 |
bin_id => t8('Bins'),
|
|
281 |
warehouse_id => t8('Warehouses'),
|
|
282 |
chargenumber => t8('Chargenumbers'),
|
|
283 |
);
|
|
284 |
die SL::X::Inventory::Allocation->new(
|
|
285 |
error => 'allocation constraints failure',
|
|
286 |
msg => t8("Allocations didn't pass constraints for #1",$error_constraints{$_}),
|
|
287 |
);
|
|
288 |
}
|
|
289 |
}
|
|
290 |
}
|
|
291 |
}
|
|
292 |
|
252 |
293 |
sub produce_assembly {
|
253 |
294 |
my (%params) = @_;
|
254 |
295 |
|
... | ... | |
715 |
756 |
be C<undef> (but must still be present at creation time). Instances are
|
716 |
757 |
considered immutable.
|
717 |
758 |
|
|
759 |
=head1 CONSTRAINTS
|
|
760 |
|
|
761 |
# whitelist constraints
|
|
762 |
->allocate(
|
|
763 |
...
|
|
764 |
constraints => {
|
|
765 |
bin_id => \@allowed_bins,
|
|
766 |
chargenumber => \@allowed_chargenumbers,
|
|
767 |
}
|
|
768 |
);
|
|
769 |
|
|
770 |
# custom constraints
|
|
771 |
->allocate(
|
|
772 |
constraints => sub {
|
|
773 |
# only allow chargenumbers with specific format
|
|
774 |
all { $_->chargenumber =~ /^ C \d{8} - \a{d2} $/x } @_
|
|
775 |
|
|
776 |
&&
|
|
777 |
# and must be all reservations
|
|
778 |
all { $_->reserve_for_id } @_;
|
|
779 |
}
|
|
780 |
)
|
|
781 |
|
|
782 |
C<allocation> is "best effort" in nature. It will take the C<bin>,
|
|
783 |
C<chargenumber> etc hints from the parameters, but will try it's bvest to
|
|
784 |
fulfil the request anyway and only bail out if it is absolutely not possible.
|
|
785 |
|
|
786 |
Sometimes you need to restrict allocations though. For this you can pass
|
|
787 |
additional constraints to C<allocate>. A constraint serves as a whitelist.
|
|
788 |
Every allocation must fulfil every constraint by having that attribute be one
|
|
789 |
of the given values.
|
|
790 |
|
|
791 |
In case even that is not enough, you may supply a custom check by passing a
|
|
792 |
function that will be given the allocation objects.
|
|
793 |
|
|
794 |
Note that both whitelists and constraints do not influence the order of
|
|
795 |
allocations, which is done purely from the initial parameters. They only serve
|
|
796 |
to reject allocations made in good faith which do fulfil required assertions.
|
|
797 |
|
718 |
798 |
=head1 ERROR HANDLING
|
719 |
799 |
|
720 |
800 |
C<allocate> and C<produce_assembly> will throw exceptions if the request can
|
Inventory-Helper: neuer Parameter "constraints" um die Verfügbarkeit von Lagerbeständen einzuschränken
Eine extra Methode prüft gefundene Einträge auf bestimmte Einschränkungen
nachdem die Sortierung stattgefunden hat
zu #9457