Revision c1808a62
Von Tamino Steinert vor mehr als 2 Jahren hinzugefügt
| SL/Controller/Order.pm | ||
|---|---|---|
|   );
 | ||
| }
 | ||
|  | ||
| sub action_add_from_reclamation {
 | ||
|   my ($self) = @_;
 | ||
|  | ||
|   require SL::DB::Reclamation;
 | ||
|   my $reclamation = SL::DB::Reclamation->new(id => $::form->{from_id})->load;
 | ||
|   my $order = $reclamation->convert_to_order();
 | ||
|  | ||
|   $self->order($order);
 | ||
|  | ||
|   $self->recalc();
 | ||
|   $self->pre_render();
 | ||
|   $self->render(
 | ||
|     'order/form',
 | ||
|     title => $self->get_title_for('edit'),
 | ||
|     %{$self->{template_args}}
 | ||
|   );
 | ||
| }
 | ||
|  | ||
| # edit an existing order
 | ||
| sub action_edit {
 | ||
|   my ($self) = @_;
 | ||
| ... | ... | |
|   );
 | ||
| }
 | ||
|  | ||
| # save the order and redirect to the frontend subroutine for a new reclamation
 | ||
| sub action_save_and_reclamation {
 | ||
|   my ($self) = @_;
 | ||
|  | ||
|   # cann't use save_and_redirect_to, because id is set!
 | ||
|   my $errors = $self->save();
 | ||
|   if (scalar @{ $errors }) {
 | ||
|     $self->js->flash('error', $_) foreach @{ $errors };
 | ||
|     return $self->js->render();
 | ||
|   }
 | ||
|  | ||
|   my $to_type = $self->order->is_sales ? 'sales_reclamation'
 | ||
|                                        : 'purchase_reclamation';
 | ||
|   $self->redirect_to(
 | ||
|     controller => 'Reclamation',
 | ||
|     action     => 'add_from_order',
 | ||
|     type       => $to_type,
 | ||
|     from_id    => $self->order->id,
 | ||
|   );
 | ||
| }
 | ||
|  | ||
| # save the order and redirect to the frontend subroutine for a new
 | ||
| # invoice
 | ||
| sub action_save_and_invoice {
 | ||
| ... | ... | |
|           only_if   => (any { $self->type eq $_ } (purchase_order_type())),
 | ||
|           disabled  => !$may_edit_create ? t8('You do not have the permissions to access this function.') : undef,
 | ||
|         ],
 | ||
|         action => [
 | ||
|           t8('Save and Reclamation'),
 | ||
|           call      => [ 'kivi.Order.save', 'save_and_reclamation', $::instance_conf->get_order_warn_duplicate_parts ],
 | ||
|           only_if   => (any { $self->type eq $_ } (sales_order_type(), purchase_order_type()))
 | ||
|         ],
 | ||
|         action => [
 | ||
|           t8('Save and Invoice'),
 | ||
|           call      => [ 'kivi.Order.save', { action             => 'save_and_invoice',
 | ||
| SL/Controller/Reclamation.pm | ||
|---|---|---|
|                           save save_as_new print preview_pdf send_email
 | ||
|                           save_and_show_email_dialog
 | ||
|                           workflow_save_and_sales_or_purchase_reclamation
 | ||
|                           save_and_order
 | ||
|                        )]);
 | ||
|  | ||
| __PACKAGE__->run_before('get_unalterable_data',
 | ||
| ... | ... | |
|                           save save_as_new print preview_pdf send_email
 | ||
|                           save_and_show_email_dialog
 | ||
|                           workflow_save_and_sales_or_purchase_reclamation
 | ||
|                           save_and_order
 | ||
|                         )]);
 | ||
|  | ||
| #
 | ||
| ... | ... | |
|   );
 | ||
| }
 | ||
|  | ||
| sub action_add_from_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::Order;
 | ||
|   my $order = SL::DB::Order->new(id => $::form->{from_id})->load;
 | ||
|   my $reclamation = $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) = @_;
 | ||
| ... | ... | |
|   $self->redirect_to(@redirect_params);
 | ||
| }
 | ||
