Inventory Helper: Bessere Fehlermeldung bei fehlenden Parametern
[kivitendo-erp.git] / SL / Helper / Inventory.pm
index 9a5910d..cd50907 100644 (file)
@@ -24,7 +24,10 @@ sub _get_stock_onhand {
 
   my $onhand_mode = !!$params{onhand};
 
-  my @selects = ('SUM(qty) as qty');
+  my @selects = (
+    'SUM(qty) AS qty',
+    'MIN(EXTRACT(epoch FROM inventory.itime)) AS itime',
+  );
   my @values;
   my @where;
   my @groups;
@@ -54,11 +57,13 @@ sub _get_stock_onhand {
   }
 
   if ($params{date}) {
+    Carp::croak("not DateTime ".$params{date}) unless ref($params{date}) eq 'DateTime';
     push @where, sprintf "shippingdate <= ?";
     push @values, $params{date};
   }
 
   if ($params{bestbefore}) {
+    Carp::croak("not DateTime ".$params{date}) unless ref($params{bestbefore}) eq 'DateTime';
     push @where, sprintf "bestbefore >= ?";
     push @values, $params{bestbefore};
   }
@@ -74,7 +79,7 @@ sub _get_stock_onhand {
   }
 
   if ($params{reserve_for}) {
-    my @objects = listify($params{chargenumber});
+    my @objects = listify($params{reserve_for});
     my @tokens;
     push @tokens, ( "(reserve_for_id = ? AND reserve_for_table = ?)") x @objects;
     push @values, map { ($_->id, $_->meta->table) } @objects;
@@ -162,8 +167,17 @@ sub get_onhand {
 sub allocate {
   my (%params) = @_;
 
-  my $part = $params{part} or Carp::croak('allocate needs a part');
-  my $qty  = $params{qty}  or Carp::croak('allocate needs a qty');
+  die SL::X::Inventory::Allocation->new(
+    error => 'allocate needs a part',
+    msg => t8("Method allocate needs the parameter 'part'"),
+  ) unless $params{part};
+  die SL::X::Inventory::Allocation->new(
+    error => 'allocate needs a qty',
+    msg => t8("Method allocate needs the parameter 'qty'"),
+  ) unless $params{qty};
+
+  my $part = $params{part};
+  my $qty  = $params{qty};
 
   return () if $qty <= 0;
 
@@ -192,6 +206,7 @@ sub allocate {
     || exists $chargenumbers{$b->{chargenumber}}  <=> exists $chargenumbers{$a->{chargenumber}} # then prefer wanted chargenumbers
     || exists $bin_whitelist{$b->{bin_id}}        <=> exists $bin_whitelist{$a->{bin_id}}       # then prefer wanted bins
     || exists $wh_whitelist{$b->{warehouse_id}}   <=> exists $wh_whitelist{$a->{warehouse_id}}  # then prefer wanted bins
+    || $a->{itime}                                <=> $b->{itime}                               # and finally prefer earlier charges
   } @filtered_results;
   my @allocations;
   my $rest_qty = $qty;
@@ -275,19 +290,22 @@ sub check_constraints {
       bin_id       => 'bin_id',
       warehouse_id => 'warehouse_id',
       chargenumber => 'chargenumber',
+      reserve_for  => 'reserve_for_id',
     );
 
     for (keys %$constraints ) {
       croak "unsupported constraint '$_'" unless $supported_constraints{$_};
+      next unless defined $constraints->{$_};
 
       my %whitelist = map { (ref $_ ? $_->id : $_) => 1 } listify($constraints->{$_});
       my $accessor = $supported_constraints{$_};
 
       if (any { !$whitelist{$_->$accessor} } @$allocations) {
         my %error_constraints = (
-          bin_id       => t8('Bins'),
-          warehouse_id => t8('Warehouses'),
-          chargenumber => t8('Chargenumbers'),
+          bin_id         => t8('Bins'),
+          warehouse_id   => t8('Warehouses'),
+          chargenumber   => t8('Chargenumbers'),
+          reserve_for    => t8('Reserve For'),
         );
         my @allocs = grep { $whitelist{$_->$accessor} } @$allocations;
         my $needed = sum map { $_->qty } grep { !$whitelist{$_->$accessor} } @$allocations;