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

(-)a/C4/Reserves.pm (-1 / +10 lines)
Lines 595-600 sub CanReserveBeCanceledFromOpac { Link Here
595
595
596
    return 0 unless $reserve->borrowernumber == $borrowernumber;
596
    return 0 unless $reserve->borrowernumber == $borrowernumber;
597
    return $reserve->is_cancelable_from_opac;
597
    return $reserve->is_cancelable_from_opac;
598
    return 0 if ( $reserve->found && $reserve->found eq 'W' ) or ( $reserve->found && $reserve->found eq 'T' );
599
600
    return 1;
601
598
}
602
}
599
603
600
=head2 GetOtherReserves
604
=head2 GetOtherReserves
Lines 854-860 sub CheckReserves { Link Here
854
        my $priority = 10000000;
858
        my $priority = 10000000;
855
        foreach my $res (@reserves) {
859
        foreach my $res (@reserves) {
856
            #Before allocating to bib-level hold check if reserve respects hold rule, i.e. can patron category/item type combination allow reserves
860
            #Before allocating to bib-level hold check if reserve respects hold rule, i.e. can patron category/item type combination allow reserves
857
            my $checkreserve = Koha::Hold->check_if_existing_hold_matches_issuingrules( $res->{'borrowernumber'}, $itemnumber );
861
            my $checkreserve;
862
            if ( $item ){
863
                $checkreserve = Koha::Holds->find( $res->{reserve_id} )->matches_circulation_rules({ itemnumber => $item });
864
            } else {
865
                $checkreserve = Koha::Holds->find( $res->{reserve_id} )->matches_circulation_rules({ barcode => $barcode });
866
            }
858
            next unless ($checkreserve eq 'OK');
867
            next unless ($checkreserve eq 'OK');
859
            if ($res->{'found'} && $res->{'found'} eq 'W') {
868
            if ($res->{'found'} && $res->{'found'} eq 'W') {
860
                return ( "Waiting", $res, \@reserves ); # Found it, it is waiting
869
                return ( "Waiting", $res, \@reserves ); # Found it, it is waiting
(-)a/Koha/Hold.pm (-16 / +27 lines)
Lines 36-42 use Koha::Items; Link Here
36
use Koha::Libraries;
36
use Koha::Libraries;
37
use Koha::Old::Holds;
37
use Koha::Old::Holds;
38
use Koha::Calendar;
38
use Koha::Calendar;
39
40
use Koha::Exceptions::Hold;
39
use Koha::Exceptions::Hold;
41
40
42
use base qw(Koha::Object);
41
use base qw(Koha::Object);
Lines 476-516 sub is_suspended { Link Here
476
    return $self->suspend();
475
    return $self->suspend();
477
}
476
}
478
477
479
=head3 check_if_existing_hold_matches_issuingrules
478
=head3 matches_circulation_rules
480
479
481
my $checkreserve = Koha::Hold->check_if_existing_hold_matches_issuingrules($res->{'borrowernumber'}, $itemnumber );
480
    my $checkreserve = Koha::Hold->matches_circulation_rules({ itemnumber => $itemnumber });
481
    my $checkreserve = Koha::Hold->matches_circulation_rules({ barcode => $barcode });
482
482
483
Upon checking in an item of a bibliographic record with a biblio-level hold on it, check if a bib-level hold can be allocated to a patron based on the current values in the issuingrules table
483
Upon checking in an item of a bibliographic record with a biblio-level hold on it, check if a bib-level hold can be allocated to a patron based on the current values in the issuingrules table
484
484
485
Parameter is an attribute of the item that is being checked in
486
485
=cut
487
=cut
486
488
487
sub check_if_existing_hold_matches_issuingrules {
489
sub matches_circulation_rules {
488
    my ( $self, $borrowernumber, $itemnumber ) = @_;
490
    my ( $self, $params ) = @_;
489
491
490
    #Get patron and item objects
492
    #Get patron and item objects
491
    my $patron = Koha::Patrons->find( $borrowernumber );
493
    my $patron = $self->borrower;
492
    my $item = Koha::Items->find( $itemnumber );
494
    my $item = Koha::Items->find( $params->{itemnumber} );
493
    $item = $item->unblessed();
495
    if ( !defined $item ){
496
        $item = Koha::Items->find({ barcode => $params->{barcode} });
497
    }
494
498
495
    #Get branchcode
499
    #Get branchcode
496
    my $branchcode;
500
    my $branchcode;
497
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
501
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
498
502
    if ( $controlbranch eq "ItemHomeLibrary" && defined $item ) {
499
    if ( $controlbranch eq "ItemHomeLibrary" ) {
503
         $branchcode  = $item->homebranch;
500
         $branchcode  = $item->{homebranch};
504
    } else {
501
    }
502
    elsif ( $controlbranch eq "PatronLibrary" ) {
503
         $branchcode  = $patron->branchcode;
505
         $branchcode  = $patron->branchcode;
504
    }
506
    }
505
507
506
    my $issuingrule = Koha::IssuingRules->get_effective_issuing_rule({
508
    my $issuingrule = Koha::CirculationRules->get_effective_rules({
507
        branchcode => $branchcode,
509
        branchcode => $branchcode,
508
        categorycode => $patron->categorycode,
510
        categorycode => $patron->categorycode,
509
        itemtype => $item->{itype},
511
        itemtype => $item->effective_itemtype,
512
        rules => [
513
            'reservesallowed',
514
            'holds_per_record',
515
            'holds_per_day',
516
        ],
510
    });
517
    });
511
518
512
    #Check if the patron category/item type combination is valid
519
    #Check if the patron category/item type combination is valid
513
    if ( ($issuingrule->reservesallowed == 0 || $issuingrule->holds_per_record == 0 || $issuingrule->holds_per_day == 0 )) {
520
    if (
521
        ( defined $issuingrule->{reservesallowed} && $issuingrule->{reservesallowed} == 0 ) ||
522
        ( defined $issuingrule->{holds_per_record} && $issuingrule->{holds_per_record} == 0 ) ||
523
        ( defined $issuingrule->{holds_per_day} && $issuingrule->{holds_per_day} == 0 )
524
    ) {
514
        return 'InvalidHold';
525
        return 'InvalidHold';
515
    } else {
526
    } else {
516
        return 'OK';
527
        return 'OK';
(-)a/t/db_dependent/Circulation.t (-3 lines)
Lines 3385-3393 subtest 'Set waiting flag' => sub { Link Here
3385
    my ( $status ) = CheckReserves($item->itemnumber);
3385
    my ( $status ) = CheckReserves($item->itemnumber);
3386
    is( $status, 'Transferred', 'Hold is not waiting yet');
3386
    is( $status, 'Transferred', 'Hold is not waiting yet');
3387
3387
3388
    my ( $status ) = CheckReserves($item->{itemnumber});
3389
    is( $status, 'Reserved', 'Hold is not waiting yet');
3390
3391
    set_userenv( $library_2 );
3388
    set_userenv( $library_2 );
3392
    $do_transfer = 0;
3389
    $do_transfer = 0;
3393
    AddReturn( $item->barcode, $library_2->{branchcode} );
3390
    AddReturn( $item->barcode, $library_2->{branchcode} );
(-)a/t/db_dependent/Hold.t (-89 / +146 lines)
Lines 28-34 use Koha::Holds; Link Here
28
use Koha::Item;
28
use Koha::Item;
29
use Koha::DateUtils;
29
use Koha::DateUtils;
30
use t::lib::TestBuilder;
30
use t::lib::TestBuilder;
31
use Koha::IssuingRules;
31
use Koha::CirculationRules;
32
use C4::Reserves;
32
33
33
use Test::More tests => 33;
34
use Test::More tests => 33;
34
use Test::Exception;
35
use Test::Exception;
Lines 288-386 subtest 'suspend() tests' => sub { Link Here
288
    $schema->storage->txn_rollback;
289
    $schema->storage->txn_rollback;
289
};
290
};
290
291
291
subtest "check_if_existing_hold_matches_issuingrules tests" => sub {
292
subtest "matches_circulation_rules tests" => sub {
292
    plan tests => 9;
293
    plan tests => 9;
293
294
294
    $schema->storage->txn_begin();
295
    $schema->storage->txn_begin();
295
296
296
    #Create test data
297
    #Create test data
297
    my $branchcode = $builder->build( { source => 'Branch' } )->{ branchcode };
298
    my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode };
298
    my $categorycode1 = $builder->build({ source => 'Category' })->{categorycode};
299
    my $categorycode = $builder->build({ source => 'Category' })->{ categorycode };
299
    my $categorycode2 = $builder->build({ source => 'Category' })->{categorycode};
300
    my $patron = $builder->build({ source => 'Borrower', value => { categorycode => $categorycode, branchcode => $branchcode }});
300
    my $patron1 = $builder->build({source => 'Borrower', value => { branchcode => $branchcode }});
301
    my $biblionumber = $builder->build({ source => 'Biblio' })->{biblionumber};
301
302
    my $itemtype1 = $builder->build({ source => 'Itemtype' })->{itemtype};
302
    my $item1 = $builder->build({ source => 'Item', value => { homebranch => $branchcode }});
303
    my $itemtype2 = $builder->build({ source => 'Itemtype' })->{itemtype};
303
    my $item2 = $builder->build({ source => 'Item', value => { homebranch => $branchcode }});
304
    my $item1 = $builder->build({ source => 'Item', value => { homebranch => $branchcode, biblionumber => $biblionumber, itype => $itemtype1 }});
304
305
    my $item2 = $builder->build({ source => 'Item', value => { homebranch => $branchcode, biblionumber => $biblionumber, itype => $itemtype2 }});
305
    my $itemtype1 = $item1->{'itype'};
306
306
    my $itemtype2 = $item2->{'itype'};
307
    Koha::CirculationRules->set_rules({
307
308
        branchcode => $branchcode,
308
    Koha::IssuingRules->delete;
309
        categorycode => $categorycode,
309
310
        itemtype => $itemtype1,
310
    #Get branchcode
311
        rules => {
311
    my $controlbranch = C4::Context->preference('ReservesControlBranch');
312
            reservesallowed => 0,
312
313
            holds_per_record => 0,
313
    if ( $controlbranch eq "ItemHomeLibrary" ) {
314
            holds_per_day => 0,
314
       $branchcode  = $item->{homebranch};
315
        }
315
    }
316
    });
316
    elsif ( $controlbranch eq "PatronLibrary" ) {
317
317
       $branchcode  = $patron1->{branchcode};
318
    my $reserveid1 = AddReserve({
318
    }
319
        branchcode => $branchcode,
319
320
        borrowernumber => $patron->{borrowernumber},
320
    #Test all cases when the check_return
321
        biblionumber => $biblionumber,
321
    #check_if_existing_hold_matches_issuingrules() returns 'InvalidHold' when reservesallowed, holds_per_record and holds_per_day are all 0
322
    });
322
    my $rule1 = Koha::IssuingRule->new({
323
    my $reserve1 = Koha::Holds->find($reserveid1);
323
        branchcode =>  $branchcode,
324
324
        categorycode => $patron1->{'categorycode'},
325
    my $checkreserve1 = $reserve1->matches_circulation_rules({ itemnumber => $item1->{itemnumber} });
325
        itemtype => $item1->{'itype'},
326
    is( $checkreserve1, 'InvalidHold', 'Circulation rules disallow item being allocated to the hold' );
326
        reservesallowed => 0,
327
327
        holds_per_record => 0,
328
    #Confirm that when any of the 3 reserves-related circulaion rules fields (reservesallowed, holds_per_record, holds_per_day) are set to 0 then matches_circulation_rules returns 'InvalidHold' and so a newly returned item is not allocated to a specific bib-level reserve
328
        holds_per_day => 0,
329
329
    })->store;
330
    Koha::CirculationRules->set_rules({
330
    my $checkreserve1 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item1->{'itemnumber'} );
331
        branchcode => $branchcode,
331
    is( $checkreserve1, 'InvalidHold', 'Allocating item1 to a bib-reserve is not allowed as the issuingrules reservesallowed, holds_per_record and holds_per_day is 0 for this patron category/itemtype combination' );
332
        categorycode => $categorycode,
332
333
        itemtype => $itemtype1,
333
    #Confirm that when any of the 4 reserves related issuingrules fields (reservesallowed, holds_per_record, holds_per_day) are set to 0 then check_if_existing_hold_matches_issuingrules() returns 'InvalidHold' and so a newly returned item is not allocated to a specific bib-level reserve
334
        rules => {
334
335
            reservesallowed => 0,
335
    #check_if_existing_hold_matches_issuingrules() returns 'InvalidHold' when reservesallowed is 0 for the patron category/itemtype combination
336
            holds_per_record => 1,
336
    $rule1->set({ reservesallowed => 0, holds_per_record => 1, holds_per_day => 1 })->store;
337
            holds_per_day => 1,
337
    my $checkreserve2 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item1->{'itemnumber'} );
338
        }
338
    is( $checkreserve2, 'InvalidHold', 'Allocating item1 to a bib-reserve is not allowed as the issuingrules reservesallowed is 0 for this patron category/itemtype combination' );
339
    });
339
340
    my $checkreserve2 = $reserve1->matches_circulation_rules({ itemnumber => $item1->{itemnumber} });
340
    #Now change to reservesallowed = 1, holds_per_record = 0, holds_per_day = 1
341
    is( $checkreserve2, 'InvalidHold', 'Reserves allowed is 0' );
341
    $rule1->set({ reservesallowed => 1, holds_per_record => 0, holds_per_day => 1 })->store;
342
342
    my $checkreserve3 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item1->{'itemnumber'} );
343
    Koha::CirculationRules->set_rules({
343
    is( $checkreserve3, 'InvalidHold', 'Allocating item1 to a bib-reserve is not allowed as the issuingrules holds_per_record is set to 0 for this patron category/itemtype combination' );
344
        branchcode => $branchcode,
344
345
        categorycode => $categorycode,
345
   #Now change to reservesallowed = 1, holds_per_record = 1, holds_per_day = 0
346
        itemtype => $itemtype1,
346
   $rule1->set({ reservesallowed => 1, holds_per_record => 1, holds_per_day => 0 })->store;
347
        rules => {
347
   my $checkreserve4 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item1->{'itemnumber'} );
348
            reservesallowed => 1,
348
   is( $checkreserve4, 'InvalidHold', 'Allocating item1 to a bib-reserve is not allowed as the issuingrules holds_per_record is set to0 for this patron category/itemtype combination' );
349
            holds_per_record => 0,
349
350
            holds_per_day => 1,
350
   #Now change to reservesallowed = 1, holds_per_record = 1, holds_per_day = 1 and confirm 'OK' is returned
351
        }
351
   $rule1->set({ reservesallowed => 1, holds_per_record => 1, holds_per_day => 1 })->store;
352
    });
352
   my $checkreserve5 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item1->{'itemnumber'} );
353
    my $checkreserve3 = $reserve1->matches_circulation_rules({ itemnumber => $item1->{itemnumber} });
353
   is( $checkreserve5, 'OK', 'Allocating item2 to a bib-reserve is allowed as there is no specific issuingrule for this patron category/itemtype combination and so we default to the all patron category/all item type rule which allows reserves' );
354
    is( $checkreserve3, 'InvalidHold', 'Holds per record is 0' );
354
355
355
   #Create a default rule (patron categories: ALL, itemtypes: ALL)
356
    Koha::CirculationRules->set_rules({
356
   my $rule3 = Koha::IssuingRule->new({
357
        branchcode => $branchcode,
357
       branchcode => $branchcode,
358
        categorycode => $categorycode,
358
       categorycode => '*',
359
        itemtype => $itemtype1,
359
       itemtype => '*',
360
        rules => {
360
       reservesallowed => 1,
361
            reservesallowed => 1,
361
       holds_per_record => 1,
362
            holds_per_record => 1,
362
       holds_per_day => 1,
363
            holds_per_day => 0,
363
    })->store;
364
        }
364
365
    });
365
    #Check that when no specific patron category/item type issuingrule combo exists we revert to using the default ALL categories/ALL
366
    my $checkreserve4 = $reserve1->matches_circulation_rules({ itemnumber => $item1->{itemnumber} });
366
    #itemtypes issuingrule. When generic rule is reservesallowed, holds_per_record and holds_per_day = 1 then 'OK' is returned
367
   is( $checkreserve4, 'InvalidHold', 'Holds per day is 0' );
367
    my $checkreserve6 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item2->{'itemnumber'} );
368
368
    is( $checkreserve6, 'OK', 'Allocating item2 to a bib-reserve is allowed as there is no specific issuingrule for this patron category/itemtype combination and so we default to the all patron category/all item type rule which allows reserves' );
369
    Koha::CirculationRules->set_rules({
369
370
        branchcode => $branchcode,
370
    #When default rule is reservesallowed = 0, holds_per_record = 1, holds_per_day = 1 then 'InvalidHold is returned
371
        categorycode => $categorycode,
371
    $rule3->set({ reservesallowed => 0, holds_per_record => 1, holds_per_day => 1 })->store;
372
        itemtype => $itemtype1,
372
    my $checkreserve7 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item2->{'itemnumber'} );
373
        rules => {
373
    is( $checkreserve7, 'InvalidHold', 'Allocating item2 to a bib-reserve is not allowed as there is no specific issuingrule for this patron category/itemtype combination and so we default to the all patron category/all item type rule which doesnt allows reserves as reservesallowed is 0' );
374
            reservesallowed => 1,
374
375
            holds_per_record => 1,
375
    #When default rule is reservesallowed = 1, holds_per_record = 0, holds_per_day = 1 then 'InvalidHold' is returned
376
            holds_per_day => 1,
376
    $rule3->set({ reservesallowed => 1, holds_per_record => 0, holds_per_day => 1 })->store;
377
        }
377
    my $checkreserve8 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item2->{'itemnumber'} );
378
    });
378
    is( $checkreserve8, 'InvalidHold', 'Allocating item2 to a bib-reserve is not allowed as there is no specific issuingrule for this patron category/itemtype combination and so we default to the all patron category/all item type rule which doesnt allows reserves as holds_per_record is 0' );
379
    my $checkreserve5 = $reserve1->matches_circulation_rules({ itemnumber => $item1->{itemnumber} });
379
380
   is( $checkreserve5, 'OK', 'Hold is allowed, item allocated to hold' );
380
    #When default rule is reservesallowed = 1, holds_per_record = 1, holds_per_day = 0 then 'InvalidHold' is returned
381
381
    $rule3->set({ reservesallowed => 1, holds_per_record => 1, holds_per_day => 0 })->store;
382
    #Check that when no specific patron category/item type circulation rule combo exists we revert to using the default ALL categories/ALL
382
    my $checkreserve9 = Koha::Hold->check_if_existing_hold_matches_issuingrules($patron1->{'borrowernumber'}, $item2->{'itemnumber'} );
383
    my $reserveid2 = AddReserve({
383
    is( $checkreserve9, 'InvalidHold', 'Allocating item2 to a bib-reserve is not allowed as there is no specific issuingrule for this patron category/itemtype combination and so we default to the all patron category/all item type rule which doesnt allows reserves as holds_per_day is 0' );
384
        branchcode => $branchcode,
385
        borrowernumber => $patron->{borrowernumber},
386
        biblionumber => $biblionumber,
387
    });
388
    my $reserve2 = Koha::Holds->find($reserveid2);
389
390
    Koha::CirculationRules->set_rules({
391
        branchcode => undef,
392
        categorycode => undef,
393
        itemtype => undef,
394
        rules => {
395
            reservesallowed => 0,
396
            holds_per_record => 1,
397
            holds_per_day => 1,
398
        }
399
    });
400
    my $checkreserve6 = $reserve2->matches_circulation_rules({ itemnumber => $item2->{itemnumber} });
401
    is( $checkreserve6, 'InvalidHold', 'Reserves allowed is 0' );
402
403
    Koha::CirculationRules->set_rules({
404
        branchcode => undef,
405
        categorycode => undef,
406
        itemtype => undef,
407
        rules => {
408
            reservesallowed => 1,
409
            holds_per_record => 0,
410
            holds_per_day => 1,
411
        }
412
    });
413
    my $checkreserve7 = $reserve2->matches_circulation_rules({ itemnumber => $item2->{itemnumber} });
414
    is( $checkreserve7, 'InvalidHold', 'Holds per record is 0' );
415
416
    Koha::CirculationRules->set_rules({
417
        branchcode => undef,
418
        categorycode => undef,
419
        itemtype => undef,
420
        rules => {
421
            reservesallowed => 1,
422
            holds_per_record => 1,
423
            holds_per_day => 0,
424
        }
425
    });
426
    my $checkreserve8 = $reserve2->matches_circulation_rules({ itemnumber => $item2->{itemnumber} });
427
    is( $checkreserve8, 'InvalidHold', 'Holds per day is 0' );
428
429
    Koha::CirculationRules->set_rules({
430
        branchcode => undef,
431
        categorycode => undef,
432
        itemtype => undef,
433
        rules => {
434
            reservesallowed => 1,
435
            holds_per_record => 1,
436
            holds_per_day => 1,
437
        }
438
    });
439
    my $checkreserve9 = $reserve2->matches_circulation_rules({ itemnumber => $item2->{itemnumber} });
440
    is( $checkreserve9, 'OK', 'Hold is allowed, item allocated to hold' );
384
441
385
    $schema->storage->txn_rollback;
442
    $schema->storage->txn_rollback;
386
};
443
};
(-)a/t/db_dependent/Reserves.t (-61 / +126 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 66;
20
use Test::More tests => 71;
21
use Test::MockModule;
21
use Test::MockModule;
22
use Test::Warn;
22
use Test::Warn;
23
23
Lines 529-541 AddReserve( Link Here
529
        priority       => 1,
529
        priority       => 1,
530
    }
530
    }
