From 3afacf536e1882641341c838567a803c05fba24c Mon Sep 17 00:00:00 2001
From: Tomas Cohen Arazi <tomascohen@theke.io>
Date: Mon, 3 Feb 2020 15:27:19 -0300
Subject: [PATCH] Bug 24857: Implement volume related controllers

Signed-off-by: Andrew Fuerste-Henry <andrew@bywatersolutions.com>

Signed-off-by: Rebecca  Coert <rcoert@arlingtonva.us>
---
 Koha/REST/V1/Biblios/Volumes.pm       | 244 ++++++++++++++++++++++++++
 Koha/REST/V1/Biblios/Volumes/Items.pm | 166 ++++++++++++++++++
 2 files changed, 410 insertions(+)
 create mode 100644 Koha/REST/V1/Biblios/Volumes.pm
 create mode 100644 Koha/REST/V1/Biblios/Volumes/Items.pm

diff --git a/Koha/REST/V1/Biblios/Volumes.pm b/Koha/REST/V1/Biblios/Volumes.pm
new file mode 100644
index 0000000000..64024334a6
--- /dev/null
+++ b/Koha/REST/V1/Biblios/Volumes.pm
@@ -0,0 +1,244 @@
+package Koha::REST::V1::Biblios::Volumes;
+
+# 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::Biblio::Volumes;
+
+use Scalar::Util qw(blessed);
+use Try::Tiny;
+
+=head1 NAME
+
+Koha::REST::V1::Biblios::Volumes - Koha REST API for handling volumes (V1)
+
+=head1 API
+
+=head2 Methods
+
+=cut
+
+=head3 list
+
+Controller function that handles listing Koha::Biblio::Volume objects
+
+=cut
+
+sub list {
+    my $c = shift->openapi->valid_input or return;
+
+    return try {
+        my $volumes_set = Koha::Biblio::Volumes->new;
+        my $volumes     = $c->objects->search( $volumes_set );
+        return $c->render(
+            status  => 200,
+            openapi => $volumes
+        );
+    }
+    catch {
+        unless ( blessed $_ && $_->can('rethrow') ) {
+            return $c->render(
+                status  => 500,
+                openapi => {
+                    error =>
+                      "Something went wrong, check Koha logs for details."
+                }
+            );
+        }
+        return $c->render(
+            status  => 500,
+            openapi => { error => "$_" }
+        );
+    };
+}
+
+=head3 get
+
+Controller function that handles retrieving a single Koha::Biblio::Volume
+
+=cut
+
+sub get {
+    my $c = shift->openapi->valid_input or return;
+
+    try {
+        my $volume = Koha::Biblio::Volumes->find($c->validation->param('volume_id'));
+        my $embed = $c->stash('koha.embed');
+
+        if ( $volume ) {
+            return $c->render(
+                status  => 200,
+                openapi => $volume->to_api({ embed => $embed })
+            );
+        }
+        else {
+            return $c->render(
+                status  => 404,
+                openapi => {
+                    error => 'Volume not found'
+                }
+            );
+        }
+    }
+    catch {
+        return $c->render(
+            status  => 500,
+            openapi => {
+                error => "Something went wrong, check the logs ($_)."
+            }
+        );
+    };
+}
+
+=head3 add
+
+Controller function to handle adding a Koha::Biblio::Volume object
+
+=cut
+
+sub add {
+    my $c = shift->openapi->valid_input or return;
+
+    return try {
+        my $volume_data = $c->validation->param('body');
+        # biblio_id comes from the path
+        $volume_data->{biblio_id} = $c->validation->param('biblio_id');
+
+        my $volume = Koha::Biblio::Volume->new_from_api($volume_data);
+        $volume->store->discard_changes();
+
+        $c->res->headers->location( $c->req->url->to_string . '/' . $volume->id );
+
+        return $c->render(
+            status  => 201,
+            openapi => $volume->to_api
+        );
+    }
+    catch {
+        if ( blessed($_) ) {
+            my $to_api_mapping = Koha::Biblio::Volume->new->to_api_mapping;
+
+            if ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) {
+                return $c->render(
+                    status  => 409,
+                    openapi => {
+                        error => "Given " . $to_api_mapping->{ $_->broken_fk } . " does not exist"
+                    }
+                );
+            }
+        }
+
+        return $c->render(
+            status  => 500,
+            openapi => {
+                error => "Unhandled exception ($_)"
+            }
+        );
+    };
+}
+
+=head3 update
+
+Controller function to handle updating a Koha::Biblio::Volume object
+
+=cut
+
+sub update {
+    my $c = shift->openapi->valid_input or return;
+
+    return try {
+        my $volume_id = $c->validation->param('volume_id');
+        my $volume = Koha::Biblio::Volumes->find( $volume_id );
+
+        unless ( $volume ) {
+            return $c->render(
+                status  => 404,
+                openapi => {
+                    error => 'Volume not found'
+                }
+            );
+        }
+
+        my $volume_data = $c->validation->param('body');
+        $volume->set_from_api( $volume_data )->store->discard_changes();
+
+        return $c->render(
+            status  => 200,
+            openapi => $volume->to_api
+        );
+    }
+    catch {
+        if ( blessed($_) ) {
+            my $to_api_mapping = Koha::Biblio::Volume->new->to_api_mapping;
+
+            if ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) {
+                return $c->render(
+                    status  => 409,
+                    openapi => {
+                        error => "Given " . $to_api_mapping->{ $_->broken_fk } . " does not exist"
+                    }
+                );
+            }
+        }
+
+        return $c->render(
+            status  => 500,
+            openapi => {
+                error => "Unhandled exception ($_)"
+            }
+        );
+    };
+}
+
+=head3 delete
+
+Controller function that handles deleting a Koha::Biblio::Volume object
+
+=cut
+
+sub delete {
+
+    my $c = shift->openapi->valid_input or return;
+
+    my $volume = Koha::Biblio::Volumes->find( $c->validation->param( 'volume_id' ) );
+
+    if ( not defined $volume ) {
+        return $c->render( status => 404, openapi => { error => "Volume not found" } );
+    }
+
+    return try {
+        $volume->delete;
+        return $c->render( status => 204, openapi => '');
+    }
+    catch {
+        unless ( blessed $_ && $_->can('rethrow') ) {
+            return $c->render(
+                status  => 500,
+                openapi => { error => "Something went wrong, check Koha logs for details." }
+            );
+        }
+
+        return $c->render(
+            status  => 500,
+            openapi => { error => "$_" }
+        );
+    };
+}
+
+1;
diff --git a/Koha/REST/V1/Biblios/Volumes/Items.pm b/Koha/REST/V1/Biblios/Volumes/Items.pm
new file mode 100644
index 0000000000..a41183423b
--- /dev/null
+++ b/Koha/REST/V1/Biblios/Volumes/Items.pm
@@ -0,0 +1,166 @@
+package Koha::REST::V1::Biblios::Volumes::Items;
+
+# 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::Biblio::Volume::Items;
+
+use Scalar::Util qw(blessed);
+use Try::Tiny;
+
+=head1 NAME
+
+Koha::REST::V1::Biblios::Volumes::Items - Koha REST API for handling volume items (V1)
+
+=head1 API
+
+=head2 Methods
+
+=head3 add
+
+Controller function to handle adding a Koha::Biblio::Volume object
+
+=cut
+
+sub add {
+    my $c = shift->openapi->valid_input or return;
+
+    return try {
+
+        my $volume = Koha::Biblio::Volumes->find(
+            $c->validation->param('volume_id')
+        );
+
+        unless ( $volume ) {
+            return $c->render(
+                status  => 404,
+                openapi => {
+                    error => 'Volume not found'
+                }
+            );
+        }
+
+        # All good, add the item
+        my $body    = $c->validation->param('body');
+        my $item_id = $body->{item_id};
+
+        $volume->add_item({ item_id => $item_id });
+
+        $c->res->headers->location( $c->req->url->to_string . '/' . $item_id );
+
+        my $embed = $c->stash('koha.embed');
+
+        return $c->render(
+            status  => 201,
+            openapi => $volume->to_api({ embed => $embed })
+        );
+    }
+    catch {
+        if ( blessed($_) ) {
+
+            if ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) {
+                if ( $_->broken_fk eq 'itemnumber' ) {
+                    return $c->render(
+                        status  => 409,
+                        openapi => {
+                            error => "Given item_id does not exist"
+                        }
+                    );
+                }
+                elsif ( $_->broken_fk eq 'biblionumber' ) {
+                    return $c->render(
+                        status  => 409,
+                        openapi => {
+                            error => "Given item_id does not belong to the volume's biblio"
+                        }
+                    );
+                }
+            }
+            elsif ( $_->isa('Koha::Exceptions::Object::DuplicateID') ) {
+
+                return $c->render(
+                    status  => 409,
+                    openapi => {
+                        error => "The given item_id is already linked to the volume"
+                    }
+                );
+            }
+        }
+
+        return $c->render(
+            status  => 500,
+            openapi => {
+                error => "Unhandled exception ($_)"
+            }
+        );
+    };
+}
+
+=head3 delete
+
+Controller function that handles deleting a Koha::Biblio::Volume object
+
+=cut
+
+sub delete {
+
+    my $c = shift->openapi->valid_input or return;
+
+    my $volume_id = $c->validation->param('volume_id');
+    my $item_id   = $c->validation->param('item_id');
+
+    my $item_link = Koha::Biblio::Volumes::Items->find(
+        {
+            itemnumber => $item_id,
+            volume_id  => $volume_id
+        }
+    );
+
+    unless ( $item_link ) {
+        return $c->render(
+            status  => 404,
+            openapi => {
+                error => 'No such volume <-> item relationship'
+            }
+        );
+    }
+
+    return try {
+        $item_link->delete;
+        return $c->render(
+            status  => 204,
+            openapi => ''
+        );
+    }
+    catch {
+        unless ( blessed $_ && $_->can('rethrow') ) {
+            return $c->render(
+                status  => 500,
+                openapi => { error => "Something went wrong, check Koha logs for details." }
+            );
+        }
+
+        return $c->render(
+            status  => 500,
+            openapi => { error => "$_" }
+        );
+    };
+}
+
+1;
-- 
2.24.1 (Apple Git-126)