|  | ||
| sub action_save_and_order {
 | ||
|   my ($self) = @_;
 | ||
|  | ||
|   my $to_type = $self->reclamation->is_sales ? 'sales_order'
 | ||
|                                              : 'purchase_order';
 | ||
|   $self->save_and_redirect_to(
 | ||
|     controller => 'Order',
 | ||
|     action     => 'add_from_reclamation',
 | ||
|     type       => $to_type,
 | ||
|     from_id    => $self->reclamation->id,
 | ||
|   );
 | ||
| }
 | ||
|  | ||
| # workflow from purchase to sales reclamation
 | ||
| sub action_save_and_sales_reclamation {
 | ||
|   $_[0]->workflow_save_and_sales_or_purchase_reclamation();
 | ||
| ... | ... | |
|   my ($self) = @_;
 | ||
|   my %allowed_linked_records = map {$_ => 1} qw(
 | ||
|     SL::DB::Reclamation
 | ||
|     SL::DB::Order
 | ||
|   );
 | ||
|   my %allowed_linked_record_items = map {$_ => 1} qw(
 | ||
|     SL::DB::ReclamationItem
 | ||
|     SL::DB::OrderItem
 | ||
|   );
 | ||
|  | ||
|   my $from_record_id = delete $::form->{converted_from_record_id};
 | ||
| ... | ... | |
|           call      => [ 'kivi.Reclamation.purchase_reclamation_check_for_direct_delivery' ],
 | ||
|           only_if   => (any { $self->type eq $_ } (sales_reclamation_type())),
 | ||
|         ],
 | ||
|         action => [
 | ||
|           t8('Save and Order'),
 | ||
|           call      => [
 | ||
|             'kivi.Reclamation.save', 'save_and_order',
 | ||
|             $::instance_conf->get_reclamation_warn_duplicate_parts,
 | ||
|             $::instance_conf->get_reclamation_warn_no_reqdate,
 | ||
|           ],
 | ||
|         ],
 | ||
|       ], # end of combobox "Workflow"
 | ||
|  | ||
|       combobox => [
 | ||
| SL/DB/Order.pm | ||
|---|---|---|
|   return $delivery_order;
 | ||
| }
 | ||
|  | ||
| sub convert_to_reclamation {
 | ||
|   my ($self, %params) = @_;
 | ||
|   $params{destination_type} = $self->is_sales ? 'sales_reclamation'
 | ||
|                                               : 'purchase_reclamation';
 | ||
|  | ||
|   require SL::DB::Reclamation;
 | ||
|   my $reclamation = SL::DB::Reclamation->new_from($self, %params);
 | ||
|  | ||
|   return $reclamation;
 | ||
| }
 | ||
