Bugzilla – Attachment 61991 Details for
Bug 18407
REST API: Include renewability information on checkouts
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 18407: REST API: Add expanded checkout information
Bug-18407-REST-API-Add-expanded-checkout-informati.patch (text/plain), 13.65 KB, created by
Lari Taskula
on 2017-04-10 09:31:42 UTC
(
hide
)
Description:
Bug 18407: REST API: Add expanded checkout information
Filename:
MIME Type:
Creator:
Lari Taskula
Created:
2017-04-10 09:31:42 UTC
Size:
13.65 KB
patch
obsolete
>From fdfa0a58ae3669c1a9dd9a6c9ac486ccdcd0f401 Mon Sep 17 00:00:00 2001 >From: Lari Taskula <lari.taskula@jns.fi> >Date: Thu, 6 Apr 2017 10:16:58 +0000 >Subject: [PATCH] Bug 18407: REST API: Add expanded checkout information > >GET /api/v1/checkouts/expanded?borrowernumber=1337 > >This endpoint includes basic checkout information as well as additionally >information on renewability. > >To test: >1. prove t/db_dependent/api/v1/checkoutsexpanded.t >--- > Koha/REST/V1/Checkout.pm | 65 +++++++-- > api/v1/swagger/definitions.json | 3 + > api/v1/swagger/definitions/checkoutexpanded.json | 16 +++ > api/v1/swagger/paths.json | 3 + > api/v1/swagger/paths/checkouts.json | 57 ++++++++ > t/db_dependent/api/v1/checkoutsexpanded.t | 174 +++++++++++++++++++++++ > 6 files changed, 309 insertions(+), 9 deletions(-) > create mode 100644 api/v1/swagger/definitions/checkoutexpanded.json > create mode 100644 t/db_dependent/api/v1/checkoutsexpanded.t > >diff --git a/Koha/REST/V1/Checkout.pm b/Koha/REST/V1/Checkout.pm >index f99537b..c6a2749 100644 >--- a/Koha/REST/V1/Checkout.pm >+++ b/Koha/REST/V1/Checkout.pm >@@ -19,7 +19,6 @@ use Modern::Perl; > > use Mojo::Base 'Mojolicious::Controller'; > use Mojo::JSON; >- > use C4::Auth qw( haspermission ); > use C4::Context; > use C4::Circulation; >@@ -105,14 +104,9 @@ sub renewability { > my $borrowernumber = $checkout->borrowernumber; > my $itemnumber = $checkout->itemnumber; > >- my $OpacRenewalAllowed; >- if ($user->borrowernumber == $borrowernumber) { >- $OpacRenewalAllowed = C4::Context->preference('OpacRenewalAllowed'); >- } >- >- unless ($user && ($OpacRenewalAllowed >- || haspermission($user->userid, { circulate => "circulate_remaining_permissions" }))) { >- return $c->render(status => 403, openapi => {error => "You don't have the required permission"}); >+ unless (_opac_renewal_allowed($user, $borrowernumber)) { >+ return $c->render(status => 403, openapi => { >+ error => "You don't have the required permission"}); > } > > my ($can_renew, $error) = C4::Circulation::CanBookBeRenewed( >@@ -160,4 +154,57 @@ sub gethistory { > return $c->render( status => 200, openapi => $checkout ); > } > >+sub expanded { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $borrowernumber = $c->validation->param('borrowernumber'); >+ my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber ) >+ or return; >+ my $user = $c->stash('koha.user'); >+ my $opac_renewability = _opac_renewal_allowed($user, $borrowernumber); >+ my $checkouts = Koha::Checkouts->search({ >+ borrowernumber => $borrowernumber >+ }); >+ my $checkouts_json = $checkouts->TO_JSON; >+ >+ foreach my $checkout (@{$checkouts_json}) { >+ my $item = Koha::Items->find($checkout->{itemnumber}); >+ my $branchcode = C4::Circulation::_GetCircControlBranch( $item->unblessed, >+ $borrower); >+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule( >+ { categorycode => $borrower->{categorycode}, >+ itemtype => $item->effective_itemtype, >+ branchcode => $branchcode >+ } >+ ); >+ $checkout->{'max_renewals'} = $issuing_rule >+ ? 0+$issuing_rule->renewalsallowed : 0; >+ my ($can_renew, $error); >+ if ($opac_renewability) { >+ ($can_renew, $error) = C4::Circulation::CanBookBeRenewed( >+ $borrowernumber, $checkout->{'itemnumber'}); >+ } >+ >+ $checkout->{'renewable'} = $can_renew >+ ? Mojo::JSON->true : Mojo::JSON->false; >+ } >+ >+ return $c->render( status => 200, openapi => $checkouts_json ); >+} >+ >+sub _opac_renewal_allowed { >+ my ($user, $borrowernumber) = @_; >+ >+ my $OpacRenewalAllowed; >+ if ($user->borrowernumber == $borrowernumber) { >+ $OpacRenewalAllowed = C4::Context->preference('OpacRenewalAllowed'); >+ } >+ >+ unless ($user && ($OpacRenewalAllowed || haspermission($user->userid, >+ { circulate => "circulate_remaining_permissions" }))) { >+ return 0; >+ } >+ return 1; >+} >+ > 1; >diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json >index 378c7cc..4dd6d33 100644 >--- a/api/v1/swagger/definitions.json >+++ b/api/v1/swagger/definitions.json >@@ -32,6 +32,9 @@ > "checkout": { > "$ref": "definitions/checkout.json" > }, >+ "checkoutexpanded": { >+ "$ref": "definitions/checkoutexpanded.json" >+ }, > "holds": { > "$ref": "definitions/holds.json" > }, >diff --git a/api/v1/swagger/definitions/checkoutexpanded.json b/api/v1/swagger/definitions/checkoutexpanded.json >new file mode 100644 >index 0000000..17bce36 >--- /dev/null >+++ b/api/v1/swagger/definitions/checkoutexpanded.json >@@ -0,0 +1,16 @@ >+{ >+ "type": "object", >+ "allOf": [ >+ { "$ref": "checkout.json" } >+ ], >+ "properties": { >+ "renewability": { >+ "type": "boolean", >+ "description": "renewability status" >+ }, >+ "max_renewals": { >+ "type": "integer", >+ "description": "maximum number of renewals allowed" >+ } >+ } >+} >diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json >index e334437..db50edc 100644 >--- a/api/v1/swagger/paths.json >+++ b/api/v1/swagger/paths.json >@@ -59,6 +59,9 @@ > "/checkouts/{checkout_id}/renewability": { > "$ref": "paths/checkouts.json#/~1checkouts~1{checkout_id}~1renewability" > }, >+ "/checkouts/expanded": { >+ "$ref": "paths/checkouts.json#/~1checkouts~1expanded" >+ }, > "/checkouts/history": { > "$ref": "paths/checkouts.json#/~1checkouts~1history" > }, >diff --git a/api/v1/swagger/paths/checkouts.json b/api/v1/swagger/paths/checkouts.json >index 495be52..04bc311 100644 >--- a/api/v1/swagger/paths/checkouts.json >+++ b/api/v1/swagger/paths/checkouts.json >@@ -198,6 +198,63 @@ > } > } > }, >+ "/checkouts/expanded": { >+ "get": { >+ "x-mojo-to": "Checkout#expanded", >+ "operationId": "expandedCheckouts", >+ "tags": ["patrons", "checkouts"], >+ "parameters": [{ >+ "$ref": "../parameters.json#/borrowernumberQueryParam" >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "A list of expanded checkouts", >+ "schema": { >+ "type": "array", >+ "items": { >+ "$ref": "../definitions.json#/checkoutexpanded" >+ } >+ } >+ }, >+ "401": { >+ "description": "Authentication required", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { "$ref": "../definitions.json#/error" } >+ }, >+ "404": { >+ "description": "Patron not found", >+ "schema": { "$ref": "../definitions.json#/error" } >+ }, >+ "500": { >+ "description": "Internal error", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "503": { >+ "description": "Under maintenance", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ } >+ }, >+ "x-koha-authorization": { >+ "allow-owner": true, >+ "allow-guarantor": true, >+ "permissions": { >+ "circulate": "circulate_remaining_permissions" >+ } >+ } >+ } >+ }, > "/checkouts/history": { > "get": { > "x-mojo-to": "Checkout#listhistory", >diff --git a/t/db_dependent/api/v1/checkoutsexpanded.t b/t/db_dependent/api/v1/checkoutsexpanded.t >new file mode 100644 >index 0000000..abb7b7c >--- /dev/null >+++ b/t/db_dependent/api/v1/checkoutsexpanded.t >@@ -0,0 +1,174 @@ >+#!/usr/bin/env perl >+ >+# Copyright 2017 Koha-Suomi Oy >+# >+# 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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use Test::More tests => 1; >+use Test::Mojo; >+use t::lib::Mocks; >+use t::lib::TestBuilder; >+ >+use C4::Auth; >+use C4::Circulation; >+use C4::Context; >+use C4::Items; >+ >+use Koha::Database; >+ >+my $schema = Koha::Database->new->schema; >+my $builder = t::lib::TestBuilder->new; >+ >+# FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling >+# this affects the other REST api tests >+t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' ); >+ >+my $remote_address = '127.0.0.1'; >+my $t = Test::Mojo->new('Koha::REST::V1'); >+ >+# Mock userenv branchcode >+my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; >+my $module = new Test::MockModule('C4::Context'); >+$module->mock('userenv', sub { { branch => $branchcode } }); >+ >+subtest 'get() tests' => sub { >+ plan tests => 13; >+ >+ $schema->storage->txn_begin; >+ >+ # Create test context >+ my ($borrowernumber, $sessionid) = create_user_and_session(); >+ my ($librariannnumber, $librariansessionid) = create_user_and_session(2); >+ >+ # 1. Patrons >+ my $patron = Koha::Patrons->find($borrowernumber); >+ my $librarian = Koha::Patrons->find($librariannnumber); >+ >+ # 2. Biblios and items >+ my $biblionumber = create_biblio('RESTful Web APIs'); >+ my $itemnumber1 = create_item($biblionumber, 'TEST1001'); >+ my $itemnumber2 = create_item($biblionumber, 'TEST1002'); >+ my $itemnumber3 = create_item($biblionumber, 'TEST1003'); >+ my $item1 = Koha::Items->find($itemnumber1); >+ my $item2 = Koha::Items->find($itemnumber2); >+ my $item3 = Koha::Items->find($itemnumber3); >+ >+ # 3. Checkouts >+ my $due = DateTime->now->add(weeks => 2); >+ my $issue1 = C4::Circulation::AddIssue($patron->unblessed, 'TEST1001', $due); >+ my $due2 = Koha::DateUtils::dt_from_string( $issue1->date_due ); >+ my $issue2 = C4::Circulation::AddIssue($patron->unblessed, 'TEST1002', $due2); >+ C4::Circulation::AddRenewal($borrowernumber, $itemnumber2, $branchcode, $due2); >+ >+ # 4. Issuing rules >+ t::lib::Mocks::mock_preference('CircControl', 'ItemHomeLibrary'); >+ t::lib::Mocks::mock_preference('HomeOrHoldingBranch', 'homebranch'); >+ Koha::IssuingRule->new({ >+ categorycode => $patron->categorycode, >+ itemtype => $item1->effective_itemtype, >+ branchcode => $item1->homebranch, >+ renewalsallowed => 5, >+ })->store; >+ Koha::IssuingRule->new({ >+ categorycode => $patron->categorycode, >+ itemtype => $item2->effective_itemtype, >+ branchcode => $item2->homebranch, >+ renewalsallowed => 10, >+ })->store; >+ >+ # BEGIN TEST >+ >+ # Request my own expanded checkout infromation >+ my $tx = $t->ua->build_tx(GET => "/api/v1/checkouts/expanded?borrowernumber=" >+ .$borrowernumber); >+ $tx->req->cookies({name =>'CGISESSID', value => $sessionid}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(200) >+ ->json_is('/0/borrowernumber' => $borrowernumber) >+ ->json_is('/0/itemnumber' => $itemnumber1) >+ ->json_like('/0/date_due' => qr/$due\+\d\d:\d\d/) >+ ->json_is('/0/renewals' => 0) >+ ->json_is('/0/max_renewals' => 5) >+ ->json_is('/1/borrowernumber' => $borrowernumber) >+ ->json_is('/1/itemnumber' => $itemnumber2) >+ ->json_like('/1/date_due' => qr/$due2\+\d\d:\d\d/) >+ ->json_is('/1/renewals' => 1) >+ ->json_is('/1/max_renewals' => 10) >+ ->json_hasnt('/2'); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+sub create_user_and_session { >+ my ($flags) = @_; >+ >+ my $categorycode = $builder->build({ source => 'Category' })->{ categorycode }; >+ my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; >+ >+ my $borrower = $builder->build({ >+ source => 'Borrower', >+ value => { >+ branchcode => $branchcode, >+ categorycode => $categorycode, >+ flags => $flags, >+ } >+ }); >+ >+ my $borrowersession = C4::Auth::get_session(''); >+ $borrowersession->param('number', $borrower->{ borrowernumber }); >+ $borrowersession->param('id', $borrower->{ userid }); >+ $borrowersession->param('ip', '127.0.0.1'); >+ $borrowersession->param('lasttime', time()); >+ $borrowersession->flush; >+ >+ return ($borrower->{borrowernumber}, $borrowersession->id); >+} >+ >+sub create_biblio { >+ my ($title) = @_; >+ >+ my $record = new MARC::Record; >+ $record->append_fields( >+ new MARC::Field('200', ' ', ' ', a => $title), >+ ); >+ >+ my ($biblionumber) = C4::Biblio::AddBiblio($record, ''); >+ >+ return $biblionumber; >+} >+ >+sub create_item { >+ my ($biblionumber, $barcode) = @_; >+ >+ my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; >+ >+ my $itemtype = $builder->build({ >+ source => 'Itemtype', value => { notforloan => 0 } >+ }); >+ my $item = { >+ barcode => $barcode, >+ homebranch => $branchcode, >+ holdingbranch => $branchcode, >+ itype => $itemtype->{itemtype}, >+ }; >+ >+ my $itemnumber = C4::Items::AddItem($item, $biblionumber); >+ >+ return $itemnumber; >+} >-- >2.7.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 18407
: 61991 |
61992
|
61993
|
65009