#
# This file is part of Koha.
#
-# Koha is free software; you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or (at your option) any later
-# version.
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
#
-# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
#
-# You should have received a copy of the GNU General Public License along
-# with Koha; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
# FIXME: expand perldoc, explain intended logic
use C4::Circulation;
use C4::Members;
use C4::Biblio;
-use C4::Dates qw/format_date/;
+use Koha::DateUtils;
use List::Util qw(shuffle);
+use List::MoreUtils qw(any);
use Data::Dumper;
-use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
BEGIN {
- $VERSION = 3.03;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(
my $dbh = C4::Context->dbh;
my $transport_costs = $dbh->selectall_arrayref("SELECT * FROM transport_cost",{ Slice => {} });
+ my $today = dt_from_string();
+ my $calendars;
my %transport_cost_matrix;
foreach (@$transport_costs) {
- my $from = $_->{frombranch};
- my $to = $_->{tobranch};
- my $cost = $_->{cost};
+ my $from = $_->{frombranch};
+ my $to = $_->{tobranch};
+ my $cost = $_->{cost};
my $disabled = $_->{disable_transfer};
- $transport_cost_matrix{$to}{$from} = { cost => $cost, disable_transfer => $disabled };
+ $transport_cost_matrix{$to}{$from} = {
+ cost => $cost,
+ disable_transfer => $disabled
+ };
+
+ if ( C4::Context->preference("HoldsQueueSkipClosed") ) {
+ $calendars->{$from} ||= Koha::Calendar->new( branchcode => $from );
+ $transport_cost_matrix{$to}{$from}{disable_transfer} ||=
+ $calendars->{$from}->is_holiday( $today );
+ }
+
}
return \%transport_cost_matrix;
}
$sth->execute(@bind_params);
my $items = [];
while ( my $row = $sth->fetchrow_hashref ){
- $row->{reservedate} = format_date($row->{reservedate});
my $record = GetMarcBiblio($row->{biblionumber});
if ($record){
- $row->{subtitle} = GetRecordValue('subtitle',$record,'')->[0]->{subfield};
+ $row->{subtitle} = [ map { $_->{subfield} } @{ GetRecordValue( 'subtitle', $record, '' ) } ];
$row->{parts} = GetRecordValue('parts',$record,'')->[0]->{subfield};
$row->{numbers} = GetRecordValue('numbers',$record,'')->[0]->{subfield};
}
* it is not currently in transit
* it is not lost
* it is not sitting on the hold shelf
+ * it is not damaged (unless AllowHoldsOnDamagedItems is on)
=cut
$items_query .= "WHERE items.notforloan = 0
AND holdingbranch IS NOT NULL
AND itemlost = 0
- AND wthdrawn = 0";
+ AND withdrawn = 0";
$items_query .= " AND damaged = 0" unless C4::Context->preference('AllowHoldsOnDamagedItems');
$items_query .= " AND items.onloan IS NULL
AND (itemtypes.notforloan IS NULL OR itemtypes.notforloan = 0)
AND (found IS NOT NULL OR priority = 0)
)
AND items.biblionumber = ?";
- $items_query .= " AND damaged = 0 "
- unless C4::Context->preference('AllowHoldsOnDamagedItems');
my @params = ($biblionumber, $biblionumber);
if ($branches_to_use && @$branches_to_use) {
my @items = grep { ! scalar GetTransfers($_->{itemnumber}) } @$itm;
return [ grep {
my $rule = GetBranchItemRule($_->{homebranch}, $_->{itype});
- $_->{holdallowed} = $rule->{holdallowed} != 0
+ $_->{holdallowed} = $rule->{holdallowed};
} @items ];
}
return unless scalar(@$hold_requests) > 0;
return unless scalar(@$available_items) > 0;
- my $automatic_return = C4::Context->preference("AutomaticItemReturn");
-
# identify item-level requests
my %specific_items_requested = map { $_->{itemnumber} => 1 }
grep { defined($_->{itemnumber}) }
my $pickup_branch = $request->{branchcode} || $request->{borrowerbranch};
my ($itemnumber, $holdingbranch);
- my $holding_branch_items = $automatic_return ? undef : $items_by_branch{$pickup_branch};
+ my $holding_branch_items = $items_by_branch{$pickup_branch};
if ( $holding_branch_items ) {
foreach my $item (@$holding_branch_items) {
if ( $request->{borrowerbranch} eq $item->{homebranch} ) {
}
}
$holdingbranch = $pickup_branch;
- $itemnumber ||= $holding_branch_items->[0]->{itemnumber};
}
elsif ($transport_cost_matrix) {
$pull_branches = [keys %items_by_branch];
$itemnumber = $item->{itemnumber};
last;
}
- $itemnumber ||= $holding_branch_items->[0]->{itemnumber};
}
else {
- warn "No transport costs for $pickup_branch";
+ next;
}
}
} else {
$pull_branches = [keys %items_by_branch];
}
+
+ # Try picking items where the home and pickup branch match first
PULL_BRANCHES:
foreach my $branch (@$pull_branches) {
my $holding_branch_items = $items_by_branch{$branch}
$holdingbranch ||= $branch;
foreach my $item (@$holding_branch_items) {
next if $pickup_branch ne $item->{homebranch};
+ next if ( $item->{holdallowed} == 1 && $item->{homebranch} ne $request->{borrowerbranch} );
$itemnumber = $item->{itemnumber};
$holdingbranch = $branch;
last PULL_BRANCHES;
}
}
- $itemnumber ||= $items_by_branch{$holdingbranch}->[0]->{itemnumber}
- if $holdingbranch;
+
+ # Now try items from the least cost branch based on the transport cost matrix or StaticHoldsQueueWeight
+ unless ( $itemnumber ) {
+ foreach my $current_item ( @{ $items_by_branch{$holdingbranch} } ) {
+ if ( $holdingbranch && ( $current_item->{holdallowed} == 2 || $request->{borrowerbranch} eq $current_item->{homebranch} ) ) {
+ $itemnumber = $current_item->{itemnumber};
+ last; # quit this loop as soon as we have a suitable item
+ }
+ }
+ }
+
+ # Now try for items for any item that can fill this hold
+ unless ( $itemnumber ) {
+ PULL_BRANCHES2:
+ foreach my $branch (@$pull_branches) {
+ my $holding_branch_items = $items_by_branch{$branch}
+ or next;
+
+ foreach my $item (@$holding_branch_items) {
+ next if ( $item->{holdallowed} == 1 && $item->{homebranch} ne $request->{borrowerbranch} );
+
+ $itemnumber = $item->{itemnumber};
+ $holdingbranch = $branch;
+ last PULL_BRANCHES2;
+ }
+ }
+ }
}
if ($itemnumber) {
}
sub load_branches_to_pull_from {
- my $static_branch_list = C4::Context->preference("StaticHoldsQueueWeight")
- or return;
-
- my @branches_to_use = map _trim($_), split /,/, $static_branch_list;
-
- @branches_to_use = shuffle(@branches_to_use) if C4::Context->preference("RandomizeHoldsQueueWeight");
+ my @branches_to_use;
+
+ my $static_branch_list = C4::Context->preference("StaticHoldsQueueWeight");
+ @branches_to_use = map { _trim($_) } split( /,/, $static_branch_list )
+ if $static_branch_list;
+
+ @branches_to_use =
+ Koha::Database->new()->schema()->resultset('Branch')
+ ->get_column('branchcode')->all()
+ unless (@branches_to_use);
+
+ @branches_to_use = shuffle(@branches_to_use)
+ if C4::Context->preference("RandomizeHoldsQueueWeight");
+
+ my $today = dt_from_string();
+ if ( C4::Context->preference('HoldsQueueSkipClosed') ) {
+ @branches_to_use = grep {
+ !Koha::Calendar->new( branchcode => $_ )
+ ->is_holiday( $today )
+ } @branches_to_use;
+ }
return \@branches_to_use;
}
#$from - arrayref
my ($to, $from, $transport_cost_matrix) = @_;
-# Nothing really spectacular: supply to branch, a list of potential from branches
-# and find the minimum from - to value from the transport_cost_matrix
- return $from->[0] if @$from == 1;
+ # Nothing really spectacular: supply to branch, a list of potential from branches
+ # and find the minimum from - to value from the transport_cost_matrix
+ return $from->[0] if ( @$from == 1 && $transport_cost_matrix->{$to}{$from->[0]}->{disable_transfer} != 1 );
+
+ # If the pickup library is in the list of libraries to pull from,
+ # return that library right away, it is obviously the least costly
+ return ($to) if any { $_ eq $to } @$from;
my ($least_cost, @branch);
foreach (@$from) {