ShippedQty: delivered korrekt setzen
authorSven Schöling <s.schoeling@linet-services.de>
Wed, 23 Jan 2019 17:07:27 +0000 (18:07 +0100)
committerJan Büren <jan@kivitendo.de>
Wed, 23 Jun 2021 10:59:26 +0000 (12:59 +0200)
Wenn der Helper ohne fill_up aufgerufen wurde, wurden nicht existierende
Positionen für die delivered Berechnung ignoriert

SL/Helper/ShippedQty.pm
t/helper/shipped_qty.t

index 3ad4619..a2f6701 100644 (file)
@@ -270,6 +270,22 @@ sub normalize_input {
   $self->shipped_qty({});
 }
 
+# some of the invocations never need to load all orderitems to copute their answers
+# delivered however needs oi_qty to be set for each orderitem to decide whether
+# delivered should be set or not.
+sub ensure_all_orderitems_for_orders {
+  my ($self) = @_;
+
+  return if $self->fill_up;
+
+  my $oi_query  = sprintf $fill_up_oi_query,   join (', ', ('?')x@{ $self->oe_ids });
+  my $oi  = selectall_hashref_query($::form, $self->dbh, $oi_query, @{ $self->oe_ids });
+  for (@$oi) {
+    $self->{oi_qty}{ $_->{id} } //= $_->{qty};
+    $self->{oi2oe}{ $_->{id} }  //= $_->{trans_id};
+  }
+}
+
 sub available_item_identity_fields {
   map { [ $_ => $item_identity_fields{$_} ] } @known_item_identity_fields;
 }
@@ -291,6 +307,9 @@ sub init_oi_qty { {} }
 sub init_matches { [] }
 sub init_delivered {
   my ($self) = @_;
+
+  $self->ensure_all_orderitems_for_orders;
+
   my $d = { };
   for (keys %{ $self->oi_qty }) {
     my $oe_id = $self->oi2oe->{$_};
index 41a91bd..f9fc4f9 100644 (file)
@@ -49,10 +49,10 @@ for my $i ( 1 .. 4 ) {
   new_part( %part_defaults, partnumber => $i, description => "part $i test" )->save;
 };
 
-my $part1 = SL::DB::Manager::Part->find_by( partnumber => '1' );
-my $part2 = SL::DB::Manager::Part->find_by( partnumber => '2' );
-my $part3 = SL::DB::Manager::Part->find_by( partnumber => '3' );
-my $part4 = SL::DB::Manager::Part->find_by( partnumber => '4' );
+my $part1 = SL::DB::Manager::Part->find_by( partnumber => '1' ) or die;
+my $part2 = SL::DB::Manager::Part->find_by( partnumber => '2' ) or die;
+my $part3 = SL::DB::Manager::Part->find_by( partnumber => '3' ) or die;
+my $part4 = SL::DB::Manager::Part->find_by( partnumber => '4' ) or die;
 
 my @part_ids; # list of all part_ids to run checks against
 push( @part_ids, $_->id ) foreach ( $part1, $part2, $part3, $part4 );
@@ -305,6 +305,36 @@ clear_up();
 
   is $order->items_sorted->[0]->{shipped_qty}, 5, 'unlinked legacy position test 1';
   is $order->items_sorted->[1]->{shipped_qty}, 3, 'unlinked legacy position test 2';
+
+}
+
+{
+# edge case:
+#
+# suppose an order was delivered, and someone removes one item from the delivery order.
+# make sure the order is then shown as not delivered.
+#
+  my $sales_order = create_sales_order(
+    save       => 1,
+    orderitems => [ create_order_item(part => new_part()->save, qty => 5),
+                    create_order_item(part => new_part()->save, qty => 6),
+                    create_order_item(part => new_part()->save, qty => 7),
+                  ]
+  );
+  $sales_order->load;
+
+  my $delivery_order = SL::DB::DeliveryOrder->new_from($sales_order);
+  $delivery_order->save;
+
+  $delivery_order->items(@{ $delivery_order->items_sorted }[0..1]);
+  $delivery_order->save;
+
+  SL::Helper::ShippedQty
+    ->new(fill_up => 0, require_stock_out => 0)
+    ->calculate($sales_order)
+    ->write_to_objects;
+
+  ok !$sales_order->delivered, 'after deleting a position from a delivery order, the order is undelivered again';
 }
 
 clear_up();