Bugzilla – Attachment 185361 Details for
Bug 37344
Patrons with cancelled discharge are seen as discharged when suspended due to overdue
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 37344: Add a real solution for discharge cancellation
Bug-37344-Add-a-real-solution-for-discharge-cancel.patch (text/plain), 16.92 KB, created by
Baptiste Wojtkowski (bwoj)
on 2025-08-13 12:00:50 UTC
(
hide
)
Description:
Bug 37344: Add a real solution for discharge cancellation
Filename:
MIME Type:
Creator:
Baptiste Wojtkowski (bwoj)
Created:
2025-08-13 12:00:50 UTC
Size:
16.92 KB
patch
obsolete
>From fcd6815a8882002a6ebb55a0bcc7332e575c5e2d Mon Sep 17 00:00:00 2001 >From: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com> >Date: Tue, 18 Mar 2025 14:52:35 +0100 >Subject: [PATCH] Bug 37344: Add a real solution for discharge cancellation > >Note: if you experience issues with the behaviour of the "generate >discharge" button while testing, you might want to have a look at >BZ39369 > >TEST PLAN: >Note: you will have to reset your db in the middle of the plan >0 - Set systempreference "useDischarge" to allow >1 - Add a discharge on Henry Acevedo (HA) >2 - Log in on the OPAC as HA >3 - Notice you are suspended due to discharge >4 - Remove the suspension due to the discharge >5 - Add another manual suspension to HA >6 - Log in on the OPAC as HA >7 - Notice you are still suspended due to the discharge >8 - Reset your db, Apply patch, updatedb, update db schema >9 - Add a discharge on HA, notice there are new columns >10 - Login to HA on the OPAC >11 - Notice you are suspended due to the discharge >12 - Click on the "Delete" button in the discharge > panel on the intranet >13 - On the modal select "Patron asked a discharge by mistake" and submit >14 - Notice the new columns are filled (cancellation reason should be PATRON_MISTAKE >15 - Add a new manual suspension to HA >16 - Login again as HA and notice your are not seen as discharged > anymore >17 - Run `prove t/db_dependent/Patron/Borrower_Discharge.t` > >Note for the QA - I'll provide tests at the end of the week >--- > Koha/Patron/Discharge.pm | 58 +++++++++++++-- > .../data/mysql/atomicupdate/bug_37344.pl | 43 ++++++++++++ > installer/data/mysql/en/optional/auth_val.yml | 10 +++ > installer/data/mysql/kohastructure.sql | 2 + > .../data/mysql/mandatory/auth_val_cat.sql | 6 ++ > .../en/modules/admin/authorised_values.tt | 2 + > .../prog/en/modules/members/discharge.tt | 70 ++++++++++++++++++- > members/discharge.pl | 18 ++++- > opac/opac-reserve.pl | 5 ++ > 9 files changed, 207 insertions(+), 7 deletions(-) > create mode 100755 installer/data/mysql/atomicupdate/bug_37344.pl > >diff --git a/Koha/Patron/Discharge.pm b/Koha/Patron/Discharge.pm >index 1d4b41e84..6f827387d 100644 >--- a/Koha/Patron/Discharge.pm >+++ b/Koha/Patron/Discharge.pm >@@ -95,10 +95,10 @@ sub is_discharged { > return unless $params->{borrowernumber}; > my $borrowernumber = $params->{borrowernumber}; > >- my $restricted = Koha::Patrons->find($borrowernumber)->is_debarred; >- my @validated = get_validated( { borrowernumber => $borrowernumber } ); >+ my $restricted = Koha::Patrons->find( $borrowernumber )->is_debarred; >+ my @validated = get_validated({borrowernumber => $borrowernumber}); > >- if ( $restricted && @validated ) { >+ if ($restricted && @validated) { > return 1; > } else { > return 0; >@@ -113,6 +113,18 @@ Place a discharge request on a given borrower after checking the borrower has th > > =cut > >+sub is_discharged { >+ my ($params) = @_; >+ my $discharge = Koha::Database->new->schema->resultset('Discharge')->search( >+ { >+ borrower => $params->{borrowernumber}, >+ validated => { "not" => undef }, >+ cancelled => undef, >+ } >+ ); >+ return $discharge->count > 0; >+} >+ > sub request { > my ($params) = @_; > my $borrowernumber = $params->{borrowernumber}; >@@ -137,6 +149,38 @@ Place a discharge request on a given borrower, if a discharge was requested, upd > > =cut > >+sub is_cancelled { >+ my ($params) = @_; >+ my $discharge = Koha::Database->new->schema->resultset('Discharge')->search( >+ { >+ discharge_id => $params->{discharge_id}, >+ cancelled => { "not" => undef }, >+ } >+ ); >+ return $discharge->count > 0; >+} >+ >+sub cancel { >+ my ($params) = @_; >+ my $discharge = Koha::Database->new->schema->resultset('Discharge')->search( >+ { >+ discharge_id => $params->{discharge_id}, >+ } >+ ); >+ $discharge->update( >+ { >+ cancelled => dt_from_string, >+ cancellation_reason => $params->{cancellation_reason} >+ } >+ ); >+ Koha::Patron::Debarments::DelUniqueDebarment( >+ { >+ borrowernumber => $params->{borrowernumber}, >+ type => "DISCHARGE", >+ } >+ ); >+} >+ > sub discharge { > my ($params) = @_; > my $borrowernumber = $params->{borrowernumber}; >@@ -163,7 +207,13 @@ sub discharge { > my $rs = Koha::Database->new->schema->resultset('Discharge'); > my $discharge = $rs->search( { borrower => $borrowernumber }, { order_by => { -desc => 'needed' }, rows => 1 } ); > if ( $discharge->count > 0 ) { >- $discharge->update( { validated => dt_from_string } ); >+ $discharge->update( >+ { >+ validated => dt_from_string, >+ cancelled => undef, >+ cancellation_reason => undef >+ } >+ ); > } else { > $rs->create( > { >diff --git a/installer/data/mysql/atomicupdate/bug_37344.pl b/installer/data/mysql/atomicupdate/bug_37344.pl >new file mode 100755 >index 000000000..f818e9886 >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/bug_37344.pl >@@ -0,0 +1,43 @@ >+use Modern::Perl; >+use Koha::Installer::Output qw(say_warning say_failure say_success say_info); >+ >+return { >+ bug_number => "37344", >+ description => "Add columns cancellation_reason and cancelled to discharge", >+ up => sub { >+ my ($args) = @_; >+ my ( $dbh, $out ) = @$args{qw(dbh out)}; >+ >+ # Do you stuffs here >+ unless ( column_exists( 'discharges', 'cancellation_reason' ) ) { >+ $dbh->do( >+ q{ >+ ALTER TABLE discharges >+ ADD COLUMN cancelled timestamp NULL default NULL, >+ ADD COLUMN cancellation_reason VARCHAR(80) NULL default NULL ; >+ } >+ ); >+ >+ $dbh->do( >+ q{ >+ INSERT IGNORE INTO authorised_value_categories (category_name) VALUES >+ ('DISCHARGE_CANCELLATION') >+ } >+ ); >+ $dbh->do( >+ q{ >+ INSERT IGNORE INTO authorised_values (category, authorised_value, lib) VALUES >+ ('DISCHARGE_CANCELLATION','PATRON_MISTAKE', 'The patron asked for a discharge by mistake.'), >+ ('DISCHARGE_CANCELLATION','PATRON_STILL_NEEDS_ACCOUNT','A discharge was required, however the patron still needs to use their account.') >+ } >+ ); >+ >+ # Print useful stuff here >+ # tables >+ say $out "Added column 'discharges.cancelled'"; >+ say $out "Added column 'discharges.cancellation_reason'"; >+ say $out "Added authorized value category DISCHARGE_CANCELLATION"; >+ say $out "Added authorized values PATRON_MISTAKE and PATRON_STILL_NEEDS_ACCOUNT"; >+ } >+ }, >+}; >diff --git a/installer/data/mysql/en/optional/auth_val.yml b/installer/data/mysql/en/optional/auth_val.yml >index 62197838f..efb6aa97f 100644 >--- a/installer/data/mysql/en/optional/auth_val.yml >+++ b/installer/data/mysql/en/optional/auth_val.yml >@@ -333,3 +333,13 @@ tables: > - category: "AR_CANCELLATION" > authorised_value: "OPAC" > lib: "Cancelled from the OPAC user page" >+ >+ >+ # Disharge cancellations >+ - category: "DISCHARGE_CANCELLATION" >+ authorised_value: "PATRON_MISTAKE" >+ lib: "Patron asked a discharge by mistake" >+ >+ - category: "DISCHARGE_CANCELLATION" >+ authorised_value: "PATRON_STILL_NEEDS_ACCOUNT" >+ lib: "Administration required a discharge however the borrower still needs to use their account" >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index e39e9350f..a678fee86 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -2873,6 +2873,8 @@ CREATE TABLE `discharges` ( > `borrower` int(11) DEFAULT NULL, > `needed` timestamp NULL DEFAULT NULL, > `validated` timestamp NULL DEFAULT NULL, >+ `cancelled` timestamp DEFAULT NULL, >+ `cancellation_reason`varchar(80) DEFAULT NULL COMMENT 'authorised value CANCELLATION_REASON', > PRIMARY KEY (`discharge_id`), > KEY `borrower_discharges_ibfk1` (`borrower`), > CONSTRAINT `borrower_discharges_ibfk1` FOREIGN KEY (`borrower`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE CASCADE ON UPDATE CASCADE >diff --git a/installer/data/mysql/mandatory/auth_val_cat.sql b/installer/data/mysql/mandatory/auth_val_cat.sql >index c1428e4a3..5d2e1550a 100644 >--- a/installer/data/mysql/mandatory/auth_val_cat.sql >+++ b/installer/data/mysql/mandatory/auth_val_cat.sql >@@ -106,3 +106,9 @@ VALUES > INSERT IGNORE INTO authorised_value_categories (category_name, is_system) > VALUES > ('BOOKING_CANCELLATION', 1); >+ >+ >+-- For discharges >+INSERT IGNORE INTO authorised_value_categories (category_name, is_system) >+VALUES >+ ('DISCHARGE_CANCELLATION', 1); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authorised_values.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authorised_values.tt >index 05384025b..6f89cb6fd 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authorised_values.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authorised_values.tt >@@ -516,6 +516,8 @@ > <p>ILL request status aliases used by the interlibrary loans module</p> > [% CASE 'AR_CANCELLATION' %] > <p>Reasons why an article request might have been cancelled</p> >+ [% CASE 'DISCHARGE_CANCELLATION' %] >+ <p>Reasons for cancelling a discharge</p> > [% CASE 'HSBND_FREQ' %] > <p>Frequencies used by the housebound module. They are displayed on the housebound tab in the patron account in staff.</p> > [% CASE 'ITEMTYPECAT' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt >index 9d9d1497c..39f96fda0 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt >@@ -86,6 +86,9 @@ > <tr> > <th>Requested</th> > <th>Validated</th> >+ <th>Cancelled</th> >+ <th>Reason cancelled</th> >+ <th>Cancel</th> > </tr> > </thead> > <tbody> >@@ -93,7 +96,25 @@ > <tr> > <td>[% d.needed | $KohaDates with_hours = 1 %]</td> > <td>[% d.validated | $KohaDates with_hours = 1 %]</td> >- </tr> >+ <td>[% d.cancelled | $KohaDates with_hours = 1 %]</td> >+ <td>[% d.cancellation_reason | html %]</td> >+ <td> >+ [% IF d.cancelled %] >+ <i> Cancelled </i> >+ [% ELSE %] >+ <a >+ class="cancel-discharge delete btn btn-default btn-xs" >+ data-borrowernumber="[% patron.borrowernumber | html %]" >+ data-bs-target="#cancelDischargeModal" >+ data-bs-toggle="modal" >+ data-discharge_id="[% d.discharge_id | html %]" >+ > >+ <i class="fa fa-trash-can"></i> >+ Cancel >+ </a> >+ [% END %] >+ </td></tr >+ > > [% END %] > </tbody> > </table> >@@ -101,9 +122,56 @@ > [% END %] > [% END %] > >+<div class="modal fade" id="cancelDischargeModal" tabindex="-1" aria-labelledby="cancelDischargeModal" aria-hidden="true"> >+ <div class="modal-dialog modal-lg"> >+ <div class="modal-content"> >+ <div class="modal-header"> >+ <h1 class="modal-title" id="cancelModalLabel">Confirm cancellation</h1> >+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> >+ </div> >+ <form id="cancel_modal_form" method="post" action="discharge.pl"> >+ <div class="modal-body"> >+ [% INCLUDE 'csrf-token.inc' %] >+ <input name="op" type="hidden" value="cud-cancel-discharge" /> >+ <div id="cancel_discharge_alert" class="alert alert-danger" style="display:none;"></div> >+ <fieldset class="action"> >+ <p>Are you sure you want to cancel this discharge? The patron will be able to check out items again.</p> >+ [% SET discharge_cancellation_reasons = AuthorisedValues.GetAuthValueDropbox('DISCHARGE_CANCELLATION') %] >+ [% IF discharge_cancellation_reasons.count %] >+ <label for="cancellation-reason">Cancellation reason: </label> >+ <select class="cancellation-reason" name="cancellation-reason" id="modal-cancellation-reason"> >+ [% FOREACH reason IN discharge_cancellation_reasons %] >+ <option value="[% reason.authorised_value | html %]">[% reason.lib | html %]</option> >+ [% END %] >+ </select> >+ [% ELSE %] >+ <div class="alert alert-warning audio-alert-warning"> You must define at least one authorized value for the category DISCHARGE_CANCELLATION </div> >+ [% END %] >+ </fieldset> >+ </div> >+ <div class="modal-footer"> >+ <input id="cancelModalConfirmBtn" type="submit" class="btn btn-danger" value="Confirm cancellation" /> >+ <button type="button" class="btn btn-default" data-bs-dismiss="modal">Cancel</button> >+ </div> >+ </form> >+ </div> >+ </div> >+</div> >+ > [% MACRO jsinclude BLOCK %] > [% INCLUDE 'str/members-menu.inc' %] > [% Asset.js("js/members-menu.js") | $raw %] >+ <script> >+ $(".cancel-discharge").on("click", function (e) { >+ e.preventDefault; >+ cancel_link = $(this); >+ let discharge_id = cancel_link.data("discharge_id"); >+ let borrowernumber = cancel_link.data("borrowernumber"); >+ $("#cancel_modal_form").append('<input type="hidden" name="discharge_id" value="' + discharge_id + '">'); >+ $("#cancel_modal_form").append('<input type="hidden" name="borrowernumber" value="' + borrowernumber + '">'); >+ return false; >+ }); >+ </script> > [% END %] > > [% INCLUDE 'intranet-bottom.inc' %] >diff --git a/members/discharge.pl b/members/discharge.pl >index b4dda3a13..1222126cc 100755 >--- a/members/discharge.pl >+++ b/members/discharge.pl >@@ -50,8 +50,10 @@ my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user( > } > ); > >-my $op = $input->param('op') // q{}; >-my $borrowernumber = $input->param('borrowernumber'); >+my $op = $input->param('op') // q{}; >+my $borrowernumber = $input->param('borrowernumber'); >+my $discharge_id = $input->param('discharge_id'); >+my $cancellation_reason = $input->param('cancellation-reason'); > > unless ( C4::Context->preference('useDischarge') ) { > print $input->redirect("/cgi-bin/koha/circ/circulation.pl?borrowernumber=$borrowernumber&nopermission=1"); >@@ -68,6 +70,18 @@ output_and_exit_if_error( > my ( $can_be_discharged, $discharge_problems ) = > Koha::Patron::Discharge::can_be_discharged( { borrowernumber => $borrowernumber } ); > >+if ( $op eq "cud-cancel-discharge" ) { >+ unless ( Koha::Patron::Discharge::is_cancelled( { discharge_id => $discharge_id } ) ) { >+ Koha::Patron::Discharge::cancel( >+ { >+ discharge_id => $discharge_id, >+ borrowernumber => $borrowernumber, >+ cancellation_reason => $cancellation_reason, >+ } >+ ); >+ } >+} >+ > # Generating discharge if needed > if ( $op eq 'cud-discharge' && $input->param('discharge') and $can_be_discharged ) { > my $is_discharged = Koha::Patron::Discharge::is_discharged( >diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl >index 6db213f29..7d2cedfe9 100755 >--- a/opac/opac-reserve.pl >+++ b/opac/opac-reserve.pl >@@ -118,6 +118,11 @@ my $can_place_holds = $patron->can_place_holds( { no_short_circuit => 1 } ); > > if ( !$can_place_holds ) { > >+ if ( Koha::Patron::Dicharge::is_discharged( { borrowernumber => $patron->borrowernumber } ) ) { >+ $template->param( >+ is_discharged => 1, >+ ); >+ } > $template->param( message => 1 ); > > my $messages = $can_place_holds->messages(); >-- >2.30.2
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 37344
:
179461
|
179489
|
179763
|
179826
|
179827
|
179828
|
181709
|
182647
|
182648
|
182649
|
182650
|
182747
|
182748
|
182749
|
182750
|
182751
|
182907
|
184427
|
184428
|
184429
|
184430
|
184431
| 185361 |
185362
|
185363
|
185364