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: