Bug 18120: Add '/acquisitions/vendors' endpoint
authorTomas Cohen Arazi <tomascohen@theke.io>
Tue, 28 Feb 2017 12:00:07 +0000 (09:00 -0300)
committerJonathan Druart <jonathan.druart@bugs.koha-community.org>
Fri, 29 Sep 2017 20:13:13 +0000 (17:13 -0300)
This patch introduces an /acquisitions/vendors endpoint.
To test:
- Apply the patch
- Run:
  $ sudo koha-shell kohadev
 k$ prove t/db_dependent/api/v1/acquisitions_vendors.t
=> SUCCESS: Tests pass
- Sign off :-D

Sponsored-by: ByWater Solutions

Signed-off-by: Matthias Meusburger <matthias.meusburger@biblibre.com>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Koha/REST/V1/Acquisitions/Vendors.pm [new file with mode: 0644]
Koha/Schema/Result/Aqbookseller.pm
api/v1/swagger/definitions.json
api/v1/swagger/definitions/vendor.json [new file with mode: 0644]
api/v1/swagger/parameters.json
api/v1/swagger/parameters/vendor.json [new file with mode: 0644]
api/v1/swagger/paths.json
api/v1/swagger/paths/acquisitions_vendors.json [new file with mode: 0644]
api/v1/swagger/x-primitives.json

