From 6e9494cbe6210f922e62ccb67e89e360e1c747ba Mon Sep 17 00:00:00 2001
From: Andrew Isherwood <andrew.isherwood@ptfs-europe.com>
Date: Fri, 7 Feb 2020 15:21:49 +0000
Subject: [PATCH] Bug 24609: Create PUT /checkouts/{checkout_id}

This patch creates a PUT /checkouts/{checkout_id} API route enabling
checkouts to be updated

Signed-off-by: Lisette Scheer <lisettes@latahlibrary.org>
---
 Koha/REST/V1/Checkouts.pm                | 43 ++++++++++++++++++++++++
 api/v1/swagger/definitions/checkout.json | 14 ++++++++
 api/v1/swagger/paths/checkouts.json      | 39 +++++++++++++++++++++
 3 files changed, 96 insertions(+)

diff --git a/Koha/REST/V1/Checkouts.pm b/Koha/REST/V1/Checkouts.pm
index e670987bff..1063ea264f 100644
--- a/Koha/REST/V1/Checkouts.pm
+++ b/Koha/REST/V1/Checkouts.pm
@@ -204,4 +204,47 @@ sub allows_renewal {
     };
 }
 
+=head3 update
+
+Update a checkout
+
+=cut
+
+sub update {
+    my $c = shift->openapi->valid_input or return;
+
+    my $checkout_id = $c->validation->param('checkout_id');
+    my $checkout = Koha::Checkouts->find( $checkout_id );
+
+    unless ($checkout) {
+        return $c->render(
+            status => 404,
+            openapi => { error => "Checkout doesn't exist" }
+        );
+    }
+
+    return try {
+        my $params = $c->req->json;
+        $checkout->set_from_api( $params );
+        $checkout->store();
+        return $c->render(
+            status  => 200,
+            openapi => $checkout->to_api
+        );
+    }
+    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/api/v1/swagger/definitions/checkout.json b/api/v1/swagger/definitions/checkout.json
index 42bdf96e1a..6aabb00fb7 100644
--- a/api/v1/swagger/definitions/checkout.json
+++ b/api/v1/swagger/definitions/checkout.json
@@ -3,13 +3,16 @@
   "properties": {
     "checkout_id": {
       "type": "integer",
+      "readOnly": true,
       "description": "internally assigned checkout identifier"
     },
     "patron_id": {
+      "readOnly": true,
       "$ref": "../x-primitives.json#/patron_id"
     },
     "item_id": {
       "type": "integer",
+      "readOnly": true,
       "description": "internal identifier of checked out item"
     },
     "due_date": {
@@ -19,6 +22,7 @@
     },
     "library_id": {
       "type": ["string", "null"],
+      "readOnly": true,
       "description": "code of the library the item was checked out"
     },
     "issuer_id": {
@@ -27,16 +31,19 @@
     },
     "checkin_date": {
       "type": ["string", "null"],
+      "readOnly": true,
       "format": "date-time",
       "description": "Date the item was returned"
     },
     "last_renewed_date": {
       "type": ["string", "null"],
+      "readOnly": true,
       "format": "date-time",
       "description": "Date the item was last renewed"
     },
     "renewals": {
       "type": ["integer", "null"],
+      "readOnly": true,
       "description": "Number of renewals"
     },
     "unseen_renewals": {
@@ -45,31 +52,38 @@
     },
     "auto_renew": {
       "type": "boolean",
+      "readOnly": true,
       "description": "Auto renewal"
     },
     "auto_renew_error": {
       "type": ["string", "null"],
+      "readOnly": true,
       "description": "Auto renewal error"
     },
     "timestamp": {
       "type": "string",
+      "readOnly": true,
       "description": "Last update time"
     },
     "checkout_date": {
       "type": "string",
+      "readOnly": true,
       "format": "date-time",
       "description": "Date the item was issued"
     },
     "onsite_checkout": {
       "type": "boolean",
+      "readOnly": true,
       "description": "On site checkout"
     },
     "note": {
       "type": ["string", "null"],
+      "readOnly": true,
       "description": "Issue note text"
     },
     "note_date": {
       "type": ["string", "null"],
+      "readOnly": true,
       "format": "date",
       "description": "Datetime of the issue note"
     },
diff --git a/api/v1/swagger/paths/checkouts.json b/api/v1/swagger/paths/checkouts.json
index e79a5db01d..117fa53f08 100644
--- a/api/v1/swagger/paths/checkouts.json
+++ b/api/v1/swagger/paths/checkouts.json
@@ -82,6 +82,45 @@
       "x-koha-embed": [
         "issuer"
       ]
+    },
+    "put": {
+      "x-mojo-to": "Checkouts#update",
+      "operationId": "updateCheckout",
+      "tags": ["patrons", "checkouts"],
+      "parameters": [
+        {
+          "$ref": "../parameters.json#/checkout_id_pp"
+        },
+        {
+          "name": "body",
+          "in": "body",
+          "description": "A JSON object containing information on the checkout",
+          "required": true,
+          "schema": {
+            "$ref": "../definitions.json#/checkout"
+          }
+        }
+      ],
+      "produces": ["application/json"],
+      "responses": {
+        "200": {
+          "description": "Updated borrower's checkout",
+          "schema": { "$ref": "../definitions.json#/checkout" }
+        },
+        "403": {
+          "description": "Access forbidden",
+          "schema": { "$ref": "../definitions.json#/error" }
+        },
+        "404": {
+          "description": "Checkout not found",
+          "schema": { "$ref": "../definitions.json#/error" }
+        }
+      },
+      "x-koha-authorization": {
+        "permissions": {
+          "circulate": "circulate_remaining_permissions"
+        }
+      }
     }
   },
   "/checkouts/{checkout_id}/renewal": {
-- 
2.20.1