|  | ||
| sub _clone_orderitem_cvar {
 | ||
|   my ($cvar) = @_;
 | ||
|  | ||
| ... | ... | |
| sub new_from {
 | ||
|   my ($class, $source, %params) = @_;
 | ||
|  | ||
|   croak("Unsupported source object type '" . ref($source) . "'") unless ref($source) eq 'SL::DB::Order';
 | ||
|   unless (any {ref($source) eq $_} qw(
 | ||
|     SL::DB::Order
 | ||
|     SL::DB::Reclamation
 | ||
|   )) {
 | ||
|     croak("Unsupported source object type '" . ref($source) . "'");
 | ||
|   }
 | ||
|   croak("A destination type must be given as parameter")         unless $params{destination_type};
 | ||
|  | ||
|   my $destination_type  = delete $params{destination_type};
 | ||
| ... | ... | |
|     { from => 'request_quotation', to => 'sales_order',       abbr => 'rqso' },
 | ||
|     { from => 'sales_quotation',   to => 'request_quotation', abbr => 'sqrq' },
 | ||
|     { from => 'sales_order',       to => 'request_quotation', abbr => 'sorq' },
 | ||
|     { from => 'sales_reclamation', to => 'sales_order',       abbr => 'srso' },
 | ||
|     { from => 'purchase_reclamation', to => 'purchase_order', abbr => 'prpo' },
 | ||
|   );
 | ||
|   my $from_to = (grep { $_->{from} eq $source->type && $_->{to} eq $destination_type} @from_tos)[0];
 | ||
|   croak("Cannot convert from '" . $source->type . "' to '" . $destination_type . "'") if !$from_to;
 | ||
| ... | ... | |
|   if (ref($source) eq 'SL::DB::Order') {
 | ||
|     $item_parent_id_column = 'trans_id';
 | ||
|     $item_parent_column    = 'order';
 | ||
|   } elsif ( ref($source) eq 'SL::DB::Reclamation') {
 | ||
|     $item_parent_id_column = 'reclamation_id';
 | ||
|     $item_parent_column    = 'reclamation';
 | ||
|   }
 | ||
|  | ||
|   my %args = ( map({ ( $_ => $source->$_ ) } qw(amount cp_id currency_id cusordnumber customer_id delivery_customer_id delivery_term_id delivery_vendor_id
 | ||
|                                                 department_id exchangerate globalproject_id intnotes marge_percent marge_total language_id netamount notes
 | ||
|                                                 ordnumber payment_id quonumber reqdate salesman_id shippingpoint shipvia taxincluded tax_point taxzone_id
 | ||
|                                                 transaction_description vendor_id billing_address_id
 | ||
|                                              )),
 | ||
|                quotation => !!($destination_type =~ m{quotation$}),
 | ||
|                closed    => 0,
 | ||
|                delivered => 0,
 | ||
|                transdate => DateTime->today_local,
 | ||
|                employee  => SL::DB::Manager::Employee->current,
 | ||
|             );
 | ||
|   # reqdate in quotation is 'offer is valid    until reqdate'
 | ||
|   # reqdate in order     is 'will be delivered until reqdate'
 | ||
|   # both dates are setable (on|off)
 | ||
|   # and may have a additional interval in days (+ n days)
 | ||
|   # dies if this convention will change
 | ||
|   $args{reqdate} = $from_to->{to} =~ m/_quotation$/
 | ||
|                  ? $::instance_conf->get_reqdate_on
 | ||
|                  ? DateTime->today_local->next_workday(extra_days => $::instance_conf->get_reqdate_interval)->to_kivitendo
 | ||
|                  : undef
 | ||
|                  : $from_to->{to} =~ m/_order$/
 | ||
|                  ? $::instance_conf->get_deliverydate_on
 | ||
|                  ? DateTime->today_local->next_workday(extra_days => $::instance_conf->get_delivery_date_interval)->to_kivitendo
 | ||
|                  : undef
 | ||
|                  : die "Wrong state for reqdate";
 | ||
|   my %args;
 | ||
|   if (ref($source) eq 'SL::DB::Order') {
 | ||
|     %args = ( map({ ( $_ => $source->$_ ) } qw(amount cp_id currency_id cusordnumber customer_id delivery_customer_id delivery_term_id delivery_vendor_id
 | ||
|                                                department_id exchangerate globalproject_id intnotes marge_percent marge_total language_id netamount notes
 | ||
|                                                ordnumber payment_id quonumber reqdate salesman_id shippingpoint shipvia taxincluded tax_point taxzone_id
 | ||
|                                                transaction_description vendor_id billing_address_id
 | ||
|                                             )),
 | ||
|                  quotation => !!($destination_type =~ m{quotation$}),
 | ||
|                  closed    => 0,
 | ||
|                  delivered => 0,
 | ||
|                  transdate => DateTime->today_local,
 | ||
|                  employee  => SL::DB::Manager::Employee->current,
 | ||
|               );
 | ||
|     # reqdate in quotation is 'offer is valid    until reqdate'
 | ||
|     # reqdate in order     is 'will be delivered until reqdate'
 | ||
|     # both dates are setable (on|off)
 | ||
|     # and may have a additional interval in days (+ n days)
 | ||
|     # dies if this convention will change
 | ||
|     $args{reqdate} = $from_to->{to} =~ m/_quotation$/
 | ||
|                    ? $::instance_conf->get_reqdate_on
 | ||
|                    ? DateTime->today_local->next_workday(extra_days => $::instance_conf->get_reqdate_interval)->to_kivitendo
 | ||
|                    : undef
 | ||
|                    : $from_to->{to} =~ m/_order$/
 | ||
|                    ? $::instance_conf->get_deliverydate_on
 | ||
|                    ? DateTime->today_local->next_workday(extra_days => $::instance_conf->get_delivery_date_interval)->to_kivitendo
 | ||
|                    : undef
 | ||
|                    : die "Wrong state for reqdate";
 | ||
|   } elsif ( ref($source) eq 'SL::DB::Reclamation') {
 | ||
|     #TODO(Tamino): add billing_address_id to reclamation
 | ||
|     %args = ( map({ ( $_ => $source->$_ ) } qw(
 | ||
|         amount currency_id customer_id delivery_term_id department_id
 | ||
|         exchangerate globalproject_id intnotes language_id netamount
 | ||
|         notes payment_id  reqdate salesman_id shippingpoint shipvia taxincluded
 | ||
|         tax_point taxzone_id transaction_description vendor_id
 | ||
|       )),
 | ||
|       cp_id     => $source->{contact_id},
 | ||
|       closed    => 0,
 | ||
|       delivered => 0,
 | ||
|       transdate => DateTime->today_local,
 | ||
|       employee  => SL::DB::Manager::Employee->current,
 | ||
|    );
 | ||
|   }
 | ||
|  | ||
|   if ( $is_abbr_any->(qw(sopo poso rqso sosq porq rqsq sqrq sorq)) ) {
 | ||
|     $args{ordnumber} = undef;
 | ||
| ... | ... | |
|     $item_parents{$source_item_id} ||= $source_item->$item_parent_column;
 | ||
|     my $item_parent                  = $item_parents{$source_item_id};
 | ||
|  | ||
|     my $current_oe_item = SL::DB::OrderItem->new(map({ ( $_ => $source_item->$_ ) }
 | ||
|                                                      qw(active_discount_source active_price_source base_qty cusordnumber
 | ||
|                                                         description discount lastcost longdescription
 | ||
|                                                         marge_percent marge_price_factor marge_total
 | ||
|                                                         ordnumber parts_id price_factor price_factor_id pricegroup_id
 | ||
|                                                         project_id qty reqdate sellprice serialnumber ship subtotal transdate unit
 | ||
|                                                         optional
 | ||
|                                                      )),
 | ||
|                                                  custom_variables => \@custom_variables,
 | ||
|     );
 | ||
|     my $current_oe_item;
 | ||
|     if (ref($source) eq 'SL::DB::Order') {
 | ||
|       $current_oe_item = SL::DB::OrderItem->new(map({ ( $_ => $source_item->$_ ) }
 | ||
|                                                        qw(active_discount_source active_price_source base_qty cusordnumber
 | ||
|                                                           description discount lastcost longdescription
 | ||
|                                                           marge_percent marge_price_factor marge_total
 | ||
|                                                           ordnumber parts_id price_factor price_factor_id pricegroup_id
 | ||
|                                                           project_id qty reqdate sellprice serialnumber ship subtotal transdate unit
 | ||
|                                                           optional
 | ||
|                                                        )),
 | ||
|                                                    custom_variables => \@custom_variables,
 | ||
|       );
 | ||
|     } elsif (ref($source) eq 'SL::DB::Reclamation') {
 | ||
|       $current_oe_item = SL::DB::OrderItem->new(
 | ||
|         map({ ( $_ => $source_item->$_ ) } qw(
 | ||
|           active_discount_source active_price_source base_qty description
 | ||
|           discount lastcost longdescription parts_id price_factor
 | ||
|           price_factor_id pricegroup_id project_id qty reqdate sellprice
 | ||
|           serialnumber unit
 | ||
|         )),
 | ||
|         custom_variables => \@custom_variables,
 | ||
|       );
 | ||
|     }
 | ||
|     if ( $is_abbr_any->(qw(sopo)) ) {
 | ||
|       $current_oe_item->sellprice($source_item->lastcost);
 | ||
|       $current_oe_item->discount(0);
 | ||
| ... | ... | |
|       $current_oe_item->lastcost($source_item->sellprice);
 | ||
|     }
 | ||
|     $current_oe_item->{"converted_from_orderitems_id"} = $_->{id} if ref($item_parent) eq 'SL::DB::Order';
 | ||
|     $current_oe_item->{"converted_from_reclamation_item_id"} = $_->{id} if ref($item_parent) eq 'SL::DB::Reclamation';
 | ||
|     $current_oe_item;
 | ||
|   } @{ $items };
 | ||
|  | ||
| SL/DB/Reclamation.pm | ||
|---|---|---|
|       where => [  $valid_for_type => 1 ]);
 | ||
