Bugzilla – Attachment 91633 Details for
Bug 23336
Add an API endpoint for checking an item out to a patron
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 23336: Add POST /checkouts issue endpoint
Bug-23336-Add-POST-checkouts-issue-endpoint.patch (text/plain), 9.90 KB, created by
Andrew Isherwood
on 2019-07-19 11:08:02 UTC
(
hide
)
Description:
Bug 23336: Add POST /checkouts issue endpoint
Filename:
MIME Type:
Creator:
Andrew Isherwood
Created:
2019-07-19 11:08:02 UTC
Size:
9.90 KB
patch
obsolete
>From 2f74752631aefbcd275013209c2744e3e2c19843 Mon Sep 17 00:00:00 2001 >From: Andrew Isherwood <andrew.isherwood@ptfs-europe.com> >Date: Fri, 19 Jul 2019 11:57:38 +0100 >Subject: [PATCH] Bug 23336: Add POST /checkouts issue endpoint > >This patch adds a POST /checkouts issue endpoint for creating checkouts > >Test plan: > >- Run unit tests in t/db_dependent/api/v1/checkouts.t >- Make POST request to http://yourlibrary/api/v1/checkouts with request body >containing at least 'patron_id' & 'barcode' properties, other possible properties are: > > "due_date": Checkout due date > "inprocess": Boolean > "ignore_reserves": Boolean > "cancel_reserve": Either null, "revert" or "cancel" > "issue_date": Checkout issue date > "sipmode": Boolean > "params": Object containing arbitrary properties that will > be passed to CanBookBeRenewed and AddIssue >- Observe returned data and HTTP code > - 201 for checkout created > - 403 for cannot be checked out (with reason in response body) > - 404 for either invalid patron or barcode > - 500 for something else went wrong >--- > Koha/REST/V1/Checkouts.pm | 91 ++++++++++++++++++++++++++++ > api/v1/swagger/paths/checkouts.json | 117 ++++++++++++++++++++++++++++++++++++ > t/db_dependent/api/v1/checkouts.t | 36 ++++++++++- > 3 files changed, 243 insertions(+), 1 deletion(-) > >diff --git a/Koha/REST/V1/Checkouts.pm b/Koha/REST/V1/Checkouts.pm >index bb349a78ec..cf03cfc084 100644 >--- a/Koha/REST/V1/Checkouts.pm >+++ b/Koha/REST/V1/Checkouts.pm >@@ -25,6 +25,8 @@ use C4::Context; > use C4::Circulation; > use Koha::Checkouts; > use Koha::IssuingRules; >+use Koha::Patrons; >+use JSON; > > use Try::Tiny; > >@@ -172,6 +174,95 @@ sub allows_renewal { > ); > } > >+=head3 add >+ >+Create a checkout >+ >+=cut >+ >+sub add { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $body = $c->validation->param('body'); >+ >+ my $patron_id = $body->{'patron_id'}; >+ my $barcode = $body->{'barcode'}; >+ my $duedate = $body->{'due_date'}; >+ my $inprocess = $body->{'inprocess'}; >+ my $ignore_reserves = $body->{'ignore_reserves'}; >+ my $cancel_reserve = $body->{'cancel_reserve'}; >+ my $issuedate = $body->{'issue_date'}; >+ my $sipmode = $body->{'sipmode'}; >+ my $params = $body->{'params'}; >+ >+ my $patron = Koha::Patrons->find({ borrowernumber => $patron_id }); >+ my $item = Koha::Items->find({ barcode => $barcode }); >+ >+ $c->res->headers->location( $c->req->url->to_string ); >+ unless ($patron) { >+ return $c->render( >+ status => 404, >+ openapi => { error => "Patron doesn't exist" } >+ ); >+ } >+ >+ unless ($item) { >+ return $c->render( >+ status => 404, >+ openapi => { error => "Item doesn't exist" } >+ ); >+ } >+ >+ my ( $error, $confirm, $alerts, $messages ) = >+ C4::Circulation::CanBookBeIssued( >+ $patron, >+ $barcode, >+ $duedate, >+ $inprocess, >+ $ignore_reserves, >+ $params >+ ); >+ >+ my $problems = {}; >+ $problems->{error} = $error if %{$error}; >+ $problems->{confirm} = $confirm if %{$confirm}; >+ $problems->{alerts} = $alerts if %{$alerts}; >+ $problems->{messages} = $messages if %{$messages}; >+ >+ if (%{$problems}) { >+ return $c->render( >+ status => 403, >+ openapi => { >+ error => encode_json $problems >+ } >+ ); >+ } >+ >+ my $issue = C4::Circulation::AddIssue( >+ $patron->unblessed, >+ $barcode, >+ $duedate, >+ $cancel_reserve, >+ $issuedate, >+ 0, >+ $params >+ ); >+ >+ if ($issue && %{$issue}) { >+ return $c->render( >+ status => 201, >+ openapi => _to_api( $issue->TO_JSON ) >+ ); >+ } else { >+ return $c->render( >+ status => 500, >+ openapi => { error => 'Unknown error during checkout' } >+ ); >+ } >+ >+ >+} >+ > =head3 _to_api > > Helper function that maps a hashref of Koha::Checkout attributes into REST api >diff --git a/api/v1/swagger/paths/checkouts.json b/api/v1/swagger/paths/checkouts.json >index 7d89e3c534..66d239784a 100644 >--- a/api/v1/swagger/paths/checkouts.json >+++ b/api/v1/swagger/paths/checkouts.json >@@ -35,6 +35,123 @@ > "circulate": "circulate_remaining_permissions" > } > } >+ }, >+ "post": { >+ "x-mojo-to": "Checkouts#add", >+ "operationId": "addCheckout", >+ "tags": ["patrons", "checkouts"], >+ "parameters": [{ >+ "name": "body", >+ "in": "body", >+ "description": "A JSON object containing information about the new checkout", >+ "required": true, >+ "schema": { >+ "type": "object", >+ "properties": { >+ "patron_id": { >+ "description": "Internal patron identifier", >+ "type": "string" >+ }, >+ "barcode": { >+ "description": "Internal item barcode", >+ "type": "string" >+ }, >+ "due_date": { >+ "description": "Checkout due date", >+ "type": ["string", "null"], >+ "format": "date" >+ }, >+ "inprocess": { >+ "description": "In process", >+ "type": ["boolean", "null"] >+ }, >+ "ignore_reserves": { >+ "description": "Should reserves on this item be ignored", >+ "type": [ "boolean", "null" ] >+ }, >+ "cancel_reserve": { >+ "description": "Should reserves on this item be cancelled", >+ "type": [ "string", "null" ], >+ "enum": [ >+ "revert", >+ "cancel" >+ ] >+ }, >+ "issue_date": { >+ "description": "Checkout issue date", >+ "type": ["string", "null"], >+ "format": "date" >+ }, >+ "sipmode": { >+ "description": "Flag indicating sipmode", >+ "type": ["boolean", "null"] >+ }, >+ "params": { >+ "description": "Object holding other arbitrary paramters", >+ "type": ["object", "null"] >+ } >+ }, >+ "required": [ "patron_id", "barcode" ] >+ } >+ } >+ ], >+ "consumes": ["application/json"], >+ "produces": ["application/json"], >+ "responses": { >+ "201": { >+ "description": "Created checkout", >+ "schema": { >+ "$ref": "../definitions.json#/checkout" >+ } >+ }, >+ "400": { >+ "description": "Missing or wrong parameters", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "401": { >+ "description": "Authentication required", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "403": { >+ "description": "Checkout not allowed", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Item not found", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Borrower not found", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "500": { >+ "description": "Internal server error", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "503": { >+ "description": "Under maintenance", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ } >+ }, >+ "x-koha-authorization": { >+ "permissions": { >+ "circulate": "circulate_remaining_permissions" >+ } >+ } > } > }, > "/checkouts/{checkout_id}": { >diff --git a/t/db_dependent/api/v1/checkouts.t b/t/db_dependent/api/v1/checkouts.t >index 89e16fdb50..1c0e3894e4 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 => 79; >+use Test::More tests => 95; > use Test::MockModule; > use Test::Mojo; > use t::lib::Mocks; >@@ -196,3 +196,37 @@ $t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/all > current_renewals => 1, > error => 'too_many' > }); >+ >+# Test create checkout POST route >+$dbh->do(q{ >+ UPDATE issuingrules SET issuelength=? >+}, {}, 7); >+my $itemtype = $builder->build({ >+ source => 'Itemtype', >+ value => { notforloan => 0 } >+})->{itemtype}; >+my $item4 = $builder->build_sample_item({ itype => $itemtype }); >+my $expected_issue_datedue = DateTime->now >+ ->set_time_zone('local') >+ ->add(days => 7) >+ ->set(hour => 23, minute => 59, second => 0); >+ >+$t->post_ok( "//$userid:$password@/api/v1/checkouts/" => json => { patron_id => $patron_id, barcode => 'not_here' }) >+ ->status_is(404) >+ ->json_is({ error => "Item doesn't exist" }) >+ ->header_is(Location => "/api/v1/checkouts/"); >+ >+$t->post_ok( "//$userid:$password@/api/v1/checkouts/" => json => { patron_id => 'not_here', barcode => $item4->barcode }) >+ ->status_is(404) >+ ->json_is({ error => "Patron doesn't exist" }) >+ ->header_is(Location => "/api/v1/checkouts/"); >+ >+$t->post_ok( "//$userid:$password@/api/v1/checkouts/" => json => { patron_id => $patron_id, barcode => $item4->barcode }) >+ ->status_is(201) >+ ->json_is('/due_date' => output_pref( { dateformat => "rfc3339", dt => $expected_issue_datedue }) ) >+ ->header_is(Location => "/api/v1/checkouts/"); >+ >+$t->post_ok( "//$userid:$password@/api/v1/checkouts/" => json => { patron_id => $patron_id, barcode => $item4->barcode }) >+ ->status_is(403) >+ ->json_is({ error => '{"confirm":{"RENEW_ISSUE":1}}' }) >+ ->header_is(Location => "/api/v1/checkouts/"); >-- >2.11.0
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 23336
:
91632
|
91633
|
91634
|
150947
|
150948
|
150949
|
150954
|
150955
|
150956
|
150960
|
150961
|
150962
|
151253
|
151318
|
151319
|
151320
|
151321
|
151322
|
151353
|
151354
|
151355
|
151356
|
151357
|
152712
|
152713
|
152714
|
152715
|
152716
|
152938
|
152999
|
153000
|
153095
|
153096