From 3e5a3b9899c0b9fbea89c16fa6794d468a09a61f Mon Sep 17 00:00:00 2001 From: Jake Deery Date: Mon, 1 Dec 2025 13:12:59 +0000 Subject: [PATCH] Bug 14962: On Display code for REST API This patch adds all the various API endpoints, and modifies a few existing API endpoints, in preparation for the On Display Vue app Please see the test files commit for instructions on how to test this bundle of patches. --- Koha/REST/V1/DisplayItems.pm | 259 ++++++++++++ Koha/REST/V1/Displays.pm | 250 +++++++++++ api/v1/swagger/definitions/display.yaml | 97 +++++ .../swagger/definitions/display_config.yaml | 7 + api/v1/swagger/definitions/displayitem.yaml | 31 ++ api/v1/swagger/definitions/item.yaml | 20 + api/v1/swagger/paths/displayitems.yaml | 395 ++++++++++++++++++ api/v1/swagger/paths/displays.yaml | 273 ++++++++++++ api/v1/swagger/paths/displays_config.yaml | 38 ++ api/v1/swagger/paths/public_displayitems.yaml | 94 +++++ api/v1/swagger/paths/public_displays.yaml | 124 ++++++ api/v1/swagger/swagger.yaml | 38 ++ 12 files changed, 1626 insertions(+) create mode 100644 Koha/REST/V1/DisplayItems.pm create mode 100644 Koha/REST/V1/Displays.pm create mode 100644 api/v1/swagger/definitions/display.yaml create mode 100644 api/v1/swagger/definitions/display_config.yaml create mode 100644 api/v1/swagger/definitions/displayitem.yaml create mode 100644 api/v1/swagger/paths/displayitems.yaml create mode 100644 api/v1/swagger/paths/displays.yaml create mode 100644 api/v1/swagger/paths/displays_config.yaml create mode 100644 api/v1/swagger/paths/public_displayitems.yaml create mode 100644 api/v1/swagger/paths/public_displays.yaml diff --git a/Koha/REST/V1/DisplayItems.pm b/Koha/REST/V1/DisplayItems.pm new file mode 100644 index 00000000000..d01696cad4e --- /dev/null +++ b/Koha/REST/V1/DisplayItems.pm @@ -0,0 +1,259 @@ +package Koha::REST::V1::DisplayItems; + +# 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::DisplayItem; +use Koha::DisplayItems; +use Koha::Displays; + +use Try::Tiny qw( catch try ); +use Scalar::Util qw( blessed ); + +use Koha::BackgroundJob::BatchAddDisplayItems; +use Koha::BackgroundJob::BatchDeleteDisplayItems; + +=head1 API + +=head2 Methods + +=head3 list + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + my $displayitems = $c->objects->search( Koha::DisplayItems->new ); + return $c->render( status => 200, openapi => $displayitems ); + } catch { + $c->unhandled_exception($_); + }; + +} + +=head3 get + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + return try { + my $displayitem = Koha::DisplayItems->find( + { + display_item_id => $c->param('display_item_id'), + display_id => $c->param('display_id'), + itemnumber => $c->param('item_id') + } + ); + return $c->render_resource_not_found("Display item") + unless $displayitem; + + return $c->render( status => 200, openapi => $c->objects->to_api($displayitem), ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 add + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + return try { + my $displayitem = Koha::DisplayItem->new_from_api( $c->req->json ); + $displayitem->store; + $c->res->headers->location( + $c->req->url->to_string . '/' . $displayitem->display_id . '/' . $displayitem->itemnumber ); + return $c->render( + status => 201, + openapi => $c->objects->to_api($displayitem), + ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 update + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $displayitem = Koha::DisplayItems->find( + { + display_item_id => $c->param('display_item_id'), + display_id => $c->param('display_id'), + itemnumber => $c->param('item_id') + } + ); + + return $c->render_resource_not_found("Display item") + unless $displayitem; + + return try { + $displayitem->set_from_api( $c->req->json ); + $displayitem->store(); + return $c->render( status => 200, openapi => $c->objects->to_api($displayitem), ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 delete + +=cut + +sub delete { + my $c = shift->openapi->valid_input or return; + + my $displayitem = Koha::DisplayItems->find( + { + display_item_id => $c->param('display_item_id'), + display_id => $c->param('display_id'), + itemnumber => $c->param('item_id') + } + ); + + return $c->render_resource_not_found("Display item") + unless $displayitem; + + return try { + $displayitem->delete; + return $c->render_resource_deleted; + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 list_public + +=cut + +sub list_public { + my $c = shift->openapi->valid_input or return; + + return try { + my $displayitems = $c->objects->search( Koha::DisplayItems->new ); + return $c->render( status => 200, openapi => $displayitems ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 get_public + +=cut + +sub get_public { + my $c = shift->openapi->valid_input or return; + + return try { + my $displayitem = Koha::DisplayItems->find( + { + display_item_id => $c->param('display_item_id'), + display_id => $c->param('display_id'), + itemnumber => $c->param('item_id') + } + ); + return $c->render_resource_not_found("Display item") + unless $displayitem; + + return $c->render( status => 200, openapi => $c->objects->to_api($displayitem), ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 batch_add + +Add multiple items to a display + +=cut + +sub batch_add { + my $c = shift->openapi->valid_input or return; + + return try { + my $body = $c->req->json; + + # Validate that display exists + my $display = Koha::Displays->find( $body->{display_id} ); + return $c->render_resource_not_found("Display") + unless $display; + + # Enqueue background job for batch processing + my $job_id = Koha::BackgroundJob::BatchAddDisplayItems->new->enqueue( + { + display_id => $body->{display_id}, + item_ids => $body->{item_ids}, + date_remove => $body->{date_remove} // undef, + } + ); + + return $c->render( + status => 202, + openapi => { + job_id => $job_id, + message => "Batch add operation queued" + } + ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 batch_delete + +Remove multiple items from displays + +=cut + +sub batch_delete { + my $c = shift->openapi->valid_input or return; + + return try { + my $body = $c->req->json; + + # Enqueue background job for batch processing + my $job_id = Koha::BackgroundJob::BatchDeleteDisplayItems->new->enqueue( + { + item_ids => $body->{item_ids}, + display_id => $body->{display_id} // undef, + } + ); + + return $c->render( + status => 202, + openapi => { + job_id => $job_id, + message => "Batch delete operation queued" + } + ); + } catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/Koha/REST/V1/Displays.pm b/Koha/REST/V1/Displays.pm new file mode 100644 index 00000000000..dc537825287 --- /dev/null +++ b/Koha/REST/V1/Displays.pm @@ -0,0 +1,250 @@ +package Koha::REST::V1::Displays; + +# 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::Display; +use Koha::Displays; +use Koha::DateUtils qw( dt_from_string ); + +use Try::Tiny qw( catch try ); + +=head1 API + +=head2 Methods + +=head3 config + +Return the configuration options needed for the Display Vue app + +=cut + +sub config { + my $c = shift->openapi->valid_input or return; + + my $patron = $c->stash('koha.user'); + + return $c->render( + status => 200, + openapi => { + settings => { + enabled => C4::Context->preference('UseDisplayModule'), + }, + }, + ); +} + +=head3 list + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + my $displays_set = Koha::Displays->new; + + my $active = $c->param('active'); + if ( defined $active && $active ) { + $displays_set = $displays_set->active; + } + + # Filter displays based on user's library permissions + my $patron = $c->stash('koha.user'); + if ($patron) { + my @restricted_branchcodes = $patron->libraries_where_can_edit_displays; + if (@restricted_branchcodes) { + + # User can only see displays from specific libraries + $displays_set = $displays_set->search( { 'me.display_branch' => { -in => \@restricted_branchcodes } } ); + } + + # If @restricted_branchcodes is empty, user has access to all displays + } + + my $displays = $c->objects->search($displays_set); + return $c->render( status => 200, openapi => $displays ); + } catch { + $c->unhandled_exception($_); + }; + +} + +=head3 get + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + return try { + my $display = Koha::Displays->find( $c->param('display_id') ); + return $c->render_resource_not_found("Display") + unless $display; + + # Check if user has permission to view this display + my $patron = $c->stash('koha.user'); + if ($patron) { + my @restricted_branchcodes = $patron->libraries_where_can_edit_displays; + if (@restricted_branchcodes) { + + # User can only see displays from specific libraries + unless ( grep { $_ eq $display->display_branch } @restricted_branchcodes ) { + return $c->render_resource_not_found("Display"); + } + } + + # If @restricted_branchcodes is empty, user has access to all displays + } + + return $c->render( status => 200, openapi => $c->objects->to_api($display), ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 add + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + return try { + my $body = $c->req->json; + + my $display_items = delete $body->{display_items} || []; + + my $display = Koha::Display->new_from_api($body)->store; + $display->display_items($display_items); + + $c->res->headers->location( $c->req->url->to_string . '/' . $display->display_id ); + return $c->render( + status => 201, + openapi => $c->objects->to_api($display), + ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 update + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $display = Koha::Displays->find( $c->param('display_id') ); + + return $c->render_resource_not_found("Display") + unless $display; + + return try { + my $body = $c->req->json; + + my $display_items = delete $body->{display_items} || []; + + $display->set_from_api($body)->store; + $display->display_items($display_items); + + return $c->render( status => 200, openapi => $c->objects->to_api($display), ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 delete + +=cut + +sub delete { + my $c = shift->openapi->valid_input or return; + + my $display = Koha::Displays->find( $c->param('display_id') ); + + return $c->render_resource_not_found("Display") + unless $display; + + return try { + $display->delete; + return $c->render_resource_deleted; + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 list_public + +=cut + +sub list_public { + my $c = shift->openapi->valid_input or return; + + return try { + my $displays_set = Koha::Displays->new; + + my $active = $c->param('active'); + if ( defined $active && $active ) { + $displays_set = $displays_set->active; + } else { + my $today = dt_from_string->truncate( to => 'day' ); + $displays_set = $displays_set->search( + { + -or => [ + { end_date => { '>=' => $today } }, + { end_date => undef } + ] + } + ); + } + + my $displays = $c->objects->search($displays_set); + return $c->render( status => 200, openapi => $displays ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 get_public + +=cut + +sub get_public { + my $c = shift->openapi->valid_input or return; + + return try { + my $display = Koha::Displays->find( $c->param('display_id') ); + + return $c->render_resource_not_found("Display") + unless $display; + + my $today = dt_from_string->truncate( to => 'day' )->ymd; + + if ( $display->end_date && $display->end_date < $today ) { + return $c->render_resource_not_found("Display"); + } + + return $c->render( status => 200, openapi => $c->objects->to_api($display), ); + } catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/api/v1/swagger/definitions/display.yaml b/api/v1/swagger/definitions/display.yaml new file mode 100644 index 00000000000..6f135d650ce --- /dev/null +++ b/api/v1/swagger/definitions/display.yaml @@ -0,0 +1,97 @@ +--- +type: object +properties: + display_id: + type: integer + description: internally assigned display identifier + readOnly: true + display_name: + description: display name + type: string + start_date: + description: display start date + type: + - string + - "null" + format: date + end_date: + description: display end date + type: + - string + - "null" + format: date + enabled: + description: determines whether the display is active + type: boolean + display_location: + description: shelving location for the display + type: + - string + - "null" + display_code: + description: collection code for the display + type: + - string + - "null" + display_branch: + description: home branch for items while on display + type: + - string + - "null" + display_holding_branch: + description: holding branch for items while on display + type: + - string + - "null" + display_itype: + description: item type for items while on display + type: + - string + - "null" + staff_note: + description: staff note for the display + type: + - string + - "null" + public_note: + description: public note for the display + type: + - string + - "null" + display_days: + description: default number of days items will remain on display + type: + - integer + - "null" + display_return_over: + description: should the item be removed from the display when it is returned + type: string + enum: + - "yes - any library" + - "yes - except at home library" + - "no" + default: "no" + display_items: + type: + - array + - "null" + description: The object representing the display items + library: + type: + - object + - "null" + description: The object representing the display library + item_type: + type: + - object + - "null" + description: The object representing the display item type + _strings: + type: + - object + - "null" +additionalProperties: false +required: + - display_name + - enabled + - display_return_over diff --git a/api/v1/swagger/definitions/display_config.yaml b/api/v1/swagger/definitions/display_config.yaml new file mode 100644 index 00000000000..535228aa01e --- /dev/null +++ b/api/v1/swagger/definitions/display_config.yaml @@ -0,0 +1,7 @@ +--- +type: object +properties: + settings: + type: object + description: List of sysprefs used for the Displays module +additionalProperties: false diff --git a/api/v1/swagger/definitions/displayitem.yaml b/api/v1/swagger/definitions/displayitem.yaml new file mode 100644 index 00000000000..2f75c59eca4 --- /dev/null +++ b/api/v1/swagger/definitions/displayitem.yaml @@ -0,0 +1,31 @@ +--- +type: object +properties: + display_item_id: + type: integer + description: primary key + display_id: + type: integer + description: foreign key to link to displays.display_id + itemnumber: + type: integer + description: items.itemnumber for the item on display + biblionumber: + type: integer + description: biblio.biblionumber for the bibliographic record on display + date_added: + description: the date the item was added to the display + type: + - string + - "null" + format: date + date_remove: + description: the date the item should be removed from the display + type: + - string + - "null" + format: date +additionalProperties: false +required: + - display_id + - itemnumber diff --git a/api/v1/swagger/definitions/item.yaml b/api/v1/swagger/definitions/item.yaml index 42dcd36e3e5..e0b7f3a4943 100644 --- a/api/v1/swagger/definitions/item.yaml +++ b/api/v1/swagger/definitions/item.yaml @@ -38,6 +38,11 @@ properties: - "null" description: Internal library id for the library the item belongs to maxLength: 10 + effective_home_library_id: + type: + - string + - "null" + description: Effective home library id - shows display branch if item is on an active display, otherwise regular home branch purchase_price: type: - number @@ -153,6 +158,11 @@ properties: - "null" description: Library that is currently in possession item maxLength: 10 + effective_holding_library_id: + type: + - string + - "null" + description: Effective holding library id - shows display holding branch if item is on an active display, otherwise regular holding branch timestamp: type: string format: date-time @@ -197,6 +207,11 @@ properties: - "null" description: Authorized value for the collection code associated with this item maxLength: 80 + effective_collection_code: + type: + - string + - "null" + description: Effective collection code - shows display collection code if item is on an active display, otherwise regular collection code materials_notes: type: - string @@ -223,6 +238,11 @@ properties: - string - "null" description: Effective itemtype defining the type for this item_id + effective_location: + type: + - string + - "null" + description: Effective location code - shows display location if item is on an active display, otherwise regular location extended_subfields: type: - string diff --git a/api/v1/swagger/paths/displayitems.yaml b/api/v1/swagger/paths/displayitems.yaml new file mode 100644 index 00000000000..5b41a6abb79 --- /dev/null +++ b/api/v1/swagger/paths/displayitems.yaml @@ -0,0 +1,395 @@ +--- +/display/items: + get: + x-mojo-to: DisplayItems#list + operationId: listDisplayItems + tags: + - displayitems + summary: List display items + produces: + - application/json + parameters: + - name: display_item_id + in: query + description: Filter by display item ID + required: false + type: integer + - name: display_id + in: query + description: Filter by display ID + required: false + type: integer + - name: itemnumber + in: query + description: Filter by item number + required: false + type: integer + - name: biblionumber + in: query + description: Filter by bibliographic record number + required: false + type: integer + - name: date_added + in: query + description: Filter by date added + required: false + type: string + format: date + - name: date_remove + in: query + description: Filter by date to remove + required: false + type: string + format: date + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/q_param" + - $ref: "../swagger.yaml#/parameters/q_body" + - $ref: "../swagger.yaml#/parameters/request_id_header" + responses: + "200": + description: A list of display items + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/displayitem" + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + 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: + displays: "*" + post: + x-mojo-to: DisplayItems#add + operationId: addDisplayItem + tags: + - displayitems + summary: Add display item + parameters: + - name: body + in: body + description: A JSON object containing information about the new display item + required: true + schema: + $ref: "../swagger.yaml#/definitions/displayitem" + produces: + - application/json + responses: + "201": + description: Display item added + schema: + $ref: "../swagger.yaml#/definitions/displayitem" + "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" + "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: + displays: add_items_to_display +"/display/items/{display_id}/{item_id}": + get: + x-mojo-to: DisplayItems#get + operationId: getDisplayItem + tags: + - displayitems + summary: Get display item + parameters: + - $ref: "../swagger.yaml#/parameters/display_id_pp" + - $ref: "../swagger.yaml#/parameters/item_id_pp" + produces: + - application/json + responses: + "200": + description: A display item + schema: + $ref: "../swagger.yaml#/definitions/displayitem" + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: Display 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: + displays: "*" + put: + x-mojo-to: DisplayItems#update + operationId: updateDisplayItem + tags: + - displayitems + summary: Update display item + parameters: + - $ref: "../swagger.yaml#/parameters/display_id_pp" + - $ref: "../swagger.yaml#/parameters/item_id_pp" + - name: body + in: body + description: A display item object + required: true + schema: + $ref: "../swagger.yaml#/definitions/displayitem" + produces: + - application/json + responses: + "200": + description: A display item + schema: + $ref: "../swagger.yaml#/definitions/displayitem" + "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: Display item not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: Internal error + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + displays: add_items_to_display + delete: + x-mojo-to: DisplayItems#delete + operationId: deleteDisplayItem + tags: + - displayitems + summary: Delete display item + parameters: + - $ref: "../swagger.yaml#/parameters/display_id_pp" + - $ref: "../swagger.yaml#/parameters/item_id_pp" + produces: + - application/json + responses: + "204": + description: Display item deleted + "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: Display item not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: Internal error + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + displays: remove_items_from_display +/display/items/batch: + post: + x-mojo-to: DisplayItems#batch_add + operationId: batchAddDisplayItems + tags: + - displayitems + summary: Add multiple items to a display + parameters: + - name: body + in: body + description: A JSON object containing display and item information + required: true + schema: + type: object + properties: + display_id: + description: ID of the display to add items to + type: integer + item_ids: + description: Array of item numbers to add to the display + type: array + items: + type: integer + minItems: 1 + date_remove: + description: Optional date when items should be removed from display + type: string + format: date + required: + - display_id + - item_ids + additionalProperties: false + produces: + - application/json + responses: + "202": + description: Batch operation queued + schema: + type: object + properties: + job_id: + type: integer + description: ID of the background job processing this request + message: + type: string + description: Confirmation message + additionalProperties: false + "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: Display not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: Internal server error + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + displays: add_items_to_display + delete: + x-mojo-to: DisplayItems#batch_delete + operationId: batchDeleteDisplayItems + tags: + - displayitems + summary: Remove multiple items from displays + parameters: + - name: body + in: body + description: A JSON object containing item information + required: true + schema: + type: object + properties: + item_ids: + description: Array of item numbers to remove from displays + type: array + items: + type: integer + minItems: 1 + display_id: + description: Optional display ID - if specified, only remove items from this display + type: integer + required: + - item_ids + additionalProperties: false + produces: + - application/json + responses: + "202": + description: Batch operation queued + schema: + type: object + properties: + job_id: + type: integer + description: ID of the background job processing this request + message: + type: string + description: Confirmation message + additionalProperties: false + "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" + "500": + description: Internal server error + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + displays: remove_items_from_display diff --git a/api/v1/swagger/paths/displays.yaml b/api/v1/swagger/paths/displays.yaml new file mode 100644 index 00000000000..c861062d876 --- /dev/null +++ b/api/v1/swagger/paths/displays.yaml @@ -0,0 +1,273 @@ +--- +/displays: + get: + x-mojo-to: Displays#list + operationId: listDisplays + tags: + - displays + summary: List displays + produces: + - application/json + parameters: + - name: display_name + in: query + description: Case insensitive search on display name + required: false + type: string + - name: enabled + in: query + description: Filter by enabled status + required: false + type: boolean + - name: active + in: query + description: Filter by active status (not expired, end_date >= today or null) + required: false + type: boolean + - name: display_branch + in: query + description: Filter by display branch + required: false + type: string + - name: display_type + in: query + description: Filter by display type + required: false + type: string + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/q_param" + - $ref: "../swagger.yaml#/parameters/q_body" + - $ref: "../swagger.yaml#/parameters/request_id_header" + - name: x-koha-embed + in: header + required: false + description: Embed list sent as a request header + type: array + items: + type: string + enum: + - display_items + - library + - item_type + - +strings + collectionFormat: csv + responses: + "200": + description: A list of displays + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/display" + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + 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: + displays: "*" + post: + x-mojo-to: Displays#add + operationId: addDisplay + tags: + - displays + summary: Add display + parameters: + - name: body + in: body + description: A JSON object containing information about the new display + required: true + schema: + $ref: "../swagger.yaml#/definitions/display" + produces: + - application/json + responses: + "201": + description: Display added + schema: + $ref: "../swagger.yaml#/definitions/display" + "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" + "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: + displays: add_display +"/displays/{display_id}": + get: + x-mojo-to: Displays#get + operationId: getDisplay + tags: + - displays + summary: Get display + parameters: + - $ref: "../swagger.yaml#/parameters/display_id_pp" + - name: x-koha-embed + in: header + required: false + description: Embed list sent as a request header + type: array + items: + type: string + enum: + - display_items + - library + - item_type + - +strings + collectionFormat: csv + produces: + - application/json + responses: + "200": + description: A display + schema: + $ref: "../swagger.yaml#/definitions/display" + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: Display 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: + displays: "*" + put: + x-mojo-to: Displays#update + operationId: updateDisplay + tags: + - displays + summary: Update display + parameters: + - $ref: "../swagger.yaml#/parameters/display_id_pp" + - name: body + in: body + description: A display object + required: true + schema: + $ref: "../swagger.yaml#/definitions/display" + produces: + - application/json + responses: + "200": + description: A display + schema: + $ref: "../swagger.yaml#/definitions/display" + "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: Display not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: Internal error + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + displays: edit_display + delete: + x-mojo-to: Displays#delete + operationId: deleteDisplay + tags: + - displays + summary: Delete display + parameters: + - $ref: "../swagger.yaml#/parameters/display_id_pp" + produces: + - application/json + responses: + "204": + description: Display deleted + "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: Display not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: Internal error + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + displays: delete_display diff --git a/api/v1/swagger/paths/displays_config.yaml b/api/v1/swagger/paths/displays_config.yaml new file mode 100644 index 00000000000..b2ebbea3da4 --- /dev/null +++ b/api/v1/swagger/paths/displays_config.yaml @@ -0,0 +1,38 @@ +--- +/displays/config: + get: + x-mojo-to: Displays#config + operationId: getDisplaysConfig + description: This resource returns a list of options needed for the Displays Vue app. EXPERIMENTAL - DO NOT RELY on this, it is subject to change! + summary: get the Displays Config + tags: + - displays + produces: + - application/json + responses: + 200: + description: The Displays module config + schema: + $ref: "../swagger.yaml#/definitions/display_config" + 400: + description: Bad request + 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: + displays: "*" diff --git a/api/v1/swagger/paths/public_displayitems.yaml b/api/v1/swagger/paths/public_displayitems.yaml new file mode 100644 index 00000000000..f31a8ef56be --- /dev/null +++ b/api/v1/swagger/paths/public_displayitems.yaml @@ -0,0 +1,94 @@ +--- +"/public/display/items": + get: + x-mojo-to: DisplayItems#list_public + operationId: listDisplayItemsPublic + tags: + - displayitems + summary: List display items (public) + produces: + - application/json + parameters: + - name: display_id + in: query + description: Filter by display ID + required: false + type: integer + - name: itemnumber + in: query + description: Filter by item number + required: false + type: integer + - name: biblionumber + in: query + description: Filter by bibliographic record number + required: false + type: integer + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/q_param" + - $ref: "../swagger.yaml#/parameters/q_body" + - $ref: "../swagger.yaml#/parameters/request_id_header" + responses: + "200": + description: A list of display items + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/displayitem" + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + 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" +"/public/display/items/{display_id}/{item_id}": + get: + x-mojo-to: DisplayItems#get_public + operationId: getDisplayItemPublic + tags: + - displayitems + summary: Get display item (public) + parameters: + - $ref: "../swagger.yaml#/parameters/display_id_pp" + - $ref: "../swagger.yaml#/parameters/item_id_pp" + produces: + - application/json + responses: + "200": + description: A display item + schema: + $ref: "../swagger.yaml#/definitions/displayitem" + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: Display 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" diff --git a/api/v1/swagger/paths/public_displays.yaml b/api/v1/swagger/paths/public_displays.yaml new file mode 100644 index 00000000000..35bf8640644 --- /dev/null +++ b/api/v1/swagger/paths/public_displays.yaml @@ -0,0 +1,124 @@ +--- +"/public/displays": + get: + x-mojo-to: Displays#list_public + operationId: listDisplaysPublic + tags: + - displays + summary: List displays (public) + produces: + - application/json + parameters: + - name: active + in: query + description: Filter by active status (enabled and within start/end date range) + required: false + type: boolean + - name: enabled + in: query + description: Filter by enabled status + required: false + type: boolean + - name: display_branch + in: query + description: Filter by display branch + required: false + type: string + - name: display_type + in: query + description: Filter by display type + required: false + type: string + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/q_param" + - $ref: "../swagger.yaml#/parameters/q_body" + - $ref: "../swagger.yaml#/parameters/request_id_header" + - name: x-koha-embed + in: header + required: false + description: Embed list sent as a request header + type: array + items: + type: string + enum: + - display_items + - library + - item_type + - +strings + collectionFormat: csv + responses: + "200": + description: A list of displays + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/display" + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + 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" +"/public/displays/{display_id}": + get: + x-mojo-to: Displays#get_public + operationId: getDisplayPublic + tags: + - displays + summary: Get display (public) + parameters: + - $ref: "../swagger.yaml#/parameters/display_id_pp" + - name: x-koha-embed + in: header + required: false + description: Embed list sent as a request header + type: array + items: + type: string + enum: + - display_items + - library + - item_type + - +strings + collectionFormat: csv + produces: + - application/json + responses: + "200": + description: A display + schema: + $ref: "../swagger.yaml#/definitions/display" + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: Display 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" diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index dcb0a3cc66e..4758daefd78 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -42,6 +42,12 @@ definitions: $ref: ./definitions/circ-rule-kind.yaml city: $ref: ./definitions/city.yaml + display_config: + $ref: ./definitions/display_config.yaml + display: + $ref: ./definitions/display.yaml + displayitem: + $ref: ./definitions/displayitem.yaml credit: $ref: ./definitions/credit.yaml debit: @@ -325,6 +331,18 @@ paths: $ref: ./paths/cities.yaml#/~1cities "/cities/{city_id}": $ref: "./paths/cities.yaml#/~1cities~1{city_id}" + /displays/config: + $ref: ./paths/displays_config.yaml#/~1displays~1config + /displays: + $ref: ./paths/displays.yaml#/~1displays + "/displays/{display_id}": + $ref: "./paths/displays.yaml#/~1displays~1{display_id}" + /display/items: + $ref: ./paths/displayitems.yaml#/~1display~1items + /display/items/batch: + $ref: ./paths/displayitems.yaml#/~1display~1items~1batch + /display/items/{display_id}/{item_id}: + $ref: ./paths/displayitems.yaml#/~1display~1items~1{display_id}~1{item_id} "/clubs/{club_id}/holds": $ref: "./paths/clubs.yaml#/~1clubs~1{club_id}~1holds" /config/smtp_servers: @@ -551,6 +569,14 @@ paths: $ref: "./paths/biblios.yaml#/~1public~1biblios~1{biblio_id}" "/public/checkouts/availability": $ref: ./paths/checkouts.yaml#/~1public~1checkouts~1availability + "/public/display/items": + $ref: "./paths/public_displayitems.yaml#/~1public~1display~1items" + "/public/display/items/{display_id}/{item_id}": + $ref: "./paths/public_displayitems.yaml#/~1public~1display~1items~1{display_id}~1{item_id}" + "/public/displays": + $ref: "./paths/public_displays.yaml#/~1public~1displays" + "/public/displays/{display_id}": + $ref: "./paths/public_displays.yaml#/~1public~1displays~1{display_id}" "/public/items": $ref: "./paths/items.yaml#/~1public~1items" "/public/biblios/{biblio_id}/items": @@ -745,6 +771,12 @@ parameters: name: city_id required: true type: integer + display_id_pp: + description: Display internal identifier + in: path + name: display_id + required: true + type: integer club_id_pp: description: Internal club identifier in: path @@ -1240,6 +1272,12 @@ tags: - description: "Manage cities\n" name: cities x-displayName: Cities + - description: "Manage displays\n" + name: displays + x-displayName: Displays + - description: "Manage display items\n" + name: displayitems + x-displayName: Display items - description: "Manage patron clubs\n" name: clubs x-displayName: Clubs -- 2.50.1 (Apple Git-155)