X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FController%2FDeliveryValueReport.pm;h=5fa5c454d99a78c92cd77c3aff8b68c458ed3198;hb=5474d397bbc42ffaea0b51ebb4bb9a4c7afaa881;hp=3134f75ede94b61a9e31db8126ef7da2ea3afdfa;hpb=eeac4a64bdb98ff54e6cc324e1d8b7532a35219b;p=kivitendo-erp.git diff --git a/SL/Controller/DeliveryValueReport.pm b/SL/Controller/DeliveryValueReport.pm index 3134f75ed..5fa5c454d 100644 --- a/SL/Controller/DeliveryValueReport.pm +++ b/SL/Controller/DeliveryValueReport.pm @@ -9,17 +9,18 @@ use SL::DB::Business; use SL::Controller::Helper::GetModels; use SL::Controller::Helper::ReportGenerator; use SL::Locale::String; +use SL::Helper::ShippedQty; use SL::AM; -use SL::DBUtils (); +use SL::DBUtils qw(selectall_as_map); +use List::MoreUtils qw(uniq); use Carp; use Data::Dumper; use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(db_args flat_filter) ], 'scalar --get_set_init' => [ qw(models vc all_employees all_businesses) ], ); - +__PACKAGE__->run_before(sub { $::auth->assert('delivery_value_report'); }); my %sort_columns = ( reqdate => t8('Reqdate'), @@ -38,7 +39,7 @@ my %sort_columns = ( delivered_qty => t8('transferred in / out'), netto_delivered_qty => t8('Net value transferred in / out'), do_closed_qty => t8('Qty in closed delivery orders'), - netto_do_closed_qty => t8('Qty in closed delivery orders') + netto_do_closed_qty => t8('Net value in closed delivery orders'), ); @@ -55,6 +56,7 @@ sub action_list { my $orderitems = $self->models->get; $self->calc_qtys_price($orderitems); + $self->setup_list_action_bar; $self->report_generator_list_objects(report => $self->{report}, objects => $orderitems); } @@ -62,7 +64,6 @@ sub prepare_report { my ($self) = @_; my $vc = $self->vc; - my $mode = 'delivery_value_report'; my $report = SL::ReportGenerator->new(\%::myconfig, $::form); my $csv_option = $::form->{report_generator_output_format}; $self->{report} = $report; @@ -83,29 +84,18 @@ sub prepare_report { obj_link => sub { $self->link_to($_[0]->part) } }, partnumber => { sub => sub { $_[0]->part->partnumber }, obj_link => sub { $self->link_to($_[0]->part) } }, - qty => { sub => sub { $_[0]->qty_as_number . - ($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, - netto_qty => { sub => sub { $::form->format_amount(\%::myconfig, - ($_[0]->qty * $_[0]->sellprice * (1 - $_[0]->discount) / - ($_[0]->price_factor || 1), 2)) },}, - unit => { sub => sub { $_[0]->unit }, - visible => $rp_csv_mod }, - shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{shipped_qty}, 2) . - ($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, - netto_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_shipped_qty}, 2) },}, - not_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]->qty - $_[0]{shipped_qty} - - $_[0]{delivered_qty} - $_[0]{do_closed_qty}, 2) . - ($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, - delivered_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{delivered_qty}, 2) . - ($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, - netto_delivered_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_delivered_qty}, 2) },}, - netto_not_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig,(($_[0]->qty - - $_[0]{shipped_qty} - $_[0]{delivered_qty} - $_[0]{do_closed_qty}) - * ($_[0]->sellprice * (1 - $_[0]->discount) / - ($_[0]->price_factor || 1)), 2)) },}, - do_closed_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{do_closed_qty}, 2) . - ($rp_csv_mod ? '' : ' ' . $_[0]->unit) },}, - netto_do_closed_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_do_closed_qty}, 2) },}, + qty => { sub => sub { _format_qty($_[0], 'qty', $rp_csv_mod) } }, + netto_qty => { sub => sub { _format_val($_[0], 'qty') },}, + unit => { sub => sub { $_[0]->unit }, + visible => $rp_csv_mod }, + shipped_qty => { sub => sub { _format_qty($_[0], 'shipped_qty', $rp_csv_mod) } }, + netto_shipped_qty => { sub => sub { _format_val($_[0], 'shipped_qty') },}, + not_shipped_qty => { sub => sub { _format_qty($_[0], 'not_shipped_qty', $rp_csv_mod) } }, + netto_not_shipped_qty => { sub => sub { _format_val($_[0], 'not_shipped_qty') },}, + delivered_qty => { sub => sub { _format_qty($_[0], 'delivered_qty', $rp_csv_mod) } }, + netto_delivered_qty => { sub => sub { _format_val($_[0], 'delivered_qty') },}, + do_closed_qty => { sub => sub { _format_qty($_[0], 'do_closed_qty', $rp_csv_mod) },}, + netto_do_closed_qty => { sub => sub { _format_val($_[0], 'do_closed_qty') },}, ordnumber => { sub => sub { $_[0]->order->ordnumber }, obj_link => sub { $self->link_to($_[0]->order) } }, vendor => { sub => sub { $_[0]->order->vendor->name }, @@ -240,11 +230,15 @@ sub link_to { my $vc = $object->is_sales ? 'customer' : 'vendor'; my $id = $object->id; - return "oe.pl?action=$action&type=$type&vc=$vc&id=$id"; + if ($::instance_conf->get_feature_experimental_order) { + return "controller.pl?action=Order/$action&type=$type&id=$id"; + } else { + return "oe.pl?action=$action&type=$type&vc=$vc&id=$id"; + } } if ($object->isa('SL::DB::Part')) { my $id = $object->id; - return "ic.pl?action=$action&id=$id"; + return "controller.pl?action=Part/$action&part.id=$id"; } if ($object->isa('SL::DB::Customer')) { my $id = $object->id; @@ -252,50 +246,72 @@ sub link_to { } } +sub _format_qty { + my ($item, $col, $csv_mod) = @_; + + $::form->format_amount(\%::myconfig, $item->{$col}, 2) . ($csv_mod ? '' : ' ' . $item->unit) +} + +sub _format_val { + my ($item, $col) = @_; + + $::form->format_amount(\%::myconfig, $item->{$col} * $item->sellprice * (1 - $item->discount) / ($item->price_factor || 1), 2) +} + sub calc_qtys_price { my ($self, $orderitems) = @_; - # using $orderitem->shipped_qty 40 times is far too slow. need to do it manually - # also for calc net values return unless scalar @$orderitems; - my %orderitems_by_id = map { $_->id => $_ } @$orderitems; + SL::Helper::ShippedQty + ->new(require_stock_out => 1) + ->calculate($orderitems) + ->write_to_objects; - my $query = <get_standard_dbh, $query, map { $_->id } @$orderitems); - - for my $row (@$result) { - my $item = $orderitems_by_id{ $row->{id} }; - $item->{shipped_qty} ||= 0; - $item->{delivered_qty} ||= 0; - $item->{do_closed_qty} ||= 0; - $item->{shipped_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} unless ($row->{delivered} || $row->{closed}); - $item->{delivered_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} if ($row->{delivered} && !$row->{closed}); - $item->{do_closed_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} if ($row->{closed}); - $item->{not_shipped_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} unless ($row->{delivered}); - - my $price_factor = $row->{price_factor} || 1; - $item->{netto_shipped_qty} = $item->{shipped_qty} * $row->{sellprice} * (1 - $row->{discount} ) / $price_factor; - $item->{netto_delivered_qty} = $item->{delivered_qty} * $row->{sellprice} * (1 - $row->{discount} ) / $price_factor; - $item->{netto_do_closed_qty} = $item->{do_closed_qty} * $row->{sellprice} * (1 - $row->{discount} ) / $price_factor; + $_->{delivered_qty} = delete $_->{shipped_qty} for @$orderitems; + + my $helper = SL::Helper::ShippedQty + ->new(require_stock_out => 0, keep_matches => 1) + ->calculate($orderitems) + ->write_to_objects; + for my $item (@$orderitems) { + $item->{not_shipped_qty} = $item->qty - $item->{shipped_qty}; + $item->{do_closed_qty} = 0; + + my $price_factor = $item->price_factor || 1; } -} + if (my @all_doi_ids = uniq map { $_->[1] } @{ $helper->matches }) { + my %oi_by_id = map { $_->id => $_ } @$orderitems; + my $query = sprintf <<'', join ', ', ("?")x@all_doi_ids; + SELECT DISTINCT doi.id, closed FROM delivery_orders + LEFT JOIN delivery_order_items doi ON (doi.delivery_order_id = delivery_orders.id) + WHERE doi.id IN (%s) + my %doi_is_closed = selectall_as_map($::form, SL::DB->client->dbh, $query, (id => 'closed'), @all_doi_ids); + for my $match (@{ $helper->matches }) { + next unless $doi_is_closed{$match->[1]}; + $oi_by_id{$match->[0]}->{do_closed_qty} += $match->[2]; + } + } +} + +sub setup_list_action_bar { + my ($self, %params) = @_; + + for my $bar ($::request->layout->get('actionbar')) { + $bar->add( + action => [ + t8('Update'), + submit => [ '#filter_form', { action => 'DeliveryValueReport/list' } ], + accesskey => 'enter', + ], + ); + } +} 1; @@ -314,7 +330,7 @@ SL::Controller::DeliveryValueReport - Controller for Delivery Value Report Controller class for Delivery Value Report -The goal of the record is to determine which goods and at what costs are already delivered, transfered in +The goal of the report is to determine which goods and at what costs are already delivered, transfered in relation to open orders, orders in process. @@ -331,7 +347,7 @@ for individual item reqdates. After some arguing we decided to implement persistent ids for all items and link them directly via record_links. This linking has been secrectly active since version 3.2, therefore this redesign is possible. Currently the report even works correctly even if the same part has been manually put in another position, renamed or some - other metadata for the position has been altered. This is due to the fact that a hidden converted_from_previous_document is +other metadata for the position has been altered. This is due to the fact that a hidden converted_from_previous_document is used in the position. The main intelligence is this query (qty_stocked as comments):