From 0deeb8b95c70885fba2edaec771fbb624d5a0b06 Mon Sep 17 00:00:00 2001 From: Lari Taskula Date: Thu, 7 Apr 2016 11:47:02 +0000 Subject: [PATCH] Bug 16223: Automatically remove any borrower debarments after a payment Some libraries debar Patrons at the end of the year for having unpaid fines, like in Bug 15157. Currently librarians have to manually remove this type of debarments after Patron has paid his/her fines. Add a system preference to define debarments that should be automatically removed after a payment is made, and add functionality to actually remove the defined debarments from Patron. Also let libraries to define the amount of outstanding fines after payment after which the debarment will be removed. This patch introduces a system preference DebarmentsToLiftAfterPayment, which allows libraries to define rules for removing debarments after paying fines. The system preference uses YAML and is defined as follows: Debarment with this comments will be removed: outstanding: 5 Which means that if a Patron has a debarment "Debarment with this comment will be removed", and he pays his fines and charges until his outstanding fees are equal or less than 5.00, this debarment will be lifted. The parameter outstanding is optional - if not given, the debarment will be lifted until Patron has paid all of his outstanding fees (in other words, equal to "outstanding: 0"). To test: 1. Set a debarment to a Patron 2. Set a fine for Patron 3. Define rule(s) for removing debarment(s) in system preference DebarmentsToLiftAfterPayment 4. Pay the fine you set in step 2 5. Note that the debarment is now lifted --- C4/Accounts.pm | 7 +++ Koha/Patron/Debarments.pm | 64 ++++++++++++++++++++++ ...move_any_borrower_debarments_after_a_payment.pl | 17 ++++++ installer/data/mysql/sysprefs.sql | 1 + .../prog/en/modules/admin/preferences/patrons.pref | 11 ++++ t/db_dependent/Patron/Borrower_Debarments.t | 24 +++++++- 6 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 installer/data/mysql/atomicupdate/Bug_16223_-_Automatically_remove_any_borrower_debarments_after_a_payment.pl diff --git a/C4/Accounts.pm b/C4/Accounts.pm index 5243712..3ee3a39 100644 --- a/C4/Accounts.pm +++ b/C4/Accounts.pm @@ -25,6 +25,7 @@ use C4::Stats; use C4::Members; use C4::Circulation qw(ReturnLostItem); use C4::Log qw(logaction); +use Koha::Patron::Debarments; use Data::Dumper qw(Dumper); @@ -164,6 +165,7 @@ sub recordpayment { borrowernumber => $borrowernumber, accountno => $nextaccntno } ); + Koha::Patron::Debarments::DelDebarmentsAfterPayment({ borrowernumber => $borrowernumber }); if ( C4::Context->preference("FinesLog") ) { $accdata->{'amountoutstanding_new'} = $newamtos; @@ -281,6 +283,7 @@ sub makepayment { borrowernumber => $borrowernumber, accountno => $accountno }); + Koha::Patron::Debarments::DelDebarmentsAfterPayment({ borrowernumber => $borrowernumber }); #check to see what accounttype if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) { @@ -574,6 +577,7 @@ sub ReversePayment { })); } + Koha::Patron::Debarments::DelDebarmentsAfterPayment({ borrowernumber => $row->{'borrowernumber'} }); } @@ -664,6 +668,7 @@ sub recordpayment_selectaccts { borrowernumber => $borrowernumber, accountno => $nextaccntno} ); + Koha::Patron::Debarments::DelDebarmentsAfterPayment({ borrowernumber => $borrowernumber }); if ( C4::Context->preference("FinesLog") ) { logaction("FINES", 'CREATE',$borrowernumber,Dumper({ @@ -731,6 +736,7 @@ sub makepartialpayment { borrowernumber => $borrowernumber, accountno => $accountno }); + Koha::Patron::Debarments::DelDebarmentsAfterPayment({ borrowernumber => $borrowernumber }); if ( C4::Context->preference("FinesLog") ) { logaction("FINES", 'CREATE',$borrowernumber,Dumper({ @@ -820,6 +826,7 @@ sub WriteOffFee { amount => $amount, borrowernumber => $borrowernumber} ); + Koha::Patron::Debarments::DelDebarmentsAfterPayment({ borrowernumber => $borrowernumber }); } diff --git a/Koha/Patron/Debarments.pm b/Koha/Patron/Debarments.pm index c305ba9..3394bcd 100644 --- a/Koha/Patron/Debarments.pm +++ b/Koha/Patron/Debarments.pm @@ -20,7 +20,10 @@ package Koha::Patron::Debarments; use Modern::Perl; use C4::Context; +use C4::Members; +use Koha::Patrons; +use YAML::XS; use parent qw( Exporter ); our @EXPORT = qw( @@ -34,6 +37,8 @@ our @EXPORT = qw( DelUniqueDebarment IsDebarred + + DelDebarmentsAfterPayment ); =head1 Koha::Patron::Debarments @@ -268,6 +273,65 @@ sub DelUniqueDebarment { return DelDebarment( $debarment->{'borrower_debarment_id'} ); } +=head2 DelDebarmentsAfterPayment + +my $success = DelDebarmentsAfterPayment({ + borrowernumber => $borrowernumber, +}); + +Deletes any debarments from Borrower by following the rules +defined in system preference DebarmentsToLiftAfterPayment + +Debarments are defined in the system preference by comment. + +=cut + +sub DelDebarmentsAfterPayment { + my ($params) = @_; + + my $borrowernumber = $params->{'borrowernumber'}; + return unless ( $borrowernumber ); + + my $debarments = GetDebarments( { borrowernumber => $borrowernumber } ); + return unless ( $debarments ); + + my $liftDebarmentRules = C4::Context->preference("DebarmentsToLiftAfterPayment"); + return unless ( $liftDebarmentRules ); + + my $borrower = Koha::Patrons->find( $borrowernumber ); + return unless ( $borrower ); + + $liftDebarmentRules = YAML::XS::Load( + Encode::encode( + 'UTF-8', + $liftDebarmentRules, + Encode::FB_CROAK + )); + + my ( $total_due, $accts, $numaccts ) = C4::Members::GetMemberAccountRecords($borrowernumber); + + foreach my $debarment (@{ $debarments }){ + if (exists $liftDebarmentRules->{$debarment->{'comment'}}) { + # Delete debarment IF: + # 1. there is no maximum outstanding fines defined for the liftDebarmentRule + # and there is no outstanding fines. + # 2. there is a maximum outstanding fines amount defined + # and total_due is smaller or equal than the defined maximum outstanding amount + # Otherwise, do not lift the debarment. + if (not defined $liftDebarmentRules->{$debarment->{'comment'}}->{'outstanding'}){ + if ($total_due <= 0) { + DelDebarment($debarment->{'borrower_debarment_id'}); + } + } + else { + if ($total_due <= $liftDebarmentRules->{$debarment->{'comment'}}->{'outstanding'}) { + DelDebarment($debarment->{'borrower_debarment_id'}); + } + } + } + } +} + =head2 _UpdateBorrowerDebarmentFlags my $success = _UpdateBorrowerDebarmentFlags( $borrowernumber ); diff --git a/installer/data/mysql/atomicupdate/Bug_16223_-_Automatically_remove_any_borrower_debarments_after_a_payment.pl b/installer/data/mysql/atomicupdate/Bug_16223_-_Automatically_remove_any_borrower_debarments_after_a_payment.pl new file mode 100644 index 0000000..63f18a7 --- /dev/null +++ b/installer/data/mysql/atomicupdate/Bug_16223_-_Automatically_remove_any_borrower_debarments_after_a_payment.pl @@ -0,0 +1,17 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use C4::Context; +use Koha::AtomicUpdater; + +my $dbh = C4::Context->dbh; +my $atomicUpdater = Koha::AtomicUpdater->new(); + +unless($atomicUpdater->find('Bug16223')) { + # Add system preference + $dbh->do("INSERT INTO systempreferences (variable, value, options, explanation, type) + VALUES ('DebarmentsToLiftAfterPayment', '', '', 'Lift these debarments after Borrower has paid his/her fees', 'textarea')"); + + print "Upgrade done (Bug 16623: Automatically remove any borrower debarments after a payment)\n"; +} diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index ef4c3f0..984832c 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -103,6 +103,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('CronjobLog','0',NULL,'If ON, log information from cron jobs.','YesNo'), ('CurrencyFormat','US','US|FR','Determines the display format of currencies. eg: \'36000\' is displayed as \'360 000,00\' in \'FR\' or \'360,000.00\' in \'US\'.','Choice'), ('dateformat','us','metric|us|iso|dmydot','Define global date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy-mm-dd, dmydot dd.mm.yyyy)','Choice'), +('DebarmentsToLiftAfterPayment', '', '', 'Lift these debarments after Borrower has paid his/her fees', 'textarea'), ('DebugLevel','2','0|1|2','Define the level of debugging information sent to the browser when errors are encountered (set to 0 in production). 0=none, 1=some, 2=most','Choice'), ('decreaseLoanHighHolds',NULL,'','Decreases the loan period for items with number of holds above the threshold specified in decreaseLoanHighHoldsValue','YesNo'), ('decreaseLoanHighHoldsControl', 'static', 'static|dynamic', "Chooses between static and dynamic high holds checking", 'Choice'), diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref index 22c2b27..b1aac70 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref @@ -50,6 +50,17 @@ Patrons: katipo: Do - check and construct borrower card numbers in the Katipo style. This overrides autoMemberNum if on. - + - pref: DebarmentsToLiftAfterPayment + type: textarea + class: code + - Lift these debarments after Borrower has paid his/her fees + - "

