1 package Koha::REST::V1::Items;
3 # This file is part of Koha.
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use Mojo::Base 'Mojolicious::Controller';
22 use C4::Circulation qw( barcodedecode );
26 use List::MoreUtils qw( any );
27 use Try::Tiny qw( catch try );
31 Koha::REST::V1::Items - Koha REST API for handling items (V1)
41 Controller function that handles listing Koha::Item objects
46 my $c = shift->openapi->valid_input or return;
49 my $items_set = Koha::Items->new;
50 my $items = $c->objects->search( $items_set );
57 $c->unhandled_exception($_);
63 Controller function that handles listing Koha::Item objects available to the opac
68 my $c = shift->openapi->valid_input or return;
71 my $patron = $c->stash('koha.user');
74 Koha::Items->filter_by_visible_in_opac( { patron => $patron } );
75 my $items = $c->objects->search($items_set);
83 $c->unhandled_exception($_);
89 Controller function that handles retrieving a single Koha::Item
94 my $c = shift->openapi->valid_input or return;
97 my $items_rs = Koha::Items->new;
98 my $item = $c->objects->find($items_rs, $c->validation->param('item_id'));
102 openapi => { error => 'Item not found'}
105 return $c->render( status => 200, openapi => $item );
108 $c->unhandled_exception($_);
114 Controller function that handles deleting a single Koha::Item
119 my $c = shift->openapi->valid_input or return;
122 my $item = Koha::Items->find($c->validation->param('item_id'));
126 openapi => { error => 'Item not found'}
130 my $safe_to_delete = $item->safe_to_delete;
132 if ( !$safe_to_delete ) {
134 # Pick the first error, if any
135 my ( $error ) = grep { $_->type eq 'error' } @{ $safe_to_delete->messages };
138 Koha::Exception->throw('Koha::Item->safe_to_delete returned false but carried no error message');
142 book_on_loan => { code => 'checked_out', description => 'The item is checked out' },
143 book_reserved => { code => 'found_hold', description => 'Waiting or in-transit hold for the item' },
144 last_item_for_hold => { code => 'last_item_for_hold', description => 'The item is the last one on a record on which a biblio-level hold is placed' },
145 linked_analytics => { code => 'linked_analytics', description => 'The item has linked analytic records' },
146 not_same_branch => { code => 'not_same_branch', description => 'The item is blocked by independent branches' },
149 if ( any { $error->message eq $_ } keys %{$errors} ) {
151 my $code = $error->message;
156 error => $errors->{ $code }->{description},
157 error_code => $errors->{ $code }->{code},
161 Koha::Exception->throw( 'Koha::Patron->safe_to_delete carried an unexpected message: ' . $error->message );
173 $c->unhandled_exception($_);
177 =head3 pickup_locations
179 Method that returns the possible pickup_locations for a given item
180 used for building the dropdown selector
184 sub pickup_locations {
185 my $c = shift->openapi->valid_input or return;
187 my $item_id = $c->validation->param('item_id');
188 my $item = Koha::Items->find( $item_id );
193 openapi => { error => "Item not found" }
197 my $patron_id = delete $c->validation->output->{patron_id};
198 my $patron = Koha::Patrons->find( $patron_id );
203 openapi => { error => "Patron not found" }
209 my $pl_set = $item->pickup_locations( { patron => $patron } );
212 if ( C4::Context->preference('AllowHoldPolicyOverride') ) {
214 my $libraries_rs = Koha::Libraries->search( { pickup_location => 1 } );
215 my $libraries = $c->objects->search($libraries_rs);
219 $library->{needs_override} = (
220 any { $_->branchcode eq $library->{library_id} }
221 @{ $pl_set->as_list }
230 my $pickup_locations = $c->objects->search($pl_set);
231 @response = map { $_->{needs_override} = Mojo::JSON->false; $_; } @{$pickup_locations};
236 openapi => \@response
240 $c->unhandled_exception($_);
246 Controller function that handles bundled_items Koha::Item objects
251 my $c = shift->openapi->valid_input or return;
253 my $item_id = $c->validation->param('item_id');
254 my $item = Koha::Items->find( $item_id );
259 openapi => { error => "Item not found" }
264 my $items_set = $item->bundle_items;
265 my $items = $c->objects->search( $items_set );
272 $c->unhandled_exception($_);
278 Controller function that handles adding items to this bundle
283 my $c = shift->openapi->valid_input or return;
285 my $item_id = $c->validation->param('item_id');
286 my $item = Koha::Items->find( $item_id );
291 openapi => { error => "Item not found" }
295 my $bundle_item_id = $c->validation->param('body')->{'external_id'};
296 $bundle_item_id = barcodedecode($bundle_item_id);
297 my $bundle_item = Koha::Items->find( { barcode => $bundle_item_id } );
299 unless ($bundle_item) {
302 openapi => { error => "Bundle item not found" }
307 my $body = $c->validation->param('body');
309 force_checkin => $body->{force_checkin},
310 ignore_holds => $body->{ignore_holds},
313 my $link = $item->add_to_bundle($bundle_item, $options);
316 openapi => $bundle_item
320 if ( ref($_) eq 'Koha::Exceptions::Object::DuplicateID' ) {
324 error => 'Item is already bundled',
325 error_code => 'already_bundled',
326 key => $_->duplicate_id
330 elsif ( ref($_) eq 'Koha::Exceptions::Item::Bundle::ItemIsCheckedOut' )
335 error => 'Item is checked out',
336 error_code => 'checked_out'
340 elsif ( ref($_) eq 'Koha::Exceptions::Checkin::FailedCheckin' ) {
344 error => 'Item cannot be checked in',
345 error_code => 'failed_checkin'
349 elsif ( ref($_) eq 'Koha::Exceptions::Item::Bundle::ItemHasHolds' ) {
353 error => 'Item is reserved',
354 error_code => 'reserved'
358 elsif ( ref($_) eq 'Koha::Exceptions::Item::Bundle::IsBundle' ) {
362 error => 'Bundles cannot be nested',
363 error_code => 'failed_nesting'
368 $c->unhandled_exception($_);
373 =head3 remove_from_bundle
375 Controller function that handles removing items from this bundle
379 sub remove_from_bundle {
380 my $c = shift->openapi->valid_input or return;
382 my $item_id = $c->validation->param('item_id');
383 my $item = Koha::Items->find( $item_id );
388 openapi => { error => "Item not found" }
392 my $bundle_item_id = $c->validation->param('bundled_item_id');
393 $bundle_item_id = barcodedecode($bundle_item_id);
394 my $bundle_item = Koha::Items->find( { itemnumber => $bundle_item_id } );
396 unless ($bundle_item) {
399 openapi => { error => "Bundle item not found" }
403 $bundle_item->remove_from_bundle;