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