my ($self) = @_;
$self->order->transdate(DateTime->now_local());
- $self->order->reqdate(DateTime->today_local->next_workday) if !$self->order->reqdate;
+ my $extra_days = $self->type eq _sales_quotation_type() ? $::instance_conf->get_reqdate_interval : 1;
+ $self->order->reqdate(DateTime->today_local->next_workday(extra_days => $extra_days)) if !$self->order->reqdate;
$self->_pre_render();
$self->render(
sub action_save_as_new {
my ($self) = @_;
- if (!$self->order->id) {
+ my $order = $self->order;
+
+ if (!$order->id) {
$self->js->flash('error', t8('This object has not been saved yet.'));
return $self->js->render();
}
- delete $::form->{$_} for qw(closed delivered converted_from_oe_id converted_from_orderitems_ids);
-
- my $src_order = SL::DB::Order->new(id => $self->order->id)->load;
+ # load order from db to check if values changed
+ my $saved_order = SL::DB::Order->new(id => $order->id)->load;
+ my %new_attrs;
# Lets assign a new number if the user hasn't changed the previous one.
# If it has been changed manually then use it as-is.
- if (trim($self->order->number) eq $src_order->number) {
- $self->order->number('');
- }
+ $new_attrs{number} = (trim($order->number) eq $saved_order->number)
+ ? ''
+ : trim($order->number);
- # Clear reqdate and transdate unless changed
- if ($self->order->transdate == $src_order->transdate) {
- $self->order->transdate(DateTime->today_local)
- }
- if ($self->order->reqdate == $src_order->reqdate) {
+ # Clear transdate unless changed
+ $new_attrs{transdate} = ($order->transdate == $saved_order->transdate)
+ ? DateTime->today_local
+ : $order->transdate;
+
+ # Set new reqdate unless changed
+ if ($order->reqdate == $saved_order->reqdate) {
my $extra_days = $self->type eq _sales_quotation_type() ? $::instance_conf->get_reqdate_interval : 1;
- $self->order->reqdate(DateTime->today_local->next_workday(extra_days => $extra_days));
+ $new_attrs{reqdate} = DateTime->today_local->next_workday(extra_days => $extra_days);
+ } else {
+ $new_attrs{reqdate} = $order->reqdate;
}
# Update employee
- $self->order->employee(SL::DB::Manager::Employee->current);
+ $new_attrs{employee} = SL::DB::Manager::Employee->current;
+
+ # Create new record from current one
+ $self->order(SL::DB::Order->new_from($order, destination_type => $order->type, attributes => \%new_attrs));
+
+ # no linked records on save as new
+ delete $::form->{$_} for qw(converted_from_oe_id converted_from_orderitems_ids);
# save
$self->action_save();
sub action_customer_vendor_changed {
my ($self) = @_;
+ _setup_order_from_cv($self->order);
+ $self->_recalc();
+
my $cv_method = $self->cv;
if ($self->order->$cv_method->contacts && scalar @{ $self->order->$cv_method->contacts } > 0) {
$self->js->hide('#shipto_row');
}
- $self->order->taxzone_id($self->order->$cv_method->taxzone_id);
-
- if ($self->order->is_sales) {
- $self->order->taxincluded(defined($self->order->$cv_method->taxincluded_checked)
- ? $self->order->$cv_method->taxincluded_checked
- : $::myconfig{taxincluded_checked});
- $self->js->val('#order_salesman_id', $self->order->$cv_method->salesman_id);
- }
-
- $self->order->payment_id($self->order->$cv_method->payment_id);
- $self->order->delivery_term_id($self->order->$cv_method->delivery_term_id);
-
- $self->_recalc();
+ $self->js->val( '#order_salesman_id', $self->order->salesman_id) if $self->order->is_sales;
$self->js
->replaceWith('#order_cp_id', $self->build_contact_select)
->replaceWith('#order_shipto_id', $self->build_shipto_select)
+ ->replaceWith('#business_info_row', $self->build_business_info_row)
->val( '#order_taxzone_id', $self->order->taxzone_id)
->val( '#order_taxincluded', $self->order->taxincluded)
->val( '#order_payment_id', $self->order->payment_id)
->val( '#order_delivery_term_id', $self->order->delivery_term_id)
- ->val( '#order_intnotes', $self->order->$cv_method->notes)
+ ->val( '#order_intnotes', $self->order->intnotes)
->focus( '#order_' . $self->cv . '_id');
$self->_js_redisplay_amounts_and_taxes;
$self->js->render();
}
+# open the dialog for customer/vendor details
+sub action_show_customer_vendor_details_dialog {
+ my ($self) = @_;
+
+ my $is_customer = 'customer' eq $::form->{vc};
+ my $cv;
+ if ($is_customer) {
+ $cv = SL::DB::Customer->new(id => $::form->{vc_id})->load;
+ } else {
+ $cv = SL::DB::Vendor->new(id => $::form->{vc_id})->load;
+ }
+
+ my %details = map { $_ => $cv->$_ } @{$cv->meta->columns};
+ $details{discount_as_percent} = $cv->discount_as_percent;
+ $details{creditlimt} = $cv->creditlimit_as_number;
+ $details{business} = $cv->business->description if $cv->business;
+ $details{language} = $cv->language_obj->description if $cv->language_obj;
+ $details{delivery_terms} = $cv->delivery_term->description if $cv->delivery_term;
+ $details{payment_terms} = $cv->payment->description if $cv->payment;
+ $details{pricegroup} = $cv->pricegroup->pricegroup if $cv->pricegroup;
+
+ foreach my $entry (@{ $cv->shipto }) {
+ push @{ $details{SHIPTO} }, { map { $_ => $entry->$_ } @{$entry->meta->columns} };
+ }
+ foreach my $entry (@{ $cv->contacts }) {
+ push @{ $details{CONTACTS} }, { map { $_ => $entry->$_ } @{$entry->meta->columns} };
+ }
+
+ $_[0]->render('common/show_vc_details', { layout => 0 },
+ is_customer => $is_customer,
+ %details);
+
+}
+
# called if a unit in an existing item row is changed
sub action_unit_changed {
my ($self) = @_;
);
}
+# render the info line for business
+#
+# Needed, if customer/vendor changed.
+sub build_business_info_row
+{
+ $_[0]->p->render('order/tabs/_business_info_row', SELF => $_[0]);
+}
+
# build the rows for displaying taxes
#
# Called if amounts where recalculated and redisplayed.
$order ||= SL::DB::Order->new(orderitems => [],
quotation => (any { $self->type eq $_ } (_sales_quotation_type(), _request_quotation_type())));
+ my $cv_id_method = $self->cv . '_id';
+ if (!$::form->{id} && $::form->{$cv_id_method}) {
+ $order->$cv_id_method($::form->{$cv_id_method});
+ _setup_order_from_cv($order);
+ }
+
my $form_orderitems = delete $::form->{order}->{orderitems};
my $form_periodic_invoices_config = delete $::form->{order}->{periodic_invoices_config};
return $item;
}
+sub _setup_order_from_cv {
+ my ($order) = @_;
+
+ $order->$_($order->customervendor->$_) for (qw(taxzone_id payment_id delivery_term_id));
+
+ $order->intnotes($order->customervendor->notes);
+
+ if ($order->is_sales) {
+ $order->salesman_id($order->customer->salesman_id);
+ $order->taxincluded(defined($order->customer->taxincluded_checked)
+ ? $order->customer->taxincluded_checked
+ : $::myconfig{taxincluded_checked});
+ }
+
+}
+
# recalculate prices and taxes
#
# Using the PriceTaxCalculator. Store linetotals in the item objects.
my $destination_type = $::form->{type} eq _sales_quotation_type() ? _sales_order_type()
: $::form->{type} eq _request_quotation_type() ? _purchase_order_type()
+ : $::form->{type} eq _purchase_order_type() ? _sales_order_type()
+ : $::form->{type} eq _sales_order_type() ? _purchase_order_type()
: '';
$self->order(SL::DB::Order->new_from($self->order, destination_type => $destination_type));
$self->{converted_from_oe_id} = delete $::form->{id};
+ # set item ids to new fake id, to identify them as new items
+ foreach my $item (@{$self->order->items_sorted}) {
+ $item->{new_fake_id} = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
+ }
+
# change form type
$::form->{type} = $destination_type;
- $self->init_type;
+ $self->type($self->init_type);
+ $self->cv ($self->init_cv);
$self->_check_auth;
$self->_recalc();
} } @all_objects;
}
- $::request->{layout}->use_javascript("${_}.js") for qw(kivi.SalesPurchase kivi.Order kivi.File ckeditor/ckeditor ckeditor/adapters/jquery edit_periodic_invoices_config);
+ $::request->{layout}->use_javascript("${_}.js") for qw(kivi.SalesPurchase kivi.Order kivi.File ckeditor/ckeditor ckeditor/adapters/jquery edit_periodic_invoices_config calculate_qty);
$self->_setup_edit_action_bar;
}
combobox => [
action => [
t8('Save'),
- call => [ 'kivi.Order.save', $::instance_conf->get_order_warn_duplicate_parts ],
+ call => [ 'kivi.Order.save', 'save', $::instance_conf->get_order_warn_duplicate_parts ],
checks => [ 'kivi.Order.check_save_active_periodic_invoices' ],
],
action => [
t8('Save as new'),
- call => [ 'kivi.Order.save_as_new', $::instance_conf->get_order_warn_duplicate_parts ],
+ call => [ 'kivi.Order.save', 'save_as_new', $::instance_conf->get_order_warn_duplicate_parts ],
checks => [ 'kivi.Order.check_save_active_periodic_invoices' ],
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
],
action => [
t8('Save and Delivery Order'),
- call => [ 'kivi.Order.save_and_delivery_order', $::instance_conf->get_order_warn_duplicate_parts ],
+ call => [ 'kivi.Order.save', 'save_and_delivery_order', $::instance_conf->get_order_warn_duplicate_parts ],
checks => [ 'kivi.Order.check_save_active_periodic_invoices' ],
only_if => (any { $self->type eq $_ } (_sales_order_type(), _purchase_order_type()))
],
action => [
t8('Save and Invoice'),
- call => [ 'kivi.Order.save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ],
+ call => [ 'kivi.Order.save', 'save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ],
checks => [ 'kivi.Order.check_save_active_periodic_invoices' ],
],
], # end of combobox "Save"
],
action => [
t8('Sales Order'),
- submit => [ '#order_form', { action => "Order/sales_order" } ],
- only_if => (any { $self->type eq $_ } (_sales_quotation_type())),
+ submit => [ '#order_form', { action => "Order/sales_order" } ],
+ only_if => (any { $self->type eq $_ } (_sales_quotation_type(), _purchase_order_type())),
+ disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
],
action => [
t8('Purchase Order'),
- submit => [ '#order_form', { action => "Order/purchase_order" } ],
- only_if => (any { $self->type eq $_ } (_request_quotation_type())),
+ submit => [ '#order_form', { action => "Order/purchase_order" } ],
+ only_if => (any { $self->type eq $_ } (_sales_order_type(), _request_quotation_type())),
+ disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
],
], # end of combobox "Workflow"
=over 4
+=item * C<template/webpages/order/tabs/_business_info_row.html>
+
+For displaying information on business type
+
=item * C<template/webpages/order/tabs/_item_input.html>
The input line for items
=item * currency
-=item * customer/vendor details ('D'-button)
-
=item * credit limit
=item * more workflows (save as new, quotation, purchase order)
=item * custom shipto address
+=item * check for direct delivery (workflow sales order -> purchase order)
+
=item * language / part translations
=item * access rights