View | Details | Raw Unified | Return to bug 7710
Collapse All | Expand All

(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 406-408 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES(' Link Here
406
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('NotesBlacklist','','List of notes fields that should not appear in the title notes/description separator of details',NULL,'free');
406
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('NotesBlacklist','','List of notes fields that should not appear in the title notes/description separator of details',NULL,'free');
407
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('SCOUserCSS', '', NULL, 'Add CSS to be included in the SCO module in an embedded <style> tag.', 'free');
407
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('SCOUserCSS', '', NULL, 'Add CSS to be included in the SCO module in an embedded <style> tag.', 'free');
408
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('SCOUserJS', '', NULL, 'Define custom javascript for inclusion in the SCO module', 'free');
408
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('SCOUserJS', '', NULL, 'Define custom javascript for inclusion in the SCO module', 'free');
409
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('MaxHoldsPerRecord', '1', 'The maximum number of holds allowed per bibliographic record per borrower', NULL, NULL);
(-)a/installer/data/mysql/updatedatabase.pl (+7 lines)
Lines 6339-6344 if ( CheckVersion($DBversion) ) { Link Here
6339
   SetVersion ($DBversion);
6339
   SetVersion ($DBversion);
6340
}
6340
}
6341
6341
6342
$DBversion = "3.11.00.XXX";
6343
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
6344
    $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, NULL)");
6345
    print "Upgrade to $DBversion done (Add syspref MaxHoldsPerRecord)\n";
6346
    SetVersion ($DBversion);
6347
}
6348
6342
=head1 FUNCTIONS
6349
=head1 FUNCTIONS
6343
6350
6344
=head2 TableExists($table)
6351
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (-1 / +6 lines)
Lines 392-398 Circulation: Link Here
392
            - Patrons can only have
392
            - Patrons can only have
393
            - pref: maxreserves
393
            - pref: maxreserves
394
              class: integer
394
              class: integer
395
            - holds at once.
395
            - total holds at a time.
396
        -
397
            - Patrons can only place
398
            - pref: MaxHoldsPerRecord
399
              class: integer
400
            - holds on a single record at a time.
396
        -
401
        -
397
            - pref: emailLibrarianWhenHoldIsPlaced
402
            - pref: emailLibrarianWhenHoldIsPlaced
398
              choices:
403
              choices:
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-12 / +13 lines)
Lines 55-61 function check() { Link Here
55
    }
55
    }
56
56
57
    if (alreadyreserved > "0"){
57
    if (alreadyreserved > "0"){
58
		msg += (_("- This patron had already placed a hold on this item") + "\n" + _("Please cancel the previous hold first") + "\n");
58
         msg += (_("This patron has already placed the maximum number of holds for this record") + "\n" + _("Please cancel a previous hold first") + "\n");
59
    }
59
    }
60
60
61
	if (msg == "") return(true);
61
	if (msg == "") return(true);
Lines 208-214 function checkMultiHold() { Link Here
208
          <li><strong>Too Many Holds: </strong> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %] </a> has too many holds.</li>
208
          <li><strong>Too Many Holds: </strong> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %] </a> has too many holds.</li>
209
        [% END %]
209
        [% END %]
210
        [% IF ( alreadyreserved ) %]
210
        [% IF ( alreadyreserved ) %]
211
          <li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>already has a hold</strong> on this item </li>
211
          <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>
212
        [% END %]
212
        [% END %]
213
        [% IF ( none_available ) %]
213
        [% IF ( none_available ) %]
214
          <li> <strong>No copies are available</strong> to be placed on hold</li>
214
          <li> <strong>No copies are available</strong> to be placed on hold</li>