531
);
531
);
532
532
my (undef, $canres, undef) = CheckReserves($item->itemnumber);
533
my (undef, $canres, undef) = CheckReserves($item->itemnumber);
533
534
534
is( CanReserveBeCanceledFromOpac(), undef,
535
is( CanReserveBeCanceledFromOpac(), undef,
535
    'CanReserveBeCanceledFromOpac should return undef if called without any parameter'
536
    'CanReserveBeCanceledFromOpac should return undef if called without any parameter'
536
);
537
);
537
is(
538
is(
538
    CanReserveBeCanceledFromOpac( $canres->{resserve_id} ),
539
    CanReserveBeCanceledFromOpac( $canres->{reserve_id} ),
539
    undef,
540
    undef,
540
    'CanReserveBeCanceledFromOpac should return undef if called without the reserve_id'
541
    'CanReserveBeCanceledFromOpac should return undef if called without the reserve_id'
541
);
542
);
Lines 724-790 MoveReserve( $item->itemnumber, $borrowernumber ); Link Here
724
is( $status, 'Reserved', 'MoveReserve did not fill future hold of 3 days');
725
is( $status, 'Reserved', 'MoveReserve did not fill future hold of 3 days');
725
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
726
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
726
727
727
728
#Test bug 23172. Check when returning an item that any patron category/item type combinations that forbid reservation are skipped over when allocating the item to a bib-level hold
728
729
$dbh->do('DELETE FROM circulation_rules');
729
730
731
732
#Test bug 23172. Check when returning an item that any patron category/item type combinations that forbid reservation are skipped over
733
#when allocating the item to a bib-level hold
734
$dbh->do('DELETE FROM issuingrules');
735
736
#Create two new patrons
737
my $patronnumcat1 = Koha::Patron->new({branchcode => $branch_1, categorycode => $category_1})->store->borrowernumber;
738
my $patronnumcat2 = Koha::Patron->new({branchcode => $branch_1, categorycode => $category_2})->store->borrowernumber;
739
740
#Create a new biblio record
741
my $bibnum3 = $builder->build_sample_biblio({frameworkcode => $frameworkcode})->biblionumber;
742
730
743
#Create a second item type
731
#Create a second item type
744
my $itemtype2 = $builder->build({ source => 'Itemtype', value => { notforloan => undef } } )->{itemtype};
732
my $itemtype2 = $builder->build({ source => 'Itemtype', value => { notforloan => undef } } )->{itemtype};
745
733
746
# Create an item from new itemtype
747
my ( $item_bibnum2, $item_bibitemnum2, $itemnumber2 ) = AddItem(
748
    {   homebranch    => $branch_1,
749
        holdingbranch => $branch_1,
750
        itype         => $itemtype2,
751
        barcode       => 'bug23172_CPL'
752
    },
753
    $bibnum3
754
);
755
756
#Make a general All patron category/all item type rule
734
#Make a general All patron category/all item type rule
757
$dbh->do(
735
Koha::CirculationRules->set_rules(
758
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_day, holds_per_record)
736
    {
759
      VALUES (?, ?, ?, ?, ?, ?)},
737
        branchcode   => undef,
760
    {},
738
        categorycode => undef,
761
    '*', '*', '*', 25, 1, 1
739
        itemtype     => undef,
740
        rules        => {
741
            reservesallowed => 25,
742
            holds_per_record => 1,
743
            holds_per_day => 1,
744
        }
745
    }
