my $result = {};
my @attempts = (
- ['SELECT holdallowed, returnbranch
+ ['SELECT holdallowed, returnbranch, hold_fulfillment_policy
FROM branch_item_rules
WHERE branchcode = ?
AND itemtype = ?', $branchcode, $itemtype],
- ['SELECT holdallowed, returnbranch
+ ['SELECT holdallowed, returnbranch, hold_fulfillment_policy
FROM default_branch_circ_rules
WHERE branchcode = ?', $branchcode],
- ['SELECT holdallowed, returnbranch
+ ['SELECT holdallowed, returnbranch, hold_fulfillment_policy
FROM default_branch_item_rules
WHERE itemtype = ?', $itemtype],
- ['SELECT holdallowed, returnbranch
+ ['SELECT holdallowed, returnbranch, hold_fulfillment_policy
FROM default_circ_rules'],
);
# defaults tables, we have to check that the key we want is set, not
# just that a row was returned
$result->{'holdallowed'} = $search_result->{'holdallowed'} unless ( defined $result->{'holdallowed'} );
+ $result->{'hold_fulfillment_policy'} = $search_result->{'hold_fulfillment_policy'} unless ( defined $result->{'hold_fulfillment_policy'} );
$result->{'returnbranch'} = $search_result->{'returnbranch'} unless ( defined $result->{'returnbranch'} );
}
# built-in default circulation rule
$result->{'holdallowed'} = 2 unless ( defined $result->{'holdallowed'} );
+ $result->{'hold_fulfillment_policy'} = 'any' unless ( defined $result->{'hold_fulfillment_policy'} );
$result->{'returnbranch'} = 'homebranch' unless ( defined $result->{'returnbranch'} );
return $result;
return [ grep {
my $rule = GetBranchItemRule($_->{homebranch}, $_->{itype});
$_->{holdallowed} = $rule->{holdallowed};
+ $_->{hold_fulfillment_policy} = $rule->{hold_fulfillment_policy};
} @items ];
}
# is this an item-level request?
if (defined($request->{itemnumber})) {
# fill it if possible; if not skip it
- if (exists $items_by_itemnumber{$request->{itemnumber}} and
- not exists $allocated_items{$request->{itemnumber}}) {
- $item_map{$request->{itemnumber}} = {
+ if (
+ exists $items_by_itemnumber{ $request->{itemnumber} }
+ and not exists $allocated_items{ $request->{itemnumber} }
+ and ( # Don't fill item level holds that contravene the hold pickup policy at this time
+ ( $items_by_itemnumber{ $request->{itemnumber} }->{hold_fulfillment_policy} eq 'any' )
+ || ( $request->{branchcode} eq $items_by_itemnumber{ $request->{itemnumber} }->{ $items_by_itemnumber{ $request->{itemnumber} }->{hold_fulfillment_policy} } )
+ )
+
+ )
+ {
+
+ $item_map{ $request->{itemnumber} } = {
borrowernumber => $request->{borrowernumber},
- biblionumber => $request->{biblionumber},
- holdingbranch => $items_by_itemnumber{$request->{itemnumber}}->{holdingbranch},
- pickup_branch => $request->{branchcode} || $request->{borrowerbranch},
- item_level => 1,
- reservedate => $request->{reservedate},
- reservenotes => $request->{reservenotes},
+ biblionumber => $request->{biblionumber},
+ holdingbranch => $items_by_itemnumber{ $request->{itemnumber} }->{holdingbranch},
+ pickup_branch => $request->{branchcode} || $request->{borrowerbranch},
+ item_level => 1,
+ reservedate => $request->{reservedate},
+ reservenotes => $request->{reservenotes},
};
- $allocated_items{$request->{itemnumber}}++;
+ $allocated_items{ $request->{itemnumber} }++;
$num_items_remaining--;
}
} else {
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} ) {
+ if (
+ $request->{borrowerbranch} eq $item->{homebranch}
+ && ( ( $item->{hold_fulfillment_policy} eq 'any' ) # Don't fill item level holds that contravene the hold pickup policy at this time
+ || $request->{branchcode} eq $item->{ $item->{hold_fulfillment_policy} } )
+ )
+ {
$itemnumber = $item->{itemnumber};
last;
}
foreach my $item (@$holding_branch_items) {
next if $request->{borrowerbranch} ne $item->{homebranch};
+ # Don't fill item level holds that contravene the hold pickup policy at this time
+ next unless $item->{hold_fulfillment_policy} eq 'any'
+ || $request->{branchcode} eq $item->{ $item->{hold_fulfillment_policy} };
+
$itemnumber = $item->{itemnumber};
last;
}
next if $pickup_branch ne $item->{homebranch};
next if ( $item->{holdallowed} == 1 && $item->{homebranch} ne $request->{borrowerbranch} );
+ # Don't fill item level holds that contravene the hold pickup policy at this time
+ next unless $item->{hold_fulfillment_policy} eq 'any'
+ || $request->{branchcode} eq $item->{ $item->{hold_fulfillment_policy} };
+
$itemnumber = $item->{itemnumber};
$holdingbranch = $branch;
last PULL_BRANCHES;
unless ( $itemnumber ) {
foreach my $current_item ( @{ $items_by_branch{$holdingbranch} } ) {
if ( $holdingbranch && ( $current_item->{holdallowed} == 2 || $request->{borrowerbranch} eq $current_item->{homebranch} ) ) {
+
+ # Don't fill item level holds that contravene the hold pickup policy at this time
+ next unless $current_item->{hold_fulfillment_policy} eq 'any'
+ || $request->{branchcode} eq $current_item->{ $current_item->{hold_fulfillment_policy} };
+
$itemnumber = $current_item->{itemnumber};
last; # quit this loop as soon as we have a suitable item
}
foreach my $item (@$holding_branch_items) {
next if ( $item->{holdallowed} == 1 && $item->{homebranch} ne $request->{borrowerbranch} );
+ # Don't fill item level holds that contravene the hold pickup policy at this time
+ next unless $item->{hold_fulfillment_policy} eq 'any'
+ || $request->{branchcode} eq $item->{ $item->{hold_fulfillment_policy} };
+
$itemnumber = $item->{itemnumber};
$holdingbranch = $branch;
last PULL_BRANCHES2;
my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$iteminfo->{'itype'});
next if ($branchitemrule->{'holdallowed'} == 0);
next if (($branchitemrule->{'holdallowed'} == 1) && ($branch ne $borrowerinfo->{'branchcode'}));
+ next if ( ($branchitemrule->{hold_fulfillment_policy} ne 'any') && ($res->{branchcode} ne $iteminfo->{ $branchitemrule->{hold_fulfillment_policy} }) );
$priority = $res->{'priority'};
$highest = $res;
last if $local_hold_match;
my $maxissueqty = $input->param('maxissueqty');
my $maxonsiteissueqty = $input->param('maxonsiteissueqty');
my $holdallowed = $input->param('holdallowed');
+ my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy');
my $returnbranch = $input->param('returnbranch');
$maxissueqty =~ s/\s//g;
$maxissueqty = undef if $maxissueqty !~ /^\d+/;
my $sth_search = $dbh->prepare("SELECT count(*) AS total
FROM default_circ_rules");
my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules
- (maxissueqty, maxonsiteissueqty, holdallowed, returnbranch)
- VALUES (?, ?, ?, ?)");
+ (maxissueqty, maxonsiteissueqty, holdallowed, hold_fulfillment_policy, returnbranch)
+ VALUES (?, ?, ?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_circ_rules
- SET maxissueqty = ?, maxonsiteissueqty = ?, holdallowed = ?, returnbranch = ?");
+ SET maxissueqty = ?, maxonsiteissueqty = ?, holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?");
$sth_search->execute();
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $returnbranch);
+ $sth_update->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
} else {
- $sth_insert->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $returnbranch);
+ $sth_insert->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
}
} else {
my $sth_search = $dbh->prepare("SELECT count(*) AS total
FROM default_branch_circ_rules
WHERE branchcode = ?");
my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules
- (branchcode, maxissueqty, maxonsiteissueqty, holdallowed, returnbranch)
- VALUES (?, ?, ?, ?, ?)");
+ (branchcode, maxissueqty, maxonsiteissueqty, holdallowed, hold_fulfillment_policy, returnbranch)
+ VALUES (?, ?, ?, ?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules
- SET maxissueqty = ?, maxonsiteissueqty = ?, holdallowed = ?, returnbranch = ?
+ SET maxissueqty = ?, maxonsiteissueqty = ?, holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
WHERE branchcode = ?");
$sth_search->execute($branch);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $returnbranch, $branch);
+ $sth_update->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch, $branch);
} else {
- $sth_insert->execute($branch, $maxissueqty, $maxonsiteissueqty, $holdallowed, $returnbranch);
+ $sth_insert->execute($branch, $maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
}
}
}
}
}
elsif ($op eq "add-branch-item") {
- my $itemtype = $input->param('itemtype');
- my $holdallowed = $input->param('holdallowed');
- my $returnbranch = $input->param('returnbranch');
+ my $itemtype = $input->param('itemtype');
+ my $holdallowed = $input->param('holdallowed');
+ my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy');
+ my $returnbranch = $input->param('returnbranch');
+
$holdallowed =~ s/\s//g;
$holdallowed = undef if $holdallowed !~ /^\d+/;
my $sth_search = $dbh->prepare("SELECT count(*) AS total
FROM default_circ_rules");
my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules
- (holdallowed, returnbranch)
- VALUES (?, ?)");
+ (holdallowed, hold_fulfillment_policy, returnbranch)
+ VALUES (?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_circ_rules
- SET holdallowed = ?, returnbranch = ?");
+ SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?");
$sth_search->execute();
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($holdallowed, $returnbranch);
+ $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch);
} else {
- $sth_insert->execute($holdallowed, $returnbranch);
+ $sth_insert->execute($holdallowed, $hold_fulfillment_policy, $returnbranch);
}
} else {
my $sth_search = $dbh->prepare("SELECT count(*) AS total
FROM default_branch_item_rules
WHERE itemtype = ?");
my $sth_insert = $dbh->prepare("INSERT INTO default_branch_item_rules
- (itemtype, holdallowed, returnbranch)
- VALUES (?, ?, ?)");
+ (itemtype, holdallowed, hold_fulfillment_policy, returnbranch)
+ VALUES (?, ?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_branch_item_rules
- SET holdallowed = ?, returnbranch = ?
+ SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
WHERE itemtype = ?");
$sth_search->execute($itemtype);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($holdallowed, $returnbranch, $itemtype);
+ $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $itemtype);
} else {
- $sth_insert->execute($itemtype, $holdallowed, $returnbranch);
+ $sth_insert->execute($itemtype, $holdallowed, $hold_fulfillment_policy, $returnbranch);
}
}
} elsif ($itemtype eq "*") {
FROM default_branch_circ_rules
WHERE branchcode = ?");
my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules
- (branchcode, holdallowed, returnbranch)
- VALUES (?, ?, ?)");
+ (branchcode, holdallowed, hold_fulfillment_policy, returnbranch)
+ VALUES (?, ?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules
- SET holdallowed = ?, returnbranch = ?
+ SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
WHERE branchcode = ?");
$sth_search->execute($branch);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($holdallowed, $returnbranch, $branch);
+ $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $branch);
} else {
- $sth_insert->execute($branch, $holdallowed, $returnbranch);
+ $sth_insert->execute($branch, $holdallowed, $hold_fulfillment_policy, $returnbranch);
}
} else {
my $sth_search = $dbh->prepare("SELECT count(*) AS total
WHERE branchcode = ?
AND itemtype = ?");
my $sth_insert = $dbh->prepare("INSERT INTO branch_item_rules
- (branchcode, itemtype, holdallowed, returnbranch)
- VALUES (?, ?, ?, ?)");
+ (branchcode, itemtype, holdallowed, hold_fulfillment_policy, returnbranch)
+ VALUES (?, ?, ?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE branch_item_rules
- SET holdallowed = ?, returnbranch = ?
+ SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
WHERE branchcode = ?
AND itemtype = ?");
$sth_search->execute($branch, $itemtype);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($holdallowed, $returnbranch, $branch, $itemtype);
+ $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $branch, $itemtype);
} else {
- $sth_insert->execute($branch, $itemtype, $holdallowed, $returnbranch);
+ $sth_insert->execute($branch, $itemtype, $holdallowed, $hold_fulfillment_policy, $returnbranch);
}
}
}
# note undef holdallowed so that template can deal with them
foreach my $entry (@sorted_branch_item_rules) {
- $entry->{holdallowed_any} = 1 if($entry->{holdallowed} == 2);
- $entry->{holdallowed_same} = 1 if($entry->{holdallowed} == 1);
+ $entry->{holdallowed_any} = 1 if ( $entry->{holdallowed} == 2 );
+ $entry->{holdallowed_same} = 1 if ( $entry->{holdallowed} == 1 );
}
$template->param(show_branch_cat_rule_form => 1);
my $defaults = $sth_defaults->fetchrow_hashref;
if ($defaults) {
- $template->param(default_holdallowed_none => 1) if($defaults->{holdallowed} == 0);
- $template->param(default_holdallowed_same => 1) if($defaults->{holdallowed} == 1);
- $template->param(default_holdallowed_any => 1) if($defaults->{holdallowed} == 2);
- $template->param(default_maxissueqty => $defaults->{maxissueqty});
- $template->param(default_maxonsiteissueqty => $defaults->{maxonsiteissueqty});
- $template->param(default_returnbranch => $defaults->{returnbranch});
+ $template->param( default_holdallowed_none => 1 ) if ( $defaults->{holdallowed} == 0 );
+ $template->param( default_holdallowed_same => 1 ) if ( $defaults->{holdallowed} == 1 );
+ $template->param( default_holdallowed_any => 1 ) if ( $defaults->{holdallowed} == 2 );
+ $template->param( default_hold_fulfillment_policy => $defaults->{hold_fulfillment_policy} );
+ $template->param( default_maxissueqty => $defaults->{maxissueqty} );
+ $template->param( default_maxonsiteissueqty => $defaults->{maxonsiteissueqty} );
+ $template->param( default_returnbranch => $defaults->{returnbranch} );
}
$template->param(default_rules => ($defaults ? 1 : 0));
--- /dev/null
+ALTER TABLE branch_item_rules ADD COLUMN hold_fulfillment_policy ENUM('any', 'homebranch', 'holdingbranch') NOT NULL DEFAULT 'any' AFTER holdallowed;
+ALTER TABLE default_branch_circ_rules ADD COLUMN hold_fulfillment_policy ENUM('any', 'homebranch', 'holdingbranch') NOT NULL DEFAULT 'any' AFTER holdallowed;
+ALTER TABLE default_branch_item_rules ADD COLUMN hold_fulfillment_policy ENUM('any', 'homebranch', 'holdingbranch') NOT NULL DEFAULT 'any' AFTER holdallowed;
+ALTER TABLE default_circ_rules ADD COLUMN hold_fulfillment_policy ENUM('any', 'homebranch', 'holdingbranch') NOT NULL DEFAULT 'any' AFTER holdallowed;
`branchcode` varchar(10) NOT NULL, -- the branch this rule is for (branches.branchcode)
`itemtype` varchar(10) NOT NULL, -- the item type this rule applies to (items.itype)
`holdallowed` tinyint(1) default NULL, -- the number of holds allowed
+ hold_fulfillment_policy ENUM('any', 'homebranch', 'holdingbranch') NOT NULL DEFAULT 'any', -- limit trapping of holds by branchcode
`returnbranch` varchar(15) default NULL, -- the branch the item returns to (homebranch, holdingbranch, noreturn)
PRIMARY KEY (`itemtype`,`branchcode`),
KEY `branch_item_rules_ibfk_2` (`branchcode`),
`maxissueqty` int(4) default NULL,
`maxonsiteissueqty` int(4) default NULL,
`holdallowed` tinyint(1) default NULL,
+ hold_fulfillment_policy ENUM('any', 'homebranch', 'holdingbranch') NOT NULL DEFAULT 'any', -- limit trapping of holds by branchcode
`returnbranch` varchar(15) default NULL,
PRIMARY KEY (`branchcode`),
CONSTRAINT `default_branch_circ_rules_ibfk_1` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`)
CREATE TABLE `default_branch_item_rules` (
`itemtype` varchar(10) NOT NULL,
`holdallowed` tinyint(1) default NULL,
+ hold_fulfillment_policy ENUM('any', 'homebranch', 'holdingbranch') NOT NULL DEFAULT 'any', -- limit trapping of holds by branchcode
`returnbranch` varchar(15) default NULL,
PRIMARY KEY (`itemtype`),
CONSTRAINT `default_branch_item_rules_ibfk_1` FOREIGN KEY (`itemtype`) REFERENCES `itemtypes` (`itemtype`)
`maxissueqty` int(4) default NULL,
`maxonsiteissueqty` int(4) default NULL,
`holdallowed` int(1) default NULL,
+ hold_fulfillment_policy ENUM('any', 'homebranch', 'holdingbranch') NOT NULL DEFAULT 'any', -- limit trapping of holds by branchcode
`returnbranch` varchar(15) default NULL,
PRIMARY KEY (`singleton`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
<th>Total current checkouts allowed</th>
<th>Total current on-site checkouts allowed</th>
<th>Hold policy</th>
+ <th>Hold pickup library match</th>
<th>Return policy</th>
<th> </th>
<th> </th>
</option>
</select>
</td>
+ <td>
+ <select name="hold_fulfillment_policy">
+ [% IF default_hold_fulfillment_policy == 'any' %]
+ <option value="any" selected="selected">
+ any library
+ </option>
+ [% ELSE %]
+ <option value="any">
+ any library
+ </option>
+ [% END %]
+
+ [% IF default_hold_fulfillment_policy == 'homebranch' %]
+ <option value="homebranch" selected="selected">
+ item's home library
+ </option>
+ [% ELSE %]
+ <option value="homebranch">
+ item's home library
+ </option>
+ [% END %]
+
+ [% IF default_hold_fulfillment_policy == 'holdingbranch' %]
+ <option value="holdingbranch" selected="selected">
+ item's holding library
+ </option>
+ [% ELSE %]
+ <option value="holdingbranch">
+ item's holding library
+ </option>
+ [% END %]
+ </select>
+ </td>
<td>
<select name="returnbranch">
[% IF ( default_returnbranch == 'homebranch' ) %]
<tr>
<th>Item type</th>
<th>Hold policy</th>
+ <th>Hold pickup library match</th>
<th>Return policy</th>
<th> </th>
</tr>
No holds allowed
[% END %]
</td>
+ <td>[% IF ( branch_item_rule_loo.hold_fulfillment_policy == 'any' ) %]
+ any library
+ [% ELSIF ( branch_item_rule_loo.hold_fulfillment_policy == 'homebranch' ) %]
+ item's home library
+ [% ELSIF ( branch_item_rule_loo.hold_fulfillment_policy == 'holdingbranch' ) %]
+ item's holding library
+ [% END %]
+ </td>
<td>[% IF ( branch_item_rule_loo.returnbranch == 'homebranch' ) %]
Item returns home
[% ELSIF ( branch_item_rule_loo.returnbranch == 'holdingbranch' ) %]
<option value="0">No holds allowed</option>
</select>
</td>
+ <td>
+ <select name="hold_fulfillment_policy">
+ <option value="any">
+ any library
+ </option>
+
+ <option value="homebranch">
+ item's home library
+ </option>
+
+ <option value="holdingbranch">
+ item's holding library
+ </option>
+ </select>
+ </td>
<td>
<select name="returnbranch">
<option value="homebranch">Item returns home</option>
--- /dev/null
+#!/usr/bin/perl
+
+use Modern::Perl;
+
+use C4::Context;
+
+use Test::More tests => 10;
+
+use t::lib::TestBuilder;
+
+BEGIN {
+ use FindBin;
+ use lib $FindBin::Bin;
+ use_ok('C4::Reserves');
+}
+
+my $schema = Koha::Database->schema;
+$schema->storage->txn_begin;
+my $dbh = C4::Context->dbh;
+
+my $builder = t::lib::TestBuilder->new;
+
+my $library1 = $builder->build({
+ source => 'Branch',
+});
+my $library2 = $builder->build({
+ source => 'Branch',
+});
+my $library3 = $builder->build({
+ source => 'Branch',
+});
+
+my $bib_title = "Test Title";
+
+my $borrower = $builder->build({
+ source => 'Borrower',
+ value => {
+ categorycode => 'S',
+ branchcode => $library1->{branchcode},
+ }
+});
+
+# Test hold_fulfillment_policy
+my ( $itemtype ) = @{ $dbh->selectrow_arrayref("SELECT itemtype FROM itemtypes LIMIT 1") };
+my $borrowernumber = $borrower->{borrowernumber};
+my $library_A = $library1->{branchcode};
+my $library_B = $library2->{branchcode};
+my $library_C = $library3->{branchcode};
+$dbh->do("DELETE FROM reserves");
+$dbh->do("DELETE FROM issues");
+$dbh->do("DELETE FROM items");
+$dbh->do("DELETE FROM biblio");
+$dbh->do("DELETE FROM biblioitems");
+$dbh->do("DELETE FROM transport_cost");
+$dbh->do("DELETE FROM tmp_holdsqueue");
+$dbh->do("DELETE FROM hold_fill_targets");
+$dbh->do("DELETE FROM default_branch_circ_rules");
+$dbh->do("DELETE FROM default_branch_item_rules");
+$dbh->do("DELETE FROM default_circ_rules");
+$dbh->do("DELETE FROM branch_item_rules");
+
+$dbh->do("INSERT INTO biblio (frameworkcode, author, title, datecreated) VALUES ('', 'Koha test', '$bib_title', '2011-02-01')");
+
+my $biblionumber = $dbh->selectrow_array("SELECT biblionumber FROM biblio WHERE title = '$bib_title'")
+ or BAIL_OUT("Cannot find newly created biblio record");
+
+$dbh->do("INSERT INTO biblioitems (biblionumber, marcxml, itemtype) VALUES ($biblionumber, '', '$itemtype')");
+
+my $biblioitemnumber =
+ $dbh->selectrow_array("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber = $biblionumber")
+ or BAIL_OUT("Cannot find newly created biblioitems record");
+
+$dbh->do("
+ INSERT INTO items (biblionumber, biblioitemnumber, homebranch, holdingbranch, notforloan, damaged, itemlost, withdrawn, onloan, itype)
+ VALUES ($biblionumber, $biblioitemnumber, '$library_A', '$library_B', 0, 0, 0, 0, NULL, '$itemtype')
+");
+
+my $itemnumber =
+ $dbh->selectrow_array("SELECT itemnumber FROM items WHERE biblionumber = $biblionumber")
+ or BAIL_OUT("Cannot find newly created item");
+
+# With hold_fulfillment_policy = homebranch, hold should only be picked up if pickup branch = homebranch
+$dbh->do("DELETE FROM default_circ_rules");
+$dbh->do("INSERT INTO default_circ_rules ( holdallowed, hold_fulfillment_policy ) VALUES ( 2, 'homebranch' )");
+
+my $holds_queue;
+# Home branch matches pickup branch
+my $reserve_id = AddReserve( $library_A, $borrowernumber, $biblionumber, '', 1 );
+my ( $status ) = CheckReserves($itemnumber);
+is( $status, 'Reserved', "Hold where pickup branch matches home branch targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Holding branch matches pickup branch
+$reserve_id = AddReserve( $library_B, $borrowernumber, $biblionumber, '', 1 );
+( $status ) = CheckReserves($itemnumber);
+is($status, q{}, "Hold where pickup ne home, pickup eq home not targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Neither branch matches pickup branch
+$reserve_id = AddReserve( $library_C, $borrowernumber, $biblionumber, '', 1 );
+( $status ) = CheckReserves($itemnumber);
+is( $status, q{}, "Hold where pickup ne home, pickup ne holding not targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# With hold_fulfillment_policy = holdingbranch, hold should only be picked up if pickup branch = holdingbranch
+$dbh->do("DELETE FROM default_circ_rules");
+$dbh->do("INSERT INTO default_circ_rules ( holdallowed, hold_fulfillment_policy ) VALUES ( 2, 'holdingbranch' )");
+
+# Home branch matches pickup branch
+$reserve_id = AddReserve( $library_A, $borrowernumber, $biblionumber, '', 1 );
+( $status ) = CheckReserves($itemnumber);
+is( $status, q{}, "Hold where pickup eq home, pickup ne holding not targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Holding branch matches pickup branch
+$reserve_id = AddReserve( $library_B, $borrowernumber, $biblionumber, '', 1 );
+( $status ) = CheckReserves($itemnumber);
+is( $status, 'Reserved', "Hold where pickup ne home, pickup eq holding targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Neither branch matches pickup branch
+$reserve_id = AddReserve( $library_C, $borrowernumber, $biblionumber, '', 1 );
+( $status ) = CheckReserves($itemnumber);
+is( $status, q{}, "Hold where pickup ne home, pickup ne holding not targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# With hold_fulfillment_policy = any, hold should be pikcup up reguardless of matching home or holding branch
+$dbh->do("DELETE FROM default_circ_rules");
+$dbh->do("INSERT INTO default_circ_rules ( holdallowed, hold_fulfillment_policy ) VALUES ( 2, 'any' )");
+
+# Home branch matches pickup branch
+$reserve_id = AddReserve( $library_A, $borrowernumber, $biblionumber, '', 1 );
+( $status ) = CheckReserves($itemnumber);
+is( $status, 'Reserved', "Hold where pickup eq home, pickup ne holding targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Holding branch matches pickup branch
+$reserve_id = AddReserve( $library_B, $borrowernumber, $biblionumber, '', 1 );
+( $status ) = CheckReserves($itemnumber);
+is( $status, 'Reserved', "Hold where pickup ne home, pickup eq holding targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Neither branch matches pickup branch
+$reserve_id = AddReserve( $library_C, $borrowernumber, $biblionumber, '', 1 );
+( $status ) = CheckReserves($itemnumber);
+is( $status, 'Reserved', "Hold where pickup ne home, pickup ne holding targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# End testing hold_fulfillment_policy
+
+# Cleanup
+$schema->storage->txn_rollback;
use Modern::Perl;
-use Test::More tests => 26;
+use Test::More tests => 35;
use Data::Dumper;
+
use C4::Branch;
use C4::Calendar;
use C4::Context;
my $borrower = $builder->build({
source => 'Borrower',
value => {
- categorycode => 'S',
branchcode => $library1->{branchcode},
}
});
my $borrower1 = $builder->build({
source => 'Borrower',
value => {
- categorycode => 'S',
branchcode => $branchcodes[0],
},
});
my $borrower2 = $builder->build({
source => 'Borrower',
value => {
- categorycode => 'S',
branchcode => $branchcodes[1],
},
});
my $borrower3 = $builder->build({
source => 'Borrower',
value => {
- categorycode => 'S',
branchcode => $branchcodes[2],
},
});
is( @$holds_queue, 0, "Bug 15062 - Holds queue with Transport Cost Matrix will transfer item even if transfers disabled");
# End Bug 15062
+# Test hold_fulfillment_policy
+C4::Context->set_preference( "UseTransportCostMatrix", 0 );
+$borrowernumber = $borrower3->{borrowernumber};
+$library_A = $library1->{branchcode};
+$library_B = $library2->{branchcode};
+$library_C = $library3->{branchcode};
+$dbh->do("DELETE FROM reserves");
+$dbh->do("DELETE FROM issues");
+$dbh->do("DELETE FROM items");
+$dbh->do("DELETE FROM biblio");
+$dbh->do("DELETE FROM biblioitems");
+$dbh->do("DELETE FROM transport_cost");
+$dbh->do("DELETE FROM tmp_holdsqueue");
+$dbh->do("DELETE FROM hold_fill_targets");
+$dbh->do("DELETE FROM default_branch_circ_rules");
+$dbh->do("DELETE FROM default_branch_item_rules");
+$dbh->do("DELETE FROM default_circ_rules");
+$dbh->do("DELETE FROM branch_item_rules");
+
+$dbh->do("INSERT INTO biblio (frameworkcode, author, title, datecreated) VALUES ('', 'Koha test', '$TITLE', '2011-02-01')");
+
+$biblionumber = $dbh->selectrow_array("SELECT biblionumber FROM biblio WHERE title = '$TITLE'")
+ or BAIL_OUT("Cannot find newly created biblio record");
+
+$dbh->do("INSERT INTO biblioitems (biblionumber, marcxml, itemtype) VALUES ($biblionumber, '', '$itemtype')");
+
+$biblioitemnumber =
+ $dbh->selectrow_array("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber = $biblionumber")
+ or BAIL_OUT("Cannot find newly created biblioitems record");
+
+$dbh->do("
+ INSERT INTO items (biblionumber, biblioitemnumber, homebranch, holdingbranch, notforloan, damaged, itemlost, withdrawn, onloan, itype)
+ VALUES ($biblionumber, $biblioitemnumber, '$library_A', '$library_B', 0, 0, 0, 0, NULL, '$itemtype')
+");
+
+# With hold_fulfillment_policy = homebranch, hold should only be picked up if pickup branch = homebranch
+$dbh->do("DELETE FROM default_circ_rules");
+$dbh->do("INSERT INTO default_circ_rules ( holdallowed, hold_fulfillment_policy ) VALUES ( 2, 'homebranch' )");
+
+# Home branch matches pickup branch
+$reserve_id = AddReserve( $library_A, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 1, "Hold where pickup branch matches home branch targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Holding branch matches pickup branch
+$reserve_id = AddReserve( $library_B, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 0, "Hold where pickup ne home, pickup eq home not targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Neither branch matches pickup branch
+$reserve_id = AddReserve( $library_C, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 0, "Hold where pickup ne home, pickup ne holding not targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# With hold_fulfillment_policy = holdingbranch, hold should only be picked up if pickup branch = holdingbranch
+$dbh->do("DELETE FROM default_circ_rules");
+$dbh->do("INSERT INTO default_circ_rules ( holdallowed, hold_fulfillment_policy ) VALUES ( 2, 'holdingbranch' )");
+
+# Home branch matches pickup branch
+$reserve_id = AddReserve( $library_A, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 0, "Hold where pickup eq home, pickup ne holding not targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Holding branch matches pickup branch
+$reserve_id = AddReserve( $library_B, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 1, "Hold where pickup ne home, pickup eq holding targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Neither branch matches pickup branch
+$reserve_id = AddReserve( $library_C, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 0, "Hold where pickup ne home, pickup ne holding not targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# With hold_fulfillment_policy = any, hold should be pikcup up reguardless of matching home or holding branch
+$dbh->do("DELETE FROM default_circ_rules");
+$dbh->do("INSERT INTO default_circ_rules ( holdallowed, hold_fulfillment_policy ) VALUES ( 2, 'any' )");
+
+# Home branch matches pickup branch
+$reserve_id = AddReserve( $library_A, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 1, "Hold where pickup eq home, pickup ne holding targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Holding branch matches pickup branch
+$reserve_id = AddReserve( $library_B, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 1, "Hold where pickup ne home, pickup eq holding targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# Neither branch matches pickup branch
+$reserve_id = AddReserve( $library_C, $borrowernumber, $biblionumber, '', 1 );
+C4::HoldsQueue::CreateQueue();
+$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
+is( @$holds_queue, 1, "Hold where pickup ne home, pickup ne holding targeted" );
+CancelReserve( { reserve_id => $reserve_id } );
+
+# End testing hold_fulfillment_policy
+
# Cleanup
$schema->storage->txn_rollback;