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

(-)a/C4/Reserves.pm (-1 / +33 lines)
Lines 428-433 See CanItemBeReserved() for possible return values. Link Here
428
sub CanBookBeReserved{
428
sub CanBookBeReserved{
429
    my ($borrowernumber, $biblionumber) = @_;
429
    my ($borrowernumber, $biblionumber) = @_;
430
430
431
    # Check if borrower already has reserved the same biblio.
432
    my @reserves = GetReservesFromBorrowernumber($borrowernumber);
433
    foreach my $reserve (@reserves) {
434
        if ($reserve->{biblionumber} == $biblionumber) {
435
            return 'alreadyReserved';
436
        }
437
    }
438
439
    # Check if borrower has reached the maximum number of holds allowed
440
    my $maxreserves = C4::Context->preference('maxreserves');
441
    if ($maxreserves && scalar(@reserves) >= $maxreserves) {
442
        return 'tooManyReserves';
443
    }
444
431
    my $items = GetItemnumbersForBiblio($biblionumber);
445
    my $items = GetItemnumbersForBiblio($biblionumber);
432
    #get items linked via host records
446
    #get items linked via host records
433
    my @hostitems = get_hostitemnumbers_of($biblionumber);
447
    my @hostitems = get_hostitemnumbers_of($biblionumber);
Lines 440-446 sub CanBookBeReserved{ Link Here
440
        $canReserve = CanItemBeReserved( $borrowernumber, $item );
454
        $canReserve = CanItemBeReserved( $borrowernumber, $item );
441
        return 'OK' if $canReserve eq 'OK';
455
        return 'OK' if $canReserve eq 'OK';
442
    }
456
    }
443
    return $canReserve;
457
458
    return 'none_available';
444
}
459
}
445
460
446
=head2 CanItemBeReserved
461
=head2 CanItemBeReserved
Lines 454-459 sub CanBookBeReserved{ Link Here
454
         cannotReserveFromOtherBranches, if syspref 'canreservefromotherbranches' is OK.
469
         cannotReserveFromOtherBranches, if syspref 'canreservefromotherbranches' is OK.
455
         tooManyReserves, if the borrower has exceeded his maximum reserve amount.
470
         tooManyReserves, if the borrower has exceeded his maximum reserve amount.
456
         notReservable,   if holds on this item are not allowed
471
         notReservable,   if holds on this item are not allowed
472
         alreadyReserved, if the borrower has already reserved this item.
457
473
458
=cut
474
=cut
459
475
Lines 485-490 sub CanItemBeReserved { Link Here
485
    return 'itemAlreadyOnHold'
501
    return 'itemAlreadyOnHold'
486
      if Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count();
502
      if Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count();
487
503
504
    # Check if borrower already has reserved the same item or biblio.
505
    my @reserves = GetReservesFromBorrowernumber($borrowernumber);
506
    foreach my $reserve (@reserves) {
507
        if (   $reserve->{itemnumber} == $itemnumber
508
            or $reserve->{biblionumber} == $item->{biblionumber} )
509
        {
510
            return 'alreadyReserved';
511
        }
512
    }
513
514
    # Check if borrower has reached the maximum number of holds allowed
515
    my $maxreserves = C4::Context->preference('maxreserves');
516
    if ($maxreserves && scalar(@reserves) >= $maxreserves) {
517
        return 'tooManyReserves';
518
    }
519
488
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
520
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
489
521
490
    my $querycount = q{
522
    my $querycount = q{
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-2 / +2 lines)
Lines 265-271 function checkMultiHold() { Link Here
265
    </form>
265
    </form>
266
  [% ELSIF NOT noitems %]
266
  [% ELSIF NOT noitems %]
267
267
268
[% IF ( exceeded_maxreserves || exceeded_holds_per_record || alreadyreserved || none_available || alreadypossession || ageRestricted ) %]
268
[% IF ( exceeded_maxreserves || exceeded_holds_per_record || alreadyReserved || none_available || alreadypossession || ageRestricted ) %]
269
    <div class="dialog alert">
269
    <div class="dialog alert">
270
270
271
    [% UNLESS ( multi_hold ) %]
271
    [% UNLESS ( multi_hold ) %]
Lines 277-283 function checkMultiHold() { Link Here
277
          <li><strong>Too many holds for this record: </strong> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %] </a> can only place a maximum of [% max_holds_for_record %] hold(s) on this record.</li>
277
          <li><strong>Too many holds for this record: </strong> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %] </a> can only place a maximum of [% max_holds_for_record %] hold(s) on this record.</li>
278
        [% ELSIF ( alreadypossession ) %]
278
        [% ELSIF ( alreadypossession ) %]
279
          <li> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>is already in possession</strong> of one item.</li>
279
          <li> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>is already in possession</strong> of one item.</li>
280
        [% ELSIF ( alreadyreserved ) %]
280
        [% ELSIF ( alreadyReserved ) %]
281
          <li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>already has a hold</strong> on this item.</li>
281
          <li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>already has a hold</strong> on this item.</li>
282
        [% ELSIF ( ageRestricted ) %]
282
        [% ELSIF ( ageRestricted ) %]
283
          <li><strong>Age restricted</strong></li>
283
          <li><strong>Age restricted</strong></li>
(-)a/reserve/request.pl (-1 / +3 lines)
Lines 226-232 foreach my $biblionumber (@biblionumbers) { Link Here
226
        $exceeded_holds_per_record = 1;
226
        $exceeded_holds_per_record = 1;
227
        $biblioloopiter{$canReserve} = 1;
227
        $biblioloopiter{$canReserve} = 1;
228
    }
228
    }
229
    elsif ( $canReserve eq 'ageRestricted' ) {
229
    elsif ( grep { $canReserve eq $_ }
230
        (qw(ageRestricted alreadyReserved none_available)) )
231
    {
230
        $template->param( $canReserve => 1 );
232
        $template->param( $canReserve => 1 );
231
        $biblioloopiter{$canReserve} = 1;
233
        $biblioloopiter{$canReserve} = 1;
232
    }
234
    }
(-)a/t/db_dependent/Holds.t (-14 / +35 lines)
Lines 7-13 use t::lib::TestBuilder; Link Here
7
7
8
use C4::Context;
8
use C4::Context;
9
9
10
use Test::More tests => 61;
10
use Test::More tests => 64;
11
use MARC::Record;
11
use MARC::Record;
12
use C4::Biblio;
12
use C4::Biblio;
13
use C4::Items;
13
use C4::Items;
Lines 334-343 ModReserve({ reserve_id => $reserveid2, rank => 'del' }); Link Here
334
$reserve3 = GetReserve( $reserveid3 );
334
$reserve3 = GetReserve( $reserveid3 );
335
is( $reserve3->{priority}, 1, "After ModReserve, the 3rd reserve becomes the first on the waiting list" );
335
is( $reserve3->{priority}, 1, "After ModReserve, the 3rd reserve becomes the first on the waiting list" );
336
336
337
ok( defined( ( CheckReserves($itemnumber) )[1] ), "Hold can be trapped for damaged item with AllowHoldsOnDamagedItems enabled" );
338
337
ModItem({ damaged => 1 }, $item_bibnum, $itemnumber);
339
ModItem({ damaged => 1 }, $item_bibnum, $itemnumber);
340
CancelReserve({reserve_id => $reserveid3});
338
t::lib::Mocks::mock_preference( 'AllowHoldsOnDamagedItems', 1 );
341
t::lib::Mocks::mock_preference( 'AllowHoldsOnDamagedItems', 1 );
339
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber), 'OK', "Patron can reserve damaged item with AllowHoldsOnDamagedItems enabled" );
342
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber), 'OK', "Patron can reserve damaged item with AllowHoldsOnDamagedItems enabled" );
340
ok( defined( ( CheckReserves($itemnumber) )[1] ), "Hold can be trapped for damaged item with AllowHoldsOnDamagedItems enabled" );
341
343
342
$hold = Koha::Hold->new(
344
$hold = Koha::Hold->new(
343
    {
345
    {
Lines 365-387 AddReserve( Link Here
365
    '',
367
    '',
366
    1,
368
    1,
367
);
369
);
370
my ($bibnum2, $title2, $bibitemnum2) = create_helper_biblio('CANNOT');
371
my ($item_bibnum2, $item_bibitemnum2, $itemnumber2) = AddItem({ homebranch => $branch_1, holdingbranch => $branch_1, itype => 'CANNOT' } , $bibnum2);
368
is(
372
is(
369
    CanItemBeReserved( $borrowernumbers[0], $itemnumber), 'tooManyReserves',
373
    CanItemBeReserved( $borrowernumbers[0], $itemnumber2), 'tooManyReserves',
370
    "cannot request item if policy that matches on item-level item type forbids it"
374
    "cannot request item if policy that matches on item-level item type forbids it"
371
);
375
);
372
ModItem({ itype => 'CAN' }, $item_bibnum, $itemnumber);
376
ModItem({ itype => 'CAN' }, $item_bibnum2, $itemnumber2);
373
ok(
377
ok(
374
    CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'OK',
378
    CanItemBeReserved( $borrowernumbers[0], $itemnumber2) eq 'OK',
375
    "can request item if policy that matches on item type allows it"
379
    "can request item if policy that matches on item type allows it"
376
);
380
);
377
381
378
t::lib::Mocks::mock_preference('item-level_itypes', 0);
382
t::lib::Mocks::mock_preference('item-level_itypes', 0);
379
ModItem({ itype => undef }, $item_bibnum, $itemnumber);
383
ModItem({ itype => undef }, $item_bibnum2, $itemnumber2);
380
ok(
384
ok(
381
    CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'tooManyReserves',
385
    CanItemBeReserved( $borrowernumbers[0], $itemnumber2) eq 'tooManyReserves',
382
    "cannot request item if policy that matches on bib-level item type forbids it (bug 9532)"
386
    "cannot request item if policy that matches on bib-level item type forbids it (bug 9532)"
383
);
387
);
384
388
389
is(CanBookBeReserved($borrowernumbers[0], $bibnum), 'alreadyReserved');
390
391
C4::Context->set_preference('maxreserves', 1);
392
ok(CanBookBeReserved($borrowernumbers[0], $biblionumber) eq 'tooManyReserves');
393
394
C4::Context->set_preference('maxreserves', 0);
395
t::lib::Mocks::mock_preference('IndependentBranches', 1);
396
t::lib::Mocks::mock_preference('canreservefromotherbranches', 0);
397
ok(CanBookBeReserved($borrowernumbers[0], $foreign_bibnum) eq 'none_available');
385
398
386
# Test branch item rules
399
# Test branch item rules
387
400
Lines 491-500 sub create_helper_biblio { Link Here
491
    my $itemtype = shift;
504
    my $itemtype = shift;
492
    my $bib = MARC::Record->new();
505
    my $bib = MARC::Record->new();
493
    my $title = 'Silence in the library';
506
    my $title = 'Silence in the library';
494
    $bib->append_fields(
507
    if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
495
        MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
508
        $bib->append_fields(
496
        MARC::Field->new('245', ' ', ' ', a => $title),
509
            MARC::Field->new('700', ' ', '0', a => 'Moffat, Steven'),
497
        MARC::Field->new('942', ' ', ' ', c => $itemtype),
510
            MARC::Field->new('200', ' ', ' ', a => $title),
498
    );
511
            MARC::Field->new('099', ' ', ' ', t => $itemtype),
499
    return ($bibnum, $title, $bibitemnum) = AddBiblio($bib, '');
512
        );
513
    } else {
514
        $bib->append_fields(
515
            MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
516
            MARC::Field->new('245', ' ', ' ', a => $title),
517
            MARC::Field->new('942', ' ', ' ', c => $itemtype),
518
        );
519
    }
520
521
    return AddBiblio($bib, '');
500
}
522
}
501
- 

Return to bug 11999