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

(-)a/C4/Reserves.pm (-2 / +34 lines)
Lines 412-417 See CanItemBeReserved() for possible return values. Link Here
412
sub CanBookBeReserved{
412
sub CanBookBeReserved{
413
    my ($borrowernumber, $biblionumber) = @_;
413
    my ($borrowernumber, $biblionumber) = @_;
414
414
415
    # Check if borrower already has reserved the same biblio.
416
    my @reserves = GetReservesFromBorrowernumber($borrowernumber);
417
    foreach my $reserve (@reserves) {
418
        if ($reserve->{biblionumber} == $biblionumber) {
419
            return 'alreadyReserved';
420
        }
421
    }
422
423
    # Check if borrower has reached the maximum number of holds allowed
424
    my $maxreserves = C4::Context->preference('maxreserves');
425
    if ($maxreserves && scalar(@reserves) >= $maxreserves) {
426
        return 'tooManyReserves';
427
    }
428
415
    my $items = GetItemnumbersForBiblio($biblionumber);
429
    my $items = GetItemnumbersForBiblio($biblionumber);
416
    #get items linked via host records
430
    #get items linked via host records
417
    my @hostitems = get_hostitemnumbers_of($biblionumber);
431
    my @hostitems = get_hostitemnumbers_of($biblionumber);
Lines 424-430 sub CanBookBeReserved{ Link Here
424
        $canReserve = CanItemBeReserved( $borrowernumber, $item );
438
        $canReserve = CanItemBeReserved( $borrowernumber, $item );
425
        return 'OK' if $canReserve eq 'OK';
439
        return 'OK' if $canReserve eq 'OK';
426
    }
440
    }
427
    return $canReserve;
441
442
    return 'none_available';
428
}
443
}
429
444
430
=head2 CanItemBeReserved
445
=head2 CanItemBeReserved
Lines 438-443 sub CanBookBeReserved{ Link Here
438
         cannotReserveFromOtherBranches, if syspref 'canreservefromotherbranches' is OK.
453
         cannotReserveFromOtherBranches, if syspref 'canreservefromotherbranches' is OK.
439
         tooManyReserves, if the borrower has exceeded his maximum reserve amount.
454
         tooManyReserves, if the borrower has exceeded his maximum reserve amount.
440
         notReservable,   if holds on this item are not allowed
455
         notReservable,   if holds on this item are not allowed
456
         alreadyReserved, if the borrower has already reserved this item.
441
457
442
=cut
458
=cut
443
459
Lines 447-453 sub CanItemBeReserved{ Link Here
447
    my $dbh             = C4::Context->dbh;
463
    my $dbh             = C4::Context->dbh;
448
    my $ruleitemtype; # itemtype of the matching issuing rule
464
    my $ruleitemtype; # itemtype of the matching issuing rule
449
    my $allowedreserves = 0;
465
    my $allowedreserves = 0;
450
            
466
451
    # we retrieve borrowers and items informations #
467
    # we retrieve borrowers and items informations #
452
    # item->{itype} will come for biblioitems if necessery
468
    # item->{itype} will come for biblioitems if necessery
453
    my $item = GetItem($itemnumber);
469
    my $item = GetItem($itemnumber);
Lines 461-466 sub CanItemBeReserved{ Link Here
461
    my ($ageRestriction, $daysToAgeRestriction) = C4::Circulation::GetAgeRestriction( $biblioData->{agerestriction}, $borrower );
477
    my ($ageRestriction, $daysToAgeRestriction) = C4::Circulation::GetAgeRestriction( $biblioData->{agerestriction}, $borrower );
462
    return 'ageRestricted' if $daysToAgeRestriction && $daysToAgeRestriction > 0;
478
    return 'ageRestricted' if $daysToAgeRestriction && $daysToAgeRestriction > 0;
463
479
480
    # Check if borrower already has reserved the same item or biblio.
481
    my @reserves = GetReservesFromBorrowernumber($borrowernumber);
482
    foreach my $reserve (@reserves) {
483
        if (   $reserve->{itemnumber} == $itemnumber
484
            or $reserve->{biblionumber} == $item->{biblionumber} )
485
        {
486
            return 'alreadyReserved';
487
        }
488
    }
489
490
    # Check if borrower has reached the maximum number of holds allowed
491
    my $maxreserves = C4::Context->preference('maxreserves');
492
    if ($maxreserves && scalar(@reserves) >= $maxreserves) {
493
        return 'tooManyReserves';
494
    }
495
464
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
496
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
465
497
466
    # we retrieve user rights on this itemtype and branchcode
498
    # we retrieve user rights on this itemtype and branchcode
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-2 / +2 lines)
Lines 298-304 function checkMultiHold() { Link Here
298
    </form>
298
    </form>
299
  [% ELSE %]
299
  [% ELSE %]
300
300
301
[% IF ( exceeded_maxreserves || alreadyreserved || none_available || alreadypossession || ageRestricted ) %]
301
[% IF ( exceeded_maxreserves || alreadyReserved || none_available || alreadypossession || ageRestricted ) %]
302
    <div class="dialog alert">
302
    <div class="dialog alert">
303
303
304
    [% UNLESS ( multi_hold ) %]
304
    [% UNLESS ( multi_hold ) %]
Lines 308-314 function checkMultiHold() { Link Here
308
          <li><strong>Too many holds: </strong> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %] </a> can only place a maximum of [% maxreserves %] total holds.</li>
308
          <li><strong>Too many holds: </strong> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %] </a> can only place a maximum of [% maxreserves %] total holds.</li>
309
        [% ELSIF ( alreadypossession ) %]
309
        [% ELSIF ( alreadypossession ) %]
310
          <li> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>is already in possession</strong> of one item</li>
310
          <li> <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>is already in possession</strong> of one item</li>
311
        [% ELSIF ( alreadyreserved ) %]
311
        [% ELSIF ( alreadyReserved ) %]
312
          <li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>already has a hold</strong> on this item </li>
312
          <li><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">[% borrowerfirstname %] [% borrowersurname %]</a> <strong>already has a hold</strong> on this item </li>
313
        [% ELSIF ( ageRestricted ) %]
313
        [% ELSIF ( ageRestricted ) %]
314
          <li><strong>Age restricted</strong></li>
314
          <li><strong>Age restricted</strong></li>
(-)a/reserve/request.pl (-14 / +3 lines)
Lines 226-232 foreach my $biblionumber (@biblionumbers) { Link Here
226
    elsif ( $canReserve eq 'tooManyReserves' ) {
226
    elsif ( $canReserve eq 'tooManyReserves' ) {
227
        $exceeded_maxreserves = 1;
227
        $exceeded_maxreserves = 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
    }
Lines 243-269 foreach my $biblionumber (@biblionumbers) { Link Here
243
    my $reserves = GetReservesFromBiblionumber({ biblionumber => $biblionumber, all_dates => 1 });
245
    my $reserves = GetReservesFromBiblionumber({ biblionumber => $biblionumber, all_dates => 1 });
244
    my $count = scalar( @$reserves );
246
    my $count = scalar( @$reserves );
245
    my $totalcount = $count;
247
    my $totalcount = $count;
246
    my $holds_count = 0;
247
    my $alreadyreserved = 0;
248
248
249
    foreach my $res (@$reserves) {
249
    foreach my $res (@$reserves) {
250
        if ( defined $res->{found} ) { # found can be 'W' or 'T'
250
        if ( defined $res->{found} ) { # found can be 'W' or 'T'
251
            $count--;
251
            $count--;
252
        }
252
        }
253
254
        if ( defined $borrowerinfo && defined($borrowerinfo->{borrowernumber}) && ($borrowerinfo->{borrowernumber} eq $res->{borrowernumber}) ) {
255
            $holds_count++;
256
        }
257
    }
258
259
    if ( $holds_count ) {
260
            $alreadyreserved = 1;
261
            $biblioloopiter{warn} = 1;
262
            $biblioloopiter{alreadyres} = 1;
263
    }
253
    }
264
254
265
    $template->param(
255
    $template->param(
266
        alreadyreserved => $alreadyreserved,
267
        alreadypossession => $alreadypossession,
256
        alreadypossession => $alreadypossession,
268
    );
257
    );
269
258
(-)a/t/db_dependent/Holds.t (-14 / +35 lines)
Lines 8-14 use t::lib::TestBuilder; Link Here
8
use C4::Context;
8
use C4::Context;
9
use C4::Branch;
9
use C4::Branch;
10
10
11
use Test::More tests => 56;
11
use Test::More tests => 59;
12
use MARC::Record;
12
use MARC::Record;
13
use C4::Biblio;
13
use C4::Biblio;
14
use C4::Items;
14
use C4::Items;
Lines 314-323 ModReserve({ reserve_id => $reserveid2, rank => 'del' }); Link Here
314
$reserve3 = GetReserve( $reserveid3 );
314
$reserve3 = GetReserve( $reserveid3 );
315
is( $reserve3->{priority}, 1, "After ModReserve, the 3rd reserve becomes the first on the waiting list" );
315
is( $reserve3->{priority}, 1, "After ModReserve, the 3rd reserve becomes the first on the waiting list" );
316
316
317
ok( defined( ( CheckReserves($itemnumber) )[1] ), "Hold can be trapped for damaged item with AllowHoldsOnDamagedItems enabled" );
318
317
ModItem({ damaged => 1 }, $item_bibnum, $itemnumber);
319
ModItem({ damaged => 1 }, $item_bibnum, $itemnumber);
320
CancelReserve({reserve_id => $reserveid3});
318
C4::Context->set_preference( 'AllowHoldsOnDamagedItems', 1 );
321
C4::Context->set_preference( 'AllowHoldsOnDamagedItems', 1 );
319
ok( CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'OK', "Patron can reserve damaged item with AllowHoldsOnDamagedItems enabled" );
322
ok( CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'OK', "Patron can reserve damaged item with AllowHoldsOnDamagedItems enabled" );
320
ok( defined( ( CheckReserves($itemnumber) )[1] ), "Hold can be trapped for damaged item with AllowHoldsOnDamagedItems enabled" );
321
C4::Context->set_preference( 'AllowHoldsOnDamagedItems', 0 );
323
C4::Context->set_preference( 'AllowHoldsOnDamagedItems', 0 );
322
ok( CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'damaged', "Patron cannot reserve damaged item with AllowHoldsOnDamagedItems disabled" );
324
ok( CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'damaged', "Patron cannot reserve damaged item with AllowHoldsOnDamagedItems disabled" );
323
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for damaged item with AllowHoldsOnDamagedItems disabled" );
325
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for damaged item with AllowHoldsOnDamagedItems disabled" );
Lines 332-354 AddReserve( Link Here
332
    '',
334
    '',
333
    1,
335
    1,
334
);
336
);
337
my ($bibnum2, $title2, $bibitemnum2) = create_helper_biblio('CANNOT');
338
my ($item_bibnum2, $item_bibitemnum2, $itemnumber2) = AddItem({ homebranch => $branch_1, holdingbranch => $branch_1, itype => 'CANNOT' } , $bibnum2);
335
ok(
339
ok(
336
    CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'tooManyReserves',
340
    CanItemBeReserved( $borrowernumbers[0], $itemnumber2) eq 'tooManyReserves',
337
    "cannot request item if policy that matches on item-level item type forbids it"
341
    "cannot request item if policy that matches on item-level item type forbids it"
338
);
342
);
339
ModItem({ itype => 'CAN' }, $item_bibnum, $itemnumber);
343
ModItem({ itype => 'CAN' }, $item_bibnum2, $itemnumber2);
340
ok(
344
ok(
341
    CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'OK',
345
    CanItemBeReserved( $borrowernumbers[0], $itemnumber2) eq 'OK',
342
    "can request item if policy that matches on item type allows it"
346
    "can request item if policy that matches on item type allows it"
343
);
347
);
344
348
345
t::lib::Mocks::mock_preference('item-level_itypes', 0);
349
t::lib::Mocks::mock_preference('item-level_itypes', 0);
346
ModItem({ itype => undef }, $item_bibnum, $itemnumber);
350
ModItem({ itype => undef }, $item_bibnum2, $itemnumber2);
347
ok(
351
ok(
348
    CanItemBeReserved( $borrowernumbers[0], $itemnumber) eq 'tooManyReserves',
352
    CanItemBeReserved( $borrowernumbers[0], $itemnumber2) eq 'tooManyReserves',
349
    "cannot request item if policy that matches on bib-level item type forbids it (bug 9532)"
353
    "cannot request item if policy that matches on bib-level item type forbids it (bug 9532)"
350
);
354
);
351
355
356
is(CanBookBeReserved($borrowernumbers[0], $bibnum), 'alreadyReserved');
357
358
C4::Context->set_preference('maxreserves', 1);
359
ok(CanBookBeReserved($borrowernumbers[0], $biblionumber) eq 'tooManyReserves');
360
361
C4::Context->set_preference('maxreserves', 0);
362
t::lib::Mocks::mock_preference('IndependentBranches', 1);
363
t::lib::Mocks::mock_preference('canreservefromotherbranches', 0);
364
ok(CanBookBeReserved($borrowernumbers[0], $foreign_bibnum) eq 'none_available');
352
365
353
# Test branch item rules
366
# Test branch item rules
354
367
Lines 458-467 sub create_helper_biblio { Link Here
458
    my $itemtype = shift;
471
    my $itemtype = shift;
459
    my $bib = MARC::Record->new();
472
    my $bib = MARC::Record->new();
460
    my $title = 'Silence in the library';
473
    my $title = 'Silence in the library';
461
    $bib->append_fields(
474
    if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
462
        MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
475
        $bib->append_fields(
463
        MARC::Field->new('245', ' ', ' ', a => $title),
476
            MARC::Field->new('700', ' ', '0', a => 'Moffat, Steven'),
464
        MARC::Field->new('942', ' ', ' ', c => $itemtype),
477
            MARC::Field->new('200', ' ', ' ', a => $title),
465
    );
478
            MARC::Field->new('099', ' ', ' ', t => $itemtype),
466
    return ($bibnum, $title, $bibitemnum) = AddBiblio($bib, '');
479
        );
480
    } else {
481
        $bib->append_fields(
482
            MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
483
            MARC::Field->new('245', ' ', ' ', a => $title),
484
            MARC::Field->new('942', ' ', ' ', c => $itemtype),
485
        );
486
    }
487
488
    return AddBiblio($bib, '');
467
}
489
}
468
- 

Return to bug 11999