Bugzilla – Attachment 56229 Details for
Bug 15565
Place multiple item-level holds at once for the same record
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bz 15565 - Place multiple holds at once for the same record on staff and OPAC.
Bz-15565---Place-multiple-holds-at-once-for-the-sa.patch (text/plain), 37.65 KB, created by
Alex Arnaud
on 2016-10-12 08:17:01 UTC
(
hide
)
Description:
Bz 15565 - Place multiple holds at once for the same record on staff and OPAC.
Filename:
MIME Type:
Creator:
Alex Arnaud
Created:
2016-10-12 08:17:01 UTC
Size:
37.65 KB
patch
obsolete
>From 3ff64f520ac7c8cbd2e6447b2686caf6d6a947ff Mon Sep 17 00:00:00 2001 >From: Alex Arnaud <alex.arnaud@biblibre.com> >Date: Wed, 12 Oct 2016 07:02:19 +0000 >Subject: [PATCH] Bz 15565 - Place multiple holds at once for the same record > on staff and OPAC. > >--- > .../prog/en/modules/reserve/request.tt | 16 +- > .../opac-tmpl/bootstrap/en/modules/opac-reserve.tt | 188 ++++++++++----------- > koha-tmpl/opac-tmpl/bootstrap/less/opac.less | 3 + > opac/opac-reserve.pl | 183 +++++++++----------- > reserve/placerequest.pl | 34 ++-- > 5 files changed, 201 insertions(+), 223 deletions(-) > >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 12b4e1b..bae2d7b 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >@@ -25,6 +25,8 @@ var override_items = {[% FOREACH bibitemloo IN bibitemloop %][% FOREACH itemloo > [% END %][% END %][% END %] > }; > var MSG_NO_ITEMS_AVAILABLE = _("A hold cannot be requested on any of these items."); >+var MSG_EXCEEDED_HOLDS_PER_RECORD = _("Patron has exceeded the number of holds for this record."); >+var remainingHolds = "[% remaining_holds_for_record %]"; > > $(document).ready(function() { > function ToggleHoldsToPlace() { >@@ -149,17 +151,21 @@ function checkMultiHold() { > } > }); > $("input[name=checkitem]").click(function() { >- onechecked = 0; >+ numchecked = 0; > $("input[name=checkitem]").each(function() { > if(this.checked){ >- onechecked = 1; >+ numchecked = 1; > } > }); >- if(onechecked == 1){ >+ if(numchecked > 0){ > $("#requestany").prop("checked", false); > } else { > $("#requestany").prop("checked",true); > } >+ >+ if (remainingHolds - numchecked < 0) { >+ alert(MSG_EXCEEDED_HOLDS_PER_RECORD); >+ } > }); > > $(".clear-date").on("click",function(e){ >@@ -495,9 +501,9 @@ function checkMultiHold() { > Hold must be record level > </span> > [% ELSIF ( itemloo.available ) %] >- <input type="radio" name="checkitem" value="[% itemloo.itemnumber %]" /> >+ <input type="checkbox" name="checkitem" value="[% itemloo.itemnumber %]" /> > [% ELSIF ( itemloo.override ) %] >- <input type="radio" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" /> >+ <input type="checkbox" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" /> > <i class="fa fa-exclamation-triangle fa-lg" style="color:gold" alt="Requires override of hold policy"/></i> > [% ELSE %] > <span class="error"> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt >index c0dd300..750aa7d 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt >@@ -134,20 +134,18 @@ > <form action="/cgi-bin/koha/opac-reserve.pl" method="post" id="hold-request-form"> > <input type="hidden" name="place_reserve" value="1"/> > <!-- These values are set dynamically by js --> >- <input type="hidden" name="biblionumbers" id="biblionumbers"/> >- <input type="hidden" name="selecteditems" id="selections"/> > <div id="bigloop"> > > [% FOREACH bibitemloo IN bibitemloop %] > <div class="holdrow"> >+ <input id="remaining_holds_[% bibitemloo.biblionumber %]" type="hidden" value="[% bibitemloo.remaining_holds_for_record %]"/> > <p> > [% IF ( bibitemloo.holdable ) %] >- <input class="reserve_mode" name="reserve_mode" type="hidden" value="single"/> >- <input class="single_bib" name="single_bib" type="hidden" value="[% bibitemloo.biblionumber %]"/> >- <span class="confirmjs_hold" title="[% bibitemloo.biblionumber %]" style="padding:.3em"></span> >- <span class="confirm_nonjs"> >- <input type="radio" class="confirmbox checkitem [% bibitemloo.biblionumber %]" name="[% bibitemloo.biblionumber %]" checked="checked" id="single_[% bibitemloo.biblionumber %]" value="any" /> >- <label class="confirm_label" for="single_[% bibitemloo.biblionumber %]">Place a hold on </label> >+ <span title="[% bibitemloo.biblionumber %]" style="padding:.3em"> >+ <label> >+ <input class="biblionumbers" name="biblionumbers" type="checkbox" value="[% bibitemloo.biblionumber %]" checked="checked"> >+ Place a hold on >+ </label> > </span> > [% END # / bibitemloo.holdable %] > >@@ -214,11 +212,11 @@ > <li class="branch"> > <label for="branch_[% bibitemloo.biblionumber %]">Pick up location:</label> > [% UNLESS ( bibitemloo.holdable ) %] >- <select name="branch" id="branch_[% bibitemloo.biblionumber %]" disabled="disabled"> >+ <select name="branch_[% bibitemloo.biblionumber %]" id="branch_[% bibitemloo.biblionumber %]" disabled="disabled"> > [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %] > </select> > [% ELSE %] >- <select name="branch" id="branch_[% bibitemloo.biblionumber %]"> >+ <select name="branch_[% bibitemloo.biblionumber %]" id="branch_[% bibitemloo.biblionumber %]"> > [% PROCESS options_for_libraries libraries => Branches.all( selected => branch ) %] > </select> > [% END # / UNLESS bibitemloo.holdable %] >@@ -273,29 +271,39 @@ > </li> > [% END # / IF OpacHoldNotes %] > >- [% IF bibitemloo.itemholdable %] >- <!-- ITEM HOLDS --> >- <li class="lradio place_on_type" style="display:none;"> >- [% IF NOT bibitemloo.force_hold %] >- <label class="radio inline" for="reqany_[% bibitemloo.biblionumber %]">Next available item</label> >- <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]" >- id="reqany_[% bibitemloo.biblionumber %]" >- class="selectany" >- value="Any" >- checked="checked" >- /> >- [% END %] >- <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber %]">A specific item</label> >+ <!-- ITEM HOLDS --> >+ <li class="lradio place_on_type" style="display:none;"> >+ <label class="radio inline" for="reqany_[% bibitemloo.biblionumber %]">Next available item</label> > <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]" >- id="reqspecific_[% bibitemloo.biblionumber %]" >- class="selectspecific" >- value="Specific" >+ id="reqany_[% bibitemloo.biblionumber %]" >+ class="selectany" >+ value="Any" >+ checked="checked" > /> >- </li> >- [% END # / IF bibitemloo.itemholdable %] >+ <label class="radio inline" for="reqspecific_[% bibitemloo.biblionumber %]">A specific item</label> >+ <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]" >+ id="reqspecific_[% bibitemloo.biblionumber %]" >+ class="selectspecific" >+ value="Specific" >+ /> >+ </li> > </ul> > >- [% IF bibitemloo.itemholdable %] >+ [% IF bibitemloo.remaining_holds_for_record > 1 %] >+ [% SET count = 1 %] >+ <div id="holds_to_place_[% bibitemloo.biblionumber %]" class="hold-options holds-to-place"> >+ <label>Holds to place (count)</label> >+ <select name="holds_to_place_count_[% bibitemloo.biblionumber %]"> >+ [% WHILE count <= bibitemloo.remaining_holds_for_record %] >+ <option value="[% count %]">[% count %]</option> >+ [% SET count = count + 1 %] >+ [% END %] >+ </select> >+ </div> >+ [% ELSE %] >+ <input type="hidden" name="holds_to_place_count_[% bibitemloo.biblionumber %]" value="1" /> >+ [% END %] >+ > <table class="copiesrow table table-bordered table-striped" id="copiesrow_[% bibitemloo.biblionumber %]"> > <caption>Select a specific item:</caption> > <tr> >@@ -319,9 +327,9 @@ > <tr class="[% itemLoo.backgroundcolor %]"> > <td class="copynumber"> > [% IF ( itemLoo.available ) %] >- <input type="radio" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]" value="[% itemLoo.itemnumber %]" /> >+ <input type="checkbox" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]" value="[% itemLoo.itemnumber %]" /> > [% ELSE %] >- <input disabled="disabled" type="radio" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]" >+ <input disabled="disabled" type="checkbox" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]" > style="display:none;" /> > <img src="[% interface %]/lib/famfamfam/silk/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" /> > [% END %] >@@ -395,7 +403,6 @@ > </tr> > [% END # / FOREACH itemLoo IN bibitemloo.itemLoop%] > </table> <!-- / #copiesrow_[% bibitemloo.biblionumber %] --> >- [% END # / IF ( bibitemloo.itemholdable )%] > </div> <!-- / #hold-options-[% bibitemloo.biblionumber %] --> > </fieldset> > [% END # / IF ( bibitemloo.holdable ) %] >@@ -418,6 +425,7 @@ > <script type="text/javascript"> > // <![CDATA[ > var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection."); >+ var MSG_MAX_HOLDS_EXCEEDED = _("Maximum number of reserve exceded."); > var ForceHoldNotesReasons=new Array( > _("This title consists of multiple volumes/parts. Please indicate which part you need. Clicking on specific item information may be helpful."), > "*** Add a new reason above this line ***" ); >@@ -431,8 +439,8 @@ > > // Select the first item available > function select_first_available(id){ >- var radios = $("input:radio[name='checkitem_" + id + "']"); >- $(radios).first().attr("checked", "checked"); >+ var checkboxes = $("input:checkbox[name='checkitem_" + id + "']"); >+ $(checkboxes).first().attr("checked", "checked"); > } > > $(document).ready(function() { >@@ -453,14 +461,16 @@ > } > }); > >- // click on a first td check the confirmjs checkbox >- $("td.hold").click(function(e){ >- if(e.target.tagName.toLowerCase() == 'td'){ >- $(this).find("input.confirmjs").each( function() { >- $(this).attr('checked', !$(this).attr('checked')); >- $(this).change(); >- }); >- } >+ $('.checkitem').click(function(e) { >+ var bibNum = suffixOf($(this).attr("name"), "_"); >+ var nbCheked = $("input[name='checkitem_"+bibNum+"']:checked").length; >+ var remaining = $("input[id='remaining_holds_"+bibNum+"']").val(); >+ if (nbCheked >= remaining) { >+ $("input[name='checkitem_"+bibNum+"']:not(:checked)").attr('disabled', 'disabled'); >+ } >+ else { >+ $('.checkitem_'+bibNum).attr('disabled', false); >+ } > }); > > $(".toggle-hold-options").on("click",function(e){ >@@ -475,12 +485,21 @@ > // Hides all 'specific copy' table rows on load. > $(".copiesrow").hide(); > >+ $(".holds-to-place").show(); > [% FOREACH bibitemloo IN bibitemloop %] >- [% IF bibitemloo.force_hold %] >- $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click(); >- $("#reqspecific_[% bibitemloo.biblionumber %]").click(); >- $("#copiesrow_[% bibitemloo.biblionumber %]").show(); >- [% END %] >+ [% IF bibitemloo.force_hold %] >+ [% IF bibitemloo.force_hold == 'item' %] >+ $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click(); >+ $("#reqspecific_[% bibitemloo.biblionumber %]").attr('checked', true); >+ $("#holds_to_place_[% bibitemloo.biblionumber %]").hide(); >+ $("#copiesrow_[% bibitemloo.biblionumber %]").show(); >+ [% ELSIF bibitemloo.force_hold == 'record' %] >+ $("#toggle-hold-options-[% bibitemloo.biblionumber %]").click(); >+ $("#reqany_[% bibitemloo.biblionumber %]").attr('checked', true); >+ [% END %] >+ $("#reqany_[% bibitemloo.biblionumber %]").attr('disabled', 'disabled'); >+ $("#reqspecific_[% bibitemloo.biblionumber %]").attr('disabled', 'disabled'); >+ [% END %] > [% END %] > > // Insert reasons for forced hold notes >@@ -506,40 +525,37 @@ > $("#" + op + fieldID).val(""); > }); > >- // Replace non-JS single-selection with multi-selection capability. >- $(".reserve_mode").val("multi"); >- $(".confirm_nonjs").remove(); >- $(".confirmjs_hold").each(function(){ >- var bib = $(this).attr("title"); >- var html = "<label><input type =\"checkbox\" class=\"confirmjs\" checked=\"checked\""; >- html += "value=\"" + bib + "\" id=\"" + bib + "\" /> " + _("Place a hold on") + " </label> "; >- $(this).html(html); >- }); >- $(".confirmjs_nohold").each(function(){ >- var bib = $(this).attr("title"); >- var html = "<label><input type =\"checkbox\" class=\"confirmjs\" disabled=\"disabled\""; >- html += "value=\"" + bib + "\" id=\"" + bib + "\" />" + _("Place a hold on: ") + "</label>"; >- $(this).html(html); >- }); >- > // expand or collapse the copiesrow tr > function toggle_copiesrow(biblioNum) { > var checkbox = $("input:checkbox[value='"+biblioNum+"']"); > newCopiesRowId = "#copiesrow_" + biblioNum; >+ holdsToPlaceCountId = "#holds_to_place_" + biblioNum; > var select_specific = $("#reqspecific_"+biblioNum).is(":checked"); > // If the checkbox is checked AND we want a specific item, we display the items block > if ( $(checkbox).is(":checked") && select_specific ) { > $(newCopiesRowId).show(); >+ $(holdsToPlaceCountId).hide(); > } else { > $(newCopiesRowId).hide(); >+ $(holdsToPlaceCountId).show(); > } > }; > >- $("#place_on_hdr").show(); >+ function total_requested() { >+ var total = 0; >+ $("input[name='biblionumbers']:checked").each(function() { >+ var biblioNum = $(this).val(); >+ if ($("#reqspecific_" + biblioNum + ":checked").size() > 0) { >+ total += parseInt($("input[name='checkitem_'"+biblioNum+"]:checked").length); >+ } else { >+ total += parseInt($("select[name='holds_to_place_count_"+biblioNum+"']").val()); >+ } >+ }); >+ return total; >+ } > > $(".place_on_type").show(); > // onload, selectany is checked >- $(".selectany").attr("checked", "checked"); > > // If the user is *allowed* to choose a specific item > // The first one is preselected >@@ -548,8 +564,8 @@ > select_first_available(id); > }); > >- // On confirmsjs change >- $(".confirmjs").change(function(){ >+ // On biblionumbers change >+ $(".biblionumbers").change(function(){ > var id = suffixOf($(this).attr("id"), "_"); > // If I m checked, I enable radio buttons > if ( $(this).is(":checked") ) { >@@ -571,35 +587,22 @@ > toggle_copiesrow(id); > }); > >- // Show or hide holds notes >- $(".shownotes").click(function(){ >- biblioNum = suffixOf($(this).attr("id"), "_"); >- $("#notesrow_"+biblioNum).toggle(); >- }); >- > // When 'Place Hold' button is clicked > $(".placehold").click(function(){ >- var biblionumbers = ""; >- var selections = ""; >- >- [% IF new_reserves_allowed %] >- if ($(".confirmjs:checked").size() > [% new_reserves_allowed %] ) { >- alert(MSG_MAX_HOLDS_EXCEEDED); >- return false; >- } >- [% END %] >+ if (total_requested() + [% reserves_count %] > [% maxreserves %]) { >+ alert(MSG_MAX_HOLDS_EXCEEDED); >+ return false; >+ } > >- if ($(".confirmjs:checked").size() == 0) { >+ if ($("input[name='biblionumbers']:checked").size() == 0) { > alert(MSG_NO_RECORD_SELECTED); > return false; > } > > // Find the items with the 'Hold' box checked > var badBib = null; >- $(".confirmjs:checked").each(function() { >+ $("input[name='biblionumbers']:checked").each(function() { > var biblioNum = $(this).val(); >- biblionumbers += biblioNum + "/"; >- selections += biblioNum + "/"; > > // If the 'specific copy' radio button is checked > if ($("#reqspecific_" + biblioNum + ":checked").size() > 0) { >@@ -608,18 +611,8 @@ > if ($(item).size() == 0) { > badBib = biblioNum; > return false; >- } else { >- selections += $(item).val(); > } > } >- selections += "/"; >- >- // Add the pickup location >- var branchSel = $("#branch_" + biblioNum); >- if (branchSel.size() > 0) { >- selections += $(branchSel).val(); >- } >- selections += "/"; > return true; > }); > >@@ -628,9 +621,6 @@ > return false; > } > >- $("#selections").val(selections); >- $("#biblionumbers").val(biblionumbers); >- > return true; > }); > >diff --git a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less b/koha-tmpl/opac-tmpl/bootstrap/less/opac.less >index 0bd32b4..4df2f01 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less >+++ b/koha-tmpl/opac-tmpl/bootstrap/less/opac.less >@@ -2370,6 +2370,9 @@ td img { > margin: 1em 0; > padding: .5em; > } >+.hold-option select { >+ width: auto; >+} > .copiesrow { > clear : both; > } >diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl >index d02e96c..43fbbe9 100755 >--- a/opac/opac-reserve.pl >+++ b/opac/opac-reserve.pl >@@ -90,34 +90,19 @@ if ($borr->{reservefee} > 0){ > > my $itemTypes = GetItemTypes(); > >-# There are two ways of calling this script, with a single biblio num >-# or multiple biblio nums. >-my $biblionumbers = $query->param('biblionumbers'); >-my $reserveMode = $query->param('reserve_mode'); >-if ($reserveMode && ($reserveMode eq 'single')) { >- my $bib = $query->param('single_bib'); >- $biblionumbers = "$bib/"; >-} >-if (! $biblionumbers) { >- $biblionumbers = $query->param('biblionumber'); >-} >- >-if ((! $biblionumbers) && (! $query->param('place_reserve'))) { >- $template->param(message=>1, no_biblionumber=>1); >- &get_out($query, $cookie, $template->output); >+# Coming from opac-search biblionumbers param is a string, coming from >+# opac-reserve, it's an array. >+my @biblionumbers = ref($query->param('biblionumbers')) eq 'Array' >+ ? $query->param('biblionumbers') >+ : split(/\//, $query->param('biblionumbers')); >+ >+unless (@biblionumbers) { >+ push(@biblionumbers, $query->param('biblionumber')); > } > > # Pass the numbers to the page so they can be fed back > # when the hold is confirmed. TODO: Not necessary? >-$template->param( biblionumbers => $biblionumbers ); >- >-# Each biblio number is suffixed with '/', e.g. "1/2/3/" >-my @biblionumbers = split /\//, $biblionumbers; >-if (($#biblionumbers < 0) && (! $query->param('place_reserve'))) { >- # TODO: New message? >- $template->param(message=>1, no_biblionumber=>1); >- &get_out($query, $cookie, $template->output); >-} >+$template->param( biblionumbers => @biblionumbers ); > > > # pass the pickup branch along.... >@@ -189,39 +174,22 @@ if ( $query->param('place_reserve') ) { > $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber ); > } > >- # List is composed of alternating biblio/item/branch >- my $selectedItems = $query->param('selecteditems'); >- >- if ($query->param('reserve_mode') eq 'single') { >- # This indicates non-JavaScript mode, so there was >- # only a single biblio number selected. >- my $bib = $query->param('single_bib'); >- my $item = $query->param("checkitem_$bib"); >- if ($item eq 'any') { >- $item = ''; >- } >- my $branch = $query->param('branch'); >- $selectedItems = "$bib/$item/$branch/"; >- } >- >- $selectedItems =~ s!/$!!; >- my @selectedItems = split /\//, $selectedItems, -1; >- >- # Make sure there is a biblionum/itemnum/branch triplet for each item. >- # The itemnum can be 'any', meaning next available. >- my $selectionCount = @selectedItems; >- if (($selectionCount == 0) || (($selectionCount % 3) != 0)) { >- $template->param(message=>1, bad_data=>1); >- &get_out($query, $cookie, $template->output); >- } >- > my $failed_holds = 0; >- while (@selectedItems) { >- my $biblioNum = shift(@selectedItems); >- my $itemNum = shift(@selectedItems); >- my $branch = shift(@selectedItems); # i.e., branch code, not name >- >- my $canreserve = 0; >+ foreach my $biblioNum (@biblionumbers) { >+ my $itemNum = $query->param("checkitem_$biblioNum"); >+ my @itemnumbers = $query->param("checkitem_$biblioNum"); >+ my $branch = $query->param("branch_$biblioNum"); >+ my $reqtype = $query->param("reqtype_$biblioNum"); >+ my $holds_to_place_count = $query->param("holds_to_place_count_$biblioNum") || 1; >+ my $notes = $query->param('notes_'.$biblioNum) || ''; >+ my $nbRequested = $reqtype eq 'Specific' ? @itemnumbers : $holds_to_place_count; >+ >+ my $canreserve = 1; >+ if ( $maxreserves >+ && $reserve_cnt + $nbRequested >= $maxreserves ) >+ { >+ $canreserve = 0; >+ } > > my $singleBranchMode = Koha::Libraries->search->count == 1; > if ( $singleBranchMode || !$OPACChooseBranch ) >@@ -229,14 +197,6 @@ if ( $query->param('place_reserve') ) { > $branch = $borr->{'branchcode'}; > } > >-#item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber >- if ( $itemNum ne '' ) { >- my $hostbiblioNum = GetBiblionumberFromItemnumber($itemNum); >- if ( $hostbiblioNum ne $biblioNum ) { >- $biblioNum = $hostbiblioNum; >- } >- } >- > my $biblioData = $biblioDataHash{$biblioNum}; > my $found; > >@@ -250,45 +210,60 @@ if ( $query->param('place_reserve') ) { > > my $expiration_date = $query->param("expiration_date_$biblioNum"); > >- # If a specific item was selected and the pickup branch is the same as the >- # holdingbranch, force the value $rank and $found. >+ # If a specific item was selected and the pickup branch is the same as the >+ # holdingbranch, force the value $rank and $found. > my $rank = $biblioData->{rank}; >- if ( $itemNum ne '' ) { >- $canreserve = 1 if CanItemBeReserved( $borrowernumber, $itemNum ) eq 'OK'; >- $rank = '0' unless C4::Context->preference('ReservesNeedReturns'); >- my $item = GetItem($itemNum); >- if ( $item->{'holdingbranch'} eq $branch ) { >- $found = 'W' >- unless C4::Context->preference('ReservesNeedReturns'); >+ if ( $reqtype eq 'Specific') { >+ foreach my $itemnumber (@itemnumbers) { >+ my $biblionumber = $biblioNum; >+ >+ #item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber >+ my $hostbiblioNum = GetBiblionumberFromItemnumber($itemnumber); >+ if ( $hostbiblioNum ne $biblioNum ) { >+ $biblionumber = $hostbiblioNum; >+ } >+ >+ $canreserve = 0 unless CanItemBeReserved( $borrowernumber, $itemnumber ) eq 'OK'; >+ $rank = '0' unless C4::Context->preference('ReservesNeedReturns'); >+ my $item = GetItem($itemnumber); >+ if ( $item->{'holdingbranch'} eq $branch ) { >+ $found = 'W' >+ unless C4::Context->preference('ReservesNeedReturns'); >+ } >+ >+ if ($canreserve) { >+ my $reserve_id = AddReserve( >+ $branch, $borrowernumber, >+ $biblionumber, >+ [$biblionumber], $rank, >+ $startdate, $expiration_date, >+ $notes, $biblioData->{title}, >+ $itemnumber, $found >+ ); >+ $failed_holds++ unless $reserve_id; >+ ++$reserve_cnt; >+ } > } >+ print $query->redirect("/cgi-bin/koha/opac-user.pl?" . ( $failed_holds ? "failed_holds=$failed_holds" : q|| ) . "#opac-user-holds"); >+ exit; > } >- else { >- $canreserve = 1 if CanBookBeReserved( $borrowernumber, $biblioNum ) eq 'OK'; >- >- # Inserts a null into the 'itemnumber' field of 'reserves' table. >- $itemNum = undef; >- } >- my $notes = $query->param('notes_'.$biblioNum)||''; >- >- if ( $maxreserves >- && $reserve_cnt >= $maxreserves ) >- { >- $canreserve = 0; >- } >+ $canreserve = 0 unless CanBookBeReserved( $borrowernumber, $biblioNum ) eq 'OK'; > > my $itemtype = $query->param('itemtype') || undef; > $itemtype = undef if $itemNum; > > # Here we actually do the reserveration. Stage 3. > if ($canreserve) { >- my $reserve_id = AddReserve( >- $branch, $borrowernumber, $biblioNum, >- [$biblioNum], $rank, $startdate, >- $expiration_date, $notes, $biblioData->{title}, >- $itemNum, $found, $itemtype, >- ); >- $failed_holds++ unless $reserve_id; >- ++$reserve_cnt; >+ for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) { >+ my $reserve_id = AddReserve( >+ $branch, $borrowernumber, $biblioNum, >+ [$biblioNum], $rank, $startdate, >+ $expiration_date, $notes, $biblioData->{title}, >+ $itemNum, $found, $itemtype, >+ ); >+ $failed_holds++ unless $reserve_id; >+ ++$reserve_cnt; >+ } > } > } > >@@ -347,6 +322,10 @@ if ( $maxreserves && ( $reserves_count >= $maxreserves ) ) { > } > > unless ( $noreserves ) { >+ $template->param( >+ maxreserves => $maxreserves, >+ reserves_count => $reserves_count >+ ); > my $requested_reserves_count = scalar( @biblionumbers ); > if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) { > $template->param( new_reserves_allowed => $maxreserves - $reserves_count ); >@@ -514,7 +493,7 @@ foreach my $biblioNum (@biblionumbers) { > if ( my $hold_allowed = OPACItemHoldsAllowed( $itemInfo, $borr ) ) { > $itemLoopIter->{available} = 1; > $numCopiesOPACAvailable++; >- $biblioLoopIter{force_hold} = 1 if $hold_allowed eq 'F'; >+ $biblioLoopIter{force_hold} = 'item' if $hold_allowed eq 'F'; > } > $numCopiesAvailable++; > } >@@ -552,18 +531,24 @@ foreach my $biblioNum (@biblionumbers) { > # patron placed a record level hold, all the holds the patron places must > # be record level. If the patron placed an item level hold, all holds > # the patron places must be item level >- my $forced_hold_level = Koha::Holds->search( >+ my $holds = Koha::Holds->search( > { > borrowernumber => $borrowernumber, > biblionumber => $biblioNum, > found => undef, > } >- )->forced_hold_level(); >+ ); >+ my $forced_hold_level = $holds->forced_hold_level(); > if ($forced_hold_level) { >- $biblioLoopIter{force_hold} = 1 if $forced_hold_level eq 'item'; >- $biblioLoopIter{itemholdable} = 0 if $forced_hold_level eq 'record'; >+ #$biblioLoopIter{force_hold} = 1 if $forced_hold_level eq 'item'; >+ #$biblioLoopIter{itemholdable} = 0 if $forced_hold_level eq 'record'; >+ $biblioLoopIter{force_hold} = $forced_hold_level; > } > >+ my $max_holds_for_record = GetMaxPatronHoldsForRecord( $borrowernumber, $biblioNum ); >+ my $remaining_holds_for_record = $max_holds_for_record - $holds->count(); >+ $biblioLoopIter{remaining_holds_for_record} = $remaining_holds_for_record; >+ > > push @$biblioLoop, \%biblioLoopIter; > >diff --git a/reserve/placerequest.pl b/reserve/placerequest.pl >index 92f3c48..db07ff0 100755 >--- a/reserve/placerequest.pl >+++ b/reserve/placerequest.pl >@@ -47,7 +47,7 @@ my $startdate = $input->param('reserve_date') || ''; > my @rank = $input->multi_param('rank-request'); > my $type = $input->param('type'); > my $title = $input->param('title'); >-my $checkitem = $input->param('checkitem'); >+my @checkitems = $input->param('checkitem'); > my $expirationdate = $input->param('expiration_date'); > my $itemtype = $input->param('itemtype') || undef; > >@@ -57,6 +57,7 @@ my $multi_hold = $input->param('multi_hold'); > my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/'); > my $bad_bibs = $input->param('bad_bibs'); > my $holds_to_place_count = $input->param('holds_to_place_count') || 1; >+$holds_to_place_count = scalar(@checkitems) if scalar(@checkitems); > > my %bibinfos = (); > my @biblionumbers = split '/', $biblionumbers; >@@ -67,17 +68,15 @@ foreach my $bibnum (@biblionumbers) { > $bibinfos{$bibnum} = \%bibinfo; > } > >-my $found; >+my @found; > >-# if we have an item selectionned, and the pickup branch is the same as the holdingbranch >-# of the document, we force the value $rank and $found . >-if (defined $checkitem && $checkitem ne ''){ >- $holds_to_place_count = 1; >+foreach my $checkitem (@checkitems) { >+ # if we have an item selectionned, and the pickup branch is the same as the holdingbranch >+ # of the document, we force the value $rank and $found . > $rank[0] = '0' unless C4::Context->preference('ReservesNeedReturns'); >- my $item = $checkitem; >- $item = GetItem($item); >+ my $item = GetItem($checkitem); > if ( $item->{'holdingbranch'} eq $branch ){ >- $found = 'W' unless C4::Context->preference('ReservesNeedReturns'); >+ push @found, 'W' unless C4::Context->preference('ReservesNeedReturns'); > } > } > >@@ -97,23 +96,18 @@ if ( $type eq 'str8' && $borrower ) { > } > } > >- if ( defined $checkitem && $checkitem ne '' ) { >- my $item = GetItem($checkitem); >- if ( $item->{'biblionumber'} ne $biblionumber ) { >- $biblionumber = $item->{'biblionumber'}; >- } >- } >- > if ($multi_hold) { > my $bibinfo = $bibinfos{$biblionumber}; >- AddReserve($branch,$borrower->{'borrowernumber'},$biblionumber,[$biblionumber], >- $bibinfo->{rank},$startdate,$expirationdate,$notes,$bibinfo->{title},$checkitem,$found); >+ AddReserve( $branch, $borrower->{'borrowernumber'}, >+ $biblionumber, [$biblionumber], >+ $bibinfo->{rank}, $startdate, $expirationdate, $notes,$bibinfo->{title}); > } else { > # place a request on 1st available > for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) { >+ my $item = GetItem($checkitems[$i]); > AddReserve( $branch, $borrower->{'borrowernumber'}, >- $biblionumber, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, >- $checkitem, $found, $itemtype ); >+ $item->{biblionumber}, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, >+ $checkitems[$i], $found[$i] ); > } > } > } >-- >2.7.4
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 15565
:
47527
|
47551
|
47552
|
50068
|
50069
|
50392
|
50393
|
56229
|
56230
|
56231
|
56232
|
56458
|
56510
|
56511
|
56512
|
56513
|
56514
|
56515
|
56517
|
56518
|
56519
|
56520
|
56521
|
56522
|
56523
|
56524
|
61244
|
61245
|
61246
|
61247
|
61248
|
61576
|
61577
|
61578
|
61579
|
61580
|
64590
|
64591
|
64592
|
64593
|
64594
|
66594
|
66595
|
66596
|
66597
|
66598
|
68759
|
68760
|
68761
|
68762
|
68763
|
71643
|
71644
|
71645
|
71646
|
71647
|
71648
|
72644
|
72645
|
72646
|
72647
|
72648
|
72649
|
78242
|
78243
|
78244
|
78245
|
78246
|
78247
|
78248
|
78266
|
78305
|
78417
|
78418
|
78419
|
78420
|
78421
|
78422
|
78423
|
78424
|
78425
|
78426
|
78712
|
78713
|
78714
|
78715
|
78716
|
78717
|
78718
|
78719
|
78720
|
78815
|
78816
|
78817
|
78818
|
78819
|
78820
|
78821
|
78822
|
78823
|
81419
|
81420
|
81421
|
81422
|
81423
|
81424
|
81425
|
81426
|
81427
|
81431
|
81449
|
81570
|
81571
|
81572
|
81573
|
81574
|
81575
|
81576
|
81577
|
81578
|
81579
|
81580
|
81581
|
82205
|
82206
|
82207
|
82208
|
82209
|
82210
|
82211
|
82212
|
82213
|
82214
|
82215
|
82216
|
82220
|
82221
|
83331
|
83332
|
83333
|
83334
|
83335
|
83336
|
83337
|
83338
|
83339
|
83340
|
83341
|
83342
|
83378
|
83380
|
83381
|
84541
|
84542
|
84543
|
84544
|
84545
|
84546
|
84547
|
84548
|
84549
|
84550
|
84551
|
84552
|
84553
|
87979
|
87980
|
87981
|
87982
|
87983
|
87984
|
87985
|
87986
|
87987
|
87988
|
87989
|
87990
|
87991
|
117128
|
117129
|
117130
|
117131
|
117132
|
117133
|
120365
|
120366
|
120367
|
120639
|
120640
|
120641
|
121941
|
122098
|
162071
|
162072
|
162073
|
162074
|
163052
|
163053
|
163054
|
163055
|
163092
|
163093
|
166005
|
166006
|
166007
|
166008
|
166009