@@ -, +, @@
of titles
--- a/C4/Reserves.pm
+++ a/C4/Reserves.pm
@@ -141,6 +141,10 @@ BEGIN {
&GetReservesControlBranch
IsItemOnHoldAndFound
+
+ AddReserveGroup
+ DeleteReserveGroup
+ GetReserveGroupReserves
);
@EXPORT_OK = qw( MergeHolds );
}
@@ -165,7 +169,8 @@ sub AddReserve {
my (
$branch, $borrowernumber, $biblionumber, $bibitems,
$priority, $resdate, $expdate, $notes,
- $title, $checkitem, $found, $itemtype
+ $title, $checkitem, $found, $itemtype,
+ $reserve_group_id
) = @_;
if ( Koha::Holds->search( { borrowernumber => $borrowernumber, biblionumber => $biblionumber } )->count() > 0 ) {
@@ -210,6 +215,7 @@ sub AddReserve {
waitingdate => $waitingdate,
expirationdate => $expdate,
itemtype => $itemtype,
+ reserve_group_id => $reserve_group_id,
}
)->store();
my $reserve_id = $hold->id();
@@ -1348,6 +1354,17 @@ sub ModReserveAffect {
}
$sth = $dbh->prepare($query);
$sth->execute( $itemnumber, $borrowernumber,$biblionumber);
+
+ if ($request->{reserve_group_id}) {
+ # Delete other reserves from same group
+ $dbh->do(q{
+ DELETE FROM reserves
+ WHERE reserve_group_id = ?
+ AND reserve_id != ?
+ }, undef, $request->{reserve_group_id}, $request->{reserve_id});
+ DeleteReserveGroup($request->{reserve_group_id});
+ }
+
_koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ) if ( !$transferToDo && !$already_on_shelf );
_FixPriority( { biblionumber => $biblionumber } );
if ( C4::Context->preference("ReturnToShelvingCart") ) {
@@ -1427,6 +1444,7 @@ sub GetReserveInfo {
reminderdate,
priority,
found,
+ reserve_group_id,
firstname,
surname,
phone,
@@ -2482,6 +2500,60 @@ sub IsItemOnHoldAndFound {
return $found;
}
+=head2 AddReserveGroup
+
+ my $reserve_group_id = AddReserveGroup();
+
+Creates a new reserve group and returns its ID
+
+=cut
+
+sub AddReserveGroup {
+ my $dbh = C4::Context->dbh;
+
+ $dbh->do('INSERT INTO reserve_group VALUES ()');
+ return $dbh->last_insert_id(undef, undef, 'reserve_group', undef);
+}
+
+=head2 DeleteReserveGroup
+
+ DeleteReserveGroup($reserve_group_id);
+
+Delete a reserve group. Reserves that belong to this group are not removed.
+
+=cut
+
+sub DeleteReserveGroup {
+ my ($reserve_group_id) = @_;
+
+ my $dbh = C4::Context->dbh;
+ my $query = 'DELETE FROM reserve_group WHERE reserve_group_id = ?';
+ $dbh->do($query, undef, $reserve_group_id);
+}
+
+=head2 GetReserveGroupReserves
+
+ my @reserves = GetReserveGroupReserves($reserve_group_id);
+
+Fetch all reserve from a reserve group.
+
+=cut
+
+sub GetReserveGroupReserves {
+ my ($reserve_group_id) = @_;
+
+ my $dbh = C4::Context->dbh;
+
+ my $reserves = $dbh->selectall_arrayref(q{
+ SELECT * FROM reserves
+ WHERE reserve_group_id = ?
+ }, { Slice => {} }, $reserve_group_id);
+
+ return () unless defined $reserves;
+
+ return @$reserves;
+}
+
=head1 AUTHOR
Koha Development Team
--- a/Koha/Template/Plugin/Biblio.pm
+++ a/Koha/Template/Plugin/Biblio.pm
@@ -32,4 +32,12 @@ sub HoldsCount {
return $holds->count();
}
+sub Get {
+ my ($self, $biblionumber) = @_;
+
+ my $biblio = Koha::Biblios->find($biblionumber);
+
+ return $biblio;
+}
+
1;
--- a/circ/pendingreserves.pl
+++ a/circ/pendingreserves.pl
@@ -118,6 +118,7 @@ if ( $run_report ) {
reminderdate,
max(priority) as priority,
reserves.found,
+ reserves.reserve_group_id,
biblio.title,
biblio.author,
count(DISTINCT items.itemnumber) as icount,
@@ -167,7 +168,8 @@ if ( $run_report ) {
biblionumber => $data->{biblionumber},
statusw => ( $data->{found} eq "W" ),
statusf => ( $data->{found} eq "F" ),
- holdingbranches => [split('\|', $data->{l_holdingbranch})],,
+ reserve_group_id => $data->{reserve_group_id},
+ holdingbranches => [split('\|', $data->{l_holdingbranch})],
branch => $data->{l_branch},
itemcallnumber => $data->{l_itemcallnumber},
enumchron => $data->{l_enumchron},
--- a/installer/data/mysql/atomicupdate/bug_15516.sql
+++ a/installer/data/mysql/atomicupdate/bug_15516.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS reserve_group;
+CREATE TABLE reserve_group (
+ reserve_group_id int unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (reserve_group_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+ALTER TABLE reserves ADD COLUMN reserve_group_id int unsigned NULL DEFAULT NULL;
+ALTER TABLE reserves ADD CONSTRAINT reserves_ibfk_6 FOREIGN KEY (reserve_group_id) REFERENCES reserve_group (reserve_group_id) ON DELETE SET NULL ON UPDATE CASCADE;
--- a/installer/data/mysql/kohastructure.sql
+++ a/installer/data/mysql/kohastructure.sql
@@ -1864,6 +1864,7 @@ CREATE TABLE `reserves` ( -- information related to holds/reserves in Koha
`suspend` BOOLEAN NOT NULL DEFAULT 0,
`suspend_until` DATETIME NULL DEFAULT NULL,
`itemtype` VARCHAR(10) NULL DEFAULT NULL, -- If record level hold, the optional itemtype of the item the patron is requesting
+ `reserve_group_id` int unsigned NULL DEFAULT NULL, -- Id used on reservations spanning multiple titles
PRIMARY KEY (`reserve_id`),
KEY priorityfoundidx (priority,found),
KEY `borrowernumber` (`borrowernumber`),
@@ -1875,7 +1876,18 @@ CREATE TABLE `reserves` ( -- information related to holds/reserves in Koha
CONSTRAINT `reserves_ibfk_2` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `reserves_ibfk_3` FOREIGN KEY (`itemnumber`) REFERENCES `items` (`itemnumber`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `reserves_ibfk_4` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`) ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT `reserves_ibfk_5` FOREIGN KEY (`itemtype`) REFERENCES `itemtypes` (`itemtype`) ON DELETE CASCADE ON UPDATE CASCADE
+ CONSTRAINT `reserves_ibfk_5` FOREIGN KEY (`itemtype`) REFERENCES `itemtypes` (`itemtype`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `reserves_ibfk_6` FOREIGN KEY (`reserve_group_id`) REFERENCES `reserve_group` (`reserve_group_id`) ON DELETE SET NULL ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+--
+-- Table structure for table reserve_group
+--
+
+DROP TABLE IF EXISTS `reserve_group`;
+CREATE TABLE `reserve_group` (
+ `reserve_group_id` int unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY(`reserve_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/reserve-group-modal.inc
+++ a/koha-tmpl/intranet-tmpl/prog/en/includes/reserve-group-modal.inc
@@ -0,0 +1,27 @@
+
+
+
+
Reserve group
+
+
+
Loading
+
+
+
+
+
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc
+++ a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc
@@ -39,5 +39,7 @@
var SUSPEND_HOLD_ERROR_DATE = _("Unable to suspend hold, invalid date");
var SUSPEND_HOLD_ERROR_NOT_FOUND = _("Unable to suspend hold, hold not found");
var RESUME_HOLD_ERROR_NOT_FOUND = _("Unable to resume, hold not found");
+ var PART_OF_A = _("(part of a %s)");
+ var RESERVE_GROUP = _("reserve group");
//]]>
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
@@ -979,4 +979,5 @@ No patron matched [% message %]
You have already submitted a barcode, please wait for the checkout to process...
+[% INCLUDE 'reserve-group-modal.inc' %]
[% INCLUDE 'intranet-bottom.inc' %]
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt
@@ -112,10 +112,16 @@ $(document).ready(function() {
+ [% END %]
+ [% INCLUDE 'intranet-bottom.inc' %]
--- a/koha-tmpl/intranet-tmpl/prog/js/holds.js
+++ a/koha-tmpl/intranet-tmpl/prog/js/holds.js
@@ -42,6 +42,12 @@ $(document).ready(function() {
title += " - " + oObj.itemnotes + ""
}
+ if (oObj.reserve_group_id) {
+ title += ' ';
+ var link = '' + RESERVE_GROUP +''
+ title += '' + PART_OF_A.format(link) + '';
+ }
+
return title;
}
},
--- a/reserve/placerequest.pl
+++ a/reserve/placerequest.pl
@@ -50,6 +50,7 @@ my $title = $input->param('title');
my $checkitem = $input->param('checkitem');
my $expirationdate = $input->param('expiration_date');
my $itemtype = $input->param('itemtype') || undef;
+my $requestany = $input->param('requestany');
my $borrower = GetMember( 'borrowernumber' => $borrowernumber );
@@ -81,6 +82,11 @@ if (defined $checkitem && $checkitem ne ''){
if ($type eq 'str8' && $borrower){
+ my $reserve_group_id;
+ if ($multi_hold && $requestany) {
+ $reserve_group_id = AddReserveGroup();
+ }
+
foreach my $biblionumber (keys %bibinfos) {
my $count=@bibitems;
@bibitems=sort @bibitems;
@@ -106,8 +112,10 @@ if ($type eq 'str8' && $borrower){
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}, $checkitem, $found,
+ $reserve_group_id);
} else {
# place a request on 1st available
AddReserve($branch,$borrower->{'borrowernumber'},$biblionumber,\@realbi,$rank[0],$startdate,$expirationdate,$notes,$title,$checkitem,$found, $itemtype);
--- a/reserve/request.pl
+++ a/reserve/request.pl
@@ -568,6 +568,7 @@ foreach my $biblionumber (@biblionumbers) {
$reserve{'suspend_until'} = $res->suspend_until();
$reserve{'reserve_id'} = $res->reserve_id();
$reserve{itemtype} = $res->itemtype();
+ $reserve{'reserve_group_id'} = $res->reserve_group_id;
if ( C4::Context->preference('IndependentBranches') && $flags->{'superlibrarian'} != 1 ) {
$reserve{'branchloop'} = [ Koha::Libraries->find( $res->branchcode() ) ];
--- a/reserve/reserve-group.pl
+++ a/reserve/reserve-group.pl
@@ -0,0 +1,42 @@
+#!/usr/bin/env perl
+
+# 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 .
+
+use Modern::Perl;
+use CGI qw( -utf8 );
+
+use C4::Auth;
+use C4::Output;
+use C4::Reserves;
+
+my $cgi = new CGI;
+my ($template, $loggedinuser, $cookie) = get_template_and_user({
+ template_name => "reserve/reserve-group.tt",
+ query => $cgi,
+ type => "intranet",
+ authnotrequired => 0,
+ flagsrequired => { circulate => 'circulate_remaining_permissions' },
+});
+
+my $reserve_group_id = $cgi->param('reserve_group_id');
+my @reserves = GetReserveGroupReserves($reserve_group_id);
+
+$template->param(
+ reserve_group_id => $reserve_group_id,
+ reserves => \@reserves,
+);
+
+output_html_with_http_headers $cgi, $cookie, $template->output;
--- a/svc/holds
+++ a/svc/holds
@@ -96,6 +96,7 @@ while ( my $h = $holds_rs->next() ) {
waiting_here => $h->branch()->branchcode() eq $branch,
priority => $h->priority(),
itemtype_limit => $itemtype_limit,
+ reserve_group_id => $h->reserve_group_id,
subtitle => GetRecordValue(
'subtitle', GetMarcBiblio($biblionumber),
GetFrameworkCode($biblionumber)
--