From 6b19cf4d84378ad10655fa957d8ea9ed4502b915 Mon Sep 17 00:00:00 2001 From: Aleisha Amohia Date: Tue, 13 Feb 2024 01:12:31 +0000 Subject: [PATCH] Bug 36075: Add REST API endpoint to list recalls This enhancement adds a REST API endpoint to list recalls and run search queries on recalls /api/v1/recalls /api/v1/recalls?patron_id=X To test: 1. Log in to the staff interface as your superlibrarian self (Patron A) 2. Go to Koha Administration -> Global system preferences. Enable the UseRecalls system preference 3. Set the relevant recalls circulation and fines rules 4. Search for an item (Item A) 5. Check out Item A to yourself (Patron A) 6. Log in to the OPAC as Patron B 7. Search for Item A and request a recall 8. Test the API returns the recall: https://your-opac-url/api/v1/recalls 9. Test other search parameters: https://your-opac-url/api/v1/recalls?patron_id=PATRON_B_NUMBER 10. Confirm you are able to view a list of Patron B's recalls 11. Confirm tests pass: t/db_dependent/api/v1/recalls.t Sponsored-by: Auckland University of Technology --- Koha/REST/V1/Recalls.pm | 46 +++++++++++++ api/v1/swagger/paths/recalls.yaml | 111 ++++++++++++++++++++++++++++++ api/v1/swagger/swagger.yaml | 2 + t/db_dependent/api/v1/recalls.t | 66 ++++++++++++++++++ 4 files changed, 225 insertions(+) create mode 100644 Koha/REST/V1/Recalls.pm create mode 100644 api/v1/swagger/paths/recalls.yaml create mode 100755 t/db_dependent/api/v1/recalls.t diff --git a/Koha/REST/V1/Recalls.pm b/Koha/REST/V1/Recalls.pm new file mode 100644 index 00000000000..6716918fb1c --- /dev/null +++ b/Koha/REST/V1/Recalls.pm @@ -0,0 +1,46 @@ +package Koha::REST::V1::Recalls; + +# 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 Mojo::JSON; + +use Koha::Recalls; + +=head1 API + +=head2 Methods + +=head3 list + +Method that handles listing Koha::Recall objects + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + my $recalls = $c->objects->search( Koha::Recalls->new ); + return $c->render( status => 200, openapi => $recalls ); + } + catch { + $c->unhandled_exception($_); + }; +} diff --git a/api/v1/swagger/paths/recalls.yaml b/api/v1/swagger/paths/recalls.yaml new file mode 100644 index 00000000000..af1fd3de2ea --- /dev/null +++ b/api/v1/swagger/paths/recalls.yaml @@ -0,0 +1,111 @@ +--- +/recalls: + get: + x-mojo-to: Recalls#list + operationId: listRecalls + tags: + - recalls + summary: List recalls + parameters: + - name: recall_id + in: query + description: Internal recall identifier + type: integer + - name: patron_id + in: query + description: Internal patron identifier + type: integer + - name: created_date + in: query + description: The date the recall was requested + type: string + - name: biblio_id + in: query + description: Internal biblio identifier + type: integer + - name: pickup_library_id + in: query + description: Internal library identifier for the pickup library + type: string + - name: waiting_date + in: query + description: The date the item was marked as waiting for the patron at the library + type: string + - name: expiration_date + in: query + description: The date the recall expires + type: string + - name: completed_date + in: query + description: The date the recall was fulfilled + type: string + - name: notes + in: query + description: Notes related to this recall + type: string + - name: priority + in: query + description: Where in the queue the patron sits (not yet implemented) + type: integer + - name: status + in: query + description: Status of the recall + type: string + - name: timestamp + in: query + description: Timestamp for the latest recall update + type: string + - name: item_id + in: query + description: Internal item identifier + type: integer + - name: completed + in: query + description: Controls if the recall is fulfilled + type: boolean + - name: item_level + in: query + description: If the recall is requested at item level + type: boolean + - $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" + produces: + - application/json + responses: + "200": + description: The patron's recalls + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/recall" + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: Patron 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: + recalls: manage_recalls diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index 563575784a3..3d6dcc9b84a 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -489,6 +489,8 @@ paths: $ref: ./paths/quotes.yaml#/~1quotes "/quotes/{quote_id}": $ref: "./paths/quotes.yaml#/~1quotes~1{quote_id}" + /recalls: + $ref: ./paths/recalls.yaml#/~1recalls /return_claims: $ref: ./paths/return_claims.yaml#/~1return_claims "/return_claims/{claim_id}": diff --git a/t/db_dependent/api/v1/recalls.t b/t/db_dependent/api/v1/recalls.t new file mode 100755 index 00000000000..7ae87ee7549 --- /dev/null +++ b/t/db_dependent/api/v1/recalls.t @@ -0,0 +1,66 @@ +#!/usr/bin/env perl + +# 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 Test::More tests => 1; +use Test::Mojo; + +use t::lib::TestBuilder; +use t::lib::Mocks; + +use Koha::Database; + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new(); + +my $t = Test::Mojo->new('Koha::REST::V1'); + +t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + +subtest 'list() tests' => sub { + + plan tests => 8; + + $schema->storage->txn_begin; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**27 } # recalls flag == 27 + } + ); + my $password = 'thePassword123'; + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $patron->userid; + + $t->get_ok( "//$userid:$password@/api/v1/recalls" )->status_is( 200, 'SWAGGER3.2.2' ) + ->json_is( [] ); + + my $recall_1 = $builder->build_object( { class => 'Koha::Recalls', value => { patron_id => $patron->id } } ); + my $recall_2 = $builder->build_object( { class => 'Koha::Recalls', value => { patron_id => $patron->id, completed => 1 } } ); + + $t->get_ok( "//$userid:$password@/api/v1/recalls?patron_id=" . $patron->id ) + ->status_is( 200, 'SWAGGER3.2.2' ) + ->json_is( '' => [ $recall_1->to_api, $recall_2->to_api ], 'Recalls retrieved' ); + + $t->get_ok( "//$userid:$password@/api/v1/recalls?patron_id=" . $patron->id . "&completed=false" ) + ->status_is( 200, 'SWAGGER3.2.2' ) + ->json_is( '' => [ $recall_1->to_api ], 'Current recalls retrieved' ); + + $schema->storage->txn_rollback; +}; -- 2.30.2