seko 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +23 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +210 -0
  8. data/Rakefile +1 -0
  9. data/lib/seko/client.rb +236 -0
  10. data/lib/seko/company.rb +33 -0
  11. data/lib/seko/dispatch.rb +22 -0
  12. data/lib/seko/filter.rb +9 -0
  13. data/lib/seko/order.rb +77 -0
  14. data/lib/seko/product.rb +27 -0
  15. data/lib/seko/receipt.rb +36 -0
  16. data/lib/seko/response.rb +33 -0
  17. data/lib/seko/shipping.rb +26 -0
  18. data/lib/seko/stock.rb +9 -0
  19. data/lib/seko/tracking.rb +22 -0
  20. data/lib/seko/version.rb +3 -0
  21. data/lib/seko.rb +31 -0
  22. data/seko.gemspec +27 -0
  23. data/spec/fixtures/company_submit.json +21 -0
  24. data/spec/fixtures/dispatch_statuses.json +25 -0
  25. data/spec/fixtures/grn.json +45 -0
  26. data/spec/fixtures/order_status.json +11 -0
  27. data/spec/fixtures/order_submit.json +33 -0
  28. data/spec/fixtures/order_tracking.json +12 -0
  29. data/spec/fixtures/order_websubmit.json +29 -0
  30. data/spec/fixtures/product_submit.json +15 -0
  31. data/spec/fixtures/receipt_submit.json +26 -0
  32. data/spec/fixtures/stock.json +29 -0
  33. data/spec/fixtures/stock_adjustment.json +7 -0
  34. data/spec/fixtures/stock_movement.json +7 -0
  35. data/spec/lib/client_spec.rb +364 -0
  36. data/spec/lib/company_spec.rb +22 -0
  37. data/spec/lib/dispatch_spec.rb +17 -0
  38. data/spec/lib/filter_spec.rb +12 -0
  39. data/spec/lib/order_spec.rb +60 -0
  40. data/spec/lib/product_spec.rb +23 -0
  41. data/spec/lib/receipt_spec.rb +36 -0
  42. data/spec/lib/response_spec.rb +53 -0
  43. data/spec/lib/stock_spec.rb +12 -0
  44. data/spec/logs/spec.log +0 -0
  45. data/spec/spec_helper.rb +176 -0
  46. metadata +196 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7ccf252a5f73196d16afac7f326d8fca9163f7dc
