Bugzilla – Attachment 188750 Details for
Bug 23415
Notify patron fines when renewing
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 23415: Add debt override support to circulation checkout page
Bug-23415-Add-debt-override-support-to-circulation.patch (text/plain), 16.76 KB, created by
Martin Renvoize (ashimema)
on 2025-10-31 06:58:43 UTC
(
hide
)
Description:
Bug 23415: Add debt override support to circulation checkout page
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2025-10-31 06:58:43 UTC
Size:
16.76 KB
patch
obsolete
>From 92d485821faa998c4d3815785bbcfc9f10666bd4 Mon Sep 17 00:00:00 2001 >From: Martin Renvoize <martin.renvoize@openfifth.co.uk> >Date: Thu, 30 Oct 2025 14:56:34 +0000 >Subject: [PATCH] Bug 23415: Add debt override support to circulation checkout > page > >This patch implements fine override functionality for the checkouts >table on the circulation page (circ/circulation.pl), completing the >debt override feature for all renewal workflows. > >Changes: >- Added override_debt checkbox to checkouts-table.inc when > AllowFineOverrideRenewing preference is enabled >- Updated /svc/renew to accept and process override_debt parameter, > matching the pattern used for override_limit >- Enhanced circulation-api-client.js to pass override_debt parameter > through the renewal API call >- Implemented specific CSS classes for renewal error types > (renewals-allowed-too_many, renewals-allowed-too_much_owing, etc.) > to enable selective checkbox control >- Modified override checkbox handlers to selectively enable only > relevant renewal checkboxes based on the specific blocking error: > * override_limit enables checkboxes for 'too_many' and 'on_reserve' > * override_debt enables checkboxes for 'too_much_owing' and > 'auto_too_much_owing' >- Added AllowFineOverrideRenewing JavaScript variable to circulation.tt > >This provides clear visual feedback to staff about which renewals will >be affected by each override option, improving usability and reducing >confusion when multiple items have different blocking reasons. >--- > circ/renew.pl | 4 +-- > .../prog/en/includes/checkouts-table.inc | 10 ++++++ > .../prog/en/modules/circ/circulation.tt | 1 + > .../prog/en/modules/circ/renew.tt | 20 ++++++++---- > koha-tmpl/intranet-tmpl/prog/js/checkouts.js | 31 +++++++++++++------ > .../prog/js/fetch/circulation-api-client.js | 5 +-- > svc/renew | 9 ++++++ > .../Circulation/FineNoRenewals_spec.ts | 19 ++++++------ > 8 files changed, 70 insertions(+), 29 deletions(-) > >diff --git a/circ/renew.pl b/circ/renew.pl >index 44ab1435fca..67df976745a 100755 >--- a/circ/renew.pl >+++ b/circ/renew.pl >@@ -53,7 +53,7 @@ my $hard_due_date = $cgi->param('hard_due_date'); > > my ( $item, $checkout, $patron ); > my $error = q{}; >-my ( $soonest_renew_date, $latest_auto_renew_date, $balance ); >+my ( $soonest_renew_date, $latest_auto_renew_date ); > > if ( $op eq 'cud-renew' && $barcode ) { > $barcode = barcodedecode($barcode) if $barcode; >@@ -100,8 +100,6 @@ if ( $op eq 'cud-renew' && $barcode ) { > $can_renew = 1; > $error = undef; > } else { >- $balance = $patron->account->balance; >- $template->param( balance => $balance ); > $can_renew = 0; > } > } >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc >index 316b28889b3..adb0545d483 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc >@@ -64,6 +64,10 @@ > <label for="override_limit">Override renewal restrictions:</label> > <input type="checkbox" name="override_limit" id="override_limit" value="1" /> > [% END %] >+ [% IF Koha.Preference( 'AllowFineOverrideRenewing' ) %] >+ <label for="override_debt">Override fine restrictions:</label> >+ <input type="checkbox" name="override_debt" id="override_debt" value="1" /> >+ [% END %] > [% END %] > [% IF ( CAN_user_circulate_circulate_remaining_permissions ) %] > [% IF Koha.Preference( 'UnseenRenewals' ) %] >@@ -75,6 +79,12 @@ > <button class="btn btn-default" id="RenewAll"><i class="fa fa-book"></i> Renew all</button> > [% END %] > </fieldset> >+ [% IF patron.account.non_issues_charges >= Koha.Preference('FineNoRenewals') %] >+ <p >+ ><strong>Note: </strong> Patron has <strong><span id="patron-non-issues-charges">[% patron.account.non_issues_charges | $Price %]</span></strong> of non-issuing charges outstanding, renewals are restricted at >+ <strong><span id="fine-no-renewals-limit">[% Koha.Preference('FineNoRenewals') | $Price %]</span></strong></p >+ > >+ [% END %] > > [% IF Koha.Preference('ExportCircHistory') %] > <fieldset> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >index 041e3e8b436..02c1a4941fd 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >@@ -1096,6 +1096,7 @@ > var exports_enabled = [% Koha.Preference('ExportCircHistory') ? 1 : 0 | html %]; > var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride') )? 1: 0 | html %]; > var AllowRenewalOnHoldOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalOnHoldOverride') )? 1: 0 | html %]; >+ var AllowFineOverrideRenewing = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowFineOverrideRenewing') )? 1: 0 | html %]; > var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 | html %]; > var script = "circulation"; > var relatives_borrowernumbers = new Array(); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt >index 53b2df6a5ca..66cf5f32a7c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/renew.tt >@@ -129,11 +129,14 @@ > [% ELSIF error == "auto_renew" or error == "auto_too_much_owing" %] > <p>[% INCLUDE 'biblio-title.inc' biblio=item.biblio link = 1 %] ( [% item.barcode | html %] ) has been scheduled for automatic renewal. </p> > [% IF error == "auto_too_much_owing" %] >- [% IF balance %] >- <ul> >- <li>The patron has a debt of [% balance | $Price %] and renewals are restricted at [% Koha.Preference('FineNoRenewals') | $Price %].</li> >- </ul> >- [% END %] >+ [% SET patron_account = borrower.account %] >+ [% SET total_balance = patron_account.balance %] >+ [% SET non_issues_charges = patron_account.non_issues_charges %] >+ [% SET fine_no_renewals = Koha.Preference('FineNoRenewals') %] >+ <ul> >+ <li>The patron has a total debt of [% total_balance | $Price %], of which [% non_issues_charges | $Price %] are non-issuing charges.</li> >+ <li>Renewals are blocked when non-issuing charges exceed [% fine_no_renewals | $Price %].</li> >+ </ul> > [% IF Koha.Preference('AllowFineOverrideRenewing') %] > <form method="post" action="/cgi-bin/koha/circ/renew.pl"> > [% INCLUDE 'csrf-token.inc' %] >@@ -156,8 +159,13 @@ > [% END %] > [% END %] > [% ELSIF error == "too_much_owing" %] >+ [% SET patron_account = borrower.account %] >+ [% SET total_balance = patron_account.balance %] >+ [% SET non_issues_charges = patron_account.non_issues_charges %] >+ [% SET fine_no_renewals = Koha.Preference('FineNoRenewals') %] > <ul> >- <li>The patron has a debt of [% balance | $Price %] and renewals are restricted at [% Koha.Preference('FineNoRenewals') | $Price %].</li> >+ <li>The patron has a total debt of [% total_balance | $Price %], of which [% non_issues_charges | $Price %] are non-issuing charges.</li> >+ <li>Renewals are blocked when non-issuing charges exceed [% fine_no_renewals | $Price %].</li> > </ul> > [% IF Koha.Preference('AllowFineOverrideRenewing') %] > <form method="post" action="/cgi-bin/koha/circ/renew.pl"> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js >index 107541a2c99..1cab6faa393 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js >@@ -393,7 +393,7 @@ function LoadIssuesTable() { > "</span>"; > > span_style = "display: none"; >- span_class = "renewals-allowed"; >+ span_class = "renewals-allowed-too_many"; > } else if (oObj.can_renew_error == "too_unseen") { > msg += > "<span>" + >@@ -447,7 +447,7 @@ function LoadIssuesTable() { > "</span>"; > > span_style = "display: none"; >- span_class = "renewals-allowed"; >+ span_class = "renewals-allowed-auto_too_much_owing"; > } else if ( > oObj.can_renew_error == "auto_account_expired" > ) { >@@ -476,13 +476,12 @@ function LoadIssuesTable() { > msg += > "<span class='renewals-disabled'>" + > __( >- "Cannot renew, the patron has a debt of " + >- parseFloat(oObj.fine).format_price() >+ "Cannot renew - patron has debts blocking renewal" > ) + > "</span>"; > > span_style = "display: none"; >- span_class = "renewals-allowed"; >+ span_class = "renewals-allowed-too_much_owing"; > } else { > msg += > "<span class='renewals-disabled'>" + >@@ -968,6 +967,7 @@ $(document).ready(function () { > > function renew(item_id) { > var override_limit = $("#override_limit").is(":checked") ? 1 : 0; >+ var override_debt = $("#override_debt").is(":checked") ? 1 : 0; > > $(this) > .parent() >@@ -987,6 +987,7 @@ $(document).ready(function () { > patron_id: borrowernumber, > library_id: branchcode, > override_limit: override_limit, >+ override_debt: override_debt, > }; > > if (UnseenRenewals) { >@@ -1379,16 +1380,28 @@ $(document).ready(function () { > .click(function () { > if (this.checked) { > if (AllowRenewalLimitOverride) { >- $(".renewals-allowed").show(); >- $(".renewals-disabled").hide(); >+ $(".renewals-allowed-too_many").show(); > } > if (AllowRenewalOnHoldOverride) { > $(".renewals-allowed-on_reserve").show(); > } > } else { >- $(".renewals-allowed").hide(); >+ $(".renewals-allowed-too_many").hide(); > $(".renewals-allowed-on_reserve").hide(); >- $(".renewals-disabled").show(); >+ } >+ }) >+ .prop("checked", false); >+ } >+ >+ if (AllowFineOverrideRenewing) { >+ $("#override_debt") >+ .click(function () { >+ if (this.checked) { >+ $(".renewals-allowed-too_much_owing").show(); >+ $(".renewals-allowed-auto_too_much_owing").show(); >+ } else { >+ $(".renewals-allowed-too_much_owing").hide(); >+ $(".renewals-allowed-auto_too_much_owing").hide(); > } > }) > .prop("checked", false); >diff --git a/koha-tmpl/intranet-tmpl/prog/js/fetch/circulation-api-client.js b/koha-tmpl/intranet-tmpl/prog/js/fetch/circulation-api-client.js >index 2b478eebb7f..3f8f3368a29 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/fetch/circulation-api-client.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/fetch/circulation-api-client.js >@@ -31,11 +31,12 @@ export class CirculationAPIClient { > this.httpClient.post({ > endpoint: "renew", > body: >- "itemnumber=%s&borrowernumber=%s&branchcode=%s&override_limit=%s".format( >+ "itemnumber=%s&borrowernumber=%s&branchcode=%s&override_limit=%s&override_debt=%s".format( > checkout.item_id, > checkout.patron_id, > checkout.library_id, >- checkout.override_limit >+ checkout.override_limit, >+ checkout.override_debt || 0 > ) + > (checkout.seen !== undefined > ? "&seen=%s".format(checkout.seen) >diff --git a/svc/renew b/svc/renew >index 86c8b1548ae..faff4c822a9 100755 >--- a/svc/renew >+++ b/svc/renew >@@ -46,10 +46,12 @@ print $input->header( -type => 'application/json', -charset => 'UTF-8' ); > my $itemnumber = $input->param('itemnumber'); > my $borrowernumber = $input->param('borrowernumber'); > my $override_limit = $input->param('override_limit'); >+my $override_debt = $input->param('override_debt'); > my $branchcode = $input->param('branchcode') > || C4::Context->userenv->{'branch'}; > my $seen = $input->param('seen'); > my $date_due; >+ > if ( $input->param('date_due') ) { > $date_due = dt_from_string( scalar $input->param('date_due') ); > } >@@ -79,6 +81,13 @@ if ( $data->{error} && $data->{error} eq 'too_many' && C4::Context->preference(' > push @{$confirmations}, 'RENEWAL_LIMIT' if $override_limit; > } > >+if ( $data->{error} && ( $data->{error} eq 'too_much_owing' or $data->{error} eq 'auto_too_much_owing' ) ) { >+ if ( $override_debt && C4::Context->preference('AllowFineOverrideRenewing') ) { >+ $data->{renew_okay} = 1; >+ $data->{error} = undef; >+ } >+} >+ > if ( $data->{renew_okay} || ( $seen && $data->{error} eq 'too_unseen' ) ) { > try { > $date_due = AddRenewal( >diff --git a/t/cypress/integration/Circulation/FineNoRenewals_spec.ts b/t/cypress/integration/Circulation/FineNoRenewals_spec.ts >index 7d28d2b7c15..9d30932e6f3 100644 >--- a/t/cypress/integration/Circulation/FineNoRenewals_spec.ts >+++ b/t/cypress/integration/Circulation/FineNoRenewals_spec.ts >@@ -59,9 +59,11 @@ describe("Circulation - FineNoRenewals and AllowFineOverrideRenewing", () => { > > // Should see error message about patron debt > cy.get(".dialog.alert").should("be.visible"); >- cy.get(".dialog.alert li").should( >+ cy.get(".dialog.alert").should("contain", "total debt of"); >+ cy.get(".dialog.alert").should("contain", "non-issuing charges"); >+ cy.get(".dialog.alert").should( > "contain", >- `The patron has a debt of` >+ "Renewals are blocked when non-issuing charges exceed" > ); > }); > >@@ -80,11 +82,8 @@ describe("Circulation - FineNoRenewals and AllowFineOverrideRenewing", () => { > > // Should see error message about patron debt > cy.get(".dialog.alert").should("be.visible"); >- >- cy.get(".dialog.alert li").should( >- "contain", >- `The patron has a debt of` >- ); >+ cy.get(".dialog.alert").should("contain", "total debt of"); >+ cy.get(".dialog.alert").should("contain", "non-issuing charges"); > > // Should see override button > cy.get('.dialog.alert form button[type="submit"].approve').should( >@@ -111,9 +110,11 @@ describe("Circulation - FineNoRenewals and AllowFineOverrideRenewing", () => { > > // Should see error message about patron debt > cy.get(".dialog.alert").should("be.visible"); >- cy.get(".dialog.alert li").should( >+ cy.get(".dialog.alert").should("contain", "total debt of"); >+ cy.get(".dialog.alert").should("contain", "non-issuing charges"); >+ cy.get(".dialog.alert").should( > "contain", >- `The patron has a debt of` >+ "Renewals are blocked when non-issuing charges exceed" > ); > > // Should NOT see override button >-- >2.51.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 23415
:
92039
|
92541
|
98442
|
98634
|
98996
|
98997
|
105893
|
105894
|
108392
|
109871
|
109872
|
109876
|
109880
|
116919
|
116920
|
116921
|
116922
|
118175
|
118176
|
118177
|
118178
|
118183
|
119300
|
119301
|
119302
|
119303
|
121472
|
139670
|
139671
|
139672
|
139673
|
139674
|
146415
|
148198
|
148199
|
148200
|
148201
|
148202
|
152776
|
152777
|
152778
|
152779
|
152780
|
152781
|
154595
|
154596
|
154597
|
154598
|
154599
|
154600
|
158302
|
158303
|
158304
|
158305
|
158306
|
158307
|
161964
|
161965
|
161966
|
161967
|
161968
|
161969
|
162171
|
162172
|
162173
|
162174
|
162175
|
162176
|
162177
|
162178
|
162179
|
162180
|
171620
|
171621
|
171622
|
171623
|
171983
|
171984
|
171985
|
171986
|
172906
|
172907
|
172908
|
172909
|
172910
|
185270
|
185271
|
185272
|
185273
|
185274
|
185275
|
186014
|
188331
|
188332
|
188333
|
188334
|
188335
|
188336
|
188337
|
188338
|
188339
|
188340
|
188341
|
188342
|
188708
|
188709
|
188710
|
188711
|
188712
|
188713
|
188714
|
188715
|
188716
|
188717
|
188718
|
188719
|
188720
|
188738
|
188739
|
188740
|
188741
|
188742
|
188743
|
188744
|
188745
|
188746
|
188747
|
188748
|
188749
| 188750 |
188751