762
);
746
);
763
747
764
#When patron category = $category_1 and itemtype = $itemtype1 then reservesallowed, holds_per_day and holds_per_record are 0
748
#When patron category = $category_1 and itemtype = $itemtype2 then reservesallowed, holds_per_day and holds_per_record are 0
765
$dbh->do(
749
Koha::CirculationRules->set_rules(
766
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_day, holds_per_record)
750
    {
767
     VALUES (?, ?, ?, ?, ?, ?)},
751
        branchcode   => $branch_1,
768
    {},
752
        categorycode => $category_1,
769
    $category_1, $branch_1, $itemtype2, 0, 1, 1
753
        itemtype     => $itemtype2,
754
        rules        => {
755
            reservesallowed => 0,
756
            holds_per_record => 0,
757
            holds_per_day => 0,
758
        }
759
    }
770
);
760
);
771
761
772
#When patron category = $category_2 and itemtype = $itemtype2 then reservesallowed, holds_per_day and holds_per_record are 1
762
#When patron category = $category_2 and itemtype = $itemtype2 then reservesallowed, holds_per_day and holds_per_record are 1
773
$dbh->do(
763
Koha::CirculationRules->set_rules(
774
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_day, holds_per_record)
764
    {
775
     VALUES (?, ?, ?, ?, ?, ?)},
765
        branchcode   => $branch_1,
776
    {},
766
        categorycode => $category_2,
777
    $category_2, $branch_1, $itemtype2, 1, 1, 1
767
        itemtype     => $itemtype2,
768
        rules        => {
769
            reservesallowed => 1,
770
            holds_per_record => 1,
771
            holds_per_day => 1,
772
        }
773
    }