Example, debarment is lifted after all fees are paid:

" + - "
Debarment message:
+
  outstanding: 0
" + - "

Example, debarment is lifted after payment with outstanding fees less or equal than 5:

" + - "
Another debarment:
+
  outstanding: 5.00
" + - - pref: EnhancedMessagingPreferences choices: yes: Allow diff --git a/t/db_dependent/Patron/Borrower_Debarments.t b/t/db_dependent/Patron/Borrower_Debarments.t index bb92094..a9cce50 100755 --- a/t/db_dependent/Patron/Borrower_Debarments.t +++ b/t/db_dependent/Patron/Borrower_Debarments.t @@ -8,7 +8,7 @@ use Koha::Database; use t::lib::TestBuilder; -use Test::More tests => 31; +use Test::More tests => 33; use_ok('Koha::Patron::Debarments'); @@ -161,3 +161,25 @@ is( IsDebarred( $borrowernumber ), undef, 'A patron without a debarred date is n $dbh->do(q|UPDATE borrowers SET debarred = '9999-12-31'|); # Note: Change this test before the first of January 10000! is( IsDebarred( $borrowernumber ), '9999-12-31', 'A patron with a debarred date in the future is debarred' ); + +my $debarmentsRulesPref = C4::Context->preference("DebarmentsToLiftAfterPayment"); +C4::Context->set_preference("DebarmentsToLiftAfterPayment", "Test debarment:\n outstanding: 0\nTest debarment 2:"); + +AddDebarment({ + borrowernumber => $borrowernumber, + comment => 'Test debarment', +}); +AddDebarment({ + borrowernumber => $borrowernumber, + comment => 'Test debarment 2', +}); + +$debarments = GetDebarments({ borrowernumber => $borrowernumber }); +is( @$debarments, 2, "GetDebarments returns 2 debarments before payment" ); + +DelDebarmentsAfterPayment({ borrowernumber => $borrowernumber }); +C4::Context->set_preference("DebarmentsToLiftAfterPayment", $debarmentsRulesPref); + +$debarments = GetDebarments({ borrowernumber => $borrowernumber }); +is( @$debarments, 0, "GetDebarments returns 0 debarments after payment" ); + -- 1.9.1