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

(-)a/C4/Reserves.pm (-24 / +35 lines)
Lines 373-408 sub GetReservesFromItemnumber { Link Here
373
373
374
=head2 GetReservesFromBorrowernumber
374
=head2 GetReservesFromBorrowernumber
375
375
376
    $borrowerreserv = GetReservesFromBorrowernumber($borrowernumber,$tatus);
376
    $borrowerreserv = GetReservesFromBorrowernumber($borrowernumber[,$status][,$biblionumber][,$itemnumber]);
377
378
TODO :: Descritpion
379
377
380
=cut
378
=cut
381
379
382
sub GetReservesFromBorrowernumber {
380
sub GetReservesFromBorrowernumber {
383
    my ( $borrowernumber, $status ) = @_;
381
    my ( $borrowernumber, $found, $biblionumber, $itemnumber ) = @_;
384
    my $dbh   = C4::Context->dbh;
382
385
    my $sth;
383
    my @params;
386
    if ($status) {
384
387
        $sth = $dbh->prepare("
385
    my $sql = "SELECT * FROM reserves WHERE borrowernumber = ?";
388
            SELECT *
386
    push( @params, $borrowernumber );
389
            FROM   reserves
387
390
            WHERE  borrowernumber=?
388
    if ( $biblionumber ) {
391
                AND found =?
389
        $sql .= " AND biblionumber = ? ";
392
            ORDER BY reservedate
390
        push( @params, $biblionumber );
393
        ");
391
    }
394
        $sth->execute($borrowernumber,$status);
392
395
    } else {
393
    if ( $itemnumber ) {
396
        $sth = $dbh->prepare("
394
        $sql .= " AND itemnumber = ? ";
397
            SELECT *
395
        push( @params, $itemnumber );
398
            FROM   reserves
396
    }
399
            WHERE  borrowernumber=?
397
400
            ORDER BY reservedate
398
    if ( $found ) {
401
        ");
399
        $sql .= " AND found = ? ";
402
        $sth->execute($borrowernumber);
400
        push( @params, $found );
403
    }
401
    }
402
403
    $sql .= " ORDER BY reservedate ";
404
405
    my $dbh = C4::Context->dbh;
406
    my $sth = $dbh->prepare( $sql );
407
408
    $sth->execute( @params );
409
404
    my $data = $sth->fetchall_arrayref({});
410
    my $data = $sth->fetchall_arrayref({});
405
    return @$data;
411
412
    if ( scalar @$data ) {
413
        return @$data;
414
    } else {
415
        return ();
416
    }
406
}
417
}
407
#-------------------------------------------------------------------------------------
418
#-------------------------------------------------------------------------------------
408
=head2 CanBookBeReserved
419
=head2 CanBookBeReserved
(-)a/installer/data/mysql/sysprefs.sql (+2 lines)
Lines 424-426 INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES(' Link Here
424
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('HighlightOwnItemsOnOPAC','0','','If on, and a patron is logged into the OPAC, items from his or her home library will be emphasized and shown first in search results and item details.','YesNo');
424
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('HighlightOwnItemsOnOPAC','0','','If on, and a patron is logged into the OPAC, items from his or her home library will be emphasized and shown first in search results and item details.','YesNo');
425
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('HighlightOwnItemsOnOPACWhich','PatronBranch','PatronBranch|OpacURLBranch','Decides which branch''s items to emphasize. If PatronBranch, emphasize the logged in user''s library''s items. If OpacURLBranch, highlight the items of the Apache var BRANCHCODE defined in Koha''s Apache configuration file.','Choice');
425
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('HighlightOwnItemsOnOPACWhich','PatronBranch','PatronBranch|OpacURLBranch','Decides which branch''s items to emphasize. If PatronBranch, emphasize the logged in user''s library''s items. If OpacURLBranch, highlight the items of the Apache var BRANCHCODE defined in Koha''s Apache configuration file.','Choice');
426
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('UniqueItemFields', 'barcode', 'Space-separated list of fields that should be unique (used in acquisition module for item creation). Fields must be valid SQL column names of items table', '', 'Free');
426
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('UniqueItemFields', 'barcode', 'Space-separated list of fields that should be unique (used in acquisition module for item creation). Fields must be valid SQL column names of items table', '', 'Free');
427
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('HighlightOwnItemsOnOPACWhich','PatronBranch','PatronBranch|OpacURLBranch','Decides which branch''s items to emphasize. If PatronBranch, emphasize the logged in user''s library''s items. If OpacURLBranch, highlight the items of the Apache var BRANCHCODE defined in Koha''s Apache configuration file.','Choice')
428
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 6834-6839 if (C4::Context->preference("Version") < TransformToNum($DBversion)) { Link Here
6834
    SetVersion($DBversion);
6834
    SetVersion($DBversion);
6835
}
6835
}
6836
6836
6837
$DBversion = "3.11.00.XXX";
6838
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
6839
    $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)");
6840
    print "Upgrade to $DBversion done (Add syspref MaxHoldsPerRecord)\n";
6841
    SetVersion ($DBversion);
6842
}
6843
6837
=head1 FUNCTIONS
6844
=head1 FUNCTIONS
6838
6845
6839
=head2 TableExists($table)
6846
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (-1 / +6 lines)
Lines 404-410 Circulation: Link Here
404
            - Patrons can only have
404
            - Patrons can only have
405
            - pref: maxreserves
405
            - pref: maxreserves
406
              class: integer
406
              class: integer
407
            - holds at once.
407
            - total holds at a time.
408
        -
409
            - Patrons can only place
410
            - pref: MaxHoldsPerRecord
411
              class: integer
412
            - holds on a single record at a time.
408
        -
413
        -
409
            - pref: emailLibrarianWhenHoldIsPlaced
414
            - pref: emailLibrarianWhenHoldIsPlaced
410
              choices:
415
              choices:
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-2 / +2 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\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>
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt (-1 / +5 lines)
Lines 296-302 Link Here
296
                            [% IF ( bibitemloo.already_patron_possession ) %]
296
                            [% IF ( bibitemloo.already_patron_possession ) %]
297
                                <div class="bibmessage">This title cannot be requested because it's already in your possession.</div>
297
                                <div class="bibmessage">This title cannot be requested because it's already in your possession.</div>
298
                            [% ELSE %]
298
                            [% ELSE %]
299
                                <div class="bibmessage">This title cannot be requested.</div>
299
                                [% IF bibitemloo.max_holds %]
300
                                    <div class="bibmessage">This title cannot be requested. You have already placed the maximum number of requests allowed for this title.</div>
301
                                [% ELSE %]
302
                                    <div class="bibmessage">This title cannot be requested.</div>
303
                                [% END %]
300
                            [% END %]
304
                            [% END %]
301
                          [% END %]
305
                          [% END %]
302
                        [% END %]
306
                        [% END %]
(-)a/opac/opac-reserve.pl (-11 / +18 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 172-178 foreach my $biblioNumber (@biblionumbers) { Link Here
172
if ( $query->param('place_reserve') ) {
173
if ( $query->param('place_reserve') ) {
173
    my $notes = $query->param('notes');
174
    my $notes = $query->param('notes');
174
    my $reserve_cnt = 0;
175
    my $reserve_cnt = 0;
175
    if ($MAXIMUM_NUMBER_OF_RESERVES) {
176
    if ($maxreserves) {
176
        $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber );
177
        $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber );
177
    }
178
    }
178
179
Lines 255-262 if ( $query->param('place_reserve') ) { Link Here
255
            $itemNum = undef;
256
            $itemNum = undef;
256
        }
257
        }
257
258
258
        if (   $MAXIMUM_NUMBER_OF_RESERVES
259
        if (   $maxreserves
259
            && $reserve_cnt >= $MAXIMUM_NUMBER_OF_RESERVES )
260
            && $reserve_cnt >= $maxreserves )
260
        {
261
        {
261
            $canreserve = 0;
262
            $canreserve = 0;
262
        }
263
        }
Lines 317-323 if ( CheckBorrowerDebarred($borrowernumber) ) { Link Here
317
318
318
my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
319
my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
319
$template->param( RESERVES => \@reserves );
320
$template->param( RESERVES => \@reserves );
320
if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES) ) {
321
if ( $maxreserves && (scalar(@reserves) >= $maxreserves) ) {
321
    $template->param( message => 1 );
322
    $template->param( message => 1 );
322
    $noreserves = 1;
323
    $noreserves = 1;
323
    $template->param( too_many_reserves => scalar(@reserves));
324
    $template->param( too_many_reserves => scalar(@reserves));
Lines 325-336 if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RES Link Here
325
foreach my $res (@reserves) {
326
foreach my $res (@reserves) {
326
    foreach my $biblionumber (@biblionumbers) {
327
    foreach my $biblionumber (@biblionumbers) {
327
        if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) {
328
        if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) {
328
#            $template->param( message => 1 );
329
            $biblioDataHash{$biblionumber}->{holds_count}++;
329
#            $noreserves = 1;
330
#            $template->param( already_reserved => 1 );
331
            $biblioDataHash{$biblionumber}->{already_reserved} = 1;
332
        }
330
        }
333
    }
331
    }
332
334
}
333
}
335
334
336
unless ($noreserves) {
335
unless ($noreserves) {
Lines 372-378 foreach my $biblioNum (@biblionumbers) { Link Here
372
    $biblioLoopIter{author} = $biblioData->{author};
371
    $biblioLoopIter{author} = $biblioData->{author};
373
    $biblioLoopIter{rank} = $biblioData->{rank};
372
    $biblioLoopIter{rank} = $biblioData->{rank};
374
    $biblioLoopIter{reservecount} = $biblioData->{reservecount};
373
    $biblioLoopIter{reservecount} = $biblioData->{reservecount};
375
    $biblioLoopIter{already_reserved} = $biblioData->{already_reserved};
374
    $biblioLoopIter{holds_count} = $biblioData->{holds_count};
376
375
377
    if (!$itemLevelTypes && $biblioData->{itemtype}) {
376
    if (!$itemLevelTypes && $biblioData->{itemtype}) {
378
        $biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description};
377
        $biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description};
Lines 499-509 foreach my $biblioNum (@biblionumbers) { Link Here
499
            $policy_holdallowed = 0;
498
            $policy_holdallowed = 0;
500
        }
499
        }
501
500
502
        if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{already_reserved} ne 1)) {
501
        if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{holds_count} < $max_holds_per_record )) {
503
            $itemLoopIter->{available} = 1;
502
            $itemLoopIter->{available} = 1;
504
            $numCopiesAvailable++;
503
            $numCopiesAvailable++;
505
        }
