|
Lines 64-77
my $itemnumber = $builder->build_sample_item({ library => $branch_1, biblionumbe
Link Here
|
| 64 |
|
64 |
|
| 65 |
# Create some borrowers |
65 |
# Create some borrowers |
| 66 |
my @borrowernumbers; |
66 |
my @borrowernumbers; |
|
|
67 |
my @patrons; |
| 67 |
foreach (1..$borrowers_count) { |
68 |
foreach (1..$borrowers_count) { |
| 68 |
my $borrowernumber = Koha::Patron->new({ |
69 |
my $patron = Koha::Patron->new({ |
| 69 |
firstname => 'my firstname', |
70 |
firstname => 'my firstname', |
| 70 |
surname => 'my surname ' . $_, |
71 |
surname => 'my surname ' . $_, |
| 71 |
categorycode => $category->{categorycode}, |
72 |
categorycode => $category->{categorycode}, |
| 72 |
branchcode => $branch_1, |
73 |
branchcode => $branch_1, |
| 73 |
})->store->borrowernumber; |
74 |
})->store; |
| 74 |
push @borrowernumbers, $borrowernumber; |
75 |
push @patrons, $patron; |
|
|
76 |
push @borrowernumbers, $patron->borrowernumber; |
| 75 |
} |
77 |
} |
| 76 |
|
78 |
|
| 77 |
# Create five item level holds |
79 |
# Create five item level holds |
|
Lines 233-239
is( $hold->priority, '6', "Test AlterPriority(), move to bottom" );
Link Here
|
| 233 |
# IndependentBranches is OFF. |
235 |
# IndependentBranches is OFF. |
| 234 |
|
236 |
|
| 235 |
my $foreign_biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' }); |
237 |
my $foreign_biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' }); |
| 236 |
my $foreign_itemnumber = $builder->build_sample_item({ library => $branch_2, biblionumber => $foreign_biblio->biblionumber })->itemnumber; |
238 |
my $foreign_item = $builder->build_sample_item({ library => $branch_2, biblionumber => $foreign_biblio->biblionumber }); |
| 237 |
Koha::CirculationRules->set_rules( |
239 |
Koha::CirculationRules->set_rules( |
| 238 |
{ |
240 |
{ |
| 239 |
categorycode => undef, |
241 |
categorycode => undef, |
|
Lines 265-271
t::lib::Mocks::mock_preference('item-level_itypes', 1);
Link Here
|
| 265 |
t::lib::Mocks::mock_preference('IndependentBranches', 0); |
267 |
t::lib::Mocks::mock_preference('IndependentBranches', 0); |
| 266 |
|
268 |
|
| 267 |
is( |
269 |
is( |
| 268 |
CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status}, 'OK', |
270 |
CanItemBeReserved($patrons[0], $foreign_item)->{status}, 'OK', |
| 269 |
'$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)' |
271 |
'$branch_1 patron allowed to reserve $branch_2 item with IndependentBranches OFF (bug 2394)' |
| 270 |
); |
272 |
); |
| 271 |
|
273 |
|
|
Lines 273-286
is(
Link Here
|
| 273 |
t::lib::Mocks::mock_preference('IndependentBranches', 1); |
275 |
t::lib::Mocks::mock_preference('IndependentBranches', 1); |
| 274 |
t::lib::Mocks::mock_preference('canreservefromotherbranches', 0); |
276 |
t::lib::Mocks::mock_preference('canreservefromotherbranches', 0); |
| 275 |
ok( |
277 |
ok( |
| 276 |
CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status} eq 'cannotReserveFromOtherBranches', |
278 |
CanItemBeReserved($patrons[0], $foreign_item)->{status} eq 'cannotReserveFromOtherBranches', |
| 277 |
'$branch_1 patron NOT allowed to reserve $branch_2 item with IndependentBranches ON ... (bug 2394)' |
279 |
'$branch_1 patron NOT allowed to reserve $branch_2 item with IndependentBranches ON ... (bug 2394)' |
| 278 |
); |
280 |
); |
| 279 |
|
281 |
|
| 280 |
# ... unless canreservefromotherbranches is ON |
282 |
# ... unless canreservefromotherbranches is ON |
| 281 |
t::lib::Mocks::mock_preference('canreservefromotherbranches', 1); |
283 |
t::lib::Mocks::mock_preference('canreservefromotherbranches', 1); |
| 282 |
ok( |
284 |
ok( |
| 283 |
CanItemBeReserved($borrowernumbers[0], $foreign_itemnumber)->{status} eq 'OK', |
285 |
CanItemBeReserved($patrons[0], $foreign_item)->{status} eq 'OK', |
| 284 |
'... unless canreservefromotherbranches is ON (bug 2394)' |
286 |
'... unless canreservefromotherbranches is ON (bug 2394)' |
| 285 |
); |
287 |
); |
| 286 |
|
288 |
|
|
Lines 325-333
ok(
Link Here
|
| 325 |
is( $hold3->discard_changes->priority, 1, "After ModReserve, the 3rd reserve becomes the first on the waiting list" ); |
327 |
is( $hold3->discard_changes->priority, 1, "After ModReserve, the 3rd reserve becomes the first on the waiting list" ); |
| 326 |
} |
328 |
} |
| 327 |
|
329 |
|
| 328 |
Koha::Items->find($itemnumber)->damaged(1)->store; # FIXME The $itemnumber is a bit confusing here |
330 |
my $damaged_item = Koha::Items->find($itemnumber)->damaged(1)->store; # FIXME The $itemnumber is a bit confusing here |
| 329 |
t::lib::Mocks::mock_preference( 'AllowHoldsOnDamagedItems', 1 ); |
331 |
t::lib::Mocks::mock_preference( 'AllowHoldsOnDamagedItems', 1 ); |
| 330 |
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber)->{status}, 'OK', "Patron can reserve damaged item with AllowHoldsOnDamagedItems enabled" ); |
332 |
is( CanItemBeReserved( $patrons[0], $damaged_item)->{status}, 'OK', "Patron can reserve damaged item with AllowHoldsOnDamagedItems enabled" ); |
| 331 |
ok( defined( ( CheckReserves($itemnumber) )[1] ), "Hold can be trapped for damaged item with AllowHoldsOnDamagedItems enabled" ); |
333 |
ok( defined( ( CheckReserves($itemnumber) )[1] ), "Hold can be trapped for damaged item with AllowHoldsOnDamagedItems enabled" ); |
| 332 |
|
334 |
|
| 333 |
$hold = Koha::Hold->new( |
335 |
$hold = Koha::Hold->new( |
|
Lines 337-356
$hold = Koha::Hold->new(
Link Here
|
| 337 |
biblionumber => $biblio->biblionumber, |
339 |
biblionumber => $biblio->biblionumber, |
| 338 |
} |
340 |
} |
| 339 |
)->store(); |
341 |
)->store(); |
| 340 |
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status}, |
342 |
is( CanItemBeReserved( $patrons[0], $damaged_item )->{status}, |
| 341 |
'itemAlreadyOnHold', |
343 |
'itemAlreadyOnHold', |
| 342 |
"Patron cannot place a second item level hold for a given item" ); |
344 |
"Patron cannot place a second item level hold for a given item" ); |
| 343 |
$hold->delete(); |
345 |
$hold->delete(); |
| 344 |
|
346 |
|
| 345 |
t::lib::Mocks::mock_preference( 'AllowHoldsOnDamagedItems', 0 ); |
347 |
t::lib::Mocks::mock_preference( 'AllowHoldsOnDamagedItems', 0 ); |
| 346 |
ok( CanItemBeReserved( $borrowernumbers[0], $itemnumber)->{status} eq 'damaged', "Patron cannot reserve damaged item with AllowHoldsOnDamagedItems disabled" ); |
348 |
ok( CanItemBeReserved( $patrons[0], $damaged_item)->{status} eq 'damaged', "Patron cannot reserve damaged item with AllowHoldsOnDamagedItems disabled" ); |
| 347 |
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for damaged item with AllowHoldsOnDamagedItems disabled" ); |
349 |
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for damaged item with AllowHoldsOnDamagedItems disabled" ); |
| 348 |
|
350 |
|
| 349 |
# Items that are not for loan, but holdable should not be trapped until they are available for loan |
351 |
# Items that are not for loan, but holdable should not be trapped until they are available for loan |
| 350 |
t::lib::Mocks::mock_preference( 'TrapHoldsOnOrder', 0 ); |
352 |
t::lib::Mocks::mock_preference( 'TrapHoldsOnOrder', 0 ); |
| 351 |
Koha::Items->find($itemnumber)->damaged(0)->notforloan(-1)->store; |
353 |
my $nfl_item = Koha::Items->find($itemnumber)->damaged(0)->notforloan(-1)->store; |
| 352 |
Koha::Holds->search({ biblionumber => $biblio->id })->delete(); |
354 |
Koha::Holds->search({ biblionumber => $biblio->id })->delete(); |
| 353 |
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber)->{status}, 'OK', "Patron can place hold on item that is not for loan but holdable ( notforloan < 0 )" ); |
355 |
is( CanItemBeReserved( $patrons[0], $nfl_item)->{status}, 'OK', "Patron can place hold on item that is not for loan but holdable ( notforloan < 0 )" ); |
| 354 |
$hold = Koha::Hold->new( |
356 |
$hold = Koha::Hold->new( |
| 355 |
{ |
357 |
{ |
| 356 |
borrowernumber => $borrowernumbers[0], |
358 |
borrowernumber => $borrowernumbers[0], |
|
Lines 370-380
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for i
Link Here
|
| 370 |
t::lib::Mocks::mock_preference( 'SkipHoldTrapOnNotForLoanValue', '-1|1' ); |
372 |
t::lib::Mocks::mock_preference( 'SkipHoldTrapOnNotForLoanValue', '-1|1' ); |
| 371 |
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for item with notforloan value matching SkipHoldTrapOnNotForLoanValue" ); |
373 |
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for item with notforloan value matching SkipHoldTrapOnNotForLoanValue" ); |
| 372 |
is( |
374 |
is( |
| 373 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber)->{status}, 'itemAlreadyOnHold', |
375 |
CanItemBeReserved( $patrons[0], $nfl_item)->{status}, 'itemAlreadyOnHold', |
| 374 |
"cannot request item that you have already reservedd" |
376 |
"cannot request item that you have already reservedd" |
| 375 |
); |
377 |
); |
| 376 |
is( |
378 |
is( |
| 377 |
CanItemBeReserved( $borrowernumbers[0], $item->itemnumber, undef, { ignore_hold_counts => 1 })->{status}, 'OK', |
379 |
CanItemBeReserved( $patrons[0], $item, undef, { ignore_hold_counts => 1 })->{status}, 'OK', |
| 378 |
"can request item if we are not checking holds counts, but only if policy allows or forbids it" |
380 |
"can request item if we are not checking holds counts, but only if policy allows or forbids it" |
| 379 |
); |
381 |
); |
| 380 |
$hold->delete(); |
382 |
$hold->delete(); |
|
Lines 391-401
AddReserve(
Link Here
|
| 391 |
} |
393 |
} |
| 392 |
); |
394 |
); |
| 393 |
is( |
395 |
is( |
| 394 |
CanItemBeReserved( $borrowernumbers[0], $item->itemnumber)->{status}, 'noReservesAllowed', |
396 |
CanItemBeReserved( $patrons[0], $item)->{status}, 'noReservesAllowed', |
| 395 |
"cannot request item if policy that matches on item-level item type forbids it" |
397 |
"cannot request item if policy that matches on item-level item type forbids it" |
| 396 |
); |
398 |
); |
| 397 |
is( |
399 |
is( |
| 398 |
CanItemBeReserved( $borrowernumbers[0], $item->itemnumber, undef, { ignore_hold_counts => 1 })->{status}, 'noReservesAllowed', |
400 |
CanItemBeReserved( $patrons[0], $item, undef, { ignore_hold_counts => 1 })->{status}, 'noReservesAllowed', |
| 399 |
"cannot request item if policy that matches on item-level item type forbids it even if ignoring counts" |
401 |
"cannot request item if policy that matches on item-level item type forbids it even if ignoring counts" |
| 400 |
); |
402 |
); |
| 401 |
|
403 |
|
|
Lines 468-501
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 468 |
my $biblionumber_can = $builder->build_sample_biblio({ itemtype => $itemtype_can })->biblionumber; |
470 |
my $biblionumber_can = $builder->build_sample_biblio({ itemtype => $itemtype_can })->biblionumber; |
| 469 |
my $biblionumber_record_cannot = $builder->build_sample_biblio({ itemtype => $itemtype_cant_record })->biblionumber; |
471 |
my $biblionumber_record_cannot = $builder->build_sample_biblio({ itemtype => $itemtype_cant_record })->biblionumber; |
| 470 |
|
472 |
|
| 471 |
my $itemnumber_1_can = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_cannot })->itemnumber; |
473 |
my $item_1_can = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_cannot }); |
| 472 |
my $itemnumber_1_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant, biblionumber => $biblionumber_cannot })->itemnumber; |
474 |
my $item_1_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant, biblionumber => $biblionumber_cannot }); |
| 473 |
my $itemnumber_2_can = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_can })->itemnumber; |
475 |
my $item_2_can = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_can }); |
| 474 |
my $itemnumber_2_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant, biblionumber => $biblionumber_can })->itemnumber; |
476 |
my $item_2_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant, biblionumber => $biblionumber_can }); |
| 475 |
my $itemnumber_3_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant_record, biblionumber => $biblionumber_record_cannot })->itemnumber; |
477 |
my $item_3_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant_record, biblionumber => $biblionumber_record_cannot }); |
| 476 |
|
478 |
|
| 477 |
Koha::Holds->search({borrowernumber => $borrowernumbers[0]})->delete; |
479 |
Koha::Holds->search({borrowernumber => $borrowernumbers[0]})->delete; |
| 478 |
|
480 |
|
| 479 |
t::lib::Mocks::mock_preference('item-level_itypes', 1); |
481 |
t::lib::Mocks::mock_preference('item-level_itypes', 1); |
| 480 |
is( |
482 |
is( |
| 481 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_2_cannot)->{status}, 'noReservesAllowed', |
483 |
CanItemBeReserved( $patrons[0], $item_2_cannot)->{status}, 'noReservesAllowed', |
| 482 |
"With item level set, rule from item must be picked (CANNOT)" |
484 |
"With item level set, rule from item must be picked (CANNOT)" |
| 483 |
); |
485 |
); |
| 484 |
is( |
486 |
is( |
| 485 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_1_can)->{status}, 'OK', |
487 |
CanItemBeReserved( $patrons[0], $item_1_can)->{status}, 'OK', |
| 486 |
"With item level set, rule from item must be picked (CAN)" |
488 |
"With item level set, rule from item must be picked (CAN)" |
| 487 |
); |
489 |
); |
| 488 |
t::lib::Mocks::mock_preference('item-level_itypes', 0); |
490 |
t::lib::Mocks::mock_preference('item-level_itypes', 0); |
| 489 |
is( |
491 |
is( |
| 490 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_1_can)->{status}, 'noReservesAllowed', |
492 |
CanItemBeReserved( $patrons[0], $item_1_can)->{status}, 'noReservesAllowed', |
| 491 |
"With biblio level set, rule from biblio must be picked (CANNOT)" |
493 |
"With biblio level set, rule from biblio must be picked (CANNOT)" |
| 492 |
); |
494 |
); |
| 493 |
is( |
495 |
is( |
| 494 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_2_cannot)->{status}, 'OK', |
496 |
CanItemBeReserved( $patrons[0], $item_2_cannot)->{status}, 'OK', |
| 495 |
"With biblio level set, rule from biblio must be picked (CAN)" |
497 |
"With biblio level set, rule from biblio must be picked (CAN)" |
| 496 |
); |
498 |
); |
| 497 |
is( |
499 |
is( |
| 498 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_3_cannot)->{status}, 'noReservesAllowed', |
500 |
CanItemBeReserved( $patrons[0], $item_3_cannot)->{status}, 'noReservesAllowed', |
| 499 |
"When no holds allowed and no holds per record allowed should return noReservesAllowed" |
501 |
"When no holds allowed and no holds per record allowed should return noReservesAllowed" |
| 500 |
); |
502 |
); |
| 501 |
}; |
503 |
}; |
|
Lines 504-514
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 504 |
plan tests => 7; |
506 |
plan tests => 7; |
| 505 |
|
507 |
|
| 506 |
my $biblionumber_1 = $builder->build_sample_biblio({ itemtype => $itemtype_can })->biblionumber; |
508 |
my $biblionumber_1 = $builder->build_sample_biblio({ itemtype => $itemtype_can })->biblionumber; |
| 507 |
my $itemnumber_11 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_1 })->itemnumber; |
509 |
my $item_11 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_1 }); |
| 508 |
my $itemnumber_12 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_1 })->itemnumber; |
510 |
my $item_12 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_1 }); |
| 509 |
my $biblionumber_2 = $builder->build_sample_biblio({ itemtype => $itemtype_can })->biblionumber; |
511 |
my $biblionumber_2 = $builder->build_sample_biblio({ itemtype => $itemtype_can })->biblionumber; |
| 510 |
my $itemnumber_21 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_2 })->itemnumber; |
512 |
my $item_21 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_2 }); |
| 511 |
my $itemnumber_22 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_2 })->itemnumber; |
513 |
my $item_22 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_2 }); |
| 512 |
|
514 |
|
| 513 |
Koha::Holds->search({borrowernumber => $borrowernumbers[0]})->delete; |
515 |
Koha::Holds->search({borrowernumber => $borrowernumbers[0]})->delete; |
| 514 |
|
516 |
|
|
Lines 522-528
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 522 |
t::lib::Mocks::mock_preference('item-level_itypes', $item_level); |
524 |
t::lib::Mocks::mock_preference('item-level_itypes', $item_level); |
| 523 |
is( |
525 |
is( |
| 524 |
# FIXME This is not really correct, but CanItemBeReserved does not check if biblio-level holds already exist |
526 |
# FIXME This is not really correct, but CanItemBeReserved does not check if biblio-level holds already exist |
| 525 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_11)->{status}, 'OK', |
527 |
CanItemBeReserved( $patrons[0], $item_11)->{status}, 'OK', |
| 526 |
"A biblio-level hold already exists - another hold can be placed on a specific item item" |
528 |
"A biblio-level hold already exists - another hold can be placed on a specific item item" |
| 527 |
); |
529 |
); |
| 528 |
} |
530 |
} |
|
Lines 533-539
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 533 |
branch => $branch_1, |
535 |
branch => $branch_1, |
| 534 |
borrowernumber => $borrowernumbers[0], |
536 |
borrowernumber => $borrowernumbers[0], |
| 535 |
biblionumber => $biblionumber_1, |
537 |
biblionumber => $biblionumber_1, |
| 536 |
itemnumber => $itemnumber_11, |
538 |
itemnumber => $item_11->itemnumber, |
| 537 |
}); |
539 |
}); |
| 538 |
|
540 |
|
| 539 |
$dbh->do('DELETE FROM circulation_rules'); |
541 |
$dbh->do('DELETE FROM circulation_rules'); |
|
Lines 549-555
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 549 |
} |
551 |
} |
| 550 |
); |
552 |
); |
| 551 |
is( |
553 |
is( |
| 552 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_12)->{status}, 'tooManyHoldsForThisRecord', |
554 |
CanItemBeReserved( $patrons[0], $item_12)->{status}, 'tooManyHoldsForThisRecord', |
| 553 |
"A item-level hold already exists and holds_per_record=1, another hold cannot be placed on this record" |
555 |
"A item-level hold already exists and holds_per_record=1, another hold cannot be placed on this record" |
| 554 |
); |
556 |
); |
| 555 |
Koha::CirculationRules->set_rules( |
557 |
Koha::CirculationRules->set_rules( |
|
Lines 564-570
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 564 |
} |
566 |
} |
| 565 |
); |
567 |
); |
| 566 |
is( |
568 |
is( |
| 567 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_12)->{status}, 'tooManyHoldsForThisRecord', |
569 |
CanItemBeReserved( $patrons[0], $item_12)->{status}, 'tooManyHoldsForThisRecord', |
| 568 |
"A item-level hold already exists and holds_per_record=1 - tooManyHoldsForThisRecord has priority over tooManyReserves" |
570 |
"A item-level hold already exists and holds_per_record=1 - tooManyHoldsForThisRecord has priority over tooManyReserves" |
| 569 |
); |
571 |
); |
| 570 |
Koha::CirculationRules->set_rules( |
572 |
Koha::CirculationRules->set_rules( |
|
Lines 579-585
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 579 |
} |
581 |
} |
| 580 |
); |
582 |
); |
| 581 |
is( |
583 |
is( |
| 582 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_12)->{status}, 'OK', |
584 |
CanItemBeReserved( $patrons[0], $item_12)->{status}, 'OK', |
| 583 |
"A item-level hold already exists but holds_per_record=2- another item-level hold can be placed on this record" |
585 |
"A item-level hold already exists but holds_per_record=2- another item-level hold can be placed on this record" |
| 584 |
); |
586 |
); |
| 585 |
|
587 |
|
|
Lines 587-593
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 587 |
branch => $branch_1, |
589 |
branch => $branch_1, |
| 588 |
borrowernumber => $borrowernumbers[0], |
590 |
borrowernumber => $borrowernumbers[0], |
| 589 |
biblionumber => $biblionumber_2, |
591 |
biblionumber => $biblionumber_2, |
| 590 |
itemnumber => $itemnumber_21 |
592 |
itemnumber => $item_21->itemnumber |
| 591 |
}); |
593 |
}); |
| 592 |
Koha::CirculationRules->set_rules( |
594 |
Koha::CirculationRules->set_rules( |
| 593 |
{ |
595 |
{ |
|
Lines 601-611
subtest 'CanItemBeReserved' => sub {
Link Here
|
| 601 |
} |
603 |
} |
| 602 |
); |
604 |
); |
| 603 |
is( |
605 |
is( |
| 604 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_21)->{status}, 'itemAlreadyOnHold', |
606 |
CanItemBeReserved( $patrons[0], $item_21)->{status}, 'itemAlreadyOnHold', |
| 605 |
"A item-level holds already exists on this item, itemAlreadyOnHold should be raised" |
607 |
"A item-level holds already exists on this item, itemAlreadyOnHold should be raised" |
| 606 |
); |
608 |
); |
| 607 |
is( |
609 |
is( |
| 608 |
CanItemBeReserved( $borrowernumbers[0], $itemnumber_22)->{status}, 'tooManyReserves', |
610 |
CanItemBeReserved( $patrons[0], $item_22)->{status}, 'tooManyReserves', |
| 609 |
"This patron has already placed reservesallowed holds, tooManyReserves should be raised" |
611 |
"This patron has already placed reservesallowed holds, tooManyReserves should be raised" |
| 610 |
); |
612 |
); |
| 611 |
}; |
613 |
}; |
|
Lines 647-668
Koha::CirculationRules->set_rules(
Link Here
|
| 647 |
} |
649 |
} |
| 648 |
); |
650 |
); |
| 649 |
$biblio = $builder->build_sample_biblio({ itemtype => 'CANNOT' }); |
651 |
$biblio = $builder->build_sample_biblio({ itemtype => 'CANNOT' }); |
| 650 |
$itemnumber = $builder->build_sample_item({ library => $branch_1, itype => 'CANNOT', biblionumber => $biblio->biblionumber})->itemnumber; |
652 |
my $branch_rule_item = $builder->build_sample_item({ library => $branch_1, itype => 'CANNOT', biblionumber => $biblio->biblionumber}); |
| 651 |
is(CanItemBeReserved($borrowernumbers[0], $itemnumber)->{status}, 'notReservable', |
653 |
is(CanItemBeReserved($patrons[0], $branch_rule_item)->{status}, 'notReservable', |
| 652 |
"CanItemBeReserved should return 'notReservable'"); |
654 |
"CanItemBeReserved should return 'notReservable'"); |
| 653 |
|
655 |
|
| 654 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' ); |
656 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' ); |
| 655 |
$itemnumber = $builder->build_sample_item({ library => $branch_2, itype => 'CAN', biblionumber => $biblio->biblionumber})->itemnumber; |
657 |
$branch_rule_item = $builder->build_sample_item({ library => $branch_2, itype => 'CAN', biblionumber => $biblio->biblionumber}); |
| 656 |
is(CanItemBeReserved($borrowernumbers[0], $itemnumber)->{status}, |
658 |
is(CanItemBeReserved($patrons[0], $branch_rule_item)->{status}, |
| 657 |
'cannotReserveFromOtherBranches', |
659 |
'cannotReserveFromOtherBranches', |
| 658 |
"CanItemBeReserved should use PatronLibrary rule when ReservesControlBranch set to 'PatronLibrary'"); |
660 |
"CanItemBeReserved should use PatronLibrary rule when ReservesControlBranch set to 'PatronLibrary'"); |
| 659 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'ItemHomeLibrary' ); |
661 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'ItemHomeLibrary' ); |
| 660 |
is(CanItemBeReserved($borrowernumbers[0], $itemnumber)->{status}, |
662 |
is(CanItemBeReserved($patrons[0], $branch_rule_item)->{status}, |
| 661 |
'OK', |
663 |
'OK', |
| 662 |
"CanItemBeReserved should use item home library rule when ReservesControlBranch set to 'ItemsHomeLibrary'"); |
664 |
"CanItemBeReserved should use item home library rule when ReservesControlBranch set to 'ItemsHomeLibrary'"); |
| 663 |
|
665 |
|
| 664 |
$itemnumber = $builder->build_sample_item({ library => $branch_1, itype => 'CAN', biblionumber => $biblio->biblionumber})->itemnumber; |
666 |
$branch_rule_item = $builder->build_sample_item({ library => $branch_1, itype => 'CAN', biblionumber => $biblio->biblionumber}); |
| 665 |
is(CanItemBeReserved($borrowernumbers[0], $itemnumber)->{status}, 'OK', |
667 |
is(CanItemBeReserved($patrons[0], $branch_rule_item)->{status}, 'OK', |
| 666 |
"CanItemBeReserved should return 'OK'"); |
668 |
"CanItemBeReserved should return 'OK'"); |
| 667 |
|
669 |
|
| 668 |
# Bug 12632 |
670 |
# Bug 12632 |
|
Lines 675-681
$dbh->do('DELETE FROM items');
Link Here
|
| 675 |
$dbh->do('DELETE FROM biblio'); |
677 |
$dbh->do('DELETE FROM biblio'); |
| 676 |
|
678 |
|
| 677 |
$biblio = $builder->build_sample_biblio({ itemtype => 'ONLY1' }); |
679 |
$biblio = $builder->build_sample_biblio({ itemtype => 'ONLY1' }); |
| 678 |
$itemnumber = $builder->build_sample_item({ library => $branch_1, biblionumber => $biblio->biblionumber})->itemnumber; |
680 |
my $limit_count_item = $builder->build_sample_item({ library => $branch_1, biblionumber => $biblio->biblionumber}); |
| 679 |
|
681 |
|
| 680 |
Koha::CirculationRules->set_rules( |
682 |
Koha::CirculationRules->set_rules( |
| 681 |
{ |
683 |
{ |
|
Lines 688-694
Koha::CirculationRules->set_rules(
Link Here
|
| 688 |
} |
690 |
} |
| 689 |
} |
691 |
} |
| 690 |
); |
692 |
); |
| 691 |
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status}, |
693 |
is( CanItemBeReserved( $patrons[0], $limit_count_item )->{status}, |
| 692 |
'OK', 'Patron can reserve item with hold limit of 1, no holds placed' ); |
694 |
'OK', 'Patron can reserve item with hold limit of 1, no holds placed' ); |
| 693 |
|
695 |
|
| 694 |
my $res_id = AddReserve( |
696 |
my $res_id = AddReserve( |
|
Lines 700-713
my $res_id = AddReserve(
Link Here
|
| 700 |
} |
702 |
} |
| 701 |
); |
703 |
); |
| 702 |
|
704 |
|
| 703 |
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status}, |
705 |
is( CanItemBeReserved( $patrons[0], $limit_count_item )->{status}, |
| 704 |
'tooManyReserves', 'Patron cannot reserve item with hold limit of 1, 1 bib level hold placed' ); |
706 |
'tooManyReserves', 'Patron cannot reserve item with hold limit of 1, 1 bib level hold placed' ); |
| 705 |
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber, undef, { ignore_hold_counts => 1 } )->{status}, |
707 |
is( CanItemBeReserved( $patrons[0], $limit_count_item, undef, { ignore_hold_counts => 1 } )->{status}, |
| 706 |
'OK', 'Patron can reserve item if checking policy but not counts' ); |
708 |
'OK', 'Patron can reserve item if checking policy but not counts' ); |
| 707 |
|
709 |
|
| 708 |
#results should be the same for both ReservesControlBranch settings |
710 |
#results should be the same for both ReservesControlBranch settings |
| 709 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'ItemHomeLibrary' ); |
711 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'ItemHomeLibrary' ); |
| 710 |
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status}, |
712 |
is( CanItemBeReserved( $patrons[0], $limit_count_item )->{status}, |
| 711 |
'tooManyReserves', 'Patron cannot reserve item with hold limit of 1, 1 bib level hold placed' ); |
713 |
'tooManyReserves', 'Patron cannot reserve item with hold limit of 1, 1 bib level hold placed' ); |
| 712 |
#reset for further tests |
714 |
#reset for further tests |
| 713 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' ); |
715 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' ); |
|
Lines 718-724
subtest 'Test max_holds per library/patron category' => sub {
Link Here
|
| 718 |
$dbh->do('DELETE FROM reserves'); |
720 |
$dbh->do('DELETE FROM reserves'); |
| 719 |
|
721 |
|
| 720 |
$biblio = $builder->build_sample_biblio; |
722 |
$biblio = $builder->build_sample_biblio; |
| 721 |
$itemnumber = $builder->build_sample_item({ library => $branch_1, biblionumber => $biblio->biblionumber})->itemnumber; |
723 |
my $max_holds_item = $builder->build_sample_item({ library => $branch_1, biblionumber => $biblio->biblionumber}); |
| 722 |
Koha::CirculationRules->set_rules( |
724 |
Koha::CirculationRules->set_rules( |
| 723 |
{ |
725 |
{ |
| 724 |
categorycode => undef, |
726 |
categorycode => undef, |
|
Lines 746-752
subtest 'Test max_holds per library/patron category' => sub {
Link Here
|
| 746 |
Koha::Holds->search( { borrowernumber => $borrowernumbers[0] } )->count(); |
748 |
Koha::Holds->search( { borrowernumber => $borrowernumbers[0] } )->count(); |
| 747 |
is( $count, 3, 'Patron now has 3 holds' ); |
749 |
is( $count, 3, 'Patron now has 3 holds' ); |
| 748 |
|
750 |
|
| 749 |
my $ret = CanItemBeReserved( $borrowernumbers[0], $itemnumber ); |
751 |
my $ret = CanItemBeReserved( $patrons[0], $max_holds_item ); |
| 750 |
is( $ret->{status}, 'OK', 'Patron can place hold with no borrower circ rules' ); |
752 |
is( $ret->{status}, 'OK', 'Patron can place hold with no borrower circ rules' ); |
| 751 |
|
753 |
|
| 752 |
my $rule_all = Koha::CirculationRules->set_rule( |
754 |
my $rule_all = Koha::CirculationRules->set_rule( |
|
Lines 767-785
subtest 'Test max_holds per library/patron category' => sub {
Link Here
|
| 767 |
} |
769 |
} |
| 768 |
); |
770 |
); |
| 769 |
|
771 |
|
| 770 |
$ret = CanItemBeReserved( $borrowernumbers[0], $itemnumber ); |
772 |
$ret = CanItemBeReserved( $patrons[0], $max_holds_item ); |
| 771 |
is( $ret->{status}, 'OK', 'Patron can place hold with branch/category rule of 5, category rule of 3' ); |
773 |
is( $ret->{status}, 'OK', 'Patron can place hold with branch/category rule of 5, category rule of 3' ); |
| 772 |
|
774 |
|
| 773 |
$rule_branch->delete(); |
775 |
$rule_branch->delete(); |
| 774 |
|
776 |
|
| 775 |
$ret = CanItemBeReserved( $borrowernumbers[0], $itemnumber ); |
777 |
$ret = CanItemBeReserved( $patrons[0], $max_holds_item ); |
| 776 |
is( $ret->{status}, 'tooManyReserves', 'Patron cannot place hold with only a category rule of 3' ); |
778 |
is( $ret->{status}, 'tooManyReserves', 'Patron cannot place hold with only a category rule of 3' ); |
| 777 |
|
779 |
|
| 778 |
$rule_all->delete(); |
780 |
$rule_all->delete(); |
| 779 |
$rule_branch->rule_value(3); |
781 |
$rule_branch->rule_value(3); |
| 780 |
$rule_branch->store(); |
782 |
$rule_branch->store(); |
| 781 |
|
783 |
|
| 782 |
$ret = CanItemBeReserved( $borrowernumbers[0], $itemnumber ); |
784 |
$ret = CanItemBeReserved( $patrons[0], $max_holds_item ); |
| 783 |
is( $ret->{status}, 'tooManyReserves', 'Patron cannot place hold with only a branch/category rule of 3' ); |
785 |
is( $ret->{status}, 'tooManyReserves', 'Patron cannot place hold with only a branch/category rule of 3' ); |
| 784 |
|
786 |
|
| 785 |
$rule_branch->rule_value(5); |
787 |
$rule_branch->rule_value(5); |
|
Lines 787-793
subtest 'Test max_holds per library/patron category' => sub {
Link Here
|
| 787 |
$rule_branch->rule_value(5); |
789 |
$rule_branch->rule_value(5); |
| 788 |
$rule_branch->store(); |
790 |
$rule_branch->store(); |
| 789 |
|
791 |
|
| 790 |
$ret = CanItemBeReserved( $borrowernumbers[0], $itemnumber ); |
792 |
$ret = CanItemBeReserved( $patrons[0], $max_holds_item ); |
| 791 |
is( $ret->{status}, 'OK', 'Patron can place hold with branch/category rule of 5, category rule of 5' ); |
793 |
is( $ret->{status}, 'OK', 'Patron can place hold with branch/category rule of 5, category rule of 5' ); |
| 792 |
}; |
794 |
}; |
| 793 |
|
795 |
|
|
Lines 795-801
subtest 'Pickup location availability tests' => sub {
Link Here
|
| 795 |
plan tests => 4; |
797 |
plan tests => 4; |
| 796 |
|
798 |
|
| 797 |
$biblio = $builder->build_sample_biblio({ itemtype => 'ONLY1' }); |
799 |
$biblio = $builder->build_sample_biblio({ itemtype => 'ONLY1' }); |
| 798 |
$itemnumber = $builder->build_sample_item({ library => $branch_1, biblionumber => $biblio->biblionumber})->itemnumber; |
800 |
my $pickup_item = $builder->build_sample_item({ library => $branch_1, biblionumber => $biblio->biblionumber}); |
| 799 |
#Add a default rule to allow some holds |
801 |
#Add a default rule to allow some holds |
| 800 |
|
802 |
|
| 801 |
Koha::CirculationRules->set_rules( |
803 |
Koha::CirculationRules->set_rules( |
|
Lines 809-840
subtest 'Pickup location availability tests' => sub {
Link Here
|
| 809 |
} |
811 |
} |
| 810 |
} |
812 |
} |
| 811 |
); |
813 |
); |
| 812 |
my $item = Koha::Items->find($itemnumber); |
|
|
| 813 |
my $branch_to = $builder->build({ source => 'Branch' })->{ branchcode }; |
814 |
my $branch_to = $builder->build({ source => 'Branch' })->{ branchcode }; |
| 814 |
my $library = Koha::Libraries->find($branch_to); |
815 |
my $library = Koha::Libraries->find($branch_to); |
| 815 |
$library->pickup_location('1')->store; |
816 |
$library->pickup_location('1')->store; |
| 816 |
my $patron = $builder->build({ source => 'Borrower' })->{ borrowernumber }; |
817 |
my $patron = $builder->build_object({ class => 'Koha::Patrons' }); |
| 817 |
|
818 |
|
| 818 |
t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1); |
819 |
t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1); |
| 819 |
t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype'); |
820 |
t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype'); |
| 820 |
|
821 |
|
| 821 |
$library->pickup_location('1')->store; |
822 |
$library->pickup_location('1')->store; |
| 822 |
is(CanItemBeReserved($patron, $item->itemnumber, $branch_to)->{status}, |
823 |
is(CanItemBeReserved($patron, $pickup_item, $branch_to)->{status}, |
| 823 |
'OK', 'Library is a pickup location'); |
824 |
'OK', 'Library is a pickup location'); |
| 824 |
|
825 |
|
| 825 |
my $limit = Koha::Item::Transfer::Limit->new({ |
826 |
my $limit = Koha::Item::Transfer::Limit->new({ |
| 826 |
fromBranch => $item->holdingbranch, |
827 |
fromBranch => $pickup_item->holdingbranch, |
| 827 |
toBranch => $branch_to, |
828 |
toBranch => $branch_to, |
| 828 |
itemtype => $item->effective_itemtype, |
829 |
itemtype => $pickup_item->effective_itemtype, |
| 829 |
})->store; |
830 |
})->store; |
| 830 |
is(CanItemBeReserved($patron, $item->itemnumber, $branch_to)->{status}, |
831 |
is(CanItemBeReserved($patron, $pickup_item, $branch_to)->{status}, |
| 831 |
'cannotBeTransferred', 'Item cannot be transferred'); |
832 |
'cannotBeTransferred', 'Item cannot be transferred'); |
| 832 |
$limit->delete; |
833 |
$limit->delete; |
| 833 |
|
834 |
|
| 834 |
$library->pickup_location('0')->store; |
835 |
$library->pickup_location('0')->store; |
| 835 |
is(CanItemBeReserved($patron, $item->itemnumber, $branch_to)->{status}, |
836 |
is(CanItemBeReserved($patron, $pickup_item, $branch_to)->{status}, |
| 836 |
'libraryNotPickupLocation', 'Library is not a pickup location'); |
837 |
'libraryNotPickupLocation', 'Library is not a pickup location'); |
| 837 |
is(CanItemBeReserved($patron, $item->itemnumber, 'nonexistent')->{status}, |
838 |
is(CanItemBeReserved($patron, $pickup_item, 'nonexistent')->{status}, |
| 838 |
'libraryNotFound', 'Cannot set unknown library as pickup location'); |
839 |
'libraryNotFound', 'Cannot set unknown library as pickup location'); |
| 839 |
}; |
840 |
}; |
| 840 |
|
841 |
|
|
Lines 852-862
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 852 |
|
853 |
|
| 853 |
# Create 3 biblios with items |
854 |
# Create 3 biblios with items |
| 854 |
my $biblio_1 = $builder->build_sample_biblio({ itemtype => $itemtype->itemtype }); |
855 |
my $biblio_1 = $builder->build_sample_biblio({ itemtype => $itemtype->itemtype }); |
| 855 |
my $itemnumber_1 = $builder->build_sample_item({ library => $library->branchcode, biblionumber => $biblio_1->biblionumber})->itemnumber; |
856 |
my $item_1 = $builder->build_sample_item({ library => $library->branchcode, biblionumber => $biblio_1->biblionumber}); |
| 856 |
my $biblio_2 = $builder->build_sample_biblio({ itemtype => $itemtype->itemtype }); |
857 |
my $biblio_2 = $builder->build_sample_biblio({ itemtype => $itemtype->itemtype }); |
| 857 |
my $itemnumber_2 = $builder->build_sample_item({ library => $library->branchcode, biblionumber => $biblio_2->biblionumber})->itemnumber; |
858 |
my $item_2 = $builder->build_sample_item({ library => $library->branchcode, biblionumber => $biblio_2->biblionumber}); |
| 858 |
my $biblio_3 = $builder->build_sample_biblio({ itemtype => $itemtype->itemtype }); |
859 |
my $biblio_3 = $builder->build_sample_biblio({ itemtype => $itemtype->itemtype }); |
| 859 |
my $itemnumber_3 = $builder->build_sample_item({ library => $library->branchcode, biblionumber => $biblio_3->biblionumber})->itemnumber; |
860 |
my $item_3 = $builder->build_sample_item({ library => $library->branchcode, biblionumber => $biblio_3->biblionumber}); |
| 860 |
|
861 |
|
| 861 |
Koha::CirculationRules->set_rules( |
862 |
Koha::CirculationRules->set_rules( |
| 862 |
{ |
863 |
{ |
|
Lines 872-878
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 872 |
); |
873 |
); |
| 873 |
|
874 |
|
| 874 |
is_deeply( |
875 |
is_deeply( |
| 875 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_1 ), |
876 |
CanItemBeReserved( $patron, $item_1 ), |
| 876 |
{ status => 'OK' }, |
877 |
{ status => 'OK' }, |
| 877 |
'Patron can reserve item with hold limit of 1, no holds placed' |
878 |
'Patron can reserve item with hold limit of 1, no holds placed' |
| 878 |
); |
879 |
); |
|
Lines 887-893
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 887 |
); |
888 |
); |
| 888 |
|
889 |
|
| 889 |
is_deeply( |
890 |
is_deeply( |
| 890 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_1 ), |
891 |
CanItemBeReserved( $patron, $item_1 ), |
| 891 |
{ status => 'tooManyReserves', limit => 1 }, |
892 |
{ status => 'tooManyReserves', limit => 1 }, |
| 892 |
'Patron cannot reserve item with hold limit of 1, 1 bib level hold placed' |
893 |
'Patron cannot reserve item with hold limit of 1, 1 bib level hold placed' |
| 893 |
); |
894 |
); |
|
Lines 905-911
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 905 |
); |
906 |
); |
| 906 |
|
907 |
|
| 907 |
is_deeply( |
908 |
is_deeply( |
| 908 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_2 ), |
909 |
CanItemBeReserved( $patron, $item_2 ), |
| 909 |
{ status => 'OK' }, |
910 |
{ status => 'OK' }, |
| 910 |
'Patron can reserve item with 2 reserves daily cap' |
911 |
'Patron can reserve item with 2 reserves daily cap' |
| 911 |
); |
912 |
); |
|
Lines 920-926
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 920 |
} |
921 |
} |
| 921 |
); |
922 |
); |
| 922 |
is_deeply( |
923 |
is_deeply( |
| 923 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_2 ), |
924 |
CanItemBeReserved( $patron, $item_2 ), |
| 924 |
{ status => 'tooManyReservesToday', limit => 2 }, |
925 |
{ status => 'tooManyReservesToday', limit => 2 }, |
| 925 |
'Patron cannot a third item with 2 reserves daily cap' |
926 |
'Patron cannot a third item with 2 reserves daily cap' |
| 926 |
); |
927 |
); |
|
Lines 931-937
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 931 |
$hold->reservedate($yesterday)->store; |
932 |
$hold->reservedate($yesterday)->store; |
| 932 |
|
933 |
|
| 933 |
is_deeply( |
934 |
is_deeply( |
| 934 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_2 ), |
935 |
CanItemBeReserved( $patron, $item_2 ), |
| 935 |
{ status => 'OK' }, |
936 |
{ status => 'OK' }, |
| 936 |
'Patron can reserve item with 2 bib level hold placed on different days, 2 reserves daily cap' |
937 |
'Patron can reserve item with 2 bib level hold placed on different days, 2 reserves daily cap' |
| 937 |
); |
938 |
); |
|
Lines 952-958
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 952 |
# Delete existing holds |
953 |
# Delete existing holds |
| 953 |
Koha::Holds->search->delete; |
954 |
Koha::Holds->search->delete; |
| 954 |
is_deeply( |
955 |
is_deeply( |
| 955 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_2 ), |
956 |
CanItemBeReserved( $patron, $item_2 ), |
| 956 |
{ status => 'tooManyReservesToday', limit => 0 }, |
957 |
{ status => 'tooManyReservesToday', limit => 0 }, |
| 957 |
'Patron cannot reserve if holds_per_day is 0 (i.e. 0 is 0)' |
958 |
'Patron cannot reserve if holds_per_day is 0 (i.e. 0 is 0)' |
| 958 |
); |
959 |
); |
|
Lines 970-976
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 970 |
|
971 |
|
| 971 |
Koha::Holds->search->delete; |
972 |
Koha::Holds->search->delete; |
| 972 |
is_deeply( |
973 |
is_deeply( |
| 973 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_2 ), |
974 |
CanItemBeReserved( $patron, $item_2 ), |
| 974 |
{ status => 'OK' }, |
975 |
{ status => 'OK' }, |
| 975 |
'Patron can reserve if holds_per_day is undef (i.e. undef is unlimited daily cap)' |
976 |
'Patron can reserve if holds_per_day is undef (i.e. undef is unlimited daily cap)' |
| 976 |
); |
977 |
); |
|
Lines 992-998
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 992 |
); |
993 |
); |
| 993 |
|
994 |
|
| 994 |
is_deeply( |
995 |
is_deeply( |
| 995 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_3 ), |
996 |
CanItemBeReserved( $patron, $item_3 ), |
| 996 |
{ status => 'OK' }, |
997 |
{ status => 'OK' }, |
| 997 |
'Patron can reserve if holds_per_day is undef (i.e. undef is unlimited daily cap)' |
998 |
'Patron can reserve if holds_per_day is undef (i.e. undef is unlimited daily cap)' |
| 998 |
); |
999 |
); |
|
Lines 1005-1018
subtest 'CanItemBeReserved / holds_per_day tests' => sub {
Link Here
|
| 1005 |
} |
1006 |
} |
| 1006 |
); |
1007 |
); |
| 1007 |
is_deeply( |
1008 |
is_deeply( |
| 1008 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_3 ), |
1009 |
CanItemBeReserved( $patron, $item_3 ), |
| 1009 |
{ status => 'tooManyReserves', limit => 3 }, |
1010 |
{ status => 'tooManyReserves', limit => 3 }, |
| 1010 |
'Unlimited daily holds, but reached reservesallowed' |
1011 |
'Unlimited daily holds, but reached reservesallowed' |
| 1011 |
); |
1012 |
); |
| 1012 |
#results should be the same for both ReservesControlBranch settings |
1013 |
#results should be the same for both ReservesControlBranch settings |
| 1013 |
t::lib::Mocks::mock_preference('ReservesControlBranch', 'ItemHomeLibrary'); |
1014 |
t::lib::Mocks::mock_preference('ReservesControlBranch', 'ItemHomeLibrary'); |
| 1014 |
is_deeply( |
1015 |
is_deeply( |
| 1015 |
CanItemBeReserved( $patron->borrowernumber, $itemnumber_3 ), |
1016 |
CanItemBeReserved( $patron, $item_3 ), |
| 1016 |
{ status => 'tooManyReserves', limit => 3 }, |
1017 |
{ status => 'tooManyReserves', limit => 3 }, |
| 1017 |
'Unlimited daily holds, but reached reservesallowed' |
1018 |
'Unlimited daily holds, but reached reservesallowed' |
| 1018 |
); |
1019 |
); |
|
Lines 1079-1085
subtest 'CanItemBeReserved / branch_not_in_hold_group' => sub {
Link Here
|
| 1079 |
|
1080 |
|
| 1080 |
# Test 1: Patron 3 can place hold |
1081 |
# Test 1: Patron 3 can place hold |
| 1081 |
is_deeply( |
1082 |
is_deeply( |
| 1082 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2 ), |
1083 |
CanItemBeReserved( $patron3, $item_2 ), |
| 1083 |
{ status => 'OK' }, |
1084 |
{ status => 'OK' }, |
| 1084 |
'Patron can place hold if no circ_rules where defined' |
1085 |
'Patron can place hold if no circ_rules where defined' |
| 1085 |
); |
1086 |
); |
|
Lines 1099-1112
subtest 'CanItemBeReserved / branch_not_in_hold_group' => sub {
Link Here
|
| 1099 |
|
1100 |
|
| 1100 |
# Test 2: Patron 1 can place hold |
1101 |
# Test 2: Patron 1 can place hold |
| 1101 |
is_deeply( |
1102 |
is_deeply( |
| 1102 |
CanItemBeReserved( $patron1->borrowernumber, $itemnumber_2 ), |
1103 |
CanItemBeReserved( $patron1, $item_2 ), |
| 1103 |
{ status => 'OK' }, |
1104 |
{ status => 'OK' }, |
| 1104 |
'Patron can place hold because patron\'s home library is part of hold group' |
1105 |
'Patron can place hold because patron\'s home library is part of hold group' |
| 1105 |
); |
1106 |
); |
| 1106 |
|
1107 |
|
| 1107 |
# Test 3: Patron 3 cannot place hold |
1108 |
# Test 3: Patron 3 cannot place hold |
| 1108 |
is_deeply( |
1109 |
is_deeply( |
| 1109 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2 ), |
1110 |
CanItemBeReserved( $patron3, $item_2 ), |
| 1110 |
{ status => 'branchNotInHoldGroup' }, |
1111 |
{ status => 'branchNotInHoldGroup' }, |
| 1111 |
'Patron cannot place hold because patron\'s home library is not part of hold group' |
1112 |
'Patron cannot place hold because patron\'s home library is not part of hold group' |
| 1112 |
); |
1113 |
); |
|
Lines 1126-1132
subtest 'CanItemBeReserved / branch_not_in_hold_group' => sub {
Link Here
|
| 1126 |
|
1127 |
|
| 1127 |
# Test 4: Patron 3 can place hold |
1128 |
# Test 4: Patron 3 can place hold |
| 1128 |
is_deeply( |
1129 |
is_deeply( |
| 1129 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2 ), |
1130 |
CanItemBeReserved( $patron3, $item_2 ), |
| 1130 |
{ status => 'OK' }, |
1131 |
{ status => 'OK' }, |
| 1131 |
'Patron can place hold if holdallowed is set to "any" for library 2' |
1132 |
'Patron can place hold if holdallowed is set to "any" for library 2' |
| 1132 |
); |
1133 |
); |
|
Lines 1146-1152
subtest 'CanItemBeReserved / branch_not_in_hold_group' => sub {
Link Here
|
| 1146 |
|
1147 |
|
| 1147 |
# Test 5: Patron 3 cannot place hold |
1148 |
# Test 5: Patron 3 cannot place hold |
| 1148 |
is_deeply( |
1149 |
is_deeply( |
| 1149 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2 ), |
1150 |
CanItemBeReserved( $patron3, $item_2 ), |
| 1150 |
{ status => 'branchNotInHoldGroup' }, |
1151 |
{ status => 'branchNotInHoldGroup' }, |
| 1151 |
'Patron cannot place hold if holdallowed is set to "hold group" for library 2' |
1152 |
'Patron cannot place hold if holdallowed is set to "hold group" for library 2' |
| 1152 |
); |
1153 |
); |
|
Lines 1166-1172
subtest 'CanItemBeReserved / branch_not_in_hold_group' => sub {
Link Here
|
| 1166 |
|
1167 |
|
| 1167 |
# Test 6: Patron 3 can place hold |
1168 |
# Test 6: Patron 3 can place hold |
| 1168 |
is_deeply( |
1169 |
is_deeply( |
| 1169 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2 ), |
1170 |
CanItemBeReserved( $patron3, $item_2 ), |
| 1170 |
{ status => 'OK' }, |
1171 |
{ status => 'OK' }, |
| 1171 |
'Patron can place hold if holdallowed is set to "any" for itemtype 2' |
1172 |
'Patron can place hold if holdallowed is set to "any" for itemtype 2' |
| 1172 |
); |
1173 |
); |
|
Lines 1186-1192
subtest 'CanItemBeReserved / branch_not_in_hold_group' => sub {
Link Here
|
| 1186 |
|
1187 |
|
| 1187 |
# Test 7: Patron 3 cannot place hold |
1188 |
# Test 7: Patron 3 cannot place hold |
| 1188 |
is_deeply( |
1189 |
is_deeply( |
| 1189 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2 ), |
1190 |
CanItemBeReserved( $patron3, $item_2 ), |
| 1190 |
{ status => 'branchNotInHoldGroup' }, |
1191 |
{ status => 'branchNotInHoldGroup' }, |
| 1191 |
'Patron cannot place hold if holdallowed is set to "hold group" for itemtype 2' |
1192 |
'Patron cannot place hold if holdallowed is set to "hold group" for itemtype 2' |
| 1192 |
); |
1193 |
); |
|
Lines 1206-1212
subtest 'CanItemBeReserved / branch_not_in_hold_group' => sub {
Link Here
|
| 1206 |
|
1207 |
|
| 1207 |
# Test 8: Patron 3 can place hold |
1208 |
# Test 8: Patron 3 can place hold |
| 1208 |
is_deeply( |
1209 |
is_deeply( |
| 1209 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2 ), |
1210 |
CanItemBeReserved( $patron3, $item_2 ), |
| 1210 |
{ status => 'OK' }, |
1211 |
{ status => 'OK' }, |
| 1211 |
'Patron can place hold if holdallowed is set to "any" for itemtype 2 and library 2' |
1212 |
'Patron can place hold if holdallowed is set to "any" for itemtype 2 and library 2' |
| 1212 |
); |
1213 |
); |
|
Lines 1226-1232
subtest 'CanItemBeReserved / branch_not_in_hold_group' => sub {
Link Here
|
| 1226 |
|
1227 |
|
| 1227 |
# Test 9: Patron 3 cannot place hold |
1228 |
# Test 9: Patron 3 cannot place hold |
| 1228 |
is_deeply( |
1229 |
is_deeply( |
| 1229 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2 ), |
1230 |
CanItemBeReserved( $patron3, $item_2 ), |
| 1230 |
{ status => 'branchNotInHoldGroup' }, |
1231 |
{ status => 'branchNotInHoldGroup' }, |
| 1231 |
'Patron cannot place hold if holdallowed is set to "hold group" for itemtype 2 and library 2' |
1232 |
'Patron cannot place hold if holdallowed is set to "hold group" for itemtype 2 and library 2' |
| 1232 |
); |
1233 |
); |
|
Lines 1293-1299
subtest 'CanItemBeReserved / pickup_not_in_hold_group' => sub {
Link Here
|
| 1293 |
|
1294 |
|
| 1294 |
# Test 1: Patron 3 can place hold |
1295 |
# Test 1: Patron 3 can place hold |
| 1295 |
is_deeply( |
1296 |
is_deeply( |
| 1296 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library3->branchcode ), |
1297 |
CanItemBeReserved( $patron3, $item_2, $library3->branchcode ), |
| 1297 |
{ status => 'OK' }, |
1298 |
{ status => 'OK' }, |
| 1298 |
'Patron can place hold if no circ_rules where defined' |
1299 |
'Patron can place hold if no circ_rules where defined' |
| 1299 |
); |
1300 |
); |
|
Lines 1313-1326
subtest 'CanItemBeReserved / pickup_not_in_hold_group' => sub {
Link Here
|
| 1313 |
|
1314 |
|
| 1314 |
# Test 2: Patron 1 can place hold |
1315 |
# Test 2: Patron 1 can place hold |
| 1315 |
is_deeply( |
1316 |
is_deeply( |
| 1316 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library1->branchcode ), |
1317 |
CanItemBeReserved( $patron3, $item_2, $library1->branchcode ), |
| 1317 |
{ status => 'OK' }, |
1318 |
{ status => 'OK' }, |
| 1318 |
'Patron can place hold because pickup location is part of hold group' |
1319 |
'Patron can place hold because pickup location is part of hold group' |
| 1319 |
); |
1320 |
); |
| 1320 |
|
1321 |
|
| 1321 |
# Test 3: Patron 3 cannot place hold |
1322 |
# Test 3: Patron 3 cannot place hold |
| 1322 |
is_deeply( |
1323 |
is_deeply( |
| 1323 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library3->branchcode ), |
1324 |
CanItemBeReserved( $patron3, $item_2, $library3->branchcode ), |
| 1324 |
{ status => 'pickupNotInHoldGroup' }, |
1325 |
{ status => 'pickupNotInHoldGroup' }, |
| 1325 |
'Patron cannot place hold because pickup location is not part of hold group' |
1326 |
'Patron cannot place hold because pickup location is not part of hold group' |
| 1326 |
); |
1327 |
); |
|
Lines 1340-1346
subtest 'CanItemBeReserved / pickup_not_in_hold_group' => sub {
Link Here
|
| 1340 |
|
1341 |
|
| 1341 |
# Test 4: Patron 3 can place hold |
1342 |
# Test 4: Patron 3 can place hold |
| 1342 |
is_deeply( |
1343 |
is_deeply( |
| 1343 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library3->branchcode ), |
1344 |
CanItemBeReserved( $patron3, $item_2, $library3->branchcode ), |
| 1344 |
{ status => 'OK' }, |
1345 |
{ status => 'OK' }, |
| 1345 |
'Patron can place hold if default_branch_circ_rules is set to "any" for library 2' |
1346 |
'Patron can place hold if default_branch_circ_rules is set to "any" for library 2' |
| 1346 |
); |
1347 |
); |
|
Lines 1360-1366
subtest 'CanItemBeReserved / pickup_not_in_hold_group' => sub {
Link Here
|
| 1360 |
|
1361 |
|
| 1361 |
# Test 5: Patron 3 cannot place hold |
1362 |
# Test 5: Patron 3 cannot place hold |
| 1362 |
is_deeply( |
1363 |
is_deeply( |
| 1363 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library3->branchcode ), |
1364 |
CanItemBeReserved( $patron3, $item_2, $library3->branchcode ), |
| 1364 |
{ status => 'pickupNotInHoldGroup' }, |
1365 |
{ status => 'pickupNotInHoldGroup' }, |
| 1365 |
'Patron cannot place hold if hold_fulfillment_policy is set to "hold group" for library 2' |
1366 |
'Patron cannot place hold if hold_fulfillment_policy is set to "hold group" for library 2' |
| 1366 |
); |
1367 |
); |
|
Lines 1380-1386
subtest 'CanItemBeReserved / pickup_not_in_hold_group' => sub {
Link Here
|
| 1380 |
|
1381 |
|
| 1381 |
# Test 6: Patron 3 can place hold |
1382 |
# Test 6: Patron 3 can place hold |
| 1382 |
is_deeply( |
1383 |
is_deeply( |
| 1383 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library3->branchcode ), |
1384 |
CanItemBeReserved( $patron3, $item_2, $library3->branchcode ), |
| 1384 |
{ status => 'OK' }, |
1385 |
{ status => 'OK' }, |
| 1385 |
'Patron can place hold if hold_fulfillment_policy is set to "any" for itemtype 2' |
1386 |
'Patron can place hold if hold_fulfillment_policy is set to "any" for itemtype 2' |
| 1386 |
); |
1387 |
); |
|
Lines 1400-1406
subtest 'CanItemBeReserved / pickup_not_in_hold_group' => sub {
Link Here
|
| 1400 |
|
1401 |
|
| 1401 |
# Test 7: Patron 3 cannot place hold |
1402 |
# Test 7: Patron 3 cannot place hold |
| 1402 |
is_deeply( |
1403 |
is_deeply( |
| 1403 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library3->branchcode ), |
1404 |
CanItemBeReserved( $patron3, $item_2, $library3->branchcode ), |
| 1404 |
{ status => 'pickupNotInHoldGroup' }, |
1405 |
{ status => 'pickupNotInHoldGroup' }, |
| 1405 |
'Patron cannot place hold if hold_fulfillment_policy is set to "hold group" for itemtype 2' |
1406 |
'Patron cannot place hold if hold_fulfillment_policy is set to "hold group" for itemtype 2' |
| 1406 |
); |
1407 |
); |
|
Lines 1420-1426
subtest 'CanItemBeReserved / pickup_not_in_hold_group' => sub {
Link Here
|
| 1420 |
|
1421 |
|
| 1421 |
# Test 8: Patron 3 can place hold |
1422 |
# Test 8: Patron 3 can place hold |
| 1422 |
is_deeply( |
1423 |
is_deeply( |
| 1423 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library3->branchcode ), |
1424 |
CanItemBeReserved( $patron3, $item_2, $library3->branchcode ), |
| 1424 |
{ status => 'OK' }, |
1425 |
{ status => 'OK' }, |
| 1425 |
'Patron can place hold if hold_fulfillment_policy is set to "any" for itemtype 2 and library 2' |
1426 |
'Patron can place hold if hold_fulfillment_policy is set to "any" for itemtype 2 and library 2' |
| 1426 |
); |
1427 |
); |
|
Lines 1440-1446
subtest 'CanItemBeReserved / pickup_not_in_hold_group' => sub {
Link Here
|
| 1440 |
|
1441 |
|
| 1441 |
# Test 9: Patron 3 cannot place hold |
1442 |
# Test 9: Patron 3 cannot place hold |
| 1442 |
is_deeply( |
1443 |
is_deeply( |
| 1443 |
CanItemBeReserved( $patron3->borrowernumber, $itemnumber_2, $library3->branchcode ), |
1444 |
CanItemBeReserved( $patron3, $item_2, $library3->branchcode ), |
| 1444 |
{ status => 'pickupNotInHoldGroup' }, |
1445 |
{ status => 'pickupNotInHoldGroup' }, |
| 1445 |
'Patron cannot place hold if hold_fulfillment_policy is set to "hold group" for itemtype 2 and library 2' |
1446 |
'Patron cannot place hold if hold_fulfillment_policy is set to "hold group" for itemtype 2 and library 2' |
| 1446 |
); |
1447 |
); |
|
Lines 1574-1580
subtest 'CanItemBeReserved rule precedence tests' => sub {
Link Here
|
| 1574 |
} |
1575 |
} |
| 1575 |
); |
1576 |
); |
| 1576 |
is_deeply( |
1577 |
is_deeply( |
| 1577 |
CanItemBeReserved( $patron->borrowernumber, $item->itemnumber, $library->branchcode ), |
1578 |
CanItemBeReserved( $patron, $item, $library->branchcode ), |
| 1578 |
{ status => 'OK' }, |
1579 |
{ status => 'OK' }, |
| 1579 |
'Patron of specified category can place 1 hold on specified itemtype' |
1580 |
'Patron of specified category can place 1 hold on specified itemtype' |
| 1580 |
); |
1581 |
); |
|
Lines 1587-1593
subtest 'CanItemBeReserved rule precedence tests' => sub {
Link Here
|
| 1587 |
borrowernumber => $patron->borrowernumber, |
1588 |
borrowernumber => $patron->borrowernumber, |
| 1588 |
}}); |
1589 |
}}); |
| 1589 |
is_deeply( |
1590 |
is_deeply( |
| 1590 |
CanItemBeReserved( $patron->borrowernumber, $item->itemnumber, $library->branchcode ), |
1591 |
CanItemBeReserved( $patron, $item, $library->branchcode ), |
| 1591 |
{ status => 'tooManyReserves', limit => 1 }, |
1592 |
{ status => 'tooManyReserves', limit => 1 }, |
| 1592 |
'Patron of specified category can place 1 hold on specified itemtype, cannot place a second' |
1593 |
'Patron of specified category can place 1 hold on specified itemtype, cannot place a second' |
| 1593 |
); |
1594 |
); |
|
Lines 1602-1608
subtest 'CanItemBeReserved rule precedence tests' => sub {
Link Here
|
| 1602 |
} |
1603 |
} |
| 1603 |
); |
1604 |
); |
| 1604 |
is_deeply( |
1605 |
is_deeply( |
| 1605 |
CanItemBeReserved( $patron->borrowernumber, $item->itemnumber, $library->branchcode ), |
1606 |
CanItemBeReserved( $patron, $item, $library->branchcode ), |
| 1606 |
{ status => 'OK' }, |
1607 |
{ status => 'OK' }, |
| 1607 |
'Patron of specified category can place 1 hold on specified itemtype if library rule for all types and categories set to 2' |
1608 |
'Patron of specified category can place 1 hold on specified itemtype if library rule for all types and categories set to 2' |
| 1608 |
); |
1609 |
); |