Revision 7ac17a23
Von Tamino Steinert vor mehr als 2 Jahren hinzugefügt
| SL/Controller/Reclamation.pm | ||
|---|---|---|
|                           save_and_show_email_dialog
 | ||
|                           workflow_save_and_sales_or_purchase_reclamation
 | ||
|                           save_and_order
 | ||
|                           save_and_delivery_order
 | ||
|                        )]);
 | ||
|  | ||
| __PACKAGE__->run_before('get_unalterable_data',
 | ||
| ... | ... | |
|                           save_and_show_email_dialog
 | ||
|                           workflow_save_and_sales_or_purchase_reclamation
 | ||
|                           save_and_order
 | ||
|                           save_and_delivery_order
 | ||
|                         )]);
 | ||
|  | ||
| #
 | ||
| ... | ... | |
|   );
 | ||
| }
 | ||
|  | ||
| sub action_add_from_delivery_order {
 | ||
|   my ($self) = @_;
 | ||
|  | ||
|   unless ($::form->{from_id}) {
 | ||
|     $self->js->flash('error', t8("Can't create new reclamation. No 'from_id' was given."));
 | ||
|     return $self->js->render();
 | ||
|   }
 | ||
|  | ||
|   require SL::DB::DeliveryOrder;
 | ||
|   my $delivery_order = SL::DB::DeliveryOrder->new(id => $::form->{from_id})->load;
 | ||
|   my $reclamation = $delivery_order->convert_to_reclamation();
 | ||
|  | ||
|   $self->reclamation($reclamation);
 | ||
|  | ||
|   $self->reinit_after_new_reclamation();
 | ||
|  | ||
|   $self->render(
 | ||
|     'reclamation/form',
 | ||
|     title => $self->get_title_for('add'),
 | ||
|     %{$self->{template_args}},
 | ||
|   );
 | ||
| }
 | ||
|  | ||
| # edit an existing reclamation
 | ||
| sub action_edit {
 | ||
|   my ($self) = @_;
 | ||
| ... | ... | |
|   $_[0]->workflow_save_and_sales_or_purchase_reclamation();
 | ||
| }
 | ||
|  | ||
| # save the reclamation and redirect to the frontend subroutine for a new
 | ||
| # delivery order
 | ||
| sub action_save_and_delivery_order {
 | ||
|   my ($self) = @_;
 | ||
|  | ||
|   my $to_type = $self->reclamation->is_sales ? 'sales_delivery_order'
 | ||
|                                              : 'purchase_delivery_order';
 | ||
|   $self->save_and_redirect_to(
 | ||
|     controller => 'do.pl',
 | ||
|     action     => 'add_from_reclamation',
 | ||
|     type       => $to_type,
 | ||
|     from_id    => $self->reclamation->id,
 | ||
|   );
 | ||
| }
 | ||
|  | ||
| # set form elements in respect to a changed customer or vendor
 | ||
| #
 | ||
| # This action is called on an change of the customer/vendor picker.
 | ||
| ... | ... | |
|   my %allowed_linked_records = map {$_ => 1} qw(
 | ||
|     SL::DB::Reclamation
 | ||
|     SL::DB::Order
 | ||
|     SL::DB::DeliveryOrder
 | ||
|   );
 | ||
|   my %allowed_linked_record_items = map {$_ => 1} qw(
 | ||
|     SL::DB::ReclamationItem
 | ||
|     SL::DB::OrderItem
 | ||
|     SL::DB::DeliveryOrderItem
 | ||
|   );
 | ||
|  | ||
|   my $from_record_id = delete $::form->{converted_from_record_id};
 | ||
| ... | ... | |
|             $::instance_conf->get_reclamation_warn_no_reqdate,
 | ||
|           ],
 | ||
|         ],
 | ||
|         action => [
 | ||
|           t8('Save and Delivery Order'),
 | ||
|           call      => [
 | ||
|             'kivi.Reclamation.save', 'save_and_delivery_order',
 | ||
|             $::instance_conf->get_reclamation_warn_duplicate_parts,
 | ||
|             $::instance_conf->get_reclamation_warn_no_reqdate,
 | ||
|           ],
 | ||
|         ],
 | ||
