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

(-)a/C4/Circulation.pm (+1 lines)
Lines 2062-2067 sub AddReturn { Link Here
2062
    my ($resfound, $resrec);
2062
    my ($resfound, $resrec);
2063
    my $lookahead= C4::Context->preference('ConfirmFutureHolds'); #number of days to look for future holds
2063
    my $lookahead= C4::Context->preference('ConfirmFutureHolds'); #number of days to look for future holds
2064
    ($resfound, $resrec, undef) = C4::Reserves::CheckReserves( $item->itemnumber, undef, $lookahead ) unless ( $item->withdrawn );
2064
    ($resfound, $resrec, undef) = C4::Reserves::CheckReserves( $item->itemnumber, undef, $lookahead ) unless ( $item->withdrawn );
2065
2065
    if ($resfound) {
2066
    if ($resfound) {
2066
          $resrec->{'ResFound'} = $resfound;
2067
          $resrec->{'ResFound'} = $resfound;
2067
        $messages->{'ResFound'} = $resrec;
2068
        $messages->{'ResFound'} = $resrec;
(-)a/C4/Reserves.pm (-4 / +1 lines)
Lines 214-220 sub AddReserve { Link Here
214
        }
214
        }
215
    )->store();
215
    )->store();
216
    $hold->set_waiting() if $found eq 'W';
216
    $hold->set_waiting() if $found eq 'W';
217
218
    logaction( 'HOLDS', 'CREATE', $hold->id, Dumper($hold->unblessed) )
217
    logaction( 'HOLDS', 'CREATE', $hold->id, Dumper($hold->unblessed) )
219
        if C4::Context->preference('HoldsLog');
218
        if C4::Context->preference('HoldsLog');
220
219
Lines 378-383 sub CanItemBeReserved { Link Here
378
            found          => undef, # Found holds don't count against a patron's holds limit
377
            found          => undef, # Found holds don't count against a patron's holds limit
379
        }
378
        }
380
    );
379
    );
380
381
    if ( $holds->count() >= $holds_per_record ) {
381
    if ( $holds->count() >= $holds_per_record ) {
382
        return { status => "tooManyHoldsForThisRecord", limit => $holds_per_record };
382
        return { status => "tooManyHoldsForThisRecord", limit => $holds_per_record };
383
    }
383
    }
Lines 760-766 sub CheckReserves { Link Here
760
760
761
        my $priority = 10000000;
761
        my $priority = 10000000;
762
        foreach my $res (@reserves) {
762
        foreach my $res (@reserves) {
763
764
            #Before allocating to bib-level hold check if reserve respects hold rule, i.e. can patron category/item type combination allow reserves
763
            #Before allocating to bib-level hold check if reserve respects hold rule, i.e. can patron category/item type combination allow reserves
765
            my $checkreserve = Koha::Hold->check_if_existing_hold_matches_issuingrules( $res->{'borrowernumber'}, $itemnumber );
764
            my $checkreserve = Koha::Hold->check_if_existing_hold_matches_issuingrules( $res->{'borrowernumber'}, $itemnumber );
766
            next unless ($checkreserve eq 'OK');
765
            next unless ($checkreserve eq 'OK');
Lines 812-825 sub CheckReserves { Link Here
812
            }
811
            }
813
        }
812
        }
814
    }
813
    }
815
816
    # If we get this far, then no exact match was found.
814
    # If we get this far, then no exact match was found.
817
    # We return the most important (i.e. next) reservation.
815
    # We return the most important (i.e. next) reservation.
818
    if ($highest) {
816
    if ($highest) {
819
        $highest->{'itemnumber'} = $item;
817
        $highest->{'itemnumber'} = $item;
820
        return ( "Reserved", $highest, \@reserves );
818
        return ( "Reserved", $highest, \@reserves );
821
    }
819
    }
822
823
    return ( '' );
820
    return ( '' );
