From f7aa7c58ffe0c9b01bdd03eee588d070ba341cf4 Mon Sep 17 00:00:00 2001
From: Tomas Cohen Arazi <tomascohen@theke.io>
Date: Wed, 31 Mar 2021 08:04:12 -0300
Subject: [PATCH] Bug 28002: Add extended_attributes support to POST /patrons

This patch adds support for the 'extended_attributes' parameter in the
route for adding a patron. It relies on
Koha::Patron->extended_attributes for the tests. Exceptions are catch
and the whole operation is rolled back.

I chose to handle each exception on its own if branch, with bug 28020 in
mind.

To test:
1. Apply this patchset
2. Run:
   $ kshell
  k$ prove t/db_dependent/api/v1/patrons.t
=> SUCCES: Tests pass!
3. Check they cover all the exception situations!
=> SUCCESS: They do!
4. Sign off :-D

Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
---
 Koha/REST/V1/Patrons.pm | 125 +++++++++++++++++++++++++++-------------
 1 file changed, 86 insertions(+), 39 deletions(-)

diff --git a/Koha/REST/V1/Patrons.pm b/Koha/REST/V1/Patrons.pm
index 8c63705474..a88610bfda 100644
--- a/Koha/REST/V1/Patrons.pm
+++ b/Koha/REST/V1/Patrons.pm
@@ -19,6 +19,7 @@ use Modern::Perl;
 
 use Mojo::Base 'Mojolicious::Controller';
 
+use Koha::Database;
 use Koha::DateUtils;
 use Koha::Patrons;
 
@@ -103,53 +104,99 @@ sub add {
 
     return try {
 
-        my $patron = Koha::Patron->new_from_api( $c->validation->param('body') )->store;
+        Koha::Database->new->schema->txn_do(
+            sub {
 
-        $c->res->headers->location( $c->req->url->to_string . '/' . $patron->borrowernumber );
-        return $c->render(
-            status  => 201,
-            openapi => $patron->to_api
+                my $body = $c->validation->param('body');
+
+                my $extended_attributes = delete $body->{extended_attributes} // [];
+
+                my $patron = Koha::Patron->new_from_api($body)->store;
+                $patron->extended_attributes(
+                    [
+                        map { { code => $_->{type}, attribute => $_->{value} } }
+                          @$extended_attributes
+                    ]
+                );
+
+                $c->res->headers->location($c->req->url->to_string . '/' . $patron->borrowernumber);
+                return $c->render(
+                    status  => 201,
+                    openapi => $patron->to_api
+                );
+            }
         );
     }
     catch {
 
         my $to_api_mapping = Koha::Patron->new->to_api_mapping;
 
-        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 }
-            );
-        }
-        elsif ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) {
-            return $c->render(
-                status  => 400,
-                openapi => {
-                          error => "Given "
-                        . $to_api_mapping->{ $_->broken_fk }
-                        . " does not exist"
-                }
-            );
-        }
-        elsif ( $_->isa('Koha::Exceptions::BadParameter') ) {
-            return $c->render(
-                status  => 400,
-                openapi => {
-                          error => "Given "
-                        . $to_api_mapping->{ $_->parameter }
-                        . " does not exist"
-                }
-            );
-        }
-        else {
-            $c->unhandled_exception($_);
+        if ( blessed $_ ) {
+            if ( $_->isa('Koha::Exceptions::Object::DuplicateID') ) {
+                return $c->render(
+                    status  => 409,
+                    openapi => { error => $_->error, conflict => $_->duplicate_id }
+                );
+            }
+            elsif ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) {
+                return $c->render(
+                    status  => 400,
+                    openapi => {
+                            error => "Given "
+                            . $to_api_mapping->{ $_->broken_fk }
+                            . " does not exist"
+                    }
+                );
+            }
+            elsif ( $_->isa('Koha::Exceptions::BadParameter') ) {
+                return $c->render(
+                    status  => 400,
+                    openapi => {
+                            error => "Given "
+                            . $to_api_mapping->{ $_->parameter }
+                            . " does not exist"
+                    }
+                );
+            }
+            elsif (
+                $_->isa('Koha::Exceptions::Patron::MissingMandatoryExtendedAttribute')
+              )
+            {
+                return $c->render(
+                    status  => 400,
+                    openapi => { error => "$_" }
+                );
+            }
+            elsif (
+                $_->isa('Koha::Exceptions::Patron::Attribute::InvalidType')
+              )
+            {
+                return $c->render(
+                    status  => 400,
+                    openapi => { error => "$_" }
+                );
+            }
+            elsif (
+                $_->isa('Koha::Exceptions::Patron::Attribute::NonRepeatable')
+              )
+            {
+                return $c->render(
+                    status  => 400,
+                    openapi => { error => "$_" }
+                );
+            }
+            elsif (
+                $_->isa('Koha::Exceptions::Patron::Attribute::UniqueIDConstraint')
+              )
+            {
+                return $c->render(
+                    status  => 400,
+                    openapi => { error => "$_" }
+                );
+            }
         }
+
+        $c->unhandled_exception($_);
     };
 }
 
-- 
2.31.1