Lines 374-382
sub transferbook {
Link Here
|
374 |
|
374 |
|
375 |
|
375 |
|
376 |
sub TooMany { |
376 |
sub TooMany { |
377 |
my $borrower = shift; |
377 |
my $borrower = shift; |
378 |
my $biblionumber = shift; |
378 |
my $biblionumber = shift; |
379 |
my $item = shift; |
379 |
my $item = shift; |
380 |
my $params = shift; |
380 |
my $params = shift; |
381 |
my $onsite_checkout = $params->{onsite_checkout} || 0; |
381 |
my $onsite_checkout = $params->{onsite_checkout} || 0; |
382 |
my $switch_onsite_checkout = $params->{switch_onsite_checkout} || 0; |
382 |
my $switch_onsite_checkout = $params->{switch_onsite_checkout} || 0; |
Lines 389-396
sub TooMany {
Link Here
|
389 |
? $item->{'itype'} # item-level |
389 |
? $item->{'itype'} # item-level |
390 |
: $item->{'itemtype'}; # biblio-level |
390 |
: $item->{'itemtype'}; # biblio-level |
391 |
|
391 |
|
|
|
392 |
my ($type_object, $parent_type, $parent_maxissueqty_rule); |
393 |
$type_object = Koha::ItemTypes->find( $type ); |
394 |
$parent_type = $type_object->parent_type if $type_object; |
395 |
my $child_types = Koha::ItemTypes->search( parent_type => $type ); |
396 |
# Find any children if we are a parent_type; |
397 |
|
392 |
# given branch, patron category, and item type, determine |
398 |
# given branch, patron category, and item type, determine |
393 |
# applicable issuing rule |
399 |
# applicable issuing rule |
|
|
400 |
|
401 |
$parent_maxissueqty_rule = Koha::CirculationRules->get_effective_rule( |
402 |
{ |
403 |
categorycode => $cat_borrower, |
404 |
itemtype => $parent_type, |
405 |
branchcode => $branch, |
406 |
rule_name => 'maxissueqty', |
407 |
} |
408 |
) if $parent_type; |
409 |
# If the parent rule is for default type we discount it |
410 |
$parent_maxissueqty_rule = undef if $parent_maxissueqty_rule && $parent_maxissueqty_rule->itemtype eq '*'; |
411 |
|
394 |
my $maxissueqty_rule = Koha::CirculationRules->get_effective_rule( |
412 |
my $maxissueqty_rule = Koha::CirculationRules->get_effective_rule( |
395 |
{ |
413 |
{ |
396 |
categorycode => $cat_borrower, |
414 |
categorycode => $cat_borrower, |
Lines 399-404
sub TooMany {
Link Here
|
399 |
rule_name => 'maxissueqty', |
417 |
rule_name => 'maxissueqty', |
400 |
} |
418 |
} |
401 |
); |
419 |
); |
|
|
420 |
|
421 |
|
402 |
my $maxonsiteissueqty_rule = Koha::CirculationRules->get_effective_rule( |
422 |
my $maxonsiteissueqty_rule = Koha::CirculationRules->get_effective_rule( |
403 |
{ |
423 |
{ |
404 |
categorycode => $cat_borrower, |
424 |
categorycode => $cat_borrower, |
Lines 413-421
sub TooMany {
Link Here
|
413 |
# how many loans the patron already has that meet that |
433 |
# how many loans the patron already has that meet that |
414 |
# rule |
434 |
# rule |
415 |
if (defined($maxissueqty_rule) and defined($maxissueqty_rule->rule_value)) { |
435 |
if (defined($maxissueqty_rule) and defined($maxissueqty_rule->rule_value)) { |
|
|
436 |
|
416 |
my @bind_params; |
437 |
my @bind_params; |
417 |
my $count_query = q| |
438 |
my $count_query = ""; |
418 |
SELECT COUNT(*) AS total, COALESCE(SUM(onsite_checkout), 0) AS onsite_checkouts |
439 |
|
|
|
440 |
if (C4::Context->preference('item-level_itypes')) { |
441 |
$count_query .= q|SELECT COALESCE( SUM( IF(items.itype = '| .$type . q|',1,0) ), 0) as type_total, COUNT(*) AS total, COALESCE(SUM(onsite_checkout), 0) AS onsite_checkouts|; |
442 |
} else{ |
443 |
$count_query .= q|SELECT COALESCE(SUM( IF(biblioitems.itype = '| .$type . q|',1,0) ), 0) as type_total, COUNT(*) AS total, COALESCE(SUM(onsite_checkout), 0) AS onsite_checkouts|; |
444 |
} |
445 |
|
446 |
$count_query .= q| |
419 |
FROM issues |
447 |
FROM issues |
420 |
JOIN items USING (itemnumber) |
448 |
JOIN items USING (itemnumber) |
421 |
|; |
449 |
|; |
Lines 445-459
sub TooMany {
Link Here
|
445 |
push @bind_params, $maxissueqty_rule->categorycode; |
473 |
push @bind_params, $maxissueqty_rule->categorycode; |
446 |
push @bind_params, $cat_borrower; |
474 |
push @bind_params, $cat_borrower; |
447 |
} else { |
475 |
} else { |
448 |
# rule has specific item type, so count loans of that |
476 |
my @types; |
449 |
# specific item type |
477 |
if ( $parent_maxissueqty_rule ) { |
|
|
478 |
# if we have a parent item type then we count loans of the |
479 |
# specific item type or its siblings or parent |
480 |
push @types, $parent_type; |
481 |
my $children = Koha::ItemTypes->search({ parent_type => $parent_type }); |
482 |
while ( my $child = $children->next ){ |
483 |
push @types, $child->itemtype; |
484 |
} |
485 |
} elsif ( $child_types ) { |
486 |
# If we are a parent type, we need to count all child types and our own type |
487 |
while ( my $child = $child_types->next ){ |
488 |
push @types, $child->itemtype; |
489 |
} |
490 |
push @types, $type; # And don't forget to count our own types |
491 |
} else { push @types, $type; } # Otherwise only count the specific itemtype |
492 |
my $types_param = ( '?,' ) x @types; |
493 |
$types_param =~ s/,$//; |
450 |
if (C4::Context->preference('item-level_itypes')) { |
494 |
if (C4::Context->preference('item-level_itypes')) { |
451 |
$count_query .= " WHERE items.itype = ? "; |
495 |
$count_query .= " WHERE items.itype IN (" . $types_param . ")"; |
452 |
} else { |
496 |
} else { |
453 |
$count_query .= " JOIN biblioitems USING (biblionumber) |
497 |
$count_query .= " JOIN biblioitems USING (biblionumber) |
454 |
WHERE biblioitems.itemtype= ? "; |
498 |
WHERE biblioitems.itemtype IN (" . $types_param . ")"; |
455 |
} |
499 |
} |
456 |
push @bind_params, $type; |
500 |
push @bind_params, @types; |
457 |
} |
501 |
} |
458 |
|
502 |
|
459 |
$count_query .= " AND borrowernumber = ? "; |
503 |
$count_query .= " AND borrowernumber = ? "; |
Lines 471-508
sub TooMany {
Link Here
|
471 |
} |
515 |
} |
472 |
} |
516 |
} |
473 |
|
517 |
|
474 |
my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $count_query, {}, @bind_params ); |
518 |
my ( $checkout_count_type, $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $count_query, {}, @bind_params ); |
475 |
|
519 |
|
476 |
my $max_checkouts_allowed = $maxissueqty_rule ? $maxissueqty_rule->rule_value : undef; |
|
|
477 |
my $max_onsite_checkouts_allowed = $maxonsiteissueqty_rule ? $maxonsiteissueqty_rule->rule_value : undef; |
520 |
my $max_onsite_checkouts_allowed = $maxonsiteissueqty_rule ? $maxonsiteissueqty_rule->rule_value : undef; |
478 |
|
521 |
|
479 |
if ( $onsite_checkout and defined $max_onsite_checkouts_allowed ) { |
522 |
# If parent rules exists |
480 |
if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) { |
523 |
if ( defined($parent_maxissueqty_rule) and defined($parent_maxissueqty_rule->rule_value) ){ |
481 |
return { |
524 |
my $max_checkouts_allowed = $parent_maxissueqty_rule->rule_value; |
482 |
reason => 'TOO_MANY_ONSITE_CHECKOUTS', |
525 |
|
483 |
count => $onsite_checkout_count, |
526 |
my $qty_over = _check_max_qty({ |
484 |
max_allowed => $max_onsite_checkouts_allowed, |
527 |
checkout_count => $checkout_count, |
485 |
} |
528 |
onsite_checkout_count => $onsite_checkout_count, |
486 |
} |
529 |
onsite_checkout => $onsite_checkout, |
487 |
} |
530 |
max_checkouts_allowed => $max_checkouts_allowed, |
488 |
if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) { |
531 |
max_onsite_checkouts_allowed => $max_onsite_checkouts_allowed, |
489 |
my $delta = $switch_onsite_checkout ? 1 : 0; |
532 |
switch_onsite_checkout => $switch_onsite_checkout |
490 |
if ( $checkout_count >= $max_checkouts_allowed + $delta ) { |
533 |
}); |
491 |
return { |
534 |
return $qty_over if defined $qty_over; |
492 |
reason => 'TOO_MANY_CHECKOUTS', |
535 |
|
493 |
count => $checkout_count, |
536 |
|
494 |
max_allowed => $max_checkouts_allowed, |
537 |
# If the parent rule is less than or equal to the child, we only need check the parent |
495 |
}; |
538 |
if( $maxissueqty_rule->rule_value < $parent_maxissueqty_rule->rule_value && defined($maxissueqty_rule->itemtype) ) { |
496 |
} |
539 |
my $max_checkouts_allowed = $maxissueqty_rule->rule_value; |
497 |
} elsif ( not $onsite_checkout ) { |
540 |
my $qty_over = _check_max_qty({ |
498 |
if ( $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed ) { |
541 |
checkout_count => $checkout_count_type, |
499 |
return { |
542 |
onsite_checkout_count => $onsite_checkout_count, |
500 |
reason => 'TOO_MANY_CHECKOUTS', |
543 |
onsite_checkout => $onsite_checkout, |
501 |
count => $checkout_count - $onsite_checkout_count, |
544 |
max_checkouts_allowed => $max_checkouts_allowed, |
502 |
max_allowed => $max_checkouts_allowed, |
545 |
max_onsite_checkouts_allowed => $max_onsite_checkouts_allowed, |
503 |
}; |
546 |
switch_onsite_checkout => $switch_onsite_checkout |
504 |
} |
547 |
}); |
|
|
548 |
return $qty_over if defined $qty_over; |
549 |
} |
550 |
|
551 |
} else { |
552 |
my $max_checkouts_allowed = $maxissueqty_rule->rule_value; |
553 |
my $qty_over = _check_max_qty({ |
554 |
checkout_count => $checkout_count, |
555 |
onsite_checkout_count => $onsite_checkout_count, |
556 |
onsite_checkout => $onsite_checkout, |
557 |
max_checkouts_allowed => $max_checkouts_allowed, |
558 |
max_onsite_checkouts_allowed => $max_onsite_checkouts_allowed, |
559 |
switch_onsite_checkout => $switch_onsite_checkout |
560 |
}); |
561 |
return $qty_over if defined $qty_over; |
505 |
} |
562 |
} |
|
|
563 |
|
564 |
|
506 |
} |
565 |
} |
507 |
|
566 |
|
508 |
# Now count total loans against the limit for the branch |
567 |
# Now count total loans against the limit for the branch |
Lines 528-562
sub TooMany {
Link Here
|
528 |
} |
587 |
} |
529 |
my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $branch_count_query, {}, @bind_params ); |
588 |
my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $branch_count_query, {}, @bind_params ); |
530 |
my $max_checkouts_allowed = $branch_borrower_circ_rule->{patron_maxissueqty}; |
589 |
my $max_checkouts_allowed = $branch_borrower_circ_rule->{patron_maxissueqty}; |
531 |
my $max_onsite_checkouts_allowed = $branch_borrower_circ_rule->{patron_maxonsiteissueqty}; |
590 |
my $max_onsite_checkouts_allowed = $branch_borrower_circ_rule->{patron_maxonsiteissueqty} || undef; |
532 |
|
591 |
|
533 |
if ( $onsite_checkout and $max_onsite_checkouts_allowed ne '' ) { |
592 |
my $qty_over = _check_max_qty({ |
534 |
if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) { |
593 |
checkout_count => $checkout_count, |
535 |
return { |
594 |
onsite_checkout_count => $onsite_checkout_count, |
536 |
reason => 'TOO_MANY_ONSITE_CHECKOUTS', |
595 |
onsite_checkout => $onsite_checkout, |
537 |
count => $onsite_checkout_count, |
596 |
max_checkouts_allowed => $max_checkouts_allowed, |
538 |
max_allowed => $max_onsite_checkouts_allowed, |
597 |
max_onsite_checkouts_allowed => $max_onsite_checkouts_allowed, |
539 |
} |
598 |
switch_onsite_checkout => $switch_onsite_checkout |
540 |
} |
599 |
}); |
541 |
} |
600 |
return $qty_over if defined $qty_over; |
542 |
if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) { |
601 |
|
543 |
my $delta = $switch_onsite_checkout ? 1 : 0; |
|
|
544 |
if ( $checkout_count >= $max_checkouts_allowed + $delta ) { |
545 |
return { |
546 |
reason => 'TOO_MANY_CHECKOUTS', |
547 |
count => $checkout_count, |
548 |
max_allowed => $max_checkouts_allowed, |
549 |
}; |
550 |
} |
551 |
} elsif ( not $onsite_checkout ) { |
552 |
if ( $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed ) { |
553 |
return { |
554 |
reason => 'TOO_MANY_CHECKOUTS', |
555 |
count => $checkout_count - $onsite_checkout_count, |
556 |
max_allowed => $max_checkouts_allowed, |
557 |
}; |
558 |
} |
559 |
} |
560 |
} |
602 |
} |
561 |
|
603 |
|
562 |
if ( not defined( $maxissueqty_rule ) and not defined($branch_borrower_circ_rule->{patron_maxissueqty}) ) { |
604 |
if ( not defined( $maxissueqty_rule ) and not defined($branch_borrower_circ_rule->{patron_maxissueqty}) ) { |
Lines 567-572
sub TooMany {
Link Here
|
567 |
return; |
609 |
return; |
568 |
} |
610 |
} |
569 |
|
611 |
|
|
|
612 |
sub _check_max_qty { |
613 |
my $params = shift; |
614 |
my $checkout_count = $params->{checkout_count}; |
615 |
my $onsite_checkout_count = $params->{onsite_checkout_count}; |
616 |
my $onsite_checkout = $params->{onsite_checkout}; |
617 |
my $max_checkouts_allowed = $params->{max_checkouts_allowed}; |
618 |
my $max_onsite_checkouts_allowed = $params->{max_onsite_checkouts_allowed}; |
619 |
my $switch_onsite_checkout = $params->{switch_onsite_checkout}; |
620 |
|
621 |
if ( $onsite_checkout and defined $max_onsite_checkouts_allowed ) { |
622 |
if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) { |
623 |
return { |
624 |
reason => 'TOO_MANY_ONSITE_CHECKOUTS', |
625 |
count => $onsite_checkout_count, |
626 |
max_allowed => $max_onsite_checkouts_allowed, |
627 |
} |
628 |
} |
629 |
} |
630 |
if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) { |
631 |
my $delta = $switch_onsite_checkout ? 1 : 0; |
632 |
if ( $checkout_count >= $max_checkouts_allowed + $delta ) { |
633 |
return { |
634 |
reason => 'TOO_MANY_CHECKOUTS', |
635 |
count => $checkout_count, |
636 |
max_allowed => $max_checkouts_allowed, |
637 |
}; |
638 |
} |
639 |
} elsif ( not $onsite_checkout ) { |
640 |
if ( $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed ) { |
641 |
return { |
642 |
reason => 'TOO_MANY_CHECKOUTS', |
643 |
count => $checkout_count - $onsite_checkout_count, |
644 |
max_allowed => $max_checkouts_allowed, |
645 |
}; |
646 |
} |
647 |
} |
648 |
|
649 |
return; |
650 |
} |
651 |
|
570 |
=head2 CanBookBeIssued |
652 |
=head2 CanBookBeIssued |
571 |
|
653 |
|
572 |
( $issuingimpossible, $needsconfirmation, [ $alerts ] ) = CanBookBeIssued( $patron, |
654 |
( $issuingimpossible, $needsconfirmation, [ $alerts ] ) = CanBookBeIssued( $patron, |