diff --git a/Koha/REST/V1/Acquisitions/Vendors.pm b/Koha/REST/V1/Acquisitions/Vendors.pm
new file mode 100644 (file)
index 0000000..a8302c8
--- /dev/null
@@ -0,0 +1,197 @@
+package Koha::REST::V1::Acquisitions::Vendors;
+
+# 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::Booksellers;
+
+use Try::Tiny;
+
+sub list_vendors {
+    my $c = shift->openapi->valid_input or return;
+
+    my $args = _to_model($c->req->params->to_hash);
+    my $filter;
+
+    for my $filter_param ( keys %$args ) {
+        $filter->{$filter_param} = { LIKE => $args->{$filter_param} . "%" }
+            if $args->{$filter_param};
+    }
+
+    my @vendors;
+
+    return try {
+        @vendors = Koha::Acquisition::Booksellers->search($filter);
+        @vendors = map { _to_api($_->TO_JSON) } @vendors;
+        return $c->render( status  => 200,
+                           openapi => \@vendors );
+    }
+    catch {
+        if ( $_->isa('DBIx::Class::Exception') ) {
+            return $c->render( status  => 500,
+                               openapi => { error => $_->{msg} } );
+        }
+        else {
+            return $c->render( status  => 500,
+                               openapi => { error => "Something went wrong, check the logs." } );
+        }
+    };
+}
+
+sub get_vendor {
+    my $c = shift->openapi->valid_input or return;
+
+    my $vendor = Koha::Acquisition::Booksellers->find( $c->validation->param('vendor_id') );
+    unless ($vendor) {
+        return $c->render( status  => 404,
+                           openapi => { error => "Vendor not found" } );
+    }
+
+    return $c->render( status  => 200,
+                       openapi => _to_api($vendor->TO_JSON) );
+}
+
+sub add_vendor {
+    my $c = shift->openapi->valid_input or return;
+
+    my $vendor = Koha::Acquisition::Bookseller->new( _to_model( $c->validation->param('body') ) );
+
+    return try {
+        $vendor->store;
+        return $c->render( status  => 200,
+                           openapi => _to_api($vendor->TO_JSON) );
+    }
+    catch {
+        if ( $_->isa('DBIx::Class::Exception') ) {
+            return $c->render( status  => 500,
+                               openapi => { error => $_->msg } );
+        }
+        else {
+            return $c->render( status  => 500,
+                               openapi => { error => "Something went wrong, check the logs." } );
+        }
+    };
+}
+
+sub update_vendor {
+    my $c = shift->openapi->valid_input or return;
+
+    my $vendor;
+
+    return try {
+        $vendor = Koha::Acquisition::Booksellers->find( $c->validation->param('vendor_id') );
+        $vendor->set( _to_model( $c->validation->param('body') ) );
+        $vendor->store();
+        return $c->render( status  => 200,
+                           openapi => _to_api($vendor->TO_JSON) );
+    }
+    catch {
+        if ( not defined $vendor ) {
+            return $c->render( status  => 404,
+                               openapi => { error => "Object not found" } );
+        }
+        elsif ( $_->isa('Koha::Exceptions::Object') ) {
+            return $c->render( status  => 500,
+                               openapi => { error => $_->message } );
+        }
+        else {
+            return $c->render( status  => 500,
+                               openapi => { error => "Something went wrong, check the logs." } );
+        }
+    };
+
+}
+
+sub delete_vendor {
+    my $c = shift->openapi->valid_input or return;
+
+    my $vendor;
+
+    return try {
+        $vendor = Koha::Acquisition::Booksellers->find( $c->validation->param('vendor_id') );
+        $vendor->delete;
+        return $c->render( status => 200,
+                           openapi => q{} );
+    }
+    catch {
+        if ( not defined $vendor ) {
+            return $c->render( status  => 404,
+                               openapi => { error => "Object not found" } );
+        }
+        elsif ( $_->isa('DBIx::Class::Exception') ) {
+            return $c->render( status  => 500,
+                               openapi => { error => $_->msg } );
+        }
+        else {
+            return $c->render( status  => 500,
+                               openapi => { error => "Something went wrong, check the logs." } );
+        }
+    };
+
+}
+
+sub _to_api {
+
+    my $vendor = shift;
+
+    #my $vendor = $vendor_param->TO_JSON;
+
+    # Delete unused fields
+    delete $vendor->{booksellerfax};
+    delete $vendor->{bookselleremail};
+    delete $vendor->{booksellerurl};
+    delete $vendor->{currency};
+    delete $vendor->{othersupplier};
+
+    # Rename changed fields
+    $vendor->{list_currency} = $vendor->{listprice};
+    delete $vendor->{listprice};
+    $vendor->{invoice_currency} = $vendor->{invoiceprice};
+    delete $vendor->{invoiceprice};
+    $vendor->{gst} = $vendor->{gstreg};
+    delete $vendor->{gstreg};
+    $vendor->{list_includes_gst} = $vendor->{listincgst};
+    delete $vendor->{listincgst};
+    $vendor->{invoice_includes_gst} = $vendor->{invoiceincgst};
+    delete $vendor->{invoiceincgst};
+
+    return $vendor;
+}
+
+sub _to_model {
+    my $vendor_param = shift;
+
+    my $vendor = $vendor_param;
+
+    # Rename back
+    $vendor->{listprice} = $vendor->{list_currency};
+    delete $vendor->{list_currency};
+    $vendor->{invoiceprice} = $vendor->{invoice_currency};
+    delete $vendor->{invoice_currency};
+    $vendor->{gstreg} = $vendor->{gst};
+    delete $vendor->{gst};
+    $vendor->{listincgst} = $vendor->{list_includes_gst};
+    delete $vendor->{list_includes_gst};
+    $vendor->{invoiceincgst} = $vendor->{invoice_includes_gst};
+    delete $vendor->{invoice_includes_gst};
+
+    return $vendor;
+}
+
+1;
index e9c2656..e59b705 100644 (file)
@@ -385,6 +385,13 @@ __PACKAGE__->has_many(
 # Created by DBIx::Class::Schema::Loader v0.07042 @ 2016-09-09 13:43:30
 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:b3aUNZsdvNzEuKScGD7ZPQ
 
+__PACKAGE__->add_columns(
+    '+active' => { is_boolean => 1 },
+    '+gstreg' => { is_boolean => 1 },
+    '+listincgst' => { is_boolean => 1 },
+    '+invoiceincgst' => { is_boolean => 1 },
+);
+
 
 # You can replace this text with custom code or comments, and it will be preserved on regeneration
 1;
index 939baa8..340b9a9 100644 (file)
   },
   "patron": {
     "$ref": "definitions/patron.json"
+  },
+  "error": {
+    "$ref": "definitions/error.json"
+  },
+  "vendor": {
+    "$ref": "definitions/vendor.json"
   }
 }
