Bugzilla – Attachment 178886 Details for
Bug 23732
Hold rules checker: show matched rules and syspref values to help understand why a hold is possible or not
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 23732: Hold rules checker
Bug-23732-Hold-rules-checker.patch (text/plain), 207.02 KB, created by
Victor Grousset/tuxayo
on 2025-03-01 07:08:12 UTC
(
hide
)
Description:
Bug 23732: Hold rules checker
Filename:
MIME Type:
Creator:
Victor Grousset/tuxayo
Created:
2025-03-01 07:08:12 UTC
Size:
207.02 KB
patch
obsolete
>From f53920e1bdada25e0161cf4a703b498502200c25 Mon Sep 17 00:00:00 2001 >From: Alex Arnaud <alex.arnaud@biblibre.com> >Date: Wed, 12 Dec 2018 11:08:43 +0100 >Subject: [PATCH] Bug 23732: Hold rules checker > >Test plan: >- apply patch >- try to place a hold, on the Hold details page you should see a > "Holding rules" button. Click on it >- check that the info is consistent with the holding rules, the syspref > and the current and future number of holds of the patron >- place the hold >- set maxreserves syspref to 1 >- try to place a hold >- see in the holds rules checker that the maxreserves is highlighted in > red >- restore maxreserves syspref >- test that sabotaging the matched circulation rule or hold policy is > reflected in the hold rules checker > >Co-authored-by: Victor Grousset/tuxayo <victor@tuxayo.net> >Co-authored-by: Arthur Suzuki <arthur.suzuki@biblibre.com> >Rebased-by: Julian Maurice <julian.maurice@biblibre.com> >Co-authored-by: Julian Maurice <julian.maurice@biblibre.com> >Rebased-by: Victor Grousset/tuxayo <victor@tuxayo.net> >--- > C4/Reserves.pm | 274 +- > .../prog/en/modules/reserve/request.tt | 2394 +++++++++-------- > reserve/request.pl | 60 +- > t/db_dependent/Reserves/HoldRulesChecker.t | 110 + > 4 files changed, 1641 insertions(+), 1197 deletions(-) > create mode 100644 t/db_dependent/Reserves/HoldRulesChecker.t > >diff --git a/C4/Reserves.pm b/C4/Reserves.pm >index 432ae461dc..bd4747751c 100644 >--- a/C4/Reserves.pm >+++ b/C4/Reserves.pm >@@ -373,19 +373,23 @@ sub CanBookBeReserved { > return { status => 'alreadypossession' }; > } > >+ my @circulation_rules; >+ > if ( $params->{itemtype} ) { > > # biblio-level, item type-contrained >- my $patron = Koha::Patrons->find($borrowernumber); >- my $reservesallowed = Koha::CirculationRules->get_effective_rule( >+ my $patron = Koha::Patrons->find($borrowernumber); >+ my $reservesallowed_rule = Koha::CirculationRules->get_effective_rule( > { > itemtype => $params->{itemtype}, > categorycode => $patron->categorycode, > branchcode => $pickup_branchcode, > rule_name => 'reservesallowed', > } >- )->rule_value; >+ ); >+ push @circulation_rules, $reservesallowed_rule if $reservesallowed_rule; > >+ my $reservesallowed = $reservesallowed_rule ? $reservesallowed_rule->rule_value : undef; > $reservesallowed = ( $reservesallowed eq '' ) ? undef : $reservesallowed; > > my $count = $patron->holds->search( >@@ -398,7 +402,7 @@ sub CanBookBeReserved { > { join => ['item'] } > )->count; > >- return { status => '' } >+ return { status => '', circulation_rules => \@circulation_rules } > if defined $reservesallowed and $reservesallowed < $count + 1; > } > >@@ -419,36 +423,100 @@ sub CanBookBeReserved { > $items = Koha::Items->search( { biblionumber => $biblionumber } ); > } > >- my $canReserve = { status => '' }; >- my $patron = Koha::Patrons->find($borrowernumber); >+ my $response = { status => '', item_responses => [] }; >+ my $patron = Koha::Patrons->find($borrowernumber); > while ( my $item = $items->next ) { >- $canReserve = CanItemBeReserved( $patron, $item, $pickup_branchcode, $params ); >- return { status => 'OK' } if $canReserve->{status} eq 'OK'; >+ my $itemResponse = CanItemBeReserved( $patron, $item, $pickup_branchcode, $params ); >+ push @{ $response->{item_responses} }, { %$itemResponse, item => $item }; >+ >+ if ( $itemResponse->{status} eq 'OK' ) { >+ $response->{status} = 'OK'; >+ >+ return $response; >+ } > } >- return $canReserve; >+ >+ return $response; > } > > =head2 CanItemBeReserved > >- $canReserve = &CanItemBeReserved($patron, $item, $branchcode, $params) >+ $canReserve = CanItemBeReserved($patron, $item, $branchcode, $params) > if ($canReserve->{status} eq 'OK') { #We can reserve this Item! } > >- current params are: >- 'ignore_hold_counts' - we use this routine to check if an item can fill a hold - on this case we >- should not check if there are too many holds as we only care about reservability >- >-@RETURNS { status => OK }, if the Item can be reserved. >- { status => ageRestricted }, if the Item is age restricted for this borrower. >- { status => damaged }, if the Item is damaged. >- { status => cannotReserveFromOtherBranches }, if syspref 'canreservefromotherbranches' is OK. >- { status => branchNotInHoldGroup }, if borrower home library is not in hold group, and holds are only allowed from hold groups. >- { status => tooManyReserves, limit => $limit }, if the borrower has exceeded their maximum reserve amount. >- { status => notReservable }, if holds on this item are not allowed >- { status => libraryNotFound }, if given branchcode is not an existing library >- { status => libraryNotPickupLocation }, if given branchcode is not configured to be a pickup location >- { status => cannotBeTransferred }, if branch transfer limit applies on given item and branchcode >- { status => pickupNotInHoldGroup }, pickup location is not in hold group, and pickup locations are only allowed from hold groups. >- { status => recall }, if the borrower has already placed a recall on this item >+Current params are: >+ >+=over >+ >+=item * C<ignore_hold_counts> >+ >+we use this routine to check if an item can >+fill a hold - on this case we should not check if there are too many holds as >+we only care about reservability >+ >+=back >+ >+Returns a hashref with the following keys: >+ >+=over >+ >+=item * C<status> >+ >+A string that can have the following values: >+ >+=over >+ >+=item * C<OK> if the item can be reserved >+ >+=item * C<ageRestricted> if the item is aged restricted for this borrower >+ >+=item * C<damaged> if the item is damaged >+ >+=item * C<cannotReserveFromOtherBranches> if syspref >+'canreservefromotherbranches' is OK >+ >+=item * C<branchNotInHoldGroup> if borrower home library is not in hold group, >+and holds are only allowed from hold groups. >+ >+=item * C<tooManyReserves> if the borrower has exceeded their maximum reserve >+amount. >+ >+=item * C<tooManyHoldsForThisRecord> if the borrower has exceeded their maximum >+reserve amount for this biblio record >+ >+=item * C<tooManyReservesToday> if the borrower has exceeded their maximum >+reserve amount for today >+ >+=item * C<notReservable> if holds on this item are not allowed >+ >+=item * C<libraryNotFound> if given branchcode is not an existing library >+ >+=item * C<libraryNotPickupLocation> if given branchcode is not configured to be >+a pickup location >+ >+=item * C<cannotBeTransferred> if branch transfer limit applies on given item >+and branchcode >+ >+=item * C<pickupNotInHoldGroup> if pickup location is not in hold group, and >+pickup locations are only allowed from hold groups. >+ >+=item * C<recall> if the borrower has already placed a recall on this item >+ >+=back >+ >+=item * C<limit> >+ >+Only if C<status> is equal to C<tooManyReserves>, C<tooManyHoldsForThisRecord>, >+or C<tooManyReservesToday>. >+ >+It contains the number of reserves allowed. >+ >+=item * C<circulation_rules> >+ >+An arrayref containing all circulations rules (L<Koha::CirculationRule>) that >+have been checked >+ >+=back > > =cut > >@@ -473,8 +541,6 @@ sub CanItemBeReserved { > } > > my $dbh = C4::Context->dbh; >- my $ruleitemtype; # itemtype of the matching issuing rule >- my $allowedreserves = 0; # Total number of holds allowed across all records, default to none > > # We check item branch if IndependentBranches is ON > # and canreservefromotherbranches is OFF >@@ -530,38 +596,23 @@ sub CanItemBeReserved { > $reserves_control_branch = $patron->branchcode; > } > >- # we retrieve rights >- if ( >- my $reservesallowed = Koha::CirculationRules->get_effective_rule( >- { >- itemtype => $item->effective_itemtype, >- categorycode => $patron->categorycode, >- branchcode => $reserves_control_branch, >- rule_name => 'reservesallowed', >- } >- ) >- ) >- { >- $ruleitemtype = $reservesallowed->itemtype; >- $allowedreserves = $reservesallowed->rule_value // 0; #undefined is 0, blank is unlimited >- } else { >- $ruleitemtype = undef; >- } >+ my @circulation_rules; > >- my $rights = Koha::CirculationRules->get_effective_rules( >+ my $holds_per_record_rule = Koha::CirculationRules->get_effective_rule( > { > categorycode => $patron->categorycode, > itemtype => $item->effective_itemtype, > branchcode => $reserves_control_branch, >- rules => [ 'holds_per_record', 'holds_per_day' ] >+ rule_name => 'holds_per_record', > } > ); >- my $holds_per_record = $rights->{holds_per_record} // 1; >- my $holds_per_day = $rights->{holds_per_day}; >+ push @circulation_rules, $holds_per_record_rule if $holds_per_record_rule; >+ >+ my $holds_per_record = $holds_per_record_rule ? $holds_per_record_rule->rule_value : 1; > > if ( defined $holds_per_record && $holds_per_record ne '' ) { > if ( $holds_per_record == 0 ) { >- return _cache { status => "noReservesAllowed" }; >+ return _cache { status => "noReservesAllowed", circulation_rules => \@circulation_rules }; > } > if ( !$params->{ignore_hold_counts} ) { > my $search_params = { >@@ -569,11 +620,28 @@ sub CanItemBeReserved { > biblionumber => $item->biblionumber, > }; > my $holds = Koha::Holds->search($search_params); >- return _cache { status => "tooManyHoldsForThisRecord", limit => $holds_per_record } >- if $holds->count() >= $holds_per_record; >+ >+ if ( $holds->count() >= $holds_per_record ) { >+ return _cache { >+ status => "tooManyHoldsForThisRecord", >+ limit => $holds_per_record, >+ circulation_rules => \@circulation_rules, >+ }; >+ } > } > } > >+ my $holds_per_day_rule = Koha::CirculationRules->get_effective_rule( >+ { >+ categorycode => $patron->categorycode, >+ itemtype => $item->effective_itemtype, >+ branchcode => $reserves_control_branch, >+ rule_name => 'holds_per_day', >+ } >+ ); >+ push @circulation_rules, $holds_per_day_rule if $holds_per_day_rule; >+ >+ my $holds_per_day = $holds_per_day_rule ? $holds_per_day_rule->rule_value : undef; > if ( !$params->{ignore_hold_counts} && defined $holds_per_day && $holds_per_day ne '' ) { > my $today_holds = Koha::Holds->search( > { >@@ -581,15 +649,42 @@ sub CanItemBeReserved { > reservedate => dt_from_string->date > } > ); >- return _cache { status => 'tooManyReservesToday', limit => $holds_per_day } >- if $today_holds->count() >= $holds_per_day; >+ >+ if ( $today_holds->count() >= $holds_per_day ) { >+ return _cache { >+ status => 'tooManyReservesToday', >+ limit => $holds_per_day, >+ circulation_rules => \@circulation_rules, >+ }; >+ } >+ } >+ >+ my $reservesallowed_rule = Koha::CirculationRules->get_effective_rule( >+ { >+ itemtype => $item->effective_itemtype, >+ categorycode => $patron->categorycode, >+ branchcode => $reserves_control_branch, >+ rule_name => 'reservesallowed', >+ } >+ ); >+ push @circulation_rules, $reservesallowed_rule if $reservesallowed_rule; >+ >+ my $ruleitemtype; # itemtype of the matching issuing rule >+ my $allowedreserves = 0; # Total number of holds allowed across all records, default to none >+ if ($reservesallowed_rule) { >+ $ruleitemtype = $reservesallowed_rule->itemtype; >+ $allowedreserves = $reservesallowed_rule->rule_value // 0; #undefined is 0, blank is unlimited > } > > # we check if it's ok or not > if ( defined $allowedreserves && $allowedreserves ne '' ) { > if ( $allowedreserves == 0 ) { >- return _cache { status => 'noReservesAllowed' }; >+ return _cache { >+ status => 'noReservesAllowed', >+ circulation_rules => \@circulation_rules, >+ }; > } >+ > if ( !$params->{ignore_hold_counts} ) { > > # we retrieve count >@@ -632,36 +727,61 @@ sub CanItemBeReserved { > $reservecount = $rowcount->{count}; > } > >- return _cache { status => 'tooManyReserves', limit => $allowedreserves } >- if $reservecount >= $allowedreserves; >+ if ( $reservecount >= $allowedreserves ) { >+ return _cache { >+ status => 'tooManyReserves', >+ limit => $allowedreserves, >+ circulation_rules => \@circulation_rules, >+ }; >+ } > } > } > > # Now we need to check hold limits by patron category >- my $rule = Koha::CirculationRules->get_effective_rule( >+ my $max_holds_rule = Koha::CirculationRules->get_effective_rule( > { > categorycode => $patron->categorycode, > branchcode => $reserves_control_branch, > rule_name => 'max_holds', > } > ); >- if ( !$params->{ignore_hold_counts} && $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) { >+ push @circulation_rules, $max_holds_rule if $max_holds_rule; >+ >+ if ( !$params->{ignore_hold_counts} >+ && $max_holds_rule >+ && defined( $max_holds_rule->rule_value ) >+ && $max_holds_rule->rule_value ne '' ) >+ { > my $total_holds_count = Koha::Holds->search( { borrowernumber => $patron->borrowernumber } )->count(); > >- return _cache { status => 'tooManyReserves', limit => $rule->rule_value } >- if $total_holds_count >= $rule->rule_value; >+ if ( $total_holds_count >= $max_holds_rule->rule_value ) { >+ return _cache { >+ status => 'tooManyReserves', >+ limit => $max_holds_rule->rule_value, >+ circulation_rules => \@circulation_rules, >+ }; >+ } > } > >+ my $holdallowed_rule = Koha::CirculationRules->get_effective_rule( >+ { >+ branchcode => $reserves_control_branch, >+ itemtype => $item->effective_itemtype, >+ rule_name => 'holdallowed', >+ } >+ ); >+ push @circulation_rules, $holdallowed_rule if $holdallowed_rule; >+ > my $branchitemrule = C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->effective_itemtype ); > > if ( $branchitemrule->{holdallowed} eq 'not_allowed' ) { >- return _cache { status => 'notReservable' }; >+ return _cache { status => 'notReservable', circulation_rules => \@circulation_rules }; > } > > if ( $branchitemrule->{holdallowed} eq 'from_home_library' > && $patron->branchcode ne $item->homebranch ) > { >- return _cache { status => 'cannotReserveFromOtherBranches' }; >+ return _cache { status => 'cannotReserveFromOtherBranches', circulation_rules => \@circulation_rules }; > } > > my $item_library = Koha::Libraries->find( { branchcode => $item->homebranch } ); >@@ -669,7 +789,7 @@ sub CanItemBeReserved { > if ( $patron->branchcode ne $item->homebranch > && !$item_library->validate_hold_sibling( { branchcode => $patron->branchcode } ) ) > { >- return _cache { status => 'branchNotInHoldGroup' }; >+ return _cache { status => 'branchNotInHoldGroup', circulation_rules => \@circulation_rules }; > } > } > >@@ -689,20 +809,30 @@ sub CanItemBeReserved { > unless ( $item->can_be_transferred( { to => $destination } ) ) { > return _cache { status => 'cannotBeTransferred' }; > } >+ >+ my $hold_fulfillment_policy_rule = Koha::CirculationRules->get_effective_rule( >+ { >+ branchcode => $reserves_control_branch, >+ itemtype => $item->effective_itemtype, >+ rule_name => 'hold_fulfillment_policy', >+ } >+ ); >+ push @circulation_rules, $hold_fulfillment_policy_rule if $hold_fulfillment_policy_rule; >+ > if ( $branchitemrule->{hold_fulfillment_policy} eq 'holdgroup' > && !$item_library->validate_hold_sibling( { branchcode => $pickup_branchcode } ) ) > { >- return _cache { status => 'pickupNotInHoldGroup' }; >+ return _cache { status => 'pickupNotInHoldGroup', circulation_rules => \@circulation_rules }; > } > if ( $branchitemrule->{hold_fulfillment_policy} eq 'patrongroup' > && !Koha::Libraries->find( { branchcode => $patron->branchcode } ) > ->validate_hold_sibling( { branchcode => $pickup_branchcode } ) ) > { >- return _cache { status => 'pickupNotInHoldGroup' }; >+ return _cache { status => 'pickupNotInHoldGroup', circulation_rules => \@circulation_rules }; > } > } > >- return _cache { status => 'OK' }; >+ return _cache { status => 'OK', circulation_rules => \@circulation_rules }; > } > > =head2 ChargeReserveFee >@@ -1831,9 +1961,8 @@ sub _koha_notify_reserve { > } > ); > >- my $library = Koha::Libraries->find( $hold->branchcode ); >- my $from_email_address = $library->from_email_address; >- my $reply_email_address = $library->inbound_email_address; >+ my $library = Koha::Libraries->find( $hold->branchcode ); >+ my $from_email_address = $library->from_email_address; > > my %letter_params = ( > module => 'reserves', >@@ -1869,7 +1998,6 @@ sub _koha_notify_reserve { > letter => $letter, > borrowernumber => $borrowernumber, > from_address => $from_email_address, >- reply_address => $reply_email_address, > message_transport_type => $mtt, > } > ); >@@ -2128,8 +2256,6 @@ sub RevertWaitingStatus { > } > )->next; > >- my $original = C4::Context->preference('HoldsLog') ? $hold->unblessed : undef; >- > ## Increment the priority of all other non-waiting > ## reserves for this bib record > my $holds = Koha::Holds->search( { biblionumber => $hold->biblionumber, priority => { '>' => 0 } } ) >@@ -2146,7 +2272,7 @@ sub RevertWaitingStatus { > } > )->store( { hold_reverted => 1 } ); > >- logaction( 'HOLDS', 'MODIFY', $hold->id, $hold, undef, $original ) >+ logaction( 'HOLDS', 'MODIFY', $hold->id, $hold ) > if C4::Context->preference('HoldsLog'); > > _FixPriority( { biblionumber => $hold->biblionumber } ); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >index 558b5e0d9f..74e07c438d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >@@ -22,26 +22,23 @@ > [% SET categories = Categories.all.unblessed %] > [% SET columns = ['name', 'cardnumber', 'dateofbirth', 'category', 'branch', 'address', 'phone'] %] > [% PROCESS "patron-search.inc" %] >-<title >- >[% FILTER collapse %] >- [% UNLESS ( multi_hold ) %] >- [% title_in_title = INCLUDE 'biblio-title-head.inc' %] >- [% tx("Place a hold on {title}", { title = title_in_title }) | html %] >- › >- [% ELSE %] >- [% t("Confirm holds") | html %] >- › >- [% END %] >- [% t("Holds") | html %] >- › [% t("Circulation") | html %] › [% t("Koha") | html %] >- [% END %]</title >-> >+<title>[% FILTER collapse %] >+ [% UNLESS ( multi_hold ) %] >+ [% title_in_title = INCLUDE 'biblio-title-head.inc' %] >+ [% tx("Place a hold on {title}", { title = title_in_title }) | html %] › >+ [% ELSE %] >+ [% t("Confirm holds") | html %] › >+ [% END %] >+ [% t("Holds") | html %] › >+ [% t("Circulation") | html %] › >+ [% t("Koha") | html %] >+[% END %]</title> > [% INCLUDE 'doc-head-close.inc' %] > [% FILTER collapse %] > <style> > a.hold-arrow { >- display: inline-block; >- padding: 3px; >+ display:inline-block; >+ padding:3px; > } > a.hold-arrow:link, > a.hold-arrow:visited { >@@ -49,7 +46,7 @@ > } > > a.hold-arrow:hover, >- a.hold-arrow:active { >+ a.hold-arrow:active{ > color: #75b700; > } > >@@ -59,14 +56,14 @@ > } > > a.cancel-hold { >- display: inline-block; >- padding: 3px; >+ display:inline-block; >+ padding:3px; > } > > a.cancel-hold:link, >- a.cancel-hold:visited { >- color: #c00; >- font-size: 130%; >+ a.cancel-hold:visited{ >+ color:#c00; >+ font-size:130% > } > > .icon-move-hold-up::before { >@@ -102,8 +99,8 @@ > .icon-set-lowest::before { > content: "\f04e"; > } >- :disabled { >- opacity: 0.5; >+ :disabled{ >+ opacity:0.5 > } > </style> > [% END %] >@@ -147,36 +144,43 @@ > [% END #/ WRAPPER breadcrumbs %] > [% END #/ WRAPPER sub-header.inc %] > >-[%# No sidebar menu when placing multiple holds or biblio not found %] >-[% SET aside = (multi_hold || nobiblio) ? '' : 'biblio-view-menu' %] >-[% WRAPPER 'main-container.inc' aside=aside wide_centered=1 %] >- <h1>Holds</h1> >+<div class="main container-fluid"> >+ <div class="row"> >+ [% IF ( multi_hold || nobiblio ) # No sidebar menu when placing multiple holds or biblio not found %] >+ <div class="col-md-10 offset-md-1"> >+ [% ELSE %] >+ <div class="col-md-10 order-md-2 order-sm-1"> >+ [% END %] > >- [% IF ( nobiblio ) %] >- <div class="alert alert-warning"> >- [% IF (multi_hold) %] >- <strong>Cannot place hold:</strong> one or more records don't exist. >- [% ELSE %] >- <strong>Cannot place hold:</strong> this record doesn't exist. >+ <main> >+ [% INCLUDE 'messages.inc' %] >+ <h1>Holds</h1> >+ >+ [% IF ( nobiblio ) %] >+ <div class="alert alert-warning"> >+ [%IF (multi_hold) %] >+ <strong>Cannot place hold:</strong> one or more records don't exist. >+ [% ELSE %] >+ <strong>Cannot place hold:</strong> this record doesn't exist. >+ [% END %] >+ </div> > [% END %] >- </div> >- [% END %] >- [% IF ( noitems ) %] >- <div class="alert alert-warning"> >- [% IF (multi_hold) %] >- <strong>Cannot place hold:</strong> one or more records without items attached. >- [% ELSE %] >- <strong>Cannot place hold:</strong> this record has no items attached. >+ [% IF ( noitems ) %] >+ <div class="alert alert-warning"> >+ [%IF (multi_hold) %] >+ <strong>Cannot place hold:</strong> one or more records without items attached. >+ [% ELSE %] >+ <strong>Cannot place hold:</strong> this record has no items attached. >+ [% END %] >+ </div> > [% END %] >- </div> >- [% END %] > >- [% IF ( failed_holds ) %] >- <div class="alert alert-warning"> >- <strong>One or more holds were not placed due to following errors:</strong> >- <ul> >- [% FOREACH fail IN failed_holds %] >- <li> >+ [% IF ( failed_holds ) %] >+ <div class="alert alert-warning"> >+ <strong>One or more holds were not placed due to following errors:</strong> >+ <ul> >+ [% FOREACH fail IN failed_holds %] >+ <li> > [% SWITCH fail %] > [% CASE 'damaged' %] > <span>Item is damaged</span> >@@ -215,436 +219,372 @@ > [% CASE %] > <span>Error: [% fail | html %]</span> > [% END %] >- </li> >- [% END %] >- </ul> >- </div> >- [% END %] >+ </li> >+ [% END %] >+ </ul> >+ </div> >+ [% END %] > >- [% UNLESS ( multi_hold ) %] >- <h2>Place a hold on [% INCLUDE 'biblio-title.inc' link = 1 %] [% IF biblio.author %]by [% biblio.author | html %][% END %]</h2> >- [% ELSE %] >- <h2> >- [% IF ( patron ) %] >- <span>Place holds</span> >+ [% UNLESS ( multi_hold ) %] >+ <h2>Place a hold on [% INCLUDE 'biblio-title.inc' link = 1 %] [% IF biblio.author %] by [% biblio.author | html %][% END %]</h2> > [% ELSE %] >- [% IF clubcount %] >- <span>Search patrons or clubs</span> >- [% ELSE %] >- <span>Search patrons</span> >- [% END %] >+ <h2> >+ [% IF ( patron ) %] >+ <span>Place holds</span> >+ [% ELSE %] >+ [% IF clubcount %] >+ <span>Search patrons or clubs</span> >+ [% ELSE %] >+ <span>Search patrons</span> >+ [% END %] >+ [% END %] >+ </h2> > [% END %] >- </h2> >- [% END %] > >- [% UNLESS club OR patron OR patron.borrowernumber OR noitems OR nobiblio %] >- [% IF ( messageborrower ) %] >- <div class="alert alert-warning"> >- <h3>Patron not found</h3> >- <p>No patron with this name, please, try another</p> >- </div> >- [% END %] >+ [% IF canbookbereserved_responses %] >+ <button type="button" class="btn btn-sm" data-toggle="modal" data-target="#holdruleschecker">[% t('Show circulation rules') | html %]</button> >+ [% END %] > >- [% IF ( messageclub ) %] >- <div class="alert alert-warning"> >- <h3>Club not found</h3> >- <p>No club with this name, please, try another</p> >- </div> >- [% END %] >- <fieldset> >- [% UNLESS multi_hold %] >- [% IF clubcount %] >- <h2>Search patrons or clubs</h2> >- [% ELSE %] >- <h2>Search patrons</h2> >+ [% UNLESS club OR patron OR patron.borrowernumber OR noitems OR nobiblio %] >+ [% IF ( messageborrower ) %] >+ <div class="alert alert-warning"> >+ <h3>Patron not found</h3> >+ <p>No patron with this name, please, try another</p> >+ </div> > [% END %] >- [% END %] > >- [% WRAPPER tabs id= "circ_holds_select" %] >- [% WRAPPER tabs_nav %] >- [% WRAPPER tab_item tabname= "holds_patronsearch_pane" bt_active= 1 %]<span>Patrons</span>[% END %] >- [% IF clubcount %] >- [% WRAPPER tab_item tabname= "holds_clubsearch_pane" %]<span>Clubs</span>[% END %] >- [% END %] >- [% END # /WRAPPER tabs_nav %] >- >- [% WRAPPER tab_panels %] >- [% WRAPPER tab_panel tabname="holds_patronsearch_pane" bt_active= 1 %] >- [% PROCESS patron_search_filters_simple %] >- >- [% PROCESS patron_search_table table_id => 'table_borrowers', open_on_row_click => 1 %] >- [% END # /tab_panel# %] >- [% IF clubcount %] >- [% WRAPPER tab_panel tabname="holds_clubsearch_pane" %] >- <form id="holds_clubsearch" action="request.pl" method="get"> >- <div class="hint">Enter club ID or partial name:</div> >- <input type="text" size="40" id="club" class="focus" name="findclub" autocomplete="off" /> >- <input type="hidden" name="form_submitted" value="1" /> >- <input type="submit" class="btn btn-primary" value="Search" /> >- [% FOREACH biblionumber IN biblionumbers %] >- <input type="hidden" name="biblionumber" value="[% biblionumber | html %]" /> >- [% END %] >- </form> >- <!-- /#holds_patronsearch --> >- [% IF clubs %] >- [% INCLUDE 'clubs-table.inc' destination = "holds" %] >- [% END %] >- [% END # /tab_panel# %] >- [% END # /IF clubcount %] >- [% END # /WRAPPER tab_panels %] >- [% END # /WRAPPER tabs %] >- </fieldset> >- [% ELSIF club %] >- <div class="alert alert-warning visually-hidden clubalert"> </div> >- <fieldset class="rows"> >- <legend>Hold details</legend> >- <form action="/api/v1/clubs/[% club.id | html %]/holds" method="post" name="form" id="club-request-form"> >- [% INCLUDE 'csrf-token.inc' %] >- <input type="hidden" name="op" value="cud-noop" /> >- >- [% IF ( multi_hold ) %] >- <input type="hidden" name="request" value="any" /> >- [% FOREACH biblioloo IN biblioloop %] >- [% UNLESS biblioloo.none_avail %] >- <input type="hidden" name="holdable_bibs" id="holdable_bibs" value="[% biblioloo.biblionumber | html %]" /> >- <input type="hidden" name="title_[% biblioloo.biblionumber | html %]" value="[% biblioloo.title | html %]" /> >- <input type="hidden" name="rank_[% biblioloo.biblionumber | html %]" value="[% biblioloo.rank | html %]" /> >+ [% IF ( messageclub ) %] >+ <div class="alert alert-warning"> >+ <h3>Club not found</h3> >+ <p>No club with this name, please, try another</p> >+ </div> >+ [% END %] >+ <fieldset> >+ [% UNLESS multi_hold %] >+ [% IF clubcount %] >+ <h2>Search patrons or clubs</h2> >+ [% ELSE %] >+ <h2>Search patrons</h2> > [% END %] > [% END %] >- [% ELSE %] >- <input type="hidden" name="holdable_bibs" id="holdable_bibs" value="[% biblio.biblionumber | html %]" /> >- <input type="hidden" name="title" value="[% biblio.title | html %]" /> >- <input type="hidden" name="rank-request" value="[% fixedRank | html %]" /> >- [% END # /IF multi_hold %] >- <ol> >- <li> <span class="label">Club: </span> [% club.name | html %] </li> >- <li> <span class="label">Description: </span> [% club.description | html %] </li> >- <li> >- <label for="pickup">Pickup at:</label> >- <select name="pickup" id="pickup_club"> >- [% PROCESS options_for_libraries libraries => Branches.all({ selected => club.branchcode, search_params => { pickup_location => 1 } }) %] >- </select> >- </li> >- <li> >- <label for="default_patron_home">Pickup at patron's home library when possible:</label> >- <input type="checkbox" id="default_patron_home" name="default_patron_home" /> >- </li> >- </ol> >- <h2 style="padding: 0 1em;">Members</h2> >- <ol> >- [% FOREACH member IN members %] >- [% SET patron = member.patron %] >- <li style="padding: 0.5em 1em;"> >- <div>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %]</div> >- [% IF member.exceeded_maxreserves %] >- <div> >- <i class="fa fa-error"></i> >- <strong>Too many holds: </strong> Patron can only place a maximum of [% maxreserves | html %] total holds. >- </div> >- [% END %] >- [% IF ( patron.is_expired ) %] >- <div> >- <i class="fa-solid fa-triangle-exclamation"></i> >- <strong>Account has expired</strong> >- </div> >- [% END %] >- [% IF patron.is_debarred %] >- <div> >- <i class="fa-solid fa-triangle-exclamation"></i> >- <strong>Patron has restrictions</strong> >- </div> >- [% END %] >- [% IF member.amount_outstanding && Koha.Preference('maxoutstanding') && member.amount_outstanding > Koha.Preference('maxoutstanding') %] >- <div> >- <i class="fa-solid fa-triangle-exclamation"></i> >- <strong>Patron has outstanding fines: [% member.amount_outstanding | $Price %]</strong> >- </div> >- [% END %] > >- [% IF ( member.diffbranch ) %] >- <div> >- <i class="fa-solid fa-triangle-exclamation"></i> >- <strong>Pickup library is different.</strong> Patron's home library: ([% Branches.GetName(patron.branchcode) | html %] / [% patron.branchcode | html %] ) >- </div> >+ [% WRAPPER tabs id= "circ_holds_select" %] >+ [% WRAPPER tabs_nav %] >+ [% WRAPPER tab_item tabname= "holds_patronsearch_pane" bt_active= 1 %] <span>Patrons</span> [% END %] >+ [% IF clubcount %] >+ [% WRAPPER tab_item tabname= "holds_clubsearch_pane" %] <span>Clubs</span> [% END %] > [% END %] >- </li> >- [% END %] >- </ol> >- [% UNLESS ( multi_hold ) %] >- <fieldset class="action"> >- <input type="submit" class="btn btn-primary" value="Place hold" /> >- </fieldset> >- [% ELSE %] >- <table id="requesttitles"> >- <tr> >- <th> </th> >- <th>Title</th> >- [% UNLESS Koha.Preference('item-level_itypes') %] >- <th>Item type</th> >- [% END %] >- <th>Priority</th> >- <th>Information</th> >- </tr> >- [% FOREACH biblioloo IN biblioloop %] >- <tr [% IF biblioloo.warn %]class="onissue"[% END %]> >- <td> >- [% UNLESS ( biblioloo.warn ) %] >- <input class="multi_hold_item_checkbox" type="checkbox" checked="checked" title="[% biblioloo.biblionumber | html %]" /> >- [% END %] >- </td> >- <td> >- <ul> >- <li> >- <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]">[% biblioloo.title | html %]</a> >- [% IF biblioloo.author %]by [% biblioloo.author | html %][% END %] >- </li> >- [% IF ( biblioloo.publicationyear ) %] >- <li> <span class="label">Publication year:</span> [% biblioloo.publicationyear | html %] </li> >+ [% END # /WRAPPER tabs_nav %] >+ >+ [% WRAPPER tab_panels %] >+ [% WRAPPER tab_panel tabname="holds_patronsearch_pane" bt_active= 1 %] >+ [% PROCESS patron_search_filters_simple %] >+ >+ [% PROCESS patron_search_table table_id => 'table_borrowers', open_on_row_click => 1 %] >+ [% END # /tab_panel# %] >+ [% IF clubcount %] >+ [% WRAPPER tab_panel tabname="holds_clubsearch_pane" %] >+ <form id="holds_clubsearch" action="request.pl" method="get"> >+ <div class="hint">Enter club ID or partial name:</div> >+ <input type="text" size="40" id="club" class="focus" name="findclub" autocomplete="off" /> >+ <input type="submit" class="btn btn-primary" value="Search" /> >+ [% FOREACH biblionumber IN biblionumbers %] >+ <input type="hidden" name="biblionumber" value="[% biblionumber | html %]"/> > [% END %] >- </ul> >- [% IF ( biblioloo.warn ) %] >- <span class="not_holdable" title="[% biblioloo.biblionumber | html %]"></span> >+ >+ </form> <!-- /#holds_patronsearch --> >+ [% IF clubs %] >+ [% INCLUDE 'clubs-table.inc' destination = "holds" %] > [% END %] >- </td> >- [% UNLESS Koha.Preference('item-level_itypes') %] >- <td> >- <img >- class="itemtype-image" >- src="[% biblioloo.itemtype.image_location| html %]" >- alt="[% biblioloo.itemtype.translated_description | html %]" >- title="[% biblioloo.itemtype.translated_description | html %]" >- /> >- </td> >+ [% END # /tab_panel# %] >+ [% END # /IF clubcount %] >+ [% END # /WRAPPER tab_panels %] >+ [% END # /WRAPPER tabs %] >+ </fieldset> >+ [% ELSIF club %] >+ <div class="alert alert-warning visually-hidden clubalert"> >+ </div> >+ <fieldset class="rows"> >+ <legend>Hold details</legend> >+ <form action="/api/v1/clubs/[% club.id | html %]/holds" method="post" name="form" id="club-request-form"> >+ [% INCLUDE 'csrf-token.inc' %] >+ <input type="hidden" name="op" value="cud-noop" /> >+ >+ [% IF ( multi_hold ) %] >+ <input type="hidden" name="request" value="any"/> >+ [% FOREACH biblioloo IN biblioloop %] >+ [% UNLESS biblioloo.none_avail %] >+ <input type="hidden" name="holdable_bibs" id="holdable_bibs" value="[% biblioloo.biblionumber | html %]"/> >+ <input type="hidden" name="title_[% biblioloo.biblionumber | html %]" value="[% biblioloo.title | html %]"/> >+ <input type="hidden" name="rank_[% biblioloo.biblionumber | html %]" value="[% biblioloo.rank | html %]"/> > [% END %] >- <td>[% biblioloo.rank | html %]</td> >- <td> >- [% IF ( biblioloo.checked_previously ) %] >- <span>Patron has previously checked out this title</span><br /> >+ [% END %] >+ [% ELSE %] >+ <input type="hidden" name="holdable_bibs" id="holdable_bibs" value="[% biblio.biblionumber | html %]"/> >+ <input type="hidden" name="title" value="[% biblio.title | html %]" /> >+ <input type="hidden" name="rank-request" value="[% fixedRank | html %]" /> >+ [% END # /IF multi_hold %] >+ <ol> >+ <li> >+ <span class="label">Club: </span> [% club.name | html %] >+ </li> >+ <li> >+ <span class="label">Description: </span> [% club.description | html %] >+ </li> >+ <li> >+ <label for="pickup">Pickup at:</label> >+ <select name="pickup" id="pickup_club"> >+ [% PROCESS options_for_libraries libraries => Branches.all({ selected => club.branchcode, search_params => { pickup_location => 1 } }) %] >+ </select> >+ </li> >+ <li> >+ <label for="default_patron_home">Pickup at patron's home library when possible:</label> >+ <input type="checkbox" id="default_patron_home" name="default_patron_home"/> >+ </li> >+ </ol> >+ <h2 style="padding: 0 1em;">Members</h2> >+ <ol> >+ [% FOREACH member IN members %] >+ [% SET patron = member.patron %] >+ <li style="padding: 0.5em 1em;"> >+ <div>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %]</div> >+ [% IF member.exceeded_maxreserves %] >+ <div> >+ <i class="fa fa-error"></i> >+ <strong>Too many holds: </strong> Patron can only place a maximum of [% maxreserves | html %] total holds. >+ </div> > [% END %] >- [% IF ( biblioloo.alreadyres ) %] >- <ul> >- <li> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] <strong>already has a hold</strong> on this item </li> >- </ul> >+ [% IF ( patron.is_expired ) %] >+ <div> >+ <i class="fa-solid fa-triangle-exclamation"></i> >+ <strong>Account has expired</strong> >+ </div> > [% END %] >- [% IF ( biblioloo.none_avail || biblioloo.noitems ) %] >- <ul >- ><li> <strong>No items are available</strong> to be placed on hold</li></ul >- > >+ [% IF patron.is_debarred %] >+ <div> >+ <i class="fa-solid fa-triangle-exclamation"></i> >+ <strong>Patron has restrictions</strong> >+ </div> >+ [% END %] >+ [% IF member.amount_outstanding && Koha.Preference('maxoutstanding') && member.amount_outstanding > Koha.Preference('maxoutstanding') %] >+ <div> >+ <i class="fa-solid fa-triangle-exclamation"></i> >+ <strong>Patron has outstanding fines: [% member.amount_outstanding | $Price %]</strong> >+ </div> > [% END %] >- </td> >- </tr> >- [% END # /FOREACH biblioloo %] >- </table> >- <!-- /#requesttitles --> >- [% END %] >- </form> >- </fieldset> >- [% ELSIF NOT ( noitems || nobiblio ) # /UNLESS patron %] >- >- [% IF ( checked_previously && !multi_hold ) %] >- <div class="alert alert-warning"> >- <ul> >- <li>Patron has previously checked out this title</li> >- </ul> >- </div> >- [% END %] > >- [% IF ( no_reserves_allowed || exceeded_maxreserves || exceeded_holds_per_record || alreadyreserved || none_available || alreadypossession || ageRestricted || recall ) %] >- <div class="alert alert-warning"> >- [% UNLESS ( multi_hold ) %] >- <h3>Cannot place hold</h3> >- <ul> >- [% IF ( no_reserves_allowed ) %] >- <li><strong>No holds allowed:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] cannot place a hold on any of these items.</li> >- [% ELSIF ( exceeded_maxreserves ) %] >- <li >- ><strong>Too many holds:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] can only place a maximum of [% maxreserves | html %] total >- holds.</li >- > >- [% ELSIF ( exceeded_holds_per_record ) %] >- <li >- ><strong>Too many holds for this record:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] can only place a maximum of >- [% max_holds_for_record | html %] hold(s) on this record.</li >- > >- [% ELSIF ( alreadypossession ) %] >- <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 hide_patron_infos_if_needed => 1 %] <strong>is already in possession</strong> of one item.</li> >- [% ELSIF ( alreadyreserved ) %] >- <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] <strong>already has a hold</strong> on this item.</li> >- [% ELSIF ( ageRestricted ) %] >- <li><strong>Age restricted</strong></li> >- [% ELSIF ( none_available ) %] >- <li> <strong>No items are available</strong> to be placed on hold.</li> >- [% ELSIF ( maxreserves ) %] >- <li >- ><strong>Too many holds:</strong> >- [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] has too many holds.</li >- > >- [% ELSIF ( recall ) %] >- <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] has <strong>already placed a recall</strong> on this item.</li> >- [% END # /IF exceeded_maxreserves %] >- </ul> >- [% ELSE # UNLESS multi_hold %] >- <h3>Cannot place hold on some items</h3> >- [% IF (no_reserves_allowed ) %] >- <li><strong>No holds allowed:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] cannot place holds on some of these title's items.</li> >- [% ELSIF ( exceeded_maxreserves ) %] >- <li >- ><strong>Too many holds:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] can place [% new_reserves_allowed | html %] of the requested >- [% new_reserves_count | html %] holds for a maximum of [% maxreserves | html %] total holds.</li >- > >- [% ELSIF ( exceeded_holds_per_record ) %] >- [% FOREACH biblioloo IN biblioloop %] >- [% IF (biblioloo.tooManyHoldsForThisRecord) %] >- <li >- ><strong>Too many holds for <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]"> [% biblioloo.title | html %]</a>:</strong> >- [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] can only place a maximum of [% max_holds_for_record | html %] hold(s) on this >- record.</li >- > >+ [% IF ( member.diffbranch ) %] >+ <div> >+ <i class="fa-solid fa-triangle-exclamation"></i> >+ <strong>Pickup library is different.</strong> Patron's home library: ([% Branches.GetName(patron.branchcode) | html %] / [% patron.branchcode | html %] ) >+ </div> >+ [% END %] >+ </li> > [% END %] >- [% END %] >- [% ELSIF ( none_available ) %] >- <li><strong>No items available: </strong>One or more records have no items that can be held</li> >- [% END # /IF exceeded_maxreserves %] >- [% END # /UNLESS multi_hold %] >- </div> >- [% END # /IF ( exceeded_maxreserves || ... %] >+ [% UNLESS ( multi_hold ) %] >+ <fieldset class="action"> >+ <input type="submit" class="btn btn-primary" value="Place hold" /> >+ </fieldset> >+ [% ELSE %] >+ <table id="requesttitles"> >+ <tr> >+ <th> </th> >+ <th>Title</th> >+ [% UNLESS Koha.Preference('item-level_itypes') %] >+ <th>Item type</th> >+ [% END %] >+ <th>Priority</th> >+ <th>Information</th> >+ </tr> >+ [% FOREACH biblioloo IN biblioloop %] >+ [% IF ( biblioloo.warn ) %] >+ <tr class="onissue"> >+ [% ELSE %] >+ <tr> >+ [% END %] >+ <td> >+ [% UNLESS ( biblioloo.warn ) %] >+ <input class="multi_hold_item_checkbox" type="checkbox" checked="checked" title="[% biblioloo.biblionumber | html %]"/> >+ </td> >+ [% END %] >+ <td> >+ <ul> >+ <li> >+ <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]">[% biblioloo.title | html %]</a> >+ [% IF biblioloo.author %] by [% biblioloo.author | html %][% END %] >+ </li> >+ [% IF ( biblioloo.publicationyear ) %] >+ <li> >+ <span class="label">Publication year:</span> [% biblioloo.publicationyear | html %] >+ </li> >+ [% END %] >+ </ul> >+ [% IF ( biblioloo.warn ) %] >+ <span class="not_holdable" title="[% biblioloo.biblionumber | html %]"></span> >+ [% END %] >+ </td> >+ [% UNLESS Koha.Preference('item-level_itypes') %] >+ <td> >+ <img class="itemtype-image" src="[% biblioloo.itemtype.image_location| html %]" alt="[% biblioloo.itemtype.translated_description | html %]" title="[% biblioloo.itemtype.translated_description | html %]" /> >+ </td> >+ [% END %] >+ <td>[% biblioloo.rank | html %]</td> >+ <td> >+ [% IF ( biblioloo.checked_previously ) %] >+ <span>Patron has previously checked out this title</span><br/> >+ [% END %] >+ [% IF ( biblioloo.alreadyres ) %] >+ <ul> >+ [% ELSE %] >+ [% IF ( biblioloo.none_avail || biblioloo.noitems ) %] >+ <ul> >+ [% END %] >+ [% END %] > >- [% IF ( patron.is_expired || diffbranch || patron.is_debarred || ( amount_outstanding && Koha.Preference('maxoutstanding') && amount_outstanding > Koha.Preference('maxoutstanding') ) ) %] >- <div class="alert alert-info"> >- <ul> >- [% IF ( patron.is_expired ) %] >- <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %]: <strong>Account has expired</strong></li> >- [% END %] >+ [% IF ( biblioloo.alreadyres ) %] >+ <li> >+ [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] <strong>already has a hold</strong> on this item >+ </li> >+ [% END %] >+ [% IF ( biblioloo.none_avail || biblioloo.noitems ) %] >+ <li> <strong>No items are available</strong> to be placed on hold</li> >+ [% END %] > >- [% IF patron.is_debarred %] >- <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %]: <strong>Patron has restrictions</strong></li> >- [% END %] >+ [% IF ( biblioloo.alreadyres ) %] >+ </ul> >+ [% ELSE %] >+ [% IF ( biblioloo.none_avail || biblioloo.noitems ) %] >+ </ul> >+ [% END %] >+ [% END %] >+ </td> >+ </tr> >+ [% END # /FOREACH biblioloo %] >+ </table> <!-- /#requesttitles --> >+ [% END %] >+ </form> >+ </fieldset> >+ [% ELSIF NOT ( noitems || nobiblio ) # /UNLESS patron %] > >- [% IF amount_outstanding && Koha.Preference('maxoutstanding') && amount_outstanding > Koha.Preference('maxoutstanding') %] >- <li >- >[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 link_to => 'members_pay' %]: >- <strong>Patron has outstanding fines: [% amount_outstanding | $Price %]</strong></li >- > >- [% END %] >+ [% IF ( checked_previously && !multi_hold ) %] >+ <div class="alert alert-warning"> >+ <ul> >+ <li>Patron has previously checked out this title</li> >+ </ul> >+ </div> >+ [% END %] > >- [% IF ( diffbranch ) %] >- <li >- ><strong>Pickup library is different. </strong>Patron: [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] Patron's home library: >- ([% Branches.GetName(patron.branchcode) | html %] / [% patron.branchcode | html %] )</li >- > >- [% END %] >- </ul> >- <!-- /.dialog.message --> >- </div> >- [% END # /IF patron.is_expired || diffbranch ... %] >+ [% IF ( no_reserves_allowed || exceeded_maxreserves || exceeded_holds_per_record || alreadyreserved || none_available || alreadypossession || ageRestricted || recall ) %] >+ <div class="alert alert-warning"> >+ >+ [% UNLESS ( multi_hold ) %] >+ <h3>Cannot place hold</h3> >+ <ul> >+ [% IF ( no_reserves_allowed ) %] >+ <li><strong>No holds allowed:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] cannot place a hold on any of these items.</li> >+ [% ELSIF ( exceeded_maxreserves ) %] >+ <li><strong>Too many holds:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] can only place a maximum of [% maxreserves | html %] total holds.</li> >+ [% ELSIF ( exceeded_holds_per_record ) %] >+ <li><strong>Too many holds for this record:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] can only place a maximum of [% max_holds_for_record | html %] hold(s) on this record.</li> >+ [% ELSIF ( alreadypossession ) %] >+ <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 hide_patron_infos_if_needed => 1 %] <strong>is already in possession</strong> of one item.</li> >+ [% ELSIF ( alreadyreserved ) %] >+ <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] <strong>already has a hold</strong> on this item.</li> >+ [% ELSIF ( ageRestricted ) %] >+ <li><strong>Age restricted</strong></li> >+ [% ELSIF ( none_available ) %] >+ <li> <strong>No items are available</strong> to be placed on hold.</li> >+ [% ELSIF ( maxreserves ) %] >+ <li><strong>Too many holds:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] has too many holds.</li> >+ [% ELSIF ( recall ) %] >+ <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] has <strong>already placed a recall</strong> on this item.</li> >+ [% END # /IF exceeded_maxreserves %] >+ </ul> >+ [% ELSE # UNLESS multi_hold %] >+ <h3>Cannot place hold on some items</h3> >+ [% IF (no_reserves_allowed ) %] >+ <li><strong>No holds allowed:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] cannot place holds on some of these title's items.</li> >+ [% ELSIF ( exceeded_maxreserves ) %] >+ <li><strong>Too many holds:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] can place [% new_reserves_allowed | html %] of the requested [% new_reserves_count | html %] holds for a maximum of [% maxreserves | html %] total holds.</li> >+ [% ELSIF ( exceeded_holds_per_record ) %] >+ [% FOREACH biblioloo IN biblioloop %] >+ [% IF (biblioloo.tooManyHoldsForThisRecord) %] >+ <li><strong>Too many holds for <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]"> [% biblioloo.title | html %]</a>:</strong> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] can only place a maximum of [% max_holds_for_record | html %] hold(s) on this record.</li> >+ [% END %] >+ [% END %] >+ [% ELSIF ( none_available ) %] >+ <li><strong>No items available: </strong>One or more records have no items that can be held</li> >+ [% END # /IF exceeded_maxreserves %] >+ [% END # /UNLESS multi_hold %] > >- [% IF ( messageborrower ) %] >- <div class="alert alert-warning"> >- <h3>Patron not found:</h3> >- <p>Name or barcode not found. Please try an other </p> >- </div> >- [% END %] >+ </div> >+ [% END # /IF ( exceeded_maxreserves || ... %] > >- <div class="alert alert-warning visually-hidden holdalert"> </div> >+ [% IF ( patron.is_expired || diffbranch || patron.is_debarred || ( amount_outstanding && Koha.Preference('maxoutstanding') && amount_outstanding > Koha.Preference('maxoutstanding') ) ) %] >+ <div class="alert alert-info"> >+ <ul> >+ [% IF ( patron.is_expired ) %] >+ <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %]: <strong>Account has expired</strong></li> >+ [% END %] > >- [% UNLESS ( multi_hold ) %] >- <form action="placerequest.pl" method="post" name="form" id="hold-request-form"> >- [% INCLUDE 'csrf-token.inc' %] >- <input type="hidden" name="op" value="cud-placerequest" /> >- <fieldset class="rows"> >- <legend>Hold details</legend> >+ [% IF patron.is_debarred %] >+ <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %]: <strong>Patron has restrictions</strong></li> >+ [% END %] > >- <input type="hidden" name="borrowernumber" value="[% patron.borrowernumber | html %]" /> >- [% FOREACH biblionumber IN biblionumbers %] >- <input type="hidden" name="biblionumber" value="[% biblionumber | html %]" /> >- [% END %] >- <input type="hidden" name="holdable_bibs" id="holdable_bibs" value="[% biblio.biblionumber | html %]" /> >- <input type="hidden" name="title" value="[% biblio.title | html %]" /> >- <input type="hidden" name="rank-request" value="[% fixedRank | html %]" /> >+ [% IF amount_outstanding && Koha.Preference('maxoutstanding') && amount_outstanding > Koha.Preference('maxoutstanding') %] >+ <li>[% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 link_to => 'members_pay' %]: <strong>Patron has outstanding fines: [% amount_outstanding | $Price %]</strong></li> >+ [% END %] > >- <ol> >- <li> >- <span class="label">Patron:</span> >- [% IF ( patron.borrowernumber ) %] >- [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 hide_patron_infos_if_needed => 1 %] >- [% ELSE %] >- Not defined yet >+ [% IF ( diffbranch ) %] >+ <li><strong>Pickup library is different. </strong>Patron: [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] Patron's home library: ([% Branches.GetName(patron.branchcode) | html %] / [% patron.branchcode | html %] )</li> > [% END %] >- </li> >+ </ul> <!-- /.dialog.message --> >+ </div> >+ [% END # /IF patron.is_expired || diffbranch ... %] > >- <li> >- <span class="label">Estimated priority:</span> >- <strong>[% fixedRank | html %]</strong> >- </li> >+ [% IF ( messageborrower ) %] >+ <div class="alert alert-warning"> >+ <h3>Patron not found:</h3> >+ <p>Name or barcode not found. Please try an other </p> >+ </div> >+ [% END %] > >- <li> >- <label for="holdnotes">Notes:</label> >- <textarea id="holdnotes" name="notes" cols="30" rows="1"></textarea> >- </li> >+ <div class="alert alert-warning visually-hidden holdalert"> >+ </div> > >- [% IF Koha.Preference('AllowHoldItemTypeSelection') %] >- <li> >- <label for="itemtype">Request specific item type:</label> >- <select name="itemtype" id="itemtype"> >- <option value="">Any item type</option> >- [%- FOREACH itemtype IN available_itemtypes %] >- <option value="[% itemtype | html %]">[% ItemTypes.GetDescription( itemtype ) | html %]</option> >- [%- END %] >- </select> >- </li> >- [% END %] >+ [% UNLESS ( multi_hold ) %] >+ <form action="placerequest.pl" method="post" name="form" id="hold-request-form"> >+ [% INCLUDE 'csrf-token.inc' %] >+ <input type="hidden" name="op" value="cud-placerequest" /> >+ <fieldset class="rows"> >+ <legend>Hold details</legend> >+ >+ <input type="hidden" name="borrowernumber" value="[% patron.borrowernumber | html %]" /> >+ [% FOREACH biblionumber IN biblionumbers %] >+ <input type="hidden" name="biblionumber" value="[% biblionumber | html %]"/> >+ [% END %] >+ <input type="hidden" name="holdable_bibs" id="holdable_bibs" value="[% biblio.biblionumber | html %]"/> >+ <input type="hidden" name="title" value="[% biblio.title | html %]" /> >+ <input type="hidden" name="rank-request" value="[% fixedRank | html %]" /> > >- [% IF ( Koha.Preference('AllowHoldDateInFuture') ) %] >- <li> >- <label for="from">Hold starts on date:</label> >- <input id="reserve_date" name="reserve_date" id="from" size="10" type="text" data-date_to="expiration_date" class="flatpickr" data-flatpickr-futureinclusive="true" /> >- </li> >- [% END %] >+ <ol> >+ <li> >+ <span class="label">Patron:</span> >+ [% IF ( patron.borrowernumber ) %] >+ [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 hide_patron_infos_if_needed => 1 %] >+ [% ELSE %] >+ Not defined yet >+ [% END %] >+ </li> > >- <li> >- <label for="to">Hold expires on date:</label> >- <input id="expiration_date" name="expiration_date" id="to" size="10" type="text" class="flatpickr" data-flatpickr-futuredate="true" /> >- </li> >+ <li> >+ <span class="label">Estimated priority:</span> >+ <strong>[% fixedRank | html %]</strong> >+ </li> > >- <li id="non_priority_list_item"> >- <label for="non_priority">Non priority hold:</label> >- <input name="non_priority" id="non_priority" type="checkbox" /> >- <span class="hint">A non priority hold doesn't prevent a current checkout from renewing</span> >- </li> >- </ol> >- </fieldset> >- <fieldset class="rows any_specific"> >- <legend> >- [% IF force_hold_level == 'item' || force_hold_level == 'item_group' %] >- <input type="radio" id="requestany" name="request" disabled="true" /> >- [% ELSIF force_hold_level == 'record' %] >- <input type="radio" id="requestany" checked="checked" value="Any" disabled="true" /> >- <input type="hidden" name="request" value="Any" /> >- <span class="error"><i>(Required)</i></span> >- [% ELSE %] >- <input type="radio" id="requestany" name="request" checked="checked" value="Any" /> >- [% END %] >- <label for="requestany" class="inline"> Hold next available item </label> >- </legend> >- <input type="hidden" name="alreadyreserved" value="[% alreadyreserved | html %]" /> >- <fieldset class="enable_request_any disable_request_group disable_request_specific"> >- [% IF force_hold_level == 'item' # Patron has placed a item level hold previously for this record %] >- <span class="error"> >- <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >- Hold must be item level >- </span> >- [% ELSIF force_hold_level == 'item_group' # Patron has placed an item group level hold previously for this record %] >- <span class="error"> >- <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >- Hold must be item group level >- </span> >- [% ELSE %] >- <ol> > <li> >- <label for="pickup">Pickup at:</label> >- <select name="pickup" id="pickup-next-avail" data-biblio-id="[% biblio.biblionumber | html %]" data-patron-id="[% patron.borrowernumber | html %]" data-pickup-location-source="biblio"> >- [% PROCESS options_for_libraries libraries => Branches.pickup_locations({ search_params => { biblio => biblionumber, patron => patron }, selected => pickup }) %] >- </select> >+ <label for="holdnotes">Notes:</label> >+ <textarea id="holdnotes" name="notes" cols="30" rows="1"></textarea> > </li> > > [% IF Koha.Preference('AllowHoldItemTypeSelection') %] >@@ -658,50 +598,124 @@ > </select> > </li> > [% END %] >- [% UNLESS remaining_holds_for_record == 1 %] >- <li> >- <label for="holds_to_place_count">Holds to place (count)</label> >- <input type="text" inputmode="numeric" pattern="[0-9]*" id="holds_to_place_count" name="holds_to_place_count" value="1" /> >- </li> >- [% ELSE %] >- <input type="hidden" name="holds_to_place_count" value="1" /> >- [% END %] >- </ol> >- [% END %] > >- <fieldset class="action"> >- [% IF ( patron.borrowernumber ) %] >- [% IF ( override_required ) %] >- <button type="submit" id="hold_grp_btn" class="btn btn-primary warning"><i class="fa fa-exclamation-triangle "></i> Place hold</button> >- [% ELSIF ( none_available ) %] >- <button type="submit" id="hold_grp_btn" disabled="disabled" class="btn btn-primary btn-disabled">Place hold</button> >+ [% IF ( Koha.Preference('AllowHoldDateInFuture') ) %] >+ <li> >+ <label for="from">Hold starts on date:</label> >+ <input id="reserve_date" name="reserve_date" id="from" size="10" type="text" data-date_to="expiration_date" class="flatpickr" data-flatpickr-futureinclusive="true" /> >+ </li> >+ [% END %] >+ >+ <li> >+ <label for="to">Hold expires on date:</label> >+ <input id="expiration_date" name="expiration_date" id="to" size="10" type="text" class="flatpickr" data-flatpickr-futuredate="true" /> >+ </li> >+ >+ <li id="non_priority_list_item"> >+ <label for="non_priority">Non priority hold:</label> >+ <input name="non_priority" id="non_priority" type="checkbox" /> >+ <span class="hint">A non priority hold doesn't prevent a current checkout from renewing</span> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="rows any_specific"> >+ <legend> >+ [% IF force_hold_level == 'item' || force_hold_level == 'item_group' %] >+ <input type="radio" id="requestany" name="request" disabled="true" /> >+ [% ELSIF force_hold_level == 'record' %] >+ <input type="radio" id="requestany" checked="checked" value="Any" disabled="true"/> >+ <input type="hidden" name="request" value="Any"/> >+ <span class="error"><i>(Required)</i></span> >+ [% ELSE %] >+ <input type="radio" id="requestany" name="request" checked="checked" value="Any" /> >+ [% END %] >+ <label for="requestany" class="inline"> >+ Hold next available item >+ </label> >+ </legend> >+ <input type="hidden" name="alreadyreserved" value="[% alreadyreserved | html %]" /> >+ <fieldset class="enable_request_any disable_request_group disable_request_specific"> >+ [% IF force_hold_level == 'item' # Patron has placed a item level hold previously for this record %] >+ <span class="error"> >+ <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >+ Hold must be item level >+ </span> >+ [% ELSIF force_hold_level == 'item_group' # Patron has placed an item group level hold previously for this record %] >+ <span class="error"> >+ <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >+ Hold must be item group level >+ </span> > [% ELSE %] >- <button type="submit" id="hold_grp_btn" class="btn btn-primary">Place hold</button> >+ <ol> >+ >+ <li> >+ <label for="pickup">Pickup at:</label> >+ <select name="pickup" id="pickup-next-avail" >+ data-biblio-id="[% biblio.biblionumber | html %]" >+ data-patron-id="[% patron.borrowernumber | html %]" >+ data-pickup-location-source="biblio"> >+ [% PROCESS options_for_libraries libraries => Branches.pickup_locations({ search_params => { biblio => biblionumber, patron => patron }, selected => pickup }) %] >+ </select> >+ </li> >+ >+ [% IF Koha.Preference('AllowHoldItemTypeSelection') %] >+ <li> >+ <label for="itemtype">Request specific item type:</label> >+ <select name="itemtype" id="itemtype"> >+ <option value="">Any item type</option> >+ [%- FOREACH itemtype IN available_itemtypes %] >+ <option value="[% itemtype | html %]">[% ItemTypes.GetDescription( itemtype ) | html %]</option> >+ [%- END %] >+ </select> >+ </li> >+ [% END %] >+ [% UNLESS remaining_holds_for_record == 1 %] >+ <li> >+ <label for="holds_to_place_count">Holds to place (count)</label> >+ <input type="text" inputmode="numeric" pattern="[0-9]*" id="holds_to_place_count" name="holds_to_place_count" value="1" /> >+ </li> >+ [% ELSE %] >+ <input type="hidden" name="holds_to_place_count" value="1" /> >+ [% END %] >+ </ol> > [% END %] >- [% END %] >+ >+ >+ <fieldset class="action"> >+ [% IF ( patron.borrowernumber ) %] >+ [% IF ( override_required ) %] >+ <button type="submit" id="hold_grp_btn" class="btn btn-primary warning"><i class="fa fa-exclamation-triangle "></i> Place hold</button> >+ [% ELSIF ( none_available ) %] >+ <button type="submit" id="hold_grp_btn" disabled="disabled" class="btn btn-primary btn-disabled">Place hold</button> >+ [% ELSE %] >+ <button type="submit" id="hold_grp_btn" class="btn btn-primary">Place hold</button> >+ [% END %] >+ [% END %] >+ </fieldset> >+ </fieldset> > </fieldset> >- </fieldset> >- </fieldset> > >- <hr /> >- >- [% biblio_info = biblioloop.0 %] >- <!-- ItemGroup level holds --> >- [% IF Koha.Preference('EnableItemGroupHolds') && biblio_info.object.item_groups.count %] >- <fieldset class="rows any_specific"> >- <legend> >- [% IF force_hold_level == 'item_group' %] >- <input type="radio" class="requestgrp" id="requestgrp" name="request" checked="checked" disabled="true" /> >- <span class="error"><i>(Required)</i></span> >- [% ELSIF force_hold_level == 'item' || force_hold_level == 'record' %] >- <input type="radio" class="requestgrp" id="requestgrp" name="request" disabled="true" /> >- [% ELSE %] >- <input type="radio" class="requestgrp" id="requestgrp" name="request" /> >- [% END %] >- <label for="requestgrp" class="inline"> Hold next available item from an item group </label> >- </legend> >+ <hr/> >+ >+ [% biblio_info = biblioloop.0 %] >+ <!-- ItemGroup level holds --> >+ [% IF Koha.Preference('EnableItemGroupHolds') && biblio_info.object.item_groups.count %] >+ <fieldset class="rows any_specific"> >+ <legend> >+ [% IF force_hold_level == 'item_group' %] >+ <input type="radio" class="requestgrp" id="requestgrp" name="request" checked="checked" disabled="true" /> >+ <span class="error"><i>(Required)</i></span> >+ [% ELSIF force_hold_level == 'item' || force_hold_level == 'record' %] >+ <input type="radio" class="requestgrp" id="requestgrp" name="request" disabled="true" /> >+ [% ELSE %] >+ <input type="radio" class="requestgrp" id="requestgrp" name="request" /> >+ [% END %] >+ <label for="requestgrp" class="inline"> >+ Hold next available item from an item group >+ </label> >+ </legend> > >- <fieldset class="enable_request_group disable_request_any disable_request_specific"> >+ <fieldset class="enable_request_group disable_request_any disable_request_specific"> > [% IF force_hold_level == 'record' # Patron has placed a record level hold previously for this record %] > <span class="error"> > <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >@@ -716,7 +730,10 @@ > <ul> > <li> > <label for="pickup">Pickup at:</label> >- <select name="pickup" id="pickup-item-group" data-biblio-id="[% biblio.biblionumber | html %]" data-patron-id="[% patron.borrowernumber | html %]" data-pickup-location-source="biblio"> >+ <select name="pickup" id="pickup-item-group" >+ data-biblio-id="[% biblio.biblionumber | html %]" >+ data-patron-id="[% patron.borrowernumber | html %]" >+ data-pickup-location-source="biblio"> > [% PROCESS options_for_libraries libraries => Branches.pickup_locations({ search_params => { biblio => biblionumber, patron => patron }, selected => pickup }) %] > </select> > </li> >@@ -764,673 +781,720 @@ > </li> > </ul> > [% END %] >- <fieldset class="action"> >- [% IF ( patron.borrowernumber ) %] >- [% IF ( override_required ) %] >- <button type="submit" id="hold_any_btn" class="btn btn-primary warning"><i class="fa fa-exclamation-triangle "></i> Place hold</button> >- [% ELSIF ( none_available ) %] >- <button type="submit" id="hold_any_btn" disabled="disabled" class="btn btn-primary btn-disabled">Place hold</button> >- [% ELSE %] >- <button type="submit" id="hold_any_btn" class="btn btn-primary">Place hold</button> >+ <fieldset class="action"> >+ [% IF ( patron.borrowernumber ) %] >+ [% IF ( override_required ) %] >+ <button type="submit" id="hold_any_btn" class="btn btn-primary warning"><i class="fa fa-exclamation-triangle "></i> Place hold</button> >+ [% ELSIF ( none_available ) %] >+ <button type="submit" id="hold_any_btn" disabled="disabled" class="btn btn-primary btn-disabled">Place hold</button> >+ [% ELSE %] >+ <button type="submit" id="hold_any_btn" class="btn btn-primary">Place hold</button> >+ [% END %] > [% END %] >- [% END %] >+ </fieldset> > </fieldset> > </fieldset> >- </fieldset> >- [% END %] >- <!-- /ItemGroup level holds --> >- >- <fieldset class="rows any_specific"> >- <legend> >- [% IF force_hold_level == 'item' %] >- <input type="radio" id="requestspecificitem" name="request" class="requestspecific" checked="checked" disabled="disabled" /> >- <span class="error"><em>(Required)</em></span> >- [% ELSIF force_hold_level == 'record' || force_hold_level == 'item_group' %] >- <input type="radio" id="requestspecificitem" name="request" class="requestspecific" disabled="disabled" /> >- [% ELSE %] >- <input type="radio" id="requestspecificitem" name="request" class="requestspecific" /> > [% END %] >- <label for="requestspecificitem" class="inline"> Hold a specific item </label> >- </legend> >+ <!-- /ItemGroup level holds --> >+ >+ <fieldset class="rows any_specific"> >+ <legend> >+ [% IF force_hold_level == 'item' %] >+ <input type="radio" id="requestspecificitem" name="request" class="requestspecific" checked="checked" disabled='disabled'/> >+ <span class="error"><em>(Required)</em></span> >+ [% ELSIF force_hold_level == 'record' || force_hold_level == 'item_group' %] >+ <input type="radio" id="requestspecificitem" name="request" class="requestspecific" disabled='disabled'/> >+ [% ELSE %] >+ <input type="radio" id="requestspecificitem" name="request" class="requestspecific"/> >+ [% END %] >+ <label for="requestspecificitem" class="inline"> >+ Hold a specific item >+ </label> >+ </legend> >+ >+ <fieldset class="enable_request_specific disable_request_any disable_request_group"> >+ <ol> >+ [% UNLESS Koha.Preference('item-level_itypes') %] >+ <li> >+ <span class="label">Item type:</span> >+ [% biblio_info.itemtype.translated_description | html %] >+ </li> >+ [% END %] > >- <fieldset class="enable_request_specific disable_request_any disable_request_group"> >- <ol> >- [% UNLESS Koha.Preference('item-level_itypes') %] >- <li> >- <span class="label">Item type:</span> >- [% biblio_info.itemtype.translated_description | html %] >- </li> >- [% END %] >+ [% IF ( biblio_info.biblioitem.publicationyear ) %] >+ <li> >+ <span class="label">Publication year:</span> >+ [% biblio_info.biblioitem.publicationyear | html %] >+ </li> >+ [% END %] >+ </ol> > >- [% IF ( biblio_info.biblioitem.publicationyear ) %] >- <li> >- <span class="label">Publication year:</span> >- [% biblio_info.biblioitem.publicationyear | html %] >- </li> >- [% END %] >- </ol> >+ <table id="requestspecific"> >+ <thead> >+ <tr> >+ <th>Hold</th> >+ <th>Allowed pickup locations</th> >+ [% IF Koha.Preference('item-level_itypes') %] >+ <th>Item type</th> >+ [% END %] >+ <th>Barcode</th> >+ [% IF Koha.Preference('EnableItemGroupHolds') && biblio_info.object.item_groups.count %] >+ <th>Item group</th> >+ [% END %] >+ <th>Home library</th> >+ <th>Last location</th> >+ [% IF itemdata_ccode %] >+ <th>Collection</th> >+ [% END %] >+ <th>Call number</th> >+ <th>Copy number</th> >+ [% IF itemdata_enumchron %] >+ <th>Vol no.</th> >+ [% END %] >+ <th>Information</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% SET selected = 0 %] >+ [% FOREACH itemloo IN biblio_info.itemloop %] >+ [% UNLESS ( itemloo.hide ) %] >+ <tr class="[% itemloo.backgroundcolor | html %]"> >+ <td> >+ [% IF force_hold_level == 'record' # Patron has placed a record level hold previously for this record %] >+ <span class="error"> >+ <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >+ Hold must be record level >+ </span> >+ [% ELSIF force_hold_level == 'item_group' %] >+ <span class="error"> >+ <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >+ Hold must be item group level >+ </span> >+ [% ELSIF ( itemloo.available ) %] >+ <input type="[% reserve_input_type | html %]" name="checkitem" class="requestspecific" value="[% itemloo.itemnumber | html %]" /> >+ [% ELSIF ( itemloo.override ) %] >+ <input type="[% reserve_input_type | html %]" name="checkitem" class="needsoverride requestspecific" value="[% itemloo.itemnumber | html %]" /> >+ <i class="fa fa-exclamation-triangle fa-lg" style="color:gold" title="Requires override of hold policy"/></i> >+ [% ELSE %] >+ <span class="error"> >+ <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >+ [% IF itemloo.not_holdable %] >+ [% IF itemloo.not_holdable == 'damaged' %] >+ <span>Item damaged</span> >+ [% ELSIF itemloo.not_holdable == 'ageRestricted' %] >+ <span>Age restricted</span> >+ [% ELSIF itemloo.not_holdable == 'tooManyHoldsForThisRecord' %] >+ <span>Exceeded max holds per record</span> >+ [% ELSIF itemloo.not_holdable == 'tooManyReservesToday' %] >+ <span>Daily hold limit reached for patron</span> >+ [% ELSIF itemloo.not_holdable == 'tooManyReserves' %] >+ <span>Too many holds</span> >+ [% ELSIF itemloo.not_holdable == 'notReservable' %] >+ <span>Not holdable</span> >+ [% ELSIF itemloo.not_holdable == 'cannotReserveFromOtherBranches' %] >+ <span>Patron is from different library</span> >+ [% ELSIF itemloo.not_holdable == 'branchNotInHoldGroup' %] >+ <span>Cannot place hold from patron's library</span> >+ [% ELSIF itemloo.not_holdable == 'itemAlreadyOnHold' %] >+ <span>Patron already has hold for this item</span> >+ [% ELSIF itemloo.not_holdable == 'cannotBeTransferred' %] >+ <span>Cannot be transferred to pickup library</span> >+ [% ELSIF itemloo.not_holdable == 'pickupNotInHoldGroup' %] >+ <span>Only pickup locations within the same hold group are allowed</span> >+ [% ELSIF itemloo.not_holdable == 'noReservesAllowed' %] >+ <span>No holds are allowed on this item</span> >+ [% ELSIF itemloo.not_holdable == 'libraryNotPickupLocation' %] >+ <span>Library is not a pickup location</span> >+ [% ELSIF itemloo.not_holdable == 'no_valid_pickup_location' %] >+ <span>No valid pickup location</span> >+ [% ELSIF itemloo.not_holdable == 'notforloan' %] >+ <span>Not for loan</span> >+ [% ELSE %] >+ <span>[% itemloo.not_holdable | html %]</span> >+ [% END %] >+ [% END %] >+ </span> >+ [% END # /IF force_hold_level %] >+ </td> >+ <td> >+ [% IF (itemloo.pickup_locations_count > 0) || Koha.Preference('AllowHoldPolicyOverride') %] >+ <select name="item_pickup_[% itemloo.itemnumber | html %]" class="pickup_locations requestspecific" style="width:100%;" >+ data-item-id="[% itemloo.itemnumber | html %]" >+ data-patron-id="[% patron.borrowernumber | html %]" >+ data-pickup-location-source="item"> >+ [% IF (itemloo.default_pickup_location) %] >+ <option value="[% itemloo.default_pickup_location.branchcode | html %]" selected="selected">[% itemloo.default_pickup_location.branchname | html %]</option> >+ [% END %] >+ </select> >+ [% END %] >+ </td> >+ [% IF Koha.Preference('item-level_itypes') %] >+ <td> >+ [% UNLESS ( noItemTypeImages ) %] >+ [% IF ( itemloo.itemtype.image_location) %]<img class="itemtype-image" src="[% itemloo.itemtype.image_location | html %]" alt="" /> <br /> [% END %] >+ [% END %] >+ <span class="itypetext">[% itemloo.itemtype.translated_description | html %]</span> >+ </td> >+ [% END %] >+ <td> >+ [% itemloo.barcode | html %] >+ </td> >+ [% IF Koha.Preference('EnableItemGroupHolds') && biblio_info.object.item_groups.count %] >+ <td> >+ [% itemloo.object.item_group.description | html %] >+ </td> >+ [% END %] >+ <td> >+ [% Branches.GetName( itemloo.homebranch ) | html %] >+ </td> >+ <td> >+ [% Branches.GetName( itemloo.holdingbranch ) | html %] >+ </td> >+ [% IF itemdata_ccode %] >+ <td> >+ [% IF ( itemloo.ccode ) %][% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => itemloo.ccode ) | html %][% END %] >+ </td> >+ [% END %] >+ <td> >+ [% itemloo.itemcallnumber | html %] >+ </td> >+ <td> >+ [% IF ( itemloo.copynumber ) %][% itemloo.copynumber | html %][% ELSE %] [% END %] >+ </td> >+ [% IF itemdata_enumchron %] >+ <td> >+ [% itemloo.enumchron | html %] >+ </td> >+ [% END %] >+ [% IF ( itemloo.onloan ) %] >+ <td data-order="[% itemloo.date_due | html %]"> >+ <span class="checkedout">Due [% itemloo.date_due | $KohaDates as_due_date => 1 %]</span> >+ [% ELSE %] >+ <td> >+ [% IF ( itemloo.transfertwhen ) %] >+ <span>In transit from [% Branches.GetName( itemloo.transfertfrom ) | html %], >+ to [% Branches.GetName( itemloo.transfertto ) | html %], since [% itemloo.transfertwhen | $KohaDates %]</span> >+ [% END %] >+ [% END %] > >- <table id="requestspecific"> >- <thead> >- <tr> >- <th>Hold</th> >- <th>Allowed pickup locations</th> >- [% IF Koha.Preference('item-level_itypes') %] >- <th>Item type</th> >- [% END %] >- <th>Barcode</th> >- [% IF Koha.Preference('EnableItemGroupHolds') && biblio_info.object.item_groups.count %] >- <th>Item group</th> >- [% END %] >- <th>Home library</th> >- <th>Last location</th> >- [% IF itemdata_ccode %] >- <th>Collection</th> >- [% END %] >- <th>Call number</th> >- <th>Copy number</th> >- [% IF itemdata_enumchron %] >- <th>Vol no.</th> >- [% END %] >- <th>Information</th> >- </tr> >- </thead> >- <tbody> >- [% SET selected = 0 %] >- [% FOREACH itemloo IN biblio_info.itemloop %] >- [% UNLESS ( itemloo.hide ) %] >- <tr class="[% itemloo.backgroundcolor | html %]"> >- <td> >- [% IF force_hold_level == 'record' # Patron has placed a record level hold previously for this record %] >- <span class="error"> >- <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >- Hold must be record level >- </span> >- [% ELSIF force_hold_level == 'item_group' %] >- <span class="error"> >- <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >- Hold must be item group level >- </span> >- [% ELSIF ( itemloo.available ) %] >- <input type="[% reserve_input_type | html %]" name="checkitem" class="requestspecific" value="[% itemloo.itemnumber | html %]" /> >- [% ELSIF ( itemloo.override ) %] >- <input type="[% reserve_input_type | html %]" name="checkitem" class="needsoverride requestspecific" value="[% itemloo.itemnumber | html %]" /> >- <i class="fa fa-exclamation-triangle fa-lg" style="color:gold" title="Requires override of hold policy"></i> >- [% ELSE %] >- <span class="error"> >- <i class="fa fa-times fa-lg" title="Cannot be put on hold"></i> >- [% IF itemloo.not_holdable %] >- [% IF itemloo.not_holdable == 'damaged' %] >- <span>Item damaged</span> >- [% ELSIF itemloo.not_holdable == 'ageRestricted' %] >- <span>Age restricted</span> >- [% ELSIF itemloo.not_holdable == 'tooManyHoldsForThisRecord' %] >- <span>Exceeded max holds per record</span> >- [% ELSIF itemloo.not_holdable == 'tooManyReservesToday' %] >- <span>Daily hold limit reached for patron</span> >- [% ELSIF itemloo.not_holdable == 'tooManyReserves' %] >- <span>Too many holds</span> >- [% ELSIF itemloo.not_holdable == 'notReservable' %] >- <span>Not holdable</span> >- [% ELSIF itemloo.not_holdable == 'cannotReserveFromOtherBranches' %] >- <span>Patron is from different library</span> >- [% ELSIF itemloo.not_holdable == 'branchNotInHoldGroup' %] >- <span>Cannot place hold from patron's library</span> >- [% ELSIF itemloo.not_holdable == 'itemAlreadyOnHold' %] >- <span>Patron already has hold for this item</span> >- [% ELSIF itemloo.not_holdable == 'cannotBeTransferred' %] >- <span>Cannot be transferred to pickup library</span> >- [% ELSIF itemloo.not_holdable == 'pickupNotInHoldGroup' %] >- <span>Only pickup locations within the same hold group are allowed</span> >- [% ELSIF itemloo.not_holdable == 'noReservesAllowed' %] >- <span>No holds are allowed on this item</span> >- [% ELSIF itemloo.not_holdable == 'libraryNotPickupLocation' %] >- <span>Library is not a pickup location</span> >- [% ELSIF itemloo.not_holdable == 'no_valid_pickup_location' %] >- <span>No valid pickup location</span> >- [% ELSIF itemloo.not_holdable == 'notforloan' %] >- <span>Not for loan</span> >+ [% IF ( itemloo.reservedate ) %] >+ [% IF ( itemloo.nocancel ) %] >+ <span>Can't be cancelled when item is in transit</span> > [% ELSE %] >- <span>[% itemloo.not_holdable | html %]</span> >- [% END %] >+ [% IF ( itemloo.waitingdate ) %] >+ [% IF ( itemloo.canreservefromotherbranches ) %] >+ <span>Waiting for [% INCLUDE 'patron-title.inc' patron=itemloo.ReservedFor %] at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %] since [% itemloo.waitingdate | $KohaDates %]</span> >+ [% ELSE %] >+ <span>Waiting at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %] since [% itemloo.waitingdate | $KohaDates %]</span> >+ [% END %] >+ [% ELSE %] >+ [% IF ( itemloo.canreservefromotherbranches ) %] >+ [% IF itemloo.reservedate %] >+ <span>On hold for [% INCLUDE 'patron-title.inc' patron=itemloo.ReservedFor %] expected at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %] since</span> >+ [% ELSE %] >+ <span>On hold expected at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %]</span> >+ [% END %] >+ [% ELSIF itemloo.reservedate %] >+ <span>On hold expected at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %] since [% itemloo.reservedate | $KohaDates %]</span> >+ [% ELSE %] >+ <span>On hold expected at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %]</span> >+ [% END %] >+ [% END %] >+ [% END # /IF itemloo.nocancel %] >+ [% ELSE %] >+ Not on hold >+ [% END # /IF itemloo.reservedate %] >+ >+ [% IF itemloo.item_level_holds == "N" %] >+ <br/>Item level hold not allowed from OPAC >+ [% ELSIF itemloo.item_level_holds == "F" %] >+ <br/>Item level hold forced from OPAC > [% END %] >- </span> >- [% END # /IF force_hold_level %] >- </td> >- <td> >- [% IF (itemloo.pickup_locations_count > 0) || Koha.Preference('AllowHoldPolicyOverride') %] >- <select >- name="item_pickup_[% itemloo.itemnumber | html %]" >- class="pickup_locations requestspecific" >- style="width:100%;" >- data-item-id="[% itemloo.itemnumber | html %]" >- data-patron-id="[% patron.borrowernumber | html %]" >- data-pickup-location-source="item" >- > >- [% IF (itemloo.default_pickup_location) %] >- <option value="[% itemloo.default_pickup_location.branchcode | html %]" selected="selected">[% itemloo.default_pickup_location.branchname | html %]</option> >+ >+ [% IF ( itemloo.itemlost ) %] >+ <span class="lost">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.itemlost', authorised_value => itemloo.itemlost ) | html %]</span> >+ [% END %] >+ >+ [% IF ( itemloo.damaged ) %] >+ <span class="dmg">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.damaged', authorised_value => itemloo.damaged ) | html %]</span> > [% END %] >- </select> >+ >+ [% IF ( itemloo.withdrawn ) %] >+ <span class="wdn">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.withdrawn', authorised_value => itemloo.withdrawn ) | html %]</span> >+ [% END %] >+ >+ [% IF ( itemloo.notforloan ) %] >+ <span class="nfl">Not for loan ([% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.notforloan', authorised_value => itemloo.notforloan ) | html %])</span> >+ [% ELSIF ( itemloo.notforloanitype ) %] >+ <span class="nfl">Not for loan (Itemtype not for loan)</span> >+ [% END %] >+ </td> >+ </tr> >+ [% END # / UNLESS itemloo.hide %] >+ [% END # /FOREACH itemloo %] >+ </tbody> >+ </table> <!-- /#requestspecific --> >+ >+ [% IF hiddencount %] >+ <p class="hiddencount"> >+ <a href="request.pl?biblionumber=[% biblio_info.biblionumber | uri %]&borrowernumber=[% borrowernumber | uri %]&showallitems=1">Show all items ([% hiddencount | html %] hidden)</a> >+ </p> >+ [% END # /IF hiddencount %] >+ <fieldset class="action"> >+ [% IF ( patron.borrowernumber ) %] >+ [% IF ( override_required ) %] >+ <button type="submit" id="hold_item_btn" class="btn btn-primary warning"><i class="fa fa-exclamation-triangle "></i> Place hold</button> >+ [% ELSIF ( none_available ) %] >+ <button type="submit" id="hold_item_btn" disabled="disabled" class="btn btn-primary btn-disabled">Place hold</button> >+ [% ELSE %] >+ <button type="submit" id="hold_item_btn" class="btn btn-primary">Place hold</button> >+ [% END %] >+ [% END %] >+ </fieldset> >+ >+ [% ELSE # /UNLESS multi_hold %] >+ <fieldset class="rows"> >+ <legend>Hold details</legend> >+ <form action="placerequest.pl" method="post" name="form" id="hold-request-form"> >+ [% INCLUDE 'csrf-token.inc' %] >+ <input type="hidden" name="op" value="cud-placerequest" /> >+ <input type="hidden" name="multi_holds" id="multi_holds" value="1" /> >+ <input type="hidden" name="request" value="any"/> >+ <input type="hidden" name="borrowernumber" value="[% patron.borrowernumber | html %]" /> >+ [% FOREACH biblioloo IN biblioloop %] >+ <input type="hidden" name="biblionumber" id="biblionumber" value="[% biblioloo.biblionumber | html %]"/> >+ [% UNLESS biblioloo.none_avail %] >+ <input type="hidden" name="title_[% biblioloo.biblionumber | html %]" value="[% biblioloo.title | html %]"/> >+ <input type="hidden" name="rank_[% biblioloo.biblionumber | html %]" value="[% biblioloo.rank | html %]"/> > [% END %] >- </td> >- [% IF Koha.Preference('item-level_itypes') %] >- <td> >- [% UNLESS ( noItemTypeImages ) %] >- [% IF ( itemloo.itemtype.image_location) %]<img class="itemtype-image" src="[% itemloo.itemtype.image_location | html %]" alt="" /> <br />[% END %] >- [% END %] >- <span class="itypetext">[% itemloo.itemtype.translated_description | html %]</span> >- </td> > [% END %] >- <td> [% itemloo.barcode | html %] </td> >- [% IF Koha.Preference('EnableItemGroupHolds') && biblio_info.object.item_groups.count %] >- <td> [% itemloo.object.item_group.description | html %] </td> >+ >+ <ol> >+ >+ <li> >+ <span class="label">Patron:</span> >+ [% IF ( patron.borrowernumber ) %] >+ [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 hide_patron_infos_if_needed => 1 %] >+ [% ELSE %] >+ Not defined yet >+ [% END %] >+ </li> >+ >+ >+ <li> >+ <label for="holdnotes">Notes:</label> >+ <textarea id="holdnotes" name="notes" cols="30" rows="1"></textarea> >+ </li> >+ <li> >+ <label for="pickup">Pickup at:</label> >+ <select name="pickup" id="pickup_multi" data-patron-id="[% patron.borrowernumber | html %]"> >+ <option value="" selected="selected"></option> >+ [% FOREACH pickup_location IN multi_pickup_locations %] >+ <option value="[% pickup_location.branchcode | html %]">[% pickup_location.branchname | html %]</option> >+ [% END %] >+ </select> >+ </li> >+ [% IF ( Koha.Preference('AllowHoldDateInFuture') ) %] >+ <li> >+ <label for="from">Hold starts on date:</label> >+ <input id="reserve_date" name="reserve_date" id="from" size="10" type="text" data-date_to="expiration_date" class="flatpickr" data-flatpickr-futureinclusive="true" /> >+ </li> > [% END %] >- <td> [% Branches.GetName( itemloo.homebranch ) | html %] </td> >- <td> [% Branches.GetName( itemloo.holdingbranch ) | html %] </td> >- [% IF itemdata_ccode %] >- <td> [% IF ( itemloo.ccode ) %][% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => itemloo.ccode ) | html %][% END %] </td> >+ >+ <li> >+ <label for="to">Hold expires on date:</label> >+ <input id="expiration_date" name="expiration_date" id="to" size="10" type="text" class="flatpickr" data-flatpickr-futuredate="true" /> >+ </li> >+ >+ </ol> >+ <table id="requesttitles"> >+ <tr> >+ <th> </th> >+ <th>Pickup location</th> >+ <th>Title</th> >+ [% UNLESS Koha.Preference('item-level_itypes') %] >+ <th>Item type</th> > [% END %] >- <td> [% itemloo.itemcallnumber | html %] </td> >- <td> [% IF ( itemloo.copynumber ) %][% itemloo.copynumber | html %][% ELSE %] [% END %] </td> >- [% IF itemdata_enumchron %] >- <td> [% itemloo.enumchron | html %] </td> >+ <th>Priority</th> >+ <th>Information</th> >+ </tr> >+ [% FOREACH biblioloo IN biblioloop %] >+ [% IF ( biblioloo.warn ) %] >+ <tr class="onissue"> >+ [% ELSE %] >+ <tr> > [% END %] >- <td [% IF itemloo.onloan %]data-order="[% itemloo.date_due | html %]"[% END %]> >- [% IF ( itemloo.onloan ) %] >- <span class="checkedout">Due [% itemloo.date_due | $KohaDates as_due_date => 1 %]</span> >- [% ELSE %] >- [% IF ( itemloo.transfertwhen ) %] >- <span >- >In transit from [% Branches.GetName( itemloo.transfertfrom ) | html %], to [% Branches.GetName( itemloo.transfertto ) | html %], since >- [% itemloo.transfertwhen | $KohaDates %]</span >- > >+ <td> >+ [% UNLESS ( biblioloo.warn ) %] >+ <input id="holdable_bibs" name="holdable_bibs" class="multi_hold_item_checkbox" type="checkbox" checked="checked" title="[% biblioloo.biblionumber | html %]" value="[% biblioloo.biblionumber | html %]"/> >+ [% END %] >+ </td> >+ <td> >+ [% UNLESS ( biblioloo.none_avail || biblioloo.noitems ) %] >+ <select name="pickup_[% biblioloo.biblionumber | html %]" >+ class="multi_pickup_select" >+ data-biblio-id="[% biblioloo.biblionumber | html %]" >+ data-patron-id="[% patron.borrowernumber | html %]" >+ data-pickup-locations='[% biblioloo.pickup_locations_codes.json | $raw %]'> >+ <option value=""></option> >+ [% FOREACH pickup_location IN biblioloo.pickup_locations %] >+ <option value="[% pickup_location.branchcode | html %]">[% pickup_location.branchname | html %]</option> >+ [% END %] >+ </select> >+ [% END %] >+ </td> >+ <td> >+ <ul> >+ <li> >+ <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]">[% biblioloo.title | html %]</a> >+ [% IF biblioloo.author %] by [% biblioloo.author | html %][% END %] >+ </li> >+ [% IF ( biblioloo.publicationyear ) %] >+ <li> >+ <span class="label">Publication year:</span> [% biblioloo.publicationyear | html %] >+ </li> >+ [% END %] >+ </ul> >+ [% IF ( biblioloo.warn ) %] >+ <span class="not_holdable" title="[% biblioloo.biblionumber | html %]"></span> > [% END %] >+ </td> >+ [% UNLESS Koha.Preference('item-level_itypes') %] >+ <td> >+ <img src="[% biblioloo.itemtype.image_location | html %]" alt="[% biblioloo.itemtype.translated_description | html %]" title="[% biblioloo.itemtype.translated_description | html %]" /> >+ </td> > [% END %] >- >- [% IF ( itemloo.reservedate ) %] >- [% IF ( itemloo.nocancel ) %] >- <span>Can't be cancelled when item is in transit</span> >+ <td>[% biblioloo.rank | html %]</td> >+ <td> >+ [% IF ( biblioloo.checked_previously ) %] >+ <span>Patron has previously checked out this title</span><br/> >+ [% END %] >+ [% IF ( biblioloo.alreadyres ) %] >+ <ul> > [% ELSE %] >- [% IF ( itemloo.waitingdate ) %] >- [% IF ( itemloo.canreservefromotherbranches ) %] >- <span >- >Waiting for [% INCLUDE 'patron-title.inc' patron=itemloo.ReservedFor %] at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %] since >- [% itemloo.waitingdate | $KohaDates %]</span >- > >- [% ELSE %] >- <span>Waiting at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %] since [% itemloo.waitingdate | $KohaDates %]</span> >- [% END %] >- [% ELSE %] >- [% IF ( itemloo.canreservefromotherbranches ) %] >- [% IF itemloo.reservedate %] >- <span>On hold for [% INCLUDE 'patron-title.inc' patron=itemloo.ReservedFor %] expected at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %] since</span> >- [% ELSE %] >- <span>On hold expected at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %]</span> >- [% END %] >- [% ELSIF itemloo.reservedate %] >- <span>On hold expected at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %] since [% itemloo.reservedate | $KohaDates %]</span> >- [% ELSE %] >- <span>On hold expected at [% Branches.GetName( itemloo.ExpectedAtLibrary ) | html %]</span> >- [% END %] >+ [% IF ( biblioloo.none_avail || biblioloo.noitems ) %] >+ <ul> > [% END %] >- [% END # /IF itemloo.nocancel %] >- [% ELSE %] >- Not on hold >- [% END # /IF itemloo.reservedate %] >+ [% END %] > >- [% IF itemloo.item_level_holds == "N" %] >- <br />Item level hold not allowed from OPAC >- [% ELSIF itemloo.item_level_holds == "F" %] >- <br />Item level hold forced from OPAC >- [% END %] >+ [% IF ( biblioloo.alreadyres ) %] >+ <li> >+ [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] <strong>already has a hold</strong> on this item >+ </li> >+ [% END %] >+ [% IF ( biblioloo.none_avail || biblioloo.noitems ) %] >+ <li> <strong>No items are available</strong> to be placed on hold</li> >+ [% END %] > >- [% IF ( itemloo.itemlost ) %] >- <span class="lost">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.itemlost', authorised_value => itemloo.itemlost ) | html %]</span> >- [% END %] >+ [% IF ( biblioloo.alreadyres ) %] >+ </ul> >+ [% ELSE %] >+ [% IF ( biblioloo.none_avail || biblioloo.noitems ) %] >+ </ul> >+ [% END %] >+ [% END %] >+ </td> >+ </tr> >+ [% END # /FOREACH biblioloo %] >+ </table> <!-- /#requesttitles --> >+ </fieldset> >+ <fieldset class="action"> >+ [% IF ( patron AND patron.borrowernumber ) %] >+ [% IF ( override_required ) %] >+ <button type="submit" id="hold_multi_btn" class="btn btn-primary warning"><i class="fa fa-exclamation-triangle "></i> Place holds</button> >+ [% ELSIF ( no_bibs_available ) %] >+ <button type="submit" id="hold_multi_btn" class="btn btn-primary btn-disabled" disabled="disabled">Place holds</button> >+ [% ELSIF ( none_available ) %] >+ <button type="submit" id="hold_multi_btn" class="btn btn-primary">Place holds</button> >+ [% ELSE %] >+ <button type="submit" id="hold_multi_btn" class="btn btn-primary" id="multi_hold_submit">Place holds</button> >+ [% END %] >+ [% END # /IF patron %] >+ </fieldset> <!-- /.action --> > >- [% IF ( itemloo.damaged ) %] >- <span class="dmg">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.damaged', authorised_value => itemloo.damaged ) | html %]</span> >- [% END %] >+ [% END # /UNLESS multi_hold %] > >- [% IF ( itemloo.withdrawn ) %] >- <span class="wdn">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.withdrawn', authorised_value => itemloo.withdrawn ) | html %]</span> >- [% END %] >+ </fieldset> >+ </fieldset> <!-- /.rows --> >+ </form> <!-- /#hold-request-form --> >+ [% END %] > >- [% IF ( itemloo.notforloan ) %] >- <span class="nfl">Not for loan ([% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.notforloan', authorised_value => itemloo.notforloan ) | html %])</span> >- [% ELSIF ( itemloo.notforloanitype ) %] >- <span class="nfl">Not for loan (Itemtype not for loan)</span> >- [% END %] >- </td> >- </tr> >- [% END # / UNLESS itemloo.hide %] >- [% END # /FOREACH itemloo %] >- </tbody> >- </table> >- <!-- /#requestspecific --> >- >- [% IF hiddencount %] >- <p class="hiddencount"> >- <a href="request.pl?biblionumber=[% biblio_info.biblionumber | uri %]&borrowernumber=[% borrowernumber | uri %]&showallitems=1">Show all items ([% hiddencount | html %] hidden)</a> >- </p> >- [% END # /IF hiddencount %] >- <fieldset class="action"> >- [% IF ( patron.borrowernumber ) %] >- [% IF ( override_required ) %] >- <button type="submit" id="hold_item_btn" class="btn btn-primary warning"><i class="fa fa-exclamation-triangle "></i> Place hold</button> >- [% ELSIF ( none_available ) %] >- <button type="submit" id="hold_item_btn" disabled="disabled" class="btn btn-primary btn-disabled">Place hold</button> >- [% ELSE %] >- <button type="submit" id="hold_item_btn" class="btn btn-primary">Place hold</button> >- [% END %] >+ [% UNLESS ( patron ) %] >+ [% UNLESS borrowers %] >+ [% SET hold_count = biblio.holds.count | html %] >+ [% IF hold_count %] >+ <label for ="always_show_holds">Always show holds</label> >+ [% IF always_show_holds == 'DONT' %] >+ <input type="checkbox" name="always_show_holds" id="always_show_holds" value="DO"> >+ [% UNLESS reserveloop %] >+ <a class="btn btn-default" value="Show holds" id="show_holds_now" href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% biblio.biblionumber | uri %]&show_holds_now=1">Show holds ([% hold_count | html %])</a> > [% END %] >- </fieldset> >- </fieldset> >- </fieldset> >- <!-- /.rows any_specific --> >- </form> >- <!-- /#hold-request-form --> >- [% ELSE # /UNLESS multi_hold %] >- <form action="placerequest.pl" method="post" name="form" id="hold-request-form"> >- <fieldset class="rows"> >- <legend>Hold details</legend> >- [% INCLUDE 'csrf-token.inc' %] >- <input type="hidden" name="op" value="cud-placerequest" /> >- <input type="hidden" name="multi_holds" id="multi_holds" value="1" /> >- <input type="hidden" name="request" value="any" /> >- <input type="hidden" name="borrowernumber" value="[% patron.borrowernumber | html %]" /> >- [% FOREACH biblioloo IN biblioloop %] >- <input type="hidden" name="biblionumber" id="biblionumber" value="[% biblioloo.biblionumber | html %]" /> >- [% UNLESS biblioloo.none_avail %] >- <input type="hidden" name="title_[% biblioloo.biblionumber | html %]" value="[% biblioloo.title | html %]" /> >- <input type="hidden" name="rank_[% biblioloo.biblionumber | html %]" value="[% biblioloo.rank | html %]" /> >+ [% ELSE %] >+ <input type="checkbox" name="always_show_holds" value="DO" id="always_show_holds" checked="checked"> > [% END %] > [% END %] >- >- <ol> >- <li> >- <span class="label">Patron:</span> >- [% IF ( patron.borrowernumber ) %] >- [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 hide_patron_infos_if_needed => 1 %] >- [% ELSE %] >- Not defined yet >+ [% END %] >+ [% IF ( reserveloop ) %] >+ <form id="existing_holds" name="T[% time | html %]" action="modrequest.pl" method="post" style="display:block"> >+ [% INCLUDE 'csrf-token.inc' %] >+ [% IF ( multi_hold ) %] >+ [% FOREACH biblionumber IN biblionumbers %] >+ <input type="hidden" name="biblionumber" value="[% biblionumber | html %]"/> > [% END %] >- </li> >+ [% END %] > >- <li> >- <label for="holdnotes">Notes:</label> >- <textarea id="holdnotes" name="notes" cols="30" rows="1"></textarea> >- </li> >- <li> >- <label for="pickup">Pickup at:</label> >- <select name="pickup" id="pickup_multi" data-patron-id="[% patron.borrowernumber | html %]"> >- <option value="" selected="selected"></option> >- [% FOREACH pickup_location IN multi_pickup_locations %] >- <option value="[% pickup_location.branchcode | html %]">[% pickup_location.branchname | html %]</option> >- [% END %] >- </select> >- </li> >- [% IF ( Koha.Preference('AllowHoldDateInFuture') ) %] >- <li> >- <label for="from">Hold starts on date:</label> >- <input id="reserve_date" name="reserve_date" id="from" size="10" type="text" data-date_to="expiration_date" class="flatpickr" data-flatpickr-futureinclusive="true" /> >- </li> >+ [% IF enqueued %] >+ <div class="alert alert-info"> >+ <p>The job has been enqueued! It will be processed as soon as possible.</p> >+ <p><a href="/cgi-bin/koha/admin/background_jobs.pl?op=view&id=[% job_id | uri %]" title="View detail of the enqueued job">View detail of the enqueued job</a></p> >+ </div> > [% END %] > >- <li> >- <label for="to">Hold expires on date:</label> >- <input id="expiration_date" name="expiration_date" id="to" size="10" type="text" class="flatpickr" data-flatpickr-futuredate="true" /> >- </li> >- </ol> >- <table id="requesttitles"> >- <tr> >- <th> </th> >- <th>Pickup location</th> >- <th>Title</th> >- [% UNLESS Koha.Preference('item-level_itypes') %] >- <th>Item type</th> >+ <h2>Existing holds</h2> >+ <div id="toolbar" class="btn-toolbar sticky"> >+ <div class="btn-group"> >+ <input type="hidden" name="op" value="cud-modifyall"> >+ <input type="submit" class="btn btn-primary" name="submit" value="Update hold(s)" /> >+ </div> >+ <div class="btn-group"> >+ <button class="btn cancel_selected_holds" data-bulk="true"></button> >+ </div> >+ <fieldset id="cancellation-reason-fieldset" class="action" style="display:none"> >+ [% SET hold_cancellation = AuthorisedValues.GetAuthValueDropbox('HOLD_CANCELLATION') %] >+ [% IF hold_cancellation.count %] >+ <label for="cancellation-reason">Cancellation reason: </label> >+ <select class="cancellation-reason" name="cancellation-reason" id="cancellation-reason"> >+ <option value="">No reason given</option> >+ [% FOREACH reason IN hold_cancellation %] >+ <option value="[% reason.authorised_value | html %]">[% reason.lib | html %]</option> >+ [% END %] >+ </select> > [% END %] >- <th>Priority</th> >- <th>Information</th> >- </tr> >+ </fieldset> >+ </div> >+ <div class="page-section"> >+ > [% FOREACH biblioloo IN biblioloop %] >- <tr [% IF biblioloo.warn %]class="onissue"[% END %]> >- <td> >- [% UNLESS ( biblioloo.warn ) %] >- <input >- id="holdable_bibs" >- name="holdable_bibs" >- class="multi_hold_item_checkbox" >- type="checkbox" >- checked="checked" >- title="[% biblioloo.biblionumber | html %]" >- value="[% biblioloo.biblionumber | html %]" >- /> >- [% END %] >- </td> >- <td> >- [% UNLESS ( biblioloo.none_avail || biblioloo.noitems ) %] >- <select >- name="pickup_[% biblioloo.biblionumber | html %]" >- class="multi_pickup_select" >- data-biblio-id="[% biblioloo.biblionumber | html %]" >- data-patron-id="[% patron.borrowernumber | html %]" >- data-pickup-locations="[% biblioloo.pickup_locations_codes.json | $raw %]" >- > >- <option value=""></option> >- [% FOREACH pickup_location IN biblioloo.pickup_locations %] >- <option value="[% pickup_location.branchcode | html %]">[% pickup_location.branchname | html %]</option> >- [% END %] >- </select> >- [% END %] >- </td> >- <td> >- <ul> >- <li> >- <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]">[% biblioloo.title | html %]</a> >- [% IF biblioloo.author %]by [% biblioloo.author | html %][% END %] >- </li> >- [% IF ( biblioloo.publicationyear ) %] >- <li> <span class="label">Publication year:</span> [% biblioloo.publicationyear | html %] </li> >- [% END %] >- </ul> >- [% IF ( biblioloo.warn ) %] >- <span class="not_holdable" title="[% biblioloo.biblionumber | html %]"></span> >- [% END %] >- </td> >- [% UNLESS Koha.Preference('item-level_itypes') %] >- <td> >- <img src="[% biblioloo.itemtype.image_location | html %]" alt="[% biblioloo.itemtype.translated_description | html %]" title="[% biblioloo.itemtype.translated_description | html %]" /> >- </td> >- [% END %] >- <td>[% biblioloo.rank | html %]</td> >- <td> >- [% IF ( biblioloo.checked_previously ) %] >- <span>Patron has previously checked out this title</span><br /> >+ [% IF ( biblioloo.reserveloop ) %] >+ <div class="hold_title" id="hold_title_[% biblioloo.biblionumber | html %]"> >+ [% IF ( multi_hold ) %] >+ <h3> >+ <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]"> >+ [% biblioloo.title | html %] >+ </a> <span class="badge text-bg-info"><span>[% biblioloo.reserveloop.size | html %] [% tn('Hold', 'Holds', biblioloo.reserveloop.size) | $raw %]</span></span> >+ </h3> > [% END %] >- [% IF ( biblioloo.alreadyres ) %] >- <ul> >- <li> [% INCLUDE 'patron-title.inc' patron => patron no_title => 1 no_cardnumber => 1 hide_patron_infos_if_needed => 1 %] <strong>already has a hold</strong> on this item </li> >- </ul> >- [% END %] >- [% IF ( biblioloo.none_avail || biblioloo.noitems ) %] >- <ul >- ><li> <strong>No items are available</strong> to be placed on hold</li></ul >- > >- [% END %] >- </td> >- </tr> >- [% END # /FOREACH biblioloo %] >- </table> >- <!-- /#requesttitles --> >- </fieldset> >- <fieldset class="action"> >- [% IF ( patron AND patron.borrowernumber ) %] >- [% IF ( override_required ) %] >- <button type="submit" id="hold_multi_btn" class="btn btn-primary warning"><i class="fa fa-exclamation-triangle "></i> Place holds</button> >- [% ELSIF ( no_bibs_available ) %] >- <button type="submit" id="hold_multi_btn" class="btn btn-primary btn-disabled" disabled="disabled">Place holds</button> >- [% ELSIF ( none_available ) %] >- <button type="submit" id="hold_multi_btn" class="btn btn-primary">Place holds</button> >- [% ELSE %] >- <button type="submit" id="hold_multi_btn" class="btn btn-primary" id="multi_hold_submit">Place holds</button> >- [% END %] >- [% END # /IF patron %] >- </fieldset> >- <!-- /.action --> >- </form> >- <!-- /#hold-request-form --> >- [% END # /UNLESS multi_hold %] >- [% END %] > >- [% UNLESS ( patron ) %] >- [% UNLESS borrowers %] >- [% SET hold_count = biblio.holds.count | html %] >- [% IF hold_count %] >- <label for="always_show_holds">Always show holds</label> >- [% IF always_show_holds == 'DONT' %] >- <input type="checkbox" name="always_show_holds" id="always_show_holds" value="DO" /> >- [% UNLESS reserveloop %] >- <a class="btn btn-default" value="Show holds" id="show_holds_now" href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% biblio.biblionumber | uri %]&show_holds_now=1">Show holds ([% hold_count | html %])</a> >- [% END %] >- [% ELSE %] >- <input type="checkbox" name="always_show_holds" value="DO" id="always_show_holds" checked="checked" /> >- [% END %] >- [% END %] >- [% END %] >- [% IF ( reserveloop ) %] >- <form id="existing_holds" name="T[% time | html %]" action="modrequest.pl" method="post" style="display:block"> >- [% INCLUDE 'csrf-token.inc' %] >- [% IF ( multi_hold ) %] >- [% FOREACH biblionumber IN biblionumbers %] >- <input type="hidden" name="biblionumber" value="[% biblionumber | html %]" /> >- [% END %] >- [% END %] >+ [% IF Koha.Preference('HoldsSplitQueue') == 'branch' %] > >- [% IF enqueued %] >- <div class="alert alert-info"> >- <p>The job has been enqueued! It will be processed as soon as possible.</p> >- <p><a href="/cgi-bin/koha/admin/background_jobs.pl?op=view&id=[% job_id | uri %]" title="View detail of the enqueued job">View detail of the enqueued job</a></p> >- </div> >- [% END %] >+ [% SET branchcodes = [] %] > >- <h2>Existing holds</h2> >- <div id="toolbar" class="btn-toolbar sticky"> >- <div class="btn-group"> >- <input type="hidden" name="op" value="cud-modifyall" /> >- <input type="submit" class="btn btn-primary" name="submit" value="Update hold(s)" /> >- </div> >- <div class="btn-group"> >- <button class="btn cancel_selected_holds" data-bulk="true"></button> >- </div> >- <fieldset id="cancellation-reason-fieldset" class="action" style="display:none"> >- [% SET hold_cancellation = AuthorisedValues.GetAuthValueDropbox('HOLD_CANCELLATION') %] >- [% IF hold_cancellation.count %] >- <label for="cancellation-reason">Cancellation reason: </label> >- <select class="cancellation-reason" name="cancellation-reason" id="cancellation-reason"> >- <option value="">No reason given</option> >- [% FOREACH reason IN hold_cancellation %] >- <option value="[% reason.authorised_value | html %]">[% reason.lib | html %]</option> >- [% END %] >- </select> >- [% END %] >- </fieldset> >- </div> >- <div class="page-section"> >- [% FOREACH biblioloo IN biblioloop %] >- [% IF ( biblioloo.reserveloop ) %] >- <div class="hold_title" id="hold_title_[% biblioloo.biblionumber | html %]"> >- [% IF ( multi_hold ) %] >- <h3> >- <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblioloo.biblionumber | uri %]"> [% biblioloo.title | html %] </a> >- <span class="badge text-bg-info"><span>[% biblioloo.reserveloop.size | html %] [% tn('Hold', 'Holds', biblioloo.reserveloop.size) | $raw %]</span></span> >- </h3> >- [% END %] >+ [% FOREACH h IN biblioloo.reserveloop %] >+ [% branchcodes.push( h.branchcode ) %] >+ [% END %] >+ [% branchcodes = branchcodes.unique %] >+ [% IF ( branchcodes.empty ) %] >+ <div class="note"> >+ There are no holds on this title. >+ </div> >+ [% ELSE %] > >- [% IF Koha.Preference('HoldsSplitQueue') == 'branch' %] >+ [% FOREACH b IN branchcodes.sort %] >+ [% SET holds_by_branch = [] %] >+ [% FOREACH h IN biblioloo.reserveloop %] >+ [% IF h.branchcode == b %] >+ [% holds_by_branch.push( h ) %] >+ [% END %] >+ [% END %] >+ <div class="holds_by_library"> >+ <h4>[% Branches.GetName( b ) | html %]</h4> > >- [% SET branchcodes = [] %] >+ [% INCLUDE holds_table.inc holds=holds_by_branch %] >+ </div> >+ [% END # /FOREACh b %] >+ [% END # /IF ( branchcodes.empty ) %] > >- [% FOREACH h IN biblioloo.reserveloop %] >- [% branchcodes.push( h.branchcode ) %] >- [% END %] >- [% branchcodes = branchcodes.unique %] >- [% IF ( branchcodes.empty ) %] >- <div class="alert alert-info"> There are no holds on this title. </div> >- [% ELSE %] >+ [% ELSIF Koha.Preference('HoldsSplitQueue') == 'itemtype' %] > >- [% FOREACH b IN branchcodes.sort %] >- [% SET holds_by_branch = [] %] >- [% FOREACH h IN biblioloo.reserveloop %] >- [% IF h.branchcode == b %] >- [% holds_by_branch.push( h ) %] >- [% END %] >- [% END %] >- <div class="holds_by_library"> >- <h4>[% Branches.GetName( b ) | html %]</h4> >+ [% SET itemtypes = [] %] > >- [% INCLUDE holds_table.inc holds=holds_by_branch %] >+ [% FOREACH h IN biblioloo.reserveloop %] >+ [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %] >+ [% itemtypes.push( hold_itemtype ) %] >+ [% END %] >+ [% itemtypes = itemtypes.unique %] >+ [% IF ( itemtypes.empty ) %] >+ <div class="note"> >+ There are no holds on this title. > </div> >- [% END # /FOREACh b %] >- [% END # /IF ( branchcodes.empty ) %] >- [% ELSIF Koha.Preference('HoldsSplitQueue') == 'itemtype' %] >+ [% ELSE %] > >- [% SET itemtypes = [] %] >+ [% FOREACH i IN itemtypes.sort %] >+ [% SET holds_by_itemtype = [] %] >+ [% FOREACH h IN biblioloo.reserveloop %] >+ [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %] >+ [% IF hold_itemtype == i %] >+ [% holds_by_itemtype.push( h ) %] >+ [% END %] >+ [% END %] > >- [% FOREACH h IN biblioloo.reserveloop %] >- [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %] >- [% itemtypes.push( hold_itemtype ) %] >- [% END %] >- [% itemtypes = itemtypes.unique %] >- [% IF ( itemtypes.empty ) %] >- <div class="alert alert-info"> There are no holds on this title. </div> >- [% ELSE %] >+ <div class="holds_by_itemtype"> >+ [% IF i %] >+ <h4>[% ItemTypes.GetDescription( i ) | html %]</h4> >+ [% ELSE %] >+ <h4>Any item type</h4> >+ [% END %] >+ [% INCLUDE holds_table.inc holds=holds_by_itemtype %] >+ </div> >+ [% END # /FOREACH i %] >+ [% END # /IF ( itemtypes.empty ) %] > >- [% FOREACH i IN itemtypes.sort %] >- [% SET holds_by_itemtype = [] %] >- [% FOREACH h IN biblioloo.reserveloop %] >- [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %] >- [% IF hold_itemtype == i %] >- [% holds_by_itemtype.push( h ) %] >- [% END %] >- [% END %] >+ [% ELSIF Koha.Preference('HoldsSplitQueue') == 'branch_itemtype' %] >+ [% SET branchcodes = [] %] > >- <div class="holds_by_itemtype"> >- [% IF i %] >- <h4>[% ItemTypes.GetDescription( i ) | html %]</h4> >- [% ELSE %] >- <h4>Any item type</h4> >- [% END %] >- [% INCLUDE holds_table.inc holds=holds_by_itemtype %] >+ [% FOREACH h IN biblioloo.reserveloop %] >+ [% branchcodes.push( h.branchcode ) %] >+ [% END %] >+ [% branchcodes = branchcodes.unique %] >+ [% IF ( branchcodes.empty ) %] >+ <div class="note"> >+ There are no holds on this title. > </div> >- [% END # /FOREACH i %] >- [% END # /IF ( itemtypes.empty ) %] >- [% ELSIF Koha.Preference('HoldsSplitQueue') == 'branch_itemtype' %] >- [% SET branchcodes = [] %] >- >- [% FOREACH h IN biblioloo.reserveloop %] >- [% branchcodes.push( h.branchcode ) %] >- [% END %] >- [% branchcodes = branchcodes.unique %] >- [% IF ( branchcodes.empty ) %] >- <div class="alert alert-info"> There are no holds on this title. </div> >- [% ELSE %] >+ [% ELSE %] >+ >+ [% FOREACH b IN branchcodes.sort %] >+ <div class="holds_by_library"> >+ <h4 class="library_holds">[% Branches.GetName( b ) | html %]</h4> >+ [% SET holds_by_branch = [] %] >+ [% FOREACH h IN biblioloo.reserveloop %] >+ [% IF h.branchcode == b %] >+ [% holds_by_branch.push( h ) %] >+ [% END %] >+ [% END %] > >- [% FOREACH b IN branchcodes.sort %] >- <div class="holds_by_library"> >- <h4 class="library_holds">[% Branches.GetName( b ) | html %]</h4> >- [% SET holds_by_branch = [] %] >- [% FOREACH h IN biblioloo.reserveloop %] >- [% IF h.branchcode == b %] >- [% holds_by_branch.push( h ) %] >+ [% SET itemtypes = [] %] >+ [% FOREACH h IN holds_by_branch %] >+ [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %] >+ [% itemtypes.push( hold_itemtype ) %] > [% END %] >- [% END %] >+ [% itemtypes = itemtypes.unique %] > >- [% SET itemtypes = [] %] >- [% FOREACH h IN holds_by_branch %] >- [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %] >- [% itemtypes.push( hold_itemtype ) %] >- [% END %] >- [% itemtypes = itemtypes.unique %] >+ [% FOREACH i IN itemtypes.sort %] >+ <div class="holds_by_itemtype"> >+ <h5 class="itemtype_holds"> >+ [% IF i %] >+ [% ItemTypes.GetDescription( i ) | html %] >+ [% ELSE %] >+ <span>Any item type</span> >+ [% END %] >+ </h5> > >- [% FOREACH i IN itemtypes.sort %] >- <div class="holds_by_itemtype"> >- <h5 class="itemtype_holds"> >- [% IF i %] >- [% ItemTypes.GetDescription( i ) | html %] >- [% ELSE %] >- <span>Any item type</span> >+ [% SET holds_by_itemtype = [] %] >+ [% FOREACH h IN holds_by_branch %] >+ [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %] >+ [% IF hold_itemtype == i %] >+ [% holds_by_itemtype.push( h ) %] >+ [% END %] > [% END %] >- </h5> >+ [% INCLUDE holds_table.inc holds=holds_by_itemtype %] >+ </div> <!-- /.holds_by_itemtype --> >+ [% END %] >+ </div> <!-- /.holds_by_library --> >+ [% END # /FOREACH b %] >+ [% END # /IF ( branchcodes.empty ) %] > >- [% SET holds_by_itemtype = [] %] >- [% FOREACH h IN holds_by_branch %] >- [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %] >- [% IF hold_itemtype == i %] >- [% holds_by_itemtype.push( h ) %] >- [% END %] >- [% END %] >- [% INCLUDE holds_table.inc holds=holds_by_itemtype %] >- </div> >- <!-- /.holds_by_itemtype --> >- [% END %] >+ [% ELSE %] >+ >+ [% IF ( biblioloo.reserveloop.size ) %] >+ [% INCLUDE holds_table.inc holds=biblioloo.reserveloop %] >+ [% ELSE %] >+ <div class="note"> >+ There are no holds on this title. > </div> >- <!-- /.holds_by_library --> >- [% END # /FOREACH b %] >- [% END # /IF ( branchcodes.empty ) %] >- [% ELSE %] >+ [% END %] > >- [% IF ( biblioloo.reserveloop.size ) %] >- [% INCLUDE holds_table.inc holds=biblioloo.reserveloop %] >- [% ELSE %] >- <div class="alert alert-info"> There are no holds on this title. </div> >- [% END %] >- [% END # /IF HoldsSplitQueue %] >- </div> >- <!-- /hold_title --> >- [% END # /IF biblioloo.reserveloop %] >- [% END # FOREACH biblioloo %] >- </div> >- </form> >- <!-- /#existing_holds --> >- [% END # IF reserveloop %] >- [% END # UNLESS patron %] >-[% END %] >+ [% END # /IF HoldsSplitQueue %] >+ </div> <!-- /hold_title --> >+ [% END # /IF biblioloo.reserveloop %] >+ [% END # FOREACH biblioloo %] >+ </div> >+ </form> <!-- /#existing_holds --> >+ [% END # IF reserveloop %] >+ [% END # UNLESS patron %] > >-<div id="cancelModal" class="modal" tabindex="-1" role="dialog" aria-hidden="true"> >- <div class="modal-dialog"> >- <div class="modal-content"> >- <div class="modal-header"> >- <h1 class="modal-title">Confirm deletion</h1> >- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> >- </div> >+ </main> > >- <form id="cancel_modal_form" method="post" action="request.pl"> >- [% INCLUDE 'csrf-token.inc' %] >- <div id="inputs"> >- <input type="hidden" name="op" value="cud-cancel" /> >+ [% IF ( multi_hold || nobiblio ) # No sidebar menu when placing multiple holds or biblio not found %] >+ </div> <!-- /.col-md-10.offset-md-1 --> >+ [% ELSE %] >+ </div> <!-- /.col-md-10.order-md-2 --> >+ <div class="col-md-2 order-sm-2 order-md-1"> >+ <aside> >+ [% INCLUDE 'biblio-view-menu.inc' %] >+ </aside> >+ </div> <!-- /.col-md-2.order-md-1 --> >+ [% END %] >+ </div> <!-- /.row --> >+ >+ <div id="cancelModal" class="modal" tabindex="-1" role="dialog" aria-hidden="true"> >+ <div class="modal-dialog"> >+ <div class="modal-content"> >+ <div class="modal-header"> >+ <h1 class="modal-title">Confirm deletion</h1> >+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> > </div> > >- <div class="modal-body"> >- <p>Are you sure you want to cancel this hold?</p> >- <div id="cancel_hold_alert" class="alert alert-danger" style="display:none;"></div> >- <fieldset class="action"> >- [% SET hold_cancellation = AuthorisedValues.GetAuthValueDropbox('HOLD_CANCELLATION') %] >- [% IF hold_cancellation.count %] >- <label for="modal-cancellation-reason">Cancellation reason: </label> >- <select class="cancellation-reason" name="cancellation-reason" id="modal-cancellation-reason"> >- <option value="">No reason given</option> >- [% FOREACH reason IN hold_cancellation %] >- <option value="[% reason.authorised_value | html %]">[% reason.lib | html %]</option> >- [% END %] >- </select> >- [% END %] >- </fieldset> >- </div> >+ <form id="cancel_modal_form" method="post" action="request.pl"> >+ [% INCLUDE 'csrf-token.inc' %] >+ <div id="inputs"> >+ <input type="hidden" name="op" value="cud-cancel"> >+ </div> > >- <div class="modal-footer"> >- <button id="cancelModalConfirmBtn" type="submit" class="btn btn-danger">Confirm cancellation</button> >- <button type="button" class="btn btn-default" data-bs-dismiss="modal">Cancel</button> >- </div> >- </form> >+ <div class="modal-body"> >+ <p>Are you sure you want to cancel this hold?</p> >+ <div id="cancel_hold_alert" class="alert alert-danger" style="display:none;"></div> >+ <fieldset class="action"> >+ [% SET hold_cancellation = AuthorisedValues.GetAuthValueDropbox('HOLD_CANCELLATION') %] >+ [% IF hold_cancellation.count %] >+ <label for="cancellation-reason">Cancellation reason: </label> >+ <select class="cancellation-reason" name="cancellation-reason" id="modal-cancellation-reason"> >+ <option value="">No reason given</option> >+ [% FOREACH reason IN hold_cancellation %] >+ <option value="[% reason.authorised_value | html %]">[% reason.lib | html %]</option> >+ [% END %] >+ </select> >+ [% END %] >+ </fieldset> >+ </div> >+ >+ <div class="modal-footer"> >+ <button id="cancelModalConfirmBtn" type="submit" class="btn btn-danger">Confirm cancellation</button> >+ <button type="button" class="btn btn-default" data-bs-dismiss="modal">Cancel</button> >+ </div> >+ >+ </form> >+ >+ </div> > </div> > </div> >-</div> >-<div id="hold-actions"> >- <form id="hold-actions-form"> [% INCLUDE 'csrf-token.inc' %] </form> >-</div> >+ <div id="hold-actions"> >+ <form id="hold-actions-form"> >+ [% INCLUDE 'csrf-token.inc' %] >+ </form> >+ </div> > > [% MACRO jsinclude BLOCK %] > [% INCLUDE 'datatables.inc' %] > [% INCLUDE 'calendar.inc' %] > [% INCLUDE 'select2.inc' %] >- [% Asset.js("js/holds.js") | $raw %] >- [% Asset.js("js/form-submit.js") | $raw %] >+ [% Asset.js("js/holds.js") | $raw%] >+ [% Asset.js("js/form-submit.js") | $raw%] > > [% SET url_biblio_params = "biblionumber=" _ biblionumbers.join("&biblionumber=") %] > [% IF multi_hold %] > [% SET url_biblio_params = url_biblio_params _ "&multi_hold=1" %] > [% END %] >+ > <script> > $(document).ready(function () { > hold_table_settings = [% TablesSettings.GetTableSettings( 'circ', 'holds', 'patron_holds_table', 'json' ) | $raw %]; >@@ -1860,7 +1924,7 @@ > e.preventDefault(); > if($('.holds_table .select_hold:checked').length) { > cancel_link = $(this); >- $("#cancel_modal_form #inputs").empty(); >+ $("#cancel_modal_form #inputs").empty; > biblionumbers.forEach( function(biblionumber){ > $("#cancel_modal_form #inputs").append('<input type="hidden" name="biblionumber" value="'+biblionumber+'">'); > }); >@@ -1934,27 +1998,169 @@ > return true; > }) > }); >- </script> >+</script> >+ > <script> > table_settings = [% TablesSettings.GetTableSettings( 'circ', 'circulation', 'table_borrowers', 'json' ) | $raw %]; > </script> >- [% UNLESS patron %] >- [% SET search_results_block_id = 'holds_patronsearch_pane_panel' %] >- [%# adjusting variable for patron-search.inc %] >- [% PROCESS patron_search_js table_id => 'table_borrowers', categories => categories, libraries => libraries, columns => columns, open_on_row_click => 1, on_click_url => '/cgi-bin/koha/reserve/request.pl?' _ url_biblio_params, redirect_if_one_result => 1, redirect_url => '/cgi-bin/koha/reserve/request.pl?' _ url_biblio_params, redirect_if_attribute_equal => 'cardnumber' %] >- <script> >- $(document).ready(function () { >- $("#holds_patronsearch").on("submit", filter); >- }); >- </script> >- [% END %] >+ >+ [% SET search_results_block_id = 'holds_patronsearch_pane_panel' %] [%# adjusting variable for patron-search.inc %] >+ [% PROCESS patron_search_js table_id => 'table_borrowers', categories => categories, libraries => libraries, columns => columns, open_on_row_click => 1, on_click_url => '/cgi-bin/koha/reserve/request.pl?' _ url_biblio_params, redirect_if_one_result => 1, redirect_url => '/cgi-bin/koha/reserve/request.pl?' _ url_biblio_params, redirect_if_attribute_equal => 'cardnumber' %] > <script> >- $(".printholdslip").click(function () { >- var reserve_id = $(this).attr("data-reserve_id"); >- window.open("/cgi-bin/koha/circ/hold-transfer-slip.pl?reserve_id=" + reserve_id); >- return false; >+ $(document).ready(function() { >+ $("#holds_patronsearch").on("submit", filter); > }); >+ $('.printholdslip').click(function(){ >+ var reserve_id = $(this).attr('data-reserve_id'); >+ window.open("/cgi-bin/koha/circ/hold-transfer-slip.pl?reserve_id=" + reserve_id); >+ return false; >+ }) > </script> > [% END %] > >-[% INCLUDE 'intranet-bottom.inc' %] >+<div class="modal fade" id="holdruleschecker" tabindex="-1" role="dialog" aria-labelledby="holdruleschecker-title"> >+ <div class="modal-dialog modal-lg" role="document"> >+ <div class="modal-content"> >+ <div class="modal-header"> >+ <h4 class="modal-title" id="holdruleschecker-title">[% t('Holding rules') | html %]</h4> >+ </div> >+ <div class="modal-body"> >+ <div> >+ <h4>[% t('Overall info') | html %]</h4> >+ >+ <ul> >+ <li> >+ [% tnx('Patron has {count} hold', 'Patron has {count} holds', reserves_count, { count = '<strong>' _ reserves_count _ '</strong>' }) | $raw %] >+ [% tx('and this request would raise the number to {count}.', { count = '<strong>' _ (new_reserves_count + reserves_count) _ '</strong>' }) | $raw %] >+ </li> >+ <li> >+ [% IF reserves_count >= Koha.Preference('maxreserves') %] >+ <span class="text-danger"> >+ [% ELSE %] >+ <span> >+ [% END %] >+ [% tx('{preference_name} preference:', { preference_name = '<em>maxreserves</em>' }) | $raw %] >+ <strong>[% Koha.Preference('maxreserves') | html %]</strong> >+ </span> >+ </li> >+ <li> >+ [% tx('{preference_name} preference:', { preference_name = '<em>ReservesControlBranch</em>' }) | $raw %] >+ <strong>[% Koha.Preference('ReservesControlBranch') | html %]</strong> >+ </li >+ </ul> >+ </div> >+ >+ <h4>[% t('Per record info') | html %]</h4> >+ >+ <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> >+ [% FOREACH response IN canbookbereserved_responses %] >+ <div class="panel panel-default"> >+ <div class="panel-heading" role="tab" id="heading-[% response.biblio.biblionumber | html %]"> >+ <h4 class="panel-title"> >+ <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse-[% response.biblio.biblionumber | html %]" aria-expanded="true" aria-controls="collapse-[% response.biblio.biblionumber | html %]"> >+ [% response.biblio.title | html %] >+ </a> >+ </h4> >+ </div> >+ <div id="collapse-[% response.biblio.biblionumber | html %]" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="heading-[% response.biblio.biblionumber | html %]"> >+ <div class="panel-body"> >+ <h5>[% t('Circulation rules checked') | html %]</h5> >+ >+ <table> >+ <thead> >+ <tr> >+ <th>[% t('Item') | html %]</th> >+ <th>[% t('Library') | html %]</th> >+ <th>[% t('Category') | html %]</th> >+ <th>[% t('Item type') | html %]</th> >+ <th>[% t('Rule name') | html %]</th> >+ <th>[% t('Rule value') | html %]</th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOREACH circulation_rule IN response.circulation_rules %] >+ <tr> >+ <td></td> >+ <td> >+ [% IF circulation_rule.branchcode %] >+ [% Branches.GetName(circulation_rule.branchcode) | html %] >+ ([% circulation_rule.branchcode | html %]) >+ [% ELSE %] >+ <em>[% t('All') | html %]</em> >+ [% END %] >+ </td> >+ <td> >+ [% IF circulation_rule.categorycode %] >+ [% Categories.GetName(circulation_rule.categorycode) | html %] >+ [% ELSE %] >+ <em>[% t('All') | html %]</em> >+ [% END %] >+ </td> >+ <td> >+ [% IF circulation_rule.itemtype %] >+ [% ItemTypes.GetDescription(circulation_rule.itemtype) | html %] >+ [% ELSE %] >+ <em>[% t('All') | html %]</em> >+ [% END %] >+ </td> >+ <td> >+ [% circulation_rule.rule_name | html %] >+ </td> >+ <td> >+ [% circulation_rule.rule_value | html %] >+ </td> >+ </tr> >+ [% END %] >+ [% FOREACH item_response IN response.item_responses %] >+ [% FOREACH circulation_rule IN item_response.circulation_rules %] >+ <tr> >+ <td> >+ [% item_response.item.barcode | html %] (#[% item_response.item.itemnumber | html %]) >+ </td> >+ <td> >+ [% IF circulation_rule.branchcode %] >+ [% Branches.GetName(circulation_rule.branchcode) | html %] >+ ([% circulation_rule.branchcode | html %]) >+ [% ELSE %] >+ <em>[% t('All') | html %]</em> >+ [% END %] >+ </td> >+ <td> >+ [% IF circulation_rule.categorycode %] >+ [% Categories.GetName(circulation_rule.categorycode) | html %] >+ [% ELSE %] >+ <em>[% t('All') | html %]</em> >+ [% END %] >+ </td> >+ <td> >+ [% IF circulation_rule.itemtype %] >+ [% ItemTypes.GetDescription(circulation_rule.itemtype) | html %] >+ [% ELSE %] >+ <em>[% t('All') | html %]</em> >+ [% END %] >+ </td> >+ <td> >+ [% circulation_rule.rule_name | html %] >+ </td> >+ <td> >+ [% circulation_rule.rule_value | html %] >+ </td> >+ </tr> >+ [% END %] >+ [% END %] >+ </tbody> >+ </table> >+ </div> >+ </div> >+ </div> >+ [% END %] >+ </div> >+ </div> >+ <div class="modal-footer"> >+ <button type="button" class="btn btn-default" data-dismiss="modal">[% t('Close') | html %]</button> >+ </div> >+ </div> >+ </div> >+</div> <!-- end of Modal --> >+ >+[% INCLUDE 'intranet-bottom.inc' %] >\ No newline at end of file >diff --git a/reserve/request.pl b/reserve/request.pl >index c5e354aa7d..bafa6defbf 100755 >--- a/reserve/request.pl >+++ b/reserve/request.pl >@@ -88,8 +88,7 @@ my $warnings; > my $messages; > my $exceeded_maxreserves; > my $exceeded_holds_per_record; >-my @failed_holds = $input->multi_param('failed_holds'); >-my $form_submitted = $input->param('form_submitted'); >+my @failed_holds = $input->multi_param('failed_holds'); > > my $op = $input->param('op') || q{}; > >@@ -146,29 +145,24 @@ if ($findborrower) { > $borrowernumber_hold = $patron->borrowernumber if $patron; > } > >-if ($form_submitted) { >- if ($findclub) { >- my $club = Koha::Clubs->find( { name => $findclub } ); >- if ($club) { >- $club_hold = $club->id; >+if ($findclub) { >+ my $club = Koha::Clubs->find( { name => $findclub } ); >+ if ($club) { >+ $club_hold = $club->id; >+ } else { >+ my @clubs = Koha::Clubs->search( >+ [ >+ { name => { like => '%' . $findclub . '%' } }, >+ { description => { like => '%' . $findclub . '%' } } >+ ] >+ )->as_list; >+ if ( scalar @clubs == 1 ) { >+ $club_hold = $clubs[0]->id; >+ } elsif (@clubs) { >+ $template->param( clubs => \@clubs ); > } else { >- my @clubs = Koha::Clubs->search( >- [ >- { name => { like => '%' . $findclub . '%' } }, >- { description => { like => '%' . $findclub . '%' } } >- ] >- )->as_list; >- if ( scalar @clubs == 1 ) { >- $club_hold = $clubs[0]->id; >- } elsif (@clubs) { >- $template->param( clubs => \@clubs ); >- } else { >- $messageclub = "'$findclub'"; >- } >+ $messageclub = "'$findclub'"; > } >- } else { >- my @clubs = Koha::Clubs->search()->as_list; >- $template->param( clubs => \@clubs ); > } > } > >@@ -189,8 +183,10 @@ if ( $borrowernumber_hold && !$op ) { > # FIXME At this time we have a simple count of reservs, but, later, we could improve the infos "title" ... > > my $reserves_count = $patron->holds->count; >+ $template->param( reserves_count => $reserves_count ); > > my $new_reserves_count = scalar(@biblionumbers); >+ $template->param( new_reserves_count => $new_reserves_count ); > > my $maxreserves = C4::Context->preference('maxreserves'); > $template->param( maxreserves => $maxreserves ); >@@ -206,8 +202,6 @@ if ( $borrowernumber_hold && !$op ) { > $exceeded_maxreserves = 1; > $template->param( > new_reserves_allowed => $new_reserves_allowed, >- new_reserves_count => $new_reserves_count, >- reserves_count => $reserves_count, > maxreserves => $maxreserves, > ); > } >@@ -302,6 +296,7 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) > my @biblioloop = (); > my $no_reserves_allowed = 0; > my $num_bibs_available = 0; >+ my @canbookbereserved_responses; > foreach my $biblionumber (@biblionumbers) { > next unless $biblionumber =~ m|^\d+$|; > >@@ -320,6 +315,9 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) > if ($patron) { > { # CanBookBeReserved > my $canReserve = CanBookBeReserved( $patron->borrowernumber, $biblionumber ); >+ >+ push @canbookbereserved_responses, { %$canReserve, biblio => $biblio }; >+ > if ( $canReserve->{status} eq 'OK' ) { > > #All is OK and we can continue >@@ -719,10 +717,14 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) > > $template->param( no_bibs_available => 1 ) unless $num_bibs_available > 0; > >- $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 ); >+ $Data::Dumper::Maxdepth = 3; >+ use Data::Dumper; >+ warn Dumper \@canbookbereserved_responses; >+ $template->param( canbookbereserved_responses => \@canbookbereserved_responses ); >+ $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 ); > > # FIXME: getting just the first bib's result doesn't seem right > $template->param( subscriptionsnumber => CountSubscriptionFromBiblionumber( $biblionumbers[0] ) ); >diff --git a/t/db_dependent/Reserves/HoldRulesChecker.t b/t/db_dependent/Reserves/HoldRulesChecker.t >new file mode 100644 >index 0000000000..0e41b46038 >--- /dev/null >+++ b/t/db_dependent/Reserves/HoldRulesChecker.t >@@ -0,0 +1,110 @@ >+#!/usr/bin/perl >+ >+# Copyright 2019 Biblibre >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Test::More tests => 13; >+use t::lib::TestBuilder; >+ >+use C4::Reserves qw( CanBookBeReserved ); >+ >+my $schema = Koha::Database->new->schema; >+$schema->storage->txn_begin; >+ >+my $builder = t::lib::TestBuilder->new(); >+ >+my $library = $builder->build_object( { class => 'Koha::Libraries' } ); >+my $category = $builder->build_object( { class => 'Koha::Patron::Categories' } ); >+my $patron = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { >+ categorycode => $category->categorycode, >+ branchcode => $library->branchcode, >+ }, >+ } >+); >+ >+my $itemtype = $builder->build_object( { class => 'Koha::ItemTypes' } ); >+ >+my $biblio = $builder->build_sample_biblio( >+ { >+ title => 'Title 1', >+ } >+); >+my $item = $builder->build_sample_item( >+ { >+ biblionumber => $biblio->biblionumber, >+ library => $library->branchcode, >+ itype => $itemtype->itemtype, >+ damaged => 0, >+ } >+); >+ >+my $rules_rs = Koha::Database->new()->schema()->resultset('CirculationRule'); >+$rules_rs->delete(); >+ >+my $default_reservesallowed_rule = $rules_rs->create( >+ { >+ categorycode => undef, >+ itemtype => undef, >+ branchcode => undef, >+ rule_name => 'reservesallowed', >+ rule_value => 10, >+ } >+); >+ >+my $reservesallowed_rule = $rules_rs->create( >+ { >+ categorycode => $patron->categorycode, >+ itemtype => undef, >+ branchcode => $library->branchcode, >+ rule_name => 'reservesallowed', >+ rule_value => 0, >+ } >+); >+ >+my $can = CanBookBeReserved( $patron->borrowernumber, $biblio->biblionumber ); >+is( $can->{status}, '' ); >+is( scalar @{ $can->{circulation_rules} }, 0 ); >+is( scalar @{ $can->{item_responses} }, 1 ); >+is( $can->{item_responses}->[0]->{status}, 'noReservesAllowed' ); >+is( scalar @{ $can->{item_responses}->[0]->{circulation_rules} }, 1 ); >+is( $can->{item_responses}->[0]->{circulation_rules}->[0]->id, $reservesallowed_rule->id ); >+ >+my $holds_per_record_rule = $rules_rs->create( >+ { >+ categorycode => $patron->categorycode, >+ itemtype => undef, >+ branchcode => $library->branchcode, >+ rule_name => 'holds_per_record', >+ rule_value => 1, >+ } >+); >+ >+$can = CanBookBeReserved( $patron->borrowernumber, $biblio->biblionumber ); >+is( $can->{status}, '' ); >+is( scalar @{ $can->{circulation_rules} }, 0 ); >+is( scalar @{ $can->{item_responses} }, 1 ); >+is( $can->{item_responses}->[0]->{status}, 'noReservesAllowed' ); >+is( scalar @{ $can->{item_responses}->[0]->{circulation_rules} }, 2 ); >+is( $can->{item_responses}->[0]->{circulation_rules}->[0]->id, $holds_per_record_rule->id ); >+is( $can->{item_responses}->[0]->{circulation_rules}->[1]->id, $reservesallowed_rule->id ); >+ >+$schema->storage->txn_rollback; >-- >2.48.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 23732
:
95435
|
95436
|
95443
|
95444
|
95445
|
95934
|
147501
|
147504
|
173427
|
173428
|
178886
|
178887
|
178888
|
179026
|
179027