Bug 29043: Don't fetch biblios info unless a patron is picked
If we haven't picked a patron or a club yet we don't need to fetch biblios, items and holdability infos Signed-off-by: Nick Clemens <nick@bywatersolutions.com> Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> Signed-off-by: Fridolin Somers <fridolin.somers@biblibre.com>
This commit is contained in:
parent
c33621f2d2
commit
54a1776ebf
|
|
@ -196,6 +196,9 @@ $template->param(
|
|||
multi_hold => $multi_hold,
|
||||
);
|
||||
|
||||
# If we are coming from the search result and only 1 is selected
|
||||
$biblionumber ||= $biblionumbers[0] unless $multi_hold;
|
||||
|
||||
# If we have the borrowernumber because we've performed an action, then we
|
||||
# don't want to try to place another reserve.
|
||||
if ($borrowernumber_hold && !$action) {
|
||||
|
|
@ -291,478 +294,493 @@ $template->param(
|
|||
messageclub => $messageclub
|
||||
);
|
||||
|
||||
# FIXME launch another time GetMember perhaps until (Joubu: Why?)
|
||||
my $patron = Koha::Patrons->find( $borrowernumber_hold );
|
||||
# Load the hold list if
|
||||
# - we are searching for a patron or club and found one
|
||||
# - we are not searching for anything
|
||||
if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold )
|
||||
|| ( !$findborrower && !$findclub ) )
|
||||
{
|
||||
# FIXME launch another time GetMember perhaps until (Joubu: Why?)
|
||||
my $patron = Koha::Patrons->find( $borrowernumber_hold );
|
||||
|
||||
if ( $patron && $multi_hold ) {
|
||||
my @multi_pickup_locations =
|
||||
Koha::Biblios->search( { biblionumber => \@biblionumbers } )
|
||||
->pickup_locations( { patron => $patron } )->as_list;
|
||||
$template->param( multi_pickup_locations => \@multi_pickup_locations );
|
||||
}
|
||||
|
||||
my $logged_in_patron = Koha::Patrons->find( $borrowernumber );
|
||||
|
||||
my $wants_check;
|
||||
if ($patron) {
|
||||
$wants_check = $patron->wants_check_for_previous_checkout;
|
||||
}
|
||||
my $itemdata_enumchron = 0;
|
||||
my $itemdata_ccode = 0;
|
||||
my @biblioloop = ();
|
||||
my $no_reserves_allowed = 0;
|
||||
foreach my $biblionumber (@biblionumbers) {
|
||||
next unless $biblionumber =~ m|^\d+$|;
|
||||
|
||||
my %biblioloopiter = ();
|
||||
|
||||
my $biblio = Koha::Biblios->find( $biblionumber );
|
||||
unless ($biblio) {
|
||||
$biblioloopiter{noitems} = 1;
|
||||
$template->param('nobiblio' => 1);
|
||||
last;
|
||||
if ( $patron && $multi_hold ) {
|
||||
my @multi_pickup_locations =
|
||||
Koha::Biblios->search( { biblionumber => \@biblionumbers } )
|
||||
->pickup_locations( { patron => $patron } )->as_list;
|
||||
$template->param( multi_pickup_locations => \@multi_pickup_locations );
|
||||
}
|
||||
|
||||
my $force_hold_level;
|
||||
if ( $patron ) {
|
||||
{ # CanBookBeReserved
|
||||
my $canReserve = CanBookBeReserved( $patron->borrowernumber, $biblionumber );
|
||||
if ( $canReserve->{status} eq 'OK' ) {
|
||||
my $logged_in_patron = Koha::Patrons->find( $borrowernumber );
|
||||
|
||||
#All is OK and we can continue
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'noReservesAllowed' || $canReserve->{status} eq 'notReservable' ) {
|
||||
$no_reserves_allowed = 1;
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'tooManyReserves' ) {
|
||||
$exceeded_maxreserves = 1;
|
||||
$template->param( maxreserves => $canReserve->{limit} );
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'tooManyHoldsForThisRecord' ) {
|
||||
$exceeded_holds_per_record = 1;
|
||||
$biblioloopiter{ $canReserve->{status} } = 1;
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'ageRestricted' ) {
|
||||
$template->param( $canReserve->{status} => 1 );
|
||||
$biblioloopiter{ $canReserve->{status} } = 1;
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'alreadypossession' ) {
|
||||
$template->param( $canReserve->{status} => 1);
|
||||
$biblioloopiter{ $canReserve->{status} } = 1;
|
||||
}
|
||||
else {
|
||||
$biblioloopiter{ $canReserve->{status} } = 1;
|
||||
}
|
||||
my $wants_check;
|
||||
if ($patron) {
|
||||
$wants_check = $patron->wants_check_for_previous_checkout;
|
||||
}
|
||||
my $itemdata_enumchron = 0;
|
||||
my $itemdata_ccode = 0;
|
||||
my @biblioloop = ();
|
||||
my $no_reserves_allowed = 0;
|
||||
foreach my $biblionumber (@biblionumbers) {
|
||||
next unless $biblionumber =~ m|^\d+$|;
|
||||
|
||||
my %biblioloopiter = ();
|
||||
|
||||
my $biblio = Koha::Biblios->find( $biblionumber );
|
||||
unless ($biblio) {
|
||||
$biblioloopiter{noitems} = 1;
|
||||
$template->param('nobiblio' => 1);
|
||||
last;
|
||||
}
|
||||
|
||||
# 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
|
||||
# patron placed a record level hold, all the holds the patron places must
|
||||
# be record level. If the patron placed an item level hold, all holds
|
||||
# the patron places must be item level
|
||||
my $holds = Koha::Holds->search(
|
||||
{
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
biblionumber => $biblionumber,
|
||||
found => undef,
|
||||
}
|
||||
);
|
||||
$force_hold_level = $holds->forced_hold_level();
|
||||
$biblioloopiter{force_hold_level} = $force_hold_level;
|
||||
$template->param( force_hold_level => $force_hold_level );
|
||||
my $force_hold_level;
|
||||
if ( $patron ) {
|
||||
{ # CanBookBeReserved
|
||||
my $canReserve = CanBookBeReserved( $patron->borrowernumber, $biblionumber );
|
||||
if ( $canReserve->{status} eq 'OK' ) {
|
||||
|
||||
# For a librarian to be able to place multiple record holds for a patron for a record,
|
||||
# we must find out what the maximum number of holds they can place for the patron is
|
||||
my $max_holds_for_record = GetMaxPatronHoldsForRecord( $patron->borrowernumber, $biblionumber );
|
||||
my $remaining_holds_for_record = $max_holds_for_record - $holds->count();
|
||||
$biblioloopiter{remaining_holds_for_record} = $max_holds_for_record;
|
||||
$template->param( max_holds_for_record => $max_holds_for_record );
|
||||
$template->param( remaining_holds_for_record => $remaining_holds_for_record );
|
||||
}
|
||||
|
||||
|
||||
my $count = Koha::Holds->search( { biblionumber => $biblionumber } )->count();
|
||||
my $totalcount = $count;
|
||||
|
||||
# adding a fixed value for priority options
|
||||
my $fixedRank = $count+1;
|
||||
|
||||
my %itemnumbers_of_biblioitem;
|
||||
|
||||
my @hostitems = get_hostitemnumbers_of($biblionumber);
|
||||
my @itemnumbers;
|
||||
if (@hostitems){
|
||||
$template->param('hostitemsflag' => 1);
|
||||
push(@itemnumbers, @hostitems);
|
||||
}
|
||||
|
||||
my $items = Koha::Items->search({ -or => { biblionumber => $biblionumber, itemnumber => { in => \@itemnumbers } } });
|
||||
|
||||
unless ( $items->count ) {
|
||||
# FIXME Then why do we continue?
|
||||
$template->param('noitems' => 1) unless ( $multi_hold );
|
||||
$biblioloopiter{noitems} = 1;
|
||||
}
|
||||
|
||||
## Here we go backwards again to create hash of biblioitemnumber to itemnumbers
|
||||
## this is important when we have analytic items which may be on another record
|
||||
my ( $iteminfos_of );
|
||||
while ( my $item = $items->next ) {
|
||||
$item = $item->unblessed;
|
||||
my $biblioitemnumber = $item->{biblioitemnumber};
|
||||
my $itemnumber = $item->{itemnumber};
|
||||
push( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} }, $itemnumber );
|
||||
$iteminfos_of->{$itemnumber} = $item;
|
||||
}
|
||||
|
||||
my @biblioitemnumbers = keys %itemnumbers_of_biblioitem;
|
||||
|
||||
my $biblioiteminfos_of = {
|
||||
map {
|
||||
my $biblioitem = $_;
|
||||
( $biblioitem->{biblioitemnumber} => $biblioitem )
|
||||
} @{ Koha::Biblioitems->search(
|
||||
{ biblioitemnumber => { -in => \@biblioitemnumbers } },
|
||||
{ select => ['biblionumber', 'biblioitemnumber', 'publicationyear', 'itemtype']}
|
||||
)->unblessed
|
||||
}
|
||||
};
|
||||
|
||||
my @bibitemloop;
|
||||
|
||||
my @available_itemtypes;
|
||||
foreach my $biblioitemnumber (@biblioitemnumbers) {
|
||||
my $biblioitem = $biblioiteminfos_of->{$biblioitemnumber};
|
||||
my $num_available = 0;
|
||||
my $num_override = 0;
|
||||
my $hiddencount = 0;
|
||||
my $num_alreadyheld = 0;
|
||||
|
||||
$biblioitem->{force_hold_level} = $force_hold_level;
|
||||
|
||||
if ( $biblioitem->{biblioitemnumber} ne $biblionumber ) {
|
||||
$biblioitem->{hostitemsflag} = 1;
|
||||
}
|
||||
|
||||
$biblioloopiter{description} = $biblioitem->{description};
|
||||
$biblioloopiter{itypename} = $biblioitem->{description};
|
||||
if ( $biblioitem->{itemtype} ) {
|
||||
|
||||
$biblioitem->{description} =
|
||||
$itemtypes->{ $biblioitem->{itemtype} }{description};
|
||||
|
||||
$biblioloopiter{imageurl} =
|
||||
getitemtypeimagelocation( 'intranet',
|
||||
$itemtypes->{ $biblioitem->{itemtype} }{imageurl} );
|
||||
}
|
||||
|
||||
# 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 => $biblioitem->{biblionumber}, patron => $patron })
|
||||
if $patron;
|
||||
|
||||
foreach my $itemnumber ( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} } ) {
|
||||
my $item = $iteminfos_of->{$itemnumber};
|
||||
my $do_check;
|
||||
if ( $patron ) {
|
||||
$do_check = $patron->do_check_for_previous_checkout($item) if $wants_check;
|
||||
if ( $do_check && $wants_check ) {
|
||||
$item->{checked_previously} = $do_check;
|
||||
if ( $multi_hold ) {
|
||||
$biblioloopiter{checked_previously} = $do_check;
|
||||
} else {
|
||||
$template->param( checked_previously => $do_check );
|
||||
}
|
||||
#All is OK and we can continue
|
||||
}
|
||||
}
|
||||
$item->{force_hold_level} = $force_hold_level;
|
||||
|
||||
unless (C4::Context->preference('item-level_itypes')) {
|
||||
$item->{itype} = $biblioitem->{itemtype};
|
||||
}
|
||||
|
||||
$item->{itypename} = $itemtypes->{ $item->{itype} }{description};
|
||||
$item->{imageurl} = getitemtypeimagelocation( 'intranet', $itemtypes->{ $item->{itype} }{imageurl} );
|
||||
$item->{homebranch} = $item->{homebranch};
|
||||
|
||||
# if the holdingbranch is different than the homebranch, we show the
|
||||
# holdingbranch of the document too
|
||||
if ( $item->{homebranch} ne $item->{holdingbranch} ) {
|
||||
$item->{holdingbranch} = $item->{holdingbranch};
|
||||
}
|
||||
|
||||
if($item->{biblionumber} ne $biblionumber){
|
||||
$item->{hostitemsflag} = 1;
|
||||
$item->{hosttitle} = Koha::Biblios->find( $item->{biblionumber} )->title;
|
||||
}
|
||||
|
||||
# if the item is currently on loan, we display its return date and
|
||||
# change the background color
|
||||
my $issue = Koha::Checkouts->find( { itemnumber => $itemnumber } );
|
||||
if ( $issue ) {
|
||||
$item->{date_due} = $issue->date_due;
|
||||
$item->{backgroundcolor} = 'onloan';
|
||||
}
|
||||
|
||||
# checking reserve
|
||||
my $item_object = Koha::Items->find( $itemnumber );
|
||||
my $holds = $item_object->current_holds;
|
||||
if ( my $first_hold = $holds->next ) {
|
||||
my $p = Koha::Patrons->find( $first_hold->borrowernumber );
|
||||
|
||||
$item->{backgroundcolor} = 'reserved';
|
||||
$item->{reservedate} = output_pref({ dt => dt_from_string( $first_hold->reservedate ), dateonly => 1 }); # FIXME Should be formatted in the template
|
||||
$item->{ReservedFor} = $p;
|
||||
$item->{ExpectedAtLibrary} = $first_hold->branchcode;
|
||||
$item->{waitingdate} = $first_hold->waitingdate;
|
||||
}
|
||||
|
||||
# Management of the notforloan document
|
||||
if ( $item->{notforloan} ) {
|
||||
$item->{backgroundcolor} = 'other';
|
||||
}
|
||||
|
||||
# Management of lost or long overdue items
|
||||
if ( $item->{itemlost} ) {
|
||||
$item->{backgroundcolor} = 'other';
|
||||
if ($logged_in_patron->category->hidelostitems && !$showallitems) {
|
||||
$item->{hide} = 1;
|
||||
$hiddencount++;
|
||||
elsif ( $canReserve->{status} eq 'noReservesAllowed' || $canReserve->{status} eq 'notReservable' ) {
|
||||
$no_reserves_allowed = 1;
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'tooManyReserves' ) {
|
||||
$exceeded_maxreserves = 1;
|
||||
$template->param( maxreserves => $canReserve->{limit} );
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'tooManyHoldsForThisRecord' ) {
|
||||
$exceeded_holds_per_record = 1;
|
||||
$biblioloopiter{ $canReserve->{status} } = 1;
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'ageRestricted' ) {
|
||||
$template->param( $canReserve->{status} => 1 );
|
||||
$biblioloopiter{ $canReserve->{status} } = 1;
|
||||
}
|
||||
elsif ( $canReserve->{status} eq 'alreadypossession' ) {
|
||||
$template->param( $canReserve->{status} => 1);
|
||||
$biblioloopiter{ $canReserve->{status} } = 1;
|
||||
}
|
||||
else {
|
||||
$biblioloopiter{ $canReserve->{status} } = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Check the transit status
|
||||
my ( $transfertwhen, $transfertfrom, $transfertto ) =
|
||||
GetTransfers($itemnumber);
|
||||
|
||||
if ( defined $transfertwhen && $transfertwhen ne '' ) {
|
||||
$item->{transfertwhen} = output_pref({ dt => dt_from_string( $transfertwhen ), dateonly => 1 });
|
||||
$item->{transfertfrom} = $transfertfrom;
|
||||
$item->{transfertto} = $transfertto;
|
||||
$item->{nocancel} = 1;
|
||||
}
|
||||
|
||||
# If there is no loan, return and transfer, we show a checkbox.
|
||||
$item->{notforloan} ||= 0;
|
||||
|
||||
# if independent branches is on we need to check if the person can reserve
|
||||
# for branches they arent logged in to
|
||||
if ( C4::Context->preference("IndependentBranches") ) {
|
||||
if (! C4::Context->preference("canreservefromotherbranches")){
|
||||
# can't reserve items so need to check if item homebranch and userenv branch match if not we can't reserve
|
||||
my $userenv = C4::Context->userenv;
|
||||
unless ( C4::Context->IsSuperLibrarian ) {
|
||||
$item->{cantreserve} = 1 if ( $item->{homebranch} ne $userenv->{branch} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $patron ) {
|
||||
my $patron_unblessed = $patron->unblessed;
|
||||
my $branch = C4::Circulation::_GetCircControlBranch($item, $patron_unblessed);
|
||||
|
||||
my $branchitemrule = GetBranchItemRule( $branch, $item->{'itype'} );
|
||||
|
||||
$item->{'holdallowed'} = $branchitemrule->{'holdallowed'};
|
||||
|
||||
my $can_item_be_reserved = CanItemBeReserved( $patron->borrowernumber, $itemnumber )->{status};
|
||||
$item->{not_holdable} = $can_item_be_reserved unless ( $can_item_be_reserved eq 'OK' );
|
||||
|
||||
$item->{item_level_holds} = Koha::CirculationRules->get_opacitemholds_policy( { item => $item_object, patron => $patron } );
|
||||
|
||||
if (
|
||||
!$item->{cantreserve}
|
||||
&& !$exceeded_maxreserves
|
||||
&& $can_item_be_reserved eq 'OK'
|
||||
# items_any_available defined outside of the current loop,
|
||||
# so we avoiding loop inside IsAvailableForItemLevelRequest:
|
||||
&& IsAvailableForItemLevelRequest($item_object, $patron, undef, $items_any_available)
|
||||
)
|
||||
# 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
|
||||
# patron placed a record level hold, all the holds the patron places must
|
||||
# be record level. If the patron placed an item level hold, all holds
|
||||
# the patron places must be item level
|
||||
my $holds = Koha::Holds->search(
|
||||
{
|
||||
# Send the pickup locations count to the UI, the pickup locations will be pulled using the API
|
||||
my @pickup_locations = $item_object->pickup_locations({ patron => $patron })->as_list;
|
||||
$item->{pickup_locations_count} = scalar @pickup_locations;
|
||||
|
||||
if ( @pickup_locations ) {
|
||||
$num_available++;
|
||||
$item->{available} = 1;
|
||||
|
||||
my $default_pickup_location;
|
||||
|
||||
# Default to logged-in, if valid
|
||||
if ( C4::Context->userenv->{branch} ) {
|
||||
($default_pickup_location) = grep { $_->branchcode eq C4::Context->userenv->{branch} } @pickup_locations;
|
||||
}
|
||||
|
||||
$item->{default_pickup_location} = $default_pickup_location;
|
||||
}
|
||||
else {
|
||||
$item->{available} = 0;
|
||||
$item->{not_holdable} = "no_valid_pickup_location";
|
||||
}
|
||||
|
||||
push( @available_itemtypes, $item->{itype} );
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
biblionumber => $biblionumber,
|
||||
found => undef,
|
||||
}
|
||||
elsif ( C4::Context->preference('AllowHoldPolicyOverride') ) {
|
||||
# If AllowHoldPolicyOverride is set, it should override EVERY restriction, not just branch item rules
|
||||
# with the exception of itemAlreadyOnHold because, you know, the item is already on hold
|
||||
if ( $can_item_be_reserved ne 'itemAlreadyOnHold' ) {
|
||||
);
|
||||
$force_hold_level = $holds->forced_hold_level();
|
||||
$biblioloopiter{force_hold_level} = $force_hold_level;
|
||||
$template->param( force_hold_level => $force_hold_level );
|
||||
|
||||
# For a librarian to be able to place multiple record holds for a patron for a record,
|
||||
# we must find out what the maximum number of holds they can place for the patron is
|
||||
my $max_holds_for_record = GetMaxPatronHoldsForRecord( $patron->borrowernumber, $biblionumber );
|
||||
my $remaining_holds_for_record = $max_holds_for_record - $holds->count();
|
||||
$biblioloopiter{remaining_holds_for_record} = $max_holds_for_record;
|
||||
$template->param( max_holds_for_record => $max_holds_for_record );
|
||||
$template->param( remaining_holds_for_record => $remaining_holds_for_record );
|
||||
}
|
||||
|
||||
|
||||
my $count = Koha::Holds->search( { biblionumber => $biblionumber } )->count();
|
||||
my $totalcount = $count;
|
||||
|
||||
# adding a fixed value for priority options
|
||||
my $fixedRank = $count+1;
|
||||
|
||||
my %itemnumbers_of_biblioitem;
|
||||
|
||||
my @hostitems = get_hostitemnumbers_of($biblionumber);
|
||||
my @itemnumbers;
|
||||
if (@hostitems){
|
||||
$template->param('hostitemsflag' => 1);
|
||||
push(@itemnumbers, @hostitems);
|
||||
}
|
||||
|
||||
my $items = Koha::Items->search({ -or => { biblionumber => $biblionumber, itemnumber => { in => \@itemnumbers } } });
|
||||
|
||||
unless ( $items->count ) {
|
||||
# FIXME Then why do we continue?
|
||||
$template->param('noitems' => 1) unless ( $multi_hold );
|
||||
$biblioloopiter{noitems} = 1;
|
||||
}
|
||||
|
||||
## Here we go backwards again to create hash of biblioitemnumber to itemnumbers
|
||||
## this is important when we have analytic items which may be on another record
|
||||
my ( $iteminfos_of );
|
||||
while ( my $item = $items->next ) {
|
||||
$item = $item->unblessed;
|
||||
my $biblioitemnumber = $item->{biblioitemnumber};
|
||||
my $itemnumber = $item->{itemnumber};
|
||||
push( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} }, $itemnumber );
|
||||
$iteminfos_of->{$itemnumber} = $item;
|
||||
}
|
||||
|
||||
my @biblioitemnumbers = keys %itemnumbers_of_biblioitem;
|
||||
|
||||
my $biblioiteminfos_of = {
|
||||
map {
|
||||
my $biblioitem = $_;
|
||||
( $biblioitem->{biblioitemnumber} => $biblioitem )
|
||||
} @{ Koha::Biblioitems->search(
|
||||
{ biblioitemnumber => { -in => \@biblioitemnumbers } },
|
||||
{ select => ['biblionumber', 'biblioitemnumber', 'publicationyear', 'itemtype']}
|
||||
)->unblessed
|
||||
}
|
||||
};
|
||||
|
||||
my @bibitemloop;
|
||||
|
||||
my @available_itemtypes;
|
||||
foreach my $biblioitemnumber (@biblioitemnumbers) {
|
||||
my $biblioitem = $biblioiteminfos_of->{$biblioitemnumber};
|
||||
my $num_available = 0;
|
||||
my $num_override = 0;
|
||||
my $hiddencount = 0;
|
||||
my $num_alreadyheld = 0;
|
||||
|
||||
$biblioitem->{force_hold_level} = $force_hold_level;
|
||||
|
||||
if ( $biblioitem->{biblioitemnumber} ne $biblionumber ) {
|
||||
$biblioitem->{hostitemsflag} = 1;
|
||||
}
|
||||
|
||||
$biblioloopiter{description} = $biblioitem->{description};
|
||||
$biblioloopiter{itypename} = $biblioitem->{description};
|
||||
if ( $biblioitem->{itemtype} ) {
|
||||
|
||||
$biblioitem->{description} =
|
||||
$itemtypes->{ $biblioitem->{itemtype} }{description};
|
||||
|
||||
$biblioloopiter{imageurl} =
|
||||
getitemtypeimagelocation( 'intranet',
|
||||
$itemtypes->{ $biblioitem->{itemtype} }{imageurl} );
|
||||
}
|
||||
|
||||
# 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 => $biblioitem->{biblionumber}, patron => $patron })
|
||||
if $patron;
|
||||
|
||||
foreach my $itemnumber ( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} } ) {
|
||||
my $item = $iteminfos_of->{$itemnumber};
|
||||
my $do_check;
|
||||
if ( $patron ) {
|
||||
$do_check = $patron->do_check_for_previous_checkout($item) if $wants_check;
|
||||
if ( $do_check && $wants_check ) {
|
||||
$item->{checked_previously} = $do_check;
|
||||
if ( $multi_hold ) {
|
||||
$biblioloopiter{checked_previously} = $do_check;
|
||||
} else {
|
||||
$template->param( checked_previously => $do_check );
|
||||
}
|
||||
}
|
||||
}
|
||||
$item->{force_hold_level} = $force_hold_level;
|
||||
|
||||
unless (C4::Context->preference('item-level_itypes')) {
|
||||
$item->{itype} = $biblioitem->{itemtype};
|
||||
}
|
||||
|
||||
$item->{itypename} = $itemtypes->{ $item->{itype} }{description};
|
||||
$item->{imageurl} = getitemtypeimagelocation( 'intranet', $itemtypes->{ $item->{itype} }{imageurl} );
|
||||
$item->{homebranch} = $item->{homebranch};
|
||||
|
||||
# if the holdingbranch is different than the homebranch, we show the
|
||||
# holdingbranch of the document too
|
||||
if ( $item->{homebranch} ne $item->{holdingbranch} ) {
|
||||
$item->{holdingbranch} = $item->{holdingbranch};
|
||||
}
|
||||
|
||||
if($item->{biblionumber} ne $biblionumber){
|
||||
$item->{hostitemsflag} = 1;
|
||||
$item->{hosttitle} = Koha::Biblios->find( $item->{biblionumber} )->title;
|
||||
}
|
||||
|
||||
# if the item is currently on loan, we display its return date and
|
||||
# change the background color
|
||||
my $issue = Koha::Checkouts->find( { itemnumber => $itemnumber } );
|
||||
if ( $issue ) {
|
||||
$item->{date_due} = $issue->date_due;
|
||||
$item->{backgroundcolor} = 'onloan';
|
||||
}
|
||||
|
||||
# checking reserve
|
||||
my $item_object = Koha::Items->find( $itemnumber );
|
||||
my $holds = $item_object->current_holds;
|
||||
if ( my $first_hold = $holds->next ) {
|
||||
my $p = Koha::Patrons->find( $first_hold->borrowernumber );
|
||||
|
||||
$item->{backgroundcolor} = 'reserved';
|
||||
$item->{reservedate} = output_pref({ dt => dt_from_string( $first_hold->reservedate ), dateonly => 1 }); # FIXME Should be formatted in the template
|
||||
$item->{ReservedFor} = $p;
|
||||
$item->{ExpectedAtLibrary} = $first_hold->branchcode;
|
||||
$item->{waitingdate} = $first_hold->waitingdate;
|
||||
}
|
||||
|
||||
# Management of the notforloan document
|
||||
if ( $item->{notforloan} ) {
|
||||
$item->{backgroundcolor} = 'other';
|
||||
}
|
||||
|
||||
# Management of lost or long overdue items
|
||||
if ( $item->{itemlost} ) {
|
||||
$item->{backgroundcolor} = 'other';
|
||||
if ($logged_in_patron->category->hidelostitems && !$showallitems) {
|
||||
$item->{hide} = 1;
|
||||
$hiddencount++;
|
||||
}
|
||||
}
|
||||
|
||||
# Check the transit status
|
||||
my ( $transfertwhen, $transfertfrom, $transfertto ) =
|
||||
GetTransfers($itemnumber);
|
||||
|
||||
if ( defined $transfertwhen && $transfertwhen ne '' ) {
|
||||
$item->{transfertwhen} = output_pref({ dt => dt_from_string( $transfertwhen ), dateonly => 1 });
|
||||
$item->{transfertfrom} = $transfertfrom;
|
||||
$item->{transfertto} = $transfertto;
|
||||
$item->{nocancel} = 1;
|
||||
}
|
||||
|
||||
# If there is no loan, return and transfer, we show a checkbox.
|
||||
$item->{notforloan} ||= 0;
|
||||
|
||||
# if independent branches is on we need to check if the person can reserve
|
||||
# for branches they arent logged in to
|
||||
if ( C4::Context->preference("IndependentBranches") ) {
|
||||
if (! C4::Context->preference("canreservefromotherbranches")){
|
||||
# can't reserve items so need to check if item homebranch and userenv branch match if not we can't reserve
|
||||
my $userenv = C4::Context->userenv;
|
||||
unless ( C4::Context->IsSuperLibrarian ) {
|
||||
$item->{cantreserve} = 1 if ( $item->{homebranch} ne $userenv->{branch} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $patron ) {
|
||||
my $patron_unblessed = $patron->unblessed;
|
||||
my $branch = C4::Circulation::_GetCircControlBranch($item, $patron_unblessed);
|
||||
|
||||
my $branchitemrule = GetBranchItemRule( $branch, $item->{'itype'} );
|
||||
|
||||
$item->{'holdallowed'} = $branchitemrule->{'holdallowed'};
|
||||
|
||||
my $can_item_be_reserved = CanItemBeReserved( $patron->borrowernumber, $itemnumber )->{status};
|
||||
$item->{not_holdable} = $can_item_be_reserved unless ( $can_item_be_reserved eq 'OK' );
|
||||
|
||||
$item->{item_level_holds} = Koha::CirculationRules->get_opacitemholds_policy( { item => $item_object, patron => $patron } );
|
||||
|
||||
if (
|
||||
!$item->{cantreserve}
|
||||
&& !$exceeded_maxreserves
|
||||
&& $can_item_be_reserved eq 'OK'
|
||||
# items_any_available defined outside of the current loop,
|
||||
# so we avoiding loop inside IsAvailableForItemLevelRequest:
|
||||
&& IsAvailableForItemLevelRequest($item_object, $patron, undef, $items_any_available)
|
||||
)
|
||||
{
|
||||
# Send the pickup locations count to the UI, the pickup locations will be pulled using the API
|
||||
my $pickup_locations = $item_object->pickup_locations({ patron => $patron });
|
||||
$item->{pickup_locations_count} = $pickup_locations->count;
|
||||
if ( $item->{pickup_locations_count} > 0 ) {
|
||||
$item->{override} = 1;
|
||||
$num_override++;
|
||||
# pass the holding branch for use as default
|
||||
my $default_pickup_location = $pickup_locations->search({ branchcode => $item->{holdingbranch} })->next;
|
||||
my @pickup_locations = $item_object->pickup_locations({ patron => $patron })->as_list;
|
||||
$item->{pickup_locations_count} = scalar @pickup_locations;
|
||||
|
||||
if ( @pickup_locations ) {
|
||||
$num_available++;
|
||||
$item->{available} = 1;
|
||||
|
||||
my $default_pickup_location;
|
||||
|
||||
# Default to logged-in, if valid
|
||||
if ( C4::Context->userenv->{branch} ) {
|
||||
($default_pickup_location) = grep { $_->branchcode eq C4::Context->userenv->{branch} } @pickup_locations;
|
||||
}
|
||||
|
||||
$item->{default_pickup_location} = $default_pickup_location;
|
||||
}
|
||||
else {
|
||||
$item->{available} = 0;
|
||||
$item->{not_holdable} = "no_valid_pickup_location";
|
||||
}
|
||||
} else { $num_alreadyheld++ }
|
||||
|
||||
push( @available_itemtypes, $item->{itype} );
|
||||
push( @available_itemtypes, $item->{itype} );
|
||||
}
|
||||
elsif ( C4::Context->preference('AllowHoldPolicyOverride') ) {
|
||||
# If AllowHoldPolicyOverride is set, it should override EVERY restriction, not just branch item rules
|
||||
# with the exception of itemAlreadyOnHold because, you know, the item is already on hold
|
||||
if ( $can_item_be_reserved ne 'itemAlreadyOnHold' ) {
|
||||
# Send the pickup locations count to the UI, the pickup locations will be pulled using the API
|
||||
my $pickup_locations = $item_object->pickup_locations({ patron => $patron });
|
||||
$item->{pickup_locations_count} = $pickup_locations->count;
|
||||
if ( $item->{pickup_locations_count} > 0 ) {
|
||||
$item->{override} = 1;
|
||||
$num_override++;
|
||||
# pass the holding branch for use as default
|
||||
my $default_pickup_location = $pickup_locations->search({ branchcode => $item->{holdingbranch} })->next;
|
||||
$item->{default_pickup_location} = $default_pickup_location;
|
||||
}
|
||||
else {
|
||||
$item->{available} = 0;
|
||||
$item->{not_holdable} = "no_valid_pickup_location";
|
||||
}
|
||||
} else { $num_alreadyheld++ }
|
||||
|
||||
push( @available_itemtypes, $item->{itype} );
|
||||
}
|
||||
|
||||
# If none of the conditions hold true, then neither override nor available is set and the item cannot be checked
|
||||
|
||||
# Show serial enumeration when needed
|
||||
if ($item->{enumchron}) {
|
||||
$itemdata_enumchron = 1;
|
||||
}
|
||||
# Show collection when needed
|
||||
if ($item->{ccode}) {
|
||||
$itemdata_ccode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# If none of the conditions hold true, then neither override nor available is set and the item cannot be checked
|
||||
push @{ $biblioitem->{itemloop} }, $item;
|
||||
}
|
||||
|
||||
# Show serial enumeration when needed
|
||||
if ($item->{enumchron}) {
|
||||
$itemdata_enumchron = 1;
|
||||
}
|
||||
# Show collection when needed
|
||||
if ($item->{ccode}) {
|
||||
$itemdata_ccode = 1;
|
||||
# While we can't override an alreay held item, we should be able to override the others
|
||||
# Unless all items are already held
|
||||
if ( $num_override > 0 && ($num_override + $num_alreadyheld) == scalar( @{ $biblioitem->{itemloop} } ) ) {
|
||||
# That is, if all items require an override
|
||||
$template->param( override_required => 1 );
|
||||
} elsif ( $num_available == 0 ) {
|
||||
$template->param( none_available => 1 );
|
||||
$biblioloopiter{warn} = 1;
|
||||
$biblioloopiter{none_avail} = 1;
|
||||
}
|
||||
$template->param( hiddencount => $hiddencount);
|
||||
|
||||
push @bibitemloop, $biblioitem;
|
||||
}
|
||||
|
||||
@available_itemtypes = uniq( @available_itemtypes );
|
||||
$template->param( available_itemtypes => \@available_itemtypes );
|
||||
|
||||
# existingreserves building
|
||||
my @reserveloop;
|
||||
my @reserves = Koha::Holds->search( { biblionumber => $biblionumber }, { order_by => 'priority' } );
|
||||
foreach my $res (
|
||||
sort {
|
||||
my $a_found = $a->found() || '';
|
||||
my $b_found = $a->found() || '';
|
||||
$a_found cmp $b_found;
|
||||
} @reserves
|
||||
)
|
||||
{
|
||||
my %reserve;
|
||||
if ( $res->is_found() ) {
|
||||
$reserve{'holdingbranch'} = $res->item()->holdingbranch();
|
||||
$reserve{'biblionumber'} = $res->item()->biblionumber();
|
||||
$reserve{'barcodenumber'} = $res->item()->barcode();
|
||||
$reserve{'wbrcode'} = $res->branchcode();
|
||||
$reserve{'itemnumber'} = $res->itemnumber();
|
||||
$reserve{'wbrname'} = $res->branch()->branchname();
|
||||
$reserve{'atdestination'} = $res->is_at_destination();
|
||||
$reserve{'desk_name'} = ( $res->desk() ) ? $res->desk()->desk_name() : '' ;
|
||||
$reserve{'found'} = $res->is_found();
|
||||
$reserve{'inprocessing'} = $res->is_in_processing();
|
||||
$reserve{'intransit'} = $res->is_in_transit();
|
||||
}
|
||||
elsif ( $res->priority() > 0 ) {
|
||||
if ( my $item = $res->item() ) {
|
||||
$reserve{'itemnumber'} = $item->id();
|
||||
$reserve{'barcodenumber'} = $item->barcode();
|
||||
$reserve{'item_level_hold'} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
push @{ $biblioitem->{itemloop} }, $item;
|
||||
$reserve{'expirationdate'} = $res->expirationdate;
|
||||
$reserve{'date'} = $res->reservedate;
|
||||
$reserve{'borrowernumber'} = $res->borrowernumber();
|
||||
$reserve{'biblionumber'} = $res->biblionumber();
|
||||
$reserve{'patron'} = $res->borrower;
|
||||
$reserve{'notes'} = $res->reservenotes();
|
||||
$reserve{'waiting_date'} = $res->waitingdate();
|
||||
$reserve{'ccode'} = $res->item() ? $res->item()->ccode() : undef;
|
||||
$reserve{'barcode'} = $res->item() ? $res->item()->barcode() : undef;
|
||||
$reserve{'priority'} = $res->priority();
|
||||
$reserve{'lowestPriority'} = $res->lowestPriority();
|
||||
$reserve{'suspend'} = $res->suspend();
|
||||
$reserve{'suspend_until'} = $res->suspend_until();
|
||||
$reserve{'reserve_id'} = $res->reserve_id();
|
||||
$reserve{itemtype} = $res->itemtype();
|
||||
$reserve{branchcode} = $res->branchcode();
|
||||
$reserve{non_priority} = $res->non_priority();
|
||||
$reserve{object} = $res;
|
||||
|
||||
push( @reserveloop, \%reserve );
|
||||
}
|
||||
|
||||
# While we can't override an alreay held item, we should be able to override the others
|
||||
# Unless all items are already held
|
||||
if ( $num_override > 0 && ($num_override + $num_alreadyheld) == scalar( @{ $biblioitem->{itemloop} } ) ) {
|
||||
# That is, if all items require an override
|
||||
$template->param( override_required => 1 );
|
||||
} elsif ( $num_available == 0 ) {
|
||||
$template->param( none_available => 1 );
|
||||
$biblioloopiter{warn} = 1;
|
||||
$biblioloopiter{none_avail} = 1;
|
||||
}
|
||||
$template->param( hiddencount => $hiddencount);
|
||||
# get the time for the form name...
|
||||
my $time = time();
|
||||
|
||||
push @bibitemloop, $biblioitem;
|
||||
}
|
||||
$template->param(
|
||||
time => $time,
|
||||
fixedRank => $fixedRank,
|
||||
);
|
||||
|
||||
@available_itemtypes = uniq( @available_itemtypes );
|
||||
$template->param( available_itemtypes => \@available_itemtypes );
|
||||
# display infos
|
||||
$template->param(
|
||||
bibitemloop => \@bibitemloop,
|
||||
itemdata_enumchron => $itemdata_enumchron,
|
||||
itemdata_ccode => $itemdata_ccode,
|
||||
date => $date,
|
||||
biblionumber => $biblionumber,
|
||||
findborrower => $findborrower,
|
||||
biblio => $biblio,
|
||||
holdsview => 1,
|
||||
C4::Search::enabled_staff_search_views,
|
||||
);
|
||||
|
||||
# existingreserves building
|
||||
my @reserveloop;
|
||||
my @reserves = Koha::Holds->search( { biblionumber => $biblionumber }, { order_by => 'priority' } );
|
||||
foreach my $res (
|
||||
sort {
|
||||
my $a_found = $a->found() || '';
|
||||
my $b_found = $a->found() || '';
|
||||
$a_found cmp $b_found;
|
||||
} @reserves
|
||||
)
|
||||
{
|
||||
my %reserve;
|
||||
if ( $res->is_found() ) {
|
||||
$reserve{'holdingbranch'} = $res->item()->holdingbranch();
|
||||
$reserve{'biblionumber'} = $res->item()->biblionumber();
|
||||
$reserve{'barcodenumber'} = $res->item()->barcode();
|
||||
$reserve{'wbrcode'} = $res->branchcode();
|
||||
$reserve{'itemnumber'} = $res->itemnumber();
|
||||
$reserve{'wbrname'} = $res->branch()->branchname();
|
||||
$reserve{'atdestination'} = $res->is_at_destination();
|
||||
$reserve{'desk_name'} = ( $res->desk() ) ? $res->desk()->desk_name() : '' ;
|
||||
$reserve{'found'} = $res->is_found();
|
||||
$reserve{'inprocessing'} = $res->is_in_processing();
|
||||
$reserve{'intransit'} = $res->is_in_transit();
|
||||
}
|
||||
elsif ( $res->priority() > 0 ) {
|
||||
if ( my $item = $res->item() ) {
|
||||
$reserve{'itemnumber'} = $item->id();
|
||||
$reserve{'barcodenumber'} = $item->barcode();
|
||||
$reserve{'item_level_hold'} = 1;
|
||||
}
|
||||
$biblioloopiter{biblionumber} = $biblionumber;
|
||||
$biblioloopiter{title} = $biblio->title;
|
||||
$biblioloopiter{rank} = $fixedRank;
|
||||
$biblioloopiter{reserveloop} = \@reserveloop;
|
||||
|
||||
if (@reserveloop) {
|
||||
$template->param( reserveloop => \@reserveloop );
|
||||
}
|
||||
|
||||
$reserve{'expirationdate'} = $res->expirationdate;
|
||||
$reserve{'date'} = $res->reservedate;
|
||||
$reserve{'borrowernumber'} = $res->borrowernumber();
|
||||
$reserve{'biblionumber'} = $res->biblionumber();
|
||||
$reserve{'patron'} = $res->borrower;
|
||||
$reserve{'notes'} = $res->reservenotes();
|
||||
$reserve{'waiting_date'} = $res->waitingdate();
|
||||
$reserve{'ccode'} = $res->item() ? $res->item()->ccode() : undef;
|
||||
$reserve{'barcode'} = $res->item() ? $res->item()->barcode() : undef;
|
||||
$reserve{'priority'} = $res->priority();
|
||||
$reserve{'lowestPriority'} = $res->lowestPriority();
|
||||
$reserve{'suspend'} = $res->suspend();
|
||||
$reserve{'suspend_until'} = $res->suspend_until();
|
||||
$reserve{'reserve_id'} = $res->reserve_id();
|
||||
$reserve{itemtype} = $res->itemtype();
|
||||
$reserve{branchcode} = $res->branchcode();
|
||||
$reserve{non_priority} = $res->non_priority();
|
||||
$reserve{object} = $res;
|
||||
if ( $patron ) {
|
||||
# Add the valid pickup locations
|
||||
my @pickup_locations = $biblio->pickup_locations({ patron => $patron })->as_list;
|
||||
$biblioloopiter{pickup_locations} = \@pickup_locations;
|
||||
$biblioloopiter{pickup_locations_codes} = [ map { $_->branchcode } @pickup_locations ];
|
||||
}
|
||||
|
||||
push( @reserveloop, \%reserve );
|
||||
push @biblioloop, \%biblioloopiter;
|
||||
}
|
||||
|
||||
# get the time for the form name...
|
||||
my $time = time();
|
||||
|
||||
$template->param(
|
||||
time => $time,
|
||||
fixedRank => $fixedRank,
|
||||
);
|
||||
|
||||
# display infos
|
||||
$template->param(
|
||||
bibitemloop => \@bibitemloop,
|
||||
itemdata_enumchron => $itemdata_enumchron,
|
||||
itemdata_ccode => $itemdata_ccode,
|
||||
date => $date,
|
||||
biblionumber => $biblionumber,
|
||||
findborrower => $findborrower,
|
||||
biblio => $biblio,
|
||||
holdsview => 1,
|
||||
C4::Search::enabled_staff_search_views,
|
||||
);
|
||||
|
||||
$biblioloopiter{biblionumber} = $biblionumber;
|
||||
$biblioloopiter{title} = $biblio->title;
|
||||
$biblioloopiter{rank} = $fixedRank;
|
||||
$biblioloopiter{reserveloop} = \@reserveloop;
|
||||
|
||||
if (@reserveloop) {
|
||||
$template->param( reserveloop => \@reserveloop );
|
||||
}
|
||||
|
||||
if ( $patron ) {
|
||||
# Add the valid pickup locations
|
||||
my @pickup_locations = $biblio->pickup_locations({ patron => $patron })->as_list;
|
||||
$biblioloopiter{pickup_locations} = \@pickup_locations;
|
||||
$biblioloopiter{pickup_locations_codes} = [ map { $_->branchcode } @pickup_locations ];
|
||||
}
|
||||
|
||||
push @biblioloop, \%biblioloopiter;
|
||||
$template->param( biblioloop => \@biblioloop );
|
||||
$template->param( no_reserves_allowed => $no_reserves_allowed );
|
||||
$template->param( exceeded_maxreserves => $exceeded_maxreserves );
|
||||
$template->param( exceeded_holds_per_record => $exceeded_holds_per_record );
|
||||
$template->param( subscriptionsnumber => CountSubscriptionFromBiblionumber($biblionumber));
|
||||
} elsif ( ! $multi_hold ) {
|
||||
my $biblio = Koha::Biblios->find( $biblionumber );
|
||||
$template->param( biblio => $biblio );
|
||||
}
|
||||
|
||||
$template->param( biblioloop => \@biblioloop );
|
||||
$template->param( no_reserves_allowed => $no_reserves_allowed );
|
||||
$template->param( biblionumbers => join('/', @biblionumbers) );
|
||||
$template->param( exceeded_maxreserves => $exceeded_maxreserves );
|
||||
$template->param( exceeded_holds_per_record => $exceeded_holds_per_record );
|
||||
$template->param( subscriptionsnumber => CountSubscriptionFromBiblionumber($biblionumber));
|
||||
if ( $multi_hold ) {
|
||||
$template->param( biblionumbers => join('/', @biblionumbers) );
|
||||
} else {
|
||||
$template->param( biblionumber => $biblionumber || $biblionumbers[0] );
|
||||
}
|
||||
|
||||
# pass the userenv branch if no pickup location selected
|
||||
$template->param( pickup => $pickup || C4::Context->userenv->{branch} );
|
||||
|
|
|
|||
Loading…
Reference in New Issue