Lines 556-561 function checkMultiHold() { Link Here
556
  [% FOREACH reserveloo IN biblioloo.reserveloop %]
556
  [% FOREACH reserveloo IN biblioloo.reserveloop %]
557
  [% UNLESS ( loop.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
557
  [% UNLESS ( loop.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
558
        <td>
558
        <td>
559
          <input type="hidden" name="reserve_id" value="[% reserveloo.reserve_id %]" />
559
          <input type="hidden" name="borrowernumber" value="[% reserveloo.borrowernumber %]" />
560
          <input type="hidden" name="borrowernumber" value="[% reserveloo.borrowernumber %]" />
560
          <input type="hidden" name="biblionumber" value="[% reserveloo.biblionumber %]" />
561
          <input type="hidden" name="biblionumber" value="[% reserveloo.biblionumber %]" />
561
          <select name="rank-request">
562
          <select name="rank-request">
Lines 575-593 function checkMultiHold() { Link Here
575
576
576
     [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
577
     [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
577
        <td style="white-space:nowrap;">
578
        <td style="white-space:nowrap;">
578
	        <a title="Move Hold Up" href="request.pl?action=move&amp;where=up&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;date=[% reserveloo.date %]">
579
            <a title="Move Hold Up" href="request.pl?action=move&amp;where=up&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;reserve_id=[% reserveloo.reserve_id %]&amp;date=[% reserveloo.date %]">
579
            <img src="/intranet-tmpl/[% theme %]/img/go-up.png" border="0" alt="Go up" />
580
            <img src="/intranet-tmpl/[% theme %]/img/go-up.png" border="0" alt="Go up" />
580
                </a>
581
                </a>
581
582
582
        <a title="Move hold to top" href="request.pl?action=move&amp;where=top&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;date=[% reserveloo.date %]">
583
                <a title="Move Hold To Top" href="request.pl?action=move&amp;where=top&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;reserve_id=[% reserveloo.reserve_id %]&amp;date=[% reserveloo.date %]">
583
                    <img src="/intranet-tmpl/[% theme %]/img/go-top.png" border="0" alt="Go top" />
584
                    <img src="/intranet-tmpl/[% theme %]/img/go-top.png" border="0" alt="Go top" />
584
                </a>
585
                </a>
585
586
586
                <a title="Move hold to bottom" href="request.pl?action=move&amp;where=bottom&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;date=[% reserveloo.date %]">
587
                <a title="Move Hold To Bottom" href="request.pl?action=move&amp;where=bottom&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;reserve_id=[% reserveloo.reserve_id %]&amp;date=[% reserveloo.date %]">
587
                    <img src="/intranet-tmpl/[% theme %]/img/go-bottom.png" border="0" alt="Go bottom" />
588
                    <img src="/intranet-tmpl/[% theme %]/img/go-bottom.png" border="0" alt="Go bottom" />
588
                </a>
589
                </a>
589
590
590
                <a title="Move hold down" href="request.pl?action=move&amp;where=down&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;date=[% reserveloo.date %]">
591
                <a title="Move Hold Down" href="request.pl?action=move&amp;where=down&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;reserve_id=[% reserveloo.reserve_id %]&amp;date=[% reserveloo.date %]">
591
                    <img src="/intranet-tmpl/[% theme %]/img/go-down.png" border="0" alt="Go down" />
592
                    <img src="/intranet-tmpl/[% theme %]/img/go-down.png" border="0" alt="Go down" />
592
                </a>
593
                </a>
593
        </td>
594
        </td>
Lines 667-673 function checkMultiHold() { Link Here
667
668
668
    [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
669
    [% IF ( CAN_user_reserveforothers_modify_holds_priority ) %]
669
	<td>
670
	<td>
670
        <a title="Toggle lowest priority" href="request.pl?action=setLowestPriority&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;date=[% reserveloo.date %]">
671
                <a title="Toggle Lowest Priority" href="request.pl?action=setLowestPriority&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;reserve_id=[% reserveloo.reserve_id %]&amp;date=[% reserveloo.date %]">
671
			[% IF ( reserveloo.lowestPriority ) %]
672
			[% IF ( reserveloo.lowestPriority ) %]
672
                        <img src="/intranet-tmpl/[% theme %]/img/go-bottom.png" border="0" alt="Unset Lowest Priority" />
673
                        <img src="/intranet-tmpl/[% theme %]/img/go-bottom.png" border="0" alt="Unset Lowest Priority" />
673
		        [% ELSE %]
674
		        [% ELSE %]
Lines 678-684 function checkMultiHold() { Link Here
678
    [% END %]
679
    [% END %]
679
680
680
	<td>
681
	<td>
681
        <a title="Cancel hold" href="request.pl?action=cancel&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;date=[% reserveloo.date %]">
682
           <a title="Cancel Hold" href="request.pl?action=cancel&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;reserve_id=[% reserveloo.reserve_id %]&amp;date=[% reserveloo.date %]">
682
                    <img src="/intranet-tmpl/[% theme %]/img/x.png" border="0" alt="Cancel" />
683
                    <img src="/intranet-tmpl/[% theme %]/img/x.png" border="0" alt="Cancel" />
683
                </a>
684
                </a>
684
	</td>
685
	</td>
Lines 686-697 function checkMultiHold() { Link Here
686
        [% IF SuspendHoldsIntranet %]
687
        [% IF SuspendHoldsIntranet %]
687
	<td>
688
	<td>
688
	[% UNLESS ( reserveloo.wait ) %]
689
	[% UNLESS ( reserveloo.wait ) %]
689
            <input type="button" value="[% IF ( reserveloo.suspend ) %]Unsuspend[% ELSE %]Suspend[% END %]" onclick="window.location.href='request.pl?action=toggleSuspend&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;date=[% reserveloo.date %]&amp;suspend_until=' + $('#suspend_until_[% reserveloo.borrowernumber %]').val()" />
690
            <input type="button" value="[% IF ( reserveloo.suspend ) %]Unsuspend[% ELSE %]Suspend[% END %]" onclick="window.location.href='request.pl?action=toggleSuspend&amp;reserve_id=[% reserveloo.reserve_id %]&amp;borrowernumber=[% reserveloo.borrowernumber %]&amp;biblionumber=[% reserveloo.biblionumber %]&amp;date=[% reserveloo.date %]&amp;suspend_until=' + $('#suspend_until_[% reserveloo.reserve_id %]').val()" />
690
691
691
            [% IF AutoResumeSuspendedHolds %]
692
            [% IF AutoResumeSuspendedHolds %]
692
	    <label for="suspend_until_[% reserveloo.borrowernumber %]">[% IF ( reserveloo.suspend ) %] on [% ELSE %] until [% END %]</label>
693
        <label for="suspend_until_[% reserveloo.reserve_id %]">[% IF ( reserveloo.suspend ) %] on [% ELSE %] until [% END %]</label>
693
        <input name="suspend_until" id="suspend_until_[% reserveloo.borrowernumber %]" size="10" readonly="readonly" value="[% reserveloo.suspend_until | $KohaDates %]" class="datepicker" />
694
            <input name="suspend_until" id="suspend_until_[% reserveloo.reserve_id %]" size="10" readonly="readonly" value="[% reserveloo.suspend_until | $KohaDates %]" class="datepicker" />
694
	    <a href='#' onclick="document.getElementById('suspend_until_[% reserveloo.borrowernumber %]').value='';">Clear Date</a>
695
            <a href='#' onclick="document.getElementById('suspend_until_[% reserveloo.reserve_id %]').value='';">Clear Date</a>
695
            [% END %]
696
            [% END %]
696
	[% ELSE %]
697
	[% ELSE %]
697
		<input type="hidden" name="suspend_until" value="" />
698
		<input type="hidden" name="suspend_until" value="" />
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt (-1 / +1 lines)
Lines 409-415 $.tablesorter.addParser({ Link Here
409
		[% IF ( RESERVE.cancelable ) %]
409
		[% IF ( RESERVE.cancelable ) %]
410
			<form action="/cgi-bin/koha/opac-modrequest.pl" method="post">
410
			<form action="/cgi-bin/koha/opac-modrequest.pl" method="post">
411
			<input type="hidden" name="biblionumber" value="[% RESERVE.biblionumber %]" />
411
			<input type="hidden" name="biblionumber" value="[% RESERVE.biblionumber %]" />
412
		<input type="hidden" name="reservenumber" value="[% RESERVE.reservenumber %]" />
412
                  <input type="hidden" name="reservenumber" value="[% RESERVE.reservenumber %]" />
413
			<input type="submit" name="submit" class="icon delete cancel" value="Cancel" onclick="return confirmDelete('Are you sure you want to cancel this hold?');" /></form>
413
			<input type="submit" name="submit" class="icon delete cancel" value="Cancel" onclick="return confirmDelete('Are you sure you want to cancel this hold?');" /></form>
414
		[% ELSE %]
414
		[% ELSE %]
415
		[% END %]
415
		[% END %]
(-)a/opac/opac-reserve.pl (-12 / +14 lines)
Lines 37-43 use C4::Debug; Link Here
37
use Koha::DateUtils;
37
use Koha::DateUtils;
38
# use Data::Dumper;
38
# use Data::Dumper;
39
39
40
my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves");
40
my $maxreserves = C4::Context->preference("maxreserves");
41
my $max_holds_per_record = C4::Context->preference('MaxHoldsPerRecord');
41
42
42
my $query = new CGI;
43
my $query = new CGI;
43
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
44
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
Lines 173-179 foreach my $biblioNumber (@biblionumbers) { Link Here
173
if ( $query->param('place_reserve') ) {
174
if ( $query->param('place_reserve') ) {
174
    my $notes = $query->param('notes');
175
    my $notes = $query->param('notes');
175
    my $reserve_cnt = 0;
176
    my $reserve_cnt = 0;
176
    if ($MAXIMUM_NUMBER_OF_RESERVES) {
177
    if ($maxreserves) {
177
        $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber );
178
        $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber );
178
    }
179
    }
179
180
Lines 256-263 if ( $query->param('place_reserve') ) { Link Here
256
            $itemNum = undef;
257
            $itemNum = undef;
257
        }
258
        }
258
259
259
        if (   $MAXIMUM_NUMBER_OF_RESERVES
260
        if (   $maxreserves
260
            && $reserve_cnt >= $MAXIMUM_NUMBER_OF_RESERVES )
261
            && $reserve_cnt >= $maxreserves )
261
        {
262
        {
262
            $canreserve = 0;
263
            $canreserve = 0;
263
        }
264
        }
Lines 318-324 if ( CheckBorrowerDebarred($borrowernumber) ) { Link Here
318
319
319
my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
320
my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
320
$template->param( RESERVES => \@reserves );
321
$template->param( RESERVES => \@reserves );
321
if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES) ) {
322
if ( $maxreserves && (scalar(@reserves) >= $maxreserves) ) {
322
    $template->param( message => 1 );
323
    $template->param( message => 1 );
323
    $noreserves = 1;
324
    $noreserves = 1;
324
    $template->param( too_many_reserves => scalar(@reserves));
325
    $template->param( too_many_reserves => scalar(@reserves));
Lines 326-337 if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RES Link Here
326
foreach my $res (@reserves) {
327
foreach my $res (@reserves) {
327
    foreach my $biblionumber (@biblionumbers) {
328
    foreach my $biblionumber (@biblionumbers) {
328
        if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) {
329
        if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) {
329
#            $template->param( message => 1 );
330
            $biblioDataHash{$biblionumber}->{holds_count}++;
330
#            $noreserves = 1;
331
#            $template->param( already_reserved => 1 );
332
            $biblioDataHash{$biblionumber}->{already_reserved} = 1;
333
        }
331
        }
334
    }
332
    }
333
335
}
334
}
336
335
337
unless ($noreserves) {
336
unless ($noreserves) {
Lines 373-379 foreach my $biblioNum (@biblionumbers) { Link Here
373
    $biblioLoopIter{author} = $biblioData->{author};
372
    $biblioLoopIter{author} = $biblioData->{author};
374
    $biblioLoopIter{rank} = $biblioData->{rank};
373
    $biblioLoopIter{rank} = $biblioData->{rank};
375
    $biblioLoopIter{reservecount} = $biblioData->{reservecount};
374
    $biblioLoopIter{reservecount} = $biblioData->{reservecount};
376
    $biblioLoopIter{already_reserved} = $biblioData->{already_reserved};
375
    $biblioLoopIter{holds_count} = $biblioData->{holds_count};
377
376
378
    if (!$itemLevelTypes && $biblioData->{itemtype}) {
377
    if (!$itemLevelTypes && $biblioData->{itemtype}) {
379
        $biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description};
378
        $biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description};
Lines 500-506 foreach my $biblioNum (@biblionumbers) { Link Here
500
            $policy_holdallowed = 0;
499
            $policy_holdallowed = 0;
501
        }
500
        }
502
501
503
        if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{already_reserved} ne 1)) {
502
        if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{holds_count} < $max_holds_per_record )) {
504
            $itemLoopIter->{available} = 1;
503
            $itemLoopIter->{available} = 1;
505
            $numCopiesAvailable++;
504
            $numCopiesAvailable++;
506
        }
505
        }
Lines 533-538 foreach my $biblioNum (@biblionumbers) { Link Here
533
        $biblioLoopIter{holdable} = undef;
532
        $biblioLoopIter{holdable} = undef;
534
        $anyholdable = undef;
533
        $anyholdable = undef;
535
    }
534
    }
535
    if ($biblioLoopIter{holds_count} >= $max_holds_per_record) {
536
        $biblioLoopIter{holdable} = undef;
537
        $anyholdable = undef;
538
    }
536
    if(not CanBookBeReserved($borrowernumber,$biblioNum)){
539
    if(not CanBookBeReserved($borrowernumber,$biblioNum)){
537
        $biblioLoopIter{holdable} = undef;
540
        $biblioLoopIter{holdable} = undef;
538
        $anyholdable = undef;
541
        $anyholdable = undef;
539
- 

Return to bug 7710