From ee998c8c848a0af87eb6503dd6eeda456fb18874 Mon Sep 17 00:00:00 2001 From: Jacob O'Mara Date: Thu, 30 Oct 2025 09:54:27 +0000 Subject: [PATCH] Bug 17387: add deleted items restore api Signed-off-by: Michaela --- Koha/Old/Item.pm | 60 ++++++++++ Koha/REST/V1/DeletedItems.pm | 97 ++++++++++++++++ api/v1/swagger/definitions/item.yaml | 6 + api/v1/swagger/paths/deleted_items.yaml | 145 ++++++++++++++++++++++++ 4 files changed, 308 insertions(+) create mode 100644 Koha/REST/V1/DeletedItems.pm create mode 100644 api/v1/swagger/paths/deleted_items.yaml diff --git a/Koha/Old/Item.pm b/Koha/Old/Item.pm index edaec7a368..fef7b8879f 100644 --- a/Koha/Old/Item.pm +++ b/Koha/Old/Item.pm @@ -55,6 +55,66 @@ sub restore { return $new_item; } +=head3 to_api_mapping + +This method returns the mapping for representing a Koha::Old::Item object +on the API. + +=cut + +sub to_api_mapping { + return { + itemnumber => 'item_id', + biblionumber => 'biblio_id', + biblioitemnumber => undef, + barcode => 'external_id', + dateaccessioned => 'acquisition_date', + booksellerid => 'acquisition_source', + homebranch => 'home_library_id', + price => 'purchase_price', + replacementprice => 'replacement_price', + replacementpricedate => 'replacement_price_date', + datelastborrowed => 'last_checkout_date', + datelastseen => 'last_seen_date', + stack => undef, + notforloan => 'not_for_loan_status', + damaged => 'damaged_status', + damaged_on => 'damaged_date', + itemlost => 'lost_status', + itemlost_on => 'lost_date', + withdrawn => 'withdrawn', + withdrawn_on => 'withdrawn_date', + itemcallnumber => 'callnumber', + coded_location_qualifier => 'coded_location_qualifier', + issues => 'checkouts_count', + renewals => 'renewals_count', + reserves => 'holds_count', + restricted => 'restricted_status', + itemnotes => 'public_notes', + itemnotes_nonpublic => 'internal_notes', + holdingbranch => 'holding_library_id', + permanent_location => 'permanent_location', + onloan => 'checked_out_date', + cn_source => 'call_number_source', + cn_sort => 'call_number_sort', + ccode => 'collection_code', + materials => 'materials_notes', + itype => 'item_type_id', + more_subfields_xml => 'extended_subfields', + enumchron => 'serial_issue_number', + copynumber => 'copy_number', + stocknumber => 'inventory_number', + new_status => 'new_status', + deleted_on => 'deleted_on', + bookable => undef, + location => undef, + uri => undef, + timestamp => undef, + localuse => undef, + exclude_from_local_holds_priority => undef, + }; +} + =head2 Internal methods =head3 _type diff --git a/Koha/REST/V1/DeletedItems.pm b/Koha/REST/V1/DeletedItems.pm new file mode 100644 index 0000000000..d3fa1a21df --- /dev/null +++ b/Koha/REST/V1/DeletedItems.pm @@ -0,0 +1,97 @@ +package Koha::REST::V1::DeletedItems; + +# 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::Old::Items; + +use Try::Tiny qw( catch try ); + +=head1 API + +=head2 Methods + +=head3 get + +Controller function that handles retrieving a single deleted item object + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + my $item = Koha::Old::Items->find( $c->param('item_id') ); + + return $c->render_resource_not_found("Item") + unless $item; + + return try { + return $c->render( + status => 200, + openapi => $c->objects->to_api($item), + ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 list + +Controller function that handles listing deleted item objects + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + my $items = $c->objects->search( Koha::Old::Items->new ); + return $c->render( status => 200, openapi => $items ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 restore + +Controller function that handles restoring a single deleted item object + +=cut + +sub restore { + my $c = shift->openapi->valid_input or return; + + my $deleted_item = Koha::Old::Items->find( $c->param('item_id') ); + + return $c->render_resource_not_found("Item") + unless $deleted_item; + + return try { + my $item = $deleted_item->restore; + + return $c->render( + status => 200, + openapi => $c->objects->to_api($item), + ); + } catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/api/v1/swagger/definitions/item.yaml b/api/v1/swagger/definitions/item.yaml index 42dcd36e3e..931055e0ca 100644 --- a/api/v1/swagger/definitions/item.yaml +++ b/api/v1/swagger/definitions/item.yaml @@ -157,6 +157,12 @@ properties: type: string format: date-time description: Date and time this item was last altered + deleted_on: + type: + - string + - "null" + format: date-time + description: Date and time this item was deleted location: type: - string diff --git a/api/v1/swagger/paths/deleted_items.yaml b/api/v1/swagger/paths/deleted_items.yaml new file mode 100644 index 0000000000..923ce641cc --- /dev/null +++ b/api/v1/swagger/paths/deleted_items.yaml @@ -0,0 +1,145 @@ +--- +"/deleted/items": + get: + x-mojo-to: DeletedItems#list + operationId: listDeletedItems + tags: + - items + summary: List deleted items + parameters: + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/q_param" + - $ref: "../swagger.yaml#/parameters/q_body" + - $ref: "../swagger.yaml#/parameters/request_id_header" + produces: + - application/json + responses: + "200": + description: A list of deleted items + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/item" + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + 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" + "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: + catalogue: "1" +"/deleted/items/{item_id}": + get: + x-mojo-to: DeletedItems#get + operationId: getDeletedItem + tags: + - items + summary: Get deleted item + parameters: + - $ref: "../swagger.yaml#/parameters/item_id_pp" + produces: + - application/json + responses: + "200": + description: A deleted item + schema: + $ref: "../swagger.yaml#/definitions/item" + "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: Item 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: + catalogue: "1" + put: + x-mojo-to: DeletedItems#restore + operationId: restoreDeletedItem + tags: + - items + summary: Restore deleted item + parameters: + - $ref: "../swagger.yaml#/parameters/item_id_pp" + produces: + - application/json + responses: + "200": + description: Item restored successfully + schema: + $ref: "../swagger.yaml#/definitions/item" + "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: Deleted item 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: + editcatalogue: edit_catalogue -- 2.39.5