Bugzilla – Attachment 27429 Details for
Bug 7710
multiple holds per title
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 7710 - multiple holds per title
Bug-7710---multiple-holds-per-title.patch (text/plain), 15.83 KB, created by
Kyle M Hall (khall)
on 2014-04-22 17:31:36 UTC
(
hide
)
Description:
Bug 7710 - multiple holds per title
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2014-04-22 17:31:36 UTC
Size:
15.83 KB
patch
obsolete
>From a471128088ec9db1476802370e76edde672f873c Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >Date: Wed, 22 May 2013 14:56:31 -0400 >Subject: [PATCH] Bug 7710 - multiple holds per title > >Adds the ability to allow multiple holds >on the same record for the same borrower. > >Adds new system preference MaxHoldsPerRecord, >which controls how many holds one person can >have on items for the same record. > >Test Plan: >1) Apply patch for Bug 9394 >2) Apply this patch >3) Run updatedatabase.pl >4) Attempt to place 2 holds for the same patron on the same record, > you should not be able to ( default is 1 per record ) >5) Set MaxHoldsPerRecord to 3 >6) Attempt to place multiple holds for one patron on one record, > you should be able to place 3 holds for one patron on a given > record. A 4th hold should result in a message stating the > patron has placed the max number of holds allowed on this record. > >Signed-off-by: Maxime Pelletier <maxime.pelletier@libeo.com> >--- > C4/Reserves.pm | 59 ++++++++++++-------- > installer/data/mysql/sysprefs.sql | 2 +- > installer/data/mysql/updatedatabase.pl | 7 ++ > .../en/modules/admin/preferences/circulation.pref | 7 ++- > .../prog/en/modules/reserve/request.tt | 4 +- > .../opac-tmpl/prog/en/modules/opac-reserve.tt | 2 + > opac/opac-reserve.pl | 30 ++++++---- > reserve/request.pl | 19 +++++-- > 8 files changed, 86 insertions(+), 44 deletions(-) > >diff --git a/C4/Reserves.pm b/C4/Reserves.pm >index 49f8c11..82bdaf1 100644 >--- a/C4/Reserves.pm >+++ b/C4/Reserves.pm >@@ -397,36 +397,47 @@ sub GetReservesFromItemnumber { > > =head2 GetReservesFromBorrowernumber > >- $borrowerreserv = GetReservesFromBorrowernumber($borrowernumber,$tatus); >- >-TODO :: Descritpion >+ $borrowerreserv = GetReservesFromBorrowernumber($borrowernumber[,$status][,$biblionumber][,$itemnumber]); > > =cut > > sub GetReservesFromBorrowernumber { >- my ( $borrowernumber, $status ) = @_; >- my $dbh = C4::Context->dbh; >- my $sth; >- if ($status) { >- $sth = $dbh->prepare(" >- SELECT * >- FROM reserves >- WHERE borrowernumber=? >- AND found =? >- ORDER BY reservedate >- "); >- $sth->execute($borrowernumber,$status); >- } else { >- $sth = $dbh->prepare(" >- SELECT * >- FROM reserves >- WHERE borrowernumber=? >- ORDER BY reservedate >- "); >- $sth->execute($borrowernumber); >+ my ( $borrowernumber, $found, $biblionumber, $itemnumber ) = @_; >+ >+ my @params; >+ >+ my $sql = "SELECT * FROM reserves WHERE borrowernumber = ?"; >+ push( @params, $borrowernumber ); >+ >+ if ( $biblionumber ) { >+ $sql .= " AND biblionumber = ? "; >+ push( @params, $biblionumber ); >+ } >+ >+ if ( $itemnumber ) { >+ $sql .= " AND itemnumber = ? "; >+ push( @params, $itemnumber ); > } >+ >+ if ( $found ) { >+ $sql .= " AND found = ? "; >+ push( @params, $found ); >+ } >+ >+ $sql .= " ORDER BY reservedate "; >+ >+ my $dbh = C4::Context->dbh; >+ my $sth = $dbh->prepare( $sql ); >+ >+ $sth->execute( @params ); >+ > my $data = $sth->fetchall_arrayref({}); >- return @$data; >+ >+ if ( scalar @$data ) { >+ return @$data; >+ } else { >+ return (); >+ } > } > #------------------------------------------------------------------------------------- > =head2 CanBookBeReserved >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index 05a0031..60a0fda 100644 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -179,6 +179,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` > ('MARCAuthorityControlField008','|| aca||aabn | a|a d',NULL,'Define the contents of MARC21 authority control field 008 position 06-39','Textarea'), > ('MARCOrgCode','OSt','','Define MARC Organization Code for MARC21 records - http://www.loc.gov/marc/organizations/orgshome.html','free'), > ('MaxFine',NULL,'','Maximum fine a patron can have for all late returns at one moment. Single item caps are specified in the circulation rules matrix.','Integer'), >+('MaxHoldsPerRecord', '1', 'The maximum number of holds allowed per bibliographic record per borrower', 'Integer'), > ('MaxItemsForBatch','1000',NULL,'Max number of items record to process in a batch (modification or deletion)','Integer'), > ('maxItemsInSearchResults','20',NULL,'Specify the maximum number of items to display for each result on a page of results','free'), > ('maxoutstanding','5','','maximum amount withstanding to be able make holds','Integer'), >@@ -428,7 +429,6 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` > ('XISBN','0','','Use with FRBRizeEditions. If ON, Koha will use the OCLC xISBN web service in the Editions tab on the detail pages. See: http://www.worldcat.org/affiliate/webservices/xisbn/app.jsp','YesNo'), > ('XISBNDailyLimit','999','','The xISBN Web service is free for non-commercial use when usage does not exceed 1000 requests per day','Integer'), > ('XSLTDetailsDisplay','default','','Enable XSL stylesheet control over details page display on intranet','Free'), >-('XSLTResultsDisplay','default','','Enable XSL stylesheet control over results page display on intranet','Free'), > ('yuipath','local','local|http://yui.yahooapis.com/2.5.1/build','Insert the path to YUI libraries, choose local if you use koha offline','Choice'), > ('z3950AuthorAuthFields','701,702,700',NULL,'Define the MARC biblio fields for Personal Name Authorities to fill biblio.author','free'), > ('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo') >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index 8917081..c345ffe 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -8202,6 +8202,13 @@ if ( CheckVersion($DBversion) ) { > SetVersion($DBversion); > } > >+$DBversion = "3.15.00.XXX"; >+if (C4::Context->preference("Version") < TransformToNum($DBversion)) { >+ $dbh->do("INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('MaxHoldsPerRecord', '1', 'The maximum number of holds allowed per bibliographic record per borrower', NULL, 'Integer')"); >+ print "Upgrade to $DBversion done (Bug 7710 - multiple holds per title)\n"; >+ SetVersion ($DBversion); >+} >+ > =head1 FUNCTIONS > > =head2 TableExists($table) >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >index 6282c0f..fb6a487 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >@@ -447,7 +447,12 @@ Circulation: > - Patrons can only have > - pref: maxreserves > class: integer >- - holds at once. >+ - total holds at a time. >+ - >+ - Patrons can only place >+ - pref: MaxHoldsPerRecord >+ class: integer >+ - holds on a single record at a time. > - > - pref: emailLibrarianWhenHoldIsPlaced > choices: >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 3494655..0c46c31 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >@@ -62,7 +62,7 @@ function check() { > } > > if (alreadyreserved > "0"){ >- msg += (_("- This patron had already placed a hold on this item") + "\n" + _("Please cancel the previous hold first") + "\n"); >+ msg += (_("This patron has already placed the maximum number of holds for this record.") + "\n\n" + _("Please cancel a previous hold first.") + "\n"); > } > > if (msg == "") return(true); >@@ -247,7 +247,7 @@ function checkMultiHold() { > <li><strong>Too many holds: </strong> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %] </a> has too many holds.</li> > [% END %] > [% IF ( alreadyreserved ) %] >- <li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>already has a hold</strong> on this item </li> >+ <li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>has already placed the maximum allowed number of holds</strong> on this record</li> > [% END %] > [% IF ( none_available ) %] > <li> <strong>No items are available</strong> to be placed on hold</li> >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt >index 0932d20..2e95292 100644 >--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt >@@ -330,6 +330,8 @@ > [% ELSE %] > [% IF ( bibitemloo.already_patron_possession ) %] > <div class="bibmessage">This title cannot be requested because it's already in your possession.</div> >+ [% ELSIF bibitemloo.max_holds %] >+ <div class="bibmessage">This title cannot be requested. You have already placed the maximum number of requests allowed for this title.</div> > [% ELSE %] > <div class="bibmessage">This title cannot be requested.</div> > [% END %] >diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl >index 473ead8..8c4c917 100755 >--- a/opac/opac-reserve.pl >+++ b/opac/opac-reserve.pl >@@ -37,7 +37,8 @@ use C4::Debug; > use Koha::DateUtils; > # use Data::Dumper; > >-my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves"); >+my $maxreserves = C4::Context->preference("maxreserves"); >+my $max_holds_per_record = C4::Context->preference('MaxHoldsPerRecord'); > > my $query = new CGI; > my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >@@ -171,7 +172,7 @@ foreach my $biblioNumber (@biblionumbers) { > # > if ( $query->param('place_reserve') ) { > my $reserve_cnt = 0; >- if ($MAXIMUM_NUMBER_OF_RESERVES) { >+ if ($maxreserves) { > $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber ); > } > >@@ -255,8 +256,8 @@ if ( $query->param('place_reserve') ) { > } > my $notes = $query->param('notes_'.$biblioNum)||''; > >- if ( $MAXIMUM_NUMBER_OF_RESERVES >- && $reserve_cnt >= $MAXIMUM_NUMBER_OF_RESERVES ) >+ if ( $maxreserves >+ && $reserve_cnt >= $maxreserves ) > { > $canreserve = 0; > } >@@ -317,7 +318,7 @@ if ( $borr->{'debarred'} ) { > > my @reserves = GetReservesFromBorrowernumber( $borrowernumber ); > $template->param( RESERVES => \@reserves ); >-if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES) ) { >+if ( $maxreserves && (scalar(@reserves) >= $maxreserves) ) { > $template->param( message => 1 ); > $noreserves = 1; > $template->param( too_many_reserves => scalar(@reserves)); >@@ -325,12 +326,10 @@ if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RES > foreach my $res (@reserves) { > foreach my $biblionumber (@biblionumbers) { > if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) { >-# $template->param( message => 1 ); >-# $noreserves = 1; >-# $template->param( already_reserved => 1 ); >- $biblioDataHash{$biblionumber}->{already_reserved} = 1; >+ $biblioDataHash{$biblionumber}->{holds_count}++; > } > } >+ > } > > unless ($noreserves) { >@@ -374,6 +373,7 @@ foreach my $biblioNum (@biblionumbers) { > $biblioLoopIter{reservecount} = $biblioData->{reservecount}; > $biblioLoopIter{already_reserved} = $biblioData->{already_reserved}; > $biblioLoopIter{mandatorynotes}=0; #FIXME: For future use >+ $biblioLoopIter{holds_count} = $biblioData->{holds_count}; > > if (!$itemLevelTypes && $biblioData->{itemtype}) { > $biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description}; >@@ -502,14 +502,17 @@ foreach my $biblioNum (@biblionumbers) { > $policy_holdallowed = 0; > } > >- if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{already_reserved} ne 1)) { >+ if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{holds_count} < $max_holds_per_record )) { > $itemLoopIter->{available} = 1; > $numCopiesAvailable++; > } > > $itemLoopIter->{imageurl} = getitemtypeimagelocation( 'opac', $itemTypes->{ $itemInfo->{itype} }{imageurl} ); > >- # Show serial enumeration when needed >+ # Don't allow multiple item level holds on the same item if borrowers can place multiple holds on one bib >+ $itemLoopIter->{available} = 0 if ( GetReservesFromBorrowernumber( $borrowernumber, undef, undef, $itemNum ) ); >+ >+ # Show serial enumeration when needed > if ($itemLoopIter->{enumchron}) { > $itemdata_enumchron = 1; > } >@@ -526,6 +529,11 @@ foreach my $biblioNum (@biblionumbers) { > if ($biblioLoopIter{already_reserved}) { > $biblioLoopIter{holdable} = undef; > } >+ if ($biblioLoopIter{holds_count} >= $max_holds_per_record) { >+ $biblioLoopIter{holdable} = undef; >+ $anyholdable = undef; >+ $biblioLoopIter{max_holds} = 1; >+ } > if(not CanBookBeReserved($borrowernumber,$biblioNum)){ > $biblioLoopIter{holdable} = undef; > } >diff --git a/reserve/request.pl b/reserve/request.pl >index 1b303c7..a553c57 100755 >--- a/reserve/request.pl >+++ b/reserve/request.pl >@@ -169,6 +169,7 @@ $template->param( messageborrower => $messageborrower ); > > # FIXME launch another time GetMember perhaps until > my $borrowerinfo = GetMember( borrowernumber => $borrowernumber_hold ); >+my $max_holds_per_record = C4::Context->preference('MaxHoldsPerRecord'); > > my @biblionumbers = (); > my $biblionumbers = $input->param('biblionumbers'); >@@ -212,15 +213,17 @@ foreach my $biblionumber (@biblionumbers) { > } > } > >- if ( $holds_count ) { >- $alreadyreserved = 1; >- $biblioloopiter{warn} = 1; >- $biblioloopiter{alreadyres} = 1; >+ if ( $holds_count > $max_holds_per_record ) { >+ $alreadyreserved = 1; >+ $biblioloopiter{warn} = 1; >+ $biblioloopiter{alreadyres} = 1; >+ $biblioloopiter{maxreserves} = $max_holds_per_record; > } > > $template->param( >- alreadyreserved => $alreadyreserved, >+ alreadyreserved => $alreadyreserved, > alreadypossession => $alreadypossession, >+ maxreserves => $maxreserves, > ); > > # FIXME think @optionloop, is maybe obsolete, or must be switchable by a systeme preference fixed rank or not >@@ -430,6 +433,12 @@ foreach my $biblionumber (@biblionumbers) { > $itemdata_enumchron = 1; > } > >+ # Don't allow multiple item level holds on the same item if borrowers can place multiple holds on one bib >+ if ( GetReservesFromBorrowernumber( $borrowerinfo->{borrowernumber}, undef, undef, $itemnumber) ) { >+ $item->{available} = 0; >+ $item->{override} = 0; >+ } >+ > push @{ $biblioitem->{itemloop} }, $item; > } > >-- >1.7.2.5
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 7710
:
8598
|
8599
|
8600
|
8601
|
8602
|
8603
|
10091
|
10098
|
10099
|
10100
|
10101
|
10102
|
10818
|
10897
|
12620
|
14083
|
14600
|
14602
|
14603
|
15252
|
15253
|
15295
|
15731
|
15732
|
17448
|
18217
|
18320
|
18321
|
19117
|
27429
|
30218
|
35397
|
35518