diff --git a/Koha/REST/V1/Patrons.pm b/Koha/REST/V1/Patrons.pm index a6f9fb6657..2531eac7aa 100644 --- a/Koha/REST/V1/Patrons.pm +++ b/Koha/REST/V1/Patrons.pm @@ -503,4 +503,26 @@ sub guarantors_can_see_checkouts { }; } +=head3 overdues_count + +Controller function that returns the count of overdue checkouts for a patron. + +=cut + +sub overdues_count { + my $c = shift->openapi->valid_input or return; + + return try { + my $patron = Koha::Patrons->find( $c->param('patron_id') ); + return $c->render_resource_not_found("Patron") unless $patron; + + return $c->render( + status => 200, + openapi => $patron->overdues->count, + ); + } catch { + $c->unhandled_exception($_); + }; +} + 1; diff --git a/api/v1/swagger/paths/patrons.yaml b/api/v1/swagger/paths/patrons.yaml index 3621453c70..6c05c9ac4d 100644 --- a/api/v1/swagger/paths/patrons.yaml +++ b/api/v1/swagger/paths/patrons.yaml @@ -740,3 +740,43 @@ x-koha-authorization: permissions: ill: "1" + +"/patrons/{patron_id}/overdues_count": + get: + x-mojo-to: Patrons#overdues_count + operationId: getPatronOverduesCount + tags: + - patrons + summary: Get count of overdue checkouts for a patron + parameters: + - $ref: "../swagger.yaml#/parameters/patron_id_pp" + produces: + - application/json + responses: + "200": + description: Overdue count + schema: + type: integer + "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: Patron not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: Internal server error + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + - borrowers: "list_borrowers" diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index b2497735f7..7beacae0f9 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -549,6 +549,8 @@ paths: $ref: ./paths/patrons.yaml#/~1patrons "/patrons/{patron_id}": $ref: "./paths/patrons.yaml#/~1patrons~1{patron_id}" + "/patrons/{patron_id}/overdues_count": + $ref: "./paths/patrons.yaml#/~1patrons~1{patron_id}~1overdues_count" "/patrons/{patron_id}/account": $ref: "./paths/patrons_account.yaml#/~1patrons~1{patron_id}~1account" "/patrons/{patron_id}/account/credits": @@ -1515,6 +1517,9 @@ tags: - description: "Manage search field mappings" name: search_mappings x-displayName: Search mappings + - description: "Search patrons via Elasticsearch" + name: search + x-displayName: Search - description: "Manage SIP2 accounts" name: sip2_accounts x-displayName: SIP2 Accounts diff --git a/t/db_dependent/api/v1/patrons_overdues_count.t b/t/db_dependent/api/v1/patrons_overdues_count.t new file mode 100755 index 0000000000..7dd009808e --- /dev/null +++ b/t/db_dependent/api/v1/patrons_overdues_count.t @@ -0,0 +1,94 @@ +#!/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::NoWarnings; +use Test::More tests => 3; +use Test::Mojo; + +use t::lib::TestBuilder; +use t::lib::Mocks; + +use Koha::Checkouts; +use Koha::Database; +use Koha::DateUtils qw( dt_from_string ); + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new; + +t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + +my $t = Test::Mojo->new('Koha::REST::V1'); + +subtest 'overdues_count unauthorized' => sub { + plan tests => 2; + + $schema->storage->txn_begin; + + my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); + + $t->get_ok( "/api/v1/patrons/" . $patron->borrowernumber . "/overdues_count" )->status_is(401); + + $schema->storage->txn_rollback; +}; + +subtest 'overdues_count' => sub { + plan tests => 8; + + $schema->storage->txn_begin; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**4 } # borrowers flag + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); + + # No checkouts - 0 overdues + $t->get_ok( "//$userid:$password\@/api/v1/patrons/" . $patron->borrowernumber . "/overdues_count" ) + ->status_is(200) + ->json_is(0); + + # Add an overdue checkout + my $item = $builder->build_sample_item(); + $builder->build( + { + source => 'Issue', + value => { + borrowernumber => $patron->borrowernumber, + itemnumber => $item->itemnumber, + date_due => '2020-01-01 00:00:00', + branchcode => $patron->branchcode, + } + } + ); + + $t->get_ok( "//$userid:$password\@/api/v1/patrons/" . $patron->borrowernumber . "/overdues_count" ) + ->status_is(200) + ->json_is(1); + + # Non-existent patron + $t->get_ok("//$userid:$password\@/api/v1/patrons/999999999/overdues_count")->status_is(404); + + $schema->storage->txn_rollback; +};