@EXPORT = qw(
&AddReserve
- &GetReservesForBranch
&GetReserveStatus
&GetOtherReserves
&IsAvailableForItemLevelRequest
- &OPACItemHoldsAllowed
-
&AlterPriority
&ToggleLowestPriority
$expdate = output_pref({ str => $expdate, dateonly => 1, dateformat => 'iso' });
+ # if we have an item selectionned, and the pickup branch is the same as the holdingbranch
+ # of the document, we force the value $priority and $found .
+ if ( $checkitem and not C4::Context->preference('ReservesNeedReturns') ) {
+ $priority = 0;
+ my $item = Koha::Items->find( $checkitem ); # FIXME Prevent bad calls
+ if ( $item->holdingbranch eq $branch ) {
+ $found = 'W';
+ }
+ }
+
if ( C4::Context->preference('AllowHoldDateInFuture') ) {
# Make room in reserves for this before those of a later reserve date
itemtype => $itemtype,
}
)->store();
+ $hold->set_waiting() if $found eq 'W';
logaction( 'HOLDS', 'CREATE', $hold->id, Dumper($hold->unblessed) )
if C4::Context->preference('HoldsLog');
return 'tooManyReserves';
}
+ # Now we need to check hold limits by patron category
+ my $schema = Koha::Database->new()->schema();
+ my $rule = $schema->resultset('BranchBorrowerCircRule')->find(
+ {
+ branchcode => $branchcode,
+ categorycode => $borrower->{categorycode},
+ }
+ );
+ $rule ||= $schema->resultset('DefaultBorrowerCircRule')->find(
+ {
+ categorycode => $borrower->{categorycode}
+ }
+ );
+ if ( $rule && defined $rule->max_holds ) {
+ my $total_holds_count = Koha::Holds->search(
+ {
+ borrowernumber => $borrower->{borrowernumber}
+ }
+ )->count();
+
+ return 'tooManyReserves' if $total_holds_count >= $rule->max_holds;
+ }
+
my $circ_control_branch =
C4::Circulation::_GetCircControlBranch( $item->unblessed(), $borrower );
my $branchitemrule =
return $fee;
}
-=head2 GetReservesForBranch
-
- @transreserv = GetReservesForBranch($frombranch);
-
-=cut
-
-sub GetReservesForBranch {
- my ($frombranch) = @_;
- my $dbh = C4::Context->dbh;
-
- my $query = "
- SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate, expirationdate
- FROM reserves
- WHERE priority='0'
- AND found='W'
- ";
- $query .= " AND branchcode=? " if ( $frombranch );
- $query .= "ORDER BY waitingdate" ;
-
- my $sth = $dbh->prepare($query);
- if ($frombranch){
- $sth->execute($frombranch);
- } else {
- $sth->execute();
- }
-
- my @transreserv;
- my $i = 0;
- while ( my $data = $sth->fetchrow_hashref ) {
- $transreserv[$i] = $data;
- $i++;
- }
- return (@transreserv);
-}
-
=head2 GetReserveStatus
$reservestatus = GetReserveStatus($itemnumber);
my $priority = 10000000;
foreach my $res (@reserves) {
if ( $res->{'itemnumber'} == $itemnumber && $res->{'priority'} == 0) {
- return ( "Waiting", $res, \@reserves ); # Found it
+ if ($res->{'found'} eq 'W') {
+ return ( "Waiting", $res, \@reserves ); # Found it, it is waiting
+ } else {
+ return ( "Reserved", $res, \@reserves ); # Found determinated hold, e. g. the tranferred one
+ }
} else {
my $patron;
my $iteminfo;
=cut
sub CancelExpiredReserves {
-
my $today = dt_from_string();
my $cancel_on_holidays = C4::Context->preference('ExpireReservesOnHolidays');
-
- my $dbh = C4::Context->dbh;
+ my $expireWaiting = C4::Context->preference('ExpireReservesMaxPickUpDelay');
my $dtf = Koha::Database->new->schema->storage->datetime_parser;
- my $today = dt_from_string;
+ my $params = { expirationdate => { '<', $dtf->format_date($today) } };
+ $params->{found} = undef unless $expireWaiting;
+
# FIXME To move to Koha::Holds->search_expired (?)
- my $holds = Koha::Holds->search(
- {
- expirationdate => { '<', $dtf->format_date($today) }
- }
- );
+ my $holds = Koha::Holds->search( $params );
while ( my $hold = $holds->next ) {
my $calendar = Koha::Calendar->new( branchcode => $hold->branchcode );
next if !$cancel_on_holidays && $calendar->is_holiday( $today );
my $cancel_params = {};
- if ( $holds->found eq 'W' ) {
+ if ( $hold->found eq 'W' ) {
$cancel_params->{charge_cancel_fee} = 1;
}
$hold->cancel( $cancel_params );
-
}
}
sub AutoUnsuspendReserves {
my $today = dt_from_string();
- my @holds = Koha::Holds->search( { suspend_until => { '<' => $today->ymd() } } );
+ my @holds = Koha::Holds->search( { suspend_until => { '<=' => $today->ymd() } } );
map { $_->suspend(0)->suspend_until(undef)->store() } @holds;
}
my $hold;
unless ( $reserve_id ) {
- $hold = Koha::Holds->search({ biblionumber => $biblionumber, borrowernumber => $borrowernumber, itemnumber => $itemnumber });
- return unless $hold; # FIXME Should raise an exception
+ my $holds = Koha::Holds->search({ biblionumber => $biblionumber, borrowernumber => $borrowernumber, itemnumber => $itemnumber });
+ return unless $holds->count; # FIXME Should raise an exception
+ $hold = $holds->next;
$reserve_id = $hold->reserve_id;
}
* 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,
# FIXME - a lot of places in the code do this
# or something similar - need to be
# consolidated
- my $itype = _get_itype($item);
+ my $patron = Koha::Patrons->find( $borrower->{borrowernumber} );
+ my $item_object = Koha::Items->find( $item->{itemnumber } );
+ my $itemtype = $item_object->effective_itemtype;
my $notforloan_per_itemtype
= $dbh->selectrow_array("SELECT notforloan FROM itemtypes WHERE itemtype = ?",
- undef, $itype);
+ undef, $itemtype);
return 0 if
$notforloan_per_itemtype ||
$item->{withdrawn} ||
($item->{damaged} && !C4::Context->preference('AllowHoldsOnDamagedItems'));
- my $on_shelf_holds = _OnShelfHoldsAllowed($itype,$borrower->{categorycode},$item->{holdingbranch});
+ my $on_shelf_holds = Koha::IssuingRules->get_onshelfholds_policy( { item => $item_object, patron => $patron } );
if ( $on_shelf_holds == 1 ) {
return 1;
my $any_available = 0;
foreach my $i (@items) {
+
+ my $circ_control_branch = C4::Circulation::_GetCircControlBranch( $i->unblessed(), $borrower );
+ my $branchitemrule = C4::Circulation::GetBranchItemRule( $circ_control_branch, $i->itype );
+
$any_available = 1
unless $i->itemlost
|| $i->notforloan > 0
|| IsItemOnHoldAndFound( $i->id )
|| ( $i->damaged
&& !C4::Context->preference('AllowHoldsOnDamagedItems') )
- || Koha::ItemTypes->find( $i->effective_itemtype() )->notforloan;
+ || Koha::ItemTypes->find( $i->effective_itemtype() )->notforloan
+ || $branchitemrule->{holdallowed} == 1 && $borrower->{branchcode} ne $i->homebranch;
}
return $any_available ? 0 : 1;
+ } else { # on_shelf_holds == 0 "If any unavailable" (the description is rather cryptic and could still be improved)
+ return $item->{onloan} || IsItemOnHoldAndFound( $item->{itemnumber} );
}
-
- return $item->{onloan} || GetReserveStatus($item->{itemnumber}) eq "Waiting";
-}
-
-=head2 OnShelfHoldsAllowed
-
- OnShelfHoldsAllowed($itemtype,$borrowercategory,$branchcode);
-
-Checks issuingrules, using the borrowers categorycode, the itemtype, and branchcode to see if onshelf
-holds are allowed, returns true if so.
-
-=cut
-
-sub OnShelfHoldsAllowed {
- my ($item, $borrower) = @_;
-
- my $itype = _get_itype($item);
- return _OnShelfHoldsAllowed($itype,$borrower->{categorycode},$item->{holdingbranch});
}
sub _get_itype {
return $itype;
}
-sub _OnShelfHoldsAllowed {
- my ($itype,$borrowercategory,$branchcode) = @_;
-
- my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $borrowercategory, itemtype => $itype, branchcode => $branchcode });
- return $issuing_rule ? $issuing_rule->onshelfholds : undef;
-}
-
=head2 AlterPriority
AlterPriority( $where, $reserve_id );
my $patron = Koha::Patrons->find( $borrowernumber );
# Try to get the borrower's email address
- my $to_address = C4::Members::GetNoticeEmailAddress($borrowernumber);
+ my $to_address = $patron->notice_email_address;
my $messagingprefs = C4::Members::Messaging::GetMessagingPreferences( {
borrowernumber => $borrowernumber,
return $new_priority; # so the caller knows what priority they wind up receiving
}
-=head2 OPACItemHoldsAllowed
-
- OPACItemHoldsAllowed($item_record,$borrower_record);
-
-Checks issuingrules, using the borrowers categorycode, the itemtype, and branchcode to see
-if specific item holds are allowed, returns true if so.
-
-=cut
-
-sub OPACItemHoldsAllowed {
- my ($item,$borrower) = @_;
-
- my $branchcode = $item->{homebranch} or die "No homebranch";
- my $itype;
- my $dbh = C4::Context->dbh;
- if (C4::Context->preference('item-level_itypes')) {
- # We can't trust GetItem to honour the syspref, so safest to do it ourselves
- # When GetItem is fixed, we can remove this
- $itype = $item->{itype};
- }
- else {
- my $query = "SELECT itemtype FROM biblioitems WHERE biblioitemnumber = ? ";
- my $sth = $dbh->prepare($query);
- $sth->execute($item->{biblioitemnumber});
- if (my $data = $sth->fetchrow_hashref()){
- $itype = $data->{itemtype};
- }
- }
-
- my $query = "SELECT opacitemholds,categorycode,itemtype,branchcode FROM issuingrules WHERE
- (issuingrules.categorycode = ? OR issuingrules.categorycode = '*')
- AND
- (issuingrules.itemtype = ? OR issuingrules.itemtype = '*')
- AND
- (issuingrules.branchcode = ? OR issuingrules.branchcode = '*')
- ORDER BY
- issuingrules.categorycode desc,
- issuingrules.itemtype desc,
- issuingrules.branchcode desc
- LIMIT 1";
- my $sth = $dbh->prepare($query);
- $sth->execute($borrower->{categorycode},$itype,$branchcode);
- my $data = $sth->fetchrow_hashref;
- my $opacitemholds = uc substr ($data->{opacitemholds}, 0, 1);
- return '' if $opacitemholds eq 'N';
- return $opacitemholds;
-}
-
=head2 MoveReserve
MoveReserve( $itemnumber, $borrowernumber, $cancelreserve )
=head2 ReserveSlip
- ReserveSlip($branchcode, $borrowernumber, $biblionumber)
+ReserveSlip(
+ {
+ branchcode => $branchcode,
+ borrowernumber => $borrowernumber,
+ biblionumber => $biblionumber,
+ [ itemnumber => $itemnumber, ]
+ [ barcode => $barcode, ]
+ }
+ )
Returns letter hash ( see C4::Letters::GetPreparedLetter ) or undef
=cut
sub ReserveSlip {
- my ($branch, $borrowernumber, $biblionumber) = @_;
+ my ($args) = @_;
+ my $branchcode = $args->{branchcode};
+ my $borrowernumber = $args->{borrowernumber};
+ my $biblionumber = $args->{biblionumber};
+ my $itemnumber = $args->{itemnumber};
+ my $barcode = $args->{barcode};
-# return unless ( C4::Context->boolean_preference('printreserveslips') );
- my $patron = Koha::Patrons->find( $borrowernumber );
- my $hold = Koha::Holds->search({biblionumber => $biblionumber, borrowernumber => $borrowernumber })->next;
+ my $patron = Koha::Patrons->find($borrowernumber);
+
+ my $hold;
+ if ($itemnumber || $barcode ) {
+ $itemnumber ||= Koha::Items->find( { barcode => $barcode } )->itemnumber;
+
+ $hold = Koha::Holds->search(
+ {
+ biblionumber => $biblionumber,
+ borrowernumber => $borrowernumber,
+ itemnumber => $itemnumber
+ }
+ )->next;
+ }
+ else {
+ $hold = Koha::Holds->search(
+ {
+ biblionumber => $biblionumber,
+ borrowernumber => $borrowernumber
+ }
+ )->next;
+ }
+
return unless $hold;
my $reserve = $hold->unblessed;
return C4::Letters::GetPreparedLetter (
module => 'circulation',
letter_code => 'HOLD_SLIP',
- branchcode => $branch,
+ branchcode => $branchcode,
lang => $patron->lang,
tables => {
'reserves' => $reserve,