504
        }
506
505
506
        # Don't allow multiple item level holds on the same item if borrowers can place multiple holds on one bib
507
        $itemLoopIter->{available} = 0 if ( GetReservesFromBorrowernumber( $borrowernumber, undef, undef, $itemNum ) );
508
507
	# FIXME: move this to a pm
509
	# FIXME: move this to a pm
508
        my $dbh = C4::Context->dbh;
510
        my $dbh = C4::Context->dbh;
509
        my $sth2 = $dbh->prepare("SELECT * FROM reserves WHERE borrowernumber=? AND itemnumber=? AND found='W'");
511
        my $sth2 = $dbh->prepare("SELECT * FROM reserves WHERE borrowernumber=? AND itemnumber=? AND found='W'");
Lines 530-535 foreach my $biblioNum (@biblionumbers) { Link Here
530
    if ($biblioLoopIter{already_reserved}) {
532
    if ($biblioLoopIter{already_reserved}) {
531
        $biblioLoopIter{holdable} = undef;
533
        $biblioLoopIter{holdable} = undef;
532
    }
534
    }
535
    if ($biblioLoopIter{holds_count} >= $max_holds_per_record) {
536
        $biblioLoopIter{holdable} = undef;
537
        $anyholdable = undef;
538
        $biblioLoopIter{max_holds} = 1;
539
    }
533
    if(not CanBookBeReserved($borrowernumber,$biblioNum)){
540
    if(not CanBookBeReserved($borrowernumber,$biblioNum)){
534
        $biblioLoopIter{holdable} = undef;
541
        $biblioLoopIter{holdable} = undef;
535
    }
542
    }
(-)a/reserve/request.pl (-2 / +8 lines)
Lines 209-214 if ($borrowerslist) { Link Here
209
209
210
# FIXME launch another time GetMember perhaps until
210
# FIXME launch another time GetMember perhaps until
211
my $borrowerinfo = GetMember( borrowernumber => $borrowernumber_hold );
211
my $borrowerinfo = GetMember( borrowernumber => $borrowernumber_hold );
212
my $max_holds_per_record = C4::Context->preference('MaxHoldsPerRecord');
212
213
213
my @biblionumbers = ();
214
my @biblionumbers = ();
214
my $biblionumbers = $input->param('biblionumbers');
215
my $biblionumbers = $input->param('biblionumbers');
Lines 254-260 foreach my $biblionumber (@biblionumbers) { Link Here
254
        }
255
        }
255
    }
256
    }
256
257
257
    if ( $holds_count ) {
258
    if ( $holds_count >= $max_holds_per_record ) {
258
            $alreadyreserved = 1;
259
            $alreadyreserved = 1;
259
            $warnings = 1;
260
            $warnings = 1;
260
            $biblioloopiter{warn} = 1;
261
            $biblioloopiter{warn} = 1;
Lines 482-487 foreach my $biblionumber (@biblionumbers) { Link Here
482
                $itemdata_enumchron = 1;
483
                $itemdata_enumchron = 1;
483
            }
484
            }
484
485
486
            # Don't allow multiple item level holds on the same item if borrowers can place multiple holds on one bib
487
            if ( GetReservesFromBorrowernumber( $borrowerinfo->{borrowernumber}, undef, undef, $itemnumber) ) {
488
                $item->{available} = 0;
489
                $item->{override} = 0;
490
            }
491
485
            push @{ $biblioitem->{itemloop} }, $item;
492
            push @{ $biblioitem->{itemloop} }, $item;
486
        }
493
        }
487
494
488
- 

Return to bug 7710