--- a/Koha/Patron/Discharge.pm 2024-07-23 15:40:04.029970274 +0300
+++ b/Koha/Patron/Discharge.pm 2025-12-10 14:36:25.809164340 +0200
@@ -39,8 +39,22 @@
my $patron = Koha::Patrons->find( $params->{borrowernumber} );
return unless $patron;
- my $has_pending_checkouts = $patron->checkouts->count;
- return $has_pending_checkouts ? 0 : 1;
+ my $can_be_discharged = 1;
+ my $problems = {};
+
+ my $checkouts = $patron->checkouts->count;
+ if ($checkouts) {
+ $can_be_discharged = 0;
+ $problems->{checkouts} = $checkouts;
+ }
+
+ my $debt = $patron->account->outstanding_debits->total_outstanding;
+ if ( $debt > 0 ) {
+ $can_be_discharged = 0;
+ $problems->{debt} = $debt;
+ }
+
+ return ( $can_be_discharged, $problems );
}
sub is_discharged {
@@ -62,7 +76,8 @@
my ($params) = @_;
my $borrowernumber = $params->{borrowernumber};
return unless $borrowernumber;
- return unless can_be_discharged({ borrowernumber => $borrowernumber });
+ my ($can) = can_be_discharged( { borrowernumber => $borrowernumber } );
+ return unless $can;
my $rs = Koha::Database->new->schema->resultset('Discharge');
return $rs->create({
@@ -74,7 +89,9 @@
sub discharge {
my ($params) = @_;
my $borrowernumber = $params->{borrowernumber};
- return unless $borrowernumber and can_be_discharged( { borrowernumber => $borrowernumber } );
+
+ my ($can) = can_be_discharged( { borrowernumber => $borrowernumber } );
+ return unless $borrowernumber and $can;
# Cancel reserves
my $patron = Koha::Patrons->find( $borrowernumber );
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-discharge.tt 2025-05-20 17:40:38.293395967 +0300
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-discharge.tt 2025-12-10 14:46:03.093599152 +0200
@@ -1,5 +1,6 @@
[% USE raw %]
[% USE Koha %]
+[% USE Price %]
[% USE AdditionalContents %]
[% SET OpacNav = AdditionalContents.get( location => "OpacNav", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %]
[% SET OpacNavBottom = AdditionalContents.get( location => "OpacNavBottom", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %]
@@ -43,20 +44,32 @@
Get your discharge
[% ELSIF pending %]
Your discharge will be available on this page within a few days.
- [% ELSIF has_issues %]
- You cannot be discharged, you have checked out items. Please return items before asking for a discharge.
[% ELSIF not messages %]
What is a discharge?
This document certifies that you have returned all borrowed items. It is sometimes asked during a file transfer from a school to another. The discharge is sent by us to your school. You will also find it available on your reader account.
Warning: This request is only valid if you are in good standing with the library. Once the application is made, you can not borrow library materials.
- [% IF has_checkouts %]
- You cannot be discharged, you have checked out items. Please return items before asking for a discharge.
- [% ELSE %]
+ [% IF can_be_discharged %]
+ [% ELSE %]
+ [% IF failure %]
+ There was an error during the discharge process
+ [% END %]
+ You cannot be discharged because:
+
+ [% IF discharge_problems.checkouts %]
+ - You have [% discharge_problems.checkouts | html %] item(s) checked out. Please return your checked out items before reapplying.
+ [% END %]
+
+ [% IF discharge_problems.debt %]
+ - You have unpaid charges of [% discharge_problems.debt | $Price %]. Please pay your charges before reapplying.
+ [% END %]
+
+
[% END %]
[% END %]
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-discharge.tt 2025-05-20 17:40:38.293395967 +0300
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-discharge.tt 2025-12-10 14:46:03.093599152 +0200
@@ -1,5 +1,6 @@
[% USE raw %]
[% USE Koha %]
+[% USE Price %]
[% USE AdditionalContents %]
[% SET OpacNav = AdditionalContents.get( location => "OpacNav", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %]
[% SET OpacNavBottom = AdditionalContents.get( location => "OpacNavBottom", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %]
@@ -43,20 +44,32 @@
Get your discharge
[% ELSIF pending %]
Your discharge will be available on this page within a few days.
- [% ELSIF has_issues %]
- You cannot be discharged, you have checked out items. Please return items before asking for a discharge.
[% ELSIF not messages %]
What is a discharge?
This document certifies that you have returned all borrowed items. It is sometimes asked during a file transfer from a school to another. The discharge is sent by us to your school. You will also find it available on your reader account.
Warning: This request is only valid if you are in good standing with the library. Once the application is made, you can not borrow library materials.
- [% IF has_checkouts %]
- You cannot be discharged, you have checked out items. Please return items before asking for a discharge.
- [% ELSE %]
+ [% IF can_be_discharged %]
+ [% ELSE %]
+ [% IF failure %]
+ There was an error during the discharge process
+ [% END %]
+ You cannot be discharged because:
+
+ [% IF discharge_problems.checkouts %]
+ - You have [% discharge_problems.checkouts | html %] item(s) checked out. Please return your checked out items before reapplying.
+ [% END %]
+
+ [% IF discharge_problems.debt %]
+ - You have unpaid charges of [% discharge_problems.debt | $Price %]. Please pay your charges before reapplying.
+ [% END %]
+
+
[% END %]
[% END %]
--- a/members/discharge.pl 2025-05-20 17:40:38.555392536 +0300
+++ b/members/discharge.pl 2025-12-10 14:26:03.817925780 +0200
@@ -61,9 +61,8 @@
my $patron = Koha::Patrons->find( $borrowernumber );
output_and_exit_if_error( $input, $cookie, $template, { module => 'members', logged_in_user => $logged_in_user, current_patron => $patron } );
-my $can_be_discharged = Koha::Patron::Discharge::can_be_discharged({
- borrowernumber => $borrowernumber
-});
+my ( $can_be_discharged, $discharge_problems ) =
+ Koha::Patron::Discharge::can_be_discharged( { borrowernumber => $borrowernumber } );
# Generating discharge if needed
if ( $op eq 'cud-discharge' && $input->param('discharge') and $can_be_discharged ) {
@@ -107,6 +106,7 @@
$template->param(
patron => $patron,
can_be_discharged => $can_be_discharged,
+ discharge_problems => $discharge_problems,
validated_discharges => \@validated_discharges,
);
--- a/opac/opac-discharge.pl 2025-05-20 17:40:45.151306301 +0300
+++ b//opac/opac-discharge.pl 2025-12-10 14:59:49.806228119 +0200
@@ -43,10 +43,14 @@
type => "opac",
});
-my $can_be_discharged = Koha::Patron::Discharge::can_be_discharged({ borrowernumber => $loggedinuser });
-if ($can_be_discharged == 0) {
- $template->param( has_checkouts => 1 );
-}
+my ( $can_be_discharged, $discharge_problems ) =
+ Koha::Patron::Discharge::can_be_discharged( { borrowernumber => $loggedinuser } );
+my $patron = Koha::Patrons->find($loggedinuser);
+
+$template->param(
+ can_be_discharged => $can_be_discharged,
+ discharge_problems => $discharge_problems,
+);
my $pending = Koha::Patron::Discharge::count({
borrowernumber => $loggedinuser,
@@ -67,7 +71,7 @@
$template->param( success => 1 );
}
else {
- $template->param( has_issues => 1 );
+ $template->param( failure => 1 );
}
}
elsif ( $op eq 'get' ) {
--- a/t/db_dependent/Patron/Borrower_Discharge.t 2025-05-20 17:40:46.600287390 +0300
+++ b/t/db_dependent/Patron/Borrower_Discharge.t 2025-12-10 14:33:21.243162635 +0200
@@ -16,7 +16,7 @@
use Modern::Perl;
-use Test::More tests => 23;
+use Test::More tests => 32;
use Test::MockModule;
use Test::Warn;
@@ -83,17 +83,56 @@
);
AddIssue( $patron, $barcode );
-is( Koha::Patron::Discharge::can_be_discharged({ borrowernumber => $patron->borrowernumber }), 0, 'A patron with issues cannot be discharged' );
+my ( $can, $problems ) = Koha::Patron::Discharge::can_be_discharged( { borrowernumber => $patron->borrowernumber } );
+is( $can, 0, 'A patron with issues cannot be discharged' );
+is( $problems->{checkouts}, 1, "Patron has checkouts" );
+is( $problems->{debt}, undef, "Patron has no debt" );
is( Koha::Patron::Discharge::request({ borrowernumber => $patron->borrowernumber }), undef, 'No request done if patron has issues' );
is( Koha::Patron::Discharge::discharge({ borrowernumber => $patron->borrowernumber }), undef, 'No discharge done if patron has issues' );
is_deeply( [ Koha::Patron::Discharge::get_pendings ], [], 'There is no pending discharge request' );
is_deeply( [ Koha::Patron::Discharge::get_validated ], [], 'There is no validated discharge' );
+# Discharge not possible with issues and fines
+$patron->account->add_debit(
+ {
+ amount => 0.1,
+ interface => C4::Context->interface,
+ type => 'OVERDUE'
+ }
+);
+
+( $can, $problems ) = Koha::Patron::Discharge::can_be_discharged( { borrowernumber => $patron->borrowernumber } );
+is(
+ $can, 0,
+ 'A patron with fines and checkouts cannot be discharged'
+);
+is( $problems->{checkouts}, 1, "Patron has checkouts" );
+is( $problems->{debt}, 0.1, "Patron has debt" );
+
AddReturn( $barcode );
-# Discharge possible without issue
-is( Koha::Patron::Discharge::can_be_discharged({ borrowernumber => $patron->borrowernumber }), 1, 'A patron without issues can be discharged' );
+( $can, $problems ) = Koha::Patron::Discharge::can_be_discharged( { borrowernumber => $patron->borrowernumber } );
+is(
+ $can, 0,
+ 'A patron with fines cannot be discharged'
+);
+is( $problems->{checkouts}, undef, "Patron has checkouts" );
+is( $problems->{debt}, 0.1, "Patron has debt" );
+
+$patron->account->pay(
+ {
+ amount => 0.1,
+ }
+);
+
+# Discharge possible without issue or fine
+( $can, $problems ) = Koha::Patron::Discharge::can_be_discharged( { borrowernumber => $patron->borrowernumber } );
+ is(
+ $can, 1,
+ 'A patron without issues or fines can be discharged'
+ );
+is( scalar keys %$problems, 0, "No dishcharge problems found" );
is(Koha::Patron::Discharge::generate_as_pdf,undef,"Confirm failure when lacking borrower number");