item_selected: Multiselect bzw. Mengeneingabe beim Artikelselektor
[kivitendo-erp.git] / SL / DB / DeliveryOrder.pm
index febf5e2..b530db7 100644 (file)
@@ -8,6 +8,7 @@ use Rose::DB::Object::Helpers ();
 
 use SL::DB::MetaSetup::DeliveryOrder;
 use SL::DB::Manager::DeliveryOrder;
 
 use SL::DB::MetaSetup::DeliveryOrder;
 use SL::DB::Manager::DeliveryOrder;
+use SL::DB::Helper::AttrHTML;
 use SL::DB::Helper::FlattenToForm;
 use SL::DB::Helper::LinkedRecords;
 use SL::DB::Helper::TransNumberGenerator;
 use SL::DB::Helper::FlattenToForm;
 use SL::DB::Helper::LinkedRecords;
 use SL::DB::Helper::TransNumberGenerator;
@@ -29,6 +30,8 @@ __PACKAGE__->meta->add_relationship(orderitems => { type         => 'one to many
 
 __PACKAGE__->meta->initialize;
 
 
 __PACKAGE__->meta->initialize;
 
+__PACKAGE__->attr_html('notes');
+
 __PACKAGE__->before_save('_before_save_set_donumber');
 
 # hooks
 __PACKAGE__->before_save('_before_save_set_donumber');
 
 # hooks
@@ -44,11 +47,12 @@ sub _before_save_set_donumber {
 # methods
 
 sub items { goto &orderitems; }
 # methods
 
 sub items { goto &orderitems; }
+sub add_items { goto &add_orderitems; }
 
 sub items_sorted {
   my ($self) = @_;
 
 
 sub items_sorted {
   my ($self) = @_;
 
-  return [ sort {$a->id <=> $b->id } @{ $self->items } ];
+  return [ sort {$a->position <=> $b->position } @{ $self->items } ];
 }
 
 sub sales_order {
 }
 
 sub sales_order {
@@ -97,6 +101,13 @@ sub new_from {
 
   croak("Unsupported source object type '" . ref($source) . "'") unless ref($source) eq 'SL::DB::Order';
 
 
   croak("Unsupported source object type '" . ref($source) . "'") unless ref($source) eq 'SL::DB::Order';
 
+  my ($item_parent_id_column, $item_parent_column);
+
+  if (ref($source) eq 'SL::DB::Order') {
+    $item_parent_id_column = 'trans_id';
+    $item_parent_column    = 'order';
+  }
+
   my $terms = $source->can('payment_id') && $source->payment_id ? $source->payment_terms->terms_netto : 0;
 
   my %args = ( map({ ( $_ => $source->$_ ) } qw(cp_id currency_id customer_id cusordnumber department_id employee_id globalproject_id intnotes language_id notes
   my $terms = $source->can('payment_id') && $source->payment_id ? $source->payment_terms->terms_netto : 0;
 
   my %args = ( map({ ( $_ => $source->$_ ) } qw(cp_id currency_id customer_id cusordnumber department_id employee_id globalproject_id intnotes language_id notes
@@ -132,25 +143,41 @@ sub new_from {
     $args{shipto_id} = $source->shipto_id;
   }
 
     $args{shipto_id} = $source->shipto_id;
   }
 
-  my $delivery_order = $class->new(%args, %params);
+  my $delivery_order = $class->new(%args);
+  $delivery_order->assign_attributes(%{ $params{attributes} }) if $params{attributes};
+  my $items          = delete($params{items}) || $source->items_sorted;
+  my %item_parents;
 
   my @items = map {
     my $source_item      = $_;
 
   my @items = map {
     my $source_item      = $_;
+    my $source_item_id   = $_->$item_parent_id_column;
     my @custom_variables = map { _clone_orderitem_cvar($_) } @{ $source_item->custom_variables };
 
     my @custom_variables = map { _clone_orderitem_cvar($_) } @{ $source_item->custom_variables };
 
+    $item_parents{$source_item_id} ||= $source_item->$item_parent_column;
+    my $item_parent                  = $item_parents{$source_item_id};
+
     SL::DB::DeliveryOrderItem->new(map({ ( $_ => $source_item->$_ ) }
     SL::DB::DeliveryOrderItem->new(map({ ( $_ => $source_item->$_ ) }
-                                         qw(base_qty cusordnumber description discount lastcost longdescription marge_price_factor ordnumber parts_id price_factor price_factor_id
-                                            project_id qty reqdate sellprice serialnumber transdate unit
+                                         qw(base_qty cusordnumber description discount lastcost longdescription marge_price_factor parts_id price_factor price_factor_id
+                                            project_id qty reqdate sellprice serialnumber transdate unit active_discount_source active_price_source
                                          )),
                                          )),
-                                   custom_variables => \@custom_variables);
+                                   custom_variables => \@custom_variables,
+                                   ordnumber        => ref($item_parent) eq 'SL::DB::Order' ? $item_parent->ordnumber : $source_item->ordnumber,
+                                 );
+
+  } @{ $items };
 
 
-  } @{ $source->items_sorted };
+  @items = grep { $_->qty * 1 } @items if $params{skip_items_zero_qty};
+  @items = grep { $_->qty >=0 } @items if $params{skip_items_negative_qty};
 
   $delivery_order->items(\@items);
 
   return ($delivery_order, $custom_shipto);
 }
 
 
   $delivery_order->items(\@items);
 
   return ($delivery_order, $custom_shipto);
 }
 
+sub customervendor {
+  $_[0]->is_sales ? $_[0]->customer : $_[0]->vendor;
+}
+
 1;
 __END__
 
 1;
 __END__
 
@@ -186,7 +213,7 @@ sales/purchase models.
 Returns the delivery order items sorted by their ID (same order they
 appear in the frontend delivery order masks).
 
 Returns the delivery order items sorted by their ID (same order they
 appear in the frontend delivery order masks).
 
-=item C<new_from $source>
+=item C<new_from $source, %params>
 
 Creates a new C<SL::DB::DeliveryOrder> instance and copies as much
 information from C<$source> as possible. At the moment only instances
 
 Creates a new C<SL::DB::DeliveryOrder> instance and copies as much
 information from C<$source> as possible. At the moment only instances
@@ -209,6 +236,34 @@ and returned.
 
 The objects returned are not saved.
 
 
 The objects returned are not saved.
 
+C<%params> can include the following options:
+
+=over 2
+
+=item C<items>
+
+An optional array reference of RDBO instances for the items to use. If
+missing then the method C<items_sorted> will be called on
+C<$source>. This option can be used to override the sorting, to
+exclude certain positions or to add additional ones.
+
+=item C<skip_items_negative_qty>
+
+If trueish then items with a negative quantity are skipped. Items with
+a quantity of 0 are not affected by this option.
+
+=item C<skip_items_zero_qty>
+
+If trueish then items with a quantity of 0 are skipped.
+
+=item C<attributes>
+
+An optional hash reference. If it exists then it is passed to C<new>
+allowing the caller to set certain attributes for the new delivery
+order.
+
+=back
+
 =item C<sales_order>
 
 TODO: Describe sales_order
 =item C<sales_order>
 
 TODO: Describe sales_order