From 1b47d349a66d3b51a5646e18e63bb8329c493f34 Mon Sep 17 00:00:00 2001 From: Lari Taskula Date: Mon, 22 Aug 2016 17:35:44 +0300 Subject: [PATCH] Bug 17003: Add API route to get checkout's renewability GET /checkouts/{checkout_id}/renewability (renewability status) Response: - 200: renewability { renewable: true/false, error: "error message" } To test: 1. Login to Koha 2. Checkout something for yourself 3. Make GET request to http://yourlibrary/api/v1/checkouts/YYY/renewability where YYY is checkout_id of your checkout. 4. Observe returned data. If not renewable, an error should also be presented. 5. Run t/db_dependent/api/v1/checkouts.t Signed-off-by: Jiri Kozlovsky I've signed-off this because I've made no major change and the funcionality remains the same. Changes made: 1. Added x-koha-authorization to the paths definition 2. Changed checkout_id parameter definition to the reference 3. Moved error raised when syspref OpacRenewalAllowed disabled in front of possible error "Checkout doesn't exist" (don't give users hope to renew it when not found, but tell them renewal is not allowed at all instead) --- Koha/REST/V1/Checkout.pm | 35 ++++++++++++++++++++++++++++ api/v1/swagger/definitions.json | 3 +++ api/v1/swagger/definitions/renewability.json | 13 +++++++++++ api/v1/swagger/paths.json | 3 +++ api/v1/swagger/paths/checkouts.json | 31 ++++++++++++++++++++++++ t/db_dependent/api/v1/checkouts.t | 20 +++++++++++++++- 6 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 api/v1/swagger/definitions/renewability.json diff --git a/Koha/REST/V1/Checkout.pm b/Koha/REST/V1/Checkout.pm index ac5dea5..ee75bac 100644 --- a/Koha/REST/V1/Checkout.pm +++ b/Koha/REST/V1/Checkout.pm @@ -18,6 +18,7 @@ package Koha::REST::V1::Checkout; use Modern::Perl; use Mojo::Base 'Mojolicious::Controller'; +use Mojo::JSON; use C4::Auth qw( haspermission ); use C4::Context; @@ -86,4 +87,38 @@ sub renew { return $c->$cb($checkout->unblessed, 200); } +sub renewability { + my ($c, $args, $cb) = @_; + + my $user = $c->stash('koha.user'); + + my $OpacRenewalAllowed; + if ($user->borrowernumber == $borrowernumber) { + $OpacRenewalAllowed = C4::Context->preference('OpacRenewalAllowed'); + } + + unless ($user && ($OpacRenewalAllowed + || haspermission($user->userid, { circulate => "circulate_remaining_permissions" }))) { + return $c->$cb({error => "You don't have the required permission"}, 403); + } + + my $checkout_id = $args->{checkout_id}; + my $checkout = Koha::Issues->find($checkout_id); + + if (!$checkout) { + return $c->$cb({ + error => "Checkout doesn't exist" + }, 404); + } + + my $borrowernumber = $checkout->borrowernumber; + my $itemnumber = $checkout->itemnumber; + + my ($can_renew, $error) = C4::Circulation::CanBookBeRenewed( + $borrowernumber, $itemnumber); + + return $c->$cb({ renewable => Mojo::JSON->true, error => undef }, 200) if $can_renew; + return $c->$cb({ renewable => Mojo::JSON->false, error => $error }, 200); +} + 1; diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json index 6a77132..8dba286 100644 --- a/api/v1/swagger/definitions.json +++ b/api/v1/swagger/definitions.json @@ -19,5 +19,8 @@ }, "error": { "$ref": "definitions/error.json" + }, + "renewability": { + "$ref": "definitions/renewability.json" } } diff --git a/api/v1/swagger/definitions/renewability.json b/api/v1/swagger/definitions/renewability.json new file mode 100644 index 0000000..654691e --- /dev/null +++ b/api/v1/swagger/definitions/renewability.json @@ -0,0 +1,13 @@ +{ + "type": "object", + "properties": { + "renewable": { + "type": "boolean", + "description": "Renewability status; true = renewable, false = not renewable" + }, + "error": { + "type": ["string", "null"], + "description": "Description on false renewability." + } + } +} diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json index d8879f6..5cac283 100644 --- a/api/v1/swagger/paths.json +++ b/api/v1/swagger/paths.json @@ -17,6 +17,9 @@ "/checkouts/{checkout_id}": { "$ref": "paths/checkouts.json#/~1checkouts~1{checkout_id}" }, + "/checkouts/{checkout_id}/renewability": { + "$ref": "paths/checkouts.json#/~1checkouts~1{checkout_id}~1renewability" + }, "/patrons": { "$ref": "paths/patrons.json#/~1patrons" }, diff --git a/api/v1/swagger/paths/checkouts.json b/api/v1/swagger/paths/checkouts.json index e49a33e..26f7dc6 100644 --- a/api/v1/swagger/paths/checkouts.json +++ b/api/v1/swagger/paths/checkouts.json @@ -93,5 +93,36 @@ } } } + }, + "/checkouts/{checkout_id}/renewability": { + "get": { + "operationId": "renewabilityCheckout", + "tags": ["patrons", "checkouts"], + "parameters": [{ + "$ref": "../parameters.json#/checkoutIdPathParam" + }], + "produces": ["application/json"], + "responses": { + "200": { + "description": "Checkout renewability", + "schema": { "$ref": "../definitions.json#/renewability" } + }, + "403": { + "description": "Forbidden", + "schema": { "$ref": "../definitions.json#/error" } + }, + "404": { + "description": "Checkout not found", + "schema": { "$ref": "../definitions.json#/error" } + } + }, + "x-koha-authorization": { + "allow-owner": true, + "allow-guarantor": true, + "permissions": { + "circulate": "circulate_remaining_permissions" + } + } + } } } diff --git a/t/db_dependent/api/v1/checkouts.t b/t/db_dependent/api/v1/checkouts.t index 5298d7f..d46deb5 100644 --- a/t/db_dependent/api/v1/checkouts.t +++ b/t/db_dependent/api/v1/checkouts.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 57; +use Test::More tests => 66; use Test::MockModule; use Test::Mojo; use t::lib::Mocks; @@ -189,7 +189,19 @@ $t->request_ok($tx) ->status_is(403) ->json_is({ error => "Opac Renewal not allowed" }); +$tx = $t->ua->build_tx(GET => "/api/v1/checkouts/" . $issue2->issue_id . "/renewability"); +$tx->req->cookies({name => 'CGISESSID', value => $patron_session->id}); +$t->request_ok($tx) + ->status_is(403) + ->json_is({ error => "You don't have the required permission" }); + t::lib::Mocks::mock_preference( "OpacRenewalAllowed", 1 ); +$tx = $t->ua->build_tx(GET => "/api/v1/checkouts/" . $issue2->issue_id . "/renewability"); +$tx->req->cookies({name => 'CGISESSID', value => $patron_session->id}); +$t->request_ok($tx) + ->status_is(200) + ->json_is({ renewable => Mojo::JSON->true, error => undef }); + $tx = $t->ua->build_tx(PUT => "/api/v1/checkouts/" . $issue2->issue_id); $tx->req->cookies({name => 'CGISESSID', value => $patron_session->id}); $t->request_ok($tx) @@ -202,6 +214,12 @@ $t->request_ok($tx) ->status_is(403) ->json_is({ error => 'Renewal not authorized (too_many)' }); +$tx = $t->ua->build_tx(GET => "/api/v1/checkouts/" . $issue2->issue_id . "/renewability"); +$tx->req->cookies({name => 'CGISESSID', value => $patron_session->id}); +$t->request_ok($tx) + ->status_is(200) + ->json_is({ renewable => Mojo::JSON->false, error => 'too_many' }); + sub create_biblio { my ($title) = @_; -- 2.1.4