|       ], # end of combobox "Workflow"
 | ||
|  | ||
|       combobox => [
 | ||
| SL/DB/DeliveryOrder.pm | ||
|---|---|---|
|   return $cloned;
 | ||
| }
 | ||
|  | ||
| sub convert_to_reclamation {
 | ||
|   my ($self, %params) = @_;
 | ||
|  | ||
|   $params{destination_type} = $self->is_sales ? 'sales_reclamation'
 | ||
|                                               : 'purchase_reclamation';
 | ||
|  | ||
|   my $reclamation = SL::DB::Reclamation->new_from($self, %params);
 | ||
|  | ||
|   return $reclamation;
 | ||
| }
 | ||
|  | ||
| sub new_from {
 | ||
|   my ($class, $source, %params) = @_;
 | ||
|  | ||
|   croak("Unsupported source object type '" . ref($source) . "'") unless ref($source) eq 'SL::DB::Order';
 | ||
|   my %allowed_sources = map { $_ => 1 } qw(
 | ||
|     SL::DB::Reclamation
 | ||
|     SL::DB::Order
 | ||
|   );
 | ||
|   unless( $allowed_sources{ref $source} ) {
 | ||
|     croak("Unsupported source object type '" . ref($source) . "'");
 | ||
|   }
 | ||
|  | ||
|   my ($item_parent_id_column, $item_parent_column);
 | ||
|   my %record_args = (
 | ||
|     donumber => undef,
 | ||
|     employee => SL::DB::Manager::Employee->current,
 | ||
|     closed    => 0,
 | ||
|     delivered => 0,
 | ||
|     order_type => $params{type},
 | ||
|     transdate => DateTime->today_local,
 | ||
|   );
 | ||
|  | ||
|   if (ref($source) eq 'SL::DB::Order') {
 | ||
|     $item_parent_id_column = 'trans_id';
 | ||
|     $item_parent_column    = 'order';
 | ||
|   if ( ref($source) eq 'SL::DB::Order' ) {
 | ||
|     map{ ( $record_args{$_} = $source->$_ ) } # {{{ for vim folds
 | ||
|     qw(
 | ||
|       billing_address_id
 | ||
|       cp_id
 | ||
|       currency_id
 | ||
|       cusordnumber
 | ||
|       customer_id
 | ||
|       delivery_term_id
 | ||
|       department_id
 | ||
|       globalproject_id
 | ||
|       intnotes
 | ||
|       language_id
 | ||
|       notes
 | ||
|       ordnumber
 | ||
|       payment_id
 | ||
|       reqdate
 | ||
|       salesman_id
 | ||
|       shippingpoint
 | ||
|       shipvia
 | ||
|       taxincluded
 | ||
|       taxzone_id
 | ||
|       transaction_description
 | ||
|       vendor_id
 | ||
|     );
 | ||
|     # }}} for vim folds
 | ||
|   } elsif ( ref($source) eq 'SL::DB::Reclamation' ) {
 | ||
|     map{ ( $record_args{$_} = $source->$_ ) } # {{{ for vim folds
 | ||
|       #billing_address_id #TODO(Tamino): add billing_address_id to reclamation
 | ||
|     qw(
 | ||
|       currency_id
 | ||
|       customer_id
 | ||
|       delivery_term_id
 | ||
|       department_id
 | ||
|       globalproject_id
 | ||
|       intnotes
 | ||
|       language_id
 | ||
|       notes
 | ||
|       payment_id
 | ||
|       reqdate
 | ||
|       salesman_id
 | ||
|       shippingpoint
 | ||
|       shipvia
 | ||
|       taxincluded
 | ||
|       taxzone_id
 | ||
|       transaction_description
 | ||
|       vendor_id
 | ||
|     );
 | ||
|     $record_args{cp_id} = $source->contact_id;
 | ||
|     $record_args{cusordnumber} = $source->cv_record_number;
 | ||
|     # }}} for vim folds
 | ||
|   }
 | ||
|  | ||
|   my %args = ( map({ ( $_ => $source->$_ ) } qw(cp_id currency_id customer_id cusordnumber delivery_term_id department_id employee_id globalproject_id intnotes language_id notes
 | ||
|                                                 ordnumber payment_id reqdate salesman_id shippingpoint shipvia taxincluded taxzone_id transaction_description vendor_id billing_address_id
 | ||
|                                              )),
 | ||
|                closed    => 0,
 | ||
|                delivered => 0,
 | ||
|                order_type => $params{type},
 | ||
|                transdate => DateTime->today_local,
 | ||
|             );
 | ||
|  | ||
|   # Custom shipto addresses (the ones specific to the sales/purchase
 | ||
|   # record and not to the customer/vendor) are only linked from
 | ||
|   # shipto → delivery_orders. Meaning delivery_orders.shipto_id
 | ||
|   # will not be filled in that case.
 | ||
|   if (!$source->shipto_id && $source->id) {
 | ||
|     $args{custom_shipto} = $source->custom_shipto->clone($class) if $source->can('custom_shipto') && $source->custom_shipto;
 | ||
|  | ||
|     $record_args{custom_shipto} = $source->custom_shipto->clone($class) if $source->can('custom_shipto') && $source->custom_shipto;
 | ||
|   } else {
 | ||
|     $args{shipto_id} = $source->shipto_id;
 | ||
|     $record_args{shipto_id} = $source->shipto_id;
 | ||
|   }
 | ||
|  | ||
|   # infer type from legacy fields if not given
 | ||
|   $args{order_type} //= $source->customer_id ? 'sales_delivery_order'
 | ||
|   $record_args{order_type} //= $source->customer_id ? 'sales_delivery_order'
 | ||
|                       : $source->vendor_id   ? 'purchase_delivery_order'
 | ||
|                       : $source->is_sales    ? 'sales_delivery_order'
 | ||
|                       : croak "need some way to set delivery order type from source";
 | ||
|  | ||
|   my $delivery_order = $class->new(%args);
 | ||
|   my $delivery_order = $class->new(%record_args);
 | ||
|   $delivery_order->assign_attributes(%{ $params{attributes} }) if $params{attributes};
 | ||
|   my $items          = delete($params{items}) || $source->items_sorted;
 | ||
|   my %item_parents;
 | ||
|  | ||
|   # do not copy items when converting to supplier delivery order
 | ||
|   my @items = $delivery_order->is_type(SUPPLIER_DELIVERY_ORDER_TYPE) ? () : map {
 | ||
|     my $source_item      = $_;
 | ||
|     my $source_item_id   = $_->$item_parent_id_column;
 | ||
|     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};
 | ||
|  | ||
|     my $current_do_item = SL::DB::DeliveryOrderItem->new(map({ ( $_ => $source_item->$_ ) }
 | ||
|                                          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,
 | ||
|                                    ordnumber        => ref($item_parent) eq 'SL::DB::Order' ? $item_parent->ordnumber : $source_item->ordnumber,
 | ||
|                                  );
 | ||
|     $current_do_item->{"converted_from_orderitems_id"} = $_->{id} if ref($item_parent) eq 'SL::DB::Order';
 | ||
|     $current_do_item;
 | ||
|   } @{ $items };
 | ||
|  | ||
|   my $items = delete($params{items}) || $source->items_sorted;
 | ||
|   my @items = $delivery_order->is_type(SUPPLIER_DELIVERY_ORDER_TYPE) ? ()
 | ||
|               : map { SL::DB::DeliveryOrderItem->new_from($_) } @{ $items };
 | ||
|  | ||
|   @items = grep { $params{item_filter}->($_) } @items if $params{item_filter};
 | ||
|   @items = grep { $_->qty * 1 } @items if $params{skip_items_zero_qty};
 | ||
| SL/DB/DeliveryOrderItem.pm | ||
|---|---|---|
|  | ||
| # methods
 | ||
|  | ||
| sub new_from {
 | ||
|   my ($class, $source, %params) = @_;
 | ||
|  | ||
|   my %allowed_sources = map { $_ => 1 } qw(
 | ||
|       SL::DB::ReclamationItem
 | ||
|       SL::DB::OrderItem
 | ||
|   );
 | ||
|   unless( $allowed_sources{ref $source} ) {
 | ||
|     croak("Unsupported source object type '" . ref($source) . "'");
 | ||
|   }
 | ||
|  | ||
|   my @custom_variables = map { _clone_cvar_for_delivery_order_item($_) } @{ $source->custom_variables };
 | ||
|  | ||
|   my %item_args;
 | ||
|   if (ref($source) eq 'SL::DB::ReclamationItem') {
 | ||
|     map { $item_args{$_} = $source->$_ } # {{{ for vim folds
 | ||
|     qw(
 | ||
|       active_discount_source
 | ||
|       active_price_source
 | ||
|       base_qty
 | ||
|       description
 | ||
|       discount
 | ||
|       lastcost
 | ||
|       longdescription
 | ||
|       parts_id
 | ||
|       position
 | ||
|       price_factor
 | ||
|       price_factor_id
 | ||
|       pricegroup_id
 | ||
|       project_id
 | ||
|       qty
 | ||
|       reqdate
 | ||
|       sellprice
 | ||
|       serialnumber
 | ||
|       unit
 | ||
|     );
 | ||
|     $item_args{custom_variables} = \@custom_variables;
 | ||
|     # }}} for vim folds
 | ||
|   } elsif (ref($source) eq 'SL::DB::OrderItem') {
 | ||
|     map { $item_args{$_} = $source->$_ } # {{{ for vim folds
 | ||
|     qw(
 | ||
|       active_discount_source
 | ||
|       active_price_source
 | ||
|       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
 | ||
|     );
 | ||
|     $item_args{custom_variables} = \@custom_variables;
 | ||
|     $item_args{ordnumber}        = ref($source->record) eq 'SL::DB::Order' ? $source->record->ordnumber : $source->ordnumber;
 | ||
|     # }}} for vim folds
 | ||
|   }
 | ||
|  | ||
|   my $item = $class->new(%item_args);
 | ||
|  | ||
|   my $source_table = '';
 | ||
|   if( ref($source) eq 'SL::DB::OrderItem' ) {
 | ||
|     $source_table = 'orderitems';
 | ||
|   } elsif ( ref($source) eq 'SL::DB::ReclamationItem' ) {
 | ||
|     $source_table = 'reclamation_items';
 | ||
|   }
 | ||
|   $item->{"converted_from_". $source_table ."_id"} = $_->{id};
 | ||
|  | ||
|   return $item;
 | ||
| }
 | ||
|  | ||
| sub _clone_cvar_for_delivery_order_item {
 | ||
|   my ($cvar) = @_;
 | ||
|  | ||
|   my $cloned = $_->clone_and_reset;
 | ||
|   $cloned->sub_module('delivery_order_items');
 | ||
|  | ||
|   return $cloned;
 | ||
| }
 | ||
|  | ||
| sub record { goto &delivery_order }
 | ||
| sub record_id { goto &delivery_order_id }
 | ||
|  | ||
| SL/DB/Reclamation.pm | ||
|---|---|---|
|   return $order;
 | ||
| }
 | ||
|  | ||
| sub convert_to_delivery_order {
 | ||
|   my ($self, %params) = @_;
 | ||
|  | ||
|   my $delivery_order;
 | ||
|   if (!$self->db->with_transaction(sub {
 | ||
|     require SL::DB::DeliveryOrder;
 | ||
|     $delivery_order = SL::DB::DeliveryOrder->new_from($self, %params);
 | ||
|     $delivery_order->save;
 | ||
|     $self->link_to_record($delivery_order);
 | ||
|     # TODO extend link_to_record for items, otherwise long-term no d.r.y.
 | ||
|     foreach my $item (@{ $delivery_order->items }) {
 | ||
|       foreach (qw(reclamation_items)) {
 | ||
|         if ($item->{"converted_from_${_}_id"}) {
 | ||
|           die unless $item->{id};
 | ||
|           RecordLinks->create_links('dbh'        => $self->db->dbh,
 | ||
|                                     'mode'       => 'ids',
 | ||
|                                     'from_table' => $_,
 | ||
|                                     'from_ids'   => $item->{"converted_from_${_}_id"},
 | ||
|                                     'to_table'   => 'delivery_order_items',
 | ||
|                                     'to_id'      => $item->{id},
 | ||
|           ) || die;
 | ||
|           delete $item->{"converted_from_${_}_id"};
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|  | ||
|     $self->update_attributes(delivered => 1) unless $::instance_conf->get_shipped_qty_require_stock_out;
 | ||
|     1;
 | ||
|   })) {
 | ||
|     return undef, $self->db->error->db_error->db_error;
 | ||
|   }
 | ||
|  | ||
|   return $delivery_order, undef;
 | ||
| }
 | ||
|  | ||
| #TODO(Werner): überprüfen ob alle Felder richtig gestetzt werden
 | ||
| sub new_from {
 | ||
|   my ($class, $source, %params) = @_;
 | ||
|   my %allowed_sources = map { $_ => 1 } qw(
 | ||
|     SL::DB::Reclamation
 | ||
|     SL::DB::Order
 | ||
|     SL::DB::DeliveryOrder
 | ||
|   );
 | ||
|   unless( $allowed_sources{ref $source} ) {
 | ||
|     croak("Unsupported source object type '" . ref($source) . "'");
 | ||
| ... | ... | |
|     #Order
 | ||
|     { from => 'sales_order',             to => 'sales_reclamation',    abbr => 'sosr', },
 | ||
|     { from => 'purchase_order',          to => 'purchase_reclamation', abbr => 'popr', },
 | ||
|     #Delivery Order
 | ||
|     { from => 'sales_delivery_order',    to => 'sales_reclamation',    abbr => 'sdsr', },
 | ||
|     { from => 'purchase_delivery_order', to => 'purchase_reclamation', abbr => 'pdpr', },
 | ||
|   );
 | ||
|   my $from_to = (grep { $_->{from} eq $source->type && $_->{to} eq $destination_type} @from_tos)[0];
 | ||
|   if (!$from_to) {
 | ||
| ... | ... | |
|     $record_args{contact_id} = $source->cp_id;
 | ||
|     $record_args{cv_record_number} = $source->cusordnumber;
 | ||
|     # }}} for vim folds
 | ||
|   } elsif ( $is_abbr_any->(qw(sdsr pdpr)) ) { #DeliveryOrder
 | ||
|     map { $record_args{$_} = $source->$_ } # {{{ for vim folds
 | ||
|     qw(
 | ||
|       currency_id
 | ||
|       customer_id
 | ||
|       delivery_term_id
 | ||
|       department_id
 | ||
|       globalproject_id
 | ||
|       intnotes
 | ||
|       language_id
 | ||
|       notes
 | ||
|       payment_id
 | ||
|       salesman_id
 | ||
|       shippingpoint
 | ||
|       shipvia
 | ||
|       tax_point
 | ||
|       taxincluded
 | ||
|       taxzone_id
 | ||
|       transaction_description
 | ||
|       vendor_id
 | ||
|     );
 | ||
|     $record_args{contact_id} = $source->cp_id;
 | ||
|     $record_args{cv_record_number} = $source->cusordnumber;
 | ||
|     # }}} for vim folds
 | ||
|   }
 | ||
|  | ||
|   if ( ($from_to->{from} =~ m{sales}) && ($from_to->{to} =~ m{purchase}) ) {
 | ||
| SL/DB/ReclamationItem.pm | ||
|---|---|---|
|     qw(
 | ||
|       SL::DB::ReclamationItem
 | ||
|       SL::DB::OrderItem
 | ||
|       SL::DB::DeliveryOrderItem
 | ||
|     )
 | ||
|   ) {
 | ||
|     croak("Unsupported source object type '" . ref($source) . "'");
 | ||
| ... | ... | |
|       pricegroup_id project_id qty reqdate sellprice serialnumber unit
 | ||
|     );
 | ||
|     $item_args{custom_variables} = \@custom_variables;
 | ||
|   } elsif (ref($source) eq 'SL::DB::DeliveryOrderItem') {
 | ||
|     map { $item_args{$_} = $source->$_ } qw(
 | ||
|       active_discount_source active_price_source base_qty description discount
 | ||
|       lastcost longdescription parts_id position price_factor price_factor_id
 | ||
|       pricegroup_id project_id qty reqdate sellprice serialnumber unit
 | ||
|     );
 | ||
|     $item_args{custom_variables} = \@custom_variables;
 | ||
|   }
 | ||
|  | ||
|   my $item = $class->new(%item_args);
 | ||
| bin/mozilla/do.pl | ||
|---|---|---|
|   $main::lxdebug->leave_sub();
 | ||
| }
 | ||
|  | ||
| sub add_from_reclamation {
 | ||
|  | ||
|   require SL::DB::Reclamation;
 | ||
|   my $reclamation = SL::DB::Reclamation->new(id => $::form->{from_id})->load;
 | ||
|   my ($delivery_order, $error) = $reclamation->convert_to_delivery_order();
 | ||
|   if($error) {
 | ||
|     croak("Error while converting: " . $error);
 | ||
|   }
 | ||
|  | ||
|   # edit new saved delivery order
 | ||
|   $::form->{id} = $delivery_order->id;
 | ||
|   edit();
 | ||
| }
 | ||
|  | ||
| sub edit {
 | ||
|   $main::lxdebug->enter_sub();
 | ||
|  | ||
| ... | ... | |
|  | ||
|       'separator',
 | ||
|  | ||
|       action => [
 | ||
|         t8('Invoice'),
 | ||
|         submit => [ '#form', { action => "invoice" } ],
 | ||
|         disabled => !$::form->{id} ? t8('This record has not been saved yet.') : undef,
 | ||
|         confirm  => $::form->{delivered}                                                                         ? undef
 | ||
|                   : ($::form->{vc} eq 'customer' && $::instance_conf->get_sales_delivery_order_check_stocked)    ? t8('This record has not been stocked out. Proceed?')
 | ||
|                   : ($::form->{vc} eq 'vendor'   && $::instance_conf->get_purchase_delivery_order_check_stocked) ? t8('This record has not been stocked in. Proceed?')
 | ||
|                   :                                                                                                undef,
 | ||
|       combobox => [
 | ||
|         action => [ t8('Workflow') ],
 | ||
|         action => [
 | ||
|           t8('Invoice'),
 | ||
|           submit => [ '#form', { action => "invoice" } ],
 | ||
|           disabled => !$::form->{id} ? t8('This record has not been saved yet.') : undef,
 | ||
|           confirm  => $::form->{delivered}                                                                         ? undef
 | ||
|                     : ($::form->{vc} eq 'customer' && $::instance_conf->get_sales_delivery_order_check_stocked)    ? t8('This record has not been stocked out. Proceed?')
 | ||
|                     : ($::form->{vc} eq 'vendor'   && $::instance_conf->get_purchase_delivery_order_check_stocked) ? t8('This record has not been stocked in. Proceed?')
 | ||
|                     :                                                                                                undef,
 | ||
|         ],
 | ||
|         action => [
 | ||
|           t8('Save and Reclamation'),
 | ||
|           submit => [ '#form', { action => "save_and_reclamation" } ],
 | ||
|         ],
 | ||
|       ],
 | ||
|  | ||
|       combobox => [
 | ||
| ... | ... | |
|   $main::lxdebug->leave_sub();
 | ||
| }
 | ||
|  | ||
| sub save_and_reclamation {
 | ||
|   my $form     = $main::form;
 | ||
|   my $type     = $form->{type};
 | ||
|  | ||
|   # save the delivery order
 | ||
|   save(no_redirect => 1);
 | ||
|  | ||
|   my $to_reclamation_type =
 | ||
|     $type eq 'sales_delivery_order' ? 'sales_reclamation'
 | ||
|                                     : 'purchase_reclamation';
 | ||
|   $form->{callback} =
 | ||
|     'controller.pl?action=Reclamation/add_from_delivery_order' .
 | ||
|     '&type=' . $to_reclamation_type .
 | ||
|     '&from_id=' . $form->escape($form->{id});
 | ||
|   $form->redirect;
 | ||
| }
 | ||
|  | ||
| sub save_as_new {
 | ||
|   $main::lxdebug->enter_sub();
 | ||
|  | ||
Auch abrufbar als: Unified diff
Workflow: delivery_order ↔ reclamation