Bugzilla – Attachment 172764 Details for
Bug 24401
REST API: Check-in
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 24401: Add API endpoint to checkin items
Bug-24401-Add-API-endpoint-to-checkin-items.patch (text/plain), 11.51 KB, created by
Aleisha Amohia
on 2024-10-15 03:48:58 UTC
(
hide
)
Description:
Bug 24401: Add API endpoint to checkin items
Filename:
MIME Type:
Creator:
Aleisha Amohia
Created:
2024-10-15 03:48:58 UTC
Size:
11.51 KB
patch
obsolete
>From 8cd177bf5ef4a77092aa73fb45837961c3c9aa6e Mon Sep 17 00:00:00 2001 >From: Jan Kissig <jkissig@th-wildau.de> >Date: Tue, 2 Jul 2024 10:27:44 +0200 >Subject: [PATCH] Bug 24401: Add API endpoint to checkin items > >This adds a post /checkin endpoint to return checked out items either by its item_id or by barcode. > >To test you can use f.e. ThunderClient extension in codium/vscode. > >Test plan for ktd on main: > >a) enable system preference RESTBasicAuth >b) check out an item and remember its item id or barcode. You can use the checkouts endpoint for this: > > Auth: username: koha & password: koha > Body JSON: > { > "item_id" : 578, > "library_id": "CPL" > } > POST http://localhost:8081/api/v1/checkouts > >c) apply patch and check in item via new checkin endpoint > > Auth: username: koha & password: koha > Body JSON: > { > "item_id" : 578, > "library_id": "CPL" > } > > or > > { > "external_id" : "39999000011418", > "library_id": "CPL" > } > > POST http://localhost:8081/api/v1/checkin > > The endpoint accepts item_id and/or barcode as body params. > >d) check JSON response for return messages > >e) run unit tests: prove t/db_dependent/api/v1/checkin.t > >Signed-off-by: Aleisha Amohia <aleishaamohia@hotmail.com> >--- > Koha/REST/V1/Checkouts.pm | 69 +++++++++++++ > api/v1/swagger/definitions/checkin.yaml | 20 ++++ > api/v1/swagger/paths/checkin.yaml | 63 ++++++++++++ > api/v1/swagger/swagger.yaml | 4 + > t/db_dependent/api/v1/checkin.t | 130 ++++++++++++++++++++++++ > 5 files changed, 286 insertions(+) > create mode 100644 api/v1/swagger/definitions/checkin.yaml > create mode 100644 api/v1/swagger/paths/checkin.yaml > create mode 100755 t/db_dependent/api/v1/checkin.t > >diff --git a/Koha/REST/V1/Checkouts.pm b/Koha/REST/V1/Checkouts.pm >index 301369a45c3..1ffa501e3ae 100644 >--- a/Koha/REST/V1/Checkouts.pm >+++ b/Koha/REST/V1/Checkouts.pm >@@ -281,6 +281,75 @@ sub add { > }; > } > >+=head3 checkin >+ >+Check in a checked out item via item_id or barcode >+ >+=cut >+ >+sub checkin { >+ >+ my $c = shift->openapi->valid_input or return; >+ my $body = $c->req->json; >+ my $item_id = $body->{item_id}; >+ my $barcode = $body->{external_id}; >+ my $library_id = $body->{library_id}; >+ >+ my $exemptfine = $body->{exemptfine}; >+ >+ return try { >+ >+ unless ($item_id or $barcode){ >+ return $c->render( >+ status => 400, >+ openapi => { error => 'Missing or wrong parameters.' } >+ ); >+ } >+ >+ # if item_id and barcode are set barcode gets overwritten >+ if ( $item_id ) { >+ my $item = Koha::Items->find($item_id); >+ unless ($item) { >+ return $c->render( >+ status => 409, >+ openapi => { error => 'Item not found.' } >+ ); >+ } >+ $barcode = $item->barcode; >+ } >+ >+ my ( $returned, $return_messages ) = >+ C4::Circulation::AddReturn( $barcode, $library_id, $exemptfine ); >+ >+ my $response = { returned => $returned, messages => $return_messages }; >+ >+ if ($return_messages->{BadBarcode}){ >+ $response->{error} = 'Item not found.'; >+ return $c->render( >+ status => 409, >+ openapi => $response >+ ); >+ } >+ >+ unless ($returned) { >+ return $c->render( >+ status => 403, >+ openapi => $response >+ ); >+ } >+ >+ $c->res->headers->location( $c->req->url->to_string ); >+ return $c->render( >+ status => 201, >+ openapi => $response >+ ); >+ >+ } >+ catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ > =head3 get_renewals > > List Koha::Checkout::Renewals >diff --git a/api/v1/swagger/definitions/checkin.yaml b/api/v1/swagger/definitions/checkin.yaml >new file mode 100644 >index 00000000000..42d245ccfe9 >--- /dev/null >+++ b/api/v1/swagger/definitions/checkin.yaml >@@ -0,0 +1,20 @@ >+--- >+type: object >+properties: >+ returned: >+ type: integer >+ description: True if return checkin succeeded >+ readOnly: true >+ messages: >+ description: Messages to the returned item >+ type: object >+ item_id: >+ type: integer >+ description: Internal item identifier >+ external_id: >+ type: integer >+ description: Barcode of the item >+ exemptfine: >+ type: boolean >+ description: If true overdue charges for the item will be removed >+additionalProperties: true >\ No newline at end of file >diff --git a/api/v1/swagger/paths/checkin.yaml b/api/v1/swagger/paths/checkin.yaml >new file mode 100644 >index 00000000000..0820ca322e6 >--- /dev/null >+++ b/api/v1/swagger/paths/checkin.yaml >@@ -0,0 +1,63 @@ >+--- >+/checkin: >+ post: >+ x-mojo-to: Checkouts#checkin >+ operationId: addCheckin >+ tags: >+ - checkin >+ - patrons >+ summary: Add a checkin >+ parameters: >+ - name: body >+ in: body >+ description: A JSON object containing information about the checkin >+ required: true >+ schema: >+ $ref: "../swagger.yaml#/definitions/checkin" >+ consumes: >+ - application/json >+ produces: >+ - application/json >+ responses: >+ "201": >+ description: Created checkin >+ schema: >+ $ref: "../swagger.yaml#/definitions/checkin" >+ "400": >+ description: Missing or wrong parameters >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ "401": >+ description: Authentication required >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ "403": >+ description: Cannot create checkin >+ schema: >+ $ref: "../swagger.yaml#/definitions/checkin" >+ "404": >+ description: Item not found >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ "409": >+ description: Conflict in creating checkin >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ "412": >+ description: Precondition failed >+ 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: >+ circulate: circulate_remaining_permissions >diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml >index dd72361380e..bcc80ea7936 100644 >--- a/api/v1/swagger/swagger.yaml >+++ b/api/v1/swagger/swagger.yaml >@@ -26,6 +26,8 @@ definitions: > $ref: ./definitions/cash_register.yaml > cashup: > $ref: ./definitions/cashup.yaml >+ checkin: >+ $ref: ./definitions/checkin.yaml > checkout: > $ref: ./definitions/checkout.yaml > checkouts: >@@ -271,6 +273,8 @@ paths: > $ref: "./paths/cash_registers.yaml#/~1cash_registers~1{cash_register_id}~1cashups" > "/cashups/{cashup_id}": > $ref: "./paths/cash_registers.yaml#/~1cashups~1{cashup_id}" >+ /checkin: >+ $ref: ./paths/checkin.yaml#/~1checkin > /checkouts: > $ref: ./paths/checkouts.yaml#/~1checkouts > "/checkouts/{checkout_id}": >diff --git a/t/db_dependent/api/v1/checkin.t b/t/db_dependent/api/v1/checkin.t >new file mode 100755 >index 00000000000..d68c76b25fc >--- /dev/null >+++ b/t/db_dependent/api/v1/checkin.t >@@ -0,0 +1,130 @@ >+#!/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 <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Test::More tests => 17; >+use Test::MockModule; >+use Test::Mojo; >+use t::lib::Mocks; >+use t::lib::TestBuilder; >+ >+use DateTime; >+ >+use C4::Context; >+use C4::Circulation qw( AddIssue AddReturn CanBookBeIssued ); >+ >+use Koha::Database; >+use Koha::DateUtils qw( dt_from_string output_pref ); >+use Koha::Token; >+ >+my $schema = Koha::Database->schema; >+my $builder = t::lib::TestBuilder->new; >+ >+t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); >+my $t = Test::Mojo->new('Koha::REST::V1'); >+ >+$schema->storage->txn_begin; >+ >+my $dbh = C4::Context->dbh; >+ >+my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; >+my $librarian = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 2, branchcode => $branchcode } >+ } >+); >+my $password = 'thePassword123'; >+$librarian->set_password( { password => $password, skip_validation => 1 } ); >+my $userid = $librarian->userid; >+ >+my $other_branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; >+my $patron = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 0, branchcode => $other_branchcode }, >+ } >+); >+my $unauth_password = 'thePassword000'; >+$patron->set_password( >+ { password => $unauth_password, skip_validattion => 1 } ); >+my $unauth_userid = $patron->userid; >+my $patron_id = $patron->borrowernumber; >+ >+my $item1 = $builder->build_sample_item; >+my $item1_id = $item1->id; >+ >+my $not_issued_item = $builder->build_sample_item; >+my $not_issued_item_id = $not_issued_item->id; >+my $not_issued_item_barcode = $not_issued_item->barcode; >+ >+my $barcode = '321321321321'; >+my $matching_items = Koha::Items->search({ barcode => $barcode }); >+while (my $item = $matching_items->next) { >+ $item->delete; >+} >+ >+my $unknown_item1_id = 578; >+my $del_item = Koha::Items->find($unknown_item1_id); >+if ($del_item){ >+ $del_item->delete; >+} >+ >+my $checkout = $builder->build_object( >+ { >+ class => 'Koha::Checkouts', >+ value => { >+ itemnumber => $item1_id, >+ branchcode => $branchcode, >+ borrowernumber => $patron_id, >+ note => undef, >+ notedate => undef, >+ noteseen => undef >+ } >+ } >+); >+my $checkout_id = $checkout->id; >+ >+# empty checkin >+$t->post_ok( >+ "//$userid:$password@/api/v1/checkin" => json => { } ) >+ ->status_is(400); >+ >+# checkin on unknow item id >+$t->post_ok( >+ "//$userid:$password@/api/v1/checkin" => json => { item_id => $unknown_item1_id } ) >+ ->status_is(409)->json_is( { error => "Item not found." } ); >+ >+# checkin with unknow barcode >+$t->post_ok( >+ "//$userid:$password@/api/v1/checkin" => json => { external_id => $barcode } ) >+ ->status_is(409)->json_is( '/error' => "Item not found." )->json_is( '/messages' => { BadBarcode => $barcode} ); >+ >+# not isued >+$t->post_ok( >+ "//$userid:$password@/api/v1/checkin" => json => { item_id => $not_issued_item_id, library_id => $branchcode } ) >+ ->status_is(403)->json_is( '/returned' => 0 )->json_has( '/messages' => { NotIssued => $not_issued_item_barcode } ); >+ >+# checkin okay >+$t->post_ok( >+ "//$userid:$password@/api/v1/checkin" => json => { item_id => $item1_id, library_id => $branchcode } ) >+ ->status_is(201)->json_is( '/returned' => 1 )->json_has( '/messages' => { TransferTrigger => 'ReturnToHome', WasReturned => '1' } ); >+ >+ >+ >+$schema->storage->txn_rollback; >-- >2.39.5
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 24401
:
151109
|
151181
|
151182
|
151183
|
151184
|
152717
|
154428
|
154429
|
154430
|
154431
|
156884
|
156885
|
168337
|
172764
|
173189
|
173194