824
}
821
}
825
822
(-)a/t/db_dependent/Circulation.t (-4 / +11 lines)
Lines 259-270 $dbh->do( Link Here
259
                                issuelength, lengthunit,
259
                                issuelength, lengthunit,
260
                                renewalsallowed, renewalperiod,
260
                                renewalsallowed, renewalperiod,
261
                                norenewalbefore, auto_renew,
261
                                norenewalbefore, auto_renew,
262
                                fine, chargeperiod)
262
                                fine, chargeperiod,
263
                                holds_per_day, holds_per_record
264
                                )
263
      VALUES (?, ?, ?, ?,
265
      VALUES (?, ?, ?, ?,
264
              ?, ?,
266
              ?, ?,
265
              ?, ?,
267
              ?, ?,
266
              ?, ?,
268
              ?, ?,
267
              ?, ?
269
              ?, ?,
270
              ?,?
268
             )
271
             )
269
    },
272
    },
270
    {},
273
    {},
Lines 272-278 $dbh->do( Link Here
272
    14, 'days',
275
    14, 'days',
273
    1, 7,
276
    1, 7,
274
    undef, 0,
277
    undef, 0,
275
    .10, 1
278
    .10, 1,
279
    12,1
276
);
280
);
277
281
278
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
282
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
Lines 1193-1199 subtest "AllowRenewalIfOtherItemsAvailable tests" => sub { Link Here
1193
        undef, undef, undef
1197
        undef, undef, undef
1194
    );
1198
    );
1195
1199
1196
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0");
1200
    C4::Context->dbh->do("UPDATE issuingrules SET onshelfholds = 0, holds_per_day = 1");
1197
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1201
    t::lib::Mocks::mock_preference( 'AllowRenewalIfOtherItemsAvailable', 0 );
1198
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1202
    ( $renewokay, $error ) = CanBookBeRenewed( $borrowernumber1, $item_1->itemnumber );
1199
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
1203
    is( $renewokay, 0, 'Bug 14337 - Verify the borrower cannot renew with a hold on the record if AllowRenewalIfOtherItemsAvailable and onshelfholds are disabled' );
Lines 2652-2657 subtest 'Set waiting flag' => sub { Link Here
2652
    my $biblio = $builder->build( { source => 'Biblio' } );
2656
    my $biblio = $builder->build( { source => 'Biblio' } );
2653
    my $biblioitem = $builder->build( { source => 'Biblioitem', value => { biblionumber => $biblio->{biblionumber} } } );
2657
    my $biblioitem = $builder->build( { source => 'Biblioitem', value => { biblionumber => $biblio->{biblionumber} } } );
2654
2658
2659
    C4::Context->dbh->do("UPDATE issuingrules SET reservesallowed = 1, holds_per_day = 1, holds_per_record = 1");
2660
2655
    my $item = $builder->build(
2661
    my $item = $builder->build(
2656
        {
2662
        {
2657
            source => 'Item',
2663
            source => 'Item',
Lines 2679-2684 subtest 'Set waiting flag' => sub { Link Here
2679
    my $hold = Koha::Holds->find( $reserve_id );
2685
    my $hold = Koha::Holds->find( $reserve_id );
2680
    is( $hold->found, 'T', 'Hold is in transit' );
2686
    is( $hold->found, 'T', 'Hold is in transit' );
2681
2687
2688
2682
    my ( $status ) = CheckReserves($item->{itemnumber});
2689
    my ( $status ) = CheckReserves($item->{itemnumber});
2683
    is( $status, 'Reserved', 'Hold is not waiting yet');
2690
    is( $status, 'Reserved', 'Hold is not waiting yet');
2684
2691
(-)a/t/db_dependent/Holds.t (-6 / +7 lines)
Lines 244-259 my ($foreign_item_bibnum, $foreign_item_bibitemnum, $foreign_itemnumber) Link Here
244
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_biblio->biblionumber);
244
  = AddItem({ homebranch => $branch_2, holdingbranch => $branch_2 } , $foreign_biblio->biblionumber);
245
$dbh->do('DELETE FROM issuingrules');
245
$dbh->do('DELETE FROM issuingrules');
246
$dbh->do(
246
$dbh->do(
247
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
247
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record, holds_per_day)
248
      VALUES (?, ?, ?, ?, ?)},
248
      VALUES (?, ?, ?, ?, ?, ?)},
249
    {},
249
    {},
250
    '*', '*', '*', 25, 99
250
    '*', '*', '*', 25, 99, 99
251
);
251
);
252
$dbh->do(
252
$dbh->do(
253
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record)
253
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record, holds_per_day)
254
      VALUES (?, ?, ?, ?, ?)},
254
      VALUES (?, ?, ?, ?, ?, ?)},
