From 51d50810fa39ce1e48835c5fcf1514bc729c7402 Mon Sep 17 00:00:00 2001 From: Agustin Moyano Date: Mon, 2 Jan 2023 11:44:05 -0300 Subject: [PATCH] Bug 31799: Add REST endpoint to modify a biblio's item To test: 1. Apply patch 2. Set RESTBasicAuth preference to true 3. Get a biblio with an item 4. Make a PUT request to /api/v1/biblios/:biblio_id/items/:item_id with a json body that represents an item to replace 5. Check that the item was modified 6. Sign off Signed-off-by: Lucas Gass Signed-off-by: Nick Clemens Signed-off-by: Tomas Cohen Arazi --- Koha/REST/V1/Biblios.pm | 68 +++++++++++++++++++++++++++++++ api/v1/swagger/paths/biblios.yaml | 53 ++++++++++++++++++++++++ api/v1/swagger/swagger.yaml | 2 + t/db_dependent/api/v1/biblios.t | 60 ++++++++++++++++++++++++++- 4 files changed, 182 insertions(+), 1 deletion(-) diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm index e50f426409..bd4362250a 100644 --- a/Koha/REST/V1/Biblios.pm +++ b/Koha/REST/V1/Biblios.pm @@ -393,6 +393,74 @@ sub add_item { } } +=head3 update_item + +Controller function that handles updating a biblio's item + +=cut + +sub update_item { + my $c = shift->openapi->valid_input or return; + + try { + my $biblio_id = $c->validation->param('biblio_id'); + my $item_id = $c->validation->param('item_id'); + my $biblio = Koha::Biblios->find({ biblionumber => $biblio_id }); + unless ($biblio) { + return $c->render( + status => 404, + openapi => { error => "Biblio not found" } + ); + } + + my $item = $biblio->items->find({ itemnumber => $item_id }); + + unless ($item) { + return $c->render( + status => 404, + openapi => { error => "Item not found" } + ); + } + + my $body = $c->validation->param('body'); + + $body->{biblio_id} = $biblio_id; + + # Don't save extended subfields yet. To be done in another bug. + $body->{extended_subfields} = undef; + + $item->set_from_api($body); + + my $barcodeSearch; + $barcodeSearch = Koha::Items->search( { barcode => $body->{external_id} } ) if defined $body->{external_id}; + + if ( $barcodeSearch + && ($barcodeSearch->count > 1 + || ($barcodeSearch->count == 1 + && $barcodeSearch->next->itemnumber != $item->itemnumber + ) + ) + ) + { + return $c->render( + status => 400, + openapi => { error => "Barcode not unique" } + ); + } + + my $storedItem = $item->store; + $storedItem->discard_changes; + + $c->render( + status => 200, + openapi => $storedItem->to_api + ); + } + catch { + $c->unhandled_exception($_); + } +} + =head3 get_checkouts List Koha::Checkout objects diff --git a/api/v1/swagger/paths/biblios.yaml b/api/v1/swagger/paths/biblios.yaml index 1506d019aa..e2e68e4a99 100644 --- a/api/v1/swagger/paths/biblios.yaml +++ b/api/v1/swagger/paths/biblios.yaml @@ -455,6 +455,59 @@ x-koha-authorization: permissions: editcatalogue: edit_catalogue +"/biblios/{biblio_id}/items/{item_id}": + put: + x-mojo-to: Biblios#update_item + operationId: updateBiblioItem + tags: + - biblios + summary: Update an item for a biblio + parameters: + - $ref: "../swagger.yaml#/parameters/biblio_id_pp" + - $ref: "../swagger.yaml#/parameters/item_id_pp" + - name: body + in: body + description: A JSON object containing information about the item + required: true + schema: + $ref: "../swagger.yaml#/definitions/item" + produces: + - application/json + responses: + "200": + description: Item updated + schema: + $ref: "../swagger.yaml#/definitions/item" + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: Not found + 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: + editcatalogue: edit_catalogue "/biblios/{biblio_id}/pickup_locations": get: x-mojo-to: Biblios#pickup_locations diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index ea5f9ce435..23c59b96a1 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -171,6 +171,8 @@ paths: $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}~1checkouts" "/biblios/{biblio_id}/items": $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}~1items" + "/biblios/{biblio_id}/items/{item_id}": + $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}~1items~1{item_id}" "/biblios/{biblio_id}/pickup_locations": $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}~1pickup_locations" "/biblios/{biblio_id}/item_groups": diff --git a/t/db_dependent/api/v1/biblios.t b/t/db_dependent/api/v1/biblios.t index a28885f2df..92293731ce 100755 --- a/t/db_dependent/api/v1/biblios.t +++ b/t/db_dependent/api/v1/biblios.t @@ -20,7 +20,7 @@ use Modern::Perl; use utf8; use Encode; -use Test::More tests => 12; +use Test::More tests => 13; use Test::MockModule; use Test::Mojo; use Test::Warn; @@ -1744,3 +1744,61 @@ subtest 'add_item() tests' => sub { $schema->storage->txn_rollback; }; + +subtest 'update_item() tests' => sub { + plan tests => 7; + + $schema->storage->txn_begin; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + my $password = 'thePassword123'; + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $patron->userid; + + my $item = $builder->build_sample_item({ replacementprice => 5 }); + my $biblio_id = $item->biblionumber; + my $item_id = $item->itemnumber; + + my $biblio = Koha::Biblios->find($item->biblionumber); + + my $matching_items = Koha::Items->search({ barcode => $item->barcode }); + + while (my $mbcitem = $matching_items->next) { + $mbcitem->delete if $mbcitem->biblionumber != $item->biblionumber; + } + + $t->put_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items/$item_id" => json => { external_id => 'something' }) + ->status_is(403, 'Not enough permissions to update an item'); + + # Add permissions + $builder->build( + { + source => 'UserPermission', + value => { + borrowernumber => $patron->borrowernumber, + module_bit => 9, + code => 'edit_catalogue' + } + } + ); + + my $other_item = $builder->build_sample_item(); + + $t->put_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items/$item_id" => json => { + external_id => $other_item->barcode, + }) + ->status_is(400, 'Barcode not unique'); + + $t->put_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items/$item_id" => json => { + replacement_price => 30, + }) + ->status_is(200, 'Item updated') + ->json_is('/replacement_price', 30); + + $schema->storage->txn_rollback; +}; \ No newline at end of file -- 2.39.5