| }
 | ||
|  | ||
| sub convert_to_order {
 | ||
|   my ($self, %params) = @_;
 | ||
|  | ||
|   my $order;
 | ||
|   $params{destination_type} = $self->is_sales ? 'sales_order'
 | ||
|                                               : 'purchase_order';
 | ||
|   if (!$self->db->with_transaction(sub {
 | ||
|     require SL::DB::Order;
 | ||
|     $order = SL::DB::Order->new_from($self, %params);
 | ||
|     $order->save;
 | ||
|     $self->link_to_record($order);
 | ||
|     foreach my $item (@{ $order->items }) {
 | ||
|       foreach (qw(reclamation_item)) {
 | ||
|         if ($item->{"converted_from_${_}_id"}) {
 | ||
|           die unless $item->{id};
 | ||
|           RecordLinks->create_links('dbh'        => $self->db->dbh,
 | ||
|                                     'mode'       => 'ids',
 | ||
|                                     'from_table' => 'reclamation_items',
 | ||
|                                     'from_ids'   => $item->{"converted_from_${_}_id"},
 | ||
|                                     'to_table'   => 'orderitems',
 | ||
|                                     'to_id'      => $item->{id},
 | ||
|           ) || die;
 | ||
|           delete $item->{"converted_from_${_}_id"};
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|  | ||
|     1;
 | ||
|   })) {
 | ||
|     return undef;
 | ||
|   }
 | ||
|  | ||
|   return $order;
 | ||
| }
 | ||
|  | ||
| #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
 | ||
|   );
 | ||
|   unless( $allowed_sources{ref $source} ) {
 | ||
|     croak("Unsupported source object type '" . ref($source) . "'");
 | ||
| ... | ... | |
|     { from => 'purchase_reclamation',    to => 'purchase_reclamation', abbr => 'prpr', },
 | ||
|     { from => 'sales_reclamation',       to => 'purchase_reclamation', abbr => 'srpr', },
 | ||
|     { from => 'purchase_reclamation',    to => 'sales_reclamation',    abbr => 'prsr', },
 | ||
|     #Order
 | ||
|     { from => 'sales_order',             to => 'sales_reclamation',    abbr => 'sosr', },
 | ||
|     { from => 'purchase_order',          to => 'purchase_reclamation', abbr => 'popr', },
 | ||
|   );
 | ||
|   my $from_to = (grep { $_->{from} eq $source->type && $_->{to} eq $destination_type} @from_tos)[0];
 | ||
|   if (!$from_to) {
 | ||
| ... | ... | |
|       transaction_description
 | ||
|       vendor_id
 | ||
|     ); # }}} for vim folds
 | ||
|   } elsif ( $is_abbr_any->(qw(sosr popr)) ) { #Order
 | ||
|     map { $record_args{$_} = $source->$_ } # {{{ for vim folds
 | ||
|     qw(
 | ||
|       amount
 | ||
|       currency_id
 | ||
|       customer_id
 | ||
|       delivery_term_id
 | ||
|       department_id
 | ||
|       exchangerate
 | ||
|       globalproject_id
 | ||
|       intnotes
 | ||
|       language_id
 | ||
|       netamount
 | ||
|       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 | ||
|---|---|---|
|   unless (any {ref($source) eq $_}
 | ||
|     qw(
 | ||
|       SL::DB::ReclamationItem
 | ||
|       SL::DB::OrderItem
 | ||
|     )
 | ||
|   ) {
 | ||
|     croak("Unsupported source object type '" . ref($source) . "'");
 | ||
| ... | ... | |
|       unit
 | ||
|     );
 | ||
|     $item_args{custom_variables} = \@custom_variables;
 | ||
|   } elsif (ref($source) eq 'SL::DB::OrderItem') {
 | ||
|     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);
 | ||
Auch abrufbar als: Unified diff
Workflow: order ↔ reclamation