From: Bernd Bleßmann Date: Thu, 15 Oct 2015 23:35:05 +0000 (+0200) Subject: Auftrags-Controller: PriceSources X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=e310d269250b549bb9b2e1bc0da31640fda2101d;p=kivitendo-erp.git Auftrags-Controller: PriceSources --- diff --git a/SL/Controller/Order.pm b/SL/Controller/Order.pm index 25eae7a9b..8a4f245a1 100644 --- a/SL/Controller/Order.pm +++ b/SL/Controller/Order.pm @@ -24,7 +24,7 @@ use SL::Helper::DateTime; use SL::Helper::CreatePDF qw(:all); use List::Util qw(max first); -use List::MoreUtils qw(none pairwise); +use List::MoreUtils qw(none pairwise first_index); use English qw(-no_match_vars); use File::Spec; @@ -290,22 +290,42 @@ sub action_add_item { my $item = SL::DB::OrderItem->new; $item->assign_attributes(%$form_attr); - my $part = SL::DB::Part->new(id => $form_attr->{parts_id})->load; - my $cv_method = $self->cv; - my $cv_discount = $self->order->$cv_method? $self->order->$cv_method->discount : 0.0; + my $part = SL::DB::Part->new(id => $form_attr->{parts_id})->load; - my $price = $item->sellprice; - $price ||= ($self->order->$cv_method && $self->order->$cv_method->klass) - ? (SL::DB::Manager::Price->find_by(parts_id => $part->id, pricegroup_id => $self->order->$cv_method->klass)->price || $part->sellprice) - : $part->sellprice; + my $price_source = SL::PriceSource->new(record_item => $item, record => $self->order); + + my $price_src; + if ($item->sellprice) { + $price_src = $price_source->price_from_source(""); + $price_src->price($item->sellprice); + } else { + $price_src = $price_source->best_price + ? $price_source->best_price + : $price_source->price_from_source(""); + $price_src->price(0) if !$price_source->best_price; + } + + # bb: not sure but: maybe there should be a $price_source->discount_from_source + # which can alse return an empty_discout if source is "". + my $discount; + my $discount_src; + if ($item->discount) { + $discount = $item->discount; + } else { + $discount = $price_source->best_discount + ? $price_source->best_discount->discount + : 0; + $discount_src = $price_source->best_discount->source if $price_source->best_discount; + } my %new_attr; - $new_attr{part} = $part; - $new_attr{description} = $part->description if ! $item->description; - $new_attr{qty} = 1.0 if ! $item->qty; - $new_attr{unit} = $part->unit; - $new_attr{sellprice} = $price; - $new_attr{discount} = $cv_discount if ! $item->discount; + $new_attr{part} = $part; + $new_attr{description} = $part->description if ! $item->description; + $new_attr{qty} = 1.0 if ! $item->qty; + $new_attr{sellprice} = $price_src->price; + $new_attr{discount} = $discount; + $new_attr{active_price_source} = $price_src; + $new_attr{active_discount_source} = $discount_src; # add_custom_variables adds cvars to an orderitem with no cvars for saving, but # they cannot be retrieved via custom_variables until the order/orderitem is @@ -348,6 +368,15 @@ sub action_recalc_amounts_and_taxes { $self->js->render(); } +sub action_price_popup { + my ($self) = @_; + + my $idx = first_index { $_ eq $::form->{item_id} } @{ $::form->{orderitem_ids} }; + my $item = $self->order->items->[$idx]; + + $self->render_price_dialog($item); +} + sub _js_redisplay_linetotals { my ($self) = @_; @@ -460,6 +489,27 @@ sub build_tax_rows { } +sub render_price_dialog { + my ($self, $record_item) = @_; + + my $price_source = SL::PriceSource->new(record_item => $record_item, record => $self->order); + + $self->js + ->run( + 'kivi.io.price_chooser_dialog', + t8('Available Prices'), + $self->render('order/tabs/_price_sources_dialog', { output => 0 }, price_source => $price_source) + ) + ->reinit_widgets; + +# if (@errors) { +# $self->js->text('#dialog_flash_error_content', join ' ', @errors); +# $self->js->show('#dialog_flash_error'); +# } + + $self->js->render; +} + sub _make_order { my ($self) = @_; @@ -475,7 +525,6 @@ sub _make_order { return $order; } - sub _recalc { my ($self) = @_; @@ -504,12 +553,10 @@ sub _get_unalterable_data { if ($item->id) { # load data from orderitems (db) my $db_item = SL::DB::OrderItem->new(id => $item->id)->load; - $item->$_($db_item->$_) for qw(active_discount_source active_price_source longdescription); + $item->$_($db_item->$_) for qw(longdescription); } else { # set data from part (or other sources) $item->longdescription($item->part->notes); - #$item->active_price_source(''); - #$item->active_discount_source(''); } # autovivify all cvars that are not in the form (cvars_by_config can do it). @@ -555,6 +602,17 @@ sub _pre_render { $self->{current_employee_id} = SL::DB::Manager::Employee->current->id; + foreach my $item (@{$self->order->items}) { + my $price_source = SL::PriceSource->new(record_item => $item, record => $self->order); + + my $price_src = $price_source->price_from_source($item->active_price_source); + $item->active_price_source($price_src); + + my $discount_src; + $discount_src = $price_source->price_from_source($item->active_discount_source)->source if $item->active_discount_source; + $item->active_discount_source($discount_src); + } + $::request->{layout}->use_javascript("${_}.js") for qw(ckeditor/ckeditor ckeditor/adapters/jquery); } diff --git a/templates/webpages/order/tabs/_item_input.html b/templates/webpages/order/tabs/_item_input.html index f59c22628..7d8f36efb 100644 --- a/templates/webpages/order/tabs/_item_input.html +++ b/templates/webpages/order/tabs/_item_input.html @@ -16,7 +16,10 @@ [% L.part_picker('add_item.parts_id', '', fat_set_item=1, style='width: 300px', class="add_item_input") %] [% L.input_tag('add_item.description', '', class="add_item_input") %] - [% L.input_tag('add_item.qty_as_number', '', size = 5, style='text-align:right', class="add_item_input") %] + + [% L.input_tag('add_item.qty_as_number', '', size = 5, style='text-align:right', class="add_item_input") %] + [% L.hidden_tag('add_item.unit', ''class="add_item_input") %] + [% L.input_tag('add_item.sellprice_as_number', '', size = 10, style='text-align:right', class="add_item_input") %] [% L.input_tag('add_item.discount_as_percent', '', size = 5, style='text-align:right', class="add_item_input") %] [% L.button_tag('add_item()', LxERP.t8('Add part')) %] diff --git a/templates/webpages/order/tabs/_price_sources_dialog.html b/templates/webpages/order/tabs/_price_sources_dialog.html new file mode 100644 index 000000000..090cb289f --- /dev/null +++ b/templates/webpages/order/tabs/_price_sources_dialog.html @@ -0,0 +1,89 @@ +[%- USE T8 %] +[%- USE HTML %] +[%- USE L %] +[%- USE LxERP %] +[% SET best_price = price_source.best_price %] +[% SET best_discount = price_source.best_discount %] +

[% 'Prices' | $T8 %]

+ + + + + + + + + + +[%- IF price_source.record_item.active_price_source %] + +[%- ELSE %] + +[%- END %] + + + + + + [%- FOREACH price IN price_source.available_prices %] + +[%- IF price_source.record_item.active_price_source != price.source %] + +[%- ELSIF price_source.record_item.sellprice * 1 != price.price * 1 %] + +[%- ELSE %] + +[% END %] + + +[% IF price.source == best_price.source %] + +[% ELSE %] + +[% END %] + + + [%- END %] +
[% 'Price Source' | $T8 %][% 'Price' | $T8 %][% 'Best Price' | $T8 %][% 'Details' | $T8 %]
[% L.button_tag('update_price_source(\'' _ FORM.item_id _ '\', \'\', \'' _ LxERP.t8('None (PriceSource)') _ '\')', LxERP.t8('Select')) %][% 'Selected' | $T8 %][% 'None (PriceSource)' | $T8 %]-
[% L.button_tag('update_price_source(\'' _ FORM.item_id _ '\', \'' _ price.source _ '\', \'' _ price.source_description _ '\', \'' _ LxERP.format_amount(price.price, -2) _ '\')', LxERP.t8('Select')) %][% L.button_tag('update_price_source(\'' _ FORM.item_id _ '\', \'' _ price.source _ '\', \'' _ price.source_description _ '\', \'' _ LxERP.format_amount(price.price, -2) _ '\')', LxERP.t8('Update Price')) %][% 'Selected' | $T8 %][% price.source_description | html %][% price.price_as_number %][% price.description | html %]
+ +

[% 'Discounts' | $T8 %]

+ + + + + + + + + + +[%- IF price_source.record_item.active_discount_source %] + +[%- ELSE %] + +[%- END %] + + + + + + [%- FOREACH price IN price_source.available_discounts %] + +[%- IF price_source.record_item.active_discount_source != price.source %] + +[%- ELSIF price_source.record_item.discount * 1 != price.discount * 100 %] + +[%- ELSE %] + +[% END %] + + +[% IF price.source == best_discount.source %] + +[% ELSE %] + +[% END %] + + + [%- END %] +
[% 'Price Source' | $T8 %][% 'Discount' | $T8 %][% 'Best Discount' | $T8 %][% 'Details' | $T8 %]
[% L.button_tag('update_discount_source(\'' _ FORM.item_id _ '\', \'\')', LxERP.t8('Select')) %][% 'Selected' | $T8 %][% 'None (PriceSource Discount)' | $T8 %]-
[% L.button_tag('update_discount_source(\'' _ FORM.item_id _ '\', \'' _ price.source _ '\', \'' _ price.discount_as_percent _ '\')', LxERP.t8('Select')) %][% L.button_tag('update_discount_source(\'' _ FORM.item_id _ '\', \'' _ price.source _ '\', \'' _ price.discount_as_percent _ '\')', LxERP.t8('Update Discount')) %][% 'Selected' | $T8 %][% price.source_description | html %][% price.discount_as_percent %] %[% price.description | html %]
diff --git a/templates/webpages/order/tabs/_row.html b/templates/webpages/order/tabs/_row.html index 7cf610a5a..7138d36ca 100644 --- a/templates/webpages/order/tabs/_row.html +++ b/templates/webpages/order/tabs/_row.html @@ -7,6 +7,7 @@ + [% L.hidden_tag("orderitem_ids[+]", ID) %] [% L.hidden_tag("order.orderitems[+].id", ITEM.id, id='item_' _ ID) %] [% L.hidden_tag("order.orderitems[].parts_id", ITEM.parts_id) %] @@ -47,13 +48,26 @@ class="recalc") %] - [%- L.input_tag("order.orderitems[].sellprice_as_number", - ITEM.sellprice_as_number, - size = 10, - style='text-align:right', - class="recalc") %] + [%- SET EDIT_PRICES = 1 %] + [%- IF EDIT_PRICES %] + [%- L.button_tag("price_chooser_item_row(this)", ITEM.active_price_source.source_description, name = "price_chooser_button") %] + [%- END %] + + + [%- L.hidden_tag("order.orderitems[].active_price_source", ITEM.active_price_source.source) %] + [%- IF EDIT_PRICES %] + [%- L.input_tag("order.orderitems[].sellprice_as_number", + ITEM.sellprice_as_number, + size = 10, + style='text-align:right', + class="recalc") %] + [%- ELSE %] + [%- ITEM.sellprice_as_number %] + [%- L.hidden_tag("order.orderitems[].sellprice_as_number", ITEM.sellprice_as_number) %] + [%- END %] + [%- L.hidden_tag("order.orderitems[].active_discount_source", ITEM.active_discount_source) %] [%- L.input_tag("order.orderitems[].discount_as_percent", ITEM.discount_as_percent, size = 5, diff --git a/templates/webpages/order/tabs/basic_data.html b/templates/webpages/order/tabs/basic_data.html index aa39b2421..9386c5629 100644 --- a/templates/webpages/order/tabs/basic_data.html +++ b/templates/webpages/order/tabs/basic_data.html @@ -140,6 +140,7 @@ [%- 'Qty' | $T8 %] [%- 'Price Factor' | $T8 %] [%- 'Unit' | $T8 %] + [%- 'Price Source' | $T8 %] [%- 'Price' | $T8 %] [%- 'Discount' | $T8 %] [%- 'Extended' | $T8 %] @@ -268,6 +269,42 @@ function delete_order_item_row(clicked) { recalc_amounts_and_taxes(); } +function price_chooser_item_row(clicked) { + var row = $(clicked).parents("tbody").first(); + var item_id_dom = $(row).find('[name="orderitem_ids[+]"]'); + + var data = $('#order_form').serialize(); + data += '&action=Order/price_popup'; + data += '&item_id=' + item_id_dom.val(); + + $.post("controller.pl", data, kivi.eval_json_result); +} + +function update_price_source(item_id, source, descr, price_str) { + var row = $('#item_' + item_id).parents("tbody").first(); + var source_elt = $(row).find('[name="order.orderitems[].active_price_source"]'); + var price_elt = $(row).find('[name="order.orderitems[].sellprice_as_number"]'); + var button_elt = $(row).find('[name="price_chooser_button"]'); + + button_elt.val(descr); + source_elt.val(source); + if (price_str) price_elt.val(price_str); + + recalc_amounts_and_taxes(); + kivi.io.close_dialog(); +} + +function update_discount_source(item_id, source, discount_str) { + var row = $('#item_' + item_id).parents("tbody").first(); + var source_elt = $(row).find('[name="order.orderitems[].active_discount_source"]'); + var discount_elt = $(row).find('[name="order.orderitems[].discount_as_percent"]'); + + source_elt.val(source); + if (discount_str) discount_elt.val(discount_str); + + recalc_amounts_and_taxes(); +} + function recalc_amounts_and_taxes() { var data = $('#order_form').serialize(); data += '&action=Order/recalc_amounts_and_taxes'; @@ -350,8 +387,13 @@ close_email_dialog = function() { $(function(){ $('#order_[%- cv_id %]').change(reload_cv_dependend_selections); - $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) }); + [%- IF SELF.cv == 'customer' %] + $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.sellprice, -2)) }); + [%- ELSE %] + $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_sellprice_as_number').val(kivi.format_amount(o.lastcost, -2)) }); + [%- END %] $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_description').val(o.description) }); + $('#add_item_parts_id').on('set_item:PartPicker', function(e,o) { $('#add_item_unit').val(o.unit) }); $('.add_item_input').keydown(function(event) { if(event.keyCode == 13) { event.preventDefault();