X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FHelper%2FShippedQty.pm;h=e109fa7ec0c21b5263abf56631d3d064f5632a58;hb=b9cd11d78faef7815e435c11aa6a12793e9cb9c9;hp=f5db04894e89cae5f3b2044880184e53f3841d54;hpb=6446d674acf680643858d8b5b0e6112c89e7ee3a;p=kivitendo-erp.git diff --git a/SL/Helper/ShippedQty.pm b/SL/Helper/ShippedQty.pm index f5db04894..e109fa7ec 100644 --- a/SL/Helper/ShippedQty.pm +++ b/SL/Helper/ShippedQty.pm @@ -3,21 +3,22 @@ package SL::Helper::ShippedQty; use strict; use parent qw(Rose::Object); -use SL::AM; +use Carp; use Scalar::Util qw(blessed); -use SL::DBUtils qw(selectall_hashref_query selectall_as_map); use List::Util qw(min); use List::MoreUtils qw(any all uniq); use List::UtilsBy qw(partition_by); +use SL::AM; +use SL::DBUtils qw(selectall_hashref_query selectall_as_map); use SL::Locale::String qw(t8); use Rose::Object::MakeMethods::Generic ( - 'scalar' => [ qw(objects objects_or_ids shipped_qty ) ], - 'scalar --get_set_init' => [ qw(oe_ids dbh require_stock_out fill_up item_identity_fields oi2oe oi_qty delivered) ], + 'scalar' => [ qw(objects objects_or_ids shipped_qty keep_matches) ], + 'scalar --get_set_init' => [ qw(oe_ids dbh require_stock_out fill_up item_identity_fields oi2oe oi_qty delivered matches) ], ); my $no_stock_item_links_query = <<''; - SELECT oi.trans_id, oi.id AS oi_id, oi.qty AS oi_qty, oi.unit AS oi_unit, doi.qty AS doi_qty, doi.unit AS doi_unit + SELECT oi.trans_id, oi.id AS oi_id, oi.qty AS oi_qty, oi.unit AS oi_unit, doi.id AS doi_id, doi.qty AS doi_qty, doi.unit AS doi_unit FROM record_links rl INNER JOIN orderitems oi ON oi.id = rl.from_id AND rl.from_table = 'orderitems' INNER JOIN delivery_order_items doi ON doi.id = rl.to_id AND rl.to_table = 'delivery_order_items' @@ -50,7 +51,7 @@ my $no_stock_fill_up_doi_query = <<''; AND to_id = doi.id) my $stock_item_links_query = <<''; - SELECT oi.trans_id, oi.id AS oi_id, oi.qty AS oi_qty, oi.unit AS oi_unit, + SELECT oi.trans_id, oi.id AS oi_id, oi.qty AS oi_qty, oi.unit AS oi_unit, doi.id AS doi_id, (CASE WHEN doe.customer_id > 0 THEN -1 ELSE 1 END) * i.qty AS doi_qty, p.unit AS doi_unit FROM record_links rl INNER JOIN orderitems oi ON oi.id = rl.from_id AND rl.from_table = 'orderitems' @@ -102,9 +103,7 @@ my %item_identity_fields = ( sub calculate { my ($self, $data) = @_; - die 'Need exactly one argument, either id, object or arrayref of ids or objects.' unless 2 == @_; - - return $self if !$data || ('ARRAY' eq ref $data && !@$data); + croak 'Need exactly one argument, either id, object or arrayref of ids or objects.' unless 2 == @_; $self->normalize_input($data); @@ -128,10 +127,13 @@ sub calculate_item_links { my $data = selectall_hashref_query($::form, $self->dbh, $query, @oe_ids); for (@$data) { + my $qty = $_->{doi_qty} * AM->convert_unit($_->{doi_unit} => $_->{oi_unit}); $self->shipped_qty->{$_->{oi_id}} //= 0; - $self->shipped_qty->{$_->{oi_id}} += $_->{doi_qty} * AM->convert_unit($_->{doi_unit} => $_->{oi_unit}); + $self->shipped_qty->{$_->{oi_id}} += $qty; $self->oi2oe->{$_->{oi_id}} = $_->{trans_id}; $self->oi_qty->{$_->{oi_id}} = $_->{oi_qty}; + + push @{ $self->matches }, [ $_->{oi_id}, $_->{doi_id}, $qty, 1 ] if $self->keep_matches; } } @@ -194,6 +196,7 @@ sub calculate_fill_up { $self->shipped_qty->{$oi->{id}} += $min_qty; $doi->{qty} -= $min_qty / $factor; # TODO: find a way to avoid float rounding + push @{ $self->matches }, [ $oi->{id}, $doi->{id}, $min_qty, 0 ] if $self->keep_matches; } } } @@ -205,7 +208,7 @@ sub calculate_fill_up { sub write_to { my ($self, $objects) = @_; - die 'expecting array of objects' unless 'ARRAY' eq ref $objects; + croak 'expecting array of objects' unless 'ARRAY' eq ref $objects; my $shipped_qty = $self->shipped_qty; @@ -231,7 +234,9 @@ sub write_to { sub write_to_objects { my ($self) = @_; - die 'Can only use write_to_objects, when calculate was called with objects. Use write_to instead.' unless $self->objects_or_ids; + return unless @{ $self->oe_ids }; + + croak 'Can only use write_to_objects, when calculate was called with objects. Use write_to instead.' unless $self->objects_or_ids; $self->write_to($self->objects); } @@ -250,10 +255,11 @@ sub normalize_input { $self->objects_or_ids(!!blessed($data->[0])); if ($self->objects_or_ids) { - die 'unblessed object in data while expecting object' if any { !blessed($_) } @$data; + croak 'unblessed object in data while expecting object' if any { !blessed($_) } @$data; $self->objects($data); } else { - die 'object or reference in data while expecting ids' if any { ref($_) } @$data; + croak 'object or reference in data while expecting ids' if any { ref($_) } @$data; + croak 'ids need to be numbers' if any { ! ($_ * 1) } @$data; $self->oe_ids($data); } @@ -267,9 +273,9 @@ sub available_item_identity_fields { sub init_oe_ids { my ($self) = @_; - die 'oe_ids not initialized in id mode' if !$self->objects_or_ids; - die 'objects not initialized before accessing ids' if $self->objects_or_ids && !defined $self->objects; - die 'objects need to be Order or OrderItem' if any { ref($_) !~ /^SL::DB::Order(?:Item)?$/ } @{ $self->objects }; + croak 'oe_ids not initialized in id mode' if !$self->objects_or_ids; + croak 'objects not initialized before accessing ids' if $self->objects_or_ids && !defined $self->objects; + croak 'objects need to be Order or OrderItem' if any { ref($_) !~ /^SL::DB::Order(?:Item)?$/ } @{ $self->objects }; [ uniq map { ref($_) =~ /Item/ ? $_->trans_id : $_->id } @{ $self->objects } ] } @@ -278,6 +284,7 @@ sub init_dbh { SL::DB->client->dbh } sub init_oi2oe { {} } sub init_oi_qty { {} } +sub init_matches { [] } sub init_delivered { my ($self) = @_; my $d = { }; @@ -320,7 +327,7 @@ SL::Helper::ShippedQty - Algorithmic module for calculating shipped qty $helper->calculate($oe_id); $helper->calculate(\@oe_ids); - # if these are items set elivered and shipped_qty + # if these are items set delivered and shipped_qty # if these are orders, iterate through their items and set delivered on order $helper->write_to($objects); @@ -442,6 +449,14 @@ default is a client setting. Possible values include: =back +=item * C + +Boolean. If set to true the internal matchings of OrderItems and +DeliveryOrderItems will be kept for later postprocessing, in case you need more +than this modules provides. + +See C for the returned format. + =back =item C @@ -472,6 +487,13 @@ was found it will be set to zero. C is guaranteed only to be the correct boolean value, but not any specific value. +Note: C will avoid loading unnecessary objects. This means if it is +called with an Order object that has not loaded its orderitems yet, only +C will be set in the Order object. A subsequent C<< +$order->orderitems->[0]->{delivered} >> will return C, and C<< +$order->orderitems->[0]->shipped_qty >> will invoke another implicit +calculation. + =item C Valid after L. Returns a hasref with shipped qtys by orderitems id. @@ -483,6 +505,32 @@ linked elements were found. Valid after L. Returns a hashref with a delivered flag by order id. +=item C + +Valid after L with C set. Returns an arrayref of +individual matches. Each match is an arrayref with these fields: + +=over 4 + +=item * + +The id of the OrderItem. + +=item * + +The id of the DeliveryOrderItem. + +=item * + +The qty that was matched between the two converted to the unit of the OrderItem. + +=item * + +A boolean flag indicating if this match was found with record_item links. If +false, the match was made in the fill up stage. + +=back + =back =head1 REPLACED FUNCTIONALITY