Bug 16223: Add ability to define liftable restrictions
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. This patch adds ability to create restrictions which are lifted after patron pays ceratain amount of fines. To test: 1. Apply this patch. 2. Restart your services if needed. 3. Navigate to page restrictions.pl. => Note that table has two new colums in it, "Lift after payment?" and "Fee limit". 4. Add new restriction which has "Lift after payment?" set as Yes and fee limit as 5. 5. Create fees for a patron so they exceed fee limit e.g. 10 6. Add restriction made in step 2. for the patron 7. Pay patrons fees partially so that they go under fee limit => Note that patrons restriction should now be lifted. Also prove t/db_dependent/Patron/Borrower_Debarments.t. Sponsored-by: Koha-Suomi Oy Signed-off-by: Anneli Österman <anneli.osterman@koha-suomi.fi> Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
parent
c894703b7c
commit
335f68eb51
6 changed files with 160 additions and 4 deletions
|
@ -39,6 +39,7 @@ use Koha::Account::DebitTypes;
|
|||
use Koha::Exceptions;
|
||||
use Koha::Exceptions::Account;
|
||||
use Koha::Plugins;
|
||||
use Koha::Patron::Debarments;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
@ -117,6 +118,8 @@ sub pay {
|
|||
}
|
||||
);
|
||||
|
||||
Koha::Patron::Debarments::del_restrictions_after_payment({ borrowernumber => $self->{patron_id} });
|
||||
|
||||
# NOTE: Pay historically always applied as much credit as it could to all
|
||||
# existing outstanding debits, whether passed specific debits or otherwise.
|
||||
if ( $payment->amountoutstanding ) {
|
||||
|
|
|
@ -21,6 +21,8 @@ use Modern::Perl;
|
|||
|
||||
use C4::Context;
|
||||
|
||||
use Koha::Patron::Restriction::Types;
|
||||
|
||||
our ( @ISA, @EXPORT_OK );
|
||||
|
||||
BEGIN {
|
||||
|
@ -270,6 +272,42 @@ sub UpdateBorrowerDebarmentFlags {
|
|||
return $dbh->do( "UPDATE borrowers SET debarred = ?, debarredcomment = ? WHERE borrowernumber = ?", {}, ( $expiration, $comment, $borrowernumber ) );
|
||||
}
|
||||
|
||||
=head2 del_restrictions_after_payment
|
||||
|
||||
my $success = del_restrictions_after_payment({
|
||||
borrowernumber => $borrowernumber,
|
||||
});
|
||||
|
||||
Deletes any restrictions from patron by following the rules
|
||||
defined in "Patron restrictions".
|
||||
|
||||
=cut
|
||||
|
||||
sub del_restrictions_after_payment {
|
||||
my ($params) = @_;
|
||||
|
||||
my $borrowernumber = $params->{'borrowernumber'};
|
||||
return unless ( $borrowernumber );
|
||||
|
||||
my $patron_restrictions = GetDebarments( { borrowernumber => $borrowernumber } );
|
||||
return unless ( $patron_restrictions );
|
||||
|
||||
my $patron = Koha::Patrons->find( $borrowernumber );
|
||||
return unless ( $patron );
|
||||
|
||||
my $lines = Koha::Account::Lines->search({ borrowernumber => $borrowernumber });
|
||||
my $total_due = $lines->total_outstanding;
|
||||
|
||||
foreach my $patron_restriction (@{ $patron_restrictions }){
|
||||
my $restriction = Koha::Patron::Restriction::Types->find({
|
||||
code => $patron_restriction->{type}
|
||||
});
|
||||
if($restriction->lift_after_payment && $total_due <= $restriction->fee_limit){
|
||||
DelDebarment($patron_restriction->{'borrower_debarment_id'});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
=head2 _GetBorrowernumberByDebarmentId
|
||||
|
||||
my $borrowernumber = _GetBorrowernumberByDebarmentId( $borrower_debarment_id );
|
||||
|
|
|
@ -54,6 +54,8 @@ if ( $op eq 'add_form') {
|
|||
} elsif ( $op eq 'add_validate' ) {
|
||||
|
||||
my $display_text = $input->param('display_text');
|
||||
my $lift_after_payment = $input->param('lift_after_payment');
|
||||
my $fee_limit = $input->param('fee_limit');
|
||||
my $is_a_modif = $input->param("is_a_modif");
|
||||
|
||||
if ($is_a_modif) {
|
||||
|
@ -64,13 +66,15 @@ if ( $op eq 'add_form') {
|
|||
display_text => $display_text,
|
||||
}
|
||||
);
|
||||
if ($dupe->count) {
|
||||
if ($dupe->count && $dupe->unblessed->{code} ne $code) {
|
||||
push @messages, {
|
||||
type => 'error', code => 'duplicate_display_text'
|
||||
};
|
||||
} else {
|
||||
my $restriction = Koha::Patron::Restriction::Types->find($code);
|
||||
$restriction->display_text($display_text);
|
||||
$restriction->lift_after_payment($lift_after_payment);
|
||||
$restriction->fee_limit($fee_limit);
|
||||
$restriction->store;
|
||||
push @messages, { type => 'message', code => 'update_success' };
|
||||
}
|
||||
|
@ -84,7 +88,9 @@ if ( $op eq 'add_form') {
|
|||
} else {
|
||||
my $restriction = Koha::Patron::Restriction::Type->new({
|
||||
code => $code,
|
||||
display_text => $display_text
|
||||
display_text => $display_text,
|
||||
lift_after_payment => $lift_after_payment,
|
||||
fee_limit => $fee_limit
|
||||
});
|
||||
$restriction->store;
|
||||
push @messages, { type => 'message', code => 'add_success' };
|
||||
|
|
|
@ -113,6 +113,19 @@
|
|||
<input type="text" value="[% restriction.display_text | html %]" name="display_text" id="display_text" size="50" maxlength="50" class="required" required="required" />
|
||||
<span class="required">Required</span>
|
||||
</li>
|
||||
<li>
|
||||
<label for="lift_after_payment" class="required">Lift after payment: </label>
|
||||
<select type="text" name="lift_after_payment" id="lift_after_payment" class="required" required="required" />
|
||||
<option value="1" selected="selected">Yes</option>
|
||||
<option value="0">No</option>
|
||||
</select>
|
||||
<span class="required">Required</span>
|
||||
</li>
|
||||
<li>
|
||||
<label for="fee_limit" class="required">Fee limit: </label>
|
||||
<input type="text" value="[% restriction.fee_limit | html %]" inputmode="decimal" pattern="^\d+(\.\d{2})?$" min="0" name="fee_limit" id="fee_limit" class="required" required="required" />
|
||||
<span class="required">Required</span>
|
||||
</li>
|
||||
[% ELSE %]
|
||||
<li>
|
||||
<label for="code" class="required">Code: </label>
|
||||
|
@ -124,6 +137,19 @@
|
|||
<input type="text" name="display_text" id="display_text" size="50" maxlength="50" class="required" required="required" />
|
||||
<span class="required">Required</span>
|
||||
</li>
|
||||
<li>
|
||||
<label for="lift_after_payment" class="required">Lift after payment: </label>
|
||||
<select type="text" name="lift_after_payment" id="lift_after_payment" class="required" required="required" />
|
||||
<option value="1" selected="selected">Yes</option>
|
||||
<option value="0">No</option>
|
||||
</select>
|
||||
<span class="required">Required</span>
|
||||
</li>
|
||||
<li>
|
||||
<label for="fee_limit" class="required">Fee limit: </label>
|
||||
<input type="text" inputmode="decimal" pattern="^\d+(\.\d{2})?$" min="0" name="fee_limit" id="fee_limit" class="required" required="required" />
|
||||
<span class="required">Required</span>
|
||||
</li>
|
||||
[% END %]
|
||||
</ol>
|
||||
</fieldset>
|
||||
|
@ -166,6 +192,8 @@
|
|||
<th scope="col">Code</th>
|
||||
<th scope="col">Label</th>
|
||||
<th scope="col">Default</th>
|
||||
<th scope="col">Lift after payment?</th>
|
||||
<th scope="col">Fee limit</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -181,6 +209,12 @@
|
|||
<td>
|
||||
[% IF restriction.is_default %]Yes[% END %]
|
||||
</td>
|
||||
<td>
|
||||
[% IF restriction.lift_after_payment %]Yes[% END %]
|
||||
</td>
|
||||
<td>
|
||||
[% IF restriction.fee_limit %][% restriction.fee_limit %][% END %]
|
||||
</td>
|
||||
<td class="actions">
|
||||
<a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/restrictions.pl?op=add_form&code=[% restriction.code | uri %]"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit</a>
|
||||
[% IF !restriction.is_system && !restriction.is_default %]
|
||||
|
|
|
@ -9,7 +9,8 @@ jQuery.validator.addMethod( "restrictionDisplayText", function(value){
|
|||
var ex = Object.values(existing).map(function(el) {
|
||||
return el.toLowerCase();
|
||||
});
|
||||
return (value.length > 0 && ex.indexOf(value.toLowerCase()) > -1) ?
|
||||
var code = $('input[name="code"]').val();
|
||||
return (value.length > 0 && ex.indexOf(value.toLowerCase()) > -1) && existing[code] != value ?
|
||||
false :
|
||||
true;
|
||||
}, MSG_DUPLICATE_DISPLAY_TEXT);
|
||||
|
|
|
@ -5,10 +5,11 @@ use Modern::Perl;
|
|||
use C4::Context;
|
||||
use Koha::Database;
|
||||
use Koha::Patrons;
|
||||
use Koha::Account;
|
||||
|
||||
use t::lib::TestBuilder;
|
||||
|
||||
use Test::More tests => 34;
|
||||
use Test::More tests => 38;
|
||||
|
||||
use_ok('Koha::Patron::Debarments');
|
||||
|
||||
|
@ -221,3 +222,76 @@ is( Koha::Patrons->find($borrowernumber3)->debarred,
|
|||
$debarreddate2, 'Koha::Patron->merge_with() transfers well debarred' );
|
||||
is( Koha::Patrons->find($borrowernumber3)->debarredcomment,
|
||||
$debarredcomment2, 'Koha::Patron->merge_with() transfers well debarredcomment' );
|
||||
|
||||
# Test removing debartments after payment
|
||||
$builder->build(
|
||||
{
|
||||
source => 'RestrictionType',
|
||||
value => {
|
||||
code => 'TEST',
|
||||
display_text => 'This is a test.',
|
||||
is_system => 0,
|
||||
is_default => 0,
|
||||
lift_after_payment => 1,
|
||||
fee_limit => 5
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$builder->build(
|
||||
{
|
||||
source => 'RestrictionType',
|
||||
value => {
|
||||
code => 'TEST2',
|
||||
display_text => 'This too is a test.',
|
||||
is_system => 0,
|
||||
is_default => 0,
|
||||
lift_after_payment => 1,
|
||||
fee_limit => 0
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
my $borrowernumber4 = Koha::Patron->new(
|
||||
{
|
||||
firstname => 'First',
|
||||
surname => 'Sur',
|
||||
categorycode => $patron_category->{categorycode},
|
||||
branchcode => $library->{branchcode},
|
||||
}
|
||||
)->store->borrowernumber;
|
||||
|
||||
my $account = Koha::Account->new({ patron_id => $borrowernumber4 });
|
||||
my $line1 = $account->add_debit({ type => 'ACCOUNT', amount => 10, interface => 'commandline' });
|
||||
|
||||
Koha::Patron::Debarments::AddDebarment(
|
||||
{
|
||||
borrowernumber => $borrowernumber4,
|
||||
expiration => '9999-06-10',
|
||||
type => 'TEST',
|
||||
comment => 'Test delete'
|
||||
}
|
||||
);
|
||||
|
||||
Koha::Patron::Debarments::AddDebarment(
|
||||
{
|
||||
borrowernumber => $borrowernumber4,
|
||||
expiration => '9999-10-10',
|
||||
type => 'TEST2',
|
||||
comment => 'Test delete again',
|
||||
}
|
||||
);
|
||||
|
||||
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber4 });
|
||||
|
||||
is( @$debarments, 2, "GetDebarments returns 2 debarments before payment" );
|
||||
|
||||
$account->pay({amount => 5});
|
||||
|
||||
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber4 });
|
||||
is( @$debarments, 1, "GetDebarments returns 1 debarment after paying half of the fee" );
|
||||
is( @$debarments[0]->{type}, "TEST2", "Debarment left has type value 'TEST2'" );
|
||||
|
||||
$account->pay({amount => 5});
|
||||
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber4 });
|
||||
is( @$debarments, 0, "GetDebarments returns 0 debarments after paying all fees" );
|
||||
|
|
Loading…
Reference in a new issue