use parent qw(SL::Controller::Base);
use SL::Helper::Flash qw(flash_later);
+use SL::Helper::Number qw(_format_number_units);
use SL::Presenter::Tag qw(select_tag hidden_tag div_tag);
use SL::Locale::String qw(t8);
use SL::SessionFile::Random;
use SL::Helper::UserPreferences::UpdatePositions;
use SL::Controller::Helper::GetModels;
+use SL::Controller::DeliveryOrder::TypeData;
use List::Util qw(first sum0);
use List::UtilsBy qw(sort_by uniq_by);
use Rose::Object::MakeMethods::Generic
(
scalar => [ qw(item_ids_to_delete is_custom_shipto_to_delete) ],
- 'scalar --get_set_init' => [ qw(order valid_types type cv p all_price_factors search_cvpartnumber show_update_button part_picker_classification_ids) ],
+ 'scalar --get_set_init' => [ qw(order valid_types type cv p all_price_factors search_cvpartnumber show_update_button part_picker_classification_ids type_data) ],
);
my ($self) = @_;
$self->order->transdate(DateTime->now_local());
- my $extra_days = $self->type eq sales_quotation_type() ? $::instance_conf->get_reqdate_interval :
- $self->type eq sales_order_type() ? $::instance_conf->get_delivery_date_interval : 1;
-
- if ( ($self->type eq sales_order_type() && $::instance_conf->get_deliverydate_on)
- || ($self->type eq sales_quotation_type() && $::instance_conf->get_reqdate_on)
- && (!$self->order->reqdate)) {
- $self->order->reqdate(DateTime->today_local->next_workday(extra_days => $extra_days));
- }
+ $self->type_data->set_reqdate_by_type;
$self->pre_render();
return $self->js->render();
}
- my $text = $self->type eq sales_order_type() ? $::locale->text('The order has been deleted')
- : $self->type eq purchase_order_type() ? $::locale->text('The order has been deleted')
- : $self->type eq sales_quotation_type() ? $::locale->text('The quotation has been deleted')
- : $self->type eq request_quotation_type() ? $::locale->text('The rfq has been deleted')
- : '';
- flash_later('info', $text);
+ flash_later('info', $self->type_data->text("delete"));
my @redirect_params = (
action => 'add',
return $self->js->render();
}
- my $text = $self->type eq sales_order_type() ? $::locale->text('The order has been saved')
- : $self->type eq purchase_order_type() ? $::locale->text('The order has been saved')
- : $self->type eq sales_quotation_type() ? $::locale->text('The quotation has been saved')
- : $self->type eq request_quotation_type() ? $::locale->text('The rfq has been saved')
- : '';
- flash_later('info', $text);
+ flash_later('info', $self->type_data->text("saved"));
my @redirect_params = (
action => 'edit',
: $order->transdate;
# Set new reqdate unless changed if it is enabled in client config
- if ($order->reqdate == $saved_order->reqdate) {
- my $extra_days = $self->type eq sales_quotation_type() ? $::instance_conf->get_reqdate_interval :
- $self->type eq sales_order_type() ? $::instance_conf->get_delivery_date_interval : 1;
-
- if ( ($self->type eq sales_order_type() && !$::instance_conf->get_deliverydate_on)
- || ($self->type eq sales_quotation_type() && !$::instance_conf->get_reqdate_on)) {
- $new_attrs{reqdate} = '';
- } else {
- $new_attrs{reqdate} = DateTime->today_local->next_workday(extra_days => $extra_days);
- }
- } else {
- $new_attrs{reqdate} = $order->reqdate;
- }
+ $new_attrs{reqdate} = $self->type_data->get_reqdate_by_type($order->reqdate, $saved_order->reqdate);
# Update employee
$new_attrs{employee} = SL::DB::Manager::Employee->current;
# helpers
#
-sub init_valid_types {
- [ sales_order_type(), purchase_order_type(), sales_quotation_type(), request_quotation_type() ];
-}
-
sub init_type {
my ($self) = @_;
if (none { $::form->{type} eq $_ } @{$self->valid_types}) {
- die "Not a valid type for order";
+ die "Not a valid type for delivery order";
}
$self->type($::form->{type});
sub init_cv {
my ($self) = @_;
- my $cv = (any { $self->type eq $_ } (sales_order_type(), sales_quotation_type())) ? 'customer'
- : (any { $self->type eq $_ } (purchase_order_type(), request_quotation_type())) ? 'vendor'
- : die "Not a valid type for order";
-
- return $cv;
+ return $self->type_data->customervendor;
}
sub init_search_cvpartnumber {
sub init_part_picker_classification_ids {
my ($self) = @_;
- my $attribute = 'used_for_' . ($self->type =~ m{sales} ? 'sale' : 'purchase');
- return [ map { $_->id } @{ SL::DB::Manager::PartClassification->get_all(where => [ $attribute => 1 ]) } ];
+ return [ map { $_->id } @{ SL::DB::Manager::PartClassification->get_all(where => $self->type_data->part_classification_query) } ];
}
sub check_auth {
my ($self) = @_;
- my $right_for = { map { $_ => $_.'_edit' } @{$self->valid_types} };
-
- my $right = $right_for->{ $self->type };
- $right ||= 'DOES_NOT_EXIST';
-
- $::auth->assert($right);
+ $::auth->assert($self->type_data->access || 'DOES_NOT_EXIST');
}
# build the selection box for contacts
# order here solves this problem.
my $order;
$order = SL::DB::DeliveryOrder->new(id => $::form->{id})->load(with => [ 'orderitems', 'orderitems.part' ]) if $::form->{id};
- $order ||= SL::DB::DeliveryOrder->new(orderitems => [],
- quotation => (any { $self->type eq $_ } (sales_quotation_type(), request_quotation_type())),
- currency_id => $::instance_conf->get_currency_id(),);
+ $order ||= SL::DB::DeliveryOrder->new(orderitems => [], currency_id => $::instance_conf->get_currency_id(), order_type => $self->type_data->validate($::form->{type}));
my $cv_id_method = $self->cv . '_id';
if (!$::form->{id} && $::form->{$cv_id_method}) {
return $self->js->render();
}
- my $destination_type = $::form->{type} eq sales_order_type() ? sales_quotation_type() : request_quotation_type();
+ my $destination_type = $self->type_data->workflow("to_quotation_type");
$self->order(SL::DB::DeliveryOrder->new_from($self->order, destination_type => $destination_type));
$self->{converted_from_oe_id} = delete $::form->{id};
return $self->js->render();
}
- 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()
- : '';
+ my $destination_type = $self->type_data->workflow("to_order_type");
# check for direct delivery
# copy shipto in custom shipto (custom shipto will be copied by new_from() in case)
my $custom_shipto;
- if ( $::form->{type} eq sales_order_type() && $destination_type eq purchase_order_type()
- && $::form->{use_shipto} && $self->order->shipto) {
+ if ($self->type_data->workflow("to_order_copy_shipto") && $::form->{use_shipto} && $self->order->shipto) {
$custom_shipto = $self->order->shipto->clone('SL::DB::DeliveryOrder');
}
$item->{new_fake_id} = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
}
- if ($::form->{type} eq sales_order_type() && $destination_type eq purchase_order_type()) {
+ if ($self->type_data->workflow("to_order_copy_shipto")) {
if ($::form->{use_shipto}) {
$self->order->custom_shipto($custom_shipto) if $custom_shipto;
} else {
$item->active_discount_source($price_source->discount_from_source($item->active_discount_source));
}
- if (any { $self->type eq $_ } (sales_order_type(), purchase_order_type())) {
- # Calculate shipped qtys here to prevent calling calculate for every item via the items method.
- # Do not use write_to_objects to prevent order->delivered to be set, because this should be
- # the value from db, which can be set manually or is set when linked delivery orders are saved.
- SL::Helper::ShippedQty->new->calculate($self->order)->write_to(\@{$self->order->items});
- }
-
- if ($self->order->number && $::instance_conf->get_webdav) {
+ if ($self->order->${\ $self->type_data->nr_key } && $::instance_conf->get_webdav) {
my $webdav = SL::Webdav->new(
type => $self->type,
number => $self->order->number,
} } @all_objects;
}
+ $self->{template_args}{inout} = $self->type_data->properties('transfer');
+
$self->get_item_cvpartnumber($_) for @{$self->order->items_sorted};
- $::request->{layout}->use_javascript("${_}.js") for qw(kivi.SalesPurchase kivi.Order kivi.File ckeditor/ckeditor ckeditor/adapters/jquery
+ $::request->{layout}->use_javascript("${_}.js") for qw(kivi.SalesPurchase kivi.DeliveryOrder kivi.File ckeditor/ckeditor ckeditor/adapters/jquery
calculate_qty kivi.Validator follow_up show_history);
$self->setup_edit_action_bar;
}
sub setup_edit_action_bar {
my ($self, %params) = @_;
- my $deletion_allowed = (any { $self->type eq $_ } (sales_quotation_type(), request_quotation_type()))
- || (($self->type eq sales_order_type()) && $::instance_conf->get_sales_order_show_delete)
- || (($self->type eq purchase_order_type()) && $::instance_conf->get_purchase_order_show_delete);
+ my $deletion_allowed = $self->type_data->show_menu("delete");
for my $bar ($::request->layout->get('actionbar')) {
$bar->add(
combobox => [
action => [
t8('Save'),
- call => [ 'kivi.Order.save', 'save', $::instance_conf->get_order_warn_duplicate_parts,
+ call => [ 'kivi.DeliveryOrder.save', 'save', $::instance_conf->get_order_warn_duplicate_parts,
$::instance_conf->get_order_warn_no_deliverydate,
],
],
action => [
t8('Save as new'),
- call => [ 'kivi.Order.save', 'save_as_new', $::instance_conf->get_order_warn_duplicate_parts ],
+ call => [ 'kivi.DeliveryOrder.save', 'save_as_new', $::instance_conf->get_order_warn_duplicate_parts ],
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
],
], # end of combobox "Save"
action => [
t8('Save and Quotation'),
submit => [ '#order_form', { action => "DeliveryOrder/sales_quotation" } ],
- only_if => (any { $self->type eq $_ } (sales_order_type())),
+ only_if => $self->type_data->show_menu("save_and_quotation"),
],
action => [
t8('Save and RFQ'),
submit => [ '#order_form', { action => "DeliveryOrder/request_for_quotation" } ],
- only_if => (any { $self->type eq $_ } (purchase_order_type())),
+ only_if => $self->type_data->show_menu("save_and_rfq"),
],
action => [
t8('Save and Sales Order'),
submit => [ '#order_form', { action => "DeliveryOrder/sales_order" } ],
- only_if => (any { $self->type eq $_ } (sales_quotation_type(), purchase_order_type())),
+ only_if => $self->type_data->show_menu("save_and_sales_order"),
],
action => [
t8('Save and Purchase Order'),
- call => [ 'kivi.Order.purchase_order_check_for_direct_delivery' ],
- only_if => (any { $self->type eq $_ } (sales_order_type(), request_quotation_type())),
+ call => [ 'kivi.DeliveryOrder.purchase_order_check_for_direct_delivery' ],
+ only_if => $self->type_data->show_menu("save_and_purchase_order"),
],
action => [
t8('Save and Delivery Order'),
- call => [ 'kivi.Order.save', 'save_and_delivery_order', $::instance_conf->get_order_warn_duplicate_parts,
+ call => [ 'kivi.DeliveryOrder.save', 'save_and_delivery_order', $::instance_conf->get_order_warn_duplicate_parts,
$::instance_conf->get_order_warn_no_deliverydate,
],
- only_if => (any { $self->type eq $_ } (sales_order_type(), purchase_order_type()))
+ only_if => $self->type_data->show_menu("save_and_delivery_order"),
],
action => [
t8('Save and Invoice'),
- call => [ 'kivi.Order.save', 'save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ],
+ call => [ 'kivi.DeliveryOrder.save', 'save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ],
+ only_if => $self->type_data->show_menu("save_and_invoice"),
],
action => [
t8('Save and AP Transaction'),
- call => [ 'kivi.Order.save', 'save_and_ap_transaction', $::instance_conf->get_order_warn_duplicate_parts ],
- only_if => (any { $self->type eq $_ } (purchase_order_type()))
+ call => [ 'kivi.DeliveryOrder.save', 'save_and_ap_transaction', $::instance_conf->get_order_warn_duplicate_parts ],
+ only_if => $self->type_data->show_menu("save_and_ap_transaction"),
],
], # end of combobox "Workflow"
],
action => [
t8('Save and preview PDF'),
- call => [ 'kivi.Order.save', 'preview_pdf', $::instance_conf->get_order_warn_duplicate_parts,
+ call => [ 'kivi.DeliveryOrder.save', 'preview_pdf', $::instance_conf->get_order_warn_duplicate_parts,
$::instance_conf->get_order_warn_no_deliverydate,
],
],
action => [
t8('Save and print'),
- call => [ 'kivi.Order.show_print_options', $::instance_conf->get_order_warn_duplicate_parts,
+ call => [ 'kivi.DeliveryOrder.show_print_options', $::instance_conf->get_order_warn_duplicate_parts,
$::instance_conf->get_order_warn_no_deliverydate,
],
],
action => [
t8('Save and E-mail'),
id => 'save_and_email_action',
- call => [ 'kivi.Order.save', 'save_and_show_email_dialog', $::instance_conf->get_order_warn_duplicate_parts,
+ call => [ 'kivi.DeliveryOrder.save', 'save_and_show_email_dialog', $::instance_conf->get_order_warn_duplicate_parts,
$::instance_conf->get_order_warn_no_deliverydate,
],
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
action => [
t8('Delete'),
- call => [ 'kivi.Order.delete_order' ],
+ call => [ 'kivi.DeliveryOrder.delete_order' ],
confirm => $::locale->text('Do you really want to delete this object?'),
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
- only_if => $deletion_allowed,
+ only_if => $self->type_data->show_menu("delete"),
],
combobox => [
],
action => [
t8('Follow-Up'),
- call => [ 'kivi.Order.follow_up_window' ],
+ call => [ 'kivi.DeliveryOrder.follow_up_window' ],
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
only_if => $::auth->assert('productivity', 1),
],
my ($self, $action) = @_;
return '' if none { lc($action)} qw(add edit);
-
- # for locales:
- # $::locale->text("Add Sales Order");
- # $::locale->text("Add Purchase Order");
- # $::locale->text("Add Quotation");
- # $::locale->text("Add Request for Quotation");
- # $::locale->text("Edit Sales Order");
- # $::locale->text("Edit Purchase Order");
- # $::locale->text("Edit Quotation");
- # $::locale->text("Edit Request for Quotation");
-
- $action = ucfirst(lc($action));
- return $self->type eq sales_order_type() ? $::locale->text("$action Sales Order")
- : $self->type eq purchase_order_type() ? $::locale->text("$action Purchase Order")
- : $self->type eq sales_quotation_type() ? $::locale->text("$action Quotation")
- : $self->type eq request_quotation_type() ? $::locale->text("$action Request for Quotation")
- : '';
+ return $self->type_data->text($action);
}
sub get_item_cvpartnumber {
return $texts;
}
-sub sales_order_type {
- 'sales_order';
-}
-
-sub purchase_order_type {
- 'purchase_order';
-}
-
-sub sales_quotation_type {
- 'sales_quotation';
-}
-
-sub request_quotation_type {
- 'request_quotation';
-}
-
sub nr_key {
- return $_[0]->type eq sales_order_type() ? 'ordnumber'
- : $_[0]->type eq purchase_order_type() ? 'ordnumber'
- : $_[0]->type eq sales_quotation_type() ? 'quonumber'
- : $_[0]->type eq request_quotation_type() ? 'quonumber'
- : '';
+ return $_[0]->type_data->nr_key;
}
sub save_and_redirect_to {
return $self->js->render();
}
- my $text = $self->type eq sales_order_type() ? $::locale->text('The order has been saved')
- : $self->type eq purchase_order_type() ? $::locale->text('The order has been saved')
- : $self->type eq sales_quotation_type() ? $::locale->text('The quotation has been saved')
- : $self->type eq request_quotation_type() ? $::locale->text('The rfq has been saved')
- : '';
- flash_later('info', $text);
+ flash_later('info', $self->type_data->text("saved"));
$self->redirect_to(%params, id => $self->order->id);
}
sub save_history {
my ($self, $addition) = @_;
- my $number_type = $self->order->type =~ m{order} ? 'ordnumber' : 'quonumber';
+ my $number_type = $self->nr_key;
my $snumbers = $number_type . '_' . $self->order->$number_type;
SL::DB::History->new(
return @errors;
}
+sub calculate_stock_in_out {
+ my ($self, $item) = @_;
+
+ return "" if !$item->part || !$item->part->unit;
+
+ my $in_out = $self->type_data->properties("transfer");
+
+ my $do_qty = $item->qty;
+ my $sum = sum0 map { $_->unit_obj->convert_to($_->qty, $item->unit_obj) } @{ $item->delivery_order_stock_entries };
+
+ my $matches = $do_qty == $sum;
+ my $content = _format_number_units($sum, 2, $item->unit_obj, $item->part->unit_obj);
+
+ return $content;
+}
+
+sub init_type_data {
+ SL::Controller::DeliveryOrder::TypeData->new($_[0]);
+}
+
+sub init_valid_types {
+ $_[0]->type_data->valid_types;
+}
+
1;
__END__
=back
-=item * C<js/kivi.Order.js>
+=item * C<js/kivi.DeliveryOrder.js>
java script functions