Lines 384-391
sub TooMany {
Link Here
|
384 |
$branch = _GetCircControlBranch($item_object->unblessed,$borrower); |
384 |
$branch = _GetCircControlBranch($item_object->unblessed,$borrower); |
385 |
my $type = $item_object->effective_itemtype; |
385 |
my $type = $item_object->effective_itemtype; |
386 |
|
386 |
|
|
|
387 |
my ($type_object, $parent_type, $parent_maxissueqty_rule); |
388 |
$type_object = Koha::ItemTypes->find( $type ); |
389 |
$parent_type = $type_object->parent_type if $type_object; |
390 |
my $child_types = Koha::ItemTypes->search({ parent_type => $type }); |
391 |
# Find any children if we are a parent_type; |
392 |
|
387 |
# given branch, patron category, and item type, determine |
393 |
# given branch, patron category, and item type, determine |
388 |
# applicable issuing rule |
394 |
# applicable issuing rule |
|
|
395 |
|
396 |
$parent_maxissueqty_rule = Koha::CirculationRules->get_effective_rule( |
397 |
{ |
398 |
categorycode => $cat_borrower, |
399 |
itemtype => $parent_type, |
400 |
branchcode => $branch, |
401 |
rule_name => 'maxissueqty', |
402 |
} |
403 |
) if $parent_type; |
404 |
# If the parent rule is for default type we discount it |
405 |
$parent_maxissueqty_rule = undef if $parent_maxissueqty_rule && !defined $parent_maxissueqty_rule->itemtype; |
406 |
|
389 |
my $maxissueqty_rule = Koha::CirculationRules->get_effective_rule( |
407 |
my $maxissueqty_rule = Koha::CirculationRules->get_effective_rule( |
390 |
{ |
408 |
{ |
391 |
categorycode => $cat_borrower, |
409 |
categorycode => $cat_borrower, |
Lines 394-399
sub TooMany {
Link Here
|
394 |
rule_name => 'maxissueqty', |
412 |
rule_name => 'maxissueqty', |
395 |
} |
413 |
} |
396 |
); |
414 |
); |
|
|
415 |
|
416 |
|
397 |
my $maxonsiteissueqty_rule = Koha::CirculationRules->get_effective_rule( |
417 |
my $maxonsiteissueqty_rule = Koha::CirculationRules->get_effective_rule( |
398 |
{ |
418 |
{ |
399 |
categorycode => $cat_borrower, |
419 |
categorycode => $cat_borrower, |
Lines 407-416
sub TooMany {
Link Here
|
407 |
# if a rule is found and has a loan limit set, count |
427 |
# if a rule is found and has a loan limit set, count |
408 |
# how many loans the patron already has that meet that |
428 |
# how many loans the patron already has that meet that |
409 |
# rule |
429 |
# rule |
410 |
if (defined($maxissueqty_rule) and $maxissueqty_rule->rule_value ne '') { |
430 |
if (defined($maxissueqty_rule) and defined($maxissueqty_rule->rule_value)) { |
|
|
431 |
|
411 |
my @bind_params; |
432 |
my @bind_params; |
412 |
my $count_query = q| |
433 |
my $count_query = ""; |
413 |
SELECT COUNT(*) AS total, COALESCE(SUM(onsite_checkout), 0) AS onsite_checkouts |
434 |
|
|
|
435 |
if (C4::Context->preference('item-level_itypes')) { |
436 |
$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|; |
437 |
} else{ |
438 |
$count_query .= q|SELECT COALESCE(SUM( IF(biblioitems.itemtype = '| .$type . q|',1,0) ), 0) as type_total, COUNT(*) AS total, COALESCE(SUM(onsite_checkout), 0) AS onsite_checkouts|; |
439 |
} |
440 |
|
441 |
$count_query .= q| |
414 |
FROM issues |
442 |
FROM issues |
415 |
JOIN items USING (itemnumber) |
443 |
JOIN items USING (itemnumber) |
416 |
|; |
444 |
|; |
Lines 420-456
sub TooMany {
Link Here
|
420 |
# matching rule has the default item type, so count only |
448 |
# matching rule has the default item type, so count only |
421 |
# those existing loans that don't fall under a more |
449 |
# those existing loans that don't fall under a more |
422 |
# specific rule |
450 |
# specific rule |
|
|
451 |
my $issuing_itemtypes_query = q{ |
452 |
SELECT itemtype FROM circulation_rules |
453 |
WHERE branchcode = ? |
454 |
AND (categorycode = ? OR categorycode = ?) |
455 |
AND itemtype IS NOT NULL |
456 |
AND rule_name = 'maxissueqty' |
457 |
}; |
423 |
if (C4::Context->preference('item-level_itypes')) { |
458 |
if (C4::Context->preference('item-level_itypes')) { |
424 |
$count_query .= " WHERE items.itype NOT IN ( |
459 |
$count_query .= " WHERE items.itype NOT IN ( $issuing_itemtypes_query )"; |
425 |
SELECT itemtype FROM circulation_rules |
|
|
426 |
WHERE branchcode = ? |
427 |
AND (categorycode = ? OR categorycode = ?) |
428 |
AND itemtype IS NOT NULL |
429 |
AND rule_name = 'maxissueqty' |
430 |
) "; |
431 |
} else { |
460 |
} else { |
432 |
$count_query .= " JOIN biblioitems USING (biblionumber) |
461 |
$count_query .= " WHERE biblioitems.itemtype NOT IN ( $issuing_itemtypes_query )"; |
433 |
WHERE biblioitems.itemtype NOT IN ( |
|
|
434 |
SELECT itemtype FROM circulation_rules |
435 |
WHERE branchcode = ? |
436 |
AND (categorycode = ? OR categorycode = ?) |
437 |
AND itemtype IS NOT NULL |
438 |
AND rule_name = 'maxissueqty' |
439 |
) "; |
440 |
} |
462 |
} |
441 |
push @bind_params, $maxissueqty_rule->branchcode; |
463 |
push @bind_params, $maxissueqty_rule->branchcode; |
442 |
push @bind_params, $maxissueqty_rule->categorycode; |
464 |
push @bind_params, $maxissueqty_rule->categorycode; |
443 |
push @bind_params, $cat_borrower; |
465 |
push @bind_params, $cat_borrower; |
444 |
} else { |
466 |
} else { |
445 |
# rule has specific item type, so count loans of that |
467 |
my @types; |
446 |
# specific item type |
468 |
if ( $parent_maxissueqty_rule ) { |
|
|
469 |
# if we have a parent item type then we count loans of the |
470 |
# specific item type or its siblings or parent |
471 |
my $children = Koha::ItemTypes->search({ parent_type => $parent_type }); |
472 |
@types = $children->get_column('itemtype'); |
473 |
push @types, $parent_type; |
474 |
} elsif ( $child_types ) { |
475 |
# If we are a parent type, we need to count all child types and our own type |
476 |
@types = $child_types->get_column('itemtype'); |
477 |
push @types, $type; # And don't forget to count our own types |
478 |
} else { push @types, $type; } # Otherwise only count the specific itemtype |
479 |
my $types_param = ( '?,' ) x @types; |
480 |
$types_param =~ s/,$//; |
447 |
if (C4::Context->preference('item-level_itypes')) { |
481 |
if (C4::Context->preference('item-level_itypes')) { |
448 |
$count_query .= " WHERE items.itype = ? "; |
482 |
$count_query .= " WHERE items.itype IN (" . $types_param . ")"; |
449 |
} else { |
483 |
} else { |
450 |
$count_query .= " JOIN biblioitems USING (biblionumber) |
484 |
$count_query .= " JOIN biblioitems USING (biblionumber) |
451 |
WHERE biblioitems.itemtype= ? "; |
485 |
WHERE biblioitems.itemtype IN (" . $types_param . ")"; |
452 |
} |
486 |
} |
453 |
push @bind_params, $type; |
487 |
push @bind_params, @types; |
454 |
} |
488 |
} |
455 |
|
489 |
|
456 |
$count_query .= " AND borrowernumber = ? "; |
490 |
$count_query .= " AND borrowernumber = ? "; |
Lines 468-505
sub TooMany {
Link Here
|
468 |
} |
502 |
} |
469 |
} |
503 |
} |
470 |
|
504 |
|
471 |
my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $count_query, {}, @bind_params ); |
505 |
my ( $checkout_count_type, $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $count_query, {}, @bind_params ); |
472 |
|
506 |
|
473 |
my $max_checkouts_allowed = $maxissueqty_rule ? $maxissueqty_rule->rule_value : undef; |
|
|
474 |
my $max_onsite_checkouts_allowed = $maxonsiteissueqty_rule ? $maxonsiteissueqty_rule->rule_value : undef; |
507 |
my $max_onsite_checkouts_allowed = $maxonsiteissueqty_rule ? $maxonsiteissueqty_rule->rule_value : undef; |
475 |
|
508 |
|
476 |
if ( $onsite_checkout and $max_onsite_checkouts_allowed ne '' ) { |
509 |
# If parent rules exists |
477 |
if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) { |
510 |
if ( defined($parent_maxissueqty_rule) and defined($parent_maxissueqty_rule->rule_value) ){ |
478 |
return { |
511 |
my $max_checkouts_allowed = $parent_maxissueqty_rule->rule_value; |
479 |
reason => 'TOO_MANY_ONSITE_CHECKOUTS', |
512 |
|
480 |
count => $onsite_checkout_count, |
513 |
my $qty_over = _check_max_qty({ |
481 |
max_allowed => $max_onsite_checkouts_allowed, |
514 |
checkout_count => $checkout_count, |
482 |
} |
515 |
onsite_checkout_count => $onsite_checkout_count, |
483 |
} |
516 |
onsite_checkout => $onsite_checkout, |
484 |
} |
517 |
max_checkouts_allowed => $max_checkouts_allowed, |
485 |
if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) { |
518 |
max_onsite_checkouts_allowed => $max_onsite_checkouts_allowed, |
486 |
my $delta = $switch_onsite_checkout ? 1 : 0; |
519 |
switch_onsite_checkout => $switch_onsite_checkout |
487 |
if ( $checkout_count >= $max_checkouts_allowed + $delta ) { |
520 |
}); |
488 |
return { |
521 |
return $qty_over if defined $qty_over; |
489 |
reason => 'TOO_MANY_CHECKOUTS', |
522 |
|
490 |
count => $checkout_count, |
523 |
|
491 |
max_allowed => $max_checkouts_allowed, |
524 |
# If the parent rule is less than or equal to the child, we only need check the parent |
492 |
}; |
525 |
if( $maxissueqty_rule->rule_value < $parent_maxissueqty_rule->rule_value && defined($maxissueqty_rule->itemtype) ) { |
493 |
} |
526 |
my $max_checkouts_allowed = $maxissueqty_rule->rule_value; |
494 |
} elsif ( not $onsite_checkout ) { |
527 |
my $qty_over = _check_max_qty({ |
495 |
if ( $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed ) { |
528 |
checkout_count => $checkout_count_type, |
496 |
return { |
529 |
onsite_checkout_count => $onsite_checkout_count, |
497 |
reason => 'TOO_MANY_CHECKOUTS', |
530 |
onsite_checkout => $onsite_checkout, |
498 |
count => $checkout_count - $onsite_checkout_count, |
531 |
max_checkouts_allowed => $max_checkouts_allowed, |
499 |
max_allowed => $max_checkouts_allowed, |
532 |
max_onsite_checkouts_allowed => $max_onsite_checkouts_allowed, |
500 |
}; |
533 |
switch_onsite_checkout => $switch_onsite_checkout |
501 |
} |
534 |
}); |
|
|
535 |
return $qty_over if defined $qty_over; |
536 |
} |
537 |
|
538 |
} else { |
539 |
my $max_checkouts_allowed = $maxissueqty_rule->rule_value; |
540 |
my $qty_over = _check_max_qty({ |
541 |
checkout_count => $checkout_count, |
542 |
onsite_checkout_count => $onsite_checkout_count, |
543 |
onsite_checkout => $onsite_checkout, |
544 |
max_checkouts_allowed => $max_checkouts_allowed, |
545 |
max_onsite_checkouts_allowed => $max_onsite_checkouts_allowed, |
546 |
switch_onsite_checkout => $switch_onsite_checkout |
547 |
}); |
548 |
return $qty_over if defined $qty_over; |
502 |
} |
549 |
} |
|
|
550 |
|
551 |
|
503 |
} |
552 |
} |
504 |
|
553 |
|
505 |
# Now count total loans against the limit for the branch |
554 |
# Now count total loans against the limit for the branch |
Lines 525-559
sub TooMany {
Link Here
|
525 |
} |
574 |
} |
526 |
my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $branch_count_query, {}, @bind_params ); |
575 |
my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $branch_count_query, {}, @bind_params ); |
527 |
my $max_checkouts_allowed = $branch_borrower_circ_rule->{patron_maxissueqty}; |
576 |
my $max_checkouts_allowed = $branch_borrower_circ_rule->{patron_maxissueqty}; |
528 |
my $max_onsite_checkouts_allowed = $branch_borrower_circ_rule->{patron_maxonsiteissueqty}; |
577 |
my $max_onsite_checkouts_allowed = $branch_borrower_circ_rule->{patron_maxonsiteissueqty} || undef; |
529 |
|
578 |
|
530 |
if ( $onsite_checkout and $max_onsite_checkouts_allowed ne '' ) { |
579 |
my $qty_over = _check_max_qty({ |
531 |
if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) { |
580 |
checkout_count => $checkout_count, |
532 |
return { |
581 |
onsite_checkout_count => $onsite_checkout_count, |
533 |
reason => 'TOO_MANY_ONSITE_CHECKOUTS', |
582 |
onsite_checkout => $onsite_checkout, |
534 |
count => $onsite_checkout_count, |
583 |
max_checkouts_allowed => $max_checkouts_allowed, |
535 |
max_allowed => $max_onsite_checkouts_allowed, |
584 |
max_onsite_checkouts_allowed => $max_onsite_checkouts_allowed, |
536 |
} |
585 |
switch_onsite_checkout => $switch_onsite_checkout |
537 |
} |
586 |
}); |
538 |
} |
587 |
return $qty_over if defined $qty_over; |
539 |
if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) { |
588 |
|
540 |
my $delta = $switch_onsite_checkout ? 1 : 0; |
|
|
541 |
if ( $checkout_count >= $max_checkouts_allowed + $delta ) { |
542 |
return { |
543 |
reason => 'TOO_MANY_CHECKOUTS', |
544 |
count => $checkout_count, |
545 |
max_allowed => $max_checkouts_allowed, |
546 |
}; |
547 |
} |
548 |
} elsif ( not $onsite_checkout ) { |
549 |
if ( $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed ) { |
550 |
return { |
551 |
reason => 'TOO_MANY_CHECKOUTS', |
552 |
count => $checkout_count - $onsite_checkout_count, |
553 |
max_allowed => $max_checkouts_allowed, |
554 |
}; |
555 |
} |
556 |
} |
557 |
} |
589 |
} |
558 |
|
590 |
|
559 |
if ( not defined( $maxissueqty_rule ) and not defined($branch_borrower_circ_rule->{patron_maxissueqty}) ) { |
591 |
if ( not defined( $maxissueqty_rule ) and not defined($branch_borrower_circ_rule->{patron_maxissueqty}) ) { |
Lines 564-569
sub TooMany {
Link Here
|
564 |
return; |
596 |
return; |
565 |
} |
597 |
} |
566 |
|
598 |
|
|
|
599 |
sub _check_max_qty { |
600 |
my $params = shift; |
601 |
my $checkout_count = $params->{checkout_count}; |
602 |
my $onsite_checkout_count = $params->{onsite_checkout_count}; |
603 |
my $onsite_checkout = $params->{onsite_checkout}; |
604 |
my $max_checkouts_allowed = $params->{max_checkouts_allowed}; |
605 |
my $max_onsite_checkouts_allowed = $params->{max_onsite_checkouts_allowed}; |
606 |
my $switch_onsite_checkout = $params->{switch_onsite_checkout}; |
607 |
|
608 |
if ( $onsite_checkout and defined $max_onsite_checkouts_allowed ) { |
609 |
if( $max_onsite_checkouts_allowed eq '' ){ return;} |
610 |
if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) { |
611 |
return { |
612 |
reason => 'TOO_MANY_ONSITE_CHECKOUTS', |
613 |
count => $onsite_checkout_count, |
614 |
max_allowed => $max_onsite_checkouts_allowed, |
615 |
} |
616 |
} |
617 |
} |
618 |
if ( C4::Context->preference('ConsiderOnSiteCheckoutsAsNormalCheckouts') ) { |
619 |
if( $max_checkouts_allowed eq '' ){ return;} |
620 |
my $delta = $switch_onsite_checkout ? 1 : 0; |
621 |
if ( $checkout_count >= $max_checkouts_allowed + $delta ) { |
622 |
return { |
623 |
reason => 'TOO_MANY_CHECKOUTS', |
624 |
count => $checkout_count, |
625 |
max_allowed => $max_checkouts_allowed, |
626 |
}; |
627 |
} |
628 |
} elsif ( not $onsite_checkout ) { |
629 |
if( $max_checkouts_allowed eq '' ){ return;} |
630 |
if ( $checkout_count - $onsite_checkout_count >= $max_checkouts_allowed ) { |
631 |
return { |
632 |
reason => 'TOO_MANY_CHECKOUTS', |
633 |
count => $checkout_count - $onsite_checkout_count, |
634 |
max_allowed => $max_checkouts_allowed, |
635 |
}; |
636 |
} |
637 |
} |
638 |
|
639 |
return; |
640 |
} |
641 |
|
567 |
=head2 CanBookBeIssued |
642 |
=head2 CanBookBeIssued |
568 |
|
643 |
|
569 |
( $issuingimpossible, $needsconfirmation, [ $alerts ] ) = CanBookBeIssued( $patron, |
644 |
( $issuingimpossible, $needsconfirmation, [ $alerts ] ) = CanBookBeIssued( $patron, |