diff --git a/api/v1/swagger/definitions/vendor.json b/api/v1/swagger/definitions/vendor.json
new file mode 100644 (file)
index 0000000..f24bdde
--- /dev/null
@@ -0,0 +1,149 @@
+{
+  "type": "object",
+  "properties": {
+    "id": {
+      "$ref": "../x-primitives.json#/vendor_id"
+    },
+    "name": {
+      "type": [
+        "string"
+      ],
+      "description": "Vendor name"
+    },
+    "address1": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor physical address (line 1)"
+    },
+    "address2": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor physical address (line 2)"
+    },
+    "address3": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor physical address (line 3)"
+    },
+    "address4": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor physical address (line 4)"
+    },
+    "phone": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor phone number"
+    },
+    "fax": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor fax number"
+    },
+    "accountnumber": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor account number"
+    },
+    "notes": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor notes"
+    },
+    "postal": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor postal address"
+    },
+    "url": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Vendor web address"
+    },
+    "active": {
+      "type": [
+        "boolean",
+        "null"
+      ],
+      "description": "Is this vendor active"
+    },
+    "list_currency": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "List prices currency"
+    },
+    "invoice_currency": {
+      "type": [
+        "string",
+        "null"
+      ],
+      "description": "Invoice prices currency"
+    },
+    "gst": {
+      "type": [
+        "boolean",
+        "null"
+      ],
+      "description": "Is the library taxed when buying to this vendor"
+    },
+    "list_includes_gst": {
+      "type": [
+        "boolean",
+        "null"
+      ],
+      "description": "List prices include taxes"
+    },
+    "invoice_includes_gst": {
+      "type": [
+        "boolean",
+        "null"
+      ],
+      "description": "Invoice prices include taxes"
+    },
+    "tax_rate": {
+      "type": [
+        "number",
+        "null"
+      ],
+      "description": "Tax rate"
+    },
+    "discount": {
+      "type": [
+        "number",
+        "null"
+      ],
+      "description": "Discount offered on all items ordered from this vendor"
+    },
+    "deliverytime": {
+      "type": [
+        "integer",
+        "null"
+      ],
+      "description": "Vendor expected delivery time (in days)"
+    }
+  },
+  "additionalProperties": false,
+  "required": ["name"]
+}
index eeb156a..b8835d2 100644 (file)
@@ -10,5 +10,8 @@
   },
   "holdIdPathParam": {
     "$ref": "parameters/hold.json#/holdIdPathParam"
+  },
+  "vendoridPathParam": {
+    "$ref": "parameters/vendor.json#/vendoridPathParam"
   }
 }
