X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FReserves.pm;h=83738408afc2b0dbfb73c63dea021e5a2f49b0cf;hb=20c6bd0c4d3673297d765f75add8c6152bb4dae9;hp=b4c6b43abcfedfc6dba365711eab0d9bb21bb707;hpb=aef52b8585321904c225e6c8ad27bf4b9be82d0e;p=koha_gimpoz diff --git a/C4/Reserves.pm b/C4/Reserves.pm index b4c6b43abc..83738408af 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -2,7 +2,7 @@ package C4::Reserves; # Copyright 2000-2002 Katipo Communications # 2006 SAN Ouest Provence -# 2007 BibLibre Paul POULAIN +# 2007-2010 BibLibre Paul POULAIN # # This file is part of Koha. # @@ -50,14 +50,15 @@ C4::Reserves - Koha functions for dealing with reservation. =head1 DESCRIPTION - this modules provides somes functions to deal with reservations. - +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 choosen the item - W(aiting) : the reserve has an itemnumber affected, and is on the way + 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 - itemnumber : empty : the reserve is still unaffected to an item filled: the reserve is attached to an item @@ -67,20 +68,18 @@ C4::Reserves - Koha functions for dealing with reservation. 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=NULL, I=filled + if there is a transfer to do, write in branchtransfer P =0, F=T, I=filled The pickup library recieve 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=NULL, I=filled - The pickup library recieve the book, it checks it in 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 - -=head1 FUNCTIONS -=over 2 +=head1 FUNCTIONS =cut @@ -100,7 +99,8 @@ BEGIN { &GetReserveCount &GetReserveFee &GetReserveInfo - + &GetReserveStatus + &GetOtherReserves &ModReserveFill @@ -123,7 +123,7 @@ BEGIN { ); } -=item AddReserve +=head2 AddReserve AddReserve($branch,$borrowernumber,$biblionumber,$constraint,$bibitems,$priority,$resdate,$expdate,$notes,$title,$checkitem,$found) @@ -142,7 +142,11 @@ sub AddReserve { my $const = lc substr( $constraint, 0, 1 ); $resdate = format_date_in_iso( $resdate ) if ( $resdate ); $resdate = C4::Dates->today( 'iso' ) unless ( $resdate ); - $expdate = format_date_in_iso( $expdate ) if ( $expdate ); + if ($expdate) { + $expdate = format_date_in_iso( $expdate ); + } else { + undef $expdate; # make reserves.expirationdate default to null rather than '0000-00-00' + } if ( C4::Context->preference( 'AllowHoldDateInFuture' ) ) { # Make room in reserves for this before those of a later reserve date $priority = _ShiftPriorityByDateAndPriority( $biblionumber, $resdate, $priority ); @@ -190,7 +194,9 @@ sub AddReserve { my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); my $biblio = GetBiblioData($biblionumber); my $letter = C4::Letters::getletter( 'reserves', 'HOLDPLACED'); - my $admin_email_address = C4::Context->preference('KohaAdminEmailAddress'); + my $branchcode = $borrower->{branchcode}; + my $branch_details = C4::Branch::GetBranchDetail($branchcode); + my $admin_email_address =$branch_details->{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress'); my %keys = (%$borrower, %$biblio); foreach my $key (keys %keys) { @@ -228,9 +234,9 @@ sub AddReserve { return; # FIXME: why not have a useful return value? } -=item GetReservesFromBiblionumber +=head2 GetReservesFromBiblionumber -($count, $title_reserves) = &GetReserves($biblionumber); + ($count, $title_reserves) = &GetReserves($biblionumber); This function gets the list of reservations for one C<$biblionumber>, returning a count of the reserves and an arrayref pointing to the reserves for C<$biblionumber>. @@ -308,11 +314,11 @@ sub GetReservesFromBiblionumber { return ( $#results + 1, \@results ); } -=item GetReservesFromItemnumber +=head2 GetReservesFromItemnumber ( $reservedate, $borrowernumber, $branchcode ) = GetReservesFromItemnumber($itemnumber); - TODO :: Description here +TODO :: Description here =cut @@ -333,12 +339,12 @@ sub GetReservesFromItemnumber { return ( $reservedate, $borrowernumber, $branchcode ); } -=item GetReservesFromBorrowernumber +=head2 GetReservesFromBorrowernumber $borrowerreserv = GetReservesFromBorrowernumber($borrowernumber,$tatus); - - TODO :: Descritpion - + +TODO :: Descritpion + =cut sub GetReservesFromBorrowernumber { @@ -367,92 +373,27 @@ sub GetReservesFromBorrowernumber { return @$data; } #------------------------------------------------------------------------------------- -=item CanBookBeReserved +=head2 CanBookBeReserved -$error = &CanBookBeReserved($borrowernumber, $biblionumber) + $error = &CanBookBeReserved($borrowernumber, $biblionumber) =cut sub CanBookBeReserved{ my ($borrowernumber, $biblionumber) = @_; - my $dbh = C4::Context->dbh; - my $biblio = GetBiblioData($biblionumber); - my $borrower = C4::Members::GetMember(borrowernumber=>$borrowernumber); - my $controlbranch = C4::Context->preference('ReservesControlBranch'); - my $itype = C4::Context->preference('item-level_itypes'); - my $reservesrights= 0; - my $reservescount = 0; - - # we retrieve the user rights - my @args; - my $rightsquery = "SELECT categorycode, itemtype, branchcode, reservesallowed - FROM issuingrules - WHERE categorycode IN (?, '*')"; - push @args,$borrower->{categorycode}; - - if($controlbranch eq "ItemHomeLibrary"){ - $rightsquery .= " AND branchcode = '*'"; - }elsif($controlbranch eq "PatronLibrary"){ - $rightsquery .= " AND branchcode IN (?,'*')"; - push @args, $borrower->{branchcode}; - } - - if(not $itype){ - $rightsquery .= " AND itemtype IN (?,'*')"; - push @args, $biblio->{itemtype}; - }else{ - $rightsquery .= " AND itemtype = '*'"; - } - - $rightsquery .= " ORDER BY categorycode DESC, itemtype DESC, branchcode DESC"; - my $sthrights = $dbh->prepare($rightsquery); - $sthrights->execute(@args); - - if(my $row = $sthrights->fetchrow_hashref()){ - $reservesrights = $row->{reservesallowed}; - } - - @args = (); - # we count how many reserves the borrower have - my $countquery = "SELECT count(*) as count - FROM reserves - LEFT JOIN items USING (itemnumber) - LEFT JOIN biblioitems ON (reserves.biblionumber=biblioitems.biblionumber) - LEFT JOIN borrowers USING (borrowernumber) - WHERE borrowernumber = ? - "; - push @args, $borrowernumber; - - if(not $itype){ - $countquery .= "AND itemtype = ?"; - push @args, $biblio->{itemtype}; - } - - if($controlbranch eq "PatronLibrary"){ - $countquery .= " AND borrowers.branchcode = ? "; - push @args, $borrower->{branchcode}; - } - - my $sthcount = $dbh->prepare($countquery); - $sthcount->execute(@args); - - if(my $row = $sthcount->fetchrow_hashref()){ - $reservescount = $row->{count}; - } - if($reservescount < $reservesrights){ - return 1; - }else{ - return 0; + my @items = GetItemsInfo($biblionumber); + foreach my $item (@items){ + return 1 if CanItemBeReserved($borrowernumber, $item->{itemnumber}); } - + return 0; } -=item CanItemBeReserved +=head2 CanItemBeReserved -$error = &CanItemBeReserved($borrowernumber, $itemnumber) + $error = &CanItemBeReserved($borrowernumber, $itemnumber) -this function return 1 if an item can be issued by this borrower. +This function return 1 if an item can be issued by this borrower. =cut @@ -539,9 +480,9 @@ sub CanItemBeReserved{ } } #-------------------------------------------------------------------------------- -=item GetReserveCount +=head2 GetReserveCount -$number = &GetReserveCount($borrowernumber); + $number = &GetReserveCount($borrowernumber); this function returns the number of reservation for a borrower given on input arg. @@ -563,9 +504,9 @@ sub GetReserveCount { return $row->{counter}; } -=item GetOtherReserves +=head2 GetOtherReserves -($messages,$nextreservinfo)=$GetOtherReserves(itemnumber); + ($messages,$nextreservinfo)=$GetOtherReserves(itemnumber); Check queued list of this document and check if this document must be transfered @@ -613,9 +554,9 @@ sub GetOtherReserves { return ( $messages, $nextreservinfo ); } -=item GetReserveFee +=head2 GetReserveFee -$fee = GetReserveFee($borrowernumber,$biblionumber,$constraint,$biblionumber); + $fee = GetReserveFee($borrowernumber,$biblionumber,$constraint,$biblionumber); Calculate the fee for a reserve @@ -716,9 +657,9 @@ sub GetReserveFee { return $fee; } -=item GetReservesToBranch +=head2 GetReservesToBranch -@transreserv = GetReservesToBranch( $frombranch ); + @transreserv = GetReservesToBranch( $frombranch ); Get reserve list for a given branch @@ -743,9 +684,9 @@ sub GetReservesToBranch { return (@transreserv); } -=item GetReservesForBranch +=head2 GetReservesForBranch -@transreserv = GetReservesForBranch($frombranch); + @transreserv = GetReservesForBranch($frombranch); =cut @@ -776,7 +717,19 @@ sub GetReservesForBranch { return (@transreserv); } -=item CheckReserves +sub GetReserveStatus { + my ($itemnumber) = @_; + + my $dbh = C4::Context->dbh; + + my $itemstatus = $dbh->prepare("SELECT found FROM reserves WHERE itemnumber = ?"); + + $itemstatus->execute($itemnumber); + my ($found) = $itemstatus->fetchrow_array; + return $found; +} + +=head2 CheckReserves ($status, $reserve) = &CheckReserves($itemnumber); ($status, $reserve) = &CheckReserves(undef, $barcode); @@ -851,6 +804,12 @@ sub CheckReserves { } else { # See if this item is more important than what we've got so far if ( $res->{'priority'} && $res->{'priority'} < $priority ) { + my $borrowerinfo=C4::Members::GetMemberDetails($res->{'borrowernumber'}); + my $iteminfo=C4::Items::GetItem($itemnumber); + my $branch=C4::Circulation::_GetCircControlBranch($iteminfo,$borrowerinfo); + my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$iteminfo->{'itype'}); + next if ($branchitemrule->{'holdallowed'} == 0); + next if (($branchitemrule->{'holdallowed'} == 1) && ($branch ne $borrowerinfo->{'branchcode'})); $priority = $res->{'priority'}; $highest = $res; } @@ -869,12 +828,12 @@ sub CheckReserves { } } -=item CancelExpiredReserves +=head2 CancelExpiredReserves CancelExpiredReserves(); - - Cancels all reserves with an expiration date from before today. - + +Cancels all reserves with an expiration date from before today. + =cut sub CancelExpiredReserves { @@ -892,7 +851,7 @@ sub CancelExpiredReserves { } -=item CancelReserve +=head2 CancelReserve &CancelReserve($biblionumber, $itemnumber, $borrowernumber); @@ -990,17 +949,13 @@ sub CancelReserve { $sth->execute( $biblio, $borr ); # now fix the priority on the others.... - _FixPriority( $priority, $biblio ); + _FixPriority( $biblio, $borr ); } } -=item ModReserve - -=over 4 +=head2 ModReserve -ModReserve($rank, $biblio, $borrower, $branch[, $itemnumber]) - -=back + ModReserve($rank, $biblio, $borrower, $branch[, $itemnumber]) Change a hold request's priority or cancel it. @@ -1022,7 +977,7 @@ C<$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 +B 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. @@ -1076,7 +1031,7 @@ sub ModReserve { } } -=item ModReserveFill +=head2 ModReserveFill &ModReserveFill($reserve); @@ -1140,13 +1095,13 @@ sub ModReserveFill { # now fix the priority on the others (if the priority wasn't # already sorted!).... unless ( $priority == 0 ) { - _FixPriority( $priority, $biblionumber ); + _FixPriority( $biblionumber, $borrowernumber ); } } -=item ModReserveStatus +=head2 ModReserveStatus -&ModReserveStatus($itemnumber, $newstatus); + &ModReserveStatus($itemnumber, $newstatus); Update the reserve status for the active (priority=0) reserve. @@ -1175,9 +1130,9 @@ sub ModReserveStatus { } } -=item ModReserveAffect +=head2 ModReserveAffect -&ModReserveAffect($itemnumber,$borrowernumber,$diffBranchSend); + &ModReserveAffect($itemnumber,$borrowernumber,$diffBranchSend); This function affect an item and a status for a given reserve The itemnumber parameter is used to find the biblionumber. @@ -1187,6 +1142,7 @@ to the correct reserve. 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 + =cut sub ModReserveAffect { @@ -1210,7 +1166,8 @@ sub ModReserveAffect { $query = " UPDATE reserves SET priority = 0, - itemnumber = ? + itemnumber = ?, + found = 'T' WHERE borrowernumber = ? AND biblionumber = ? "; @@ -1238,11 +1195,11 @@ sub ModReserveAffect { return; } -=item ModReserveCancelAll +=head2 ModReserveCancelAll -($messages,$nextreservinfo) = &ModReserveCancelAll($itemnumber,$borrowernumber); + ($messages,$nextreservinfo) = &ModReserveCancelAll($itemnumber,$borrowernumber); - function to cancel reserv,check other reserves, and transfer document if it's necessary +function to cancel reserv,check other reserves, and transfer document if it's necessary =cut @@ -1260,9 +1217,9 @@ sub ModReserveCancelAll { return ( $messages, $nextreservinfo ); } -=item ModReserveMinusPriority +=head2 ModReserveMinusPriority -&ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber) + &ModReserveMinusPriority($itemnumber,$borrowernumber,$biblionumber) Reduce the values of queuded list @@ -1285,12 +1242,13 @@ sub ModReserveMinusPriority { _FixPriority($biblionumber, $borrowernumber, '0'); } -=item GetReserveInfo +=head2 GetReserveInfo -&GetReserveInfo($borrowernumber,$biblionumber); + &GetReserveInfo($borrowernumber,$biblionumber); + +Get item and borrower details for a current hold. +Current implementation this query should have a single result. - Get item and borrower details for a current hold. - Current implementation this query should have a single result. =cut sub GetReserveInfo { @@ -1339,13 +1297,9 @@ sub GetReserveInfo { } -=item IsAvailableForItemLevelRequest - -=over 4 +=head2 IsAvailableForItemLevelRequest -my $is_available = IsAvailableForItemLevelRequest($itemnumber); - -=back + my $is_available = IsAvailableForItemLevelRequest($itemnumber); Checks whether a given item record is available for an item-level hold request. An item is available if @@ -1411,17 +1365,19 @@ sub IsAvailableForItemLevelRequest { if (C4::Context->preference('AllowOnShelfHolds')) { return $available_per_item; } else { - return ($available_per_item and $item->{onloan}); + return ($available_per_item and ($item->{onloan} or GetReserveStatus($itemnumber) eq "W")); } } -=item AlterPriority -AlterPriority( $where, $borrowernumber, $biblionumber, $reservedate ); +=head2 AlterPriority + + AlterPriority( $where, $borrowernumber, $biblionumber, $reservedate ); 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 =cut + sub AlterPriority { my ( $where, $borrowernumber, $biblionumber ) = @_; @@ -1450,10 +1406,12 @@ sub AlterPriority { } } -=item ToggleLowestPriority -ToggleLowestPriority( $borrowernumber, $biblionumber ); +=head2 ToggleLowestPriority + + ToggleLowestPriority( $borrowernumber, $biblionumber ); This function sets the lowestPriority field to true if is false, and false if it is true. + =cut sub ToggleLowestPriority { @@ -1475,16 +1433,16 @@ sub ToggleLowestPriority { _FixPriority( $biblionumber, $borrowernumber, '999999' ); } -=item _FixPriority +=head2 _FixPriority -&_FixPriority($biblio,$borrowernumber,$rank,$ignoreSetLowestRank); + &_FixPriority($biblio,$borrowernumber,$rank,$ignoreSetLowestRank); - Only used internally (so don't export it) - Changed how this functions works # - Now just gets an array of reserves in the rank order and updates them with - the array index (+1 as array starts from 0) - and if $rank is supplied will splice item from the array and splice it back in again - in new priority rank +Only used internally (so don't export it) +Changed how this functions works # +Now just gets an array of reserves in the rank order and updates them with +the array index (+1 as array starts from 0) +and if $rank is supplied will splice item from the array and splice it back in again +in new priority rank =cut @@ -1496,13 +1454,13 @@ sub _FixPriority { } if ( $rank eq "W" || $rank eq "0" ) { - # make sure priority for waiting items is 0 + # make sure priority for waiting or in-transit items is 0 my $query = qq/ UPDATE reserves SET priority = 0 WHERE biblionumber = ? AND borrowernumber = ? - AND found ='W' + AND found IN ('W', 'T') /; my $sth = $dbh->prepare($query); $sth->execute( $biblio, $borrowernumber ); @@ -1519,7 +1477,7 @@ sub _FixPriority { SELECT borrowernumber, reservedate, constrainttype FROM reserves WHERE biblionumber = ? - AND ((found <> 'W') or found is NULL) + AND ((found <> 'W' AND found <> 'T') or found is NULL) ORDER BY priority ASC /; my $sth = $dbh->prepare($query); @@ -1576,7 +1534,7 @@ sub _FixPriority { } } -=item _Findgroupreserve +=head2 _Findgroupreserve @results = &_Findgroupreserve($biblioitemnumber, $biblionumber, $itemnumber); @@ -1662,6 +1620,7 @@ sub _Findgroupreserve { SELECT reserves.biblionumber AS biblionumber, reserves.borrowernumber AS borrowernumber, reserves.reservedate AS reservedate, + reserves.waitingdate AS waitingdate, reserves.branchcode AS branchcode, reserves.cancellationdate AS cancellationdate, reserves.found AS found, @@ -1689,13 +1648,9 @@ sub _Findgroupreserve { return @results; } -=item _koha_notify_reserve - -=over 4 +=head2 _koha_notify_reserve -_koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ); - -=back + _koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ); Sends a notification to the patron that their hold has been filled (through ModReserveAffect, _not_ ModReserveFill) @@ -1706,12 +1661,23 @@ sub _koha_notify_reserve { my ($itemnumber, $borrowernumber, $biblionumber) = @_; my $dbh = C4::Context->dbh; - my $borrower = C4::Members::GetMember( $borrowernumber ); + my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); + + # Try to get the borrower's email address + my $to_address; + my $which_address = C4::Context->preference('AutoEmailPrimaryAddress'); + # If the system preference is set to 'first valid' (value == OFF), look up email address + if ($which_address eq 'OFF') { + $to_address = C4::Members::GetFirstValidEmailAddress( $borrowernumber ); + } else { + $to_address = $borrower->{$which_address}; + } + my $letter_code; my $print_mode = 0; my $messagingprefs; - if ( $borrower->{'email'} || $borrower->{'smsalertnumber'} ) { - $messagingprefs = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $borrowernumber, message_name => 'Hold Filled' } ); + if ( $to_address || $borrower->{'smsalertnumber'} ) { + $messagingprefs = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $borrowernumber, message_name => 'Hold_Filled' } ); return if ( !defined( $messagingprefs->{'letter_code'} ) ); $letter_code = $messagingprefs->{'letter_code'}; @@ -1779,25 +1745,21 @@ sub _koha_notify_reserve { } } -=item _ShiftPriorityByDateAndPriority - -=over 4 +=head2 _ShiftPriorityByDateAndPriority -$new_priority = _ShiftPriorityByDateAndPriority( $biblionumber, $reservedate, $priority ); - -=back + $new_priority = _ShiftPriorityByDateAndPriority( $biblionumber, $reservedate, $priority ); This increments the priority of all reserves after the one - with either the lowest date after C<$reservedate> - or the lowest priority after C<$priority>. +with either the lowest date after C<$reservedate> +or the lowest priority after C<$priority>. It effectively makes room for a new reserve to be inserted with a certain - priority, which is returned. +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. +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. =cut @@ -1832,11 +1794,9 @@ sub _ShiftPriorityByDateAndPriority { return $new_priority; # so the caller knows what priority they wind up receiving } -=back - =head1 AUTHOR -Koha Developement team +Koha Development Team =cut