Lines 285-291
sub CanBookBeReserved{
Link Here
|
285 |
my $canReserve = { status => '' }; |
285 |
my $canReserve = { status => '' }; |
286 |
foreach my $itemnumber (@itemnumbers) { |
286 |
foreach my $itemnumber (@itemnumbers) { |
287 |
$canReserve = CanItemBeReserved( $borrowernumber, $itemnumber, $pickup_branchcode ); |
287 |
$canReserve = CanItemBeReserved( $borrowernumber, $itemnumber, $pickup_branchcode ); |
288 |
return { status => 'OK' } if $canReserve->{status} eq 'OK'; |
288 |
return $canReserve if $canReserve->{status} eq 'OK'; |
289 |
} |
289 |
} |
290 |
return $canReserve; |
290 |
return $canReserve; |
291 |
} |
291 |
} |
Lines 323-353
sub CanItemBeReserved {
Link Here
|
323 |
my $patron = Koha::Patrons->find( $borrowernumber ); |
323 |
my $patron = Koha::Patrons->find( $borrowernumber ); |
324 |
my $borrower = $patron->unblessed; |
324 |
my $borrower = $patron->unblessed; |
325 |
|
325 |
|
326 |
# If an item is damaged and we don't allow holds on damaged items, we can stop right here |
|
|
327 |
return { status =>'damaged' } |
328 |
if ( $item->damaged |
329 |
&& !C4::Context->preference('AllowHoldsOnDamagedItems') ); |
330 |
|
331 |
# Check for the age restriction |
332 |
my ( $ageRestriction, $daysToAgeRestriction ) = |
333 |
C4::Circulation::GetAgeRestriction( $biblio->biblioitem->agerestriction, $borrower ); |
334 |
return { status => 'ageRestricted' } if $daysToAgeRestriction && $daysToAgeRestriction > 0; |
335 |
|
336 |
# Check that the patron doesn't have an item level hold on this item already |
337 |
return { status =>'itemAlreadyOnHold' } |
338 |
if Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count(); |
339 |
|
340 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
326 |
my $controlbranch = C4::Context->preference('ReservesControlBranch'); |
341 |
|
327 |
|
342 |
my $querycount = q{ |
|
|
343 |
SELECT count(*) AS count |
344 |
FROM reserves |
345 |
LEFT JOIN items USING (itemnumber) |
346 |
LEFT JOIN biblioitems ON (reserves.biblionumber=biblioitems.biblionumber) |
347 |
LEFT JOIN borrowers USING (borrowernumber) |
348 |
WHERE borrowernumber = ? |
349 |
}; |
350 |
|
351 |
my $branchcode = ""; |
328 |
my $branchcode = ""; |
352 |
my $branchfield = "reserves.branchcode"; |
329 |
my $branchfield = "reserves.branchcode"; |
353 |
|
330 |
|
Lines 361-376
sub CanItemBeReserved {
Link Here
|
361 |
} |
338 |
} |
362 |
|
339 |
|
363 |
# we retrieve rights |
340 |
# we retrieve rights |
364 |
if ( my $rights = GetHoldRule( $borrower->{'categorycode'}, $item->effective_itemtype, $branchcode ) ) { |
341 |
my $issuingrule; |
365 |
$ruleitemtype = $rights->{itemtype}; |
342 |
if ( $issuingrule = GetHoldRule( $borrower->{'categorycode'}, $item->effective_itemtype, $branchcode ) ) { |
366 |
$allowedreserves = $rights->{reservesallowed}; |
343 |
$ruleitemtype = $issuingrule->{itemtype}; |
367 |
$holds_per_record = $rights->{holds_per_record}; |
344 |
$allowedreserves = $issuingrule->{reservesallowed}; |
368 |
$holds_per_day = $rights->{holds_per_day}; |
345 |
$holds_per_record = $issuingrule->{holds_per_record}; |
|
|
346 |
$holds_per_day = $issuingrule->{holds_per_day}; |
369 |
} |
347 |
} |
370 |
else { |
348 |
else { |
371 |
$ruleitemtype = '*'; |
349 |
$ruleitemtype = '*'; |
372 |
} |
350 |
} |
373 |
|
351 |
|
|
|
352 |
my $circulation_rule = Koha::CirculationRules->get_effective_rule( |
353 |
{ |
354 |
categorycode => $borrower->{categorycode}, |
355 |
branchcode => $branchcode, |
356 |
rule_name => 'max_holds', |
357 |
} |
358 |
); |
359 |
|
360 |
# If an item is damaged and we don't allow holds on damaged items, we can stop right here |
361 |
return { status =>'damaged', issuingrule => $issuingrule, circulation_rule => $circulation_rule } |
362 |
if ( $item->damaged |
363 |
&& !C4::Context->preference('AllowHoldsOnDamagedItems') ); |
364 |
|
365 |
# Check for the age restriction |
366 |
my ( $ageRestriction, $daysToAgeRestriction ) = |
367 |
C4::Circulation::GetAgeRestriction( $biblio->biblioitem->agerestriction, $borrower ); |
368 |
return { status => 'ageRestricted', issuingrule => $issuingrule, circulation_rule => $circulation_rule } if $daysToAgeRestriction && $daysToAgeRestriction > 0; |
369 |
|
370 |
# Check that the patron doesn't have an item level hold on this item already |
371 |
return { status =>'itemAlreadyOnHold', issuingrule => $issuingrule, circulation_rule => $circulation_rule } |
372 |
if Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count(); |
373 |
|
374 |
my $querycount = q{ |
375 |
SELECT count(*) AS count |
376 |
FROM reserves |
377 |
LEFT JOIN items USING (itemnumber) |
378 |
LEFT JOIN biblioitems ON (reserves.biblionumber=biblioitems.biblionumber) |
379 |
LEFT JOIN borrowers USING (borrowernumber) |
380 |
WHERE borrowernumber = ? |
381 |
}; |
382 |
|
383 |
$item = Koha::Items->find( $itemnumber ); |
374 |
my $holds = Koha::Holds->search( |
384 |
my $holds = Koha::Holds->search( |
375 |
{ |
385 |
{ |
376 |
borrowernumber => $borrowernumber, |
386 |
borrowernumber => $borrowernumber, |
Lines 379-385
sub CanItemBeReserved {
Link Here
|
379 |
} |
389 |
} |
380 |
); |
390 |
); |
381 |
if ( $holds->count() >= $holds_per_record ) { |
391 |
if ( $holds->count() >= $holds_per_record ) { |
382 |
return { status => "tooManyHoldsForThisRecord", limit => $holds_per_record }; |
392 |
$issuingrule->{exceeded} = 'holds_per_record'; |
|
|
393 |
return { status => "tooManyHoldsForThisRecord", |
394 |
limit => $holds_per_record, |
395 |
issuingrule => $issuingrule, |
396 |
circulation_rule => $circulation_rule }; |
383 |
} |
397 |
} |
384 |
|
398 |
|
385 |
my $today_holds = Koha::Holds->search({ |
399 |
my $today_holds = Koha::Holds->search({ |
Lines 391-397
sub CanItemBeReserved {
Link Here
|
391 |
( ( $holds_per_day > 0 && $today_holds->count() >= $holds_per_day ) |
405 |
( ( $holds_per_day > 0 && $today_holds->count() >= $holds_per_day ) |
392 |
or ( $holds_per_day == 0 ) ) |
406 |
or ( $holds_per_day == 0 ) ) |
393 |
) { |
407 |
) { |
394 |
return { status => 'tooManyReservesToday', limit => $holds_per_day }; |
408 |
$issuingrule->{exceeded} = 'holds_per_day'; |
|
|
409 |
return { status => 'tooManyReservesToday', |
410 |
limit => $holds_per_day, |
411 |
issuingrule => $issuingrule, |
412 |
circulation_rule => $circulation_rule }; |
395 |
} |
413 |
} |
396 |
|
414 |
|
397 |
# we retrieve count |
415 |
# we retrieve count |
Lines 422-446
sub CanItemBeReserved {
Link Here
|
422 |
|
440 |
|
423 |
# we check if it's ok or not |
441 |
# we check if it's ok or not |
424 |
if ( $reservecount >= $allowedreserves ) { |
442 |
if ( $reservecount >= $allowedreserves ) { |
425 |
return { status => 'tooManyReserves', limit => $allowedreserves }; |
443 |
$issuingrule->{exceeded} = 'allowedreserves'; |
|
|
444 |
return { status => 'tooManyReserves', |
445 |
limit => $allowedreserves, |
446 |
issuingrule => $issuingrule, |
447 |
circulation_rule => $circulation_rule }; |
426 |
} |
448 |
} |
427 |
|
449 |
|
428 |
# Now we need to check hold limits by patron category |
450 |
# Now we need to check hold limits by patron category |
429 |
my $rule = Koha::CirculationRules->get_effective_rule( |
451 |
if ( $circulation_rule && defined( $circulation_rule->rule_value ) && $circulation_rule->rule_value ne '' ) { |
430 |
{ |
|
|
431 |
categorycode => $borrower->{categorycode}, |
432 |
branchcode => $branchcode, |
433 |
rule_name => 'max_holds', |
434 |
} |
435 |
); |
436 |
if ( $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) { |
437 |
my $total_holds_count = Koha::Holds->search( |
452 |
my $total_holds_count = Koha::Holds->search( |
438 |
{ |
453 |
{ |
439 |
borrowernumber => $borrower->{borrowernumber} |
454 |
borrowernumber => $borrower->{borrowernumber} |
440 |
} |
455 |
} |
441 |
)->count(); |
456 |
)->count(); |
442 |
|
457 |
|
443 |
return { status => 'tooManyReserves', limit => $rule->rule_value} if $total_holds_count >= $rule->rule_value; |
458 |
return { |
|
|
459 |
status => 'tooManyReserves', |
460 |
limit => $circulation_rule->rule_value, |
461 |
issuingrule => $issuingrule, |
462 |
circulation_rule => $circulation_rule, |
463 |
circulation_rule_exceeded => 1 |
464 |
} if $total_holds_count >= $circulation_rule->rule_value; |
444 |
} |
465 |
} |
445 |
|
466 |
|
446 |
my $reserves_control_branch = |
467 |
my $reserves_control_branch = |
Lines 449-461
sub CanItemBeReserved {
Link Here
|
449 |
C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->itype ); # FIXME Should not be item->effective_itemtype? |
470 |
C4::Circulation::GetBranchItemRule( $reserves_control_branch, $item->itype ); # FIXME Should not be item->effective_itemtype? |
450 |
|
471 |
|
451 |
if ( $branchitemrule->{holdallowed} == 0 ) { |
472 |
if ( $branchitemrule->{holdallowed} == 0 ) { |
452 |
return { status => 'notReservable' }; |
473 |
return { status => 'notReservable', issuingrule => $issuingrule, circulation_rule => $circulation_rule }; |
453 |
} |
474 |
} |
454 |
|
475 |
|
455 |
if ( $branchitemrule->{holdallowed} == 1 |
476 |
if ( $branchitemrule->{holdallowed} == 1 |
456 |
&& $borrower->{branchcode} ne $item->homebranch ) |
477 |
&& $borrower->{branchcode} ne $item->homebranch ) |
457 |
{ |
478 |
{ |
458 |
return { status => 'cannotReserveFromOtherBranches' }; |
479 |
return { status => 'cannotReserveFromOtherBranches', issuingrule => $issuingrule, circulation_rule => $circulation_rule }; |
459 |
} |
480 |
} |
460 |
|
481 |
|
461 |
# If reservecount is ok, we check item branch if IndependentBranches is ON |
482 |
# If reservecount is ok, we check item branch if IndependentBranches is ON |
Lines 464-470
sub CanItemBeReserved {
Link Here
|
464 |
and !C4::Context->preference('canreservefromotherbranches') ) |
485 |
and !C4::Context->preference('canreservefromotherbranches') ) |
465 |
{ |
486 |
{ |
466 |
if ( $item->homebranch ne $borrower->{branchcode} ) { |
487 |
if ( $item->homebranch ne $borrower->{branchcode} ) { |
467 |
return { status => 'cannotReserveFromOtherBranches' }; |
488 |
return { status => 'cannotReserveFromOtherBranches', issuingrule => $issuingrule, circulation_rule => $circulation_rule }; |
468 |
} |
489 |
} |
469 |
} |
490 |
} |
470 |
|
491 |
|
Lines 474-490
sub CanItemBeReserved {
Link Here
|
474 |
}); |
495 |
}); |
475 |
|
496 |
|
476 |
unless ($destination) { |
497 |
unless ($destination) { |
477 |
return { status => 'libraryNotFound' }; |
498 |
return { status => 'libraryNotFound', issuingrule => $issuingrule, circulation_rule => $circulation_rule }; |
478 |
} |
499 |
} |
479 |
unless ($destination->pickup_location) { |
500 |
unless ($destination->pickup_location) { |
480 |
return { status => 'libraryNotPickupLocation' }; |
501 |
return { status => 'libraryNotPickupLocation', issuingrule => $issuingrule, circulation_rule => $circulation_rule }; |
481 |
} |
502 |
} |
482 |
unless ($item->can_be_transferred({ to => $destination })) { |
503 |
unless ($item->can_be_transferred({ to => $destination })) { |
483 |
return { status => 'cannotBeTransferred' }; |
504 |
return { status => 'cannotBeTransferred' }; |
484 |
} |
505 |
} |
485 |
} |
506 |
} |
486 |
|
507 |
|
487 |
return { status => 'OK' }; |
508 |
return { status => 'OK', issuingrule => $issuingrule, circulation_rule => $circulation_rule }; |
488 |
} |
509 |
} |
489 |
|
510 |
|
490 |
=head2 CanReserveBeCanceledFromOpac |
511 |
=head2 CanReserveBeCanceledFromOpac |