From 441cde5dbdf914953986cae2af9bb7bac569f87a Mon Sep 17 00:00:00 2001 From: Tomas Cohen Arazi Date: Tue, 5 Sep 2017 16:44:43 -0300 Subject: [PATCH] Bug 18731: /acquisitions/orders endpoint This patches implement the /acquisitions/orders endpoint. The attribute names are consistent with the voted RFC To test: 1. Apply this patchset 2. Run: $ kshell k$ prove t/db_dependent/api/v1/acquisitions_orders.t => SUCCESS: Tests pass! 3. Test the API with your favourite tool (Postman?) => SUCCESS: It works as expected! 4 Sign off :-D Sponsored-by: Camden County Signed-off-by: Matthias Meusburger Signed-off-by: Kyle M Hall Signed-off-by: Martin Renvoize --- Koha/Acquisition/Order.pm | 47 ++++++ Koha/REST/V1/Acquisitions/Orders.pm | 229 ++++++++++++++++++++++++++++ Koha/Schema/Result/Aqorder.pm | 3 + 3 files changed, 279 insertions(+) create mode 100644 Koha/REST/V1/Acquisitions/Orders.pm diff --git a/Koha/Acquisition/Order.pm b/Koha/Acquisition/Order.pm index 4a25814f2d..6d37e15c2b 100644 --- a/Koha/Acquisition/Order.pm +++ b/Koha/Acquisition/Order.pm @@ -264,6 +264,53 @@ sub duplicate_to { return $new_order; } +=head3 to_api_mapping + +This method returns the mapping for representing a Koha::Acquisition::Order object +on the API. + +=cut + +sub to_api_mapping { + return { + basketno => 'basket_id', + biblionumber => 'biblio_id', + budget_id => 'fund_id', + budgetdate => undef, # unused + cancellationreason => 'cancellation_reason', + claimed_date => 'last_claim_date', + datecancellationprinted => 'cancellation_date', + datereceived => 'date_received', + discount => 'discount_rate', + entrydate => 'entry_date', + freight => 'shipping_cost', + invoiceid => 'invoice_id', + line_item_id => undef, # EDIFACT related + listprice => 'list_price', + order_internalnote => 'internal_note', + order_vendornote => 'vendor_note', + ordernumber => 'order_id', + orderstatus => 'status', + parent_ordernumber => 'parent_order_id', + purchaseordernumber => undef, # obsolete + quantityreceived => 'quantity_received', + replacementprice => 'replacement_price', + sort1 => 'statistics_1', + sort1_authcat => 'statistics_1_authcat', + sort2 => 'statistics_2', + sort2_authcat => 'statistics_2_authcat', + subscriptionid => 'subscription_id', + suppliers_reference_number => undef, # EDIFACT related + suppliers_reference_qualifier => undef, # EDIFACT related + suppliers_report => undef, # EDIFACT related + tax_rate_bak => undef, # unused + tax_value_bak => undef, # unused + uncertainprice => 'uncertain_price', + unitprice => 'unit_price', + unitprice_tax_excluded => 'unit_price_tax_excluded', + unitprice_tax_included => 'unit_price_tax_included' + }; +} =head2 Internal methods diff --git a/Koha/REST/V1/Acquisitions/Orders.pm b/Koha/REST/V1/Acquisitions/Orders.pm new file mode 100644 index 0000000000..e32e17d6b8 --- /dev/null +++ b/Koha/REST/V1/Acquisitions/Orders.pm @@ -0,0 +1,229 @@ +package Koha::REST::V1::Acquisitions::Orders; + +# 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::Acquisition::Orders; +use Koha::DateUtils; + +use Scalar::Util qw( blessed ); +use Try::Tiny; + +=head1 NAME + +Koha::REST::V1::Acquisitions::Orders + +=head1 API + +=head2 Methods + +=head3 list + +Controller function that handles listing Koha::Acquisition::Order objects + +=cut + +sub list { + + my $c = shift->openapi->valid_input or return; + + return try { + my $orders = $c->objects->search( Koha::Acquisition::Orders->new ); + + return $c->render( + status => 200, + openapi => $orders + ); + } + catch { + if ( $_->isa('Koha::Exceptions::Exception') ) { + return $c->render( + status => 500, + openapi => { error => "Unhandled exception ($_)" } + ); + } + else { + return $c->render( + status => 500, + openapi => { error => "Something went wrong, check the logs. ($_)" } + ); + } + }; +} + +=head3 get + +Controller function that handles retrieving a single Koha::Aquisition::Order object + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + my $order = Koha::Acquisition::Orders->find( $c->validation->param('order_id') ); + + unless ($order) { + return $c->render( + status => 404, + openapi => { error => "Order not found" } + ); + } + + my $embed = $c->stash('koha.embed'); + + return $c->render( + status => 200, + openapi => $order->to_api({ embed => $embed }) + ); +} + +=head3 add + +Controller function that handles adding a new Koha::Acquisition::Order object + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + return try { + my $order = Koha::Acquisition::Order->new_from_api( $c->validation->param('body') ); + $order->store->discard_changes; + + $c->res->headers->location( + $c->req->url->to_string . '/' . $order->ordernumber + ); + + return $c->render( + status => 201, + openapi => $order->to_api + ); + } + catch { + unless ( blessed $_ && $_->can('rethrow') ) { + return $c->render( + status => 500, + openapi => { + error => + "Something went wrong, check Koha logs for details." + } + ); + } + if ( $_->isa('Koha::Exceptions::Object::DuplicateID') ) { + return $c->render( + status => 409, + openapi => { error => $_->error, conflict => $_->duplicate_id } + ); + } + else { + return $c->render( + status => 500, + openapi => { error => "$_" } + ); + } + }; +} + +=head3 update + +Controller function that handles updating a Koha::Acquisition::Order object + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $order = Koha::Acquisition::Orders->find( $c->validation->param('order_id') ); + + unless ($order) { + return $c->render( + status => 404, + openapi => { error => "Order not found" } + ); + } + + return try { + $order->set_from_api( $c->validation->param('body') ); + $order->store()->discard_changes; + + return $c->render( + status => 200, + openapi => $order->to_api + ); + } + catch { + if ( $_->isa('Koha::Exceptions::Exception') ) { + return $c->render( + status => 500, + openapi => { error => "Unhandled exception ($_)" } + ); + } + else { + return $c->render( + status => 500, + openapi => { error => "Something went wrong, check the logs." } + ); + } + }; +} + +=head3 delete + +Controller function that handles deleting a Koha::Patron object + +=cut + +sub delete { + my $c = shift->openapi->valid_input or return; + + my $order = Koha::Acquisition::Orders->find( $c->validation->param('order_id') ); + + unless ($order) { + return $c->render( + status => 404, + openapi => { error => 'Order not found' } + ); + } + + return try { + + $order->delete; + + return $c->render( + status => 204, + openapi => q{} + ); + } + catch { + if ( $_->isa('Koha::Exceptions::Exception') ) { + return $c->render( + status => 500, + openapi => { error => "Unhandled exception ($_)" } + ); + } + else { + return $c->render( + status => 500, + openapi => { error => "Something went wrong, check the logs." } + ); + } + }; +} + +1; diff --git a/Koha/Schema/Result/Aqorder.pm b/Koha/Schema/Result/Aqorder.pm index 803511822d..75917c88f5 100644 --- a/Koha/Schema/Result/Aqorder.pm +++ b/Koha/Schema/Result/Aqorder.pm @@ -670,5 +670,8 @@ sub koha_objects_class { sub koha_object_class { 'Koha::Acquisition::Order'; } +__PACKAGE__->add_columns( + '+uncertainprice' => { is_boolean => 1 } +); 1; -- 2.20.1