shipvine 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +2 -0
- data/README.md +104 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/data/WarehouseFS-1.0.xsd +603 -0
- data/lib/shipvine.rb +22 -0
- data/lib/shipvine/base.rb +69 -0
- data/lib/shipvine/bill_of_lading.rb +21 -0
- data/lib/shipvine/client.rb +78 -0
- data/lib/shipvine/deep_compact.rb +23 -0
- data/lib/shipvine/error.rb +12 -0
- data/lib/shipvine/fulfillment_request.rb +243 -0
- data/lib/shipvine/inbound_shipment.rb +129 -0
- data/lib/shipvine/item.rb +74 -0
- data/lib/shipvine/item_group.rb +53 -0
- data/lib/shipvine/outbound_shipment.rb +30 -0
- data/lib/shipvine/version.rb +3 -0
- data/shipvine.gemspec +28 -0
- metadata +147 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
module Shipvine
|
2
|
+
class InboundShipment < Base
|
3
|
+
|
4
|
+
attr_reader :attributes
|
5
|
+
|
6
|
+
def initialize(attributes)
|
7
|
+
@attributes = attributes
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.list(since, state = 'Complete')
|
11
|
+
request = self.client.request(
|
12
|
+
:get,
|
13
|
+
'/inbound-shipments/' + ERB::Util.url_encode(Shipvine.merchant_code),
|
14
|
+
{
|
15
|
+
'changed-since' => since,
|
16
|
+
'state' => state
|
17
|
+
}
|
18
|
+
)
|
19
|
+
|
20
|
+
response = self.xml_to_hash(request.body)
|
21
|
+
|
22
|
+
# the GET response only returns the identifiers, we have to make another call
|
23
|
+
# to pull all of the actual inbound shipments
|
24
|
+
merchant_identifiers = Array.wrap(response.dig(:inbound_shipments, :inbound_shipment)).map do |shipment_hash|
|
25
|
+
shipment_hash[:merchant_identifier]
|
26
|
+
end
|
27
|
+
|
28
|
+
merchant_identifiers.map do |identifier|
|
29
|
+
self.get(identifier)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.get(merchant_identifier)
|
34
|
+
request = self.client.request(
|
35
|
+
:get,
|
36
|
+
'/inbound-shipments/' + ERB::Util.url_encode(Shipvine.merchant_code) + '/' + ERB::Util.url_encode(merchant_identifier)
|
37
|
+
)
|
38
|
+
|
39
|
+
self.new(self.xml_to_hash(request.body))
|
40
|
+
end
|
41
|
+
|
42
|
+
def create
|
43
|
+
translated_payload = @attributes.deep_dup
|
44
|
+
merchant_identifier = translated_payload.delete(:merchant_identifier)
|
45
|
+
|
46
|
+
# `The /InboundShipment/ExpectedAt date is not in the expected format of yyyy-MM-dd (e.g., '2014-02-28')`
|
47
|
+
if translated_payload[:expected_at] !=~ /[0-9]{4}-[0-2]{2}-[0-9]{2}/
|
48
|
+
translated_payload[:expected_at] = DateTime.parse(translated_payload[:expected_at]).strftime('%Y-%m-%d')
|
49
|
+
end
|
50
|
+
|
51
|
+
preprocess_lines(translated_payload)
|
52
|
+
preprocess_metadata(translated_payload)
|
53
|
+
|
54
|
+
client.request(
|
55
|
+
:put,
|
56
|
+
'/inbound-shipments/' + ERB::Util.url_encode(Shipvine.merchant_code) + '/' + ERB::Util.url_encode(merchant_identifier),
|
57
|
+
request_body('InboundShipment', translated_payload)
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def metadata
|
62
|
+
metadata_entries = self.attributes.dig(:inbound_shipment, :shipment_metadata, :metadata)
|
63
|
+
|
64
|
+
if metadata_entries.nil? || metadata_entries.empty?
|
65
|
+
return {}
|
66
|
+
end
|
67
|
+
|
68
|
+
# TODO cache the resulting hash here
|
69
|
+
|
70
|
+
metadata_entries = Array.wrap(metadata_entries)
|
71
|
+
|
72
|
+
metadata_entries.inject({}) do |h, sv_metadata_entry|
|
73
|
+
h[sv_metadata_entry[:name]] = sv_metadata_entry[:value]
|
74
|
+
h
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def preprocess_metadata(shipment_hash)
|
81
|
+
metadata = shipment_hash.delete(:metadata)
|
82
|
+
|
83
|
+
if metadata
|
84
|
+
shipment_hash[:shipment_metadata] = {
|
85
|
+
:metadata => metadata.map do |k, v|
|
86
|
+
{
|
87
|
+
name: k,
|
88
|
+
value: v
|
89
|
+
}
|
90
|
+
end
|
91
|
+
}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def preprocess_lines(order_hash)
|
96
|
+
items = order_hash.delete(:items)
|
97
|
+
|
98
|
+
order_hash[:lines] = {
|
99
|
+
:line => items.map do |item|
|
100
|
+
{
|
101
|
+
item: {
|
102
|
+
# TODO support other item keys, `sku`, `id`, etc
|
103
|
+
merchant_identifier: item[:product_id]
|
104
|
+
},
|
105
|
+
quantity_expected: item[:quantity],
|
106
|
+
}
|
107
|
+
end
|
108
|
+
}
|
109
|
+
|
110
|
+
order_hash
|
111
|
+
end
|
112
|
+
|
113
|
+
def build_sanitized_hash(resource_name, hash)
|
114
|
+
sanitized = hash.deep_compact!
|
115
|
+
|
116
|
+
# NOTE inbound shipments do not have a XSD!
|
117
|
+
# also, the merchant code is specified in the URL in XML
|
118
|
+
|
119
|
+
{
|
120
|
+
resource_name => sanitized
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
def validate_xml!(xml)
|
125
|
+
# NOTE there is no XSD for inbound shipments!
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Shipvine
|
2
|
+
class Item < Base
|
3
|
+
def self.get(item_group_merchant_identifier, item_merchant_identifier)
|
4
|
+
request = self.client.request(
|
5
|
+
:get,
|
6
|
+
# escape SKU?
|
7
|
+
|
8
|
+
'/item-groups/' +
|
9
|
+
Shipvine.merchant_code + '/' +
|
10
|
+
item_group_merchant_identifier + '/' +
|
11
|
+
'items/' +
|
12
|
+
item_merchant_identifier,
|
13
|
+
{},
|
14
|
+
exclude_merchant_code: true
|
15
|
+
)
|
16
|
+
|
17
|
+
self.new(self.xml_to_hash(request.body))
|
18
|
+
rescue Shipvine::Error => e
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(attributes)
|
23
|
+
@attributes = attributes
|
24
|
+
end
|
25
|
+
|
26
|
+
def create
|
27
|
+
translated_payload = @attributes.deep_dup
|
28
|
+
|
29
|
+
merchant_identifier = translated_payload.delete(:merchant_identifier)
|
30
|
+
group_merchant_identifier = translated_payload.delete(:group_merchant_identifier)
|
31
|
+
|
32
|
+
preprocess_metadata(translated_payload)
|
33
|
+
|
34
|
+
client.request(
|
35
|
+
:put,
|
36
|
+
'/item-groups/' +
|
37
|
+
Shipvine.merchant_code + '/' +
|
38
|
+
group_merchant_identifier + '/' +
|
39
|
+
'items/' +
|
40
|
+
merchant_identifier,
|
41
|
+
request_body('Item', translated_payload),
|
42
|
+
exclude_merchant_code: true
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# NOTE there are no sequence limitations on the item API
|
49
|
+
|
50
|
+
# there is no XSD, and the merchant code is included the URL; simple strip nils
|
51
|
+
def build_sanitized_hash(resource_name, hash)
|
52
|
+
{ resource_name => hash.deep_compact! }
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_xml!(xml)
|
56
|
+
# NOTE there is no XSD for item group!
|
57
|
+
end
|
58
|
+
|
59
|
+
def preprocess_metadata(item_hash)
|
60
|
+
metadata = item_hash.delete(:metadata)
|
61
|
+
|
62
|
+
if metadata
|
63
|
+
item_hash[:metadata] = {
|
64
|
+
:metadata => metadata.map do |k, v|
|
65
|
+
{
|
66
|
+
name: k,
|
67
|
+
value: v
|
68
|
+
}
|
69
|
+
end
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Shipvine
|
2
|
+
class ItemGroup < Base
|
3
|
+
|
4
|
+
def self.get(item_merchant_identifier)
|
5
|
+
request = self.client.request(
|
6
|
+
:get,
|
7
|
+
|
8
|
+
# TODO escape SKU?
|
9
|
+
|
10
|
+
'/item-groups/' +
|
11
|
+
Shipvine.merchant_code + '/' +
|
12
|
+
item_merchant_identifier
|
13
|
+
)
|
14
|
+
|
15
|
+
self.new(self.xml_to_hash(request.body))
|
16
|
+
rescue Shipvine::Error => e
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :attributes
|
21
|
+
|
22
|
+
def initialize(attributes)
|
23
|
+
@attributes = attributes
|
24
|
+
end
|
25
|
+
|
26
|
+
def create
|
27
|
+
translated_payload = @attributes.deep_dup
|
28
|
+
|
29
|
+
merchant_identifier = translated_payload.delete(:merchant_identifier)
|
30
|
+
|
31
|
+
client.request(
|
32
|
+
:put,
|
33
|
+
'/item-groups/' +
|
34
|
+
Shipvine.merchant_code + '/' + merchant_identifier,
|
35
|
+
request_body('ItemGroup', translated_payload)
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# NOTE there are no sequence limitations on the item API
|
42
|
+
|
43
|
+
# there is no XSD, and the merchant code is included the URL; simple strip nils
|
44
|
+
def build_sanitized_hash(resource_name, hash)
|
45
|
+
{ resource_name => hash.deep_compact! }
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_xml!(xml)
|
49
|
+
# NOTE there is no XSD for item group!
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Shipvine
|
2
|
+
class OutboundShipment < Base
|
3
|
+
|
4
|
+
def self.list(since)
|
5
|
+
request = self.client.request(:get, '/outbound-shipments', { 'created-since' => since })
|
6
|
+
response = self.xml_to_hash(request.body)
|
7
|
+
|
8
|
+
Array.wrap(response[:outbound_shipments][:outbound_shipment]).map do |shipment_hash|
|
9
|
+
self.new(shipment_hash)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :attributes
|
14
|
+
|
15
|
+
def initialize(shipment_hash)
|
16
|
+
@attributes = shipment_hash
|
17
|
+
end
|
18
|
+
|
19
|
+
def merchant_identifier
|
20
|
+
@attributes[:fulfillment_request][:merchant_identifier]
|
21
|
+
end
|
22
|
+
|
23
|
+
def wfs_identifier
|
24
|
+
@attributes[:fulfillment_request][:wfs_identifier]
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method :shipvine_identifier, :wfs_identifier
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/shipvine.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'shipvine/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "shipvine"
|
8
|
+
spec.version = Shipvine::VERSION
|
9
|
+
spec.authors = ["Michael Bianco"]
|
10
|
+
spec.email = ["mike@cliffsidemedia.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Shipvine API bindings}
|
13
|
+
# spec.description = %q{TODO: Write a longer description or delete this line.}
|
14
|
+
spec.homepage = "https://github.com/iloveitaly/shipvine-ruby"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'httparty', '~> 0.13.7'
|
22
|
+
spec.add_dependency 'gyoku', '~> 1.3.1'
|
23
|
+
spec.add_dependency 'nori', '~> 2.6.0'
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shipvine
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Bianco
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.13.7
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.13.7
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: gyoku
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.3.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.3.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nori
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.6.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.6.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.11'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.11'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '5.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '5.0'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- mike@cliffsidemedia.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- Gemfile
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- bin/console
|
109
|
+
- bin/setup
|
110
|
+
- data/WarehouseFS-1.0.xsd
|
111
|
+
- lib/shipvine.rb
|
112
|
+
- lib/shipvine/base.rb
|
113
|
+
- lib/shipvine/bill_of_lading.rb
|
114
|
+
- lib/shipvine/client.rb
|
115
|
+
- lib/shipvine/deep_compact.rb
|
116
|
+
- lib/shipvine/error.rb
|
117
|
+
- lib/shipvine/fulfillment_request.rb
|
118
|
+
- lib/shipvine/inbound_shipment.rb
|
119
|
+
- lib/shipvine/item.rb
|
120
|
+
- lib/shipvine/item_group.rb
|
121
|
+
- lib/shipvine/outbound_shipment.rb
|
122
|
+
- lib/shipvine/version.rb
|
123
|
+
- shipvine.gemspec
|
124
|
+
homepage: https://github.com/iloveitaly/shipvine-ruby
|
125
|
+
licenses: []
|
126
|
+
metadata: {}
|
127
|
+
post_install_message:
|
128
|
+
rdoc_options: []
|
129
|
+
require_paths:
|
130
|
+
- lib
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
requirements: []
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 2.6.4
|
144
|
+
signing_key:
|
145
|
+
specification_version: 4
|
146
|
+
summary: Shipvine API bindings
|
147
|
+
test_files: []
|