diff --git a/api/v1/swagger/parameters/vendor.json b/api/v1/swagger/parameters/vendor.json
new file mode 100644 (file)
index 0000000..64dbea0
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "vendoridPathParam": {
+      "name": "vendor_id",
+      "in": "path",
+      "description": "Vendor id",
+      "required": true,
+      "type": "integer"
+    }
+}
index b1fcf40..147e985 100644 (file)
@@ -1,4 +1,10 @@
 {
+  "/acquisitions/vendors": {
+    "$ref": "paths/acquisitions_vendors.json#/~1acquisitions~1vendors"
+  },
+  "/acquisitions/vendors/{vendor_id}": {
+    "$ref": "paths/acquisitions_vendors.json#/~1acquisitions~1vendors~1{vendor_id}"
+  },
   "/cities": {
     "$ref": "paths/cities.json#/~1cities"
   },
diff --git a/api/v1/swagger/paths/acquisitions_vendors.json b/api/v1/swagger/paths/acquisitions_vendors.json
new file mode 100644 (file)
index 0000000..a34c72a
--- /dev/null
@@ -0,0 +1,303 @@
+{
+  "/acquisitions/vendors": {
+    "get": {
+      "x-mojo-to": "Acquisitions::Vendors#list_vendors",
+      "operationId": "listVendors",
+      "tags": ["acquisitions","vendors"],
+      "produces": [
+        "application/json"
+      ],
+      "parameters": [{
+        "name": "name",
+        "in": "query",
+        "description": "Case insensitive search on vendor name",
+        "required": false,
+        "type": "string"
+      }, {
+        "name": "accountnumber",
+        "in": "query",
+        "description": "Case insensitive search on vendor's account number",
+        "required": false,
+        "type": "string"
+      }],
+      "responses": {
+        "200": {
+          "description": "A list of vendors",
+          "schema": {
+            "type": "array",
+            "items": {
+              "$ref": "../definitions.json#/vendor"
+            }
+          }
+        },
+        "401": {
+          "description": "Authentication required",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "403": {
+          "description": "Access forbidden",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "404": {
+          "description": "Vendor not found",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "500": {
+          "description": "Internal server error",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "503": {
+          "description": "Under maintenance",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        }
+      },
+      "x-koha-authorization": {
+        "permissions": {
+          "acquisition": "1"
+        }
+      }
+    },
+    "post": {
+      "x-mojo-to": "Acquisitions::Vendors#add_vendor",
+      "operationId": "addVendor",
+      "tags": ["acquisitions","vendors"],
+      "parameters": [{
+        "name": "body",
+        "in": "body",
+        "description": "A JSON object representing a vendor",
+        "required": true,
+        "schema": {
+          "$ref": "../definitions.json#/vendor"
+        }
+      }],
+      "produces": [
+        "application/json"
+      ],
+      "responses": {
+        "200": {
+          "description": "Vendor added",
+          "schema": {
+            "$ref": "../definitions.json#/vendor"
+          }
+        },
+        "401": {
+          "description": "Authentication required",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "403": {
+          "description": "Access forbidden",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "404": {
+          "description": "Vendor not found",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "500": {
+          "description": "Internal server error",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "503": {
+          "description": "Under maintenance",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        }
+      },
+      "x-koha-authorization": {
+        "permissions": {
+          "acquisition": "vendors_manage"
+        }
+      }
+    }
+  },
+  "/acquisitions/vendors/{vendor_id}": {
+    "get": {
+      "x-mojo-to": "Acquisitions::Vendors#get_vendor",
+      "operationId": "getVendor",
+      "tags": ["acquisitions","vendors"],
+      "parameters": [{
+        "$ref": "../parameters.json#/vendoridPathParam"
+      }],
+      "produces": [
+        "application/json"
+      ],
+      "responses": {
+        "200": {
+          "description": "A vendor",
+          "schema": {
+            "$ref": "../definitions.json#/vendor"
+          }
+        },
+        "401": {
+          "description": "Authentication required",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "403": {
+          "description": "Access forbidden",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "404": {
+          "description": "Vendor not found",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "500": {
+          "description": "Internal server error",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "503": {
+          "description": "Under maintenance",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        }
+      },
+      "x-koha-authorization": {
+        "permissions": {
+          "acquisition": "1"
+        }
+      }
+    },
+    "put": {
+      "x-mojo-to": "Acquisitions::Vendors#update_vendor",
+      "operationId": "updateVendor",
+      "tags": ["acquisitions","vendors"],
+      "parameters": [{
+        "$ref": "../parameters.json#/vendoridPathParam"
+      }, {
+        "name": "body",
+        "in": "body",
+        "description": "A JSON object representing a vendor",
+        "required": true,
+        "schema": {
+          "$ref": "../definitions.json#/vendor"
+        }
+      }],
+      "produces": [
+        "application/json"
+      ],
+      "responses": {
+        "200": {
+          "description": "A vendor",
+          "schema": {
+            "$ref": "../definitions.json#/vendor"
+          }
+        },
+        "401": {
+          "description": "Authentication required",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "403": {
+          "description": "Access forbidden",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "404": {
+          "description": "Vendor not found",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "500": {
+          "description": "Internal server error",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "503": {
+          "description": "Under maintenance",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        }
+      },
+      "x-koha-authorization": {
+        "permissions": {
+          "acquisition": "1"
+        }
+      }
+    },
+    "delete": {
+      "x-mojo-to": "Acquisitions::Vendors#delete_vendor",
+      "operationId": "deleteVendor",
+      "tags": ["acquisitions","vendors"],
+      "parameters": [{
+        "$ref": "../parameters.json#/vendoridPathParam"
+      }],
+      "produces": [
+        "application/json"
+      ],
+      "responses": {
+        "200": {
+          "description": "Vendor deleted",
+          "schema": {
+            "type": "string"
+          }
+        },
+        "401": {
+          "description": "Authentication required",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "403": {
+          "description": "Access forbidden",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "404": {
+          "description": "Vendor not found",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "500": {
+          "description": "Internal server error",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "503": {
+          "description": "Under maintenance",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        }
+      },
+      "x-koha-authorization": {
+        "permissions": {
+          "acquisition": "1"
+        }
+      }
+    }
+  }
+}
index ae4e739..12e5e9d 100644 (file)
   "surname": {
     "type": "string",
     "description": "patron's last name"
+  },
+  "vendor_id": {
+    "type": "integer",
+    "description": "internally assigned vendor identifier",
+    "readOnly": true
   }
 }