From daae0f3acc6cb8f9657eb7a3b27a39716914fcdb Mon Sep 17 00:00:00 2001 From: Tomas Cohen Arazi <tomascohen@theke.io> Date: Fri, 3 Mar 2017 15:52:22 +0000 Subject: [PATCH] Bug 17361: REST api | Add /items/messages endpoints This patch adds the following endpoints: - /items/{itemnumber}/messages - /items/{itemnumber}/messages/{item_message_id} for CRUD operation on item messages. Unit tests to come. --- Koha/REST/V1/Items/Messages.pm | 152 ++++++++++++++++ api/v1/swagger/definitions.json | 3 + api/v1/swagger/definitions/item_message.json | 25 +++ api/v1/swagger/parameters.json | 6 + api/v1/swagger/parameters/item.json | 9 + api/v1/swagger/parameters/item_message.json | 9 + api/v1/swagger/paths.json | 6 + api/v1/swagger/paths/item_messages.json | 255 +++++++++++++++++++++++++++ api/v1/swagger/x-primitives.json | 10 +- 9 files changed, 473 insertions(+), 2 deletions(-) create mode 100644 Koha/REST/V1/Items/Messages.pm create mode 100644 api/v1/swagger/definitions/item_message.json create mode 100644 api/v1/swagger/parameters/item.json create mode 100644 api/v1/swagger/parameters/item_message.json create mode 100644 api/v1/swagger/paths/item_messages.json diff --git a/Koha/REST/V1/Items/Messages.pm b/Koha/REST/V1/Items/Messages.pm new file mode 100644 index 0000000000..360d00deb7 --- /dev/null +++ b/Koha/REST/V1/Items/Messages.pm @@ -0,0 +1,152 @@ +package Koha::REST::V1::Items::Messages; + +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Koha::Items; +use Koha::Item::Message; +use Koha::Item::Messages; +use Koha::DateUtils; + +use Try::Tiny; + +sub list_item_messages { + my ( $c, $args, $cb ) = @_; + + if ( !Koha::Items->search({ itemnumber => $args->{itemnumber} })->count > 0 ) { + return $c->$cb( { error => 'Item not found' }, 400 ); + } + + return try { + my $item_messages = Koha::Item::Messages->search({ itemnumber => $args->{itemnumber} }); + return $c->$cb( $item_messages, 200 ); + } + catch { + if ( $_->isa('DBIx::Class::Exception') ) { + return $c->$cb( { error => $_->{msg} }, 500 ); + } + else { + return $c->$cb( { error => "Something went wrong, check the logs." }, 500 ); + } + }; +} + +sub get_item_message { + my ( $c, $args, $cb ) = @_; + + if ( !Koha::Items->search( { itemnumber => $args->{itemnumber} } )->count > 0 ) { + return $c->$cb( { error => 'Item not found' }, 400 ); + } + + return try { + my $item_message + = Koha::Item::Messages->search( + { itemnumber => $args->{itemnumber}, item_message_id => $args->{item_message_id} } ) + ->next; + if ($item_message) { + return $c->$cb( $item_message, 200 ); + } + else { + return $c->$cb( { error => 'Item message not found' }, 400 ); + } + } + catch { + if ( $_->isa('DBIx::Class::Exception') ) { + return $c->$cb( { error => $_->{msg} }, 500 ); + } + else { + return $c->$cb( { error => "Something went wrong, check the logs." }, 500 ); + } + }; +} + +sub add_item_message { + my ( $c, $args, $cb ) = @_; + + my $item_message = Koha::Item::Message->new( $args->{body} ); + $item_message->itemnumber( $args->{itemnumber} ); + + return try { + $item_message->store(); + $item_message = Koha::Item::Messages->find( $item_message->id ); + return $c->$cb( $item_message, 200 ); + } + catch { + if ( $_->isa('DBIx::Class::Exception') ) { + return $c->$cb( { error => $_->msg }, 500 ); + } + else { + return $c->$cb( { error => "Something went wrong, check the logs." }, 500 ); + } + }; +} + +sub update_item_message { + my ( $c, $args, $cb ) = @_; + + my $item_message; + + return try { + $item_message + = Koha::Item::Messages->search( + { itemnumber => $args->{itemnumber}, item_message_id => $args->{item_message_id} } ) + ->next; + $item_message->set( $args->{body} ); + $item_message->store(); + return $c->$cb( $item_message, 200 ); + } + catch { + if ( not defined $item_message ) { + return $c->$cb( { error => "Item message not found" }, 404 ); + } + elsif ( $_->isa('Koha::Exceptions::Object') ) { + return $c->$cb( { error => $_->message }, 500 ); + } + else { + return $c->$cb( { error => "Something went wrong, check the logs." }, 500 ); + } + }; + +} + +sub delete_item_message { + my ( $c, $args, $cb ) = @_; + + my $item_message; + + return try { + $item_message = Koha::Item::Messages->search( + { itemnumber => $args->{itemnumber}, item_message_id => $args->{item_message_id} } ); + $item_message->delete; + return $c->$cb( q{}, 200 ); + } + catch { + if ( not defined $item_message ) { + return $c->$cb( { error => "Item message not found" }, 404 ); + } + elsif ( $_->isa('DBIx::Class::Exception') ) { + return $c->$cb( { error => $_->msg }, 500 ); + } + else { + return $c->$cb( { error => "Something went wrong, check the logs." }, 500 ); + } + }; +} + +1; diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json index d27167b924..145e5c06a3 100644 --- a/api/v1/swagger/definitions.json +++ b/api/v1/swagger/definitions.json @@ -11,6 +11,9 @@ "hold": { "$ref": "definitions/hold.json" }, + "item_message": { + "$ref": "definitions/item_message.json" + }, "error": { "$ref": "definitions/error.json" } diff --git a/api/v1/swagger/definitions/item_message.json b/api/v1/swagger/definitions/item_message.json new file mode 100644 index 0000000000..1fcf6da8c1 --- /dev/null +++ b/api/v1/swagger/definitions/item_message.json @@ -0,0 +1,25 @@ +{ + "type": "object", + "properties": { + "item_message_id": { + "$ref": "../x-primitives.json#/item_message_id" + }, + "itemnumber": { + "$ref": "../x-primitives.json#/itemnumber" + }, + "type": { + "type": ["string", "null"], + "description": "date and time the item message was created" + }, + "message": { + "type": "string", + "description": "date and time the item message was created" + }, + "created_on": { + "type": "string", + "description": "date and time the item message was created" + } + }, + "additionalProperties": false, + "required": ["itemnumber","message"] +} diff --git a/api/v1/swagger/parameters.json b/api/v1/swagger/parameters.json index eeb156a7b8..0b780b045f 100644 --- a/api/v1/swagger/parameters.json +++ b/api/v1/swagger/parameters.json @@ -10,5 +10,11 @@ }, "holdIdPathParam": { "$ref": "parameters/hold.json#/holdIdPathParam" + }, + "itemIdPathParam": { + "$ref": "parameters/item.json#/itemIdPathParam" + }, + "itemMessageIdPathParam": { + "$ref": "parameters/item_message.json#/itemMessageIdPathParam" } } diff --git a/api/v1/swagger/parameters/item.json b/api/v1/swagger/parameters/item.json new file mode 100644 index 0000000000..3c618976f5 --- /dev/null +++ b/api/v1/swagger/parameters/item.json @@ -0,0 +1,9 @@ +{ + "itemIdPathParam": { + "name": "itemnumber", + "in": "path", + "description": "Internal item identifier", + "required": true, + "type": "integer" + } +} diff --git a/api/v1/swagger/parameters/item_message.json b/api/v1/swagger/parameters/item_message.json new file mode 100644 index 0000000000..5d9bb393db --- /dev/null +++ b/api/v1/swagger/parameters/item_message.json @@ -0,0 +1,9 @@ +{ + "itemMessageIdPathParam": { + "name": "item_message_id", + "in": "path", + "description": "Internal item message identifier", + "required": true, + "type": "integer" + } +} diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json index b1fcf40f5e..df09176abb 100644 --- a/api/v1/swagger/paths.json +++ b/api/v1/swagger/paths.json @@ -11,6 +11,12 @@ "/holds/{reserve_id}": { "$ref": "paths/holds.json#/~1holds~1{reserve_id}" }, + "/items/{itemnumber}/messages": { + "$ref": "paths/item_messages.json#/~1items~1{itemnumber}~1messages" + }, + "/items/{itemnumber}/messages/{item_message_id}": { + "$ref": "paths/item_messages.json#/~1items~1{itemnumber}~1messages~1{item_message_id}" + }, "/patrons": { "$ref": "paths/patrons.json#/~1patrons" }, diff --git a/api/v1/swagger/paths/item_messages.json b/api/v1/swagger/paths/item_messages.json new file mode 100644 index 0000000000..e88b249eb4 --- /dev/null +++ b/api/v1/swagger/paths/item_messages.json @@ -0,0 +1,255 @@ +{ + "/items/{itemnumber}/messages": { + "get": { + "x-mojo-controller": "Koha::REST::V1::Items::Messages", + "operationId": "listItemMessages", + "tags": ["items", "item_messages"], + "parameters": [ + { + "$ref": "../parameters.json#/itemIdPathParam" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "A list of item messages", + "schema": { + "type": "array", + "items": { + "$ref": "../definitions.json#/item_message" + } + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Object not found", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "catalogue": "1" + } + } + }, + "post": { + "x-mojo-controller": "Koha::REST::V1::Items::Messages", + "operationId": "addItemMessage", + "tags": ["items", "item_messages"], + "parameters": [ + { + "$ref": "../parameters.json#/itemIdPathParam" + }, + { + "name": "body", + "in": "body", + "description": "A JSON object representing an item message", + "required": true, + "schema": { + "$ref": "../definitions.json#/item_message" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Item message added", + "schema": { + "$ref": "../definitions.json#/item_message" + } + }, + "400": { + "description": "Missing or wrong parameters", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Object not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "allow-owner": true, + "permissions": { + "editcatalogue": "1" + } + } + } + }, + "/items/{itemnumber}/messages/{item_message_id}": { + "get": { + "x-mojo-controller": "Koha::REST::V1::Items::Messages", + "operationId": "getItemMessage", + "tags": ["items","item_messages"], + "parameters": [ + { + "$ref": "../parameters.json#/itemIdPathParam" + }, + { + "$ref": "../parameters.json#/itemMessageIdPathParam" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "An item messge", + "schema": { + "$ref": "../definitions.json#/item_message" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Vendor not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "catalogue": "1" + } + } + }, + "put": { + "x-mojo-controller": "Koha::REST::V1::Items::Messages", + "operationId": "updateItemMessage", + "tags": ["items","item_messages"], + "parameters": [ + { + "$ref": "../parameters.json#/itemIdPathParam" + }, + { + "$ref": "../parameters.json#/itemMessageIdPathParam" + }, + { + "name": "body", + "in": "body", + "description": "A JSON object representing an item message", + "required": true, + "schema": { + "$ref": "../definitions.json#/item_message" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Updated item message", + "schema": { + "$ref": "../definitions.json#/item_message" + } + }, + "400": { + "description": "Missing or wrong parameters", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Object not found", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "editcatalogue": "1" + } + } + }, + "delete": { + "x-mojo-controller": "Koha::REST::V1::Items::Messages", + "operationId": "deleteItemMessage", + "tags": ["items","item_messages"], + "parameters": [ + { + "$ref": "../parameters.json#/itemIdPathParam" + }, + { + "$ref": "../parameters.json#/itemMessageIdPathParam" + } + ], + "produces": ["application/json"], + "responses": { + "200": { + "description": "Item message deleted", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Object not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "editcatalogue": "1" + } + } + } + } +} diff --git a/api/v1/swagger/x-primitives.json b/api/v1/swagger/x-primitives.json index ae4e7395f6..c17855dd45 100644 --- a/api/v1/swagger/x-primitives.json +++ b/api/v1/swagger/x-primitives.json @@ -16,6 +16,11 @@ "description": "internally assigned city identifier", "readOnly": true }, + "item_message_id": { + "type": "integer", + "description": "internally assigned item message identifier", + "readOnly": true + }, "email": { "type": ["string", "null"], "description": "primary email address for patron's primary address" @@ -25,8 +30,9 @@ "description": "patron's first name" }, "itemnumber": { - "type": ["integer", "null"], - "description": "internally assigned item identifier" + "type": "integer", + "description": "internally assigned item identifier", + "readOnly": true }, "phone": { "type": ["string", "null"], -- 2.12.0