ship_compliant 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +8 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +50 -0
- data/Rakefile +47 -0
- data/cucumber.yml +9 -0
- data/features/add_update_brand.feature +20 -0
- data/features/add_update_product.feature +24 -0
- data/features/check_compliance_of_sales_order_with_address_validations.feature +18 -0
- data/features/commit_sales_order.feature +6 -0
- data/features/get_inventory_details.feature +7 -0
- data/features/get_sales_order_extended.feature +15 -0
- data/features/search_sales_orders.feature +13 -0
- data/features/step_definitions/brand_steps.rb +73 -0
- data/features/step_definitions/commit_sales_order/all_shipments.rb +15 -0
- data/features/step_definitions/compliance_check/available_product_steps.rb +175 -0
- data/features/step_definitions/compliance_check/missing_product_steps.rb +102 -0
- data/features/step_definitions/compliance_check/noncompliant_product.rb +102 -0
- data/features/step_definitions/credential_steps.rb +8 -0
- data/features/step_definitions/inventory_steps.rb +36 -0
- data/features/step_definitions/product_steps.rb +140 -0
- data/features/step_definitions/sales_order_extended_steps.rb +79 -0
- data/features/step_definitions/search_order_steps.rb +87 -0
- data/features/step_definitions/void_order_steps.rb +27 -0
- data/features/support/env.rb +14 -0
- data/features/void_sales_order.feature +11 -0
- data/fixtures/vcr_cassettes/brand_already_exists.yml +1038 -0
- data/fixtures/vcr_cassettes/brand_ignore_existing.yml +1037 -0
- data/fixtures/vcr_cassettes/brand_update_existing.yml +1037 -0
- data/fixtures/vcr_cassettes/brand_valid.yml +1037 -0
- data/fixtures/vcr_cassettes/commit_salesorder_all_shipments.yml +1034 -0
- data/fixtures/vcr_cassettes/compliance_available_product.yml +1075 -0
- data/fixtures/vcr_cassettes/compliance_missing_product.yml +1046 -0
- data/fixtures/vcr_cassettes/compliance_noncompliant_product.yml +1082 -0
- data/fixtures/vcr_cassettes/ignore_existing_product.yml +1035 -0
- data/fixtures/vcr_cassettes/invalid_search_sales_orders.yml +1038 -0
- data/fixtures/vcr_cassettes/inventory_details_for_everything.yml +1037 -0
- data/fixtures/vcr_cassettes/product_already_exists.yml +1036 -0
- data/fixtures/vcr_cassettes/product_invalid_brand.yml +1036 -0
- data/fixtures/vcr_cassettes/product_valid_brand.yml +1035 -0
- data/fixtures/vcr_cassettes/sales_order_extended.yml +1042 -0
- data/fixtures/vcr_cassettes/sales_order_missing.yml +1034 -0
- data/fixtures/vcr_cassettes/search_sales_orders.yml +1039 -0
- data/fixtures/vcr_cassettes/update_product.yml +1035 -0
- data/fixtures/vcr_cassettes/void_order.yml +1033 -0
- data/fixtures/vcr_cassettes/void_voided_order.yml +1034 -0
- data/lib/ship_compliant.rb +62 -0
- data/lib/ship_compliant/add_update_brand.rb +50 -0
- data/lib/ship_compliant/add_update_brand_result.rb +6 -0
- data/lib/ship_compliant/add_update_product.rb +66 -0
- data/lib/ship_compliant/add_update_product_result.rb +6 -0
- data/lib/ship_compliant/address.rb +87 -0
- data/lib/ship_compliant/address/suggested_address.rb +37 -0
- data/lib/ship_compliant/base_result.rb +43 -0
- data/lib/ship_compliant/channel_details.rb +31 -0
- data/lib/ship_compliant/check_compliance.rb +41 -0
- data/lib/ship_compliant/check_compliance_result.rb +95 -0
- data/lib/ship_compliant/client.rb +54 -0
- data/lib/ship_compliant/commit_sales_order.rb +48 -0
- data/lib/ship_compliant/commit_sales_order_result.rb +30 -0
- data/lib/ship_compliant/compliance_rule.rb +30 -0
- data/lib/ship_compliant/configuration.rb +46 -0
- data/lib/ship_compliant/error_result.rb +41 -0
- data/lib/ship_compliant/freight_sales_tax_rate.rb +8 -0
- data/lib/ship_compliant/get_inventory_details.rb +31 -0
- data/lib/ship_compliant/get_inventory_details_result.rb +41 -0
- data/lib/ship_compliant/get_sales_order_extended.rb +23 -0
- data/lib/ship_compliant/get_sales_order_extended_result.rb +65 -0
- data/lib/ship_compliant/inventory_product.rb +95 -0
- data/lib/ship_compliant/order_search.rb +92 -0
- data/lib/ship_compliant/package.rb +13 -0
- data/lib/ship_compliant/product_attributes.rb +98 -0
- data/lib/ship_compliant/product_sales_tax_rate.rb +23 -0
- data/lib/ship_compliant/sales_tax_rate.rb +22 -0
- data/lib/ship_compliant/search_sales_order_summary.rb +30 -0
- data/lib/ship_compliant/search_sales_orders.rb +53 -0
- data/lib/ship_compliant/search_sales_orders_result.rb +106 -0
- data/lib/ship_compliant/shipment.rb +59 -0
- data/lib/ship_compliant/shipment_compliance.rb +28 -0
- data/lib/ship_compliant/shipment_sales_tax_rate.rb +15 -0
- data/lib/ship_compliant/version.rb +3 -0
- data/lib/ship_compliant/void_sales_order.rb +42 -0
- data/lib/ship_compliant/void_sales_order_result.rb +20 -0
- data/ship_compliant.gemspec +33 -0
- data/spec/fixtures/add_update_product.xml +22 -0
- data/spec/fixtures/check_compliance.xml +125 -0
- data/spec/fixtures/coreservice.wsdl +1341 -0
- data/spec/fixtures/search_sales_orders.xml +52 -0
- data/spec/fixtures/void_order_failure.xml +31 -0
- data/spec/fixtures/void_order_success.xml +22 -0
- data/spec/lib/ship_compliant/add_update_brand_result_spec.rb +7 -0
- data/spec/lib/ship_compliant/add_update_brand_spec.rb +58 -0
- data/spec/lib/ship_compliant/add_update_product_result_spec.rb +7 -0
- data/spec/lib/ship_compliant/add_update_product_spec.rb +52 -0
- data/spec/lib/ship_compliant/address/suggested_address_spec.rb +28 -0
- data/spec/lib/ship_compliant/address_spec.rb +123 -0
- data/spec/lib/ship_compliant/base_result_spec.rb +127 -0
- data/spec/lib/ship_compliant/channel_details_spec.rb +40 -0
- data/spec/lib/ship_compliant/check_compliance_result_spec.rb +135 -0
- data/spec/lib/ship_compliant/check_compliance_spec.rb +43 -0
- data/spec/lib/ship_compliant/client_spec.rb +73 -0
- data/spec/lib/ship_compliant/commit_sales_order_result_spec.rb +32 -0
- data/spec/lib/ship_compliant/commit_sales_order_spec.rb +38 -0
- data/spec/lib/ship_compliant/compliance_rule_spec.rb +47 -0
- data/spec/lib/ship_compliant/configuration_spec.rb +47 -0
- data/spec/lib/ship_compliant/error_result_spec.rb +47 -0
- data/spec/lib/ship_compliant/freight_sales_tax_rate_spec.rb +7 -0
- data/spec/lib/ship_compliant/get_inventory_details_result_spec.rb +87 -0
- data/spec/lib/ship_compliant/get_inventory_details_spec.rb +35 -0
- data/spec/lib/ship_compliant/get_sales_order_extended_result_spec.rb +84 -0
- data/spec/lib/ship_compliant/get_sales_order_extended_spec.rb +39 -0
- data/spec/lib/ship_compliant/inventory_product_spec.rb +116 -0
- data/spec/lib/ship_compliant/order_search_spec.rb +21 -0
- data/spec/lib/ship_compliant/package_spec.rb +26 -0
- data/spec/lib/ship_compliant/product_attributes_spec.rb +36 -0
- data/spec/lib/ship_compliant/product_sales_tax_rate_spec.rb +22 -0
- data/spec/lib/ship_compliant/sales_tax_rate_spec.rb +21 -0
- data/spec/lib/ship_compliant/search_sales_order_summary_spec.rb +56 -0
- data/spec/lib/ship_compliant/search_sales_orders_result_spec.rb +121 -0
- data/spec/lib/ship_compliant/search_sales_orders_spec.rb +42 -0
- data/spec/lib/ship_compliant/shipment_compliance_spec.rb +46 -0
- data/spec/lib/ship_compliant/shipment_sales_tax_rate_spec.rb +20 -0
- data/spec/lib/ship_compliant/shipment_spec.rb +106 -0
- data/spec/lib/ship_compliant/void_sales_order_result_spec.rb +7 -0
- data/spec/lib/ship_compliant/void_sales_order_spec.rb +41 -0
- data/spec/spec_helper.rb +50 -0
- metadata +366 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
class << self
|
3
|
+
attr_accessor :ship_compliant_client
|
4
|
+
end
|
5
|
+
|
6
|
+
# Returns an instance of +Client+.
|
7
|
+
def self.client
|
8
|
+
self.ship_compliant_client ||= new_client_from_wsdl(configuration.wsdl)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Replaces #client with custom WSDL
|
12
|
+
#
|
13
|
+
# ShipCompliant.wsdl = 'https://ws-dev.shipcompliant.com/Services/1.2/ProductService.asmx?WSDL'
|
14
|
+
def self.wsdl=(wsdl)
|
15
|
+
self.ship_compliant_client = new_client_from_wsdl(wsdl)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Creates a new client from a WSDL url.
|
21
|
+
def self.new_client_from_wsdl(wsdl)
|
22
|
+
Client.new(wsdl: wsdl, log: configuration.log, filters: %W[PartnerKey Username Password])
|
23
|
+
end
|
24
|
+
|
25
|
+
class Client < Savon::Client
|
26
|
+
# "Backup" original #call from Savon::Client
|
27
|
+
alias_method :savon_call, :call
|
28
|
+
|
29
|
+
# Adds the required security credentials and formats
|
30
|
+
# the message to match the ShipCompliant structure.
|
31
|
+
#
|
32
|
+
# ShipCompliant.client.call(:some_operation, {
|
33
|
+
# 'SomeKey' => 'SomeValue'
|
34
|
+
# })
|
35
|
+
def call(operation, locals = {})
|
36
|
+
locals['Security'] = ShipCompliant.configuration.credentials
|
37
|
+
|
38
|
+
response = savon_call(operation, message: {
|
39
|
+
'Request' => locals
|
40
|
+
})
|
41
|
+
|
42
|
+
get_result_from_response(operation, response)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def get_result_from_response(operation, response)
|
48
|
+
key = operation.to_s
|
49
|
+
resp_key = (key + '_response').to_sym
|
50
|
+
result_key = (key + '_result').to_sym
|
51
|
+
response.to_hash.fetch(resp_key, {}).fetch(result_key, {})
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::CommitSalesOrder
|
3
|
+
#
|
4
|
+
# This method takes in a Sales Order Key in the request and saves the order
|
5
|
+
# if it has previously been checked for compliance.
|
6
|
+
#
|
7
|
+
# - If the CommitOption is set to “AllShipments”, all the shipments in the sales order will be committed.
|
8
|
+
# - If it is set to “CompliantShipments”, just the non-committed compliant sales orders will be committed.
|
9
|
+
#
|
10
|
+
# Please keep in mind that if “CompliantShipments” is selected, it will be of
|
11
|
+
# great value to the customer if the non-compliant, non-committed orders were
|
12
|
+
# flagged as such for further review.
|
13
|
+
#
|
14
|
+
# If the CommitOption is not specified, zero shipments will be committed.
|
15
|
+
# This allows the integrator to get the commit status of the shipments in a
|
16
|
+
# sales order without committing any of them.
|
17
|
+
#
|
18
|
+
# result = ShipCompliant::CommitSalesOrder.call({
|
19
|
+
# commit_options: 'AllShipments',
|
20
|
+
# payments: nil,
|
21
|
+
# sales_tax_collected: 0,
|
22
|
+
# sales_order_key: 'ORDER-KEY'
|
23
|
+
# })
|
24
|
+
#
|
25
|
+
# puts result.success? #=> true
|
26
|
+
# puts "The following shipments were committed."
|
27
|
+
#
|
28
|
+
# puts result.committed_shipments #=> ['1', '2', ...]
|
29
|
+
class CommitSalesOrder
|
30
|
+
|
31
|
+
# Marks a SalesOrder as committed.
|
32
|
+
#
|
33
|
+
# Returns an instance of ShipCompliant::CommitSalesOrderResult.
|
34
|
+
#
|
35
|
+
# ShipCompliant::CommitSalesOrder.call({
|
36
|
+
# commit_options: 'CompliantShipments',
|
37
|
+
# payments: nil,
|
38
|
+
# sales_tax_collected: 0,
|
39
|
+
# sales_order_key: 'ORDER-KEY'
|
40
|
+
# })
|
41
|
+
def self.call(commit_data)
|
42
|
+
commit_data.deep_transform_keys! { |key| key.to_s.camelize }
|
43
|
+
result = ShipCompliant.client.call(:commit_sales_order, commit_data)
|
44
|
+
CommitSalesOrderResult.new(result)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::CommitSalesOrderResult
|
3
|
+
#
|
4
|
+
# Wraps the response of +CommitSalesOrder+ and provides methods to quickly
|
5
|
+
# access shipments, and the committed shipment keys.
|
6
|
+
class CommitSalesOrderResult < Struct.new(:response)
|
7
|
+
include BaseResult
|
8
|
+
|
9
|
+
# Returns an array of shipment objects.
|
10
|
+
#
|
11
|
+
# puts result.shipments #=> [
|
12
|
+
# {
|
13
|
+
# key: 'SHIPMENT-KEY',
|
14
|
+
# is_committed: true/false
|
15
|
+
# }
|
16
|
+
# ]
|
17
|
+
def shipments
|
18
|
+
Array.wrap(response[:shipments][:shipment_commit_response])
|
19
|
+
end
|
20
|
+
|
21
|
+
# Gets the keys for committed shipments.
|
22
|
+
#
|
23
|
+
# puts result.committed_shipments #=> ['SHIPMENT-1', 'SHIPMENT-2', ...]
|
24
|
+
def committed_shipments
|
25
|
+
shipments
|
26
|
+
.select { |s| s[:is_committed] == true }
|
27
|
+
.map { |s| s[:key] }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
class ComplianceRule < Struct.new(:response)
|
3
|
+
|
4
|
+
# Returns the +ComplianceDescription+.
|
5
|
+
def compliance_description
|
6
|
+
response[:compliance_description]
|
7
|
+
end
|
8
|
+
|
9
|
+
# Checks if the current compliance rule was met.
|
10
|
+
def compliant?
|
11
|
+
response[:is_compliant]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the +RuleDescription+.
|
15
|
+
def rule_description
|
16
|
+
response[:rule_description]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the +LicenseRelationship+.
|
20
|
+
def license_relationship
|
21
|
+
response[:license_relationship]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the +RuleType+.
|
25
|
+
def rule_type
|
26
|
+
response[:rule_type]
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
class << self
|
3
|
+
attr_accessor :configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configure
|
7
|
+
yield(configuration)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.configuration
|
11
|
+
@configuration ||= Configuration.new
|
12
|
+
end
|
13
|
+
|
14
|
+
# Stores runtime configuration to authenticate user.
|
15
|
+
#
|
16
|
+
# ShipCompliant.configure do |c|
|
17
|
+
# c.partner_key = 'XXXX-XX-XXXXX'
|
18
|
+
# c.username = 'bob@example.com'
|
19
|
+
# c.password = 'secret'
|
20
|
+
# c.log = true # savon log
|
21
|
+
# end
|
22
|
+
class Configuration
|
23
|
+
attr_accessor :partner_key, :username, :password
|
24
|
+
attr_accessor :wsdl, :log
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@log = true
|
28
|
+
@wsdl = 'https://ws-dev.shipcompliant.com/services/1.2/coreservice.asmx?WSDL'
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a +Hash+ for authenticating each API request.
|
32
|
+
#
|
33
|
+
# {
|
34
|
+
# 'PartnerKey' => 'XXXX-XX-XXXXX',
|
35
|
+
# 'Username' => 'bob@example.com',
|
36
|
+
# 'Password' => 'secret'
|
37
|
+
# }
|
38
|
+
def credentials
|
39
|
+
{
|
40
|
+
'PartnerKey' => partner_key,
|
41
|
+
'Username' => username,
|
42
|
+
'Password' => password
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
class ErrorResult < Struct.new(:error)
|
3
|
+
|
4
|
+
# Gets the error code as an integer.
|
5
|
+
#
|
6
|
+
# puts "ERROR ##{error.code}" #=> 404
|
7
|
+
def code
|
8
|
+
error[:code].to_i
|
9
|
+
end
|
10
|
+
|
11
|
+
# Gets the key of the item with an error.
|
12
|
+
#
|
13
|
+
# puts error.key #=> 'ORDER-123'
|
14
|
+
def key
|
15
|
+
error[:key]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Gets the error message.
|
19
|
+
#
|
20
|
+
# puts "ERROR: #{error.message}" #=> 'I don't think it's a good idea,
|
21
|
+
# Yogi'
|
22
|
+
def message
|
23
|
+
error[:message]
|
24
|
+
end
|
25
|
+
|
26
|
+
# The object type that had the error.
|
27
|
+
#
|
28
|
+
# puts error.target #=> 'SalesOrder'
|
29
|
+
def target
|
30
|
+
error[:target]
|
31
|
+
end
|
32
|
+
|
33
|
+
# The type of error that occured.
|
34
|
+
#
|
35
|
+
# puts error.type #=> 'Validation'
|
36
|
+
def type
|
37
|
+
error[:type]
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::GetInventoryDetails
|
3
|
+
#
|
4
|
+
# Provides inventory details for each Product on a Fulfillment Location,
|
5
|
+
# Fulfillment Account basis.
|
6
|
+
#
|
7
|
+
# result = ShipCompliant::GetInventoryDetails.call
|
8
|
+
# product = result.products_for_location('WineShipping').first
|
9
|
+
#
|
10
|
+
# product.inventory_levels #=> {
|
11
|
+
# available: 25,
|
12
|
+
# reserved: 13
|
13
|
+
# }
|
14
|
+
class GetInventoryDetails
|
15
|
+
|
16
|
+
# Returns inventory details for the specified criteria. The method may be
|
17
|
+
# called without any parameters to return all products with Available
|
18
|
+
# inventory.
|
19
|
+
#
|
20
|
+
# ShipCompliant::GetInventoryDetails.call({
|
21
|
+
# brand_key: 'BRAND-KEY',
|
22
|
+
# fulfillment_location: 'WineShipping'
|
23
|
+
# })
|
24
|
+
def self.call(query = {})
|
25
|
+
query.deep_transform_keys! { |k| k.to_s.camelize }
|
26
|
+
result = ShipCompliant.client.call(:get_inventory_details, query)
|
27
|
+
GetInventoryDetailsResult.new(result)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::GetInventoryDetailsResult
|
3
|
+
#
|
4
|
+
# Wraps the result of +GetInventoryDetails+ and provides methods to access
|
5
|
+
# locations and products for a location
|
6
|
+
class GetInventoryDetailsResult < Struct.new(:response)
|
7
|
+
include BaseResult
|
8
|
+
|
9
|
+
# Returns an array of +InventoryLocation+ nodes.
|
10
|
+
#
|
11
|
+
# result.locations[0][:sub_inventory_code] #=> 'SUB-CODE'
|
12
|
+
def locations
|
13
|
+
Array.wrap(response[:inventory_locations]).map do |location|
|
14
|
+
location[:inventory_location]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Finds a location by +FulfillmentLocation+.
|
19
|
+
#
|
20
|
+
# result.location('WineShipping')[:supplier] #=> 'LOCATION-SUPPLIER'
|
21
|
+
def location(key)
|
22
|
+
location = locations.select { |l| l[:fulfillment_location] == key }.first
|
23
|
+
|
24
|
+
return {} if location.nil?
|
25
|
+
location
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns an array of ShipCompliant::InventoryProduct.
|
29
|
+
#
|
30
|
+
# result.products_for_location('WineShipping').each do |product|
|
31
|
+
# puts product.product_key
|
32
|
+
# puts "\t#{product.description}"
|
33
|
+
# puts "---\n"
|
34
|
+
# end
|
35
|
+
def products_for_location(key)
|
36
|
+
Array.wrap(location(key)[:inventory_products]).map do |product|
|
37
|
+
InventoryProduct.new(product[:inventory_product])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::GetSalesOrderExtended
|
3
|
+
#
|
4
|
+
# This method takes in a Sales Order Key and returns detailed data about the
|
5
|
+
# sales order, including compliance status.
|
6
|
+
#
|
7
|
+
# Use this method to query the full details of a sales order and the
|
8
|
+
# shipments in the sales order.
|
9
|
+
class GetSalesOrderExtended
|
10
|
+
|
11
|
+
# Finds a +SalesOrder+ by the +SalesOrderKey+.
|
12
|
+
#
|
13
|
+
# Returns an instance of ShipCompliant::GetSalesOrderExtendedResult.
|
14
|
+
def self.by_order_key(order_key)
|
15
|
+
result = ShipCompliant.client.call(:get_sales_order_extended, {
|
16
|
+
'SalesOrderKey' => order_key
|
17
|
+
})
|
18
|
+
|
19
|
+
GetSalesOrderExtendedResult.new(result)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::GetSalesOrderExtendedResult
|
3
|
+
#
|
4
|
+
# Wraps the response of +GetSalesOrderExtended+ and provides methods to
|
5
|
+
# quickly access compliace rules of a shipment, the billing address,
|
6
|
+
# shipments, and channel details.
|
7
|
+
class GetSalesOrderExtendedResult < Struct.new(:response)
|
8
|
+
include BaseResult
|
9
|
+
|
10
|
+
# Returns an array of the +ShipmentComplianceResponse+ node as a Hash.
|
11
|
+
#
|
12
|
+
# sales_order.shipment_compliance_rules.each do |shipment|
|
13
|
+
# puts "SHIPMENT '#{shipment[:key]}' IS NOT COMPLIANT" unless shipment[:is_compliant]
|
14
|
+
# end
|
15
|
+
def shipment_compliance_rules
|
16
|
+
Array.wrap(response[:compliance_results][:sales_order][:shipments][:shipment_compliance_response]).map do |shipment|
|
17
|
+
shipment
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Finds all the compliance rules for a shipment.
|
22
|
+
# Returns an instance of ShipmentCompliance.
|
23
|
+
#
|
24
|
+
# shipment_compliance = sales_order.compliance_rules_for_shipment('SHIPMENT-KEY')
|
25
|
+
# puts shipment_compliance.compliant? #=> false
|
26
|
+
def compliance_rules_for_shipment(shipment_key)
|
27
|
+
shipment = shipment_compliance_rules.select { |s| s[:key] == shipment_key }.first
|
28
|
+
ShipmentCompliance.new(shipment)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a ShipCompliant::Address with the customer's billing information.
|
32
|
+
#
|
33
|
+
# puts sales_order.bill_to.state #=> 'AK'
|
34
|
+
def bill_to
|
35
|
+
Address.new(response[:sales_order][:bill_to])
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns an array of +Shipment+ nodes as a Hash.
|
39
|
+
#
|
40
|
+
# sales_order.shipments.each do |shipment|
|
41
|
+
# puts shipment[:ship_date] #=> DateTime
|
42
|
+
# end
|
43
|
+
def shipments
|
44
|
+
Array.wrap(response[:sales_order][:shipments]).map do |shipment|
|
45
|
+
shipment[:shipment]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Finds a shipment by +ShipmentKey+. Returns an instance of ShipCompliant::Shipment.
|
50
|
+
#
|
51
|
+
# shipment = sales_order.find_shipment('1')
|
52
|
+
# puts shipment.ship_date #=> DateTime
|
53
|
+
def find_shipment(shipment_key)
|
54
|
+
shipment = shipments.select { |s| s[:shipment_key] == shipment_key }.first
|
55
|
+
Shipment.new(shipment)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns the +OrderChannelDetails+ node as an instance of ShipCompliant::ChannelDetails.
|
59
|
+
#
|
60
|
+
# puts sales_order.channel_details.order_channel #=> 'MyOrders'
|
61
|
+
def channel_details
|
62
|
+
ChannelDetails.new(response[:order_channel_details])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::InventoryProduct
|
3
|
+
#
|
4
|
+
# InventoryProduct is a value object that has methods to access product data from GetInventoryDetails.
|
5
|
+
#
|
6
|
+
# products = @inventory_results.products_for_location('WineShipping')
|
7
|
+
#
|
8
|
+
# products.each do |product|
|
9
|
+
# puts "[%s] %s" % [product.product_key, product.description]
|
10
|
+
#
|
11
|
+
# product.inventory_levels.each do |type, quantity|
|
12
|
+
# puts "%s are %s" % [quantity, type]
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
class InventoryProduct < Struct.new(:product)
|
16
|
+
|
17
|
+
# Returns the +DefaultCase+ of a product.
|
18
|
+
def default_case
|
19
|
+
product[:default_case]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the +ProductKey+ of a product.
|
23
|
+
def product_key
|
24
|
+
product[:product_key]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the +ProductType+ of a product.
|
28
|
+
def product_type
|
29
|
+
product[:product_type]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the +Description+ of a product.
|
33
|
+
def description
|
34
|
+
product[:description]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the +UnitPrice+ of a product as a float.
|
38
|
+
def unit_price
|
39
|
+
product[:unit_price].to_f
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the +FulfillmentSku+ of a product.
|
43
|
+
def fulfillment_sku
|
44
|
+
product[:fulfillment_sku]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the +PercentAlcohol+ of a product as a float.
|
48
|
+
def percent_alcohol
|
49
|
+
product[:percent_alcohol].to_f
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the +Vintage+ of a product as an integer.
|
53
|
+
def vintage
|
54
|
+
product[:vintage].to_i
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the +VolumeAmount+ of a product as a float.
|
58
|
+
def volume_amount
|
59
|
+
product[:volume_amount].to_f
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the +VolumeML+ of a product as a float.
|
63
|
+
def volume_ml
|
64
|
+
product[:volume_ml].to_f
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the +VolumeUnit+ of a product.
|
68
|
+
def volume_unit
|
69
|
+
product[:volume_unit]
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns a Hash of inventory levels.
|
73
|
+
#
|
74
|
+
# - The key is the +InventoryType+.
|
75
|
+
# - The value is +Quantity+ as a float.
|
76
|
+
#
|
77
|
+
# product.inventory_levels #=> {
|
78
|
+
# available: 2,
|
79
|
+
# on_hold: 2,
|
80
|
+
# back_order: 4
|
81
|
+
# }
|
82
|
+
def inventory_levels
|
83
|
+
levels = {}
|
84
|
+
|
85
|
+
product[:inventory_levels][:inventory_level].each do |level|
|
86
|
+
key = level[:inventory_type].underscore.to_sym
|
87
|
+
value = level[:quantity].to_f
|
88
|
+
|
89
|
+
levels[key] = value
|
90
|
+
end
|
91
|
+
|
92
|
+
levels
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|