diff --git a/C4/HoldsQueue.pm b/C4/HoldsQueue.pm
index 33b6eb6873..8a23493142 100644
--- a/C4/HoldsQueue.pm
+++ b/C4/HoldsQueue.pm
@@ -798,10 +798,11 @@ sub MapItemsToHoldRequests {
holdingbranch => $item->{holdingbranch},
pickup_branch => $request->{branchcode}
|| $request->{borrowerbranch},
- reserve_id => $request->{reserve_id},
- item_level => $request->{item_level_hold},
- reservedate => $request->{reservedate},
- reservenotes => $request->{reservenotes},
+ reserve_id => $request->{reserve_id},
+ item_level => $request->{item_level_hold},
+ reservedate => $request->{reservedate},
+ reservenotes => $request->{reservenotes},
+ local_holdgroup_match => 1,
};
$allocated_items{ $item->{itemnumber} }++;
$request->{allocated} = 1;
@@ -848,10 +849,11 @@ sub MapItemsToHoldRequests {
holdingbranch => $item->{holdingbranch},
pickup_branch => $request->{branchcode}
|| $request->{borrowerbranch},
- reserve_id => $request->{reserve_id},
- item_level => $request->{item_level_hold},
- reservedate => $request->{reservedate},
- reservenotes => $request->{reservenotes},
+ reserve_id => $request->{reserve_id},
+ item_level => $request->{item_level_hold},
+ reservedate => $request->{reservedate},
+ reservenotes => $request->{reservenotes},
+ local_holdgroup_match => 1,
};
$allocated_items{ $item->{itemnumber} }++;
$request->{allocated} = 1;
@@ -1086,19 +1088,20 @@ sub CreatePicklistFromItemMap {
my $sth_load = $dbh->prepare( "
INSERT INTO tmp_holdsqueue (biblionumber,itemnumber,barcode,surname,firstname,phone,borrowernumber,
cardnumber,reservedate,title, itemcallnumber,
- holdingbranch,pickbranch,notes, hold_group_id, item_level_request)
+ holdingbranch,pickbranch,notes, hold_group_id, item_level_request, local_holdgroup_match)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
" );
foreach my $itemnumber ( sort keys %$item_map ) {
- my $mapped_item = $item_map->{$itemnumber};
- my $biblionumber = $mapped_item->{biblionumber};
- my $borrowernumber = $mapped_item->{borrowernumber};
- my $pickbranch = $mapped_item->{pickup_branch};
- my $holdingbranch = $mapped_item->{holdingbranch};
- my $reservedate = $mapped_item->{reservedate};
- my $reservenotes = $mapped_item->{reservenotes};
- my $item_level = $mapped_item->{item_level};
+ my $mapped_item = $item_map->{$itemnumber};
+ my $biblionumber = $mapped_item->{biblionumber};
+ my $borrowernumber = $mapped_item->{borrowernumber};
+ my $pickbranch = $mapped_item->{pickup_branch};
+ my $holdingbranch = $mapped_item->{holdingbranch};
+ my $reservedate = $mapped_item->{reservedate};
+ my $reservenotes = $mapped_item->{reservenotes};
+ my $item_level = $mapped_item->{item_level};
+ my $local_holdgroup_match = $mapped_item->{local_holdgroup_match} ? 1 : 0;
my $item = Koha::Items->find($itemnumber);
my $barcode = $item->barcode;
@@ -1123,7 +1126,7 @@ sub CreatePicklistFromItemMap {
$sth_load->execute(
$biblionumber, $itemnumber, $barcode, $surname, $firstname, $phone, $borrowernumber,
$cardnumber, $reservedate, $title, $itemcallnumber,
- $holdingbranch, $pickbranch, $reservenotes, $hold_group_id, $item_level
+ $holdingbranch, $pickbranch, $reservenotes, $hold_group_id, $item_level, $local_holdgroup_match
);
}
}
@@ -1139,7 +1142,7 @@ sub AddToHoldTargetMap {
my $schema = Koha::Database->new->schema;
my $insert_sql = q(
- INSERT INTO hold_fill_targets (borrowernumber, biblionumber, itemnumber, source_branchcode, item_level_request, reserve_id) VALUES (?, ?, ?, ?, ?, ?)
+ INSERT INTO hold_fill_targets (borrowernumber, biblionumber, itemnumber, source_branchcode, item_level_request, reserve_id, local_holdgroup_match) VALUES (?, ?, ?, ?, ?, ?, ?)
);
my $sth_insert = $dbh->prepare($insert_sql);
@@ -1150,7 +1153,8 @@ sub AddToHoldTargetMap {
$dbh->do( 'DELETE FROM hold_fill_targets WHERE itemnumber = ?', {}, $itemnumber );
$sth_insert->execute(
$mapped_item->{borrowernumber}, $mapped_item->{biblionumber}, $itemnumber,
- $mapped_item->{holdingbranch}, $mapped_item->{item_level}, $mapped_item->{reserve_id}
+ $mapped_item->{holdingbranch}, $mapped_item->{item_level}, $mapped_item->{reserve_id},
+ $mapped_item->{local_holdgroup_match} ? 1 : 0,
);
}
);
diff --git a/C4/Reserves.pm b/C4/Reserves.pm
index 0bb4e60c56..1abef7ac71 100644
--- a/C4/Reserves.pm
+++ b/C4/Reserves.pm
@@ -895,6 +895,31 @@ sub CheckReserves {
}
}
+ # Local holds priority exclusivity period: when the queue has
+ # targeted a local-group item for this hold and we're still
+ # within the exclusivity window, skip non-local items so the
+ # targeted local item can fulfil it. If the queue has not yet
+ # run for this reserve (no hold_fill_targets row), we fall
+ # through and let the hold be filled normally.
+ my $excl_period = C4::Context->preference('LocalHoldsPriorityExclusivityPeriod');
+ if ( $excl_period
+ && !$local_hold_match
+ && !$local_hold_group_match
+ && $res->{reserve_id} )
+ {
+ my $reservedate_dt = eval { dt_from_string( $res->{reservedate} ) };
+ if ($reservedate_dt) {
+ my $age_days = dt_from_string->delta_days($reservedate_dt)->in_units('days');
+ if ( $age_days < $excl_period ) {
+ my $target =
+ Koha::Database->new->schema->resultset('HoldFillTarget')
+ ->search( { reserve_id => $res->{reserve_id} }, { rows => 1 } )
+ ->next;
+ next if $target && $target->local_holdgroup_match;
+ }
+ }
+ }
+
# See if this item is more important than what we've got so far
if ( ( $res->{'priority'} && $res->{'priority'} < $priority )
|| $local_hold_match
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
index 71721ab086..a27cb4b6b8 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
@@ -1103,6 +1103,12 @@ Circulation:
homebranch: "home library"
holdingbranch: "holding library"
-
Note: If a group option is selected, LocalHoldsPriorityPatronControl and LocalHoldsPriorityItemControl will use the library hold group of the selected libraries.
+ -
+ - For
+ - pref: LocalHoldsPriorityExclusivityPeriod
+ class: integer
+ - days after a hold is placed, only items flagged by the holds queue as a local hold group match may be used to fill the hold. Set to 0 to disable.
+ -
Note: Only takes effect when LocalHoldsPriority is set to something other than 'Don't give'.
-
- pref: OPACHoldsIfAvailableAtPickup
choices: