From 966f535c71d4835b22b9d8f88f0140fa4fd9c094 Mon Sep 17 00:00:00 2001 From: Tomas Cohen Arazi Date: Mon, 1 Apr 2024 20:24:35 +0000 Subject: [PATCH] Bug 36480: Add GET /libraries/:library_id/desks This patch adds the mentioned endpoint. For it, it does: * Add Koha::Desk->to_api_mapping * Add desk.yaml with the correct data structure for desks * Add the route to the spec * Add tests Note: Lucas and I had doubts about the right return value for when the feature is disabled. I opted for returning 404 with a message telling the feature is disabled. This can be discussed. To test: 1. Apply this patches 2. Run: $ ktd k$ qa => SUCCESS: All green, all tests pass! 3. Play with this using Postman. 4. Sign off :-D --- Koha/Desk.pm | 16 ++++++++++- Koha/REST/V1/Libraries.pm | 31 ++++++++++++++++++++ api/v1/swagger/definitions/desk.yaml | 19 ++++++++++++ api/v1/swagger/paths/libraries.yaml | 42 +++++++++++++++++++++++++++ api/v1/swagger/swagger.yaml | 7 +++++ t/db_dependent/api/v1/libraries.t | 43 +++++++++++++++++++++++++++- 6 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 api/v1/swagger/definitions/desk.yaml diff --git a/Koha/Desk.pm b/Koha/Desk.pm index b92ec93e403..56e627551c9 100644 --- a/Koha/Desk.pm +++ b/Koha/Desk.pm @@ -29,10 +29,24 @@ Koha::Desk - Koha Desk Object class =head1 API -=head2 Class Methods +=head2 Class methods + +=head3 to_api_mapping + +This method returns the mapping for representing a Koha::Desk object +on the API. =cut +sub to_api_mapping { + return { + branchcode => 'library_id', + desk_name => 'name', + }; +} + +=head2 Internal methods + =head3 _type =cut diff --git a/Koha/REST/V1/Libraries.pm b/Koha/REST/V1/Libraries.pm index 55aa426974d..7431db31afe 100644 --- a/Koha/REST/V1/Libraries.pm +++ b/Koha/REST/V1/Libraries.pm @@ -169,4 +169,35 @@ sub delete { }; } +=head3 list_desks + +Controller function that handles retrieving the library's desks + +=cut + +sub list_desks { + my $c = shift->openapi->valid_input or return; + + return $c->render( status => 404, openapi => { error => "Feature disabled" } ) + unless C4::Context->preference('UseCirculationDesks'); + + return try { + my $library = Koha::Libraries->find( $c->param('library_id') ); + + unless ($library) { + return $c->render( + status => 404, + openapi => { error => "Library not found" } + ); + } + + return $c->render( + status => 200, + openapi => $c->objects->to_api( $library->desks ) + ); + } catch { + $c->unhandled_exception($_); + }; +} + 1; diff --git a/api/v1/swagger/definitions/desk.yaml b/api/v1/swagger/definitions/desk.yaml new file mode 100644 index 00000000000..c3e691a46a2 --- /dev/null +++ b/api/v1/swagger/definitions/desk.yaml @@ -0,0 +1,19 @@ +--- +type: object +properties: + desk_id: + type: integer + description: Internal desk identifier + name: + type: string + description: The desk display name + library_id: + type: string + description: Internally assigned library identifier + maxLength: 10 + minLength: 1 +additionalProperties: false +required: + - desk_id + - name + - library_id diff --git a/api/v1/swagger/paths/libraries.yaml b/api/v1/swagger/paths/libraries.yaml index af452c59072..fb53f637f1c 100644 --- a/api/v1/swagger/paths/libraries.yaml +++ b/api/v1/swagger/paths/libraries.yaml @@ -304,6 +304,48 @@ x-koha-authorization: permissions: parameters: manage_libraries +"/libraries/{library_id}/desks": + get: + x-mojo-to: Libraries#list_desks + operationId: listLibraryDesks + tags: + - desks + summary: List the library's desks + parameters: + - $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: A list of desks for the library + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/desk" + 404: + description: Resource 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 /public/libraries: get: x-mojo-to: Libraries#list diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index 8b80908dcd1..ade6aa2b366 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -38,6 +38,8 @@ definitions: $ref: ./definitions/credit.yaml debit: $ref: ./definitions/debit.yaml + desk: + $ref: ./definitions/desk.yaml edifact_file: $ref: ./definitions/edifact_file.yaml erm_config: @@ -407,6 +409,8 @@ paths: $ref: ./paths/libraries.yaml#/~1libraries "/libraries/{library_id}": $ref: "./paths/libraries.yaml#/~1libraries~1{library_id}" + "/libraries/{library_id}/desks": + $ref: "./paths/libraries.yaml#/~1libraries~1{library_id}~1desks" "/oauth/login/{provider_code}/{interface}": $ref: ./paths/oauth.yaml#/~1oauth~1login~1{provider_code}~1{interface} /oauth/token: @@ -1036,6 +1040,9 @@ tags: - description: "Manage patron clubs\n" name: clubs x-displayName: Clubs + - description: "Manage circulation desks\n" + name: desks + x-displayName: Circulation desks - description: "Manage ERM agreements\n" name: erm_agreements x-displayName: ERM agreements diff --git a/t/db_dependent/api/v1/libraries.t b/t/db_dependent/api/v1/libraries.t index 89100a18bd3..02f28e034d4 100755 --- a/t/db_dependent/api/v1/libraries.t +++ b/t/db_dependent/api/v1/libraries.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 5; +use Test::More tests => 6; use Test::Mojo; use Test::Warn; @@ -315,3 +315,44 @@ subtest 'delete() tests' => sub { $schema->storage->txn_rollback; }; + +subtest 'list_desks() tests' => sub { + + plan tests => 11; + + $schema->storage->txn_begin; + + my $library = $builder->build_object( { class => 'Koha::Libraries' } ); + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 4 } + } + ); + my $password = 'thePassword123'; + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $patron->userid; + + t::lib::Mocks::mock_preference( 'UseCirculationDesks', 0 ); + + $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/desks" )->status_is(404) + ->json_is( '/error' => q{Feature disabled} ); + + my $non_existent_code = $library->branchcode; + $library->delete; + + t::lib::Mocks::mock_preference( 'UseCirculationDesks', 1 ); + + $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $non_existent_code . "/desks" )->status_is(404) + ->json_is( '/error' => 'Library not found' ); + + my $desk_1 = $builder->build_object( { class => 'Koha::Desks', value => { branchcode => $library->id } } ); + my $desk_2 = $builder->build_object( { class => 'Koha::Desks', value => { branchcode => $library->id } } ); + + my $res = $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode . "/desks" )->status_is(200) + ->json_is( '/0/desk_id' => $desk_1->id )->json_is( '/1/desk_id' => $desk_2->id )->tx->res->json; + + is( scalar @{$res}, 2 ); + + $schema->storage->txn_rollback; +}; -- 2.44.0