@@ -, +, @@ by guarantor and other guarantees --- C4/Circulation.pm | 15 ++ C4/SIP/ILS/Patron.pm | 10 +- Koha/Patron.pm | 46 ++++ circ/circulation.pl | 6 + .../data/mysql/atomicupdate/bug_19283.perl | 10 + installer/data/mysql/sysprefs.sql | 5 +- .../admin/preferences/circulation.pref | 5 + .../prog/en/modules/circ/circulation.tt | 8 + opac/sco/sco-main.pl | 2 +- t/db_dependent/Koha/Patron.t | 204 ++++++++++++++++++ 10 files changed, 305 insertions(+), 6 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_19283.perl --- a/C4/Circulation.pm +++ a/C4/Circulation.pm @@ -853,6 +853,21 @@ sub CanBookBeIssued { } } + # Check the debt of this patrons guarantors *and* the guarantees of those guarantors + my $no_issues_charge_guarantors = C4::Context->preference("NoIssuesChargeGuarantorsWithGuarantees"); + $no_issues_charge_guarantors = undef unless looks_like_number( $no_issues_charge_guarantors ); + if ( defined $no_issues_charge_guarantors ) { + my $guarantors_non_issues_charges += $patron->relationships_debt({ include_guarantors => 1, only_this_guaranor => 0, include_this_patron => 1 }); + + if ( $guarantors_non_issues_charges > $no_issues_charge_guarantors && !$inprocess && !$allowfineoverride) { + $issuingimpossible{DEBT_GUARANTORS} = $guarantors_non_issues_charges; + } elsif ( $guarantors_non_issues_charges > $no_issues_charge_guarantors && !$inprocess && $allowfineoverride) { + $needsconfirmation{DEBT_GUARANTORS} = $guarantors_non_issues_charges; + } elsif ( $allfinesneedoverride && $guarantors_non_issues_charges > 0 && $guarantors_non_issues_charges <= $no_issues_charge_guarantors && !$inprocess ) { + $needsconfirmation{DEBT_GUARANTORS} = $guarantors_non_issues_charges; + } + } + if ( C4::Context->preference("IssuingInProcess") ) { if ( $non_issues_charges > $amountlimit && !$inprocess && !$allowfineoverride) { $issuingimpossible{DEBT} = $non_issues_charges; --- a/C4/SIP/ILS/Patron.pm +++ a/C4/SIP/ILS/Patron.pm @@ -67,10 +67,14 @@ sub new { $dexpiry and $dexpiry =~ s/-//g; # YYYYMMDD # Get fines and add fines for guarantees (depends on preference NoIssuesChargeGuarantees) - my $fines_amount = $flags->{CHARGES}->{amount}; + my $fines_amount = $flags->{CHARGES}->{amount}; #TODO Replace with $patron->account->non_issues_charges $fines_amount = ($fines_amount and $fines_amount > 0) ? $fines_amount : 0; - my $guarantees_fines_amount = $flags->{CHARGES_GUARANTEES} ? $flags->{CHARGES_GUARANTEES}->{amount} : 0; - $fines_amount += $guarantees_fines_amount; + if ( C4::Context->preference('NoIssuesChargeGuarantorsWithGuarantees') ) { + $fines_amount += $patron->relationships_debt({ include_guarantors => 1, only_this_guaranor => 0, include_this_patron => 1 }); + } else { + my $guarantees_fines_amount = $flags->{CHARGES_GUARANTEES} ? $flags->{CHARGES_GUARANTEES}->{amount} : 0; #TODO: Replace with $patron->relationships_debt + $fines_amount += $guarantees_fines_amount; + } my $fee_limit = _fee_limit(); my $fine_blocked = $fines_amount > $fee_limit; --- a/Koha/Patron.pm +++ a/Koha/Patron.pm @@ -486,6 +486,52 @@ sub guarantee_relationships { ); } +=head3 relationships_debt + +Returns the amount owed by the patron's guarantors *and* the other guarantees of those guarantors + +=cut + +sub relationships_debt { + my ($self, $params) = @_; + + my $include_guarantors = $params->{include_guarantors}; + my $only_this_guarantor = $params->{only_this_guarantor}; + my $include_this_patron = $params->{include_this_patron}; + + my @guarantors; + if ( $only_this_guarantor ) { + @guarantors = $self->guarantee_relationships->count ? ( $self ) : (); + } elsif ( $self->guarantor_relationships->count ) { + # I am a guarantee, just get all my guarantors + @guarantors = $self->guarantor_relationships->guarantors; + } else { + # I am a guarantor, I need to get all the guarantors of all my guarantees + @guarantors = map { $_->guarantor_relationships->guarantors } $self->guarantee_relationships->guarantees; + } + + my $non_issues_charges = 0; + my $seen = $include_this_patron ? {} : { $self->id => 1 }; # For tracking members already added to the total + foreach my $guarantor (@guarantors) { + $non_issues_charges += $guarantor->account->non_issues_charges if $include_guarantors && !$seen->{ $guarantor->id }; + + # We've added what the guarantor owes, not added in that guarantor's guarantees as well + my @guarantees = map { $_->guarantee } $guarantor->guarantee_relationships(); + my $guarantees_non_issues_charges = 0; + foreach my $guarantee (@guarantees) { + next if $seen->{ $guarantee->id }; + $guarantees_non_issues_charges += $guarantee->account->non_issues_charges; + # Mark this guarantee as seen so we don't double count a guarantee linked to multiple guarantors + $seen->{ $guarantee->id } = 1; + } + + $non_issues_charges += $guarantees_non_issues_charges; + $seen->{ $guarantor->id } = 1; + } + + return $non_issues_charges; +} + =head3 housebound_profile Returns the HouseboundProfile associated with this patron. --- a/circ/circulation.pl +++ a/circ/circulation.pl @@ -379,6 +379,12 @@ if (@$barcodes) { } } + if ( $error->{DEBT_GUARANTORS} ) { + $template_params->{DEBT_GUARANTORS} = $error->{DEBT_GUARANTORS}; + $template_params->{IMPOSSIBLE} = 1; + $blocker = 1; + } + if ( $error->{UNKNOWN_BARCODE} or not $onsite_checkout or not C4::Context->preference("OnSiteCheckoutsForce") ) { delete $question->{'DEBT'} if ($debt_confirmed); foreach my $impossible ( keys %$error ) { --- a/installer/data/mysql/atomicupdate/bug_19283.perl +++ a/installer/data/mysql/atomicupdate/bug_19283.perl @@ -0,0 +1,10 @@ +$DBversion = 'XXX'; # will be replaced by the RM +if ( CheckVersion($DBversion) ) { + $dbh->do(q{ + INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES + ('NoIssuesChargeGuarantorsWithGuarantees','','','Define maximum amount withstanding before checkouts are blocked including guarantors and their other guarantees','Integer'); + }); + + print "Upgrade to $DBversion done (Bug 19382 - Add ability to block guarantees based on fees owed by guarantor and other guarantees)\n"; + SetVersion($DBversion); +} --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -335,8 +335,9 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('NewItemsDefaultLocation','','','If set, all new items will have a location of the given Location Code ( Authorized Value type LOC )',''), ('NewsAuthorDisplay','none','none|opac|staff|both','Display the author name for news items.','Choice'), ('NewsToolEditor','tinymce','tinymce|codemirror','Choose tool for editing News.', 'Choice'), -('noissuescharge','5','','Define maximum amount withstanding before check outs are blocked','Integer'), -('NoIssuesChargeGuarantees','','','Define maximum amount withstanding before check outs are blocked','Integer'), +('noissuescharge','5','','Define maximum amount withstanding before checkouts are blocked','Integer'), +('NoIssuesChargeGuarantees','','','Define maximum amount withstanding before checkouts are blocked','Integer'), +('NoIssuesChargeGuarantorsWithGuarantees','','','Define maximum amount withstanding before checkouts are blocked including guarantors and their other guarantees','Integer'), ('noItemTypeImages','0',NULL,'If ON, disables itemtype images in the staff interface','YesNo'), ('NoRefundOnLostReturnedItemsAge','','','Do not refund lost item fees if item is lost for more than this number of days','Integer'), ('NoRenewalBeforePrecision','exact_time','date|exact_time','Calculate "No renewal before" based on date only or exact time of due date','Choice'), --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -349,6 +349,11 @@ Circulation: - pref: NoIssuesChargeGuarantees class: integer - '[% local_currency %] in fines.' + - + - Prevent a patron from checking out if the patron has guarantors and those guarantor's guarantees owing in total more than + - pref: NoIssuesChargeGuarantorsWithGuarantees + class: integer + - '[% local_currency %] in fines.' - - pref: RentalsInNoissuesCharge choices: --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -106,6 +106,10 @@
  • The patron's guarantees collectively have a debt of [% DEBT_GUARANTEES | $Price %].
  • [% END %] + [% IF ( DEBT_GUARANTORS ) %] +
  • The patron's guarantors and their other guarantees collectively have a debt of [% DEBT_GUARANTORS | $Price %].
  • + [% END %] + [% IF ( RENTALCHARGE && RENTALCHARGE > 0 ) %]
  • Rental charge for this item: [% RENTALCHARGE | $Price %]
  • [% END %] @@ -310,6 +314,10 @@