255
    {},
255
    {},
256
    '*', '*', 'CANNOT', 0, 99
256
    '*', '*', 'CANNOT', 1, 99, 99
257
);
257
);
258
258
259
# make sure some basic sysprefs are set
259
# make sure some basic sysprefs are set
Lines 330-335 AddReserve( Link Here
330
    '',
330
    '',
331
    1,
331
    1,
332
);
332
);
333
333
is(
334
is(
334
    CanItemBeReserved( $borrowernumbers[0], $itemnumber)->{status}, 'tooManyReserves',
335
    CanItemBeReserved( $borrowernumbers[0], $itemnumber)->{status}, 'tooManyReserves',
335
    "cannot request item if policy that matches on item-level item type forbids it"
336
    "cannot request item if policy that matches on item-level item type forbids it"
(-)a/t/db_dependent/Reserves.t (-5 / +96 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 61;
20
use Test::More tests => 65;
21
use Test::MockModule;
21
use Test::MockModule;
22
use Test::Warn;
22
use Test::Warn;
23
23
Lines 194-203 $dbh->do('DELETE FROM default_branch_item_rules'); Link Here
194
$dbh->do('DELETE FROM default_branch_circ_rules');
194
$dbh->do('DELETE FROM default_branch_circ_rules');
195
$dbh->do('DELETE FROM default_circ_rules');
195
$dbh->do('DELETE FROM default_circ_rules');
196
$dbh->do(
196
$dbh->do(
197
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
197
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_record, holds_per_day)
198
      VALUES (?, ?, ?, ?)},
198
      VALUES (?, ?, ?, ?, ?, ?)},
199
    {},
199
    {},
200
    '*', '*', '*', 25
200
    '*', '*', '*', 25, 1, 1
201
);
201
);
202
202
203
# CPL allows only its own patrons to request its items
203
# CPL allows only its own patrons to request its items
Lines 282-287 my $messages; Link Here
282
# the one placed by the CPL patron, as the other two patron's hold
282
# the one placed by the CPL patron, as the other two patron's hold
283
# requests cannot be filled by that item per policy.
283
# requests cannot be filled by that item per policy.
284
(undef, $messages, undef, undef) = AddReturn('bug10272_CPL', $branch_2);
284
(undef, $messages, undef, undef) = AddReturn('bug10272_CPL', $branch_2);
285
285
is( $messages->{ResFound}->{borrowernumber},
286
is( $messages->{ResFound}->{borrowernumber},
286
    $requesters{$branch_1},
287
    $requesters{$branch_1},
287
    'restrictive library\'s items only fill requests by own patrons (bug 10272)');
288
    'restrictive library\'s items only fill requests by own patrons (bug 10272)');
