From 9841f7a2195b05ea2e73fceaa4b84f2727a64bca Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Tue, 1 Dec 2020 12:29:38 +0100 Subject: [PATCH] Bug 18729: Add PUT /holds/{hold_id}/pickup_location This patch adds a route to overwrite the current pickup location. Signed-off-by: Tomas Cohen Arazi --- Koha/REST/V1/Holds.pm | 32 +++++++++++ api/v1/swagger/paths.json | 3 + api/v1/swagger/paths/holds.json | 73 ++++++++++++++++++++++++ koha-tmpl/intranet-tmpl/prog/js/holds.js | 5 +- t/db_dependent/api/v1/holds.t | 54 +++++++++++++++++- 5 files changed, 163 insertions(+), 4 deletions(-) diff --git a/Koha/REST/V1/Holds.pm b/Koha/REST/V1/Holds.pm index 27f20996ce7..d1abfde5f01 100644 --- a/Koha/REST/V1/Holds.pm +++ b/Koha/REST/V1/Holds.pm @@ -475,4 +475,36 @@ sub pickup_locations { }; } +=head3 update_pickup_location + +Method that handles modifying the pickup location of a Koha::Hold object + +=cut + +sub update_pickup_location { + my $c = shift->openapi->valid_input or return; + + my $hold_id = $c->validation->param('hold_id'); + my $hold = Koha::Holds->find($hold_id); + + unless ($hold) { + return $c->render( + status => 404, + openapi => { error => "Hold not found" } + ); + } + + return try { + my $pickup_location = $c->req->json; + + $hold->branchcode($pickup_location)->store; + + return $c->render( status => 200, openapi => $pickup_location ); + } + catch { + $c->unhandled_exception($_); + }; +} + + 1; diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json index 3b5dc352d54..c5e9c7d3679 100644 --- a/api/v1/swagger/paths.json +++ b/api/v1/swagger/paths.json @@ -62,6 +62,9 @@ "/holds/{hold_id}/pickup_locations": { "$ref": "paths/holds.json#/~1holds~1{hold_id}~1pickup_locations" }, + "/holds/{hold_id}/pickup_location": { + "$ref": "paths/holds.json#/~1holds~1{hold_id}~1pickup_location" + }, "/items": { "$ref": "paths/items.json#/~1items" }, diff --git a/api/v1/swagger/paths/holds.json b/api/v1/swagger/paths/holds.json index 386b4a94701..da58afc650e 100644 --- a/api/v1/swagger/paths/holds.json +++ b/api/v1/swagger/paths/holds.json @@ -676,5 +676,78 @@ } } } + }, + "/holds/{hold_id}/pickup_location": { + "put": { + "x-mojo-to": "Holds#update_pickup_location", + "operationId": "updateHoldPickupLocation", + "tags": ["holds"], + "parameters": [ + { + "$ref": "../parameters.json#/hold_id_pp" + }, + { + "name": "body", + "in": "body", + "description": "Pickup location", + "required": true, + "schema": { + "type": "string" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "The new pickup location value for the hold", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Hold not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "409": { + "description": "Unable to perform action on hold", + "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": { + "permissions": { + "reserveforothers": "place_holds" + } + } + } } } diff --git a/koha-tmpl/intranet-tmpl/prog/js/holds.js b/koha-tmpl/intranet-tmpl/prog/js/holds.js index 66dd265a14e..ff5767036bd 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/holds.js +++ b/koha-tmpl/intranet-tmpl/prog/js/holds.js @@ -224,12 +224,11 @@ $(document).ready(function() { var cur_select = $(this); var res_id = $(this).attr('reserve_id'); $(this).after('
'); - var api_url = '/api/v1/holds/'+res_id; - var update_info = JSON.stringify({ pickup_library_id: $(this).val(), priority: parseInt($(this).attr("priority"),10) }); + var api_url = '/api/v1/holds/' + encodeURIComponent(res_id) + '/pickup_location'; $.ajax({ method: "PUT", url: api_url, - data: update_info , + data: $(this).val(), success: function( data ){ holdsTable.api().ajax.reload(); }, error: function( jqXHR, textStatus, errorThrown) { alert('There was an error:'+textStatus+" "+errorThrown); diff --git a/t/db_dependent/api/v1/holds.t b/t/db_dependent/api/v1/holds.t index 7310a671537..aa116bc7a85 100755 --- a/t/db_dependent/api/v1/holds.t +++ b/t/db_dependent/api/v1/holds.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 12; +use Test::More tests => 13; use Test::MockModule; use Test::Mojo; use t::lib::TestBuilder; @@ -1011,3 +1011,55 @@ subtest 'add() tests' => sub { $schema->storage->txn_rollback; }; + + +subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { + + plan tests => 4; + + $schema->storage->txn_begin; + + my $password = 'AbcdEFG123'; + + my $library_1 = $builder->build_object({ class => 'Koha::Libraries' }); + my $library_2 = $builder->build_object({ class => 'Koha::Libraries' }); + + my $patron = $builder->build_object( + { class => 'Koha::Patrons', value => { flags => 0 } } ); + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $patron->userid; + $builder->build( + { + source => 'UserPermission', + value => { + borrowernumber => $patron->borrowernumber, + module_bit => 6, + code => 'place_holds', + }, + } + ); + + # Disable logging + t::lib::Mocks::mock_preference( 'HoldsLog', 0 ); + t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + + my $biblio = $builder->build_sample_biblio; + my $hold = Koha::Holds->find( + AddReserve( + { + branchcode => $library_1->branchcode, + borrowernumber => $patron->borrowernumber, + biblionumber => $biblio->biblionumber, + priority => 1, + } + ) + ); + + $t->put_ok( "//$userid:$password@/api/v1/holds/" + . $hold->id + . "/pickup_location" => json => $library_2->branchcode )->status_is(200)->json_is($library_2->branchcode); + + is( $hold->discard_changes->branchcode->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' ); + + $schema->storage->txn_rollback; +}; -- 2.29.2