Bugzilla – Attachment 125167 Details for
Bug 27947
Add default cancellation reasons to article requests
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 27947: Add cancellation reason to article request
Bug-27947-Add-cancellation-reason-to-article-reque.patch (text/plain), 34.84 KB, created by
Tomás Cohen Arazi (tcohen)
on 2021-09-22 19:36:13 UTC
(
hide
)
Description:
Bug 27947: Add cancellation reason to article request
Filename:
MIME Type:
Creator:
Tomás Cohen Arazi (tcohen)
Created:
2021-09-22 19:36:13 UTC
Size:
34.84 KB
patch
obsolete
>From 61e83cdf230b3ee9a8b7e9affb82995962e5a1bb Mon Sep 17 00:00:00 2001 >From: Agustin Moyano <agustinmoyano@theke.io> >Date: Thu, 19 Aug 2021 23:51:38 -0300 >Subject: [PATCH] Bug 27947: Add cancellation reason to article request > >This bug adds a cancellation reason authorised values to article requests > >To test: >1. apply this patch >2. updatedatabase >3. in staff interface go to /cgi-bin/koha/admin/authorised_values.pl >CHECK => AR_CANCELLATION category should appears >4. place several article requests >5. in staff interface go to /cgi-bin/koha/circ/article-requests.pl >6. select multiple requests, or just one and cancel them >SUCCESS => a modal pops up offering to select a cancellation reason >CHECK => message_queue table has messages with cancellation reason included >7. repeat steps 4 to 6 but for /cgi-bin/koha/circ/request-article.pl >8. cancelling article requests from opac interface should work just as before > >Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> >Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io> >Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> >--- > Koha/ArticleRequest.pm | 18 +++- > Koha/Exceptions/ArticleRequests.pm | 17 ++++ > Koha/REST/V1/ArticleRequests.pm | 76 ++++++++++++++ > Koha/REST/V1/Patrons.pm | 49 +++++++++ > api/v1/swagger/parameters.json | 9 ++ > .../swagger/parameters/article_request.json | 23 +++++ > api/v1/swagger/paths.json | 8 +- > api/v1/swagger/paths/article_requests.json | 70 +++++++++++++ > api/v1/swagger/paths/public_patrons.json | 70 +++++++++++++ > .../en/modules/admin/authorised_values.tt | 2 + > .../prog/en/modules/circ/article-requests.tt | 99 ++++++++++++++----- > .../prog/en/modules/circ/request-article.tt | 88 +++++++++++++---- > .../bootstrap/en/modules/opac-user.tt | 45 ++++++--- > 13 files changed, 516 insertions(+), 58 deletions(-) > create mode 100644 Koha/Exceptions/ArticleRequests.pm > create mode 100644 Koha/REST/V1/ArticleRequests.pm > create mode 100644 api/v1/swagger/parameters/article_request.json > create mode 100644 api/v1/swagger/paths/article_requests.json > >diff --git a/Koha/ArticleRequest.pm b/Koha/ArticleRequest.pm >index d3554132e9..21b3751ac5 100644 >--- a/Koha/ArticleRequest.pm >+++ b/Koha/ArticleRequest.pm >@@ -102,9 +102,10 @@ sub complete { > =cut > > sub cancel { >- my ( $self, $notes ) = @_; >+ my ( $self, $cancellation_reason, $notes ) = @_; > > $self->status(Koha::ArticleRequest::Status::Canceled); >+ $self->cancellation_reason($cancellation_reason) if $cancellation_reason; > $self->notes($notes) if $notes; > $self->store(); > $self->notify(); >@@ -119,6 +120,16 @@ sub notify { > my ($self) = @_; > > my $status = $self->status; >+ my $reason = $self->notes; >+ if ( !defined $reason && $self->cancellation_reason ) { >+ my $av = Koha::AuthorisedValues->search( >+ { >+ category => 'AR_CANCELLATION', >+ authorised_value => $self->cancellation_reason >+ } >+ )->next; >+ $reason = $av->lib_opac ? $av->lib_opac : $av->lib if $av; >+ } > > require C4::Letters; > if ( >@@ -135,6 +146,9 @@ sub notify { > items => $self->itemnumber, > branches => $self->branchcode, > }, >+ substitute => { >+ reason => $reason, >+ }, > ) > ) > { >@@ -144,7 +158,7 @@ sub notify { > borrowernumber => $self->borrowernumber, > message_transport_type => 'email', > } >- ) or warn "can't enqueue letter ". $letter->{code}; >+ ) or warn "can't enqueue letter " . $letter->{code}; > } > } > >diff --git a/Koha/Exceptions/ArticleRequests.pm b/Koha/Exceptions/ArticleRequests.pm >new file mode 100644 >index 0000000000..669529ca47 >--- /dev/null >+++ b/Koha/Exceptions/ArticleRequests.pm >@@ -0,0 +1,17 @@ >+package Koha::Exceptions::ArticleRequests; >+ >+use Modern::Perl; >+ >+use Exception::Class ( >+ >+ 'Koha::Exceptions::ArticleRequests' => { >+ description => 'Something went wrong!', >+ }, >+ 'Koha::Exceptions::ArticleRequests::FailedCancel' => { >+ isa => 'Koha::Exceptions::ArticleRequests', >+ description => 'Failed to cancel article request' >+ } >+ >+); >+ >+1; >\ No newline at end of file >diff --git a/Koha/REST/V1/ArticleRequests.pm b/Koha/REST/V1/ArticleRequests.pm >new file mode 100644 >index 0000000000..a026b8887c >--- /dev/null >+++ b/Koha/REST/V1/ArticleRequests.pm >@@ -0,0 +1,76 @@ >+package Koha::REST::V1::ArticleRequests; >+ >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Mojo::Base 'Mojolicious::Controller'; >+ >+use Koha::Database; >+use Koha::ArticleRequests; >+ >+use Scalar::Util qw( blessed ); >+use Try::Tiny qw( catch try ); >+ >+=head1 NAME >+ >+Koha::REST::V1::ArticleRequests >+ >+=head1 API >+ >+=head2 Methods >+ >+=head3 cancel >+ >+Controller function that handles cancelling a Koha::ArticleRequest object >+ >+=cut >+ >+sub cancel { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $ar = Koha::ArticleRequests->find( $c->validation->param('ar_id') ); >+ >+ unless ( $ar ) { >+ return $c->render( >+ status => 404, >+ openapi => { error => "Article request not found" } >+ ); >+ } >+ >+ my $reason = $c->validation->param('cancellation_reason'); >+ my $notes = $c->validation->param('notes'); >+ >+ return try { >+ >+ $ar->cancel($reason, $notes); >+ return $c->render( >+ status => 204, >+ openapi => q{} >+ ); >+ } catch { >+ if ( blessed $_ && $_->isa('Koha::Exceptions::ArticleRequests::FailedCancel') ) { >+ return $c->render( >+ status => 403, >+ openapi => { error => "Article request cannot be canceled" } >+ ); >+ } >+ >+ $c->unhandled_exception($_); >+ }; >+} >+ >+1; >\ No newline at end of file >diff --git a/Koha/REST/V1/Patrons.pm b/Koha/REST/V1/Patrons.pm >index 80b64ee963..6790e9f6b8 100644 >--- a/Koha/REST/V1/Patrons.pm >+++ b/Koha/REST/V1/Patrons.pm >@@ -419,4 +419,53 @@ sub guarantors_can_see_checkouts { > }; > } > >+=head3 cancel_article_request >+ >+Controller function that handles cancelling a patron's Koha::ArticleRequest object >+ >+=cut >+ >+sub cancel_article_request { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $patron = Koha::Patrons->find( $c->validation->param('patron_id') ); >+ >+ unless ( $patron ) { >+ return $c->render( >+ status => 404, >+ openapi => { error => "Patron not found" } >+ ); >+ } >+ >+ my $ar = $patron->article_requests->find( $c->validation->param('ar_id') ); >+ >+ unless ( $ar ) { >+ return $c->render( >+ status => 404, >+ openapi => { error => "Article request not found" } >+ ); >+ } >+ >+ my $reason = $c->validation->param('cancellation_reason'); >+ my $notes = $c->validation->param('notes'); >+ >+ return try { >+ >+ $ar->cancel($reason, $notes); >+ return $c->render( >+ status => 204, >+ openapi => q{} >+ ); >+ } catch { >+ if ( blessed $_ && $_->isa('Koha::Exceptions::ArticleRequests::FailedCancel') ) { >+ return $c->render( >+ status => 403, >+ openapi => { error => "Article request cannot be canceled" } >+ ); >+ } >+ >+ $c->unhandled_exception($_); >+ }; >+} >+ > 1; >diff --git a/api/v1/swagger/parameters.json b/api/v1/swagger/parameters.json >index 95464e1461..120b8371f1 100644 >--- a/api/v1/swagger/parameters.json >+++ b/api/v1/swagger/parameters.json >@@ -56,6 +56,15 @@ > "cashup_id_pp": { > "$ref": "parameters/cashup.json#/cashup_id_pp" > }, >+ "ar_id_pp": { >+ "$ref": "parameters/article_request.json#/ar_id_pp" >+ }, >+ "ar_reason_qp": { >+ "$ref": "parameters/article_request.json#/ar_reason_qp" >+ }, >+ "ar_notes_qp": { >+ "$ref": "parameters/article_request.json#/ar_notes_qp" >+ }, > "match": { > "name": "_match", > "in": "query", >diff --git a/api/v1/swagger/parameters/article_request.json b/api/v1/swagger/parameters/article_request.json >new file mode 100644 >index 0000000000..5644936af5 >--- /dev/null >+++ b/api/v1/swagger/parameters/article_request.json >@@ -0,0 +1,23 @@ >+{ >+ "ar_id_pp": { >+ "name": "ar_id", >+ "in": "path", >+ "description": "Article request identifier", >+ "required": true, >+ "type": "integer" >+ }, >+ "ar_reason_qp": { >+ "name": "cancellation_reason", >+ "in": "query", >+ "description": "Article request cancellation reason", >+ "required": false, >+ "type": "string" >+ }, >+ "ar_notes_qp": { >+ "name": "notes", >+ "in": "query", >+ "description": "Article request custom cancellation reason", >+ "required": false, >+ "type": "string" >+ } >+} >diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json >index 23f420cc05..1e96c452cb 100644 >--- a/api/v1/swagger/paths.json >+++ b/api/v1/swagger/paths.json >@@ -17,6 +17,9 @@ > "/acquisitions/funds": { > "$ref": "paths/acquisitions_funds.json#/~1acquisitions~1funds" > }, >+ "/article_requests/{ar_id}": { >+ "$ref": "paths/article_requests.json#/~1article_requests~1{ar_id}" >+ }, > "/biblios/{biblio_id}": { > "$ref": "paths/biblios.json#/~1biblios~1{biblio_id}" > }, >@@ -134,7 +137,7 @@ > "/patrons/{patron_id}/extended_attributes/{extended_attribute_id}": { > "$ref": "paths/patrons_extended_attributes.json#/~1patrons~1{patron_id}~1extended_attributes~1{extended_attribute_id}" > }, >- "/patrons/{patron_id}/holds": { >+ "/patrons/{patron_id}/holds": { > "$ref": "paths/patrons_holds.json#/~1patrons~1{patron_id}~1holds" > }, > "/patrons/{patron_id}/password": { >@@ -170,6 +173,9 @@ > "/public/patrons/{patron_id}/guarantors/can_see_checkouts": { > "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1guarantors~1can_see_checkouts" > }, >+ "/public/patrons/{patron_id}/article_requests/{ar_id}": { >+ "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1article_requests~1{ar_id}" >+ }, > "/quotes": { > "$ref": "paths/quotes.json#/~1quotes" > }, >diff --git a/api/v1/swagger/paths/article_requests.json b/api/v1/swagger/paths/article_requests.json >new file mode 100644 >index 0000000000..22ac503d63 >--- /dev/null >+++ b/api/v1/swagger/paths/article_requests.json >@@ -0,0 +1,70 @@ >+{ >+ "/article_requests/{ar_id}": { >+ "delete": { >+ "x-mojo-to": "ArticleRequests#cancel", >+ "operationId": "cancelArticleRequest", >+ "tags": [ >+ "article_requests" >+ ], >+ "summary": "Cancel article requests", >+ "parameters": [ >+ { >+ "$ref": "../parameters.json#/ar_id_pp" >+ }, >+ { >+ "$ref": "../parameters.json#/ar_reason_qp" >+ }, >+ { >+ "$ref": "../parameters.json#/ar_notes_qp" >+ } >+ ], >+ "produces": ["application/json"], >+ "responses": { >+ "204": { >+ "description": "Article request canceled" >+ }, >+ "400": { >+ "description": "Bad request", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "401": { >+ "description": "Authentication required", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Patron not found", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "500": { >+ "description": "Internal server error", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "503": { >+ "description": "Under maintenance", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ } >+ }, >+ "x-koha-authorization": { >+ "permissions": { >+ "reserveforothers": "1" >+ } >+ } >+ } >+ } >+} >\ No newline at end of file >diff --git a/api/v1/swagger/paths/public_patrons.json b/api/v1/swagger/paths/public_patrons.json >index 90d6cfe4c4..af06a0c7c7 100644 >--- a/api/v1/swagger/paths/public_patrons.json >+++ b/api/v1/swagger/paths/public_patrons.json >@@ -242,5 +242,75 @@ > "allow-owner": true > } > } >+ }, >+ "/public/patrons/{patron_id}/article_requests/{ar_id}": { >+ "delete": { >+ "x-mojo-to": "Patrons#cancel_article_request", >+ "operationId": "cancelPatronArticleRequest", >+ "tags": [ >+ "patrons", >+ "article_requests" >+ ], >+ "summary": "Cancel patron's article requests", >+ "parameters": [ >+ { >+ "$ref": "../parameters.json#/patron_id_pp" >+ }, >+ { >+ "$ref": "../parameters.json#/ar_id_pp" >+ }, >+ { >+ "$ref": "../parameters.json#/ar_reason_qp" >+ }, >+ { >+ "$ref": "../parameters.json#/ar_notes_qp" >+ } >+ ], >+ "produces": ["application/json"], >+ "responses": { >+ "204": { >+ "description": "Patron's article request canceled" >+ }, >+ "400": { >+ "description": "Bad request", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "401": { >+ "description": "Authentication required", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Patron not found", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "500": { >+ "description": "Internal server error", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "503": { >+ "description": "Under maintenance", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ } >+ }, >+ "x-koha-authorization": { >+ "allow-owner": true >+ } >+ } > } > } >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 b8e1f82b71..e6cb47ce5c 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 >@@ -424,6 +424,8 @@ Authorized values › Administration › Koha > <p>General holdings: type of unit designator</p> > [% CASE 'HOLD_CANCELLATION' %] > <p>Reasons why a hold might have been cancelled</p> >+ [% CASE 'AR_CANCELLATION' %] >+ <p>Reasons why an article request might have been cancelled</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/circ/article-requests.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/article-requests.tt >index f93baf6d5d..0e4301e860 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/article-requests.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/article-requests.tt >@@ -42,7 +42,7 @@ > Complete request > </a> > >- <a class="ar-cancel-request" href="#" onclick="HandleMulti( Cancel, [% id_arg | html %], $(this) ); return false;"> >+ <a class="ar-cancel-request" href="#" onclick="Cancel( [% id_arg | html %], $(this) ); return false;"> > <i class="fa fa-minus-circle"></i> > Cancel request > </a> >@@ -82,6 +82,44 @@ > </div> > </div> > [% END %] >+[% BLOCK cancel_modal %] >+ <div id="cancelModal" class="modal" tabindex="-1" role="dialog" aria-hidden="true"> >+ <div class="modal-dialog" role="document"> >+ <div class="modal-content"> >+ <div class="modal-header"> >+ <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">Ã</button> >+ <h3>Confirm deletion</h3> >+ </div> >+ >+ <div class="modal-body"> >+ <p>Are you sure you want to cancel this article request?</p> >+ >+ <fieldset class="action"> >+ [% SET ar_cancellation = AuthorisedValues.GetAuthValueDropbox('AR_CANCELLATION') %] >+ [% IF ar_cancellation %] >+ <label for="cancellation-reason" class="col-sm-4">Cancellation reason: </label> >+ <select class="cancellation-reason col-sm-8" name="cancellation-reason" id="modal-cancellation-reason"> >+ <option value="" selected>Other reasons</option> >+ [% FOREACH reason IN ar_cancellation %] >+ <option value="[% reason.authorised_value | html %]">[% reason.lib | html %]</option> >+ [% END %] >+ </select> >+ [% END %] >+ </fieldset> >+ <fieldset class="action"> >+ <div class="hint col-sm-offset-4">Enter reason</div> >+ <input type="text" class="notes col-sm-offset-4 col-sm-8" name="notes" id="modal-notes"/> >+ </fieldset> >+ </div> >+ >+ <div class="modal-footer"> >+ <button id="cancelModalConfirmBtn" type="button" class="btn btn-danger" data-dismiss="modal">Confirm cancellation</button> >+ <a href="#" data-dismiss="modal">Cancel</a> >+ </div> >+ </div> >+ </div> >+ </div> >+[% END %] > > <body id="circ_article-requests" class="circ"> > [% INCLUDE 'header.inc' %] >@@ -465,6 +503,7 @@ > </div> > </div> > </div> >+ [% PROCESS cancel_modal %] > > [% MACRO jsinclude BLOCK %] > [% INCLUDE 'datatables.inc' %] >@@ -573,30 +612,44 @@ > window.open(link, 'popup', 'width=600,height=400,resizable=1,toolbar=0,scrollbars=1,top'); > } > >+ $('#modal-cancellation-reason').on('change', function(e) { >+ let reason = $(this).val(); >+ $('#modal-notes').attr('disabled', !!reason); >+ }) >+ >+ // Confirm cancellation of article requests >+ let cancel_id; >+ let cancel_a; >+ $("#cancelModalConfirmBtn").on("click",function(e) { >+ let reason = $("#modal-cancellation-reason").val(); >+ let notes = $("#modal-notes").val(); >+ let query = '?'+(reason?'cancellation_reason='+reason:'notes='+notes) >+ >+ HandleMulti(function(id, a) { >+ var table_row = a.closest('tr'); >+ table_row.find('.ar-process-request').remove(); >+ table_row.find('input[type="checkbox"]').prop('checked', false); >+ >+ >+ a.closest('td').prepend('<img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif"/>').find('div.dropdown').hide(); >+ >+ $.ajax({ >+ type: "DELETE", >+ url: '/api/v1/article_requests/'+id+query, >+ success: function( data ) { >+ active_datatable.row( a.closest('tr') ).remove().draw(); >+ UpdateTabCounts(); >+ activateBatchActions( active_tab ); >+ } >+ }); >+ }, cancel_id, cancel_a) >+ }); >+ > function Cancel( id, a ) { >- // last_cancel_reason: undefined means 'prompt for new reason' >- // a null value indicates that prompt was cancelled >- if( last_cancel_reason === undefined ) last_cancel_reason = prompt(_("Please specify the reason for cancelling selected item(s):")); >- if ( last_cancel_reason === null ) { >- return; >- } >+ cancel_id = id; >+ cancel_a = a; > >- a.closest('td').prepend('<img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif"/>').find('div.dropdown').hide(); >- $.ajax({ >- type: "POST", >- url: '/cgi-bin/koha/svc/article_request', >- data: { >- action: 'cancel', >- id: id, >- notes: last_cancel_reason >- }, >- success: function( data ) { >- active_datatable.row( a.closest('tr') ).remove().draw(); >- UpdateTabCounts(); >- activateBatchActions( active_tab ); >- }, >- dataType: 'json' >- }); >+ $('#cancelModal').modal(); > } > > function SetPending( id, a ) { >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/request-article.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/request-article.tt >index f26a10318d..d47549db90 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/request-article.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/request-article.tt >@@ -3,6 +3,7 @@ > [% USE KohaDates %] > [% USE Branches %] > [% USE ItemTypes %] >+[% USE AuthorisedValues %] > [% SET footerjs = 1 %] > [% SET article_requests_view = 1 %] > [% SET biblionumber = biblio.biblionumber %] >@@ -11,6 +12,45 @@ > [% INCLUDE 'doc-head-close.inc' %] > </head> > >+[% BLOCK cancel_modal %] >+ <div id="cancelModal" class="modal" tabindex="-1" role="dialog" aria-hidden="true"> >+ <div class="modal-dialog" role="document"> >+ <div class="modal-content"> >+ <div class="modal-header"> >+ <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">Ã</button> >+ <h3>Confirm deletion</h3> >+ </div> >+ >+ <div class="modal-body"> >+ <p>Are you sure you want to cancel this article request?</p> >+ >+ <fieldset class="action"> >+ [% SET ar_cancellation = AuthorisedValues.GetAuthValueDropbox('AR_CANCELLATION') %] >+ [% IF ar_cancellation %] >+ <label for="cancellation-reason" class="col-sm-4">Cancellation reason: </label> >+ <select class="cancellation-reason col-sm-8" name="cancellation-reason" id="modal-cancellation-reason"> >+ <option value="" selected>Other reasons</option> >+ [% FOREACH reason IN ar_cancellation %] >+ <option value="[% reason.authorised_value | html %]">[% reason.lib | html %]</option> >+ [% END %] >+ </select> >+ [% END %] >+ </fieldset> >+ <fieldset class="action"> >+ <div class="hint col-sm-offset-4">Enter reason</div> >+ <input type="text" class="notes col-sm-offset-4 col-sm-8" name="notes" id="modal-notes"/> >+ </fieldset> >+ </div> >+ >+ <div class="modal-footer"> >+ <button id="cancelModalConfirmBtn" type="button" class="btn btn-danger" data-dismiss="modal">Confirm cancellation</button> >+ <a href="#" data-dismiss="modal">Cancel</a> >+ </div> >+ </div> >+ </div> >+ </div> >+[% END %] >+ > <body id="circ_request-article" class="circ"> > [% INCLUDE 'header.inc' %] > [% INCLUDE 'circ-search.inc' %] >@@ -317,6 +357,7 @@ > [% END %] > </table> > </fieldset> >+ [% PROCESS cancel_modal %] > [% END %] > > </main> >@@ -401,29 +442,34 @@ > } > }); > >- $(".ar-cancel-request").on("click", function(){ >- var a = $(this); >- var notes = prompt(_("Reason for cancellation:")); >+ $('#modal-cancellation-reason').on('change', function(e) { >+ let reason = $(this).val(); >+ $('#modal-notes').attr('disabled', !!reason); >+ }) >+ >+ let cancel_a; >+ $("#cancelModalConfirmBtn").on("click",function(e) { >+ var id = cancel_a.attr('id').split("cancel-")[1]; >+ $("#cancel-processing-" + id ).hide('slow'); >+ $("#cancel-processing-spinner-" + id ).show('slow'); >+ >+ let reason = $("#modal-cancellation-reason").val(); >+ let notes = $("#modal-notes").val(); >+ let query = '?'+(reason?'cancellation_reason='+reason:'notes='+notes) >+ >+ $.ajax({ >+ type: "DELETE", >+ url: '/api/v1/article_requests/'+id+query, >+ success: function( data ) { >+ cancel_a.parents('tr').hide('slow'); >+ } >+ }); >+ }); > >- if ( notes != null ) { >- var id = this.id.split("cancel-")[1]; >- $("#cancel-processing-" + id ).hide('slow'); >- $("#cancel-processing-spinner-" + id ).show('slow'); > >- $.ajax({ >- type: "POST", >- url: '/cgi-bin/koha/svc/article_request', >- data: { >- action: 'cancel', >- id: id, >- notes: notes >- }, >- success: function( data ) { >- a.parents('tr').hide('slow'); >- }, >- dataType: 'json' >- }); >- } >+ $(".ar-cancel-request").on("click", function(){ >+ cancel_a = $(this); >+ $('#cancelModal').modal(); > }); > > // Initialize format(s) >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >index 578b6ccfbf..1fdc32b0e5 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >@@ -5,6 +5,7 @@ > [% USE Branches %] > [% USE ItemTypes %] > [% USE Price %] >+[% USE AuthorisedValues %] > [% SET AdlibrisEnabled = Koha.Preference('AdlibrisCoversEnabled') %] > [% SET AdlibrisURL = Koha.Preference('AdlibrisCoversURL') %] > >@@ -715,7 +716,7 @@ > <div id="opac-user-article-requests"> > [% IF logged_in_user.article_requests_current.count %] > <table id="article-requests-table" class="table table-bordered table-striped"> >- <caption>Article requests <span class="count">([% logged_in_user.article_requests_current.count | html %] total)</span></caption> >+ <caption>Article requests <span class="count"></span></caption> > <thead> > <tr> > <th class="anti-the article-request-record-title">Record title</th> >@@ -803,12 +804,7 @@ > </td> > > <td class="article-request-cancel"> >- <span class="tdlabel">Cancel:</span> >- <form action="/cgi-bin/koha/opac-article-request-cancel.pl" id="delete_article_request_[% ar.id | html %]"> >- <legend class="sr-only">Cancel article request</legend> >- <input type="hidden" name="id" value="[% ar.id | html %]" /> >- <button data-title="[% ar.biblio.title | html %] [% ar.item.enumchron | html %]" data-article-request_id="[% ar.id | html %]" type="submit" class="btn btn-sm btn-danger btn-delete-article-request"><i class="fa fa-remove" aria-hidden="true"></i> Cancel</button> >- </form> >+ <button data-title="[% ar.biblio.title | html %] [% ar.item.enumchron | html %]" data-article-request_id="[% ar.id | html %]" class="btn btn-sm btn-danger btn-delete-article-request"><i class="fa fa-remove" aria-hidden="true"></i> Cancel</button> > </td> > </tr> > [% END %] >@@ -845,6 +841,9 @@ > [% INCLUDE 'calendar.inc' %] > [% INCLUDE 'datatables.inc' %] > <script> >+ var AR_CAPTION_COUNT = _("(%s total)"); >+ >+ > function tableInit( tableId ){ > if( tableId == "checkoutst" ){ > $(".dt-buttons").append("<button type=\"button\" class=\"dt-button buttons-ical\" id=\"buttons-ics\">iCal</button> "); >@@ -854,6 +853,7 @@ > } > } > $(document).ready(function(){ >+ $('#opac-user-article-requests caption .count').html(AR_CAPTION_COUNT.format('[% logged_in_user.article_requests_current.count | html %]')); > $('#opac-user-views').tabs(); > $(".modal-nojs").addClass("modal").addClass("hide").removeClass("modal-nojs"); > $(".suspend-until").prop("readonly",1); >@@ -863,6 +863,7 @@ > var hold_title = $(this).data("title"); > var reserve_id = $(this).data("reserve_id"); > confirmModal( hold_title, _("Are you sure you want to cancel this hold?"), _("Yes, cancel hold"), _("No, do not cancel hold"), function( result ){ >+ $("#bootstrap-confirm-box-modal").remove() > if( result ){ > $("#delete_hold_" + reserve_id ).submit(); > } >@@ -874,12 +875,32 @@ > e.preventDefault(); > var article_request = $(this).data("title"); > var article_request_id = $(this).data("article-request_id"); >- confirmModal( article_request, _("Are you sure you want to cancel this article request?"), _("Yes, cancel article request"), _("No, do not cancel article request"), function( result ){ >+ (function(row){ >+ var doCancel = function( result ){ >+ $("#bootstrap-confirm-box-modal").remove(); > if( result ){ >- $("#delete_article_request_" + article_request_id ).submit(); >+ $.ajax({ >+ type: "DELETE", >+ url: '/api/v1/public/patrons/'+borrowernumber+'/article_requests/'+article_request_id, >+ success: function( data ) { >+ row.parents('tr').hide({ >+ duration: 'slow', >+ complete: function() { >+ var ar_tab = $('a[href="#opac-user-article-requests"'); >+ var ar_table = $('#article-requests-table'); >+ var ar_length = $('tbody tr:visible', ar_table).length; >+ var ar_count = $('caption .count', ar_table); >+ >+ ar_tab.html(ar_tab.html().replace(/\(\d+\)/, '('+ar_length+')')); >+ ar_count.html(AR_CAPTION_COUNT.format(ar_length)); >+ } >+ }); >+ } >+ }); > } >- } >- ); >+ }; >+ confirmModal( article_request, _("Are you sure you want to cancel this article request?"), _("Yes, cancel article request"), _("No, do not cancel article request"), doCancel); >+ })($(this)) > }); > > $("#suspend_all_submit").on("click", function(e){ >@@ -887,6 +908,7 @@ > var title = _("Are you sure you want to suspend all holds?"); > var body = _("All holds will be suspended."); > confirmModal( body, title, _("Yes, suspend all holds"), "", function( result ){ >+ $("#bootstrap-confirm-box-modal").remove() > if( result ){ > $("#suspend_all_holds").submit(); > } >@@ -899,6 +921,7 @@ > var title = _("Are you sure you want to resume all suspended holds?"); > var body = _("All holds will resume."); > confirmModal( body, title, _("Yes, resume all holds"), _("No, do not resume holds"), function( result ){ >+ $("#bootstrap-confirm-box-modal").remove() > if( result ){ > $("#resume_all_holds").submit(); > } >-- >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 27947
:
124063
|
124064
|
124065
|
124849
|
124850
|
124851
|
124952
|
124953
|
124954
|
124955
|
124956
|
124993
|
124994
|
124995
|
124996
|
124997
|
124998
|
124999
|
125002
|
125003
|
125004
|
125005
|
125006
|
125007
|
125008
|
125009
|
125010
|
125016
|
125038
|
125039
|
125040
|
125041
|
125042
|
125043
|
125044
|
125045
|
125046
|
125047
|
125165
|
125166
| 125167 |
125168
|
125169
|
125170
|
125171
|
125172
|
125173
|
125174
|
125739
|
125740