use SL::Helper::PrintOptions;
use SL::Helper::ShippedQty;
use SL::Helper::UserPreferences::PositionsScrollbar;
+use SL::Helper::UserPreferences::UpdatePositions;
use SL::Controller::Helper::GetModels;
-use List::Util qw(first);
+use List::Util qw(first sum0);
use List::UtilsBy qw(sort_by uniq_by);
use List::MoreUtils qw(any none pairwise first_index);
use English qw(-no_match_vars);
use Rose::Object::MakeMethods::Generic
(
scalar => [ qw(item_ids_to_delete) ],
- 'scalar --get_set_init' => [ qw(order valid_types type cv p multi_items_models all_price_factors search_cvpartnumber) ],
+ 'scalar --get_set_init' => [ qw(order valid_types type cv p multi_items_models all_price_factors search_cvpartnumber show_update_button) ],
);
# print the order
#
# This is called if "print" is pressed in the print dialog.
-# If PDF creation was requested and succeeded, the pdf is stored in a session
-# file and the filename is stored as session value with an unique key. A
-# javascript function with this key is then called. This function calls the
-# download action below (action_download_pdf), which offers the file for
-# download.
+# If PDF creation was requested and succeeded, the pdf is offered for download
+# via send_file (which uses ajax in this case).
sub action_print {
my ($self) = @_;
if ($media eq 'screen') {
# screen/download
- my $sfile = SL::SessionFile::Random->new(mode => "w");
- $sfile->fh->print($pdf);
- $sfile->fh->close;
-
- my $key = join('_', Time::HiRes::gettimeofday(), int rand 1000000000000);
- $::auth->set_session_value("Order::print-${key}" => $sfile->file_name);
-
- $self->js
- ->run('kivi.Order.download_pdf', $pdf_filename, $key)
- ->flash('info', t8('The PDF has been created'));
+ $self->js->flash('info', t8('The PDF has been created'));
+ $self->send_file(
+ \$pdf,
+ type => SL::MIME->mime_type_from_ext($pdf_filename),
+ name => $pdf_filename,
+ js_no_render => 1,
+ );
} elsif ($media eq 'printer') {
# printer
$self->js->render;
}
-# offer pdf for download
-#
-# It needs to get the key for the session value to get the pdf file.
-sub action_download_pdf {
- my ($self) = @_;
-
- my $key = $::form->{key};
- my $tmp_filename = $::auth->get_session_value("Order::print-${key}");
- return $self->send_file(
- $tmp_filename,
- type => SL::MIME->mime_type_from_ext($::form->{pdf_filename}),
- name => $::form->{pdf_filename},
- );
-}
-
# open the email dialog
sub action_show_email_dialog {
my ($self) = @_;
$form->{$self->nr_key()} = $self->order->number;
$form->{formname} = $self->type;
$form->{type} = $self->type;
- $form->{language} = 'de';
+ $form->{language} = '_' . $self->order->language->template_code if $self->order->language;
+ $form->{language_id} = $self->order->language->id if $self->order->language;
$form->{format} = 'pdf';
$email_form->{subject} = $form->generate_email_subject();
->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_currency_id', $self->order->currency_id)
->val( '#order_payment_id', $self->order->payment_id)
->val( '#order_delivery_term_id', $self->order->delivery_term_id)
->val( '#order_intnotes', $self->order->intnotes)
->val( '#language_id', $self->order->$cv_method->language_id)
- ->focus( '#order_' . $self->cv . '_id');
+ ->focus( '#order_' . $self->cv . '_id')
+ ->run('kivi.Order.update_exchangerate');
$self->js_redisplay_amounts_and_taxes;
$self->js_redisplay_cvpartnumbers;
my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
my $row_as_html = $self->p->render('order/tabs/_row',
- ITEM => $item,
- ID => $item_id,
- TYPE => $self->type,
- ALL_PRICE_FACTORS => $self->all_price_factors,
- SEARCH_CVPARTNUMBER => $self->search_cvpartnumber,
+ ITEM => $item,
+ ID => $item_id,
+ SELF => $self,
);
- $self->js
- ->append('#row_table_id', $row_as_html);
+ if ($::form->{insert_before_item_id}) {
+ $self->js
+ ->before ('.row_entry:has(#item_' . $::form->{insert_before_item_id} . ')', $row_as_html);
+ } else {
+ $self->js
+ ->append('#row_table_id', $row_as_html);
+ }
if ( $item->part->is_assortment ) {
$form_attr->{qty_as_number} = 1 unless $form_attr->{qty_as_number};
$self->get_item_cvpartnumber($item);
my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
my $row_as_html = $self->p->render('order/tabs/_row',
- ITEM => $item,
- ID => $item_id,
- TYPE => $self->type,
- ALL_PRICE_FACTORS => $self->all_price_factors,
- SEARCH_CVPARTNUMBER => $self->search_cvpartnumber,
+ ITEM => $item,
+ ID => $item_id,
+ SELF => $self,
);
- $self->js
- ->append('#row_table_id', $row_as_html);
+ if ($::form->{insert_before_item_id}) {
+ $self->js
+ ->before ('.row_entry:has(#item_' . $::form->{insert_before_item_id} . ')', $row_as_html);
+ } else {
+ $self->js
+ ->append('#row_table_id', $row_as_html);
+ }
};
};
$self->js
->val('.add_item_input', '')
->run('kivi.Order.init_row_handlers')
- ->run('kivi.Order.row_table_scroll_down')
->run('kivi.Order.renumber_positions')
->focus('#add_item_parts_id_name');
+ $self->js->run('kivi.Order.row_table_scroll_down') if !$::form->{insert_before_item_id};
+
$self->js_redisplay_amounts_and_taxes;
$self->js->render();
}
$self->get_item_cvpartnumber($item);
my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
my $row_as_html = $self->p->render('order/tabs/_row',
- ITEM => $item,
- ID => $item_id,
- TYPE => $self->type,
- ALL_PRICE_FACTORS => $self->all_price_factors,
- SEARCH_CVPARTNUMBER => $self->search_cvpartnumber,
+ ITEM => $item,
+ ID => $item_id,
+ SELF => $self,
);
- $self->js->append('#row_table_id', $row_as_html);
+ if ($::form->{insert_before_item_id}) {
+ $self->js
+ ->before ('.row_entry:has(#item_' . $::form->{insert_before_item_id} . ')', $row_as_html);
+ } else {
+ $self->js
+ ->append('#row_table_id', $row_as_html);
+ }
}
$self->js
->run('kivi.Order.close_multi_items_dialog')
->run('kivi.Order.init_row_handlers')
- ->run('kivi.Order.row_table_scroll_down')
->run('kivi.Order.renumber_positions')
->focus('#add_item_parts_id_name');
+ $self->js->run('kivi.Order.row_table_scroll_down') if !$::form->{insert_before_item_id};
+
$self->js_redisplay_amounts_and_taxes;
$self->js->render();
}
$self->js->render();
}
+sub action_update_exchangerate {
+ my ($self) = @_;
+
+ my $data = {
+ is_standard => $self->order->currency_id == $::instance_conf->get_currency_id,
+ currency_name => $self->order->currency->name,
+ exchangerate => $self->order->daily_exchangerate_as_null_number,
+ };
+
+ $self->render(\SL::JSON::to_json($data), { type => 'json', process => 0 });
+}
+
# redisplay item rows if they are sorted by an attribute
sub action_reorder_items {
my ($self) = @_;
$price_src = $price_source->best_price
? $price_source->best_price
: $price_source->price_from_source("");
+ $price_src->price($::form->round_amount($price_src->price / $self->order->exchangerate, 5)) if $self->order->exchangerate;
$price_src->price(0) if !$price_source->best_price;
}
+
$item->sellprice($price_src->price);
$item->active_price_source($price_src);
$self->js
->run('kivi.Order.update_sellprice', $item_id, $item->sellprice_as_number)
- ->val('.row_entry:has(#item_' . $item_id . ') [name = "order.orderitems[].description"]', $item->description)
- ->val('.row_entry:has(#item_' . $item_id . ') [name = "order.orderitems[].longdescription"]', $item->longdescription);
+ ->html('.row_entry:has(#item_' . $item_id . ') [name = "partnumber"] a', $item->part->partnumber)
+ ->val ('.row_entry:has(#item_' . $item_id . ') [name = "order.orderitems[].description"]', $item->description)
+ ->val ('.row_entry:has(#item_' . $item_id . ') [name = "order.orderitems[].longdescription"]', $item->longdescription);
+
+ if ($self->search_cvpartnumber) {
+ $self->get_item_cvpartnumber($item);
+ $self->js->html('.row_entry:has(#item_' . $item_id . ') [name = "cvpartnumber"]', $item->{cvpartnumber});
+ }
}
$self->recalc();
return $search_cvpartnumber;
}
+sub init_show_update_button {
+ my ($self) = @_;
+
+ !!SL::Helper::UserPreferences::UpdatePositions->new()->get_show_update_button();
+}
+
sub init_p {
SL::Presenter->get;
}
# order here solves this problem.
my $order;
$order = SL::DB::Order->new(id => $::form->{id})->load(with => [ 'orderitems', 'orderitems.part' ]) if $::form->{id};
- $order ||= SL::DB::Order->new(orderitems => [],
- quotation => (any { $self->type eq $_ } (sales_quotation_type(), request_quotation_type())));
+ $order ||= SL::DB::Order->new(orderitems => [],
+ quotation => (any { $self->type eq $_ } (sales_quotation_type(), request_quotation_type())),
+ currency_id => $::instance_conf->get_currency_id());
my $cv_id_method = $self->cv . '_id';
if (!$::form->{id} && $::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};
+ my $form_orderitems = delete $::form->{order}->{orderitems};
+ my $form_periodic_invoices_config = delete $::form->{order}->{periodic_invoices_config};
$order->assign_attributes(%{$::form->{order}});
$price_src->price($item->sellprice);
} else {
$price_src = $price_source->best_price
- ? $price_source->best_price
- : $price_source->price_from_source("");
+ ? $price_source->best_price
+ : $price_source->price_from_source("");
+ $price_src->price($::form->round_amount($price_src->price / $record->exchangerate, 5)) if $record->exchangerate;
$price_src->price(0) if !$price_source->best_price;
}
sub setup_order_from_cv {
my ($order) = @_;
- $order->$_($order->customervendor->$_) for (qw(taxzone_id payment_id delivery_term_id));
+ $order->$_($order->customervendor->$_) for (qw(taxzone_id payment_id delivery_term_id currency_id));
$order->intnotes($order->customervendor->notes);
sub recalc {
my ($self) = @_;
- # bb: todo: currency later
- $self->order->currency_id($::instance_conf->get_currency_id());
-
my %pat = $self->order->calculate_prices_and_taxes();
+
$self->{taxes} = [];
- foreach my $tax_chart_id (keys %{ $pat{taxes} }) {
- my $tax = SL::DB::Manager::Tax->find_by(chart_id => $tax_chart_id);
+ foreach my $tax_id (keys %{ $pat{taxes_by_tax_id} }) {
+ my $netamount = sum0 map { $pat{amounts}->{$_}->{amount} } grep { $pat{amounts}->{$_}->{tax_id} == $tax_id } keys %{ $pat{amounts} };
- my @amount_keys = grep { $pat{amounts}->{$_}->{tax_id} == $tax->id } keys %{ $pat{amounts} };
- push(@{ $self->{taxes} }, { amount => $pat{taxes}->{$tax_chart_id},
- netamount => $pat{amounts}->{$amount_keys[0]}->{amount},
- tax => $tax });
+ push(@{ $self->{taxes} }, { amount => $pat{taxes_by_tax_id}->{$tax_id},
+ netamount => $netamount,
+ tax => SL::DB::Tax->new(id => $tax_id)->load });
}
-
pairwise { $a->{linetotal} = $b->{linetotal} } @{$self->order->items_sorted}, @{$pat{items}};
}
my ($self) = @_;
$self->{all_taxzones} = SL::DB::Manager::TaxZone->get_all_sorted();
+ $self->{all_currencies} = SL::DB::Manager::Currency->get_all_sorted();
$self->{all_departments} = SL::DB::Manager::Department->get_all_sorted();
$self->{all_employees} = SL::DB::Manager::Employee->get_all(where => [ or => [ id => $self->order->employee_id,
deleted => 0 ] ],
$self->{positions_scrollbar_height} = SL::Helper::UserPreferences::PositionsScrollbar->new()->get_height();
my $print_form = Form->new('');
- $print_form->{type} = $self->type;
- $print_form->{printers} = SL::DB::Manager::Printer->get_all_sorted;
- $print_form->{languages} = SL::DB::Manager::Language->get_all_sorted;
- $self->{print_options} = SL::Helper::PrintOptions->get_print_options(
+ $print_form->{type} = $self->type;
+ $print_form->{printers} = SL::DB::Manager::Printer->get_all_sorted;
+ $print_form->{languages} = SL::DB::Manager::Language->get_all_sorted;
+ $print_form->{language_id} = $self->order->language_id;
+ $self->{print_options} = SL::Helper::PrintOptions->get_print_options(
form => $print_form,
options => {dialog_name_prefix => 'print_options.',
show_headers => 1,
sub get_item_cvpartnumber {
my ($self, $item) = @_;
+ return if !$self->search_cvpartnumber;
+ return if !$self->order->customervendor;
+
if ($self->cv eq 'vendor') {
my @mms = grep { $_->make eq $self->order->customervendor->id } @{$item->part->makemodels};
$item->{cvpartnumber} = $mms[0]->model if scalar @mms;
=item * testing
-=item * currency
-
=item * credit limit
=item * more workflows (quotation, rfq)
C<show_multi_items_dialog> does not use the currently inserted string for
filtering.
-=item *
-
-The language selected in print or email dialog is not saved when the order is saved.
-
=back
=head1 To discuss / Nice to have