1 |
|
package SL::Controller::Order;
|
|
1 |
package SL::Controller::DeliveryOrder;
|
2 |
2 |
|
3 |
3 |
use strict;
|
4 |
4 |
use parent qw(SL::Controller::Base);
|
... | ... | |
14 |
14 |
use SL::Util qw(trim);
|
15 |
15 |
use SL::YAML;
|
16 |
16 |
use SL::DB::History;
|
17 |
|
use SL::DB::Order;
|
|
17 |
use SL::DB::DeliveryOrder;
|
18 |
18 |
use SL::DB::Default;
|
19 |
19 |
use SL::DB::Unit;
|
20 |
20 |
use SL::DB::Part;
|
... | ... | |
28 |
28 |
|
29 |
29 |
use SL::Helper::CreatePDF qw(:all);
|
30 |
30 |
use SL::Helper::PrintOptions;
|
31 |
|
use SL::Helper::ShippedQty;
|
32 |
31 |
use SL::Helper::UserPreferences::PositionsScrollbar;
|
33 |
32 |
use SL::Helper::UserPreferences::UpdatePositions;
|
34 |
33 |
|
... | ... | |
69 |
68 |
my ($self) = @_;
|
70 |
69 |
|
71 |
70 |
$self->order->transdate(DateTime->now_local());
|
72 |
|
my $extra_days = $self->type eq sales_quotation_type() ? $::instance_conf->get_reqdate_interval :
|
73 |
|
$self->type eq sales_order_type() ? $::instance_conf->get_delivery_date_interval : 1;
|
|
71 |
my $extra_days = $self->type eq vendor_in_type() ? $::instance_conf->get_reqdate_interval :
|
|
72 |
$self->type eq customer_in_type() ? $::instance_conf->get_delivery_date_interval : 1;
|
74 |
73 |
|
75 |
|
if ( ($self->type eq sales_order_type() && $::instance_conf->get_deliverydate_on)
|
76 |
|
|| ($self->type eq sales_quotation_type() && $::instance_conf->get_reqdate_on)
|
|
74 |
if ( ($self->type eq customer_in_type() && $::instance_conf->get_deliverydate_on)
|
|
75 |
|| ($self->type eq vendor_in_type() && $::instance_conf->get_reqdate_on)
|
77 |
76 |
&& (!$self->order->reqdate)) {
|
78 |
77 |
$self->order->reqdate(DateTime->today_local->next_workday(extra_days => $extra_days));
|
79 |
78 |
}
|
... | ... | |
81 |
80 |
|
82 |
81 |
$self->pre_render();
|
83 |
82 |
$self->render(
|
84 |
|
'order/form',
|
|
83 |
'delivery_order/form',
|
85 |
84 |
title => $self->get_title_for('add'),
|
86 |
85 |
%{$self->{template_args}}
|
87 |
86 |
);
|
... | ... | |
110 |
109 |
$self->recalc();
|
111 |
110 |
$self->pre_render();
|
112 |
111 |
$self->render(
|
113 |
|
'order/form',
|
|
112 |
'delivery_order/form',
|
114 |
113 |
title => $self->get_title_for('edit'),
|
115 |
114 |
%{$self->{template_args}}
|
116 |
115 |
);
|
... | ... | |
133 |
132 |
|
134 |
133 |
# fall back to save as new if only one id is given
|
135 |
134 |
if (scalar @multi_ids == 1) {
|
136 |
|
$self->order(SL::DB::Order->new(id => $multi_ids[0])->load);
|
|
135 |
$self->order(SL::DB::DeliveryOrder->new(id => $multi_ids[0])->load);
|
137 |
136 |
$self->action_save_as_new();
|
138 |
137 |
return;
|
139 |
138 |
}
|
140 |
139 |
|
141 |
140 |
# make new order from given orders
|
142 |
|
my @multi_orders = map { SL::DB::Order->new(id => $_)->load } @multi_ids;
|
|
141 |
my @multi_orders = map { SL::DB::DeliveryOrder->new(id => $_)->load } @multi_ids;
|
143 |
142 |
$self->{converted_from_oe_id} = join ' ', map { $_->id } @multi_orders;
|
144 |
|
$self->order(SL::DB::Order->new_from_multi(\@multi_orders, sort_sources_by => 'transdate'));
|
|
143 |
$self->order(SL::DB::DeliveryOrder->new_from_multi(\@multi_orders, sort_sources_by => 'transdate'));
|
145 |
144 |
|
146 |
145 |
$self->action_edit();
|
147 |
146 |
}
|
... | ... | |
157 |
156 |
return $self->js->render();
|
158 |
157 |
}
|
159 |
158 |
|
160 |
|
my $text = $self->type eq sales_order_type() ? $::locale->text('The order has been deleted')
|
161 |
|
: $self->type eq purchase_order_type() ? $::locale->text('The order has been deleted')
|
162 |
|
: $self->type eq sales_quotation_type() ? $::locale->text('The quotation has been deleted')
|
163 |
|
: $self->type eq request_quotation_type() ? $::locale->text('The rfq has been deleted')
|
|
159 |
my $text = $self->type eq customer_in_type() ? $::locale->text('The order has been deleted')
|
|
160 |
: $self->type eq customer_out_type() ? $::locale->text('The order has been deleted')
|
|
161 |
: $self->type eq vendor_in_type() ? $::locale->text('The quotation has been deleted')
|
|
162 |
: $self->type eq vendor_out_type() ? $::locale->text('The rfq has been deleted')
|
164 |
163 |
: '';
|
165 |
164 |
flash_later('info', $text);
|
166 |
165 |
|
... | ... | |
183 |
182 |
return $self->js->render();
|
184 |
183 |
}
|
185 |
184 |
|
186 |
|
my $text = $self->type eq sales_order_type() ? $::locale->text('The order has been saved')
|
187 |
|
: $self->type eq purchase_order_type() ? $::locale->text('The order has been saved')
|
188 |
|
: $self->type eq sales_quotation_type() ? $::locale->text('The quotation has been saved')
|
189 |
|
: $self->type eq request_quotation_type() ? $::locale->text('The rfq has been saved')
|
|
185 |
my $text = $self->type eq customer_in_type() ? $::locale->text('The order has been saved')
|
|
186 |
: $self->type eq customer_out_type() ? $::locale->text('The order has been saved')
|
|
187 |
: $self->type eq vendor_in_type() ? $::locale->text('The quotation has been saved')
|
|
188 |
: $self->type eq vendor_out_type() ? $::locale->text('The rfq has been saved')
|
190 |
189 |
: '';
|
191 |
190 |
flash_later('info', $text);
|
192 |
191 |
|
... | ... | |
211 |
210 |
}
|
212 |
211 |
|
213 |
212 |
# load order from db to check if values changed
|
214 |
|
my $saved_order = SL::DB::Order->new(id => $order->id)->load;
|
|
213 |
my $saved_order = SL::DB::DeliveryOrder->new(id => $order->id)->load;
|
215 |
214 |
|
216 |
215 |
my %new_attrs;
|
217 |
216 |
# Lets assign a new number if the user hasn't changed the previous one.
|
... | ... | |
227 |
226 |
|
228 |
227 |
# Set new reqdate unless changed if it is enabled in client config
|
229 |
228 |
if ($order->reqdate == $saved_order->reqdate) {
|
230 |
|
my $extra_days = $self->type eq sales_quotation_type() ? $::instance_conf->get_reqdate_interval :
|
231 |
|
$self->type eq sales_order_type() ? $::instance_conf->get_delivery_date_interval : 1;
|
|
229 |
my $extra_days = $self->type eq vendor_in_type() ? $::instance_conf->get_reqdate_interval :
|
|
230 |
$self->type eq customer_in_type() ? $::instance_conf->get_delivery_date_interval : 1;
|
232 |
231 |
|
233 |
|
if ( ($self->type eq sales_order_type() && !$::instance_conf->get_deliverydate_on)
|
234 |
|
|| ($self->type eq sales_quotation_type() && !$::instance_conf->get_reqdate_on)) {
|
|
232 |
if ( ($self->type eq customer_in_type() && !$::instance_conf->get_deliverydate_on)
|
|
233 |
|| ($self->type eq vendor_in_type() && !$::instance_conf->get_reqdate_on)) {
|
235 |
234 |
$new_attrs{reqdate} = '';
|
236 |
235 |
} else {
|
237 |
236 |
$new_attrs{reqdate} = DateTime->today_local->next_workday(extra_days => $extra_days);
|
... | ... | |
244 |
243 |
$new_attrs{employee} = SL::DB::Manager::Employee->current;
|
245 |
244 |
|
246 |
245 |
# Create new record from current one
|
247 |
|
$self->order(SL::DB::Order->new_from($order, destination_type => $order->type, attributes => \%new_attrs));
|
|
246 |
$self->order(SL::DB::DeliveryOrder->new_from($order, destination_type => $order->type, attributes => \%new_attrs));
|
248 |
247 |
|
249 |
248 |
# no linked records on save as new
|
250 |
249 |
delete $::form->{$_} for qw(converted_from_oe_id converted_from_orderitems_ids);
|
... | ... | |
420 |
419 |
$email_form->{subject} = $form->generate_email_subject();
|
421 |
420 |
$email_form->{attachment_filename} = $form->generate_attachment_filename();
|
422 |
421 |
$email_form->{message} = $form->generate_email_body();
|
423 |
|
$email_form->{js_send_function} = 'kivi.Order.send_email()';
|
|
422 |
$email_form->{js_send_function} = 'kivi.DeliveryOrder.send_email()';
|
424 |
423 |
|
425 |
424 |
my %files = $self->get_files_for_email_dialog();
|
426 |
425 |
$self->{all_employees} = SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]);
|
... | ... | |
433 |
432 |
);
|
434 |
433 |
|
435 |
434 |
$self->js
|
436 |
|
->run('kivi.Order.show_email_dialog', $dialog_html)
|
|
435 |
->run('kivi.DeliveryOrder.show_email_dialog', $dialog_html)
|
437 |
436 |
->reinit_widgets
|
438 |
437 |
->render($self);
|
439 |
438 |
}
|
... | ... | |
447 |
446 |
my $errors = $self->save();
|
448 |
447 |
|
449 |
448 |
if (scalar @{ $errors }) {
|
450 |
|
$self->js->run('kivi.Order.close_email_dialog');
|
|
449 |
$self->js->run('kivi.DeliveryOrder.close_email_dialog');
|
451 |
450 |
$self->js->flash('error', $_) foreach @{ $errors };
|
452 |
451 |
return $self->js->render();
|
453 |
452 |
}
|
... | ... | |
520 |
519 |
$self->redirect_to(@redirect_params);
|
521 |
520 |
}
|
522 |
521 |
|
523 |
|
# open the periodic invoices config dialog
|
524 |
|
#
|
525 |
|
# If there are values in the form (i.e. dialog was opened before),
|
526 |
|
# then use this values. Create new ones, else.
|
527 |
|
sub action_show_periodic_invoices_config_dialog {
|
528 |
|
my ($self) = @_;
|
529 |
|
|
530 |
|
my $config = make_periodic_invoices_config_from_yaml(delete $::form->{config});
|
531 |
|
$config ||= SL::DB::Manager::PeriodicInvoicesConfig->find_by(oe_id => $::form->{id}) if $::form->{id};
|
532 |
|
$config ||= SL::DB::PeriodicInvoicesConfig->new(periodicity => 'm',
|
533 |
|
order_value_periodicity => 'p', # = same as periodicity
|
534 |
|
start_date_as_date => $::form->{transdate_as_date} || $::form->current_date,
|
535 |
|
extend_automatically_by => 12,
|
536 |
|
active => 1,
|
537 |
|
email_subject => GenericTranslations->get(
|
538 |
|
language_id => $::form->{language_id},
|
539 |
|
translation_type =>"preset_text_periodic_invoices_email_subject"),
|
540 |
|
email_body => GenericTranslations->get(
|
541 |
|
language_id => $::form->{language_id},
|
542 |
|
translation_type =>"preset_text_periodic_invoices_email_body"),
|
543 |
|
);
|
544 |
|
$config->periodicity('m') if none { $_ eq $config->periodicity } @SL::DB::PeriodicInvoicesConfig::PERIODICITIES;
|
545 |
|
$config->order_value_periodicity('p') if none { $_ eq $config->order_value_periodicity } ('p', @SL::DB::PeriodicInvoicesConfig::ORDER_VALUE_PERIODICITIES);
|
546 |
|
|
547 |
|
$::form->get_lists(printers => "ALL_PRINTERS",
|
548 |
|
charts => { key => 'ALL_CHARTS',
|
549 |
|
transdate => 'current_date' });
|
550 |
|
|
551 |
|
$::form->{AR} = [ grep { $_->{link} =~ m/(?:^|:)AR(?::|$)/ } @{ $::form->{ALL_CHARTS} } ];
|
552 |
|
|
553 |
|
if ($::form->{customer_id}) {
|
554 |
|
$::form->{ALL_CONTACTS} = SL::DB::Manager::Contact->get_all_sorted(where => [ cp_cv_id => $::form->{customer_id} ]);
|
555 |
|
my $customer_object = SL::DB::Manager::Customer->find_by(id => $::form->{customer_id});
|
556 |
|
$::form->{postal_invoice} = $customer_object->postal_invoice;
|
557 |
|
$::form->{email_recipient_invoice_address} = $::form->{postal_invoice} ? '' : $customer_object->invoice_mail;
|
558 |
|
$config->send_email(0) if $::form->{postal_invoice};
|
559 |
|
}
|
560 |
|
|
561 |
|
$self->render('oe/edit_periodic_invoices_config', { layout => 0 },
|
562 |
|
popup_dialog => 1,
|
563 |
|
popup_js_close_function => 'kivi.Order.close_periodic_invoices_config_dialog()',
|
564 |
|
popup_js_assign_function => 'kivi.Order.assign_periodic_invoices_config()',
|
565 |
|
config => $config,
|
566 |
|
%$::form);
|
567 |
|
}
|
568 |
|
|
569 |
|
# assign the values of the periodic invoices config dialog
|
570 |
|
# as yaml in the hidden tag and set the status.
|
571 |
|
sub action_assign_periodic_invoices_config {
|
572 |
|
my ($self) = @_;
|
573 |
|
|
574 |
|
$::form->isblank('start_date_as_date', $::locale->text('The start date is missing.'));
|
575 |
|
|
576 |
|
my $config = { active => $::form->{active} ? 1 : 0,
|
577 |
|
terminated => $::form->{terminated} ? 1 : 0,
|
578 |
|
direct_debit => $::form->{direct_debit} ? 1 : 0,
|
579 |
|
periodicity => (any { $_ eq $::form->{periodicity} } @SL::DB::PeriodicInvoicesConfig::PERIODICITIES) ? $::form->{periodicity} : 'm',
|
580 |
|
order_value_periodicity => (any { $_ eq $::form->{order_value_periodicity} } ('p', @SL::DB::PeriodicInvoicesConfig::ORDER_VALUE_PERIODICITIES)) ? $::form->{order_value_periodicity} : 'p',
|
581 |
|
start_date_as_date => $::form->{start_date_as_date},
|
582 |
|
end_date_as_date => $::form->{end_date_as_date},
|
583 |
|
first_billing_date_as_date => $::form->{first_billing_date_as_date},
|
584 |
|
print => $::form->{print} ? 1 : 0,
|
585 |
|
printer_id => $::form->{print} ? $::form->{printer_id} * 1 : undef,
|
586 |
|
copies => $::form->{copies} * 1 ? $::form->{copies} : 1,
|
587 |
|
extend_automatically_by => $::form->{extend_automatically_by} * 1 || undef,
|
588 |
|
ar_chart_id => $::form->{ar_chart_id} * 1,
|
589 |
|
send_email => $::form->{send_email} ? 1 : 0,
|
590 |
|
email_recipient_contact_id => $::form->{email_recipient_contact_id} * 1 || undef,
|
591 |
|
email_recipient_address => $::form->{email_recipient_address},
|
592 |
|
email_sender => $::form->{email_sender},
|
593 |
|
email_subject => $::form->{email_subject},
|
594 |
|
email_body => $::form->{email_body},
|
595 |
|
};
|
596 |
|
|
597 |
|
my $periodic_invoices_config = SL::YAML::Dump($config);
|
598 |
|
|
599 |
|
my $status = $self->get_periodic_invoices_status($config);
|
600 |
|
|
601 |
|
$self->js
|
602 |
|
->remove('#order_periodic_invoices_config')
|
603 |
|
->insertAfter(hidden_tag('order.periodic_invoices_config', $periodic_invoices_config), '#periodic_invoices_status')
|
604 |
|
->run('kivi.Order.close_periodic_invoices_config_dialog')
|
605 |
|
->html('#periodic_invoices_status', $status)
|
606 |
|
->flash('info', t8('The periodic invoices config has been assigned.'))
|
607 |
|
->render($self);
|
608 |
|
}
|
609 |
|
|
610 |
|
sub action_get_has_active_periodic_invoices {
|
611 |
|
my ($self) = @_;
|
612 |
|
|
613 |
|
my $config = make_periodic_invoices_config_from_yaml(delete $::form->{config});
|
614 |
|
$config ||= SL::DB::Manager::PeriodicInvoicesConfig->find_by(oe_id => $::form->{id}) if $::form->{id};
|
615 |
|
|
616 |
|
my $has_active_periodic_invoices =
|
617 |
|
$self->type eq sales_order_type()
|
618 |
|
&& $config
|
619 |
|
&& $config->active
|
620 |
|
&& (!$config->end_date || ($config->end_date > DateTime->today_local))
|
621 |
|
&& $config->get_previous_billed_period_start_date;
|
622 |
|
|
623 |
|
$_[0]->render(\ !!$has_active_periodic_invoices, { type => 'text' });
|
624 |
|
}
|
625 |
522 |
|
626 |
523 |
# save the order and redirect to the frontend subroutine for a new
|
627 |
524 |
# delivery order
|
... | ... | |
713 |
610 |
->val( '#order_intnotes', $self->order->intnotes)
|
714 |
611 |
->val( '#order_language_id', $self->order->$cv_method->language_id)
|
715 |
612 |
->focus( '#order_' . $self->cv . '_id')
|
716 |
|
->run('kivi.Order.update_exchangerate');
|
|
613 |
->run('kivi.DeliveryOrder.update_exchangerate');
|
717 |
614 |
|
718 |
615 |
$self->js_redisplay_amounts_and_taxes;
|
719 |
616 |
$self->js_redisplay_cvpartnumbers;
|
... | ... | |
767 |
664 |
$self->recalc();
|
768 |
665 |
|
769 |
666 |
$self->js
|
770 |
|
->run('kivi.Order.update_sellprice', $::form->{item_id}, $item->sellprice_as_number);
|
|
667 |
->run('kivi.DeliveryOrder.update_sellprice', $::form->{item_id}, $item->sellprice_as_number);
|
771 |
668 |
$self->js_redisplay_line_values;
|
772 |
669 |
$self->js_redisplay_amounts_and_taxes;
|
773 |
670 |
$self->js->render();
|
... | ... | |
790 |
687 |
$self->get_item_cvpartnumber($item);
|
791 |
688 |
|
792 |
689 |
my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
|
793 |
|
my $row_as_html = $self->p->render('order/tabs/_row',
|
|
690 |
my $row_as_html = $self->p->render('delivery_order/tabs/_row',
|
794 |
691 |
ITEM => $item,
|
795 |
692 |
ID => $item_id,
|
796 |
693 |
SELF => $self,
|
... | ... | |
821 |
718 |
$self->recalc();
|
822 |
719 |
$self->get_item_cvpartnumber($item);
|
823 |
720 |
my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
|
824 |
|
my $row_as_html = $self->p->render('order/tabs/_row',
|
|
721 |
my $row_as_html = $self->p->render('delivery_order/tabs/_row',
|
825 |
722 |
ITEM => $item,
|
826 |
723 |
ID => $item_id,
|
827 |
724 |
SELF => $self,
|
... | ... | |
838 |
735 |
|
839 |
736 |
$self->js
|
840 |
737 |
->val('.add_item_input', '')
|
841 |
|
->run('kivi.Order.init_row_handlers')
|
842 |
|
->run('kivi.Order.renumber_positions')
|
|
738 |
->run('kivi.DeliveryOrder.init_row_handlers')
|
|
739 |
->run('kivi.DeliveryOrder.renumber_positions')
|
843 |
740 |
->focus('#add_item_parts_id_name');
|
844 |
741 |
|
845 |
|
$self->js->run('kivi.Order.row_table_scroll_down') if !$::form->{insert_before_item_id};
|
|
742 |
$self->js->run('kivi.DeliveryOrder.row_table_scroll_down') if !$::form->{insert_before_item_id};
|
846 |
743 |
|
847 |
744 |
$self->js_redisplay_amounts_and_taxes;
|
848 |
745 |
$self->js->render();
|
... | ... | |
881 |
778 |
foreach my $item (@items) {
|
882 |
779 |
$self->get_item_cvpartnumber($item);
|
883 |
780 |
my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
|
884 |
|
my $row_as_html = $self->p->render('order/tabs/_row',
|
|
781 |
my $row_as_html = $self->p->render('delivery_order/tabs/_row',
|
885 |
782 |
ITEM => $item,
|
886 |
783 |
ID => $item_id,
|
887 |
784 |
SELF => $self,
|
... | ... | |
898 |
795 |
|
899 |
796 |
$self->js
|
900 |
797 |
->run('kivi.Part.close_picker_dialogs')
|
901 |
|
->run('kivi.Order.init_row_handlers')
|
902 |
|
->run('kivi.Order.renumber_positions')
|
|
798 |
->run('kivi.DeliveryOrder.init_row_handlers')
|
|
799 |
->run('kivi.DeliveryOrder.renumber_positions')
|
903 |
800 |
->focus('#add_item_parts_id_name');
|
904 |
801 |
|
905 |
|
$self->js->run('kivi.Order.row_table_scroll_down') if !$::form->{insert_before_item_id};
|
|
802 |
$self->js->run('kivi.DeliveryOrder.row_table_scroll_down') if !$::form->{insert_before_item_id};
|
906 |
803 |
|
907 |
804 |
$self->js_redisplay_amounts_and_taxes;
|
908 |
805 |
$self->js->render();
|
... | ... | |
962 |
859 |
}
|
963 |
860 |
}
|
964 |
861 |
$self->js
|
965 |
|
->run('kivi.Order.redisplay_items', \@to_sort)
|
|
862 |
->run('kivi.DeliveryOrder.redisplay_items', \@to_sort)
|
966 |
863 |
->render;
|
967 |
864 |
}
|
968 |
865 |
|
... | ... | |
992 |
889 |
$self->js_load_second_row($item, $item_id, 0);
|
993 |
890 |
}
|
994 |
891 |
|
995 |
|
$self->js->run('kivi.Order.init_row_handlers') if $self->order->is_sales; # for lastcosts change-callback
|
|
892 |
$self->js->run('kivi.DeliveryOrder.init_row_handlers') if $self->order->is_sales; # for lastcosts change-callback
|
996 |
893 |
|
997 |
894 |
$self->js->render();
|
998 |
895 |
}
|
... | ... | |
1029 |
926 |
$item->active_price_source($price_src);
|
1030 |
927 |
|
1031 |
928 |
$self->js
|
1032 |
|
->run('kivi.Order.update_sellprice', $item_id, $item->sellprice_as_number)
|
|
929 |
->run('kivi.DeliveryOrder.update_sellprice', $item_id, $item->sellprice_as_number)
|
1033 |
930 |
->html('.row_entry:has(#item_' . $item_id . ') [name = "partnumber"] a', $item->part->partnumber)
|
1034 |
931 |
->val ('.row_entry:has(#item_' . $item_id . ') [name = "order.orderitems[].description"]', $item->description)
|
1035 |
932 |
->val ('.row_entry:has(#item_' . $item_id . ') [name = "order.orderitems[].longdescription"]', $item->longdescription);
|
... | ... | |
1060 |
957 |
$item->parse_custom_variable_values;
|
1061 |
958 |
}
|
1062 |
959 |
|
1063 |
|
my $row_as_html = $self->p->render('order/tabs/_second_row', ITEM => $item, TYPE => $self->type);
|
|
960 |
my $row_as_html = $self->p->render('delivery_order/tabs/_second_row', ITEM => $item, TYPE => $self->type);
|
1064 |
961 |
|
1065 |
962 |
$self->js
|
1066 |
963 |
->html('#second_row_' . $item_id, $row_as_html)
|
... | ... | |
1089 |
986 |
}
|
1090 |
987 |
|
1091 |
988 |
$self->js
|
1092 |
|
->run('kivi.Order.redisplay_line_values', $is_sales, \@data);
|
|
989 |
->run('kivi.DeliveryOrder.redisplay_line_values', $is_sales, \@data);
|
1093 |
990 |
}
|
1094 |
991 |
|
1095 |
992 |
sub js_redisplay_amounts_and_taxes {
|
... | ... | |
1135 |
1032 |
my @data = map {[$_->{cvpartnumber}]} @{ $self->order->items_sorted };
|
1136 |
1033 |
|
1137 |
1034 |
$self->js
|
1138 |
|
->run('kivi.Order.redisplay_cvpartnumbers', \@data);
|
|
1035 |
->run('kivi.DeliveryOrder.redisplay_cvpartnumbers', \@data);
|
1139 |
1036 |
}
|
1140 |
1037 |
|
1141 |
1038 |
sub js_reset_order_and_item_ids_after_save {
|
... | ... | |
1165 |
1062 |
#
|
1166 |
1063 |
|
1167 |
1064 |
sub init_valid_types {
|
1168 |
|
[ sales_order_type(), purchase_order_type(), sales_quotation_type(), request_quotation_type() ];
|
|
1065 |
[ customer_in_type(), customer_out_type(), vendor_in_type(), vendor_out_type() ];
|
1169 |
1066 |
}
|
1170 |
1067 |
|
1171 |
1068 |
sub init_type {
|
... | ... | |
1181 |
1078 |
sub init_cv {
|
1182 |
1079 |
my ($self) = @_;
|
1183 |
1080 |
|
1184 |
|
my $cv = (any { $self->type eq $_ } (sales_order_type(), sales_quotation_type())) ? 'customer'
|
1185 |
|
: (any { $self->type eq $_ } (purchase_order_type(), request_quotation_type())) ? 'vendor'
|
|
1081 |
my $cv = (any { $self->type eq $_ } (customer_in_type(), vendor_in_type())) ? 'customer'
|
|
1082 |
: (any { $self->type eq $_ } (customer_out_type(), vendor_out_type())) ? 'vendor'
|
1186 |
1083 |
: die "Not a valid type for order";
|
1187 |
1084 |
|
1188 |
1085 |
return $cv;
|
... | ... | |
1227 |
1124 |
sub check_auth {
|
1228 |
1125 |
my ($self) = @_;
|
1229 |
1126 |
|
1230 |
|
my $right_for = { map { $_ => $_.'_edit' } @{$self->valid_types} };
|
1231 |
|
|
1232 |
|
my $right = $right_for->{ $self->type };
|
|
1127 |
my $right = $self->type =~ /customer/ ? 'sales_delivery_order_edit' : 'purchase_delivery_order_edit';
|
1233 |
1128 |
$right ||= 'DOES_NOT_EXIST';
|
1234 |
1129 |
|
1235 |
1130 |
$::auth->assert($right);
|
... | ... | |
1286 |
1181 |
# Needed, if customer/vendor changed.
|
1287 |
1182 |
sub build_business_info_row
|
1288 |
1183 |
{
|
1289 |
|
$_[0]->p->render('order/tabs/_business_info_row', SELF => $_[0]);
|
|
1184 |
$_[0]->p->render('delivery_order/tabs/_business_info_row', SELF => $_[0]);
|
1290 |
1185 |
}
|
1291 |
1186 |
|
1292 |
1187 |
# build the rows for displaying taxes
|
... | ... | |
1312 |
1207 |
->run(
|
1313 |
1208 |
'kivi.io.price_chooser_dialog',
|
1314 |
1209 |
t8('Available Prices'),
|
1315 |
|
$self->render('order/tabs/_price_sources_dialog', { output => 0 }, price_source => $price_source)
|
|
1210 |
$self->render('delivery_order/tabs/_price_sources_dialog', { output => 0 }, price_source => $price_source)
|
1316 |
1211 |
)
|
1317 |
1212 |
->reinit_widgets;
|
1318 |
1213 |
|
... | ... | |
1329 |
1224 |
|
1330 |
1225 |
return if !$::form->{id};
|
1331 |
1226 |
|
1332 |
|
$self->order(SL::DB::Order->new(id => $::form->{id})->load);
|
|
1227 |
$self->order(SL::DB::DeliveryOrder->new(id => $::form->{id})->load);
|
1333 |
1228 |
|
1334 |
1229 |
# Add an empty custom shipto to the order, so that the dialog can render the cvar inputs.
|
1335 |
1230 |
# You need a custom shipto object to call cvars_by_config to get the cvars.
|
1336 |
|
$self->order->custom_shipto(SL::DB::Shipto->new(module => 'OE', custom_variables => [])) if !$self->order->custom_shipto;
|
|
1231 |
$self->order->custom_shipto(SL::DB::Shipto->new(module => 'DO', custom_variables => [])) if !$self->order->custom_shipto;
|
1337 |
1232 |
|
1338 |
1233 |
return $self->order;
|
1339 |
1234 |
}
|
... | ... | |
1351 |
1246 |
# be retrieved via items until the order is saved. Adding empty items to new
|
1352 |
1247 |
# order here solves this problem.
|
1353 |
1248 |
my $order;
|
1354 |
|
$order = SL::DB::Order->new(id => $::form->{id})->load(with => [ 'orderitems', 'orderitems.part' ]) if $::form->{id};
|
1355 |
|
$order ||= SL::DB::Order->new(orderitems => [],
|
1356 |
|
quotation => (any { $self->type eq $_ } (sales_quotation_type(), request_quotation_type())),
|
|
1249 |
$order = SL::DB::DeliveryOrder->new(id => $::form->{id})->load(with => [ 'orderitems', 'orderitems.part' ]) if $::form->{id};
|
|
1250 |
$order ||= SL::DB::DeliveryOrder->new(orderitems => [],
|
|
1251 |
quotation => (any { $self->type eq $_ } (vendor_in_type(), vendor_out_type())),
|
1357 |
1252 |
currency_id => $::instance_conf->get_currency_id(),);
|
1358 |
1253 |
|
1359 |
1254 |
my $cv_id_method = $self->cv . '_id';
|
... | ... | |
1363 |
1258 |
}
|
1364 |
1259 |
|
1365 |
1260 |
my $form_orderitems = delete $::form->{order}->{orderitems};
|
1366 |
|
my $form_periodic_invoices_config = delete $::form->{order}->{periodic_invoices_config};
|
1367 |
1261 |
|
1368 |
1262 |
$order->assign_attributes(%{$::form->{order}});
|
1369 |
1263 |
|
1370 |
1264 |
$self->setup_custom_shipto_from_form($order, $::form);
|
1371 |
1265 |
|
1372 |
|
if (my $periodic_invoices_config_attrs = $form_periodic_invoices_config ? SL::YAML::Load($form_periodic_invoices_config) : undef) {
|
1373 |
|
my $periodic_invoices_config = $order->periodic_invoices_config || $order->periodic_invoices_config(SL::DB::PeriodicInvoicesConfig->new);
|
1374 |
|
$periodic_invoices_config->assign_attributes(%$periodic_invoices_config_attrs);
|
1375 |
|
}
|
1376 |
|
|
1377 |
1266 |
# remove deleted items
|
1378 |
1267 |
$self->item_ids_to_delete([]);
|
1379 |
1268 |
foreach my $idx (reverse 0..$#{$order->orderitems}) {
|
... | ... | |
1412 |
1301 |
# add_custom_variables adds cvars to an orderitem with no cvars for saving, but
|
1413 |
1302 |
# they cannot be retrieved via custom_variables until the order/orderitem is
|
1414 |
1303 |
# saved. Adding empty custom_variables to new orderitem here solves this problem.
|
1415 |
|
$item ||= SL::DB::OrderItem->new(custom_variables => []);
|
|
1304 |
$item ||= SL::DB::DeliveryOrderItem->new(custom_variables => []);
|
1416 |
1305 |
|
1417 |
1306 |
$item->assign_attributes(%$attr);
|
1418 |
1307 |
|
... | ... | |
1432 |
1321 |
sub new_item {
|
1433 |
1322 |
my ($record, $attr) = @_;
|
1434 |
1323 |
|
1435 |
|
my $item = SL::DB::OrderItem->new;
|
|
1324 |
my $item = SL::DB::DeliveryOrderItem->new;
|
1436 |
1325 |
|
1437 |
1326 |
# Remove attributes where the user left or set the inputs empty.
|
1438 |
1327 |
# So these attributes will be undefined and we can distinguish them
|
... | ... | |
1546 |
1435 |
sub recalc {
|
1547 |
1436 |
my ($self) = @_;
|
1548 |
1437 |
|
1549 |
|
my %pat = $self->order->calculate_prices_and_taxes();
|
1550 |
|
|
1551 |
|
$self->{taxes} = [];
|
1552 |
|
foreach my $tax_id (keys %{ $pat{taxes_by_tax_id} }) {
|
1553 |
|
my $netamount = sum0 map { $pat{amounts}->{$_}->{amount} } grep { $pat{amounts}->{$_}->{tax_id} == $tax_id } keys %{ $pat{amounts} };
|
1554 |
|
|
1555 |
|
push(@{ $self->{taxes} }, { amount => $pat{taxes_by_tax_id}->{$tax_id},
|
1556 |
|
netamount => $netamount,
|
1557 |
|
tax => SL::DB::Tax->new(id => $tax_id)->load });
|
1558 |
|
}
|
1559 |
|
pairwise { $a->{linetotal} = $b->{linetotal} } @{$self->order->items_sorted}, @{$pat{items}};
|
|
1438 |
# nothing to do here
|
1560 |
1439 |
}
|
1561 |
1440 |
|
1562 |
1441 |
# get data for saving, printing, ..., that is not changed in the form
|
... | ... | |
1615 |
1494 |
$self->order->custom_shipto(undef);
|
1616 |
1495 |
}
|
1617 |
1496 |
|
1618 |
|
SL::DB::OrderItem->new(id => $_)->delete for @{$self->item_ids_to_delete || []};
|
|
1497 |
SL::DB::DeliveryOrderItem->new(id => $_)->delete for @{$self->item_ids_to_delete || []};
|
1619 |
1498 |
$self->order->save(cascade => 1);
|
1620 |
1499 |
|
1621 |
1500 |
# link records
|
1622 |
1501 |
if ($::form->{converted_from_oe_id}) {
|
1623 |
1502 |
my @converted_from_oe_ids = split ' ', $::form->{converted_from_oe_id};
|
1624 |
1503 |
foreach my $converted_from_oe_id (@converted_from_oe_ids) {
|
1625 |
|
my $src = SL::DB::Order->new(id => $converted_from_oe_id)->load;
|
|
1504 |
my $src = SL::DB::DeliveryOrder->new(id => $converted_from_oe_id)->load;
|
1626 |
1505 |
$src->update_attributes(closed => 1) if $src->type =~ /_quotation$/;
|
1627 |
1506 |
$src->link_to_record($self->order);
|
1628 |
1507 |
}
|
... | ... | |
1631 |
1510 |
foreach (@{ $self->order->items_sorted }) {
|
1632 |
1511 |
my $from_id = $::form->{converted_from_orderitems_ids}->[$idx];
|
1633 |
1512 |
next if !$from_id;
|
1634 |
|
SL::DB::RecordLink->new(from_table => 'orderitems',
|
|
1513 |
SL::DB::RecordLink->new(from_table => 'delivery_order_items',
|
1635 |
1514 |
from_id => $from_id,
|
1636 |
|
to_table => 'orderitems',
|
|
1515 |
to_table => 'delivery_order_items',
|
1637 |
1516 |
to_id => $_->id
|
1638 |
1517 |
)->save;
|
1639 |
1518 |
$idx++;
|
... | ... | |
1660 |
1539 |
return $self->js->render();
|
1661 |
1540 |
}
|
1662 |
1541 |
|
1663 |
|
my $destination_type = $::form->{type} eq sales_order_type() ? sales_quotation_type() : request_quotation_type();
|
|
1542 |
my $destination_type = $::form->{type} eq customer_in_type() ? vendor_in_type() : vendor_out_type();
|
1664 |
1543 |
|
1665 |
|
$self->order(SL::DB::Order->new_from($self->order, destination_type => $destination_type));
|
|
1544 |
$self->order(SL::DB::DeliveryOrder->new_from($self->order, destination_type => $destination_type));
|
1666 |
1545 |
$self->{converted_from_oe_id} = delete $::form->{id};
|
1667 |
1546 |
|
1668 |
1547 |
# set item ids to new fake id, to identify them as new items
|
... | ... | |
1686 |
1565 |
$_->{render_second_row} = 1 for @{ $self->order->items_sorted };
|
1687 |
1566 |
|
1688 |
1567 |
$self->render(
|
1689 |
|
'order/form',
|
|
1568 |
'delivery_order/form',
|
1690 |
1569 |
title => $self->get_title_for('edit'),
|
1691 |
1570 |
%{$self->{template_args}}
|
1692 |
1571 |
);
|
... | ... | |
1703 |
1582 |
return $self->js->render();
|
1704 |
1583 |
}
|
1705 |
1584 |
|
1706 |
|
my $destination_type = $::form->{type} eq sales_quotation_type() ? sales_order_type()
|
1707 |
|
: $::form->{type} eq request_quotation_type() ? purchase_order_type()
|
1708 |
|
: $::form->{type} eq purchase_order_type() ? sales_order_type()
|
1709 |
|
: $::form->{type} eq sales_order_type() ? purchase_order_type()
|
|
1585 |
my $destination_type = $::form->{type} eq vendor_in_type() ? customer_in_type()
|
|
1586 |
: $::form->{type} eq vendor_out_type() ? customer_out_type()
|
|
1587 |
: $::form->{type} eq customer_out_type() ? customer_in_type()
|
|
1588 |
: $::form->{type} eq customer_in_type() ? customer_out_type()
|
1710 |
1589 |
: '';
|
1711 |
1590 |
|
1712 |
1591 |
# check for direct delivery
|
1713 |
1592 |
# copy shipto in custom shipto (custom shipto will be copied by new_from() in case)
|
1714 |
1593 |
my $custom_shipto;
|
1715 |
|
if ( $::form->{type} eq sales_order_type() && $destination_type eq purchase_order_type()
|
|
1594 |
if ( $::form->{type} eq customer_in_type() && $destination_type eq customer_out_type()
|
1716 |
1595 |
&& $::form->{use_shipto} && $self->order->shipto) {
|
1717 |
|
$custom_shipto = $self->order->shipto->clone('SL::DB::Order');
|
|
1596 |
$custom_shipto = $self->order->shipto->clone('SL::DB::DeliveryOrder');
|
1718 |
1597 |
}
|
1719 |
1598 |
|
1720 |
|
$self->order(SL::DB::Order->new_from($self->order, destination_type => $destination_type));
|
|
1599 |
$self->order(SL::DB::DeliveryOrder->new_from($self->order, destination_type => $destination_type));
|
1721 |
1600 |
$self->{converted_from_oe_id} = delete $::form->{id};
|
1722 |
1601 |
|
1723 |
1602 |
# set item ids to new fake id, to identify them as new items
|
... | ... | |
1725 |
1604 |
$item->{new_fake_id} = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
|
1726 |
1605 |
}
|
1727 |
1606 |
|
1728 |
|
if ($::form->{type} eq sales_order_type() && $destination_type eq purchase_order_type()) {
|
|
1607 |
if ($::form->{type} eq customer_in_type() && $destination_type eq customer_out_type()) {
|
1729 |
1608 |
if ($::form->{use_shipto}) {
|
1730 |
1609 |
$self->order->custom_shipto($custom_shipto) if $custom_shipto;
|
1731 |
1610 |
} else {
|
... | ... | |
1750 |
1629 |
$_->{render_second_row} = 1 for @{ $self->order->items_sorted };
|
1751 |
1630 |
|
1752 |
1631 |
$self->render(
|
1753 |
|
'order/form',
|
|
1632 |
'delivery_order/form',
|
1754 |
1633 |
title => $self->get_title_for('edit'),
|
1755 |
1634 |
%{$self->{template_args}}
|
1756 |
1635 |
);
|
... | ... | |
1774 |
1653 |
obsolete => 0 ] ]);
|
1775 |
1654 |
$self->{all_delivery_terms} = SL::DB::Manager::DeliveryTerm->get_all_sorted();
|
1776 |
1655 |
$self->{current_employee_id} = SL::DB::Manager::Employee->current->id;
|
1777 |
|
$self->{periodic_invoices_status} = $self->get_periodic_invoices_status($self->order->periodic_invoices_config);
|
1778 |
1656 |
$self->{order_probabilities} = [ map { { title => ($_ * 10) . '%', id => $_ * 10 } } (0..10) ];
|
1779 |
1657 |
$self->{positions_scrollbar_height} = SL::Helper::UserPreferences::PositionsScrollbar->new()->get_height();
|
1780 |
1658 |
|
... | ... | |
1797 |
1675 |
$item->active_discount_source($price_source->discount_from_source($item->active_discount_source));
|
1798 |
1676 |
}
|
1799 |
1677 |
|
1800 |
|
if (any { $self->type eq $_ } (sales_order_type(), purchase_order_type())) {
|
1801 |
|
# Calculate shipped qtys here to prevent calling calculate for every item via the items method.
|
1802 |
|
# Do not use write_to_objects to prevent order->delivered to be set, because this should be
|
1803 |
|
# the value from db, which can be set manually or is set when linked delivery orders are saved.
|
1804 |
|
SL::Helper::ShippedQty->new->calculate($self->order)->write_to(\@{$self->order->items});
|
1805 |
|
}
|
1806 |
|
|
1807 |
1678 |
if ($self->order->number && $::instance_conf->get_webdav) {
|
1808 |
1679 |
my $webdav = SL::Webdav->new(
|
1809 |
1680 |
type => $self->type,
|
... | ... | |
1818 |
1689 |
|
1819 |
1690 |
$self->get_item_cvpartnumber($_) for @{$self->order->items_sorted};
|
1820 |
1691 |
|
1821 |
|
$::request->{layout}->use_javascript("${_}.js") for qw(kivi.SalesPurchase kivi.Order kivi.File ckeditor/ckeditor ckeditor/adapters/jquery
|
1822 |
|
edit_periodic_invoices_config calculate_qty kivi.Validator follow_up show_history);
|
|
1692 |
$::request->{layout}->use_javascript("${_}.js") for qw(kivi.SalesPurchase kivi.DeliveryOrder kivi.File ckeditor/ckeditor ckeditor/adapters/jquery
|
|
1693 |
calculate_qty kivi.Validator follow_up show_history);
|
1823 |
1694 |
$self->setup_edit_action_bar;
|
1824 |
1695 |
}
|
1825 |
1696 |
|
1826 |
1697 |
sub setup_edit_action_bar {
|
1827 |
1698 |
my ($self, %params) = @_;
|
1828 |
1699 |
|
1829 |
|
my $deletion_allowed = (any { $self->type eq $_ } (sales_quotation_type(), request_quotation_type()))
|
1830 |
|
|| (($self->type eq sales_order_type()) && $::instance_conf->get_sales_order_show_delete)
|
1831 |
|
|| (($self->type eq purchase_order_type()) && $::instance_conf->get_purchase_order_show_delete);
|
|
1700 |
my $deletion_allowed = (any { $self->type eq $_ } (vendor_in_type(), vendor_out_type()))
|
|
1701 |
|| (($self->type eq customer_in_type()) && $::instance_conf->get_sales_order_show_delete)
|
|
1702 |
|| (($self->type eq customer_out_type()) && $::instance_conf->get_purchase_order_show_delete);
|
1832 |
1703 |
|
1833 |
1704 |
for my $bar ($::request->layout->get('actionbar')) {
|
1834 |
1705 |
$bar->add(
|
1835 |
1706 |
combobox => [
|
1836 |
1707 |
action => [
|
1837 |
1708 |
t8('Save'),
|
1838 |
|
call => [ 'kivi.Order.save', 'save', $::instance_conf->get_order_warn_duplicate_parts,
|
|
1709 |
call => [ 'kivi.DeliveryOrder.save', 'save', $::instance_conf->get_order_warn_duplicate_parts,
|
1839 |
1710 |
$::instance_conf->get_order_warn_no_deliverydate,
|
1840 |
1711 |
],
|
1841 |
|
checks => [ 'kivi.Order.check_save_active_periodic_invoices', ['kivi.validate_form','#order_form'] ],
|
|
1712 |
checks => [ ['kivi.validate_form','#order_form'] ],
|
1842 |
1713 |
],
|
1843 |
1714 |
action => [
|
1844 |
1715 |
t8('Save as new'),
|
1845 |
|
call => [ 'kivi.Order.save', 'save_as_new', $::instance_conf->get_order_warn_duplicate_parts ],
|
1846 |
|
checks => [ 'kivi.Order.check_save_active_periodic_invoices' ],
|
|
1716 |
call => [ 'kivi.DeliveryOrder.save', 'save_as_new', $::instance_conf->get_order_warn_duplicate_parts ],
|
1847 |
1717 |
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
|
1848 |
1718 |
],
|
1849 |
1719 |
], # end of combobox "Save"
|
... | ... | |
1854 |
1724 |
],
|
1855 |
1725 |
action => [
|
1856 |
1726 |
t8('Save and Quotation'),
|
1857 |
|
submit => [ '#order_form', { action => "Order/sales_quotation" } ],
|
1858 |
|
only_if => (any { $self->type eq $_ } (sales_order_type())),
|
|
1727 |
submit => [ '#order_form', { action => "DeliveryOrder/sales_quotation" } ],
|
|
1728 |
only_if => (any { $self->type eq $_ } (customer_in_type())),
|
1859 |
1729 |
],
|
1860 |
1730 |
action => [
|
1861 |
1731 |
t8('Save and RFQ'),
|
1862 |
|
submit => [ '#order_form', { action => "Order/request_for_quotation" } ],
|
1863 |
|
only_if => (any { $self->type eq $_ } (purchase_order_type())),
|
|
1732 |
submit => [ '#order_form', { action => "DeliveryOrder/request_for_quotation" } ],
|
|
1733 |
only_if => (any { $self->type eq $_ } (customer_out_type())),
|
1864 |
1734 |
],
|
1865 |
1735 |
action => [
|
1866 |
1736 |
t8('Save and Sales Order'),
|
1867 |
|
submit => [ '#order_form', { action => "Order/sales_order" } ],
|
1868 |
|
only_if => (any { $self->type eq $_ } (sales_quotation_type(), purchase_order_type())),
|
|
1737 |
submit => [ '#order_form', { action => "DeliveryOrder/sales_order" } ],
|
|
1738 |
only_if => (any { $self->type eq $_ } (vendor_in_type(), customer_out_type())),
|
1869 |
1739 |
],
|
1870 |
1740 |
action => [
|
1871 |
1741 |
t8('Save and Purchase Order'),
|
1872 |
|
call => [ 'kivi.Order.purchase_order_check_for_direct_delivery' ],
|
1873 |
|
only_if => (any { $self->type eq $_ } (sales_order_type(), request_quotation_type())),
|
|
1742 |
call => [ 'kivi.DeliveryOrder.purchase_order_check_for_direct_delivery' ],
|
|
1743 |
only_if => (any { $self->type eq $_ } (customer_in_type(), vendor_out_type())),
|
1874 |
1744 |
],
|
1875 |
1745 |
action => [
|
1876 |
1746 |
t8('Save and Delivery Order'),
|
1877 |
|
call => [ 'kivi.Order.save', 'save_and_delivery_order', $::instance_conf->get_order_warn_duplicate_parts,
|
|
1747 |
call => [ 'kivi.DeliveryOrder.save', 'save_and_delivery_order', $::instance_conf->get_order_warn_duplicate_parts,
|
1878 |
1748 |
$::instance_conf->get_order_warn_no_deliverydate,
|
1879 |
1749 |
],
|
1880 |
|
checks => [ 'kivi.Order.check_save_active_periodic_invoices' ],
|
1881 |
|
only_if => (any { $self->type eq $_ } (sales_order_type(), purchase_order_type()))
|
|
1750 |
only_if => (any { $self->type eq $_ } (customer_in_type(), customer_out_type()))
|
1882 |
1751 |
],
|
1883 |
1752 |
action => [
|
1884 |
1753 |
t8('Save and Invoice'),
|
1885 |
|
call => [ 'kivi.Order.save', 'save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ],
|
1886 |
|
checks => [ 'kivi.Order.check_save_active_periodic_invoices' ],
|
|
1754 |
call => [ 'kivi.DeliveryOrder.save', 'save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ],
|
1887 |
1755 |
],
|
1888 |
1756 |
action => [
|
1889 |
1757 |
t8('Save and AP Transaction'),
|
1890 |
|
call => [ 'kivi.Order.save', 'save_and_ap_transaction', $::instance_conf->get_order_warn_duplicate_parts ],
|
1891 |
|
only_if => (any { $self->type eq $_ } (purchase_order_type()))
|
|
1758 |
call => [ 'kivi.DeliveryOrder.save', 'save_and_ap_transaction', $::instance_conf->get_order_warn_duplicate_parts ],
|
|
1759 |
only_if => (any { $self->type eq $_ } (customer_out_type()))
|
1892 |
1760 |
],
|
1893 |
1761 |
|
1894 |
1762 |
], # end of combobox "Workflow"
|
... | ... | |
1899 |
1767 |
],
|
1900 |
1768 |
action => [
|
1901 |
1769 |
t8('Save and preview PDF'),
|
1902 |
|
call => [ 'kivi.Order.save', 'preview_pdf', $::instance_conf->get_order_warn_duplicate_parts,
|
|
1770 |
call => [ 'kivi.DeliveryOrder.save', 'preview_pdf', $::instance_conf->get_order_warn_duplicate_parts,
|
1903 |
1771 |
$::instance_conf->get_order_warn_no_deliverydate,
|
1904 |
1772 |
],
|
1905 |
1773 |
],
|
1906 |
1774 |
action => [
|
1907 |
1775 |
t8('Save and print'),
|
1908 |
|
call => [ 'kivi.Order.show_print_options', $::instance_conf->get_order_warn_duplicate_parts,
|
|
1776 |
call => [ 'kivi.DeliveryOrder.show_print_options', $::instance_conf->get_order_warn_duplicate_parts,
|
1909 |
1777 |
$::instance_conf->get_order_warn_no_deliverydate,
|
1910 |
1778 |
],
|
1911 |
1779 |
],
|
1912 |
1780 |
action => [
|
1913 |
1781 |
t8('Save and E-mail'),
|
1914 |
1782 |
id => 'save_and_email_action',
|
1915 |
|
call => [ 'kivi.Order.save', 'save_and_show_email_dialog', $::instance_conf->get_order_warn_duplicate_parts,
|
|
1783 |
call => [ 'kivi.DeliveryOrder.save', 'save_and_show_email_dialog', $::instance_conf->get_order_warn_duplicate_parts,
|
1916 |
1784 |
$::instance_conf->get_order_warn_no_deliverydate,
|
1917 |
1785 |
],
|
1918 |
1786 |
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
|
... | ... | |
1927 |
1795 |
|
1928 |
1796 |
action => [
|
1929 |
1797 |
t8('Delete'),
|
1930 |
|
call => [ 'kivi.Order.delete_order' ],
|
|
1798 |
call => [ 'kivi.DeliveryOrder.delete_order' ],
|
1931 |
1799 |
confirm => $::locale->text('Do you really want to delete this object?'),
|
1932 |
1800 |
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
|
1933 |
1801 |
only_if => $deletion_allowed,
|
... | ... | |
1939 |
1807 |
],
|
1940 |
1808 |
action => [
|
1941 |
1809 |
t8('Follow-Up'),
|
1942 |
|
call => [ 'kivi.Order.follow_up_window' ],
|
|
1810 |
call => [ 'kivi.DeliveryOrder.follow_up_window' ],
|
1943 |
1811 |
disabled => !$self->order->id ? t8('This object has not been saved yet.') : undef,
|
1944 |
1812 |
only_if => $::auth->assert('productivity', 1),
|
1945 |
1813 |
],
|
... | ... | |
2047 |
1915 |
return %files;
|
2048 |
1916 |
}
|
2049 |
1917 |
|
2050 |
|
sub make_periodic_invoices_config_from_yaml {
|
2051 |
|
my ($yaml_config) = @_;
|
2052 |
|
|
2053 |
|
return if !$yaml_config;
|
2054 |
|
my $attr = SL::YAML::Load($yaml_config);
|
2055 |
|
return if 'HASH' ne ref $attr;
|
2056 |
|
return SL::DB::PeriodicInvoicesConfig->new(%$attr);
|
2057 |
|
}
|
2058 |
|
|
2059 |
|
|
2060 |
|
sub get_periodic_invoices_status {
|
2061 |
|
my ($self, $config) = @_;
|
2062 |
|
|
2063 |
|
return if $self->type ne sales_order_type();
|
2064 |
|
return t8('not configured') if !$config;
|
2065 |
|
|
2066 |
|
my $active = ('HASH' eq ref $config) ? $config->{active}
|
2067 |
|
: ('SL::DB::PeriodicInvoicesConfig' eq ref $config) ? $config->active
|
2068 |
|
: die "Cannot get status of periodic invoices config";
|
2069 |
|
|
2070 |
|
return $active ? t8('active') : t8('inactive');
|
2071 |
|
}
|
2072 |
1918 |
|
2073 |
1919 |
sub get_title_for {
|
2074 |
1920 |
my ($self, $action) = @_;
|
... | ... | |
2076 |
1922 |
return '' if none { lc($action)} qw(add edit);
|
2077 |
1923 |
|
2078 |
1924 |
# for locales:
|
2079 |
|
# $::locale->text("Add Sales Order");
|
2080 |
|
# $::locale->text("Add Purchase Order");
|
2081 |
|
# $::locale->text("Add Quotation");
|
2082 |
|
# $::locale->text("Add Request for Quotation");
|
2083 |
|
# $::locale->text("Edit Sales Order");
|
2084 |
|
# $::locale->text("Edit Purchase Order");
|
2085 |
|
# $::locale->text("Edit Quotation");
|
2086 |
|
# $::locale->text("Edit Request for Quotation");
|
|
1925 |
# $::locale->text("Add Sales Delivery Order");
|
|
1926 |
# $::locale->text("Add Purchase Delivery Order");
|
|
1927 |
# $::locale->text("Edit Sales Delivery Order");
|
|
1928 |
# $::locale->text("Edit Purchase Delivery Order");
|
2087 |
1929 |
|
2088 |
1930 |
$action = ucfirst(lc($action));
|
2089 |
|
return $self->type eq sales_order_type() ? $::locale->text("$action Sales Order")
|
2090 |
|
: $self->type eq purchase_order_type() ? $::locale->text("$action Purchase Order")
|
2091 |
|
: $self->type eq sales_quotation_type() ? $::locale->text("$action Quotation")
|
2092 |
|
: $self->type eq request_quotation_type() ? $::locale->text("$action Request for Quotation")
|
|
1931 |
return $self->type eq customer_in_type() ? $::locale->text("$action Sales Delivery Order")
|
|
1932 |
: $self->type eq customer_out_type() ? $::locale->text("$action Sales Delivery Order")
|
|
1933 |
: $self->type eq vendor_in_type() ? $::locale->text("$action Purchase Delivery Order")
|
|
1934 |
: $self->type eq vendor_out_type() ? $::locale->text("$action Purchase Delivery Quotation")
|
2093 |
1935 |
: '';
|
2094 |
1936 |
}
|
2095 |
1937 |
|
... | ... | |
2132 |
1974 |
return $texts;
|
2133 |
1975 |
}
|
2134 |
1976 |
|
2135 |
|
sub sales_order_type {
|
2136 |
|
'sales_order';
|
|
1977 |
sub customer_in_type {
|
|
1978 |
'customer_in_delivery_order';
|
2137 |
1979 |
}
|
2138 |
1980 |
|
2139 |
|
sub purchase_order_type {
|
2140 |
|
'purchase_order';
|
|
1981 |
sub customer_out_type {
|
|
1982 |
'customer_out_delivery_order';
|
2141 |
1983 |
}
|
2142 |
1984 |
|
2143 |
|
sub sales_quotation_type {
|
2144 |
|
'sales_quotation';
|
|
1985 |
sub vendor_in_type {
|
|
1986 |
'vendor_in_delivery_order';
|
2145 |
1987 |
}
|
2146 |
1988 |
|
2147 |
|
sub request_quotation_type {
|
2148 |
|
'request_quotation';
|
|
1989 |
sub vendor_out_type {
|
|
1990 |
'vendor_out_delivery_order';
|
2149 |
1991 |
}
|
2150 |
1992 |
|
2151 |
1993 |
sub nr_key {
|
2152 |
|
return $_[0]->type eq sales_order_type() ? 'ordnumber'
|
2153 |
|
: $_[0]->type eq purchase_order_type() ? 'ordnumber'
|
2154 |
|
: $_[0]->type eq sales_quotation_type() ? 'quonumber'
|
2155 |
|
: $_[0]->type eq request_quotation_type() ? 'quonumber'
|
2156 |
|
: '';
|
|
1994 |
'donumber'
|
2157 |
1995 |
}
|
2158 |
1996 |
|
2159 |
1997 |
sub save_and_redirect_to {
|
... | ... | |
2166 |
2004 |
return $self->js->render();
|
2167 |
2005 |
}
|
2168 |
2006 |
|
2169 |
|
my $text = $self->type eq sales_order_type() ? $::locale->text('The order has been saved')
|
2170 |
|
: $self->type eq purchase_order_type() ? $::locale->text('The order has been saved')
|
2171 |
|
: $self->type eq sales_quotation_type() ? $::locale->text('The quotation has been saved')
|
2172 |
|
: $self->type eq request_quotation_type() ? $::locale->text('The rfq has been saved')
|
2173 |
|
: '';
|
|
2007 |
my $text = $::locale->text('The delivery_order has been saved');
|
2174 |
2008 |
flash_later('info', $text);
|
2175 |
2009 |
|
2176 |
2010 |
$self->redirect_to(%params, id => $self->order->id);
|
... | ... | |
2293 |
2127 |
|
2294 |
2128 |
=over 4
|
2295 |
2129 |
|
2296 |
|
=item * C<SL/Controller/Order.pm>
|
|
2130 |
=item * C<SL/Controller/DeliveryOrder.pm>
|
2297 |
2131 |
|
2298 |
2132 |
the controller
|
2299 |
2133 |
|
2300 |
|
=item * C<template/webpages/order/form.html>
|
|
2134 |
=item * C<template/webpages/delivery_order/form.html>
|
2301 |
2135 |
|
2302 |
2136 |
main form
|
2303 |
2137 |
|
2304 |
|
=item * C<template/webpages/order/tabs/basic_data.html>
|
|
2138 |
=item * C<template/webpages/delivery_order/tabs/basic_data.html>
|
2305 |
2139 |
|
2306 |
2140 |
Main tab for basic_data.
|
2307 |
2141 |
|
... | ... | |
2310 |
2144 |
|
2311 |
2145 |
=over 4
|
2312 |
2146 |
|
2313 |
|
=item * C<template/webpages/order/tabs/_business_info_row.html>
|
|
2147 |
=item * C<template/webpages/delivery_order/tabs/_business_info_row.html>
|
2314 |
2148 |
|
2315 |
2149 |
For displaying information on business type
|
2316 |
2150 |
|
2317 |
|
=item * C<template/webpages/order/tabs/_item_input.html>
|
|
2151 |
=item * C<template/webpages/delivery_order/tabs/_item_input.html>
|
2318 |
2152 |
|
2319 |
2153 |
The input line for items
|
2320 |
2154 |
|
2321 |
|
=item * C<template/webpages/order/tabs/_row.html>
|
|
2155 |
=item * C<template/webpages/delivery_order/tabs/_row.html>
|
2322 |
2156 |
|
2323 |
2157 |
One row for already entered items
|
2324 |
2158 |
|
2325 |
|
=item * C<template/webpages/order/tabs/_tax_row.html>
|
|
2159 |
=item * C<template/webpages/delivery_order/tabs/_tax_row.html>
|
2326 |
2160 |
|
2327 |
2161 |
Displaying tax information
|
2328 |
2162 |
|
2329 |
|
=item * C<template/webpages/order/tabs/_price_sources_dialog.html>
|
|
2163 |
=item * C<template/webpages/delivery_order/tabs/_price_sources_dialog.html>
|
2330 |
2164 |
|
2331 |
2165 |
Dialog for selecting price and discount sources
|
2332 |
2166 |
|
2333 |
2167 |
=back
|
2334 |
2168 |
|
2335 |
|
=item * C<js/kivi.Order.js>
|
|
2169 |
=item * C<js/kivi.DeliveryOrder.js>
|
2336 |
2170 |
|
2337 |
2171 |
java script functions
|
2338 |
2172 |
|
DeliveryOrder: Anpassungen