use SL::DB::Default;
use SL::DB::Unit;
use SL::DB::Part;
+use SL::DB::PartClassification;
use SL::DB::PartsGroup;
use SL::DB::Printer;
use SL::DB::Language;
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 multi_items_models all_price_factors search_cvpartnumber show_update_button) ],
+ 'scalar --get_set_init' => [ qw(order valid_types type cv p all_price_factors search_cvpartnumber show_update_button part_picker_classification_ids) ],
);
);
}
+# workflow from sales order to sales quotation
+sub action_sales_quotation {
+ $_[0]->workflow_sales_or_request_for_quotation();
+}
+
+# workflow from sales order to sales quotation
+sub action_request_for_quotation {
+ $_[0]->workflow_sales_or_request_for_quotation();
+}
+
# workflow from sales quotation to sales order
sub action_sales_order {
$_[0]->workflow_sales_or_purchase_order();
$self->js->render();
}
-# open the dialog for entering multiple items at once
-sub action_show_multi_items_dialog {
- $_[0]->render('order/tabs/_multi_items_dialog', { layout => 0 },
- all_partsgroups => SL::DB::Manager::PartsGroup->get_all);
-}
-
-# update the filter results in the multi item dialog
-sub action_multi_items_update_result {
- my $max_count = 100;
-
- $::form->{multi_items}->{filter}->{obsolete} = 0;
-
- my $count = $_[0]->multi_items_models->count;
-
- if ($count == 0) {
- my $text = SL::Presenter::EscapedText->new(text => $::locale->text('No results.'));
- $_[0]->render($text, { layout => 0 });
- } elsif ($count > $max_count) {
- my $text = SL::Presenter::EscapedText->new(text => $::locale->text('Too many results (#1 from #2).', $count, $max_count));
- $_[0]->render($text, { layout => 0 });
- } else {
- my $multi_items = $_[0]->multi_items_models->get;
- $_[0]->render('order/tabs/_multi_items_result', { layout => 0 },
- multi_items => $multi_items);
- }
-}
-
# add item rows for multiple items at once
sub action_add_multi_items {
my ($self) = @_;
- my @form_attr = grep { $_->{qty_as_number} } @{ $::form->{add_multi_items} };
+ my @form_attr = grep { $_->{qty_as_number} } @{ $::form->{add_items} };
return $self->js->render() unless scalar @form_attr;
my @items;
}
$self->js
- ->run('kivi.Order.close_multi_items_dialog')
+ ->run('kivi.Part.close_picker_dialogs')
->run('kivi.Order.init_row_handlers')
->run('kivi.Order.renumber_positions')
->focus('#add_item_parts_id_name');
$_[0]->make_order;
}
-# model used to filter/display the parts in the multi-items dialog
-sub init_multi_items_models {
- SL::Controller::Helper::GetModels->new(
- controller => $_[0],
- model => 'Part',
- with_objects => [ qw(unit_obj) ],
- disable_plugin => 'paginated',
- source => $::form->{multi_items},
- sorted => {
- _default => {
- by => 'partnumber',
- dir => 1,
- },
- partnumber => t8('Partnumber'),
- description => t8('Description')}
- );
-}
-
sub init_all_price_factors {
SL::DB::Manager::PriceFactor->get_all;
}
+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 ]) } ];
+}
+
sub check_auth {
my ($self) = @_;
return $errors;
}
+sub workflow_sales_or_request_for_quotation {
+ my ($self) = @_;
+
+ # always save
+ my $errors = $self->save();
+
+ if (scalar @{ $errors }) {
+ $self->js->flash('error', $_) for @{ $errors };
+ return $self->js->render();
+ }
+
+ my $destination_type = $::form->{type} eq sales_order_type() ? sales_quotation_type() : request_quotation_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->type($self->init_type);
+ $self->cv ($self->init_cv);
+ $self->check_auth;
+
+ $self->recalc();
+ $self->get_unalterable_data();
+ $self->pre_render();
+
+ # trigger rendering values for second row as hidden, because they
+ # are loaded only on demand. So we need to keep the values from the
+ # source.
+ $_->{render_second_row} = 1 for @{ $self->order->items_sorted };
+
+ $self->render(
+ 'order/form',
+ title => $self->get_title_for('edit'),
+ %{$self->{template_args}}
+ );
+}
+
sub workflow_sales_or_purchase_order {
my ($self) = @_;
action => [
t8('Workflow'),
],
+ action => [
+ t8('Save and Quotation'),
+ submit => [ '#order_form', { action => "Order/sales_quotation" } ],
+ only_if => (any { $self->type eq $_ } (sales_order_type())),
+ ],
+ action => [
+ t8('Save and RFQ'),
+ submit => [ '#order_form', { action => "Order/request_for_quotation" } ],
+ only_if => (any { $self->type eq $_ } (purchase_order_type())),
+ ],
action => [
t8('Save and Sales Order'),
submit => [ '#order_form', { action => "Order/sales_order" } ],
Displaying tax information
-=item * C<template/webpages/order/tabs/_multi_items_dialog.html>
-
-Dialog for entering more than one item at once
-
-=item * C<template/webpages/order/tabs/_multi_items_result.html>
-
-Results for the filter in the multi items dialog
-
=item * C<template/webpages/order/tabs/_price_sources_dialog.html>
Dialog for selecting price and discount sources
=item * testing
-=item * credit limit
-
-=item * more workflows (quotation, rfq)
-
=item * price sources: little symbols showing better price / better discount
=item * select units in input row?
This behavior was implemented intentionally. But we can discuss, which behavior
should be implemented.
-=item *
-
-C<show_multi_items_dialog> does not use the currently inserted string for
-filtering.
-
=back
=head1 To discuss / Nice to have