From 045d04dcb02374b45abfadb447f68cdc8cb255bd Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Fri, 5 May 2023 15:56:27 +0100 Subject: [PATCH] Bug 30979: Add public endpoints This patch expands the checkouts endpoints to allow for a public workflow. We add the availability endpoint under `/public/checkouts/availability` and restrict the information we send back to only those fields a public user should be allowed to see. We also add a new checkout endpoint at `/patrons/{patron_id}/checkouts` that allows for users to checkout to themselves and accepts the same POST request with checkout details including item_id and a confirmation token in the body that the staff client endpoints accept. Signed-off-by: Silvia Meakins Signed-off-by: Kyle M Hall --- Koha/REST/V1/Checkouts.pm | 74 ++++++++++++++++-------- api/v1/swagger/paths/checkouts.yaml | 40 +++++++++++-- api/v1/swagger/paths/public_patrons.yaml | 61 +++++++++++++++++++ api/v1/swagger/swagger.yaml | 4 ++ 4 files changed, 151 insertions(+), 28 deletions(-) diff --git a/Koha/REST/V1/Checkouts.pm b/Koha/REST/V1/Checkouts.pm index 2fd756e3ae..0689601908 100644 --- a/Koha/REST/V1/Checkouts.pm +++ b/Koha/REST/V1/Checkouts.pm @@ -102,7 +102,51 @@ sub get { }; } -=head3 get_availablity +=head3 _check_availability + +Internal function to call CanBookBeIssued and return an appropriately filtered +set return + +=cut + +sub _check_availability { + my ( $c, $patron, $item ) = @_; + + my $inprocess = 0; # What does this do? + my $ignore_reserves = 0; # Don't ignore reserves + my $params = { item => $item }; + + my ( $impossible, $confirmation, $alerts, $messages ) = + C4::Circulation::CanBookBeIssued( $patron, undef, undef, $inprocess, + $ignore_reserves, $params ); + + if ( $c->stash('is_public') ) { + + # Upgrade some confirmations to blockers + my @should_block = + qw/TOO_MANY ISSUED_TO_ANOTHER RESERVED RESERVED_WAITING TRANSFERRED PROCESSING AGE_RESTRICTION/; + for my $block (@should_block) { + if ( exists( $confirmation->{$block} ) ) { + $impossible->{$block} = $confirmation->{$block}; + delete $confirmation->{$block}; + } + } + + # Remove any non-public info that's returned by CanBookBeIssued + my @restricted_keys = + qw/issued_borrowernumber issued_cardnumber issued_firstname issued_surname resborrowernumber resbranchcode rescardnumber reserve_id resfirstname resreservedate ressurname item_notforloan/; + for my $key (@restricted_keys) { + delete $confirmation->{$key}; + delete $impossible->{$key}; + delete $alerts->{$key}; + delete $messages->{$key}; + } + } + + return ( $impossible, $confirmation, { %{$alerts}, %{$messages} } ); +} + +=head3 get_availability Controller function that handles retrieval of Checkout availability @@ -113,16 +157,10 @@ sub get_availability { my $user = $c->stash('koha.user'); my $patron = Koha::Patrons->find( $c->param('patron_id') ); - my $inprocess = 0; # What does this do? - my $ignore_reserves = 0; # Don't ignore reserves my $item = Koha::Items->find( $c->param('item_id') ); - my $params = { - item => $item - }; - my ( $impossible, $confirmation, $alerts, $messages ) = - C4::Circulation::CanBookBeIssued( $patron, undef, undef, $inprocess, $ignore_reserves, - $params ); + my ( $impossible, $confirmation, $warnings ) = + $c->_check_availability( $patron, $item ); my $confirm_keys = join( ":", sort keys %{$confirmation} ); $confirm_keys = $user->id . ":" . $item->id . ":" . $confirm_keys; @@ -131,7 +169,7 @@ sub get_availability { my $response = { blockers => $impossible, confirms => $confirmation, - warnings => { %{$alerts}, %{$messages} }, + warnings => $warnings, confirmation_token => $token }; @@ -176,20 +214,8 @@ sub add { ); } - my $inprocess = 0; # What does this do? - my $ignore_reserves = 0; # Don't ignore reserves - my $params = { item => $item }; - - # Call 'CanBookBeIssued' - my ( $impossible, $confirmation, $alerts, $messages ) = - C4::Circulation::CanBookBeIssued( - $patron, - undef, - undef, - $inprocess, - $ignore_reserves, - $params - ); + my ( $impossible, $confirmation, $warnings ) = + $c->_check_availability( $patron, $item ); # * Fail for blockers - render 403 if ( keys %{$impossible} ) { diff --git a/api/v1/swagger/paths/checkouts.yaml b/api/v1/swagger/paths/checkouts.yaml index afe6e5660c..e324b61c52 100644 --- a/api/v1/swagger/paths/checkouts.yaml +++ b/api/v1/swagger/paths/checkouts.yaml @@ -89,13 +89,13 @@ description: Created checkout schema: $ref: "../swagger.yaml#/definitions/checkout" - "400": + "400": description: Missing or wrong parameters - schema: + schema: $ref: "../swagger.yaml#/definitions/error" - "401": + "401": description: Authentication required - schema: + schema: $ref: "../swagger.yaml#/definitions/error" "403": description: Cannot create checkout @@ -370,3 +370,35 @@ x-koha-authorization: permissions: circulate: circulate_remaining_permissions +"/public/checkouts/availability": + get: + x-mojo-to: Checkouts#get_availability + operationId: availabilityCheckoutsPublic + tags: + - checkouts + summary: Get checkout availability + parameters: + - $ref: "../swagger.yaml#/parameters/patron_id_qp" + - $ref: "../swagger.yaml#/parameters/item_id_qp" + produces: + - application/json + responses: + "200": + description: Availability + schema: + type: "object" + "403": + description: Access forbidden + 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" diff --git a/api/v1/swagger/paths/public_patrons.yaml b/api/v1/swagger/paths/public_patrons.yaml index 2f92f6751b..fb50548fd0 100644 --- a/api/v1/swagger/paths/public_patrons.yaml +++ b/api/v1/swagger/paths/public_patrons.yaml @@ -62,6 +62,67 @@ $ref: "../swagger.yaml#/definitions/error" x-koha-authorization: allow-owner: true +"/public/patrons/{patron_id}/checkouts": + post: + x-mojo-to: Checkouts#add + operationId: addCheckoutPublic + tags: + - checkouts + - patrons + summary: Add a new checkout + parameters: + - $ref: "../swagger.yaml#/parameters/patron_id_pp" + - name: body + in: body + description: A JSON object containing information about the new checkout + required: true + schema: + $ref: "../swagger.yaml#/definitions/checkout" + - name: confirmation + in: query + description: A JWT confirmation token + required: false + type: string + produces: + - application/json + responses: + "201": + description: Created checkout + schema: + $ref: "../swagger.yaml#/definitions/checkout" + "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 checkout + schema: + $ref: "../swagger.yaml#/definitions/error" + "409": + description: Conflict in creating checkout + 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: + allow-owner: true "/public/patrons/{patron_id}/guarantors/can_see_charges": put: x-mojo-to: Patrons#guarantors_can_see_charges diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index 52c04a21e6..86dbbac99c 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -307,6 +307,8 @@ paths: $ref: "./paths/patrons_password.yaml#/~1patrons~1{patron_id}~1password~1expiration_date" "/public/biblios/{biblio_id}": $ref: "./paths/biblios.yaml#/~1public~1biblios~1{biblio_id}" + "/public/checkouts/availability": + $ref: ./paths/checkouts.yaml#/~1public~1checkouts~1availability "/public/items": $ref: "./paths/items.yaml#/~1public~1items" "/public/biblios/{biblio_id}/items": @@ -321,6 +323,8 @@ paths: $ref: ./paths/public_oauth.yaml#/~1public~1oauth~1login~1{provider_code}~1{interface} "/public/patrons/{patron_id}/article_requests/{article_request_id}": $ref: "./paths/article_requests.yaml#/~1public~1patrons~1{patron_id}~1article_requests~1{article_request_id}" + "/public/patrons/{patron_id}/checkouts": + $ref: "./paths/public_patrons.yaml#/~1public~1patrons~1{patron_id}~1checkouts" "/public/patrons/{patron_id}/guarantors/can_see_charges": $ref: "./paths/public_patrons.yaml#/~1public~1patrons~1{patron_id}~1guarantors~1can_see_charges" "/public/patrons/{patron_id}/guarantors/can_see_checkouts": -- 2.40.1