Zeiterfassung: Konvertierung: geliefert/gelieferte Mengen in Auftrag anpassen
authorBernd Bleßmann <bernd@kivitendo-premium.de>
Mon, 3 May 2021 11:24:41 +0000 (13:24 +0200)
committerBernd Bleßmann <bernd@kivitendo-premium.de>
Wed, 5 May 2021 15:25:03 +0000 (17:25 +0200)
SL/BackgroundJob/ConvertTimeRecordings.pm
SL/DB/DeliveryOrder.pm
t/background_job/convert_time_recordings.t

index ffc2bae..906c8db 100644 (file)
@@ -211,8 +211,11 @@ sub convert_with_linking {
           }
         }
 
+        # update delivered and item's ship for related order
         my $helper = SL::Helper::ShippedQty->new->calculate($related_order)->write_to_objects;
-        $related_order->update_attributes(delivered => $related_order->{delivered});
+        $related_order->delivered($related_order->{delivered});
+        $_->ship($_->{shipped_qty}) for @{$related_order->items};
+        $related_order->save(cascade => 1);
 
         1;
       })) {
@@ -287,9 +290,10 @@ sub get_order_for_time_recording {
     return;
   }
 
-  my $orders = SL::DB::Manager::Order->get_all(where => [customer_id      => $tr->customer_id,
-                                                         or               => [quotation => undef, quotation => 0],
-                                                         globalproject_id => $project_id, ]);
+  my $orders = SL::DB::Manager::Order->get_all(where        => [customer_id      => $tr->customer_id,
+                                                                or               => [quotation => undef, quotation => 0],
+                                                                globalproject_id => $project_id, ],
+                                               with_objects => ['orderitems']);
   my @matching_orders;
   foreach my $order (@$orders) {
     if (any { $_->parts_id == $part_id } @{ $order->items_sorted }) {
index 30db8e6..8bb89bd 100644 (file)
@@ -20,7 +20,7 @@ use SL::DB::Unit;
 use SL::Helper::Number qw(_format_total _round_total);
 
 use List::Util qw(first);
-use List::MoreUtils qw(any);
+use List::MoreUtils qw(any pairwise);
 use Math::Round qw(nhimult);
 
 __PACKAGE__->meta->add_relationship(orderitems => { type         => 'one to many',
@@ -264,17 +264,20 @@ sub new_from_time_recordings {
   if ($params{related_order}) {
     # collect suitable items in related order
     my @items_to_use;
+    my @new_attributes;
     foreach my $item (@items) {
       my $item_to_use = first {$item->parts_id == $_->parts_id} @{ $params{related_order}->items_sorted };
 
       die "no suitable item found in related order" if !$item_to_use;
 
       my %new_attributes;
-      $new_attributes{$_} = $item->$_ for qw(qty unit_obj longdescription);
-      $item_to_use->assign_attributes(%new_attributes);
-      push @items_to_use, $item_to_use;
+      $new_attributes{$_} = $item->$_ for qw(qty base_qty unit_obj longdescription);
+      push @items_to_use,   $item_to_use;
+      push @new_attributes, \%new_attributes;
     }
-    $delivery_order = SL::DB::DeliveryOrder->new_from($params{related_order}, items => \@items_to_use, %params);
+
+    $delivery_order = $class->new_from($params{related_order}, items => \@items_to_use, %params);
+    pairwise { $a->assign_attributes( %$b) } @{$delivery_order->items}, @new_attributes;
 
   } else {
     my %args = (
index 3ba2c9a..d08c03d 100644 (file)
@@ -1,4 +1,4 @@
-use Test::More tests => 7;
+use Test::More tests => 18;
 
 use strict;
 
@@ -8,6 +8,7 @@ use utf8;
 use Support::TestSetup;
 use Test::Exception;
 use DateTime;
+use Rose::DB::Object::Helpers qw(forget_related);
 
 use SL::DB::BackgroundJob;
 
@@ -34,6 +35,9 @@ $::locale = Locale->new('en');
 
 clear_up();
 
+########################################
+# two time recordings, one order linked with project_id
+########################################
 my $part     = new_service(partnumber => 'Serv1', unit => 'Std')->save;
 my $project  = create_project(projectnumber => 'p1', description => 'Project 1');
 my $customer = new_customer()->save;
@@ -50,20 +54,19 @@ my $sales_order = create_sales_order(
 my @time_recordings;
 push @time_recordings, new_time_recording(
   start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 10, minute =>  5),
-  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 11, minute => 10),
+  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 11, minute =>  5),
   customer   => $customer,
   project    => $project,
   part       => $part,
 )->save;
 push @time_recordings, new_time_recording(
   start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 12, minute =>  5),
-  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 14, minute => 10),
+  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 14, minute =>  5),
   customer   => $customer,
   project    => $project,
   part       => $part,
 )->save;
 
-# two time recordings, one order linked with project_id
 my %data   = (
   link_project => 1,
   project_id   => $project->id,
@@ -84,10 +87,139 @@ is($linked_dos->[0]->globalproject_id, $sales_order->globalproject_id, 'project
 
 my $linked_items = $sales_order->items->[0]->linked_records(to => 'DeliveryOrderItem');
 is(scalar @$linked_items, 1, 'one delivery order item linked to order item');
-is($linked_items->[0]->qty*1, 3.16, 'qty in delivery order');
+is($linked_items->[0]->qty*1, 3, 'qty in delivery order');
+is($linked_items->[0]->base_qty*1, 3, 'base_qty in delivery order');
+
+# reload order and orderitems to get changes to deliverd and ship
+Rose::DB::Object::Helpers::forget_related($sales_order, 'orderitems');
+$sales_order->load;
+
+ok($sales_order->delivered, 'related order is delivered');
+is($sales_order->items->[0]->ship*1, 3, 'ship in related order');
+
+clear_up();
+
+
+########################################
+# two time recordings, one order linked with project_id
+# unit in order is 'min', but part is 'Std'
+########################################
+$part     = new_service(partnumber => 'Serv1', unit => 'Std')->save;
+$project  = create_project(projectnumber => 'p1', description => 'Project 1');
+$customer = new_customer()->save;
+
+$sales_order = create_sales_order(
+  save             => 1,
+  customer         => $customer,
+  globalproject    => $project,
+  taxincluded      => 0,
+  orderitems       => [ create_order_item(part => $part, qty => 180, unit => 'min', sellprice => 70), ]
+);
+
+@time_recordings = ();
+push @time_recordings, new_time_recording(
+  start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 10, minute => 10),
+  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 11, minute => 10),
+  customer   => $customer,
+  project    => $project,
+  part       => $part,
+)->save;
+push @time_recordings, new_time_recording(
+  start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 12, minute => 10),
+  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 14, minute => 10),
+  customer   => $customer,
+  project    => $project,
+  part       => $part,
+)->save;
+
+# two time recordings, one order linked with project_id
+%data = (
+  link_project => 1,
+  project_id   => $project->id,
+  from_date    => '01.04.2021',
+  to_date      => '30.04.2021',
+);
+$db_obj = SL::DB::BackgroundJob->new();
+$db_obj->set_data(%data);
+$job    = SL::BackgroundJob::ConvertTimeRecordings->new;
+$ret    = $job->run($db_obj);
+
+$linked_dos = $sales_order->linked_records(to => 'DeliveryOrder');
+$linked_items = $sales_order->items->[0]->linked_records(to => 'DeliveryOrderItem');
+is($linked_items->[0]->qty*1, 3, 'different units: qty in delivery order');
+is($linked_items->[0]->base_qty*1, 3, 'different units: base_qty in delivery order');
+
+# reload order and orderitems to get changes to deliverd and ship
+Rose::DB::Object::Helpers::forget_related($sales_order, 'orderitems');
+$sales_order->load;
+
+ok($sales_order->delivered, 'different units: related order is delivered');
+is($sales_order->items->[0]->ship*1, 180, 'different units: ship in related order');
+
+clear_up();
+
+
+########################################
+# two time recordings, one order linked with project_id
+# unit in order is 'Std', but part is 'min'
+########################################
+$part     = new_service(partnumber => 'Serv1', unit => 'min')->save;
+$project  = create_project(projectnumber => 'p1', description => 'Project 1');
+$customer = new_customer()->save;
+
+$sales_order = create_sales_order(
+  save             => 1,
+  customer         => $customer,
+  globalproject    => $project,
+  taxincluded      => 0,
+  orderitems       => [ create_order_item(part => $part, qty => 2, unit => 'Std', sellprice => 70), ]
+);
+
+@time_recordings = ();
+push @time_recordings, new_time_recording(
+  start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 10, minute => 10),
+  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 11, minute => 10),
+  customer   => $customer,
+  project    => $project,
+  part       => $part,
+)->save;
+push @time_recordings, new_time_recording(
+  start_time => DateTime->new(year => 2021, month =>  4, day => 19, hour => 12, minute => 10),
+  end_time   => DateTime->new(year => 2021, month =>  4, day => 19, hour => 13, minute => 10),
+  customer   => $customer,
+  project    => $project,
+  part       => $part,
+)->save;
+
+# two time recordings, one order linked with project_id
+%data = (
+  link_project => 1,
+  project_id   => $project->id,
+  from_date    => '01.04.2021',
+  to_date      => '30.04.2021',
+);
+$db_obj = SL::DB::BackgroundJob->new();
+$db_obj->set_data(%data);
+$job    = SL::BackgroundJob::ConvertTimeRecordings->new;
+$ret    = $job->run($db_obj);
+
+$linked_dos = $sales_order->linked_records(to => 'DeliveryOrder');
+$linked_items = $sales_order->items->[0]->linked_records(to => 'DeliveryOrderItem');
+is($linked_items->[0]->qty*1, 2, 'different units 2: qty in delivery order');
+is($linked_items->[0]->base_qty*1, 120, 'different units 2: base_qty in delivery order');
+
+# reload order and orderitems to get changes to deliverd and ship
+Rose::DB::Object::Helpers::forget_related($sales_order, 'orderitems');
+$sales_order->load;
+
+ok($sales_order->delivered, 'different units 2: related order is delivered');
+is($sales_order->items->[0]->ship*1, 2, 'different units 2: ship in related order');
 
 clear_up();
 
+
+########################################
+
 $::locale = $old_locale;
 
 1;