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
   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
 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
   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
 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});
     } 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};
       } 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
    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.
    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");
 
 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();
 
 {
 clear_up();
 
 {