veeqo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.hound.yml +3 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +629 -0
  6. data/.sample.pryrc +4 -0
  7. data/.travis.yml +5 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +574 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +10 -0
  13. data/bin/rspec +17 -0
  14. data/bin/setup +8 -0
  15. data/lib/veeqo.rb +16 -0
  16. data/lib/veeqo/actions/base.rb +13 -0
  17. data/lib/veeqo/actions/delete.rb +11 -0
  18. data/lib/veeqo/actions/find.rb +11 -0
  19. data/lib/veeqo/actions/list.rb +11 -0
  20. data/lib/veeqo/allocation.rb +32 -0
  21. data/lib/veeqo/base.rb +26 -0
  22. data/lib/veeqo/company.rb +17 -0
  23. data/lib/veeqo/configuration.rb +17 -0
  24. data/lib/veeqo/customer.rb +24 -0
  25. data/lib/veeqo/delivery_method.rb +19 -0
  26. data/lib/veeqo/errors.rb +30 -0
  27. data/lib/veeqo/errors/forbidden.rb +9 -0
  28. data/lib/veeqo/errors/request_error.rb +15 -0
  29. data/lib/veeqo/errors/server_error.rb +9 -0
  30. data/lib/veeqo/errors/unauthorized.rb +9 -0
  31. data/lib/veeqo/order.rb +25 -0
  32. data/lib/veeqo/product.rb +25 -0
  33. data/lib/veeqo/purchase_order.rb +11 -0
  34. data/lib/veeqo/request.rb +89 -0
  35. data/lib/veeqo/response.rb +27 -0
  36. data/lib/veeqo/shipment.rb +30 -0
  37. data/lib/veeqo/store.rb +19 -0
  38. data/lib/veeqo/supplier.rb +19 -0
  39. data/lib/veeqo/version.rb +3 -0
  40. data/lib/veeqo/warehouse.rb +19 -0
  41. data/spec/fixtures/allocation_created.json +554 -0
  42. data/spec/fixtures/company.json +3 -0
  43. data/spec/fixtures/customer.json +4 -0
  44. data/spec/fixtures/customer_created.json +15 -0
  45. data/spec/fixtures/customers.json +38 -0
  46. data/spec/fixtures/delivery_method.json +3 -0
  47. data/spec/fixtures/delivery_method_created.json +4 -0
  48. data/spec/fixtures/delivery_methods.json +5 -0
  49. data/spec/fixtures/empty.json +0 -0
  50. data/spec/fixtures/order.json +3 -0
  51. data/spec/fixtures/order_created.json +554 -0
  52. data/spec/fixtures/orders.json +5 -0
  53. data/spec/fixtures/ping.json +3 -0
  54. data/spec/fixtures/product.json +4 -0
  55. data/spec/fixtures/product_created.json +137 -0
  56. data/spec/fixtures/products.json +5 -0
  57. data/spec/fixtures/purchase_orders.json +177 -0
  58. data/spec/fixtures/shipment_created.json +19 -0
  59. data/spec/fixtures/store.json +3 -0
  60. data/spec/fixtures/store_created.json +4 -0
  61. data/spec/fixtures/stores.json +5 -0
  62. data/spec/fixtures/supplier.json +3 -0
  63. data/spec/fixtures/supplier_created.json +4 -0
  64. data/spec/fixtures/suppliers.json +5 -0
  65. data/spec/fixtures/warehouse.json +3 -0
  66. data/spec/fixtures/warehouse_created.json +4 -0
  67. data/spec/fixtures/warehouses.json +5 -0
  68. data/spec/spec_helper.rb +15 -0
  69. data/spec/support/fake_veeqo_api.rb +408 -0
  70. data/spec/veeqo/actions/list_spec.rb +38 -0
  71. data/spec/veeqo/allocation_spec.rb +49 -0
  72. data/spec/veeqo/base_spec.rb +23 -0
  73. data/spec/veeqo/company_spec.rb +23 -0
  74. data/spec/veeqo/configuration_spec.rb +24 -0
  75. data/spec/veeqo/customer_spec.rb +77 -0
  76. data/spec/veeqo/delivery_method_spec.rb +65 -0
  77. data/spec/veeqo/order_spec.rb +93 -0
  78. data/spec/veeqo/product_spec.rb +82 -0
  79. data/spec/veeqo/purchase_order_spec.rb +14 -0
  80. data/spec/veeqo/request_spec.rb +40 -0
  81. data/spec/veeqo/shipment_spec.rb +38 -0
  82. data/spec/veeqo/store_spec.rb +61 -0
  83. data/spec/veeqo/supplier_spec.rb +61 -0
  84. data/spec/veeqo/warehouse_spec.rb +61 -0
  85. data/veeqo.gemspec +26 -0
  86. metadata +198 -0
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "veeqo"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rspec' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rspec-core", "rspec")
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,16 @@
1
+ require "veeqo/version"
2
+ require "veeqo/base"
3
+ require "veeqo/order"
4
+ require "veeqo/allocation"
5
+ require "veeqo/product"
6
+ require "veeqo/purchase_order"
7
+ require "veeqo/supplier"
8
+ require "veeqo/company"
9
+ require "veeqo/warehouse"
10
+ require "veeqo/customer"
11
+ require "veeqo/store"
12
+ require "veeqo/delivery_method"
13
+ require "veeqo/shipment"
14
+
15
+ module Veeqo
16
+ end
@@ -0,0 +1,13 @@
1
+ require "veeqo/actions/list"
2
+ require "veeqo/actions/find"
3
+ require "veeqo/actions/delete"
4
+
5
+ module Veeqo
6
+ module Actions
7
+ module Base
8
+ include Veeqo::Actions::List
9
+ include Veeqo::Actions::Find
10
+ include Veeqo::Actions::Delete
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ require "veeqo/request"
2
+
3
+ module Veeqo
4
+ module Actions
5
+ module Delete
6
+ def delete(resource_id)
7
+ Veeqo::Request.new(:delete, [end_point, resource_id].join("/")).parse
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require "veeqo/request"
2
+
3
+ module Veeqo
4
+ module Actions
5
+ module Find
6
+ def find(resource_id)
7
+ Veeqo::Request.new(:get, [end_point, resource_id].join("/")).parse
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require "veeqo/request"
2
+
3
+ module Veeqo
4
+ module Actions
5
+ module List
6
+ def list(filters = {})
7
+ Veeqo::Request.new(:get, end_point, filters).parse
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ module Veeqo
2
+ class Allocation < Base
3
+ include Veeqo::Actions::Delete
4
+
5
+ def create(order_id:, warehouse_id:, line_items:)
6
+ @order_id = order_id
7
+ create_resource(
8
+ warehouse_id: warehouse_id,
9
+ line_items_attributes: line_items,
10
+ )
11
+ end
12
+
13
+ def update(allocation_id, order_id:, line_items:, **attributes)
14
+ @order_id = order_id
15
+ update_resource(
16
+ allocation_id,
17
+ attributes.merge(line_items_attributes: line_items),
18
+ )
19
+ end
20
+
21
+ def delete(order_id, allocation_id)
22
+ @order_id = order_id
23
+ super(allocation_id)
24
+ end
25
+
26
+ private
27
+
28
+ def end_point
29
+ ["orders", @order_id, "allocations"].compact.join("/")
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ require "veeqo/request"
2
+ require "veeqo/actions/base"
3
+
4
+ module Veeqo
5
+ class Base
6
+ def self.method_missing(method_name, *arguments, &block)
7
+ if new.respond_to?(method_name, include_private: false)
8
+ new.send(method_name, *arguments, &block)
9
+ else
10
+ super
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def create_resource(attributes)
17
+ Veeqo::Request.new(:post, end_point, attributes).parse
18
+ end
19
+
20
+ def update_resource(resource_id, attributes)
21
+ Veeqo::Request.new(
22
+ :put, [end_point, resource_id].join("/"), attributes
23
+ ).parse
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ module Veeqo
2
+ class Company < Base
3
+ def find
4
+ Veeqo::Request.new(:get, end_point).parse
5
+ end
6
+
7
+ def update(attributes)
8
+ Veeqo::Request.new(:put, end_point, attributes).parse
9
+ end
10
+
11
+ private
12
+
13
+ def end_point
14
+ "current_company"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Veeqo
2
+ class Configuration
3
+ attr_accessor :api_host, :api_key
4
+
5
+ def initialize
6
+ @api_host ||= "api.veeqo.com"
7
+ end
8
+ end
9
+
10
+ def self.configure
11
+ yield configuration
12
+ end
13
+
14
+ def self.configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ module Veeqo
2
+ class Customer < Base
3
+ include Veeqo::Actions::Base
4
+
5
+ def create(email:, **attributes)
6
+ required_attributes = { email: email }
7
+ create_resource(customer: required_attributes.merge(attributes))
8
+ end
9
+
10
+ def update(customer_id, email:, **attributes)
11
+ required_attributes = { email: email }
12
+
13
+ update_resource(
14
+ customer_id, customer: required_attributes.merge(attributes)
15
+ )
16
+ end
17
+
18
+ private
19
+
20
+ def end_point
21
+ "customers"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ module Veeqo
2
+ class DeliveryMethod < Base
3
+ include Veeqo::Actions::Base
4
+
5
+ def create(name:)
6
+ create_resource(name: name)
7
+ end
8
+
9
+ def update(delivery_method_id, name:)
10
+ update_resource(delivery_method_id, name: name)
11
+ end
12
+
13
+ private
14
+
15
+ def end_point
16
+ "delivery_methods"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ require "veeqo/errors/request_error"
2
+ require "veeqo/errors/forbidden"
3
+ require "veeqo/errors/server_error"
4
+ require "veeqo/errors/unauthorized"
5
+
6
+ module Veeqo
7
+ module Errors
8
+ def self.server_errors
9
+ [
10
+ OpenSSL::SSL::SSLError,
11
+ Errno::ETIMEDOUT,
12
+ Errno::EHOSTUNREACH,
13
+ Errno::ENETUNREACH,
14
+ Errno::ECONNRESET,
15
+ Net::OpenTimeout,
16
+ SocketError,
17
+ Net::HTTPServerError,
18
+ ]
19
+ end
20
+
21
+ def self.error_klass_for(response)
22
+ case response
23
+ when *server_errors then Errors::ServerError
24
+ when Net::HTTPUnauthorized then Errors::Unauthorized
25
+ when Net::HTTPForbidden then Errors::Forbidden
26
+ else Errors::RequestError
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ module Veeqo
2
+ module Errors
3
+ class Forbidden < RequestError
4
+ def explanation
5
+ "A request to Veeqo API was considered forbidden by the server"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ module Veeqo
2
+ module Errors
3
+ class RequestError < StandardError
4
+ def message
5
+ explanation
6
+ end
7
+
8
+ def explanation
9
+ "A request to Veeqo API failed"
10
+ end
11
+ end
12
+ end
13
+
14
+ Error = Errors::RequestError
15
+ end
@@ -0,0 +1,9 @@
1
+ module Veeqo
2
+ module Errors
3
+ class ServerError < RequestError
4
+ def explanation
5
+ "A request to Veeqo API caused an unexpected server error"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Veeqo
2
+ module Errors
3
+ class Unauthorized < RequestError
4
+ def explanation
5
+ "A request to Veeqo API was sent without a valid authentication"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module Veeqo
2
+ class Order < Base
3
+ include Veeqo::Actions::Base
4
+
5
+ def create(channel_id:, customer_id:, delivery_method_id:, **attributes)
6
+ required_attributes = {
7
+ channel_id: channel_id,
8
+ customer_id: customer_id,
9
+ delivery_method_id: delivery_method_id,
10
+ }
11
+
12
+ create_resource(order: required_attributes.merge(attributes))
13
+ end
14
+
15
+ def update(order_id, attributes = {})
16
+ update_resource(order_id, attributes)
17
+ end
18
+
19
+ private
20
+
21
+ def end_point
22
+ "orders"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Veeqo
2
+ class Product < Base
3
+ include Veeqo::Actions::Base
4
+
5
+ def create(title:, variants:, images: [], **attributes)
6
+ required_attributes = {
7
+ title: title,
8
+ product_variants_attributes: variants,
9
+ images_attributes: images,
10
+ }
11
+
12
+ create_resource(product: required_attributes.merge(attributes))
13
+ end
14
+
15
+ def update(product_id, attributes)
16
+ update_resource(product_id, product: attributes)
17
+ end
18
+
19
+ private
20
+
21
+ def end_point
22
+ "products"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ module Veeqo
2
+ class PurchaseOrder < Base
3
+ include Veeqo::Actions::List
4
+
5
+ private
6
+
7
+ def end_point
8
+ "purchase_orders"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,89 @@
1
+ require "net/http"
2
+ require "veeqo/errors"
3
+ require "veeqo/response"
4
+ require "veeqo/configuration"
5
+
6
+ module Veeqo
7
+ class Request
8
+ def initialize(http_method, path, attributes = {})
9
+ @path = path
10
+ @http_method = http_method
11
+ @attributes = attributes
12
+ end
13
+
14
+ def run
15
+ valid_response || raise_response_error
16
+ end
17
+
18
+ def parse
19
+ Response.new(run).parse
20
+ end
21
+
22
+ private
23
+
24
+ def valid_response
25
+ if valid_response?
26
+ response
27
+ end
28
+ end
29
+
30
+ def raise_response_error
31
+ raise response_error
32
+ end
33
+
34
+ def valid_response?
35
+ response.is_a?(Net::HTTPSuccess)
36
+ end
37
+
38
+ def response
39
+ @response ||= send_http_request
40
+ rescue *server_errors => error
41
+ @response ||= error
42
+ end
43
+
44
+ def send_http_request
45
+ Net::HTTP.start(*net_http_options) do |http|
46
+ http.request(build_net_http_request)
47
+ end
48
+ end
49
+
50
+ def net_http_options
51
+ [uri.host, uri.port, use_ssl: true]
52
+ end
53
+
54
+ def build_net_http_request
55
+ request = constantize_net_http_class.new(uri)
56
+ set_request_headers!(request)
57
+ set_request_body!(request)
58
+ request
59
+ end
60
+
61
+ def uri
62
+ @uri ||= URI::HTTPS.build(
63
+ host: Veeqo.configuration.api_host,
64
+ path: ["", @path].join("/").squeeze("/"),
65
+ )
66
+ end
67
+
68
+ def constantize_net_http_class
69
+ Object.const_get("Net::HTTP::#{@http_method.to_s.capitalize}")
70
+ end
71
+
72
+ def set_request_body!(request)
73
+ request.body = @attributes.to_json
74
+ end
75
+
76
+ def set_request_headers!(request)
77
+ request.initialize_http_header("Content-Type" => "application/json")
78
+ request.initialize_http_header("x-api-key" => Veeqo.configuration.api_key)
79
+ end
80
+
81
+ def server_errors
82
+ Veeqo::Errors.server_errors
83
+ end
84
+
85
+ def response_error
86
+ Veeqo::Errors.error_klass_for(response)
87
+ end
88
+ end
89
+ end