C4::Reserves - Koha functions for dealing with reservation.
use C4::Reserves;
This modules provides somes functions to deal with reservations.
Reserves are stored in reserves table. The following columns contains important values : - priority >0 : then the reserve is at 1st stage, and not yet affected to any item. =0 : then the reserve is being dealed - found : NULL : means the patron requested the 1st available, and we haven't chosen the item T(ransit) : the reserve is linked to an item but is in transit to the pickup branch W(aiting) : the reserve is linked to an item, is at the pickup branch, and is waiting on the hold shelf F(inished) : the reserve has been completed, and is done P(rocessing) : reserved item has been returned using self-check machine and reserve needs to be confirmed by librarian before notice is send and status changed to waiting. Applicable only if HoldsNeedProcessingSIP system preference is set. - itemnumber : empty : the reserve is still unaffected to an item filled: the reserve is attached to an item The complete workflow is : ==== 1st use case ==== patron request a document, 1st available : P >0, F=NULL, I=NULL a library having it run "transfertodo", and clic on the list if there is no transfer to do, the reserve waiting patron can pick it up P =0, F=W, I=filled if there is a transfer to do, write in branchtransfer P =0, F=T, I=filled The pickup library receive the book, it check in P =0, F=W, I=filled The patron borrow the book P =0, F=F, I=filled ==== 2nd use case ==== patron requests a document, a given item, If pickup is holding branch P =0, F=W, I=filled If transfer needed, write in branchtransfer P =0, F=T, I=filled The pickup library receive the book, it checks it in P =0, F=W, I=filled The patron borrow the book P =0, F=F, I=filled
AddReserve( { branchcode => $branchcode, borrowernumber => $borrowernumber, biblionumber => $biblionumber, priority => $priority, reservation_date => $reservation_date, expiration_date => $expiration_date, notes => $notes, title => $title, itemnumber => $itemnumber, found => $found, itemtype => $itemtype, item_group_id => $item_group_id } );
Adds reserve and generates HOLDPLACED message and HOLDPLACED_PATRON message.
The following tables are available witin the HOLDPLACED message:
branches borrowers biblio biblioitems items reserves
The following tables are available within the HOLDPLACED_PATRON message:
borrowers reserves
$canReserve = &CanBookBeReserved($borrowernumber, $biblionumber, $branchcode, $params) if ($canReserve eq 'OK') { #We can reserve this Item! } $params are passed directly through to CanItemBeReserved
See CanItemBeReserved() for possible return values.
$canReserve = &CanItemBeReserved($patron, $item, $branchcode, $params) if ($canReserve->{status} eq 'OK') { #We can reserve this Item! } current params are: 'ignore_hold_counts' - we use this routine to check if an item can fill a hold - on this case we should not check if there are too many holds as we only care about reservability
@RETURNS { status => OK }, if the Item can be reserved. { status => ageRestricted }, if the Item is age restricted for this borrower. { status => damaged }, if the Item is damaged. { status => cannotReserveFromOtherBranches }, if syspref 'canreservefromotherbranches' is OK. { status => branchNotInHoldGroup }, if borrower home library is not in hold group, and holds are only allowed from hold groups. { status => tooManyReserves, limit => $limit }, if the borrower has exceeded their maximum reserve amount. { status => notReservable }, if holds on this item are not allowed { status => libraryNotFound }, if given branchcode is not an existing library { status => libraryNotPickupLocation }, if given branchcode is not configured to be a pickup location { status => cannotBeTransferred }, if branch transfer limit applies on given item and branchcode { status => pickupNotInHoldGroup }, pickup location is not in hold group, and pickup locations are only allowed from hold groups. { status => recall }, if the borrower has already placed a recall on this item
$fee = ChargeReserveFee( $borrowernumber, $fee, $title ); Charge the fee for a reserve (if $fee > 0)
$fee = GetReserveFee( $borrowernumber, $biblionumber ); Calculate the fee for a reserve (if applicable).
$reservestatus = GetReserveStatus($itemnumber);
Takes an itemnumber and returns the status of the reserve placed on it. If several reserves exist, the reserve with the lower priority is given.
($status, $matched_reserve, $possible_reserves) = &CheckReserves($item); ($status, $matched_reserve, $possible_reserves) = &CheckReserves($item, $lookahead);
Find a book in the reserves.
$item
is the book's item. $lookahead
is the number of days to look in advance for future reserves.
As I understand it, &CheckReserves
looks for the given item in the reserves. If it is found, that's a match, and $status
is set to Waiting
.
Otherwise, it finds the most important item in the reserves with the same biblio number as this book (I'm not clear on this) and returns it with $status
set to Reserved
.
&CheckReserves
returns a two-element list:
$status
is either Waiting
, Reserved
(see above), or 0.
$reserve
is the reserve item that matched. It is a reference-to-hash whose keys are mostly the fields of the reserves table in the Koha database.
CancelExpiredReserves();
Cancels all reserves with an expiration date from before today.
AutoUnsuspendReserves();
Unsuspends all suspended reserves with a suspend_until date from before today.
ModReserve({ rank => $rank, reserve_id => $reserve_id, branchcode => $branchcode [, itemnumber => $itemnumber ] [, biblionumber => $biblionumber, $borrowernumber => $borrowernumber ] });
Change a hold request's priority or cancel it.
$rank
specifies the effect of the change. If $rank
is 'n', nothing happens. This corresponds to leaving a request alone when changing its priority in the holds queue for a bib.
If $rank
is 'del', the hold request is cancelled.
If $rank
is an integer greater than zero, the priority of the request is set to that value. Since priority != 0 means that the item is not waiting on the hold shelf, setting the priority to a non-zero value also sets the request's found status and waiting date to NULL.
If the hold is 'found' (waiting, in-transit, processing) the only field that can be updated is the expiration date.
The optional $itemnumber
parameter is used only when $rank
is a non-zero integer; if supplied, the itemnumber of the hold request is set accordingly; if omitted, the itemnumber is cleared.
FIXME: Note that the forgoing can have the effect of causing item-level hold requests to turn into title-level requests. This will be fixed once reserves has separate columns for requested itemnumber and supplying itemnumber.
&ModReserveStatus($itemnumber, $newstatus);
Update the reserve status for the active (priority=0) reserve.
$itemnumber is the itemnumber the reserve is on
$newstatus is the new status.
&ModReserveAffect($itemnumber,$borrowernumber,$diffBranchSend,$reserve_id, $desk_id, $notify_library);
This function affect an item and a status for a given reserve, either fetched directly by record_id, or by borrowernumber and itemnumber or biblionumber. If only biblionumber is given, only first reserve returned is affected, which is ok for anything but multi-item holds.
if $transferToDo is not set, then the status is set to "Waiting" as well. otherwise, a transfer is on the way, and the end of the transfer will take care of the waiting status
This function also removes any entry of the hold in holds queue table.
($messages,$nextreservinfo) = &ModReserveCancelAll($itemnumber,$borrowernumber,$reason);
function to cancel reserve and check other reserves
&ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber)
Reduce the values of queued list
my $is_available = IsAvailableForItemLevelRequest( $item_record, $borrower_record, $pickup_branchcode );
Checks whether a given item record is available for an item-level hold request. An item is available if
* it is not lost AND * it is not damaged AND * it is not withdrawn AND * a waiting or in transit reserve is placed on * does not have a not for loan value > 0
Need to check the issuingrules onshelfholds column, if this is set items on the shelf can be placed on hold
Note that IsAvailableForItemLevelRequest() does not check if the staff operator is authorized to place a request on the item - in particular, this routine does not check IndependentBranches and canreservefromotherbranches.
Note also that this subroutine does not checks smart rules limits for item by reservesallowed/holds_per_record values, this complemented in calling code with calls and checks with CanItemBeReserved or CanBookBeReserved.
ItemsAnyAvailableAndNotRestricted( { biblionumber => $biblionumber, patron => $patron });
This function checks all items for specified biblionumber (numeric) against patron (object) and returns true (1) if at least one item available for loan/check out/present/not held and also checks other parameters logic which not restricts item for hold at all (for ex. AllowHoldsOnDamagedItems or 'holdallowed' own/sibling library)
AlterPriority( $where, $reserve_id, $prev_priority, $next_priority, $first_priority, $last_priority );
This function changes a reserve's priority up, down, to the top, or to the bottom. Input: $where is 'up', 'down', 'top' or 'bottom'. Biblionumber, Date reserve was placed
ToggleLowestPriority( $borrowernumber, $biblionumber );
This function sets the lowestPriority field to true if is false, and false if it is true.
SuspendAll( borrowernumber => $borrowernumber, [ biblionumber => $biblionumber, ] [ suspend_until => $suspend_until, ] [ suspend => $suspend ] ); This function accepts a set of hash keys as its parameters. It requires either borrowernumber or biblionumber, or both. suspend_until is wholly optional.
_FixPriority({ reserve_id => $reserve_id, [rank => $rank,] [ignoreSetLowestRank => $ignoreSetLowestRank] }); or _FixPriority({ biblionumber => $biblionumber});
This routine adjusts the priority of a hold request and holds on the same bib.
In the first form, where a reserve_id is passed, the priority of the hold is set to supplied rank, and other holds for that bib are adjusted accordingly. If the rank is "del", the hold is cancelled. If no rank is supplied, all of the holds on that bib have their priority adjusted as if the second form had been used.
In the second form, where a biblionumber is passed, the holds on that bib (that are not captured) are sorted in order of increasing priority, then have reserves.priority set so that the first non-captured hold has its priority set to 1, the second non-captured hold has its priority set to 2, and so forth.
In both cases, holds that have the lowestPriority flag on are have their priority adjusted to ensure that they remain at the end of the line.
Note that the ignoreSetLowestRank parameter is meant to be used only when _FixPriority calls itself.
@results = &_Findgroupreserve($biblionumber, $itemnumber, $lookahead, $ignore_borrowers);
Looks for a holds-queue based item-specific match first, then for a holds-queue title-level match, returning the first match found. If neither, then we look for non-holds-queue based holds. Lookahead is the number of days to look in advance.
&_Findgroupreserve
returns : @results
is an array of references-to-hash whose keys are mostly fields from the reserves table of the Koha database, plus biblioitemnumber
.
This routine with either return: 1 - Item specific holds from the holds queue 2 - Title level holds from the holds queue 3 - All holds for this biblionumber
All return values will respect any borrowernumbers passed as arrayref in $ignore_borrowers
_koha_notify_reserve( $hold->reserve_id );
Sends a notification to the patron that their hold has been filled (through ModReserveAffect)
The letter code for this notice may be found using the following query:
select distinct letter_code from message_transports inner join message_attributes using (message_attribute_id) where message_name = 'Hold_Filled'
This will probably sipmly be 'HOLD', but because it is defined in the database, it is subject to addition or change.
The following tables are availalbe witin the notice:
branches borrowers biblio biblioitems reserves items
_koha_notify_hold_changed( $hold_object );
$new_priority = _ShiftPriority( $biblionumber, $priority );
This increments the priority of all reserves after the one with either the lowest date after $reservedate
or the lowest priority after $priority
.
It effectively makes room for a new reserve to be inserted with a certain priority, which is returned.
This is most useful when the reservedate can be set by the user. It allows the new reserve to be placed before other reserves that have a later reservedate. Since priority also is set by the form in reserves/request.pl the sub accounts for that too.
MoveReserve( $itemnumber, $borrowernumber, $cancelreserve )
Use when checking out an item to handle reserves If $cancelreserve boolean is set to true, it will remove existing reserve
MergeHolds($dbh,$to_biblio, $from_biblio);
This shifts the holds from $from_biblio
to $to_biblio
and reorders them by the date they were placed
RevertWaitingStatus({ itemnumber => $itemnumber }); Reverts a 'waiting' hold back to a regular hold with a priority of 1. Caveat: Any waiting hold fixed with RevertWaitingStatus will be an item level hold, even if it was only a bibliolevel hold to begin with. This is because we can no longer know if a hold was item-level or bib-level after a hold has been set to waiting status.
ReserveSlip( { branchcode => $branchcode, borrowernumber => $borrowernumber, biblionumber => $biblionumber, [ itemnumber => $itemnumber, ] [ barcode => $barcode, ] } )
Returns letter hash ( see C4::Letters::GetPreparedLetter ) or undef
The letter code will be HOLD_SLIP, and the following tables are available within the slip:
reserves branches borrowers biblio biblioitems items
my $p = CalculatePriority($biblionumber, $resdate);
Calculate priority for a new reserve on biblionumber, placing it at the end of the line of all holds whose start date falls before the current system time and that are neither on the hold shelf or in transit.
The reserve date parameter is optional; if it is supplied, the priority is based on the set of holds whose start date falls before the parameter value.
After calculation of this priority, it is recommended to call _ShiftPriority. Note that this is currently done in AddReserves.
my $holds_per_record = ReservesControlBranch( $borrowernumber, $biblionumber );
For multiple holds on a given record for a given patron, the max number of record level holds that a patron can be placed is the highest value of the holds_per_record rule for each item if the record for that patron. This subroutine finds and returns the highest holds_per_record rule value for a given patron id and record id.
Koha Development Team <http://koha-community.org/>