From f278bc08596839129e89274ac46b0b45fe33cd54 Mon Sep 17 00:00:00 2001 From: Pedro Amorim Date: Fri, 12 May 2023 17:09:39 +0000 Subject: [PATCH] Bug 30719: ILL Batch Statuses - UI adding support for batch statuses in batch UI - Admin UI for managing batch statuses - API specs Co-authored-by: Andrew Isherwood --- Koha/IllbatchStatus.pm | 162 ++++++++++++ Koha/IllbatchStatuses.pm | 61 +++++ Koha/REST/V1/IllbatchStatuses.pm | 167 +++++++++++++ admin/ill_batch_statuses.pl | 102 ++++++++ .../swagger/definitions/illbatchstatus.yaml | 20 ++ .../swagger/definitions/illbatchstatuses.yaml | 5 + api/v1/swagger/paths/illbatchstatuses.yaml | 232 ++++++++++++++++++ .../prog/en/includes/admin-menu.inc | 3 + .../prog/en/modules/admin/admin-home.tt | 4 + .../en/modules/admin/ill_batch_statuses.tt | 168 +++++++++++++ 10 files changed, 924 insertions(+) create mode 100644 Koha/IllbatchStatus.pm create mode 100644 Koha/IllbatchStatuses.pm create mode 100644 Koha/REST/V1/IllbatchStatuses.pm create mode 100755 admin/ill_batch_statuses.pl create mode 100644 api/v1/swagger/definitions/illbatchstatus.yaml create mode 100644 api/v1/swagger/definitions/illbatchstatuses.yaml create mode 100644 api/v1/swagger/paths/illbatchstatuses.yaml create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/ill_batch_statuses.tt diff --git a/Koha/IllbatchStatus.pm b/Koha/IllbatchStatus.pm new file mode 100644 index 0000000000..c49ec48703 --- /dev/null +++ b/Koha/IllbatchStatus.pm @@ -0,0 +1,162 @@ +package Koha::IllbatchStatus; + +# Copyright PTFS Europe 2022 +# +# 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 . + +use Modern::Perl; +use Koha::Database; +use Koha::Illrequest::Logger; +use Koha::Illbatch; +use JSON qw( to_json ); +use base qw(Koha::Object); + +=head1 NAME + +Koha::IllbatchStatus - Koha IllbatchStatus Object class + +=head2 Class methods + +=head3 create_and_log + + $status->create_and_log; + +Log batch status creation following storage + +=cut + +sub create_and_log { + my ( $self ) = @_; + + # Ensure code is uppercase and contains only word characters + my $fixed_code = uc $self->code; + $fixed_code =~ s/\W/_/; + + # Ensure this status doesn't already exist + my $status = Koha::IllbatchStatuses->find({ code => $fixed_code }); + if ($status) { + return { + error => "Duplicate status found" + }; + } + + # Ensure system statuses can't be created + $self->set({ + code => $fixed_code, + is_system => 0 + })->store; + + my $logger = Koha::Illrequest::Logger->new; + + $logger->log_something({ + modulename => 'ILL', + actionname => 'batch_status_create', + objectnumber => $self->id, + infos => to_json({}) + }); +} + +=head3 update_and_log + + $status->update_and_log; + +Log batch status update following storage + +=cut + +sub update_and_log { + my ( $self, $params ) = @_; + + my $before = { + name => $self->name + }; + + # Ensure only the name can be changed + $self->set({ + name => $params->{name} + }); + my $update = $self->store; + + my $after = { + name => $self->name + }; + + my $logger = Koha::Illrequest::Logger->new; + + $logger->log_something({ + modulename => 'ILL', + actionname => 'batch_status_update', + objectnumber => $self->id, + infos => to_json({ + before => $before, + after => $after + }) + }); +} + +=head3 delete_and_log + + $batch->delete_and_log; + +Log batch status delete + +=cut + +sub delete_and_log { + my ( $self ) = @_; + + # Don't permit deletion of system statuses + if ($self->is_system) { + return; + } + + # Update all batches that use this status to have status UNKNOWN + my $affected = Koha::Illbatches->search({ statuscode => $self->code }); + $affected->update({ statuscode => 'UNKNOWN'}); + + my $logger = Koha::Illrequest::Logger->new; + + $logger->log_something({ + modulename => 'ILL', + actionname => 'batch_status_delete', + objectnumber => $self->id, + infos => to_json({}) + }); + + $self->delete; +} + +=head2 Internal methods + +=head3 _type + + my $type = Koha::IllbatchStatus->_type; + +Return this object's type + +=cut + +sub _type { + return 'IllbatchStatus'; +} + +=head1 AUTHOR + +Andrew Isherwood + +=cut + +1; diff --git a/Koha/IllbatchStatuses.pm b/Koha/IllbatchStatuses.pm new file mode 100644 index 0000000000..1cbeedbd03 --- /dev/null +++ b/Koha/IllbatchStatuses.pm @@ -0,0 +1,61 @@ +package Koha::IllbatchStatuses; + +# Copyright PTFS Europe 2022 +# +# 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 . + +use Modern::Perl; +use Koha::Database; +use Koha::IllbatchStatus; +use base qw(Koha::Objects); + +=head1 NAME + +Koha::IllbatchStatuses - Koha IllbatchStatuses Object class + +=head2 Internal methods + +=head3 _type + + my $type = Koha::IllbatchStatuses->_type; + +Return this object's type + +=cut + +sub _type { + return 'IllbatchStatus'; +} + +=head3 object_class + + my $class = Koha::IllbatchStatuses->object_class; + +Return this object's class name + +=cut + +sub object_class { + return 'Koha::IllbatchStatus'; +} + +=head1 AUTHOR + +Andrew Isherwood + +=cut + +1; diff --git a/Koha/REST/V1/IllbatchStatuses.pm b/Koha/REST/V1/IllbatchStatuses.pm new file mode 100644 index 0000000000..28f398efb1 --- /dev/null +++ b/Koha/REST/V1/IllbatchStatuses.pm @@ -0,0 +1,167 @@ +package Koha::REST::V1::IllbatchStatuses; + +# 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 . + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Koha::IllbatchStatuses; + +=head1 NAME + +Koha::REST::V1::IllbatchStatuses + +=head2 Operations + +=head3 list + +Return a list of available ILL batch statuses + +=cut + +sub list { + my $c = shift->openapi->valid_input; + + my @statuses = Koha::IllbatchStatuses->search()->as_list; + + return $c->render( status => 200, openapi => \@statuses ); +} + +=head3 get + +Get one batch statuses + +=cut + +sub get { + my $c = shift->openapi->valid_input; + + my $status_code = $c->validation->param('illbatchstatus_code'); + + my $status = Koha::IllbatchStatuses->find({ code => $status_code }); + + if (not defined $status) { + return $c->render( + status => 404, + openapi => { error => "ILL batch status not found" } + ); + } + + return $c->render( + status => 200, + openapi => { + %{$status->unblessed} + } + ); +} + +=head3 add + +Add a new batch status + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + my $body = $c->validation->param('body'); + + my $status = Koha::IllbatchStatus->new( $body ); + + return try { + my $return = $status->create_and_log; + if ($return && $return->{error}) { + return $c->render( + status => 500, + openapi => $return + ); + } else { + return $c->render( + status => 201, + openapi => $status + ); + } + } + catch { + $c->unhandled_exception($_); + }; +} + +=head3 update + +Update a batch status + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $status = Koha::IllbatchStatuses->find({ code => $c->validation->param('illbatchstatus_code') }); + + if ( not defined $status ) { + return $c->render( + status => 404, + openapi => { error => "ILL batch status not found" } + ); + } + + my $params = $c->req->json; + + return try { + # Only permit updating of name + $status->update_and_log({ name => $params->{name} }); + + return $c->render( + status => 200, + openapi => $status + ); + } + catch { + $c->unhandled_exception($_); + }; +} + +=head3 delete + +Delete a batch status + +=cut + +sub delete { + + my $c = shift->openapi->valid_input or return; + + my $status = Koha::IllbatchStatuses->find({ code => $c->validation->param( 'illbatchstatus_code' ) }); + + if ( not defined $status ) { + return $c->render( status => 404, openapi => { errors => [ { message => "ILL batch status not found" } ] } ); + } + + if ( $status->is_system) { + return $c->render( status => 400, openapi => { errors => [ { message => "ILL batch status cannot be deleted" } ] } ); + } + + return try { + $status->delete_and_log; + return $c->render( status => 204, openapi => ''); + } + catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/admin/ill_batch_statuses.pl b/admin/ill_batch_statuses.pl new file mode 100755 index 0000000000..bf16b06ded --- /dev/null +++ b/admin/ill_batch_statuses.pl @@ -0,0 +1,102 @@ +#! /usr/bin/perl + +# Copyright 2019 Koha Development Team +# +# 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 . + +use Modern::Perl; +use CGI qw ( -utf8 ); +use Try::Tiny qw( catch try ); + +use C4::Context; +use C4::Auth qw( get_template_and_user ); +use C4::Output qw( output_html_with_http_headers ); + +use Koha::IllbatchStatus; +use Koha::IllbatchStatuses; + +my $input = CGI->new; +my $code = $input->param('code'); +my $op = $input->param('op') || 'list'; +my @messages; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "admin/ill_batch_statuses.tt", + query => $input, + type => "intranet", + flagsrequired => { parameters => 'ill' }, + } +); + +my $status; +if ($code) { + $status = Koha::IllbatchStatuses->find({ code => $code }); +} + +if ( $op eq 'add_form' ) { + if ($status) { + $template->param( + status => $status + ); + } +} +elsif ( $op eq 'add_validate' ) { + my $name = $input->param('name'); + my $code = $input->param('code'); + + if ( not defined $status ) { + $status = Koha::IllbatchStatus->new( { + name => $name, + code => $code + } ); + } + + try { + if ($status->id) { + $status->update_and_log({ name => $name }); + } else { + $status->create_and_log; + } + push @messages, { type => 'message', code => 'success_on_saving' }; + } + catch { + push @messages, { type => 'error', code => 'error_on_saving' }; + }; + $op = 'list'; +} +elsif ( $op eq 'delete' ) { + try { + $status->delete_and_log; + push @messages, { code => 'success_on_delete', type => 'message' }; + } + catch { + push @messages, { code => 'error_on_delete', type => 'alert' }; + + }; + $op = 'list'; +} +if ( $op eq 'list' ) { + my $statuses = Koha::IllbatchStatuses->search(); + $template->param( statuses => $statuses ); +} + +$template->param( + messages => \@messages, + op => $op, +); + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/api/v1/swagger/definitions/illbatchstatus.yaml b/api/v1/swagger/definitions/illbatchstatus.yaml new file mode 100644 index 0000000000..42b2452551 --- /dev/null +++ b/api/v1/swagger/definitions/illbatchstatus.yaml @@ -0,0 +1,20 @@ +--- +type: object +properties: + id: + type: string + description: Internal ILL batch status identifier + name: + type: string + description: Status name + code: + type: string + description: Unique, immutable status code + is_system: + type: string + description: Is this status required for system operation +additionalProperties: false +required: + - name + - code + - is_system diff --git a/api/v1/swagger/definitions/illbatchstatuses.yaml b/api/v1/swagger/definitions/illbatchstatuses.yaml new file mode 100644 index 0000000000..5eb4b53400 --- /dev/null +++ b/api/v1/swagger/definitions/illbatchstatuses.yaml @@ -0,0 +1,5 @@ +--- +type: array +items: + $ref: "illbatchstatus.yaml" +additionalProperties: false diff --git a/api/v1/swagger/paths/illbatchstatuses.yaml b/api/v1/swagger/paths/illbatchstatuses.yaml new file mode 100644 index 0000000000..f211b2b62d --- /dev/null +++ b/api/v1/swagger/paths/illbatchstatuses.yaml @@ -0,0 +1,232 @@ +--- +/illbatchstatuses: + get: + x-mojo-to: IllbatchStatuses#list + operationId: listIllbatchstatuses + tags: + - illbatchstatuses + summary: List ILL batch statuses + parameters: [] + produces: + - application/json + responses: + "200": + description: A list of ILL batch statuses + schema: + $ref: "../swagger.yaml#/definitions/illbatchstatuses" + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: ILL batch statuses not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + ill: "1" + post: + x-mojo-to: IllbatchStatuses#add + operationId: addIllbatchstatus + tags: + - illbatchstatuses + summary: Add ILL batch status + parameters: + - name: body + in: body + description: A JSON object containing informations about the new batch status + required: true + schema: + $ref: "../swagger.yaml#/definitions/illbatchstatus" + produces: + - application/json + responses: + "201": + description: Batch status added + schema: + $ref: "../swagger.yaml#/definitions/illbatchstatus" + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "409": + description: Conflict in creating resource + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + ill: "1" +"/illbatchstatuses/{illbatchstatus_code}": + get: + x-mojo-to: IllbatchStatuses#get + operationId: getIllbatchstatuses + tags: + - illbatchstatuses + summary: Get ILL batch status + parameters: + - name: illbatchstatus_code + in: path + description: ILL batch status + required: true + type: string + produces: + - application/json + responses: + "200": + description: An ILL batch status + schema: + $ref: "../swagger.yaml#/definitions/illbatchstatus" + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: ILL batch status not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + ill: "1" + put: + x-mojo-to: IllbatchStatuses#update + operationId: updateIllBatchstatus + tags: + - illbatchstatuses + summary: Update batch status + parameters: + - $ref: "../swagger.yaml#/parameters/illbatchstatus_code_pp" + - name: body + in: body + description: A JSON object containing information on the batch status + required: true + schema: + $ref: "../swagger.yaml#/definitions/illbatchstatus" + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: An ILL batch status + schema: + $ref: "../swagger.yaml#/definitions/illbatchstatus" + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: ILL batch status not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + ill: "1" + delete: + x-mojo-to: IllbatchStatuses#delete + operationId: deleteBatchstatus + tags: + - illbatchstatuses + summary: Delete ILL batch status + parameters: + - $ref: "../swagger.yaml#/parameters/illbatchstatus_code_pp" + produces: + - application/json + responses: + "204": + description: ILL batch status deleted + schema: + type: string + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: ILL batch status not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + ill: "1" diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc index 96ca936832..1a2adcb8d4 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc @@ -177,6 +177,9 @@ [% IF ( Koha.Preference('EnableAdvancedCatalogingEditor') && CAN_user_parameters_manage_keyboard_shortcuts ) %]
  • Keyboard shortcuts
  • [% END %] + [% IF Koha.Preference('ILLModule ') && CAN_user_ill %] +
  • Interlibrary Loan batch statuses
  • + [% END %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt index 47b2142fea..3eb1749b81 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt @@ -282,6 +282,10 @@
    Keyboard shortcuts
    Define which keys trigger actions in the advanced cataloging editor
    [% END %] + [% IF Koha.Preference('ILLModule') && CAN_user_ill %] +
    Interlibrary Loan batch statuses
    +
    Manage the statuses that can be assigned to Interlibrary Loan batches
    + [% END %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/ill_batch_statuses.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/ill_batch_statuses.tt new file mode 100644 index 0000000000..c47cc27e2c --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/ill_batch_statuses.tt @@ -0,0 +1,168 @@ +[% USE raw %] +[% USE Asset %] +[% USE Branches %] +[% USE Price %] +[% SET footerjs = 1 %] +[% INCLUDE 'doc-head-open.inc' %] + + [% IF op =='add_form' %] + [% IF status.id %] + Modify batch status + [% ELSE %] + New batch status + [% END %] › [% END %] + Interlibrary Loan batch statuses › Administration › Koha + +[% INCLUDE 'doc-head-close.inc' %] + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'prefs-admin-search.inc' %] + + + +
    +
    +
    +
    + + [% FOREACH m IN messages %] +
    + [% SWITCH m.code %] + [% CASE 'success_on_saving' %] + Batch status saved successfully + [% CASE 'success_on_delete' %] + Batch status deleted successfully + [% CASE 'error_on_saving' %] + An error occurred when saving this batch status + [% CASE 'error_on_delete' %] + An error occurred when deleting this batch status + [% CASE %] + [% m.code | html %] + [% END %] +
    + [% END %] + + [% IF op == 'add_form' %] + [% IF status %] +

    Modify a batch status

    + [% ELSE %] +

    New batch status

    + [% END %] + +
    + +
    +
      +
    1. + + Required. Maximum length is 100 letters +
    2. +
    3. + + [% IF status %] + [% status.code | html %] + + [% ELSE %] + Required, specify UPPERCASE LETTERS. Maximum length is 20 letters + [% END %] +
    4. +
    5. + + [% status.is_system ? "Yes" : "No" | html %] + +
    6. +
    +
    + +
    + + Cancel +
    +
    + [% END %] + + [% IF op == 'list' %] + + +

    Interlibrary Loan batch statuses

    + [% IF statuses.count %] + + + + + + + + + [% FOREACH status IN statuses %] + + + + + + + [% END %] + +
    NameCodeIs systemActions
    [% status.name | html %][% status.code | html %][% status.is_system ? "Yes" : "No" | html %] + Edit + [% IF !status.is_system %] + Delete + [% END %] +
    + [% ELSE %] +
    + There are no batch statuses defined. Create new batch status +
    + [% END %] + [% END %] +
    +
    + +
    + +
    +
    + +[% MACRO jsinclude BLOCK %] + [% Asset.js("js/admin-menu.js") | $raw %] + [% INCLUDE 'datatables.inc' %] +[% END %] + +[% INCLUDE 'intranet-bottom.inc' %] -- 2.30.2