X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FController%2FInventory.pm;h=a4c11f6a0ababcf0b843139b38f3877fa59cf431;hb=53593baa211863fbf66540cf1bcc36c8fb37257f;hp=f20f6aee8d5de286f2d7faf777ae763f1464700b;hpb=44ed4e99507c6de660029eabad6b3ccdc7ab5fd6;p=kivitendo-erp.git diff --git a/SL/Controller/Inventory.pm b/SL/Controller/Inventory.pm index f20f6aee8..a4c11f6a0 100644 --- a/SL/Controller/Inventory.pm +++ b/SL/Controller/Inventory.pm @@ -20,6 +20,7 @@ use SL::DBUtils; use SL::Helper::Flash; use SL::Controller::Helper::ReportGenerator; use SL::Controller::Helper::GetModels; +use List::MoreUtils qw(uniq); use English qw(-no_match_vars); @@ -44,6 +45,12 @@ sub action_stock_in { $::form->{title} = t8('Stock'); + # Sometimes we want to open stock_in with a part already selected, but only + # the parts_id is passed in the url (and not also warehouse, bin and unit). + # Setting select_default_bin in the form will make sure the default warehouse + # and bin of that part will already be preselected, as normally + # set_target_from_part is only called when a part is changed. + $self->set_target_from_part if $::form->{select_default_bin}; $::request->layout->focus('#part_id_name'); my $transfer_types = WH->retrieve_transfer_types('in'); map { $_->{description} = $main::locale->text($_->{description}) } @{ $transfer_types }; @@ -387,7 +394,7 @@ sub make_row_result { $row->{outcorrection}->{data} - $row->{incorrection}->{data}; $row->{averconsumed}->{data} = $row->{consumed}->{data}*30/$days ; map { $row->{$_}->{data} = $form->format_amount($myconfig,$row->{$_}->{data},2); } $self->getnumcolumns(); - $row->{partnumber}->{link} = 'controller.pl?action=Part/edit&part.id' . $partid; + $row->{partnumber}->{link} = 'controller.pl?action=Part/edit&part.id=' . $partid; } sub action_stock { @@ -697,7 +704,7 @@ sub init_stocktaking_cutoff_date { my $now = DateTime->now_local; my $cutoff = DateTime->new(year => $now->year, month => 12, day => 31); if ($now->month < 1) { - $cutoff->substract(years => 1); + $cutoff->subtract(years => 1); } return $cutoff; } @@ -781,22 +788,55 @@ sub build_unit_select { sub mini_journal { my ($self) = @_; - # get last 10 transaction ids - my $query = 'SELECT trans_id, max(itime) FROM inventory GROUP BY trans_id ORDER BY max(itime) DESC LIMIT 10'; - my @ids = selectall_array_query($::form, $::form->get_standard_dbh, $query); + # We want to fetch the last 10 inventory events (inventory rows with the same trans_id) + # To prevent a Seq Scan on inventory set an index on inventory.itime + # Each event may have one (transfer_in/out) or two (transfer) inventory rows + # So fetch the last 20, group by trans_id, limit to the last 10 trans_ids, + # and then extract the inventory ids from those 10 trans_ids + # By querying Inventory->get_all via the id instead of trans_id we can make + # use of the existing index on id - my $objs; - $objs = SL::DB::Manager::Inventory->get_all(query => [ trans_id => \@ids ]) if @ids; + # inventory ids of the most recent 10 inventory trans_ids + my $query = <get_all( + query => [ id => [ \"$query" ] ], # " make emacs happy + with_objects => [ 'parts', 'trans_type', 'bin', 'bin.warehouse' ], # prevent lazy loading in template + sort_by => 'itime DESC', + ); + # remember order of trans_ids from query, for ordering hash later + my @sorted_trans_ids = uniq map { $_->trans_id } @$objs; + + # at most 2 of them belong to a transaction and the qty determines in or out. my %transactions; for (@$objs) { $transactions{ $_->trans_id }{ $_->qty > 0 ? 'in' : 'out' } = $_; $transactions{ $_->trans_id }{base} = $_; } - # and get them into order again - my @sorted = map { $transactions{$_} } @ids; + + # because the inventory transactions were built in a hash, we need to sort the + # hash by using the original sort order of the trans_ids + my @sorted = map { $transactions{$_} } @sorted_trans_ids; return \@sorted; } @@ -913,7 +953,7 @@ sub _already_counted { my %bestbefore_filter; if ($::instance_conf->get_show_bestbefore) { - %bestbefore_filter = (bestbefore => $params{bestbefore}); + %bestbefore_filter = (bestbefore => ($params{bestbefore} || undef)); } SL::DB::Manager::Stocktaking->get_all(query => [and => [parts_id => $part->id,