ShippedQty: Optionale OrderItems nicht für Status Order->delivered auswerten
authorJan Büren <jan@kivitendo.de>
Thu, 27 May 2021 09:27:16 +0000 (11:27 +0200)
committerJan Büren <jan@kivitendo.de>
Thu, 27 May 2021 09:27:16 +0000 (11:27 +0200)
S.a.: Testfall und Changelog

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

index e109fa7..0157c22 100644 (file)
@@ -26,6 +26,7 @@ my $no_stock_item_links_query = <<'';
   ORDER BY oi.trans_id, oi.position
 
 # oi not item linked. takes about 250ms for 100k hits
+# obsolete since 3.5.6
 my $fill_up_oi_query = <<'';
   SELECT oi.id, oi.trans_id, oi.position, oi.parts_id, oi.description, oi.reqdate, oi.serialnumber, oi.qty, oi.unit
   FROM orderitems oi
@@ -33,6 +34,7 @@ my $fill_up_oi_query = <<'';
   ORDER BY oi.trans_id, oi.position
 
 # doi linked by record, but not by items; 250ms for 100k hits
+# obsolete since 3.5.6
 my $no_stock_fill_up_doi_query = <<'';
   SELECT doi.id, doi.delivery_order_id, doi.position, doi.parts_id, doi.description, doi.reqdate, doi.serialnumber, doi.qty, doi.unit
   FROM delivery_order_items doi
@@ -219,7 +221,7 @@ sub write_to {
     } elsif ('SL::DB::Order' eq ref $obj) {
       if (defined $obj->{orderitems}) {
         $self->write_to($obj->{orderitems});
-        $obj->{delivered} = all { $_->{delivered} } @{ $obj->{orderitems} };
+        $obj->{delivered} = all { $_->{delivered} } grep { !$_->{optional} || $_->{optional} == 0 } @{ $obj->{orderitems} };
       } else {
         # don't force a load on items. just compute by oe_id directly
         $obj->{delivered} = $self->delivered->{$obj->id};
index 4d530eb..415e03c 100644 (file)
@@ -54,9 +54,12 @@ Kleinere neue Features und Detailverbesserungen:
    Innerhalb der Druckvorlagen steht das Attribut mit <%optional%> als Variable zu Verfügung.
    Beim Status setzen eines Auftrags (offen oder geschlossen) werden optionale Position
    ignoriert. D.h. ein Auftrag gilt als geschlossen, wenn alle nicht optionalen
-   Positionen fakturiert worden sind. Das Attribut optional steht auch nur in
-   den Angeboten/Aufträgen zu Verfügung. Sobald über den Workflow ein neuer Beleg
-   erstellt wird, wird die vorher optionale Position zu einer normalen Position
+   Positionen fakturiert worden sind.
+   Das Gleiche gilt für Lieferscheine. Sollten alles bis auf optionale Artikel
+   geliefert worden sein, gilt der Auftrag als komplett geliefert.
+   Das Attribut optional steht auch nur in den Angeboten/Aufträgen zu Verfügung.
+   Sobald über den Workflow ein neuer Beleg erstellt wird,
+   wird die vorher optionale Position zu einer normalen Position
    und wird dann auch entsprechend bei dem Rechnungsbeleg mit fakturiert und im
    Druckvorlagen-System entfällt das Attribut <%optional%>.
    Entsprechend exemplarisch im aktuellen Druckvorlagensatz RB ergänzt.
index dc2f9dd..c300bb5 100644 (file)
@@ -204,6 +204,55 @@ note('misc tests');
 my $number_of_linked_items = SL::DB::Manager::RecordLink->get_all_count( where => [ from_table => 'orderitems', to_table => 'delivery_order_items' ] );
 is ($number_of_linked_items , 6, "6 record_links for items, 3 from sales order, 3 from purchase order");
 
+note('testing optional orderitems');
+
+my $item_optional = create_order_item(part => $part3, qty => 7, optional => 1);
+ok($item_optional->{optional},       "optional order item");
+
+my $sales_order_opt = create_sales_order(
+  save       => 1,
+  orderitems => [ create_order_item(part => $part1, qty => 5),
+                  create_order_item(part => $part2, qty => 6),
+                  $item_optional,
+                ]
+);
+
+
+SL::Helper::ShippedQty
+  ->new(require_stock_out => 1)  # should make no difference while there is no delivery order
+  ->calculate($sales_order_opt)
+  ->write_to_objects;
+
+is($sales_order_opt->items_sorted->[2]->{shipped_qty}, 0,  "third optional sales orderitem has no shipped_qty");
+ok(!$sales_order_opt->items_sorted->[2]->{delivered},      "third optional sales orderitem is not delivered");
+ok($sales_order_opt->items_sorted->[2]->{optional},        "third optional sales orderitem is optional");
+
+my $orderitem_part3_opt = SL::DB::Manager::OrderItem->find_by(parts_id => $part3->id, trans_id => $sales_order_opt->id);
+is($orderitem_part3_opt->shipped_qty, 0, "OrderItem shipped_qty method ok");
+
+# create sales delivery order from sales order
+my $sales_delivery_order_opt = $sales_order_opt->convert_to_delivery_order;
+is(scalar @{ $sales_delivery_order_opt->items_sorted }, 3,   "third optional sales delivery orderitem is there");
+
+# and delete third item
+my $optional =  SL::DB::Manager::DeliveryOrderItem->find_by(parts_id => $part3->id, delivery_order_id => $sales_delivery_order_opt->id);
+SL::DB::DeliveryOrderItem->new(id => $optional->id)->delete;
+$sales_delivery_order_opt->save(cascade => 1);
+my $new_sales_delivery_order_opt = SL::DB::Manager::DeliveryOrder->find_by(id => $sales_delivery_order_opt->id);
+is(scalar @{ $new_sales_delivery_order_opt->items_sorted }, 2,   "third optional sales delivery orderitem is undef");
+
+SL::Helper::ShippedQty
+  ->new(require_stock_out => 0)
+  ->calculate($sales_order_opt)
+  ->write_to_objects;
+
+is($sales_order_opt->items_sorted->[0]->{shipped_qty}, 5,  "require_stock_out => 0: first sales orderitem has shipped_qty");
+ok($sales_order_opt->items_sorted->[0]->{delivered},       "require_stock_out => 0: first sales orderitem is delivered");
+ok($sales_order_opt->items_sorted->[1]->{delivered},       "require_stock_out => 0: second sales orderitem is delivered");
+ok(!$sales_order_opt->items_sorted->[2]->{delivered},      "require_stock_out => 0: third sales orderitem is NOT delivered");
+is($sales_order_opt->items_sorted->[2]->{shipped_qty}, 0,  "require_stock_out => 0: third sales orderitem has no shipped_qty");
+ok($sales_order_opt->{delivered},                          "require_stock_out => 0: order IS delivered");
+
 clear_up();
 
 {