Lines 588-593 MoveReserve( $itemnumber, $borrowernumber ); Link Here
588
is( $status, 'Reserved', 'MoveReserve did not fill future hold of 3 days');
589
is( $status, 'Reserved', 'MoveReserve did not fill future hold of 3 days');
589
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
590
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
590
591
592
593
594
595
596
597
#Test bug 23172. Check when returning an item that any patron category/item type combinations that forbid reservation are skipped over
598
#when allocating the item to a bib-level hold
599
$dbh->do('DELETE FROM issuingrules');
600
601
#Create two new patrons
602
my $patronnumcat1 = Koha::Patron->new({branchcode => $branch_1, categorycode => $category_1})->store->borrowernumber;
603
my $patronnumcat2 = Koha::Patron->new({branchcode => $branch_1, categorycode => $category_2})->store->borrowernumber;
604
605
#Create a new biblio record
606
my $bibnum3 = $builder->build_sample_biblio({frameworkcode => $frameworkcode})->biblionumber;
607
608
#Create a second item type
609
my $itemtype2 = $builder->build({ source => 'Itemtype', value => { notforloan => undef } } )->{itemtype};
610
611
# Create an item from new itemtype
612
my ( $item_bibnum2, $item_bibitemnum2, $itemnumber2 ) = AddItem(
613
    {   homebranch    => $branch_1,
614
        holdingbranch => $branch_1,
615
        itype         => $itemtype2,
616
        barcode       => 'bug23172_CPL'
617
    },
618
    $bibnum3
619
);
620
621
#Make a general All patron category/all item type rule
622
$dbh->do(
623
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_day, holds_per_record)
624
      VALUES (?, ?, ?, ?, ?, ?)},
625
    {},
626
    '*', '*', '*', 25, 1, 1
627
);
628
629
#When patron category = $category_1 and itemtype = $itemtype1 then reservesallowed, holds_per_day and holds_per_record are 0
630
$dbh->do(
631
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_day, holds_per_record)
632
     VALUES (?, ?, ?, ?, ?, ?)},
633
    {},
634
    $category_1, $branch_1, $itemtype2, 0, 1, 1
635
);
636
637
#When patron category = $category_2 and itemtype = $itemtype2 then reservesallowed, holds_per_day and holds_per_record are 1
638
$dbh->do(
639
    q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_day, holds_per_record)
640
     VALUES (?, ?, ?, ?, ?, ?)},
641
    {},
642
    $category_2, $branch_1, $itemtype2, 1, 1, 1
643
);
644
645
#Remove existing reserves
646
$dbh->do("DELETE FROM reserves");
647
648
#Create Bib-level hold for borrower who has a patron category of $category_2
649
my $reserveid2 = AddReserve($branch_1,  $patronnumcat2, $bibnum3);
650
651
#Bib-level hold for borrower who has a patron category of $category_1
652
my $reserveid1 = AddReserve($branch_1,  $patronnumcat1, $bibnum3 );
653
654
#Check bib-level hold priority and confirm hold made by patronnumcat1 (who fits into issuingrule with reserveallowed = 0) has first priority
655
my $reserve1 = Koha::Holds->find($reserveid1);
656
is( $reserve1->priority, 1, 'patronnumcat1 reserve is first priority');
657
658
my $reserve2 = Koha::Holds->find($reserveid2);
659
is( $reserve2->priority, 2, 'patronnumcat2 reserve is second priority');
660
661
#Return the item
662
(undef, $messages, undef, undef) = AddReturn('bug23172_CPL', $branch_1);
663
664
#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
665
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)');
666
667
#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
668
$dbh->do(q{DELETE FROM issuingrules WHERE categorycode = ? AND branchcode = ? AND itemtype = ?},
669
        {},
670
        $category_1, $branch_1, $itemtype2
671
);
672
$dbh->do(
673
   q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed, holds_per_day, holds_per_record)
674
    VALUES (?, ?, ?, ?, ?, ?)},
675
   {},
676
   $category_1, $branch_1, $itemtype2, 1, 1, 1
677
);
678
679
#Return the item again and notice this time it is allocated to the bib-level hold made by patronnumcat1
680
(undef, $messages, undef, undef) = AddReturn('bug23172_CPL', $branch_1);
681
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)');
682
591
$cache->clear_from_cache("MarcStructure-0-$frameworkcode");
683
$cache->clear_from_cache("MarcStructure-0-$frameworkcode");
592
$cache->clear_from_cache("MarcStructure-1-$frameworkcode");
684
$cache->clear_from_cache("MarcStructure-1-$frameworkcode");
593
$cache->clear_from_cache("default_value_for_mod_marc-");
685
$cache->clear_from_cache("default_value_for_mod_marc-");
594
- 

Return to bug 23172