774
);
775
776
#When patron category = $category_1 and itemtype = $itemtype2 AND different branch, then reservesallowed, holds_per_day and holds_per_record are 0
777
Koha::CirculationRules->set_rules(
778
    {
779
        branchcode   => $branch_2,
780
        categorycode => $category_1,
781
        itemtype     => $itemtype2,
782
        rules        => {
783
            reservesallowed => 0,
784
            holds_per_record => 0,
785
            holds_per_day => 0,
786
        }
787
    }
778
);
788
);
779
789
790
#Create a new biblio record
791
my $bibnum3 = $builder->build_sample_biblio({frameworkcode => $frameworkcode})->biblionumber;
792
793
# Create an item from new itemtype
794
my $item2 = $builder->build_sample_item({
795
    homebranch => $branch_1,
796
    holdingbranch => $branch_1,
797
    itype => $itemtype2,
798
    barcode => 'bug23172_CPL',
799
    biblionumber => $bibnum3
800
});
801
802
#Create two new patrons
803
my $patronnumcat1 = Koha::Patron->new({branchcode => $branch_1, categorycode => $category_1})->store->borrowernumber;
804
my $patronnumcat2 = Koha::Patron->new({branchcode => $branch_1, categorycode => $category_2})->store->borrowernumber;
805
my $patronnumcat3 = Koha::Patron->new({branchcode => $branch_2, categorycode => $category_1})->store->borrowernumber;
806
780
#Remove existing reserves
807
#Remove existing reserves
781
$dbh->do("DELETE FROM reserves");
808
$dbh->do("DELETE FROM reserves");
782
809
783
#Create Bib-level hold for borrower who has a patron category of $category_2
784
my $reserveid2 = AddReserve($branch_1,  $patronnumcat2, $bibnum3);
785
786
#Bib-level hold for borrower who has a patron category of $category_1
810
#Bib-level hold for borrower who has a patron category of $category_1
787
my $reserveid1 = AddReserve($branch_1,  $patronnumcat1, $bibnum3 );
811
my $reserveid1 = AddReserve({
812
    branchcode => $branch_1,
813
    borrowernumber => $patronnumcat1,
814
    biblionumber => $bibnum3
815
});
816
817
#Create Bib-level hold for borrower who has a patron category of $category_2
818
my $reserveid2 = AddReserve({
819
    branchcode => $branch_1,
820
    borrowernumber => $patronnumcat2,
821
    biblionumber => $bibnum3
822
});
788
823
789
#Check bib-level hold priority and confirm hold made by patronnumcat1 (who fits into issuingrule with reserveallowed = 0) has first priority
824
#Check bib-level hold priority and confirm hold made by patronnumcat1 (who fits into issuingrule with reserveallowed = 0) has first priority
790
my $reserve1 = Koha::Holds->find($reserveid1);
825
my $reserve1 = Koha::Holds->find($reserveid1);
Lines 793-819 is( $reserve1->priority, 1, 'patronnumcat1 reserve is first priority'); Link Here
793
my $reserve2 = Koha::Holds->find($reserveid2);
828
my $reserve2 = Koha::Holds->find($reserveid2);
794
is( $reserve2->priority, 2, 'patronnumcat2 reserve is second priority');
829
is( $reserve2->priority, 2, 'patronnumcat2 reserve is second priority');
795
830
796
#Return the item
831
#Test with ReservesControlBranch system preference set to ItemHomeLibrary
832
t::lib::Mocks::mock_preference('ReservesControlBranch', 'ItemHomeLibrary');
833
834
# Reserve 1 should be skipped because the circ rule for that patron's category does not allow reserves
797
(undef, $messages, undef, undef) = AddReturn('bug23172_CPL', $branch_1);
835
(undef, $messages, undef, undef) = AddReturn('bug23172_CPL', $branch_1);
798
836
799
#First priority hold is skipped as issuingrule is checked and the first hold does not respect issuingrules (as one of the three fields: reservesallowed, holds_per_day is 0) therefore not allocating item to this bib-level hold
837
#First priority hold is skipped as issuingrule is checked and the first hold does not respect issuingrules (as one of the three fields: reservesallowed, holds_per_day is 0) therefore not allocating item to this bib-level hold
800
is( $messages->{ResFound}->{borrowernumber}, $patronnumcat2,'Skip allocating item to first priority hold as it does not respect issuingrules instead allocate to next valid hold (bug 23172)');
838
is( $messages->{ResFound}->{borrowernumber}, $patronnumcat2,'First priority hold is skipped because circulation rules disallow holds for this patron category, so item is allocated to next hold.');
801
839
802
#Remove and re-add the issuing rule that prevented patronnumcat1 bib-level hold from being allocated upon item return making reservesallowed, holds_per_day and holds_per_record > 0
840
#Remove existing reserves
803
$dbh->do(q{DELETE FROM issuingrules WHERE categorycode = ? AND branchcode = ? AND itemtype = ?},
841
$dbh->do("DELETE FROM reserves");
804
        {},
842
805
        $category_1, $branch_1, $itemtype2
843
#Bib-level hold for borrower who has a patron category of $category_1
806
);
844
my $reserveid3 = AddReserve({
807
$dbh->do(
845
    branchcode => $branch_1,
808
   q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_day, holds_per_record)
846
    borrowernumber => $patronnumcat3,
809
    VALUES (?, ?, ?, ?, ?, ?)},
847
    biblionumber => $bibnum3
810
   {},
848
});
811
   $category_1, $branch_1, $itemtype2, 1, 1, 1
