Lines 26-32
use C4::Koha qw( getitemtypeimagelocation getitemtypeimagesrc );
Link Here
|
26 |
use C4::Circulation qw( GetBranchItemRule GetTransfers ); |
26 |
use C4::Circulation qw( GetBranchItemRule GetTransfers ); |
27 |
use C4::Reserves qw( CanItemBeReserved CanBookBeReserved AddReserve GetReservesControlBranch ItemsAnyAvailableAndNotRestricted IsAvailableForItemLevelRequest ); |
27 |
use C4::Reserves qw( CanItemBeReserved CanBookBeReserved AddReserve GetReservesControlBranch ItemsAnyAvailableAndNotRestricted IsAvailableForItemLevelRequest ); |
28 |
use C4::Biblio qw( GetBiblioData GetFrameworkCode ); |
28 |
use C4::Biblio qw( GetBiblioData GetFrameworkCode ); |
29 |
use C4::Items qw( GetHostItemsInfo GetItemsInfo ); |
|
|
30 |
use C4::Output qw( output_html_with_http_headers ); |
29 |
use C4::Output qw( output_html_with_http_headers ); |
31 |
use C4::Context; |
30 |
use C4::Context; |
32 |
use C4::Members; |
31 |
use C4::Members; |
Lines 142-171
$template->param( branch => $branch );
Link Here
|
142 |
# |
141 |
# |
143 |
|
142 |
|
144 |
my %biblioDataHash; # Hash of biblionumber to biblio/biblioitems record. |
143 |
my %biblioDataHash; # Hash of biblionumber to biblio/biblioitems record. |
145 |
my %itemInfoHash; # Hash of itemnumber to item info. |
|
|
146 |
foreach my $biblioNumber (@biblionumbers) { |
144 |
foreach my $biblioNumber (@biblionumbers) { |
147 |
|
145 |
|
148 |
my $biblioData = GetBiblioData($biblioNumber); |
146 |
my $biblioData = GetBiblioData($biblioNumber); |
149 |
$biblioDataHash{$biblioNumber} = $biblioData; |
147 |
$biblioDataHash{$biblioNumber} = $biblioData; |
150 |
|
148 |
|
151 |
my @itemInfos = GetItemsInfo($biblioNumber); |
|
|
152 |
|
153 |
my $biblio = Koha::Biblios->find( $biblioNumber ); |
149 |
my $biblio = Koha::Biblios->find( $biblioNumber ); |
154 |
next unless $biblio; |
150 |
next unless $biblio; |
155 |
|
151 |
|
156 |
my $marcrecord = $biblio->metadata->record; |
152 |
my $marcrecord = $biblio->metadata->record; |
157 |
|
153 |
|
158 |
# flag indicating existence of at least one item linked via a host record |
154 |
my $items = |
159 |
# adding items linked via host biblios |
155 |
$biblio->items->filter_by_visible_in_opac( { patron => $patron } ); |
160 |
my @hostitemInfos = GetHostItemsInfo($marcrecord); |
156 |
my $host_items = |
161 |
if (@hostitemInfos){ |
157 |
$biblio->host_items->filter_by_visible_in_opac( { patron => $patron } ); |
162 |
push (@itemInfos,@hostitemInfos); |
158 |
$items = $biblio->items->search( |
163 |
} |
159 |
{ |
|
|
160 |
itemnumber => { |
161 |
-in => [ |
162 |
$items->get_column('itemnumber'), |
163 |
$host_items->get_column('itemnumber') |
164 |
] |
165 |
} |
166 |
} |
167 |
); |
164 |
|
168 |
|
165 |
$biblioData->{itemInfos} = \@itemInfos; |
169 |
$biblioData->{items} = [$items->as_list]; # FIXME Potentially a lot in memory here! |
166 |
foreach my $itemInfo (@itemInfos) { |
|
|
167 |
$itemInfoHash{$itemInfo->{itemnumber}} = $itemInfo; |
168 |
} |
169 |
|
170 |
|
170 |
# Compute the priority rank. |
171 |
# Compute the priority rank. |
171 |
$biblioData->{object} = $biblio; |
172 |
$biblioData->{object} = $biblio; |
Lines 237-242
if ( $query->param('place_reserve') ) {
Link Here
|
237 |
$branch = $patron->branchcode; |
238 |
$branch = $patron->branchcode; |
238 |
} |
239 |
} |
239 |
|
240 |
|
|
|
241 |
# FIXME We shouldn't need to fetch the item here |
240 |
my $item = $itemNum ? Koha::Items->find( $itemNum ) : undef; |
242 |
my $item = $itemNum ? Koha::Items->find( $itemNum ) : undef; |
241 |
# When choosing a specific item, the default pickup library should be dictated by the default hold policy |
243 |
# When choosing a specific item, the default pickup library should be dictated by the default hold policy |
242 |
if ( ! C4::Context->preference("OPACAllowUserToChooseBranch") && $item ) { |
244 |
if ( ! C4::Context->preference("OPACAllowUserToChooseBranch") && $item ) { |
Lines 411-416
my $itemLevelTypes = C4::Context->preference('item-level_itypes');
Link Here
|
411 |
my $pickup_locations = Koha::Libraries->search({ pickup_location => 1 }); |
413 |
my $pickup_locations = Koha::Libraries->search({ pickup_location => 1 }); |
412 |
$template->param('item_level_itypes' => $itemLevelTypes); |
414 |
$template->param('item_level_itypes' => $itemLevelTypes); |
413 |
|
415 |
|
|
|
416 |
my $patron_unblessed = $patron->unblessed; |
414 |
foreach my $biblioNum (@biblionumbers) { |
417 |
foreach my $biblioNum (@biblionumbers) { |
415 |
|
418 |
|
416 |
# Init the bib item with the choices for branch pickup |
419 |
# Init the bib item with the choices for branch pickup |
Lines 448-472
foreach my $biblioNum (@biblionumbers) {
Link Here
|
448 |
$biblioLoopIter{imageurl} = getitemtypeimagesrc() . "/". $itemtypes->{$biblioData->{itemtype}}{imageurl}; |
451 |
$biblioLoopIter{imageurl} = getitemtypeimagesrc() . "/". $itemtypes->{$biblioData->{itemtype}}{imageurl}; |
449 |
} |
452 |
} |
450 |
|
453 |
|
451 |
foreach my $itemInfo (@{$biblioData->{itemInfos}}) { |
|
|
452 |
if ($itemLevelTypes && $itemInfo->{itype}) { |
453 |
$itemInfo->{translated_description} = $itemtypes->{$itemInfo->{itype}}{translated_description}; |
454 |
$itemInfo->{imageurl} = getitemtypeimagesrc() . "/". $itemtypes->{$itemInfo->{itype}}{imageurl}; |
455 |
} |
456 |
|
457 |
if (!$itemInfo->{'notforloan'} && !($itemInfo->{'itemnotforloan'} > 0)) { |
458 |
$biblioLoopIter{forloan} = 1; |
459 |
} |
460 |
} |
461 |
|
462 |
my @notforloan_avs = Koha::AuthorisedValues->search_by_koha_field({ kohafield => 'items.notforloan', frameworkcode => $frameworkcode })->as_list; |
463 |
my $notforloan_label_of = { map { $_->authorised_value => $_->opac_description } @notforloan_avs }; |
464 |
|
465 |
my $visible_items = { map { $_->itemnumber => $_ } $biblio->items->filter_by_visible_in_opac( { patron => $patron } )->as_list }; |
466 |
|
454 |
|
467 |
# Only keep the items that are visible in the opac (i.e. those in %visible_items) |
|
|
468 |
# FIXME: We should get rid of itemInfos altogether and use $visible_items |
469 |
$biblioData->{itemInfos} = [ grep { $visible_items->{ $_->{itemnumber} } } @{ $biblioData->{itemInfos} } ]; |
470 |
|
455 |
|
471 |
$biblioLoopIter{itemLoop} = []; |
456 |
$biblioLoopIter{itemLoop} = []; |
472 |
my $numCopiesAvailable = 0; |
457 |
my $numCopiesAvailable = 0; |
Lines 477-567
foreach my $biblioNum (@biblionumbers) {
Link Here
|
477 |
# (before this loop was inside that sub loop so it was O(n^2) ) |
462 |
# (before this loop was inside that sub loop so it was O(n^2) ) |
478 |
my $items_any_available; |
463 |
my $items_any_available; |
479 |
$items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $biblioNum, patron => $patron }) if $patron; |
464 |
$items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $biblioNum, patron => $patron }) if $patron; |
480 |
foreach my $itemInfo (@{$biblioData->{itemInfos}}) { |
465 |
foreach my $item (@{$biblioData->{items}}) { |
481 |
my $itemNum = $itemInfo->{itemnumber}; |
|
|
482 |
my $item = $visible_items->{$itemNum}; |
483 |
my $itemLoopIter = {}; |
484 |
|
485 |
$itemLoopIter->{itemnumber} = $itemNum; |
486 |
$itemLoopIter->{barcode} = $itemInfo->{barcode}; |
487 |
$itemLoopIter->{homeBranchName} = $itemInfo->{homebranch}; |
488 |
$itemLoopIter->{callNumber} = $itemInfo->{itemcallnumber}; |
489 |
$itemLoopIter->{enumchron} = $itemInfo->{enumchron}; |
490 |
$itemLoopIter->{ccode} = $itemInfo->{ccode}; |
491 |
$itemLoopIter->{copynumber} = $itemInfo->{copynumber}; |
492 |
$itemLoopIter->{itemnotes} = $itemInfo->{itemnotes}; |
493 |
if ($itemLevelTypes) { |
494 |
$itemLoopIter->{translated_description} = $itemInfo->{translated_description}; |
495 |
$itemLoopIter->{itype} = $itemInfo->{itype}; |
496 |
$itemLoopIter->{imageurl} = $itemInfo->{imageurl}; |
497 |
} |
498 |
|
499 |
# If the holdingbranch is different than the homebranch, we show the |
500 |
# holdingbranch of the document too. |
501 |
if ( $itemInfo->{homebranch} ne $itemInfo->{holdingbranch} ) { |
502 |
$itemLoopIter->{holdingBranchName} = $itemInfo->{holdingbranch}; |
503 |
} |
504 |
|
466 |
|
505 |
# If the item is currently on loan, we display its return date and |
467 |
my $item_info = $item->unblessed; |
506 |
# change the background color. |
468 |
$item_info->{holding_branch} = $item->holding_branch; |
507 |
my $issue = Koha::Checkouts->find( { itemnumber => $itemNum } ); |
469 |
$item_info->{home_branch} = $item->home_branch; |
508 |
if ( $issue ) { |
470 |
if ($itemLevelTypes) { |
509 |
$itemLoopIter->{dateDue} = $issue->date_due; |
471 |
my $itemtype = $item->itemtype; |
510 |
$itemLoopIter->{onloan} = 'onloan'; |
472 |
$item_info->{'imageurl'} = getitemtypeimagelocation( 'opac', |
|
|
473 |
$itemtypes->{ $itemtype->itemtype }->{'imageurl'} ); |
474 |
$item_info->{'translated_description'} = |
475 |
$itemtypes->{ $itemtype->itemtype }->{translated_description}; |
511 |
} |
476 |
} |
512 |
|
477 |
|
513 |
# checking reserve |
478 |
# checking for holds |
514 |
my $holds = $item->current_holds; |
479 |
my $holds = $item->current_holds; |
515 |
|
|
|
516 |
if ( my $first_hold = $holds->next ) { |
480 |
if ( my $first_hold = $holds->next ) { |
517 |
$itemLoopIter->{backgroundcolor} = 'reserved'; |
481 |
$item_info->{first_hold} = $first_hold; |
518 |
$itemLoopIter->{reservedate} = $first_hold->reservedate, |
|
|
519 |
$itemLoopIter->{ExpectedAtLibrary} = $first_hold->branchcode; |
520 |
$itemLoopIter->{waitingdate} = $first_hold->waitingdate; |
521 |
} |
482 |
} |
522 |
|
483 |
|
523 |
$itemLoopIter->{notforloan} = $itemInfo->{notforloan}; |
484 |
$item_info->{checkout} = $item->checkout; |
524 |
$itemLoopIter->{itemnotforloan} = $itemInfo->{itemnotforloan}; |
|
|
525 |
|
526 |
# Management of the notforloan document |
527 |
if ( $itemLoopIter->{notforloan} || $itemLoopIter->{itemnotforloan}) { |
528 |
$itemLoopIter->{backgroundcolor} = 'other'; |
529 |
$itemLoopIter->{notforloanvalue} = |
530 |
$notforloan_label_of->{ $itemLoopIter->{notforloan} }; |
531 |
} |
532 |
|
533 |
# Management of lost or long overdue items |
534 |
if ( $itemInfo->{itemlost} ) { |
535 |
|
536 |
# FIXME localized strings should never be in Perl code |
537 |
$itemLoopIter->{message} = |
538 |
$itemInfo->{itemlost} == 1 ? "(lost)" |
539 |
: $itemInfo->{itemlost} == 2 ? "(long overdue)" |
540 |
: ""; |
541 |
$itemInfo->{backgroundcolor} = 'other'; |
542 |
} |
543 |
|
485 |
|
544 |
# Check of the transferred documents |
486 |
# Check of the transferred documents |
545 |
my ( $transfertwhen, $transfertfrom, $transfertto ) = |
487 |
my ( $transfertwhen, $transfertfrom, $transfertto ) = |
546 |
GetTransfers($itemNum); |
488 |
GetTransfers($item->itemnumber); |
547 |
if ( $transfertwhen && ($transfertwhen ne '') ) { |
489 |
if ( $transfertwhen && ($transfertwhen ne '') ) { |
548 |
$itemLoopIter->{transfertwhen} = output_pref({ dt => dt_from_string($transfertwhen), dateonly => 1 }); |
490 |
$item_info->{transfertwhen} = $transfertwhen; |
549 |
$itemLoopIter->{transfertfrom} = $transfertfrom; |
491 |
$item_info->{transfertfrom} = $transfertfrom; |
550 |
$itemLoopIter->{transfertto} = $transfertto; |
492 |
$item_info->{transfertto} = $transfertto; |
551 |
$itemLoopIter->{nocancel} = 1; |
493 |
$item_info->{nocancel} = 1; |
552 |
} |
494 |
} |
553 |
|
495 |
|
554 |
# if the items belongs to a host record, show link to host record |
496 |
# if the items belongs to a host record, show link to host record |
555 |
if ( $itemInfo->{biblionumber} ne $biblioNum ) { |
497 |
if ( $item_info->{biblionumber} ne $biblioNum ) { |
556 |
$itemLoopIter->{hostbiblionumber} = $itemInfo->{biblionumber}; |
498 |
$item_info->{hostbiblionumber} = $item->biblionumber; |
557 |
$itemLoopIter->{hosttitle} = Koha::Biblios->find( $itemInfo->{biblionumber} )->title; |
499 |
$item_info->{hosttitle} = Koha::Biblios->find( $item_info->{biblionumber} )->title; |
558 |
} |
500 |
} |
559 |
|
501 |
|
560 |
# If there is no loan, return and transfer, we show a checkbox. |
502 |
my $branch = GetReservesControlBranch( $item_info, $patron_unblessed ); |
561 |
$itemLoopIter->{notforloan} = $itemLoopIter->{notforloan} || 0; |
|
|
562 |
|
563 |
my $patron_unblessed = $patron->unblessed; |
564 |
my $branch = GetReservesControlBranch( $itemInfo, $patron_unblessed ); |
565 |
|
503 |
|
566 |
# items_any_available defined outside of the current loop, |
504 |
# items_any_available defined outside of the current loop, |
567 |
# so we avoiding loop inside IsAvailableForItemLevelRequest: |
505 |
# so we avoiding loop inside IsAvailableForItemLevelRequest: |
Lines 572-604
foreach my $biblioNum (@biblionumbers) {
Link Here
|
572 |
if ($policy_holdallowed) { |
510 |
if ($policy_holdallowed) { |
573 |
my $opac_hold_policy = Koha::CirculationRules->get_opacitemholds_policy( { item => $item, patron => $patron } ); |
511 |
my $opac_hold_policy = Koha::CirculationRules->get_opacitemholds_policy( { item => $item, patron => $patron } ); |
574 |
if ( $opac_hold_policy ne 'N' ) { # If Y or F |
512 |
if ( $opac_hold_policy ne 'N' ) { # If Y or F |
575 |
$itemLoopIter->{available} = 1; |
513 |
$item_info->{available} = 1; |
576 |
$numCopiesOPACAvailable++; |
514 |
$numCopiesOPACAvailable++; |
577 |
$biblioLoopIter{force_hold} = 1 if $opac_hold_policy eq 'F'; |
515 |
$biblioLoopIter{force_hold} = 1 if $opac_hold_policy eq 'F'; |
578 |
} |
516 |
} |
579 |
$numCopiesAvailable++; |
517 |
$numCopiesAvailable++; |
580 |
|
518 |
|
581 |
unless ( $can_place_hold_if_available_at_pickup ) { |
519 |
unless ( $can_place_hold_if_available_at_pickup ) { |
582 |
my $items_in_this_library = Koha::Items->search({ biblionumber => $itemInfo->{biblionumber}, holdingbranch => $itemInfo->{holdingbranch} }); |
520 |
my $items_in_this_library = Koha::Items->search({ biblionumber => $item->biblionumber, holdingbranch => $item->holdingbranch }); |
583 |
my $nb_of_items_issued = $items_in_this_library->search({ 'issue.itemnumber' => { not => undef }}, { join => 'issue' })->count; |
521 |
my $nb_of_items_issued = $items_in_this_library->search({ 'issue.itemnumber' => { not => undef }}, { join => 'issue' })->count; |
584 |
if ( $items_in_this_library->count > $nb_of_items_issued ) { |
522 |
if ( $items_in_this_library->count > $nb_of_items_issued ) { |
585 |
push @not_available_at, $itemInfo->{holdingbranch}; |
523 |
push @not_available_at, $item->holdingbranch; |
586 |
} |
524 |
} |
587 |
} |
525 |
} |
588 |
} |
526 |
} |
589 |
|
527 |
|
590 |
$itemLoopIter->{imageurl} = getitemtypeimagelocation( 'opac', $itemtypes->{ $itemInfo->{itype} }{imageurl} ); |
528 |
# Show serial enumeration when needed |
591 |
|
529 |
if ($item_info->{enumchron}) { |
592 |
# Show serial enumeration when needed |
|
|
593 |
if ($itemLoopIter->{enumchron}) { |
594 |
$itemdata_enumchron = 1; |
530 |
$itemdata_enumchron = 1; |
595 |
} |
531 |
} |
596 |
# Show collection when needed |
532 |
# Show collection when needed |
597 |
if ($itemLoopIter->{ccode}) { |
533 |
if ($item_info->{ccode}) { |
598 |
$itemdata_ccode = 1; |
534 |
$itemdata_ccode = 1; |
599 |
} |
535 |
} |
600 |
|
536 |
|
601 |
push @{$biblioLoopIter{itemLoop}}, $itemLoopIter; |
537 |
push @{$biblioLoopIter{itemLoop}}, $item_info; |
602 |
} |
538 |
} |
603 |
$template->param( |
539 |
$template->param( |
604 |
itemdata_enumchron => $itemdata_enumchron, |
540 |
itemdata_enumchron => $itemdata_enumchron, |
605 |
- |
|
|