#!/usr/bin/perl
+
# Copyright Katipo Communications 2002
# Copyright Koha Development team 2012
#
use Modern::Perl;
use CGI qw ( -utf8 );
-use C4::Auth; # checkauth, getborrowernumber.
-use C4::Koha;
-use C4::Circulation;
-use C4::Reserves;
-use C4::Biblio;
-use C4::Items;
-use C4::Output;
+use C4::Auth qw( get_template_and_user );
+use C4::Koha qw( getitemtypeimagelocation getitemtypeimagesrc );
+use C4::Circulation qw( GetBranchItemRule );
+use C4::Reserves qw( CanItemBeReserved CanBookBeReserved AddReserve GetReservesControlBranch ItemsAnyAvailableAndNotRestricted IsAvailableForItemLevelRequest GetReserveFee );
+use C4::Biblio qw( GetBiblioData GetFrameworkCode );
+use C4::Output qw( output_html_with_http_headers );
use C4::Context;
use C4::Members;
use C4::Overdues;
-use C4::Debug;
use Koha::AuthorisedValues;
use Koha::Biblios;
-use Koha::DateUtils;
use Koha::CirculationRules;
use Koha::Items;
use Koha::ItemTypes;
use Koha::Checkouts;
use Koha::Libraries;
use Koha::Patrons;
-use Date::Calc qw/Today Date_to_Days/;
-use List::MoreUtils qw/uniq/;
+use List::MoreUtils qw( uniq );
my $maxreserves = C4::Context->preference("maxreserves");
-my $query = new CGI;
+my $query = CGI->new;
-# if RequestOnOpac (for placing holds) is disabled, leave immediately
-if ( ! C4::Context->preference('RequestOnOpac') ) {
+# if OPACHoldRequests (for placing holds) is disabled, leave immediately
+if ( ! C4::Context->preference('OPACHoldRequests') ) {
print $query->redirect("/cgi-bin/koha/errors/404.pl");
exit;
}
template_name => "opac-reserve.tt",
query => $query,
type => "opac",
- authnotrequired => 0,
- debug => 1,
}
);
-my ($show_holds_count, $show_priority);
-for ( C4::Context->preference("OPACShowHoldQueueDetails") ) {
- m/holds/o and $show_holds_count = 1;
- m/priority/ and $show_priority = 1;
-}
-
-my $patron = Koha::Patrons->find( $borrowernumber );
+my $patron = Koha::Patrons->find( $borrowernumber, { prefetch => ['categorycode'] } );
+my $category = $patron->category;
my $can_place_hold_if_available_at_pickup = C4::Context->preference('OPACHoldsIfAvailableAtPickup');
unless ( $can_place_hold_if_available_at_pickup ) {
- my @patron_categories = split '\|', C4::Context->preference('OPACHoldsIfAvailableAtPickupExceptions');
+ my @patron_categories = split ',', C4::Context->preference('OPACHoldsIfAvailableAtPickupExceptions');
if ( @patron_categories ) {
my $categorycode = $patron->categorycode;
$can_place_hold_if_available_at_pickup = grep { $_ eq $categorycode } @patron_categories;
}
}
-# check if this user can place a reserve, -1 means use sys pref, 0 means dont block, 1 means block
-if ( $patron->category->effective_BlockExpiredPatronOpacActions ) {
-
- if ( $patron->is_expired ) {
-
- # cannot reserve, their card has expired and the rules set mean this is not allowed
- $template->param( message => 1, expired_patron => 1 );
- output_html_with_http_headers $query, $cookie, $template->output, undef, { force_no_caching => 1 };
- exit;
- }
-}
-
-# Pass through any reserve charge
-my $reservefee = $patron->category->reservefee;
-if ( $reservefee > 0){
- $template->param( RESERVE_CHARGE => $reservefee);
-}
-
my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } };
# There are two ways of calling this script, with a single biblio num
exit;
}
-
-# pass the pickup branch along....
-my $branch = $query->param('branch') || $patron->branchcode || C4::Context->userenv->{branch} || '' ;
-$template->param( branch => $branch );
-
#
#
-# Build hashes of the requested biblio(item)s and items.
+# Here we check that the borrower can actually make reserves Stage 1.
#
#
+my $noreserves = 0;
+if ( $category->effective_BlockExpiredPatronOpacActions ) {
+ if ( $patron->is_expired ) {
+ # cannot reserve, their card has expired and the rules set mean this is not allowed
+ $noreserves = 1;
+ $template->param( message => 1, expired_patron => 1 );
+ }
+}
-my %biblioDataHash; # Hash of biblionumber to biblio/biblioitems record.
-my %itemInfoHash; # Hash of itemnumber to item info.
-foreach my $biblioNumber (@biblionumbers) {
-
- my $biblioData = GetBiblioData($biblioNumber);
- $biblioDataHash{$biblioNumber} = $biblioData;
+my $maxoutstanding = C4::Context->preference("maxoutstanding");
+my $amountoutstanding = $patron->account->balance;
+if ( $amountoutstanding && ($amountoutstanding > $maxoutstanding) ) {
+ my $amount = sprintf "%.02f", $amountoutstanding;
+ $template->param( message => 1 );
+ $noreserves = 1;
+ $template->param( too_much_oweing => $amount );
+}
- my @itemInfos = GetItemsInfo($biblioNumber);
+if ( $patron->gonenoaddress && ($patron->gonenoaddress == 1) ) {
+ $noreserves = 1;
+ $template->param(
+ message => 1,
+ GNA => 1
+ );
+}
- my $marcrecord= GetMarcBiblio({ biblionumber => $biblioNumber });
+if ( $patron->lost && ($patron->lost == 1) ) {
+ $noreserves = 1;
+ $template->param(
+ message => 1,
+ lost => 1
+ );
+}
- # flag indicating existence of at least one item linked via a host record
- my $hostitemsflag;
- # adding items linked via host biblios
- my @hostitemInfos = GetHostItemsInfo($marcrecord);
- if (@hostitemInfos){
- $hostitemsflag =1;
- push (@itemInfos,@hostitemInfos);
- }
+if ( $patron->is_debarred ) {
+ $noreserves = 1;
+ $template->param(
+ message => 1,
+ debarred => 1,
+ debarred_comment => $patron->debarredcomment,
+ debarred_date => $patron->debarred,
+ );
+}
- $biblioData->{itemInfos} = \@itemInfos;
- foreach my $itemInfo (@itemInfos) {
- $itemInfoHash{$itemInfo->{itemnumber}} = $itemInfo;
- }
+my $holds = $patron->holds;
+my $reserves_count = $holds->count;
+$template->param( RESERVES => $holds->unblessed );
+if ( $maxreserves && ( $reserves_count >= $maxreserves ) ) {
+ $template->param( message => 1 );
+ $noreserves = 1;
+ $template->param( too_many_reserves => $holds->count );
+}
- # Compute the priority rank.
- my $biblio = Koha::Biblios->find( $biblioNumber );
- $biblioData->{object} = $biblio;
- my $holds = $biblio->holds;
- my $rank = $holds->count;
- $biblioData->{reservecount} = 1; # new reserve
- while ( my $hold = $holds->next ) {
- if ( $hold->is_waiting ) {
- $rank--;
- }
- else {
- $biblioData->{reservecount}++;
- }
- }
- $biblioData->{rank} = $rank + 1;
+if( $noreserves ){
+ output_html_with_http_headers $query, $cookie, $template->output, undef, { force_no_caching => 1 };
+ exit;
}
+
+# pass the pickup branch along....
+my $branch = $query->param('branch') || $patron->branchcode || C4::Context->userenv->{branch} || '' ;
+$template->param( branch => $branch );
+
#
#
-# If this is the second time through this script, it
-# means we are carrying out the hold request, possibly
+# Here we are carrying out the hold request, possibly
# with a specific item for each biblionumber.
#
#
$branch = $patron->branchcode;
}
+ # FIXME We shouldn't need to fetch the item here
+ my $item = $itemNum ? Koha::Items->find( $itemNum ) : undef;
# When choosing a specific item, the default pickup library should be dictated by the default hold policy
- if ( ! C4::Context->preference("OPACAllowUserToChooseBranch") && $itemNum ) {
- my $item = Koha::Items->find( $itemNum );
+ if ( ! C4::Context->preference("OPACAllowUserToChooseBranch") && $item ) {
my $type = $item->effective_itemtype;
my $rule = GetBranchItemRule( $patron->branchcode, $type );
- if ( $rule->{hold_fulfillment_policy} eq 'any' ) {
+ if ( $rule->{hold_fulfillment_policy} eq 'any' || $rule->{hold_fulfillment_policy} eq 'patrongroup' ) {
$branch = $patron->branchcode;
+ } elsif ( $rule->{hold_fulfillment_policy} eq 'holdgroup' ){
+ $branch = $item->homebranch;
} else {
my $policy = $rule->{hold_fulfillment_policy};
$branch = $item->$policy;
}
}
-#item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber
- if ( $itemNum ne '' ) {
- my $item = Koha::Items->find( $itemNum );
- my $hostbiblioNum = $item->biblio->biblionumber;
- if ( $hostbiblioNum ne $biblioNum ) {
- $biblioNum = $hostbiblioNum;
- }
+ # if we have an item, we are placing the hold on the item's bib, in case of analytics
+ if ( $item ) {
+ $biblioNum = $item->biblionumber;
}
- my $biblioData = $biblioDataHash{$biblioNum};
- my $found;
-
# Check for user supplied reserve date
my $startdate;
if ( C4::Context->preference('AllowHoldDateInFuture')
$startdate = $query->param("reserve_date_$biblioNum");
}
- my $expiration_date = $query->param("expiration_date_$biblioNum");
+ my $patron_expiration_date = $query->param("expiration_date_$biblioNum");
+
+ my $itemtype = $query->param('itemtype') || undef;
+ $itemtype = undef if $itemNum;
- my $rank = $biblioData->{rank};
- if ( $itemNum ne '' ) {
- $canreserve = 1 if CanItemBeReserved( $borrowernumber, $itemNum, $branch )->{status} eq 'OK';
+ my $biblio = Koha::Biblios->find($biblioNum);
+ my $rank = $biblio->holds->search( { found => [ { "!=" => "W" }, undef ] } )->count + 1;
+ if ( $item ) {
+ $canreserve = 1 if CanItemBeReserved( $patron, $item, $branch )->{status} eq 'OK';
}
else {
- $canreserve = 1 if CanBookBeReserved( $borrowernumber, $biblioNum, $branch )->{status} eq 'OK';
+ $canreserve = 1
+ if CanBookBeReserved( $borrowernumber, $biblioNum, $branch, { itemtype => $itemtype } )->{status} eq 'OK';
# Inserts a null into the 'itemnumber' field of 'reserves' table.
$itemNum = undef;
}
}
- my $itemtype = $query->param('itemtype') || undef;
- $itemtype = undef if $itemNum;
-
# Here we actually do the reserveration. Stage 3.
if ($canreserve) {
my $reserve_id = AddReserve(
biblionumber => $biblioNum,
priority => $rank,
reservation_date => $startdate,
- expiration_date => $expiration_date,
+ expiration_date => $patron_expiration_date,
notes => $notes,
- title => $biblioData->{title},
+ title => $biblio->title,
itemnumber => $itemNum,
- found => $found,
+ found => undef,
itemtype => $itemtype,
}
);
#
#
-# Here we check that the borrower can actually make reserves Stage 1.
+# Build hashes of the requested biblio(item)s and items.
#
#
-my $noreserves = 0;
-my $maxoutstanding = C4::Context->preference("maxoutstanding");
-$template->param( noreserve => 1 ) unless $maxoutstanding;
-my $amountoutstanding = $patron->account->balance;
-if ( $amountoutstanding && ($amountoutstanding > $maxoutstanding) ) {
- my $amount = sprintf "%.02f", $amountoutstanding;
- $template->param( message => 1 );
- $noreserves = 1;
- $template->param( too_much_oweing => $amount );
-}
-if ( $patron->gonenoaddress && ($patron->gonenoaddress == 1) ) {
- $noreserves = 1;
- $template->param(
- message => 1,
- GNA => 1
- );
-}
+my %biblioDataHash; # Hash of biblionumber to biblio/biblioitems record.
+foreach my $biblioNumber (@biblionumbers) {
-if ( $patron->lost && ($patron->lost == 1) ) {
- $noreserves = 1;
- $template->param(
- message => 1,
- lost => 1
- );
-}
+ my $biblioData = GetBiblioData($biblioNumber);
+ $biblioDataHash{$biblioNumber} = $biblioData;
-if ( $patron->is_debarred ) {
- $noreserves = 1;
- $template->param(
- message => 1,
- debarred => 1,
- debarred_comment => $patron->debarredcomment,
- debarred_date => $patron->debarred,
- );
-}
+ my $biblio = Koha::Biblios->find( $biblioNumber );
+ next unless $biblio;
+
+ my $items = Koha::Items->search_ordered(
+ [
+ biblionumber => $biblioNumber,
+ 'me.itemnumber' => {
+ -in => [
+ $biblio->host_items->get_column('itemnumber')
+ ]
+ }
+ ],
+ { prefetch => [ 'issue', 'homebranch', 'holdingbranch' ] }
+ )->filter_by_visible_in_opac({ patron => $patron });
-my $holds = $patron->holds;
-my $reserves_count = $holds->count;
-$template->param( RESERVES => $holds->unblessed );
-if ( $maxreserves && ( $reserves_count >= $maxreserves ) ) {
- $template->param( message => 1 );
- $noreserves = 1;
- $template->param( too_many_reserves => $holds->count );
-}
+ $biblioData->{items} = [$items->as_list]; # FIXME Potentially a lot in memory here!
-unless ( $noreserves ) {
- my $requested_reserves_count = scalar( @biblionumbers );
- if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) {
- $template->param( new_reserves_allowed => $maxreserves - $reserves_count );
- }
+ # Compute the priority rank.
+ $biblioData->{object} = $biblio;
+ my $reservecount = $biblio->holds->search({ found => [ {"!=" => "W"},undef] })->count;
+ $biblioData->{reservecount} = $reservecount;
+ $biblioData->{rank} = $reservecount + 1;
}
-unless ($noreserves) {
- $template->param( select_item_types => 1 );
+
+my $requested_reserves_count = scalar( @biblionumbers );
+if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) {
+ $template->param( new_reserves_allowed => $maxreserves - $reserves_count );
}
+$template->param( select_item_types => 1 );
+
#
#
my $pickup_locations = Koha::Libraries->search({ pickup_location => 1 });
$template->param('item_level_itypes' => $itemLevelTypes);
+my $patron_unblessed = $patron->unblessed;
foreach my $biblioNum (@biblionumbers) {
# Init the bib item with the choices for branch pickup
$biblioLoopIter{rank} = $biblioData->{rank};
$biblioLoopIter{reservecount} = $biblioData->{reservecount};
$biblioLoopIter{already_reserved} = $biblioData->{already_reserved};
- $biblioLoopIter{reqholdnotes}=0; #TODO: For future use
if (!$itemLevelTypes && $biblioData->{itemtype}) {
$biblioLoopIter{translated_description} = $itemtypes->{$biblioData->{itemtype}}{translated_description};
$biblioLoopIter{imageurl} = getitemtypeimagesrc() . "/". $itemtypes->{$biblioData->{itemtype}}{imageurl};
}
- foreach my $itemInfo (@{$biblioData->{itemInfos}}) {
- if ($itemLevelTypes && $itemInfo->{itype}) {
- $itemInfo->{translated_description} = $itemtypes->{$itemInfo->{itype}}{translated_description};
- $itemInfo->{imageurl} = getitemtypeimagesrc() . "/". $itemtypes->{$itemInfo->{itype}}{imageurl};
- }
- if (!$itemInfo->{'notforloan'} && !($itemInfo->{'itemnotforloan'} > 0)) {
- $biblioLoopIter{forloan} = 1;
- }
- }
-
- my @notforloan_avs = Koha::AuthorisedValues->search_by_koha_field({ kohafield => 'items.notforloan', frameworkcode => $frameworkcode });
- my $notforloan_label_of = { map { $_->authorised_value => $_->opac_description } @notforloan_avs };
$biblioLoopIter{itemLoop} = [];
my $numCopiesAvailable = 0;
my $numCopiesOPACAvailable = 0;
- foreach my $itemInfo (@{$biblioData->{itemInfos}}) {
- my $itemNum = $itemInfo->{itemnumber};
- my $item = Koha::Items->find( $itemNum );
- my $itemLoopIter = {};
-
- $itemLoopIter->{itemnumber} = $itemNum;
- $itemLoopIter->{barcode} = $itemInfo->{barcode};
- $itemLoopIter->{homeBranchName} = $itemInfo->{homebranch};
- $itemLoopIter->{callNumber} = $itemInfo->{itemcallnumber};
- $itemLoopIter->{enumchron} = $itemInfo->{enumchron};
- $itemLoopIter->{ccode} = $itemInfo->{ccode};
- $itemLoopIter->{copynumber} = $itemInfo->{copynumber};
+ # iterating through all items first to check if any of them available
+ # to pass this value further inside down to IsAvailableForItemLevelRequest to
+ # it's complicated logic to analyse.
+ # (before this loop was inside that sub loop so it was O(n^2) )
+ my $items_any_available;
+ $items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $biblioNum, patron => $patron }) if $patron;
+ foreach my $item (@{$biblioData->{items}}) {
+
+ my $item_info = $item->unblessed;
+ $item_info->{holding_branch} = $item->holding_branch;
+ $item_info->{home_branch} = $item->home_branch;
if ($itemLevelTypes) {
- $itemLoopIter->{translated_description} = $itemInfo->{translated_description};
- $itemLoopIter->{itype} = $itemInfo->{itype};
- $itemLoopIter->{imageurl} = $itemInfo->{imageurl};
+ my $itemtype = $item->itemtype;
+ $item_info->{'imageurl'} = getitemtypeimagelocation( 'opac',
+ $itemtypes->{ $itemtype->itemtype }->{'imageurl'} );
+ $item_info->{'translated_description'} =
+ $itemtypes->{ $itemtype->itemtype }->{translated_description};
}
- # If the holdingbranch is different than the homebranch, we show the
- # holdingbranch of the document too.
- if ( $itemInfo->{homebranch} ne $itemInfo->{holdingbranch} ) {
- $itemLoopIter->{holdingBranchName} = $itemInfo->{holdingbranch};
- }
-
- # If the item is currently on loan, we display its return date and
- # change the background color.
- my $issue = Koha::Checkouts->find( { itemnumber => $itemNum } );
- if ( $issue ) {
- $itemLoopIter->{dateDue} = output_pref({ dt => dt_from_string($issue->date_due, 'sql'), as_due_date => 1 });
- $itemLoopIter->{backgroundcolor} = 'onloan';
- }
-
- # checking reserve
+ # checking for holds
my $holds = $item->current_holds;
-
if ( my $first_hold = $holds->next ) {
- $itemLoopIter->{backgroundcolor} = 'reserved';
- $itemLoopIter->{reservedate} = output_pref({ dt => dt_from_string($first_hold->reservedate), dateonly => 1 }); # FIXME Should be formatted in the template
- $itemLoopIter->{ExpectedAtLibrary} = $first_hold->branchcode;
- $itemLoopIter->{waitingdate} = $first_hold->waitingdate;
+ $item_info->{first_hold} = $first_hold;
}
- $itemLoopIter->{notforloan} = $itemInfo->{notforloan};
- $itemLoopIter->{itemnotforloan} = $itemInfo->{itemnotforloan};
-
- # Management of the notforloan document
- if ( $itemLoopIter->{notforloan} || $itemLoopIter->{itemnotforloan}) {
- $itemLoopIter->{backgroundcolor} = 'other';
- $itemLoopIter->{notforloanvalue} =
- $notforloan_label_of->{ $itemLoopIter->{notforloan} };
- }
-
- # Management of lost or long overdue items
- if ( $itemInfo->{itemlost} ) {
-
- # FIXME localized strings should never be in Perl code
- $itemLoopIter->{message} =
- $itemInfo->{itemlost} == 1 ? "(lost)"
- : $itemInfo->{itemlost} == 2 ? "(long overdue)"
- : "";
- $itemInfo->{backgroundcolor} = 'other';
- }
+ $item_info->{checkout} = $item->checkout;
# Check of the transferred documents
- my ( $transfertwhen, $transfertfrom, $transfertto ) =
- GetTransfers($itemNum);
- if ( $transfertwhen && ($transfertwhen ne '') ) {
- $itemLoopIter->{transfertwhen} = output_pref({ dt => dt_from_string($transfertwhen), dateonly => 1 });
- $itemLoopIter->{transfertfrom} = $transfertfrom;
- $itemLoopIter->{transfertto} = $transfertto;
- $itemLoopIter->{nocancel} = 1;
+ my $transfer = $item->get_transfer;
+ if ( $transfer && $transfer->in_transit ) {
+ $item_info->{transfertwhen} = $transfer->datesent;
+ $item_info->{transfertfrom} = $transfer->frombranch;
+ $item_info->{transfertto} = $transfer->tobranch;
+ $item_info->{nocancel} = 1;
}
# if the items belongs to a host record, show link to host record
- if ( $itemInfo->{biblionumber} ne $biblioNum ) {
- $biblioLoopIter{hostitemsflag} = 1;
- $itemLoopIter->{hostbiblionumber} = $itemInfo->{biblionumber};
- $itemLoopIter->{hosttitle} = Koha::Biblios->find( $itemInfo->{biblionumber} )->title;
+ if ( $item_info->{biblionumber} ne $biblioNum ) {
+ $item_info->{hostbiblionumber} = $item->biblionumber;
+ $item_info->{hosttitle} = Koha::Biblios->find( $item_info->{biblionumber} )->title;
}
- # If there is no loan, return and transfer, we show a checkbox.
- $itemLoopIter->{notforloan} = $itemLoopIter->{notforloan} || 0;
+ my $branch = GetReservesControlBranch( $item_info, $patron_unblessed );
- my $patron_unblessed = $patron->unblessed;
- my $branch = GetReservesControlBranch( $itemInfo, $patron_unblessed );
-
- my $policy_holdallowed = !$itemLoopIter->{already_reserved};
- $policy_holdallowed &&=
- IsAvailableForItemLevelRequest($item, $patron) &&
- CanItemBeReserved( $borrowernumber, $itemNum )->{status} eq 'OK';
+ # items_any_available defined outside of the current loop,
+ # so we avoiding loop inside IsAvailableForItemLevelRequest:
+ my $policy_holdallowed =
+ CanItemBeReserved( $patron, $item )->{status} eq 'OK' &&
+ IsAvailableForItemLevelRequest($item, $patron, undef, $items_any_available);
if ($policy_holdallowed) {
my $opac_hold_policy = Koha::CirculationRules->get_opacitemholds_policy( { item => $item, patron => $patron } );
if ( $opac_hold_policy ne 'N' ) { # If Y or F
- $itemLoopIter->{available} = 1;
+ $item_info->{available} = 1;
$numCopiesOPACAvailable++;
$biblioLoopIter{force_hold} = 1 if $opac_hold_policy eq 'F';
}
$numCopiesAvailable++;
unless ( $can_place_hold_if_available_at_pickup ) {
- my $items_in_this_library = Koha::Items->search({ biblionumber => $itemInfo->{biblionumber}, holdingbranch => $itemInfo->{holdingbranch} });
+ my $items_in_this_library = Koha::Items->search({ biblionumber => $item->biblionumber, holdingbranch => $item->holdingbranch });
my $nb_of_items_issued = $items_in_this_library->search({ 'issue.itemnumber' => { not => undef }}, { join => 'issue' })->count;
if ( $items_in_this_library->count > $nb_of_items_issued ) {
- push @not_available_at, $itemInfo->{holdingbranch};
+ push @not_available_at, $item->holdingbranch;
}
}
}
- $itemLoopIter->{imageurl} = getitemtypeimagelocation( 'opac', $itemtypes->{ $itemInfo->{itype} }{imageurl} );
-
- # Show serial enumeration when needed
- if ($itemLoopIter->{enumchron}) {
+ # Show serial enumeration when needed
+ if ($item_info->{enumchron}) {
$itemdata_enumchron = 1;
}
- # Show collection when needed
- if ($itemLoopIter->{ccode}) {
+ # Show collection when needed
+ if ($item_info->{ccode}) {
$itemdata_ccode = 1;
}
- push @{$biblioLoopIter{itemLoop}}, $itemLoopIter;
+ push @{$biblioLoopIter{itemLoop}}, $item_info;
}
$template->param(
itemdata_enumchron => $itemdata_enumchron,
$biblioLoopIter{holdable} = undef;
$biblioLoopIter{itemholdable} = undef;
}
- if(not C4::Context->preference('AllowHoldsOnPatronsPossessions') and CheckIfIssuedToPatron($borrowernumber,$biblioNum)) {
- $biblioLoopIter{holdable} = undef;
- $biblioLoopIter{already_patron_possession} = 1;
- }
-
if ( $biblioLoopIter{holdable} ) {
@not_available_at = uniq @not_available_at;
$biblioLoopIter{not_available_at} = \@not_available_at ;
}
}
- $biblioLoopIter{holdable} &&= CanBookBeReserved( $borrowernumber, $biblioNum )->{status} eq 'OK';
+ my $status = CanBookBeReserved( $borrowernumber, $biblioNum )->{status};
+ $biblioLoopIter{holdable} &&= $status eq 'OK';
+ $biblioLoopIter{$status} = 1;
+
+ if ( $biblioLoopIter{holdable} and C4::Context->preference('AllowHoldItemTypeSelection') ) {
+ # build the allowed item types loop
+ my $rs = $biblio->items->search_ordered(
+ undef,
+ { select => [ { distinct => 'itype' } ],
+ as => 'item_type'
+ }
+ );
+
+ my @item_types =
+ grep { CanBookBeReserved( $borrowernumber, $biblioNum, $branch, { itemtype => $_ } )->{status} eq 'OK' }
+ $rs->get_column('item_type');
+
+ $biblioLoopIter{allowed_item_types} = \@item_types;
+ }
+
+ if ( $status eq 'recall' ) {
+ $biblioLoopIter{recall} = 1;
+ }
# For multiple holds per record, if a patron has previously placed a hold,
# the patron can only place more holds of the same type. That is, if the
$biblioLoopIter{forced_hold_level} = $forced_hold_level;
}
+ # Pass through any reserve charge
+ $biblioLoopIter{reserve_charge} = GetReserveFee( $patron->id, $biblioNum );
push @$biblioLoop, \%biblioLoopIter;