From 0b5bb3e8f376c2788d85f5287e8800a2a5d787af Mon Sep 17 00:00:00 2001 From: Julian Maurice Date: Mon, 7 Nov 2022 14:30:34 +0100 Subject: [PATCH] Bug 32121: Show an alert when adding a checked out item to an item bundle When trying to add a checked out item to an item bundle, an alert message will show up, giving the user a chance to return the item immediately before adding it to the bundle Test plan: 1. Create an item bundle (see bug 28854 comment 458) 2. Create a biblio with one item and check out this item. 3. Try to add the checked out item to the bundle You should see a message saying that the item is checked out. Next to this message should be a button "Check in and add to bundle". 4. Click on the button. There should be a message saying that the item was added to the bundle. 5. Close the modal window and verify that the item was correctly returned and added to the bundle Signed-off-by: Martin Renvoize --- Koha/Exceptions/Checkin.pm | 32 ++++++++++++++ Koha/Exceptions/Item/Bundle.pm | 11 ++++- Koha/Item.pm | 21 ++++++++- Koha/REST/V1/Items.pm | 22 ++++++++-- api/v1/swagger/definitions/bundle_link.yaml | 4 ++ .../prog/en/modules/catalogue/detail.tt | 43 +++++++++++++------ t/db_dependent/Koha/Item.t | 27 +++++++++++- 7 files changed, 140 insertions(+), 20 deletions(-) create mode 100644 Koha/Exceptions/Checkin.pm diff --git a/Koha/Exceptions/Checkin.pm b/Koha/Exceptions/Checkin.pm new file mode 100644 index 00000000000..cdc1533c452 --- /dev/null +++ b/Koha/Exceptions/Checkin.pm @@ -0,0 +1,32 @@ +package Koha::Exceptions::Checkin; + +# 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::Exception; + +use Exception::Class ( + 'Koha::Exceptions::Checkin' => { + isa => 'Koha::Exception', + }, + 'Koha::Exceptions::Checkin::FailedCheckin' => { + isa => 'Koha::Exceptions::Checkin', + description => "Checkin failed" + }, +); + +1; diff --git a/Koha/Exceptions/Item/Bundle.pm b/Koha/Exceptions/Item/Bundle.pm index 0ad0a2af002..8c42fd2cb2a 100644 --- a/Koha/Exceptions/Item/Bundle.pm +++ b/Koha/Exceptions/Item/Bundle.pm @@ -20,14 +20,17 @@ use Modern::Perl; use Koha::Exception; use Exception::Class ( - 'Koha::Exceptions::Item::Bundle' => { isa => 'Koha::Exception', }, 'Koha::Exceptions::Item::Bundle::IsBundle' => { isa => 'Koha::Exceptions::Item::Bundle', description => "A bundle cannot be added to a bundle", - } + }, + 'Koha::Exceptions::Item::Bundle::ItemIsCheckedOut' => { + isa => 'Koha::Exceptions::Item::Bundle', + description => 'Someone tried to add a checked out item to a bundle', + }, ); =head1 NAME @@ -44,6 +47,10 @@ Generic Item::Bundle exception Exception to be used when attempting to add one bundle into another. +=head2 Koha::Exceptions::Item::Bundle::ItemIsCheckedOut + +Exception to be used when attempting to add a checked out item to a bundle. + =cut 1; diff --git a/Koha/Item.pm b/Koha/Item.pm index a0a18e5fb19..13d26748646 100644 --- a/Koha/Item.pm +++ b/Koha/Item.pm @@ -36,6 +36,8 @@ use Koha::Biblio::ItemGroups; use Koha::Checkouts; use Koha::CirculationRules; use Koha::CoverImages; +use Koha::Exceptions::Checkin; +use Koha::Exceptions::Item::Bundle; use Koha::Exceptions::Item::Transfer; use Koha::Item::Attributes; use Koha::Exceptions::Item::Bundle; @@ -1703,7 +1705,9 @@ Adds the bundle_item passed to this item =cut sub add_to_bundle { - my ( $self, $bundle_item ) = @_; + my ( $self, $bundle_item, $options ) = @_; + + $options //= {}; Koha::Exceptions::Item::Bundle::IsBundle->throw() if ( $self->itemnumber eq $bundle_item->itemnumber @@ -1717,6 +1721,19 @@ sub add_to_bundle { try { $schema->txn_do( sub { + my $checkout = $bundle_item->checkout; + if ($checkout) { + unless ($options->{force_checkin}) { + Koha::Exceptions::Item::Bundle::ItemIsCheckedOut->throw(); + } + + my $branchcode = C4::Context->userenv->{'branch'}; + my ($success) = C4::Circulation::AddReturn($bundle_item->barcode, $branchcode); + unless ($success) { + Koha::Exceptions::Checkin::FailedCheckin->throw(); + } + } + $self->_result->add_to_item_bundles_hosts( { item => $bundle_item->itemnumber } ); @@ -1768,7 +1785,7 @@ sub add_to_bundle { $_->rethrow(); } else { - $_; + $_->rethrow(); } }; } diff --git a/Koha/REST/V1/Items.pm b/Koha/REST/V1/Items.pm index 013ac03f157..3f39009db45 100644 --- a/Koha/REST/V1/Items.pm +++ b/Koha/REST/V1/Items.pm @@ -278,7 +278,8 @@ sub add_to_bundle { } return try { - my $link = $item->add_to_bundle($bundle_item); + my $force_checkin = $c->validation->param('body')->{'force_checkin'}; + my $link = $item->add_to_bundle($bundle_item, { force_checkin => $force_checkin }); return $c->render( status => 201, openapi => $bundle_item @@ -301,8 +302,23 @@ sub add_to_bundle { error => 'Bundles cannot be nested' } ); - } - else { + } elsif (ref($_) eq 'Koha::Exceptions::Item::Bundle::ItemIsCheckedOut') { + return $c->render( + status => 409, + openapi => { + error => 'Item is checked out', + key => 'checked_out' + } + ); + } elsif (ref($_) eq 'Koha::Exceptions::Checkin::FailedCheckin') { + return $c->render( + status => 409, + openapi => { + error => 'Item cannot be checked in', + key => 'failed_checkin' + } + ); + } else { $c->unhandled_exception($_); } }; diff --git a/api/v1/swagger/definitions/bundle_link.yaml b/api/v1/swagger/definitions/bundle_link.yaml index 572be83d8ee..382ad675169 100644 --- a/api/v1/swagger/definitions/bundle_link.yaml +++ b/api/v1/swagger/definitions/bundle_link.yaml @@ -11,4 +11,8 @@ properties: - string - "null" description: Item barcode + force_checkin: + type: + - boolean + - "null" additionalProperties: false diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt index 707a5d7cf3f..7a34ce04d69 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -1937,36 +1937,45 @@ Note that permanent location is a code, and location may be an authval. bundle_form_active = item_id; }); - $("#addToBundleForm").submit(function(event) { - - /* stop form from submitting normally */ - event.preventDefault(); - - /* get the action attribute from the
element */ - var $form = $(this), - url = $form.attr('action'); - + function addToBundle (url, data) { /* Send the data using post with external_id */ var posting = $.post({ url: url, - data: JSON.stringify({ external_id: $('#external_id').val()}), + data: JSON.stringify(data), contentType: "application/json; charset=utf-8", dataType: "json" }); + const barcode = data.external_id; + /* Report the results */ posting.done(function(data) { - var barcode = $('#external_id').val(); $('#addResult').replaceWith('
'+_("Success: Added '%s'").format(barcode)+'
'); $('#external_id').val('').focus(); bundle_changed = 1; }); posting.fail(function(data) { - var barcode = $('#external_id').val(); if ( data.status === 409 ) { var response = data.responseJSON; if ( response.key === "PRIMARY" ) { $('#addResult').replaceWith('
'+_("Warning: Item '%s' already attached").format(barcode)+'
'); + } else if (response.key === 'checked_out') { + const button = $('