4
+ data.tar.gz: 2fb7c168442260f3b587d28e7823fb497bc98254
5
+ SHA512:
6
+ metadata.gz: 1bd565235abd405f4f44d2bf98a1942770ca3b4252ddffd0d83affd78db0d0a1680de9661f0df2f6a2e19d7c5d820e2b9f25f062d9fa5fc9b1cc2f90b3146d3b
7
+ data.tar.gz: eafb4f39d5629a62b5554b09cbdf8678a810c1f65129693e0a95d1ec4f0312394e6cc9e42e9a617f814b8629651404c69c91f1654f0ed6338077385a28eaa336
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,23 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+
5
+ matrix:
6
+ allow_failures:
7
+ - rvm: rbx-19mode
8
+
9
+ script:
10
+ - CODECLIMATE_REPO_TOKEN=dd4351c1e437fe6bb682de8e30eae582e627b4e0959ed3202839ad057af5d4d1 bundle exec rspec
11
+
12
+ # addons:
13
+ # code_climate:
14
+ # repo_token: dd4351c1e437fe6bb682de8e30eae582e627b4e0959ed3202839ad057af5d4d1
15
+
16
+ notifications:
17
+ email:
18
+ - justin@jgrubbs.net
19
+
20
+ gemfile:
21
+ - Gemfile
22
+
23
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in seko.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Justin Grubbs
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # Seko
2
+
3
+ [![Build Status](https://travis-ci.org/jGRUBBS/seko-ruby-api.svg?branch=master)](https://travis-ci.org/jGRUBBS/seko-ruby-api.svg?branch=master)
4
+ [![Code Climate](https://codeclimate.com/github/jGRUBBS/seko-ruby-api/badges/gpa.svg)](https://codeclimate.com/github/jGRUBBS/seko-ruby-api)
5
+ [![Test Coverage](https://codeclimate.com/github/jGRUBBS/seko-ruby-api/badges/coverage.svg)](https://codeclimate.com/github/jGRUBBS/seko-ruby-api)
6
+
7
+ Ruby wrapper for Seko Logistics' SupplyStream iHub REST API v1
8
+
9
+ [SupplyStream REST API Documentation](https://wiki.supplystream.com/GetFile.aspx?Page=MANUAL.Integration-Hub-Rest-APIs&File=integration-ihub-rest-apis-v1.4.pdf)
10
+
11
+ ## Integrations
12
+
13
+ 1. **Inbound Product Master Upload and method**
14
+ 2. **Inbound Companies Upload and method**
15
+ 3. **Inbound Advanced Shipment Notification**
16
+ 4. **Inbound Sales Order / Cancel Orders**
17
+ 5. **Retrieve GRN’s**
18
+ 6. **Retrieve Stock Quantity**
19
+ 7. **Retrieve Tracking Details**
20
+ 8. **Retrieve Sales Order Status**
21
+ 9. **Retrieve Stock Adjustments**
22
+ 10. **Retrieve Stock Movements**
23
+
24
+ ## Installation
25
+
26
+ Add this line to your application's Gemfile:
27
+
28
+ ```ruby
29
+ gem 'seko'
30
+ ```
31
+
32
+ And then execute:
33
+
34
+ $ bundle
35
+
36
+ Or install it yourself as:
37
+
38
+ $ gem install seko
39
+
40
+ ## Usage
41
+ #### Configuration
42
+ config/initializers/seko.rb
43
+ ```ruby
44
+ Seko.configure(
45
+ token: 'SekoAPIToKeN'
46
+ supplier_code: 'DEFSUPLJLTD001',
47
+ supplier_description: 'Default Supplier LARSSON & JENNINGS LTD',
48
+ supplier_uom: 1,
49
+ warehouses: {
50
+ us: 'US123',
51
+ uk: 'UK123'
52
+ }
53
+ )
54
+ ```
55
+
56
+ #### Submit Product
57
+
58
+ ```ruby
59
+ client = Seko::Client.new(Seko.config[:token])
60
+ response = client.submit_product(upc: "123456", description: 'A test product')
61
+ ```
62
+
63
+ #### Submit Receipt
64
+
65
+ ```ruby
66
+ line_items = [ { upc: "123456", quantity: 10 } ]
67
+ warehouse = Seko.config[:warehouses][:us]
68
+ client = Seko::Client.new(Seko.config[:token])
69
+ response = client.submit_receipt(line_item_array, warehouse)
70
+ ```
71
+
72
+ #### Submit Company
73
+
74
+ ```ruby
75
+ company_hash = {
76
+ code: 'IND001',
77
+ description: 'Indigina'
78
+ }
79
+ client = Seko::Client.new(Seko.config[:token])
80
+ response = client.submit_company(company_hash)
81
+ ```
82
+
83
+ #### Get Stock
84
+
85
+ ```ruby
86
+ client = Seko::Client.new(Seko.config[:token])
87
+ response = client.get_inventory
88
+ ```
89
+
90
+ #### Check GRN
91
+
92
+ ```ruby
93
+ client = Seko::Client.new(Seko.config[:token])
94
+ response = client.check_grn('5b2dcd8e-52c3-4e27-a712-eaacda2dd8fe')
95
+ ```
96
+
97
+ #### Order Status
98
+
99
+ ```ruby
100
+ client = Seko::Client.new(Seko.config[:token])
101
+ response = client.order_status('5b2dcd8e-52c3-4e27-a712-eaacda2dd8fe')
102
+ ```
103
+
104
+ #### Order Tracking
105
+
106
+ ```ruby
107
+ client = Seko::Client.new(Seko.config[:token])
108
+ response = client.order_tracking('5b2dcd8e-52c3-4e27-a712-eaacda2dd8fe')
109
+ ```
110
+
111
+ #### Cancel Order
112
+
113
+ ```ruby
114
+ Seko::Order::CANCEL_CODES
115
+ # => {
116
+ # "001" => "Customer Request",
117
+ # "002" => "Order Delayed",
118
+ # "003" => "Duplicate",
119
+ # "004" => "Item not available",
120
+ # "005" => "Cannot ship to address",
121
+ # "006" => "Other"
122
+ # }
123
+
124
+ client = Seko::Client.new(Seko.config[:token])
125
+ response = client.cancel_order('5b2dcd8e-52c3-4e27-a712-eaacda2dd8fe', '001')
126
+ ```
127
+
128
+ #### Stock Movements
129
+
130
+ ```ruby
131
+ client = Seko::Client.new(Seko.config[:token])
132
+ warehouse = Seko.config[:warehouses][:us]
133
+ from = 3.days.ago
134
+ to = Time.now
135
+ response = client.stock_movements(from, to, warehouse)
136
+ ```
137
+
138
+ #### Stock Adjustments
139
+
140
+ ```ruby
141
+ client = Seko::Client.new(Seko.config[:token])
142
+ warehouse = Seko.config[:warehouses][:us]
143
+ from = 3.days.ago
144
+ to = Time.now
145
+ response = client.stock_adjustments(from, to, warehouse)
146
+ ```
147
+
148
+ #### Dispatch Statuses
149
+
150
+ ```ruby
151
+ client = Seko::Client.new(Seko.config[:token])
152
+ warehouse = Seko.config[:warehouses][:us] # warehouse is optional
153
+ from = 3.days.ago
154
+ to = Time.now
155
+ response = client.dispatch_statuses(from, to, warehouse)
156
+
157
+ # get collection of GUIDs dispatched
158
+ guid_array = Seko::Dispatch.parse(response)
159
+ # returns something like this
160
+ # => ["2b5e52cc-fb6f-4ea4-b8cf-cf64e3a2b8db", "93e92ca2-725a-46f8-90dd-43a16105f78d"]
161
+ ```
162
+
163
+ #### Submit Order
164
+
165
+ ```ruby
166
+ order = {
167
+ shipping_address: {
168
+ first_name: "John",
169
+ last_name: "Smith",
170
+ address1: "123 Here Now",
171
+ address2: "2nd Floor",
172
+ city: "New York",
173
+ state: "New York",
174
+ country: "US",
175
+ zipcode: "10012",
176
+ phone: "123-123-1234"
177
+ },
178
+ email: "someone@somehwere.com",
179
+ number: "R123123123",
180
+ warehouse: "DC123",
181
+ date: "2013-12-12",
182
+ line_items: [
183
+ {
184
+ quantity: "1",
185
+ sku: "123332211"
186
+ }
187
+ ]
188
+ }
189
+
190
+ client = Seko::Client.new(Seko.config[:token])
191
+ response = client.send_order_request(order)
192
+
193
+ ### NOTE you may want to store the GUID from the response
194
+ ### you need the guid for status updates, tracking, and canceling orders
195
+ response.guid
196
+
197
+ if response.success?
198
+ # DO SOMETHING
199
+ else
200
+ # QUEUE REQUEST, STORE AND RAISE ERRORS
201
+ end
202
+ ```
203
+
204
+ ## Contributing
205
+
206
+ 1. Fork it ( https://github.com/[my-github-username]/seko/fork )
207
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
208
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
209
+ 4. Push to the branch (`git push origin my-new-feature`)
210
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,236 @@
1
+ require 'net/https'
2
+ require 'json'
3
+
4
+ module Seko
5
+ class Client
6
+
7
+ PORT = 443
8
+ TEST_HOST = 'hubuat1.supplystream.com'
9
+ # api.supplystream.com
10
+ LIVE_HOST = 'hub.supplystream.com'
11
+ API_PATH = '/hub/api/'
12
+ API_VERSION = 'v1'
13
+ CONTENT_TYPE = 'application/json'
14
+ KEYS_MAP = {
15
+ "FreeQuantity" => "qty",
16
+ "ProductCode" => "upc"
17
+ }
18
+
19
+ attr_accessor :token, :response, :type, :request_uri, :path, :service, :endpoint, :options
20
+
21
+ def initialize(token, options = {})
22
+ raise "Token is required" unless token
23
+
24
+ @token = token
25
+ @options = default_options.merge(options)
26
+ end
27
+
28
+ def send_order_request(order_hash)
29
+ @service = 'salesorders'
30
+ @endpoint = 'websubmit'
31
+ post(Order.websubmit(order_hash))
32
+ end
33
+
34
+ def order_request(order_hash)
35
+ Order.websubmit(order_hash).to_json
36
+ end
37
+
38
+ def send_wholesale_request(order_hash)
39
+ @service = 'salesorders'
40
+ @endpoint = 'submit'
41
+ post(Order.submit(order_hash))
42
+ end
43
+
44
+ def wholesale_request(order_hash)
45
+ Order.submit(order_hash).to_json
46
+ end
47
+
48
+ # FIXME: use this method once SS fixes their API
49
+ # for now we are manually sorting the distribution centre
50
+ # see #inventory_response below
51
+ #
52
+ # def get_inventory(warehouse = nil)
53
+ # @service = 'stock'
54
+ # @endpoint = if warehouse.nil?
55
+ # "all"
56
+ # else
57
+ # "dc/#{warehouse}"
58
+ # end
59
+ # inventory_response
60
+ # end
61
+ #
62
+ # def inventory_response
63
+ # response = get
64
+ # response.parsed = map_results(Stock.parse(response))
65
+ # response
66
+ # end
67
+
68
+ def get_inventory(warehouse = nil)
69
+ @service = 'stock'
70
+ @endpoint = 'all'
71
+ inventory_response(warehouse)
72
+ end
73
+
74
+
75
+ def inventory_response(warehouse = nil)
76
+ response = get
77
+ response.parsed = map_results(Stock.parse(response)).select do |stock|
78
+ warehouse.nil? ? true : stock["DCCode"] == warehouse
79
+ end
80
+ response
81
+ end
82
+
83
+ def upcs(inventory)
84
+ inventory.collect { |s| s["upc"] }
85
+ end
86
+
87
+ def mapped_inventory(upcs, inventory)
88
+ inventory.collect do |stock|
89
+ if upcs.include?(stock["upc"])
90
+ { quantity: stock["qty"].to_i }
91
+ end
92
+ end.compact
93
+ end
94
+
95
+ def map_results(results)
96
+ results.map { |h| h.inject({ }) { |x, (k,v)| x[map_keys(k)] = v; x } }
97
+ end
98
+
99
+ def map_keys(key)
100
+ KEYS_MAP[key] || key
101
+ end
102
+
103
+ def submit_product(product_hash)
104
+ @service = 'products'
105
+ @endpoint = 'submit'
106
+ post(Product.format(product_hash))
107
+ end
108
+
109
+ def submit_receipt(line_item_array, warehouse)
110
+ @service = 'receipts'
111
+ @endpoint = 'submit'
112
+ post(Receipt.format(line_item_array, warehouse))
113
+ end
114
+
115
+ def submit_company(company_hash)
116
+ @service = 'companies'
117
+ @endpoint = 'submit'
118
+ post(Company.format(company_hash))
119
+ end
120
+
121
+ def check_grn(guid)
122
+ @service = 'grns'
123
+ @endpoint = guid
124
+ get
125
+ end
126
+
127
+ def order_status(guid)
128
+ @service = 'salesorders'
129
+ @endpoint = "#{guid}/status"
130
+ get
131
+ end
132
+
133
+ def order_tracking(guid)
134
+ @service = 'salesorders'
135
+ @endpoint = "#{guid}/tracking"
136
+ get
137
+ end
138
+
139
+ def cancel_order(guid, reason_code)
140
+ @service = 'salesorders'
141
+ @endpoint = "#{guid}/cancel/reasoncode/#{reason_code}"
142
+ post({'Cancel' => 'Order'})
143
+ end
144
+
145
+ def stock_adjustments(from, to, warehouse)
146
+ @service = 'stock'
147
+ @endpoint = "adjustment/#{format_from_to(from, to)}"
148
+ get("#{request_uri}&dc=#{warehouse}")
149
+ end
150
+
151
+ def stock_movements(from, to, warehouse)
152
+ @service = 'stock'
153
+ @endpoint = "movement/#{format_from_to(from, to)}"
154
+ get("#{request_uri}&dc=#{warehouse}")
155
+ end
156
+
157
+ def dispatch_statuses(from, to, warehouse = nil)
158
+ @service = 'dispatches'
159
+ @endpoint = "status/#{format_from_to(from, to)}"
160
+ request_url = "#{request_uri}&status=Dispatched"
161
+ request_url += "&dc=#{warehouse}" unless warehouse.nil?
162
+ get(request_url)
163
+ end
164
+
165
+ def request_uri
166
+ "https://#{host}#{path}?token=#{token}"
167
+ end
168
+
169
+ def path
170
+ "#{API_PATH}#{service}/#{API_VERSION}/#{endpoint}.json"
171
+ end
172
+
173
+ private
174
+ def default_options
175
+ {
176
+ verbose: false,
177
+ test_mode: true
178
+ }
179
+ end
180
+
181
+ def testing?
182
+ @options[:test_mode]
183
+ end
184
+
185
+ def verbose?
186
+ @options[:verbose]
187
+ end
188
+
189
+ def host
190
+ testing? ? TEST_HOST : LIVE_HOST
191
+ end
192
+
193
+ def log(message)
194
+ return unless verbose?
195
+ puts message
196
+ end
197
+
198
+ def http
199
+ @http ||= Net::HTTP.new(host, PORT)
200
+ end
201
+
202
+ def build_request(type, url = request_uri)
203
+ request = Net::HTTP.const_get(type).new(url)
204
+ request.content_type = CONTENT_TYPE
205
+ request
206
+ end
207
+
208
+ def request(request, json_request = nil)
209
+ http.use_ssl = true
210
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
211
+ response = http.request(request)
212
+ parse_response(response.body)
213
+ end
214
+
215
+ def get(url = request_uri)
216
+ request = build_request('Get', url)
217
+ request(request)
218
+ end
219
+
220
+ def post(json_request, url = request_uri)
221
+ request = build_request('Post', url)
222
+ request.body = json_request.to_json
223
+ request(request)
224
+ end
225
+
226
+ def parse_response(json_response)
227
+ log(json_response)
228
+ @response = Response.new(json_response)
229
+ end
230
+
231
+ def format_from_to(from, to)
232
+ "#{from.strftime('%F')}T00:00:00Z/#{to.strftime('%F')}T00:00:00Z"
233
+ end
234
+
235
+ end
236
+ end
@@ -0,0 +1,33 @@
1
+ module Seko
2
+ class Company
3
+
4
+ def self.format(company)
5
+ {
6
+ "Request" => {
7
+ "Company" => {
8
+ "CompanyCode" => company[:code],
9
+ "CompanyDescription" => company[:description],
10
+ "CompanyType" => "Ship To"
11
+ },
12
+ "List" => {
13
+ "Address" => address(company[:address])
14
+ }
15
+ }
16
+ }
17
+ end
18
+
19
+ def self.address(address)
20
+ {
21
+ "AddressLine1" => address[:address1],
22
+ "AddressLine2" => address[:address2],
23
+ "AddressLine3" => address[:address3],
24
+ "AddressType" => "Delivery",
25
+ "City" => address[:city],
26
+ "CountryCode" => address[:country],
27
+ "County" => address[:country_name],
28
+ "PostcodeZip" => address[:zipcode]
29
+ }
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ module Seko
2
+ class Dispatch
3
+
4
+ def self.line_items(response)
5
+ response.root_response["List"]["DispatchLineItem"]
6
+ end
7
+
8
+ # returns array of GUIDs
9
+ def self.parse(response)
10
+ dispatches = line_items(response)
11
+ # API is flawed and returns an array if multiple dispatches
12
+ if dispatches.is_a?(Array)
13
+ dispatches.collect { |h| h["GUID"] }
14
+ else
15
+ # and a singular object otherwise
16
+ # so we wrap it as an array
17
+ Array(dispatches["GUID"])
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ module Seko
2
+ class Filter
3
+
4
+ def self.parse(text)
5
+ text.gsub('|', '-')
6
+ end
7
+
8
+ end
9
+ end
data/lib/seko/order.rb ADDED
@@ -0,0 +1,77 @@
1
+ module Seko
2
+ class Order
3
+
4
+ CANCEL_CODES = {
5
+ '001' => 'Customer Request',
6
+ '002' => 'Order Delayed',
7
+ '003' => 'Duplicate',
8
+ '004' => 'Item not available',
9
+ '005' => 'Cannot ship to address',
10
+ '006' => 'Other'
11
+ }
12
+
13
+ def self.websubmit(attributes)
14
+ build_request(attributes, "Web")
15
+ end
16
+
17
+ def self.submit(attributes)
18
+ build_request(attributes)
19
+ end
20
+
21
+ def self.build_request(attributes, type = nil)
22
+ formatted = format(attributes, type)
23
+ formatted["Request"].merge!(company(attributes[:company])) if attributes[:company]
24
+ formatted
25
+ end
26
+
27
+ def self.format(order, order_prefix = nil)
28
+ {
29
+ "Request" => {
30
+ "DeliveryDetails" => address(order[:shipping_address], order[:email]),
31
+ "List" => {
32
+ "SalesOrderLineItem" => line_items(order[:line_items])
33
+ },
34
+ "SalesOrderHeader" => { "DCCode" => order[:warehouse] },
35
+ "#{order_prefix}SalesOrder" => {
36
+ "SalesOrderDate" => order[:date],
37
+ "SalesOrderNumber" => order[:number]
38
+ }
39
+ }
40
+ }
41
+ end
42
+
43
+ def self.address(address, email)
44
+ {
45
+ "City" => address[:city],
46
+ "CountryCode" => address[:country],
47
+ "EmailAddress" => email,
48
+ "FirstName" => address[:first_name],
49
+ "LastName" => address[:last_name],
50
+ "Line1" => address[:address1],
51
+ "Line2" => address[:address2],
52
+ "PhoneNumber" => address[:phone],
53
+ "PostcodeZip" => address[:zipcode]
54
+ }
55
+ end
56
+
57
+ def self.line_items(items)
58
+ items.collect.with_index do |line_item, index|
59
+ {
60
+ "LineNumber" => index + 1,
61
+ "ProductCode" => line_item[:sku],
62
+ "Quantity" => line_item[:quantity]
63
+ }
64
+ end
65
+ end
66
+
67
+ def self.company(company)
68
+ {
69
+ "ShipToCompany" => {
70
+ "CompanyCode" => company[:code],
71
+ "CompanyDescription" => company[:description]
72
+ }
73
+ }
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,27 @@
1
+ module Seko
2
+ class Product
3
+
4
+ def self.supplier
5
+ {
6
+ "SupplierCode" => Seko.config[:supplier_code],
7
+ "SupplierDescription" => Seko.config[:supplier_description],
8
+ "UOM" => Seko.config[:supplier_uom]
9
+ }
10
+ end
11
+
12
+ def self.format(attributes)
13
+ {
14
+ "Request" => {
15
+ "List" => {
16
+ "SupplierMapping" => supplier
17
+ },
18
+ "ProductMaster" => {
19
+ "ProductCode" => attributes[:upc],
20
+ "ProductDescription" => Filter.parse(attributes[:description])
21
+ }
22
+ }
23
+ }
24
+ end
25
+
26
+ end
27
+ end