849
850
#Create Bib-level hold for borrower who has a patron category of $category_2
851
my $reserveid4 = AddReserve({
852
    branchcode => $branch_1,
853
    borrowernumber => $patronnumcat2,
854
    biblionumber => $bibnum3
855
});
856
857
#Test with ReservesControlBranch system preference set to PatronLibrary
858
t::lib::Mocks::mock_preference('ReservesControlBranch', 'PatronLibrary');
859
860
# Reserve 1 should be skipped because the circ rule for that patron's library does not allow reserves
861
(undef, $messages, undef, undef) = AddReturn('bug23172_CPL', $branch_1);
862
863
#First priority hold is skipped as issuingrule is checked and the first hold does not respect issuingrules (as one of the three fields: reservesallowed, holds_per_day is 0) therefore not allocating item to this bib-level hold
864
is( $messages->{ResFound}->{borrowernumber}, $patronnumcat2,'First priority hold is skipped because circulation rules disallow holds for this branch, so item is allocated to next hold.');
865
866
# Update the circulation rule that prevented patronnumcat3 bib-level hold from being allocated upon item return making reservesallowed, holds_per_day and holds_per_record > 0
867
Koha::CirculationRules->set_rules(
868
    {
869
        branchcode   => $branch_2,
870
        categorycode => $category_1,
871
        itemtype     => $itemtype2,
872
        rules        => {
873
            reservesallowed => 1,
874
            holds_per_record => 1,
875
            holds_per_day => 1,
876
        }
877
    }
812
);
878
);
813
879
814
#Return the item again and notice this time it is allocated to the bib-level hold made by patronnumcat1
880
#Return the item again and notice this time it is allocated to the bib-level hold made by patronnumcat1
815
(undef, $messages, undef, undef) = AddReturn('bug23172_CPL', $branch_1);
881
(undef, $messages, undef, undef) = AddReturn('bug23172_CPL', $branch_1);
816
is( $messages->{ResFound}->{borrowernumber}, $patronnumcat1,'Skip allocating item to first priority hold as it does not respect issuingrules instead allocate to next valid hold (bug 23172)');
882
is( $messages->{ResFound}->{borrowernumber}, $patronnumcat3,'Skip allocating item to first priority hold as it does not respect issuingrules instead allocate to next valid hold (bug 23172)');
817
883
818
$cache->clear_from_cache("MarcStructure-0-$frameworkcode");
884
$cache->clear_from_cache("MarcStructure-0-$frameworkcode");
819
$cache->clear_from_cache("MarcStructure-1-$frameworkcode");
885
$cache->clear_from_cache("MarcStructure-1-$frameworkcode");
820
- 

Return to bug 23172