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,62 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require 'active_support/all'
|
3
|
+
|
4
|
+
require "ship_compliant/version"
|
5
|
+
require "ship_compliant/configuration"
|
6
|
+
require "ship_compliant/client"
|
7
|
+
require "ship_compliant/base_result"
|
8
|
+
require "ship_compliant/error_result"
|
9
|
+
|
10
|
+
require "ship_compliant/address"
|
11
|
+
require "ship_compliant/address/suggested_address"
|
12
|
+
|
13
|
+
require "ship_compliant/shipment"
|
14
|
+
require "ship_compliant/package"
|
15
|
+
require "ship_compliant/channel_details"
|
16
|
+
|
17
|
+
# SEARCH SALES ORDERS
|
18
|
+
require "ship_compliant/order_search"
|
19
|
+
require "ship_compliant/search_sales_orders"
|
20
|
+
require "ship_compliant/search_sales_orders_result"
|
21
|
+
require "ship_compliant/search_sales_order_summary"
|
22
|
+
|
23
|
+
require "ship_compliant/get_sales_order_extended"
|
24
|
+
require "ship_compliant/get_sales_order_extended_result"
|
25
|
+
|
26
|
+
# VOID SALES ORDER
|
27
|
+
require "ship_compliant/void_sales_order"
|
28
|
+
require "ship_compliant/void_sales_order_result"
|
29
|
+
|
30
|
+
# ADD UPDATE PRODUCT
|
31
|
+
require "ship_compliant/product_attributes"
|
32
|
+
require "ship_compliant/add_update_product"
|
33
|
+
require "ship_compliant/add_update_product_result"
|
34
|
+
|
35
|
+
# ADD UPDATE BRAND
|
36
|
+
require "ship_compliant/add_update_brand"
|
37
|
+
require "ship_compliant/add_update_brand_result"
|
38
|
+
|
39
|
+
# SALES TAX
|
40
|
+
require "ship_compliant/shipment_sales_tax_rate"
|
41
|
+
require "ship_compliant/sales_tax_rate"
|
42
|
+
require "ship_compliant/product_sales_tax_rate"
|
43
|
+
require "ship_compliant/freight_sales_tax_rate"
|
44
|
+
|
45
|
+
# CHECK COMPLIANCE OF SALES ORDER WITH ADDRESS VALIDATION
|
46
|
+
require "ship_compliant/check_compliance"
|
47
|
+
require "ship_compliant/check_compliance_result"
|
48
|
+
|
49
|
+
require "ship_compliant/shipment_compliance"
|
50
|
+
require "ship_compliant/compliance_rule"
|
51
|
+
|
52
|
+
require "ship_compliant/commit_sales_order"
|
53
|
+
require "ship_compliant/commit_sales_order_result"
|
54
|
+
|
55
|
+
require "ship_compliant/inventory_product"
|
56
|
+
|
57
|
+
require "ship_compliant/get_inventory_details"
|
58
|
+
require "ship_compliant/get_inventory_details_result"
|
59
|
+
|
60
|
+
module ShipCompliant
|
61
|
+
# Your code goes here...
|
62
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::AddUpdateBrand
|
3
|
+
#
|
4
|
+
# Checks to see if a brand with the same key already exists. If one does not
|
5
|
+
# exist, it will add the brand with the specified name. If a brand exists
|
6
|
+
# with the same brand key then the brand name will be updated.
|
7
|
+
#
|
8
|
+
# Use this method to add a new brand or update an existing brand in the
|
9
|
+
# system. A brand must be defined before adding products.
|
10
|
+
#
|
11
|
+
# ShipCompliant::AddUpdateBrand.brand({
|
12
|
+
# key: 'DENSNW',
|
13
|
+
# name: 'Denver Snow',
|
14
|
+
#
|
15
|
+
# this_brand_is_bottled_by_a_third_party: false,
|
16
|
+
# this_brand_is_produced_by_a_third_party: false,
|
17
|
+
# this_brand_operates_under_a_trade_name: false,
|
18
|
+
# this_brand_was_acquired_from_a_third_party: false
|
19
|
+
# })
|
20
|
+
class AddUpdateBrand
|
21
|
+
|
22
|
+
# Adds or updates a brand depending on +:update_mode+.
|
23
|
+
#
|
24
|
+
# +brand+ parameter must be a Hash.
|
25
|
+
#
|
26
|
+
# === Options
|
27
|
+
#
|
28
|
+
# You can specify the update mode by passing a hash as the second argument.
|
29
|
+
# The default is +ErrorOnExisting+.
|
30
|
+
#
|
31
|
+
# Available options are.
|
32
|
+
#
|
33
|
+
# * UpdateExisting - Existing brand information is updated.
|
34
|
+
# * IgnoreExisting - Pre-existing information is not updated.
|
35
|
+
# * ErrorOnExisting - An error message is returned if the brand already exists.
|
36
|
+
#
|
37
|
+
# ShipCompliant::AddUpdateBrand.product({
|
38
|
+
# # brand attributes
|
39
|
+
# }, update_mode: 'UpdateExisting')
|
40
|
+
def self.brand(brand, options = {})
|
41
|
+
result = ShipCompliant.client.call(:add_update_brand, {
|
42
|
+
'Brand' => brand.deep_transform_keys { |key| key.to_s.camelize },
|
43
|
+
'UpdateMode' => options.fetch(:update_mode, 'ErrorOnExisting')
|
44
|
+
})
|
45
|
+
|
46
|
+
AddUpdateBrandResult.new(result)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::AddUpdateProduct
|
3
|
+
#
|
4
|
+
# This method checks to see if a product with the same product key and brand
|
5
|
+
# key already exists.
|
6
|
+
#
|
7
|
+
# If one does not exist, it will add the product with the specified
|
8
|
+
# information.
|
9
|
+
#
|
10
|
+
# If a product exists with the same product key and brand key, but is not
|
11
|
+
# referenced by any shipments, the product will be updated with the specified
|
12
|
+
# information.
|
13
|
+
#
|
14
|
+
# If a product exists with the same product key and brand key, and is
|
15
|
+
# referenced by one or more shipments, the product will not be updated.
|
16
|
+
#
|
17
|
+
# result = ShipCompliant::AddUpdateProduct.product({
|
18
|
+
# # product attributes
|
19
|
+
# }, update_mode: 'IgnoreExisting')
|
20
|
+
#
|
21
|
+
# if result.success?
|
22
|
+
# puts "Product added successfully.
|
23
|
+
# else
|
24
|
+
# result.errors.each do |error|
|
25
|
+
# puts error.message
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
class AddUpdateProduct
|
29
|
+
|
30
|
+
# Adds or updates product depending on +:update_mode+.
|
31
|
+
#
|
32
|
+
# +product+ parameter must be a Hash. The keys must be related to the the
|
33
|
+
# keys located in ShipCompliant::ProductAttributes.
|
34
|
+
#
|
35
|
+
# === Options
|
36
|
+
#
|
37
|
+
# You can specify the update mode by passing a Hash as the second argument.
|
38
|
+
# The default is +ErrorOnExisting+.
|
39
|
+
#
|
40
|
+
# Available options are.
|
41
|
+
#
|
42
|
+
# * UpdateExisting - Existing product information is updated.
|
43
|
+
# * IgnoreExisting - Pre-existing information is not updated.
|
44
|
+
# * ErrorOnExisting - An error message is returned if the product already exists.
|
45
|
+
#
|
46
|
+
# ShipCompliant::AddUpdateProduct.product({
|
47
|
+
# # product attributes
|
48
|
+
# }, update_mode: 'UpdateExisting')
|
49
|
+
def self.product(product, options = {})
|
50
|
+
details = {
|
51
|
+
'Product' => ProductAttributes.new(product).to_h,
|
52
|
+
'UpdateMode' => options.fetch(:update_mode, 'ErrorOnExisting')
|
53
|
+
}
|
54
|
+
|
55
|
+
result = add_update_product(details)
|
56
|
+
AddUpdateProductResult.new(result)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def self.add_update_product(request)
|
62
|
+
ShipCompliant.client.call(:add_update_product, request)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::Address
|
3
|
+
#
|
4
|
+
# This is a value object that wraps an address node. +BillTo+ and +ShipTo+.
|
5
|
+
#
|
6
|
+
# address = ShipCompliant::Address.new(city: 'Boston', state: 'MA')
|
7
|
+
# address.city #=> 'Boston'
|
8
|
+
# address.state #=> 'MA'
|
9
|
+
class Address < Struct.new(:address)
|
10
|
+
|
11
|
+
# Returns the suggested city.
|
12
|
+
def city
|
13
|
+
address[:city]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the suggested county.
|
17
|
+
def county
|
18
|
+
address[:county]
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the suggested state.
|
22
|
+
def state
|
23
|
+
address[:state]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the country.
|
27
|
+
def country
|
28
|
+
address[:country]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the suggested street.
|
32
|
+
def street1
|
33
|
+
address[:street1]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the suggested street line 2.
|
37
|
+
def street2
|
38
|
+
address[:street2]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the suggested zip code.
|
42
|
+
def zip1
|
43
|
+
address[:zip1].to_i
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the suggested zip code extension.
|
47
|
+
def zip2
|
48
|
+
return nil if address[:zip2].blank?
|
49
|
+
address[:zip2].to_i
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the company.
|
53
|
+
def company
|
54
|
+
address[:company]
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the first name.
|
58
|
+
def first_name
|
59
|
+
address[:first_name]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the last name.
|
63
|
+
def last_name
|
64
|
+
address[:last_name]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the phone.
|
68
|
+
def phone
|
69
|
+
address[:phone]
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the fax.
|
73
|
+
def fax
|
74
|
+
address[:fax]
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns the email address.
|
78
|
+
def email
|
79
|
+
address[:email]
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the date of birth.
|
83
|
+
def date_of_birth
|
84
|
+
address[:date_of_birth]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::SuggestedAddress
|
3
|
+
#
|
4
|
+
# This is a value object that wraps the +SuggestedAddress+ node. It inherits
|
5
|
+
# methods from Address, but it also as methods to access suggested address
|
6
|
+
# details and parts.
|
7
|
+
class SuggestedAddress < Address
|
8
|
+
|
9
|
+
# Returns a Hash of the address location details.
|
10
|
+
#
|
11
|
+
# - +city_abbreviation+
|
12
|
+
# - +congressional_district+
|
13
|
+
# - +county_fips+
|
14
|
+
# - +time_zone+
|
15
|
+
# - +time_zone_code+
|
16
|
+
def details
|
17
|
+
address[:details]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a Hash of the address parts.
|
21
|
+
#
|
22
|
+
# - +company+
|
23
|
+
# - +mail_box_name+
|
24
|
+
# - +mail_box_number+
|
25
|
+
# - +post_direction+
|
26
|
+
# - +pre_direction+
|
27
|
+
# - +street_name+
|
28
|
+
# - +street_number+
|
29
|
+
# - +street_suffix+
|
30
|
+
# - +suite_name+
|
31
|
+
# - +suite_number+
|
32
|
+
def parts
|
33
|
+
address[:parts]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::BaseResult
|
3
|
+
#
|
4
|
+
# This class provides methods to are relevant to every
|
5
|
+
# API request. All requests made through the
|
6
|
+
# ShipCompliant API client include these methods.
|
7
|
+
module BaseResult
|
8
|
+
|
9
|
+
# Returns boolean whether order was successfully voided.
|
10
|
+
#
|
11
|
+
# puts "SUCCESS" if result.success?
|
12
|
+
def success?
|
13
|
+
response[:response_status] == "Success"
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns true if order failed to be voided.
|
17
|
+
#
|
18
|
+
# puts "FAILED" if result.failure?
|
19
|
+
def failure?
|
20
|
+
!success?
|
21
|
+
end
|
22
|
+
|
23
|
+
# An array of +ErrorResult+ items or an empty array if the response was
|
24
|
+
# successful.
|
25
|
+
#
|
26
|
+
# result.errors.each do |error|
|
27
|
+
# puts "#{error.message} [#error.key]"
|
28
|
+
# end
|
29
|
+
def errors
|
30
|
+
return [] if success?
|
31
|
+
@errors ||= Array.wrap(response[:errors]).map do |error|
|
32
|
+
ErrorResult.new(error[:error])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# The number of errors in the response.
|
37
|
+
def errors_count
|
38
|
+
errors.length
|
39
|
+
end
|
40
|
+
alias_method :error_count, :errors_count
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::ChannelDetails
|
3
|
+
#
|
4
|
+
# A value object that wraps the +OrderChanelDetails+ node.
|
5
|
+
#
|
6
|
+
# channel_details = sales_order.channel_details
|
7
|
+
# puts channel_details.order_channel #=> 'MyOrders'
|
8
|
+
class ChannelDetails < Struct.new(:channel)
|
9
|
+
|
10
|
+
# Returns +OrderChannel+.
|
11
|
+
def order_channel
|
12
|
+
channel[:order_channel]
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns +AdvertiserKey+.
|
16
|
+
def advertiser_key
|
17
|
+
channel[:advertiser_key]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns +AdvertiserName+.
|
21
|
+
def advertiser_name
|
22
|
+
channel[:advertiser_name]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns +Meta+.
|
26
|
+
def meta
|
27
|
+
channel[:meta]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::CheckCompliance
|
3
|
+
#
|
4
|
+
# The CheckComplianceOfSalesOrderWithAddressValidation API method is used for
|
5
|
+
# real time compliance checks from the order point of entry (eCommerce, POS).
|
6
|
+
#
|
7
|
+
# The method can do three things in one call:
|
8
|
+
#
|
9
|
+
# - Calculate Sales Tax Due for order and return product level tax rates
|
10
|
+
# (IncludeSalesTaxRates = true)
|
11
|
+
# - Validate the ShipTo address and get normalized address result
|
12
|
+
# - Check compliance of the order
|
13
|
+
#
|
14
|
+
# This method takes requires specific order information from the order point
|
15
|
+
# of entry for ShipCompliant to check the order for compliance. The sales
|
16
|
+
# order will not be committed via this method. This API call is usually
|
17
|
+
# paired with CommitSalesOrder() to save the sales order to ShipCompliant.
|
18
|
+
#
|
19
|
+
# Look at the following example request: http://git.io/xMNOvw
|
20
|
+
class CheckCompliance
|
21
|
+
|
22
|
+
# Checks the compliance of a sales order from the data specified.
|
23
|
+
#
|
24
|
+
# An example of all the required fields can be seen here: http://git.io/xMNOvw
|
25
|
+
#
|
26
|
+
# ShipCompliant::CheckCompliance.of_sales_order({
|
27
|
+
# address_option: {
|
28
|
+
# ignore_street_level_errors: true,
|
29
|
+
# reject_if_address_suggested: 'false' # Savon bug? Passes the value as an attribute when a boolean
|
30
|
+
# },
|
31
|
+
# include_sales_tax_rates: true,
|
32
|
+
# # ...
|
33
|
+
# })
|
34
|
+
def self.of_sales_order(data)
|
35
|
+
camel_cased_keys = data.deep_transform_keys { |key| key.to_s.camelize }
|
36
|
+
result = ShipCompliant.client.call(:check_compliance_of_sales_order_with_address_validation, camel_cased_keys)
|
37
|
+
CheckComplianceResult.new(result)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module ShipCompliant
|
2
|
+
# == ShipCompliant::CheckComplianceResult
|
3
|
+
#
|
4
|
+
# CheckComplianceResult wraps the response from the
|
5
|
+
# +CheckComplianceOfSalesOrderWithAddressValidation+ API method.
|
6
|
+
#
|
7
|
+
# It provides methods to access nested objects and easily iterate over taxes
|
8
|
+
# rates for shipments.
|
9
|
+
#
|
10
|
+
# compliant_status = ShipCompliant::CheckCompliance.of_sales_order({
|
11
|
+
# # attributes here
|
12
|
+
# })
|
13
|
+
#
|
14
|
+
# compliant_status.compliant? #=> true
|
15
|
+
class CheckComplianceResult < Struct.new(:response)
|
16
|
+
include BaseResult
|
17
|
+
|
18
|
+
# Returns true if all shipments of a SalesOrder are compliant.
|
19
|
+
def compliant?
|
20
|
+
response[:sales_order][:is_compliant] == true
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a float of the recommended sales tax due for a SalesOrder.
|
24
|
+
def recommended_tax_due
|
25
|
+
response[:sales_order][:sales_tax_rates][:recommended_sales_tax_due].to_f
|
26
|
+
end
|
27
|
+
|
28
|
+
# Access the tax information for a shipment. Returns an instance of
|
29
|
+
# ShipmentSalesTaxRate.
|
30
|
+
def taxes_for_shipment(shipment_key)
|
31
|
+
shipment = shipment_sales_tax_rates.select { |s| s[:@shipment_key] == shipment_key }.first
|
32
|
+
|
33
|
+
# convert attribute keys to symbols
|
34
|
+
freight = attributes_to_symbols(shipment[:freight_sales_tax_rate])
|
35
|
+
|
36
|
+
# wrap products in ProductSalesTaxRate
|
37
|
+
products = wrap_products(shipment[:product_sales_tax_rates])
|
38
|
+
|
39
|
+
ShipmentSalesTaxRate.new(shipment_key, FreightSalesTaxRate.new(freight), products)
|
40
|
+
end
|
41
|
+
|
42
|
+
# This method returns an Array containing information about each shipment of a
|
43
|
+
# SalesOrder.
|
44
|
+
def shipment_sales_tax_rates
|
45
|
+
Array.wrap(response[:sales_order][:sales_tax_rates][:shipment_sales_tax_rates][:shipment_sales_tax_rate])
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns an array of the +ShipmentComplianceResponse+ node as a Hash.
|
49
|
+
#
|
50
|
+
# compliance_result.shipment_compliance_rules.each do |shipment|
|
51
|
+
# puts "SHIPMENT '#{shipment[:key]}' IS NOT COMPLIANT" unless shipment[:is_compliant]
|
52
|
+
# end
|
53
|
+
def shipment_compliance_rules
|
54
|
+
Array.wrap(response[:sales_order][:shipments][:shipment_compliance_response])
|
55
|
+
end
|
56
|
+
|
57
|
+
# Finds all the compliance rules for a shipment.
|
58
|
+
# Returns an instance of ShipmentCompliance.
|
59
|
+
#
|
60
|
+
# shipment_compliance = compliance_result.compliance_rules_for_shipment('SHIPMENT-KEY')
|
61
|
+
# puts shipment_compliance.compliant? #=> false
|
62
|
+
def compliance_rules_for_shipment(shipment_key)
|
63
|
+
shipment = shipment_compliance_rules.select { |s| s[:key] == shipment_key }.first
|
64
|
+
ShipmentCompliance.new(shipment)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the +AddressValidationResult+.
|
68
|
+
def address_validation_result
|
69
|
+
response[:address_validation_result]
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns an instance of ShipCompliant::SuggestedAddress.
|
73
|
+
def suggested_address
|
74
|
+
SuggestedAddress.new(response[:suggested_address])
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Nori returns XML attributes as a key beginning with a spiral (@).
|
80
|
+
# This removes the spiral and changes key to a symbol.
|
81
|
+
def attributes_to_symbols(object)
|
82
|
+
object.transform_keys do |key|
|
83
|
+
key.to_s.gsub('@', '').to_sym
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Wraps each +ProductSalesTaxRates+ node with
|
88
|
+
# ShipCompliant::ProductSalesTaxRate
|
89
|
+
def wrap_products(products)
|
90
|
+
Array.wrap(products[:product_sales_tax_rate]).map do |product|
|
91
|
+
ProductSalesTaxRate.new(attributes_to_symbols(product))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|