ship_compliant 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.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +50 -0
  7. data/Rakefile +47 -0
  8. data/cucumber.yml +9 -0
  9. data/features/add_update_brand.feature +20 -0
  10. data/features/add_update_product.feature +24 -0
  11. data/features/check_compliance_of_sales_order_with_address_validations.feature +18 -0
  12. data/features/commit_sales_order.feature +6 -0
  13. data/features/get_inventory_details.feature +7 -0
  14. data/features/get_sales_order_extended.feature +15 -0
  15. data/features/search_sales_orders.feature +13 -0
  16. data/features/step_definitions/brand_steps.rb +73 -0
  17. data/features/step_definitions/commit_sales_order/all_shipments.rb +15 -0
  18. data/features/step_definitions/compliance_check/available_product_steps.rb +175 -0
  19. data/features/step_definitions/compliance_check/missing_product_steps.rb +102 -0
  20. data/features/step_definitions/compliance_check/noncompliant_product.rb +102 -0
  21. data/features/step_definitions/credential_steps.rb +8 -0
  22. data/features/step_definitions/inventory_steps.rb +36 -0
  23. data/features/step_definitions/product_steps.rb +140 -0
  24. data/features/step_definitions/sales_order_extended_steps.rb +79 -0
  25. data/features/step_definitions/search_order_steps.rb +87 -0
  26. data/features/step_definitions/void_order_steps.rb +27 -0
  27. data/features/support/env.rb +14 -0
  28. data/features/void_sales_order.feature +11 -0
  29. data/fixtures/vcr_cassettes/brand_already_exists.yml +1038 -0
  30. data/fixtures/vcr_cassettes/brand_ignore_existing.yml +1037 -0
  31. data/fixtures/vcr_cassettes/brand_update_existing.yml +1037 -0
  32. data/fixtures/vcr_cassettes/brand_valid.yml +1037 -0
  33. data/fixtures/vcr_cassettes/commit_salesorder_all_shipments.yml +1034 -0
  34. data/fixtures/vcr_cassettes/compliance_available_product.yml +1075 -0
  35. data/fixtures/vcr_cassettes/compliance_missing_product.yml +1046 -0
  36. data/fixtures/vcr_cassettes/compliance_noncompliant_product.yml +1082 -0
  37. data/fixtures/vcr_cassettes/ignore_existing_product.yml +1035 -0
  38. data/fixtures/vcr_cassettes/invalid_search_sales_orders.yml +1038 -0
  39. data/fixtures/vcr_cassettes/inventory_details_for_everything.yml +1037 -0
  40. data/fixtures/vcr_cassettes/product_already_exists.yml +1036 -0
  41. data/fixtures/vcr_cassettes/product_invalid_brand.yml +1036 -0
  42. data/fixtures/vcr_cassettes/product_valid_brand.yml +1035 -0
  43. data/fixtures/vcr_cassettes/sales_order_extended.yml +1042 -0
  44. data/fixtures/vcr_cassettes/sales_order_missing.yml +1034 -0
  45. data/fixtures/vcr_cassettes/search_sales_orders.yml +1039 -0
  46. data/fixtures/vcr_cassettes/update_product.yml +1035 -0
  47. data/fixtures/vcr_cassettes/void_order.yml +1033 -0
  48. data/fixtures/vcr_cassettes/void_voided_order.yml +1034 -0
  49. data/lib/ship_compliant.rb +62 -0
  50. data/lib/ship_compliant/add_update_brand.rb +50 -0
  51. data/lib/ship_compliant/add_update_brand_result.rb +6 -0
  52. data/lib/ship_compliant/add_update_product.rb +66 -0
  53. data/lib/ship_compliant/add_update_product_result.rb +6 -0
  54. data/lib/ship_compliant/address.rb +87 -0
  55. data/lib/ship_compliant/address/suggested_address.rb +37 -0
  56. data/lib/ship_compliant/base_result.rb +43 -0
  57. data/lib/ship_compliant/channel_details.rb +31 -0
  58. data/lib/ship_compliant/check_compliance.rb +41 -0
  59. data/lib/ship_compliant/check_compliance_result.rb +95 -0
  60. data/lib/ship_compliant/client.rb +54 -0
  61. data/lib/ship_compliant/commit_sales_order.rb +48 -0
  62. data/lib/ship_compliant/commit_sales_order_result.rb +30 -0
  63. data/lib/ship_compliant/compliance_rule.rb +30 -0
  64. data/lib/ship_compliant/configuration.rb +46 -0
  65. data/lib/ship_compliant/error_result.rb +41 -0
  66. data/lib/ship_compliant/freight_sales_tax_rate.rb +8 -0
  67. data/lib/ship_compliant/get_inventory_details.rb +31 -0
  68. data/lib/ship_compliant/get_inventory_details_result.rb +41 -0
  69. data/lib/ship_compliant/get_sales_order_extended.rb +23 -0
  70. data/lib/ship_compliant/get_sales_order_extended_result.rb +65 -0
  71. data/lib/ship_compliant/inventory_product.rb +95 -0
  72. data/lib/ship_compliant/order_search.rb +92 -0
  73. data/lib/ship_compliant/package.rb +13 -0
  74. data/lib/ship_compliant/product_attributes.rb +98 -0
  75. data/lib/ship_compliant/product_sales_tax_rate.rb +23 -0
  76. data/lib/ship_compliant/sales_tax_rate.rb +22 -0
  77. data/lib/ship_compliant/search_sales_order_summary.rb +30 -0
  78. data/lib/ship_compliant/search_sales_orders.rb +53 -0
  79. data/lib/ship_compliant/search_sales_orders_result.rb +106 -0
  80. data/lib/ship_compliant/shipment.rb +59 -0
  81. data/lib/ship_compliant/shipment_compliance.rb +28 -0
  82. data/lib/ship_compliant/shipment_sales_tax_rate.rb +15 -0
  83. data/lib/ship_compliant/version.rb +3 -0
  84. data/lib/ship_compliant/void_sales_order.rb +42 -0
  85. data/lib/ship_compliant/void_sales_order_result.rb +20 -0
  86. data/ship_compliant.gemspec +33 -0
  87. data/spec/fixtures/add_update_product.xml +22 -0
  88. data/spec/fixtures/check_compliance.xml +125 -0
  89. data/spec/fixtures/coreservice.wsdl +1341 -0
  90. data/spec/fixtures/search_sales_orders.xml +52 -0
  91. data/spec/fixtures/void_order_failure.xml +31 -0
  92. data/spec/fixtures/void_order_success.xml +22 -0
  93. data/spec/lib/ship_compliant/add_update_brand_result_spec.rb +7 -0
  94. data/spec/lib/ship_compliant/add_update_brand_spec.rb +58 -0
  95. data/spec/lib/ship_compliant/add_update_product_result_spec.rb +7 -0
  96. data/spec/lib/ship_compliant/add_update_product_spec.rb +52 -0
  97. data/spec/lib/ship_compliant/address/suggested_address_spec.rb +28 -0
  98. data/spec/lib/ship_compliant/address_spec.rb +123 -0
  99. data/spec/lib/ship_compliant/base_result_spec.rb +127 -0
  100. data/spec/lib/ship_compliant/channel_details_spec.rb +40 -0
  101. data/spec/lib/ship_compliant/check_compliance_result_spec.rb +135 -0
  102. data/spec/lib/ship_compliant/check_compliance_spec.rb +43 -0
  103. data/spec/lib/ship_compliant/client_spec.rb +73 -0
  104. data/spec/lib/ship_compliant/commit_sales_order_result_spec.rb +32 -0
  105. data/spec/lib/ship_compliant/commit_sales_order_spec.rb +38 -0
  106. data/spec/lib/ship_compliant/compliance_rule_spec.rb +47 -0
  107. data/spec/lib/ship_compliant/configuration_spec.rb +47 -0
  108. data/spec/lib/ship_compliant/error_result_spec.rb +47 -0
  109. data/spec/lib/ship_compliant/freight_sales_tax_rate_spec.rb +7 -0
  110. data/spec/lib/ship_compliant/get_inventory_details_result_spec.rb +87 -0
  111. data/spec/lib/ship_compliant/get_inventory_details_spec.rb +35 -0
  112. data/spec/lib/ship_compliant/get_sales_order_extended_result_spec.rb +84 -0
  113. data/spec/lib/ship_compliant/get_sales_order_extended_spec.rb +39 -0
  114. data/spec/lib/ship_compliant/inventory_product_spec.rb +116 -0
  115. data/spec/lib/ship_compliant/order_search_spec.rb +21 -0
  116. data/spec/lib/ship_compliant/package_spec.rb +26 -0
  117. data/spec/lib/ship_compliant/product_attributes_spec.rb +36 -0
  118. data/spec/lib/ship_compliant/product_sales_tax_rate_spec.rb +22 -0
  119. data/spec/lib/ship_compliant/sales_tax_rate_spec.rb +21 -0
  120. data/spec/lib/ship_compliant/search_sales_order_summary_spec.rb +56 -0
  121. data/spec/lib/ship_compliant/search_sales_orders_result_spec.rb +121 -0
  122. data/spec/lib/ship_compliant/search_sales_orders_spec.rb +42 -0
  123. data/spec/lib/ship_compliant/shipment_compliance_spec.rb +46 -0
  124. data/spec/lib/ship_compliant/shipment_sales_tax_rate_spec.rb +20 -0
  125. data/spec/lib/ship_compliant/shipment_spec.rb +106 -0
  126. data/spec/lib/ship_compliant/void_sales_order_result_spec.rb +7 -0
  127. data/spec/lib/ship_compliant/void_sales_order_spec.rb +41 -0
  128. data/spec/spec_helper.rb +50 -0
  129. metadata +366 -0
@@ -0,0 +1,92 @@
1
+ module ShipCompliant
2
+ # === ShipCompliant::OrderSearch
3
+ #
4
+ # Acts as a hash for adding search criteria to the +SearchSalesOrders+
5
+ # API endpoint. It removes invalid keys when converting to a Hash.
6
+ #
7
+ # query = ShipCompliant::OrderSearch({
8
+ # invalid: 'lolz',
9
+ # requested_ship_date_max: DateTime.new(2014, 1, 1)
10
+ # })
11
+ #
12
+ # query.to_h #=> {
13
+ # 'RequestedShipDateMax' => DateTime
14
+ # }
15
+ class OrderSearch < Struct.new(:details)
16
+
17
+ # == Available Search Methods
18
+ #
19
+ # * +channel+
20
+ # * +compliance_status+
21
+ # * +external_club_key+
22
+ # * +external_offer_key+
23
+ # * +external_sales_order_key_max+
24
+ # * +external_sales_order_keys+
25
+ # * +fulfillment_house+
26
+ # * +fulfillment_status+
27
+ # * +fulfillment_account+
28
+ # * +fulfillment_exception_type+
29
+ # * +license_relationship_type+
30
+ # * +not_tag+
31
+ # * +purchase_date_max+
32
+ # * +purchase_date_min+
33
+ # * +requested_ship_date_max+
34
+ # * +requested_ship_date_min+
35
+ # * +sale_type+
36
+ # * +sales_order_keys+
37
+ # * +sales_order_key_min+
38
+ # * +sales_order_key_max+
39
+ # * +settlement_batch_number+
40
+ # * +shipment_status+
41
+ # * +ship_date_max+
42
+ # * +ship_date_min+
43
+ # * +ship_to_state+
44
+ # * +tag+
45
+ # * +tracking_existence+
46
+ KEYS = [
47
+ :channel,
48
+ :compliance_status,
49
+
50
+ :external_club_key,
51
+ :external_offer_key,
52
+ :external_sales_order_key_max,
53
+ :external_sales_order_keys,
54
+
55
+ :fulfillment_house,
56
+ :fulfillment_status,
57
+ :fulfillment_account,
58
+ :fulfillment_exception_type,
59
+
60
+ :license_relationship_type,
61
+ :not_tag,
62
+ :purchase_date_max,
63
+ :purchase_date_min,
64
+
65
+ :requested_ship_date_max,
66
+ :requested_ship_date_min,
67
+
68
+ :sale_type,
69
+ :sales_order_keys,
70
+ :sales_order_key_min,
71
+ :sales_order_key_max,
72
+
73
+ :settlement_batch_number,
74
+ :shipment_status,
75
+ :ship_date_max,
76
+ :ship_date_min,
77
+ :ship_to_state,
78
+
79
+ :tag,
80
+ :tracking_existence,
81
+ ]
82
+
83
+ # Converts hash keys to Pascal case and rejects invalid keys.
84
+ #
85
+ # :sales_order_keys #=> 'SalesOrderKeys'
86
+ def to_h
87
+ details.reject do |key|
88
+ !KEYS.include?(key)
89
+ end.deep_transform_keys { |key| key.to_s.camelize }
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,13 @@
1
+ module ShipCompliant
2
+ class Package < Struct.new(:package)
3
+
4
+ def tracking_number
5
+ package[:tracking_number]
6
+ end
7
+
8
+ def tracking_status
9
+ package[:tracking_status]
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,98 @@
1
+ module ShipCompliant
2
+ # === ShipCompliant::ProductAttributes
3
+ #
4
+ # Acts as a hash for working with the +AddUpdateProduct+ API endpoint.
5
+ #
6
+ # attributes = ShipCompliant::ProductAttributes({
7
+ # bottle_size_ml: 750,
8
+ # gtin: 'value',
9
+ # product_description: 'It's great!'
10
+ # })
11
+ #
12
+ # attributes.to_h #=> {
13
+ # 'BottleSizeML' => 750,
14
+ # 'GTIN' => 'value',
15
+ # 'ProductDescription' => 'It's great!'
16
+ # }
17
+ class ProductAttributes < Struct.new(:details)
18
+ # == Available Product Attributes
19
+ #
20
+ # * +age+
21
+ # * +bottle_size_ml+
22
+ # * +brand_key+
23
+ # * +default_case+
24
+ # * +default_retail_unit_price+
25
+ # * +default_retail_case_price+
26
+ # * +description+
27
+ # * +flavor+
28
+ # * +gtin+
29
+ # * +label+
30
+ # * +percent_alcohol+
31
+ # * +product_key+
32
+ # * +product_type+
33
+ # * +product_description+
34
+ # * +nabca+
35
+ # * +scc+
36
+ # * +upc+
37
+ # * +unimerc+
38
+ # * +unit_price+
39
+ # * +varietal+
40
+ # * +vintage+
41
+ # * +volume_amount+
42
+ # * +volume_unit+
43
+ KEYS = [
44
+ :age,
45
+ :bottle_size_ml,
46
+ :brand_key,
47
+
48
+ :default_case,
49
+ :default_retail_unit_price,
50
+ :default_retail_case_price,
51
+ :description,
52
+
53
+ :flavor,
54
+ :gtin,
55
+ :label,
56
+
57
+ :percent_alcohol,
58
+ :product_key,
59
+ :product_type,
60
+ :product_description,
61
+
62
+ :nabca,
63
+ :scc,
64
+ :upc,
65
+ :unimerc,
66
+ :unit_price,
67
+
68
+ :varietal,
69
+ :vintage,
70
+ :volume_amount,
71
+ :volume_unit
72
+ ]
73
+
74
+ SPECIAL_CASES = {
75
+ gtin: 'GTIN',
76
+ nabca: 'NABCA',
77
+ scc: 'SCC',
78
+ unimerc: 'UNIMERC',
79
+ upc: 'UPC',
80
+ bottle_size_ml: 'BottleSizeML'
81
+ }
82
+
83
+ # Converts hash keys to Pascal case and handles special cases.
84
+ #
85
+ # :bottle_size_ml #=> 'BottleSizeML'
86
+ def to_h
87
+ details.deep_transform_keys do |key|
88
+ # handle special cases
89
+ pascal_key = key.to_s.camelize
90
+ if SPECIAL_CASES.has_key?(key)
91
+ pascal_key = SPECIAL_CASES[key]
92
+ end
93
+
94
+ pascal_key
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,23 @@
1
+ module ShipCompliant
2
+ # == ShipCompliant::ProductSalesTaxRate
3
+ #
4
+ # ProductSalesTaxRate wraps the SalesTaxRate value object. It provides methods
5
+ # to easily access various attributes about each product.
6
+ class ProductSalesTaxRate < SalesTaxRate
7
+
8
+ # Returns the product's key.
9
+ #
10
+ # product_tax_rate.product_key #=> 'ProductKey123'
11
+ def product_key
12
+ sales_tax[:product_key]
13
+ end
14
+
15
+ # Returns the product's brand key.
16
+ #
17
+ # product_tax_rate.brand_key #=> 'BrandKey123'
18
+ def brand_key
19
+ sales_tax[:brand_key]
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ module ShipCompliant
2
+ # == ShipCompliant::SalesTaxRate
3
+ #
4
+ # SalesTaxRate is a value object to store sales tax information for freight
5
+ # and products.
6
+ #
7
+ # tax_rate = SalesTaxRate.new(sales_tax_due: '123.45')
8
+ # puts tax_rate.sales_tax_due #=> 123.45
9
+ class SalesTaxRate < Struct.new(:sales_tax)
10
+
11
+ # Returns the +sales_tax_due+ as a float.
12
+ def sales_tax_due
13
+ sales_tax[:sales_tax_due].to_f
14
+ end
15
+
16
+ # Returns the +sales_tax_rate+ as a float.
17
+ def sales_tax_rate
18
+ sales_tax[:sales_tax_rate].to_f
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ module ShipCompliant
2
+ # === ShipCompliant::SearchSalesOrderSummary
3
+ #
4
+ # Wraps the +SalesOrderSummary+ hash with a simple DSL
5
+ # to provide easy access to various keys.
6
+ class SearchSalesOrderSummary < Struct.new(:data)
7
+
8
+ # Returns a +DateTime+ from the order +purchase_date+
9
+ def purchase_date
10
+ data[:purchase_date]
11
+ end
12
+
13
+ # Returns the +sales_order_key+
14
+ def order_key
15
+ data[:sales_order_key]
16
+ end
17
+ alias_method :sales_order_key, :order_key
18
+
19
+ # Returns the parsed hash from the +ShipmentSummary+ element.
20
+ #
21
+ # {
22
+ # compliance: 'ValueHere',
23
+ # requested_ship_date: DateTime,
24
+ # # etc...
25
+ # }
26
+ def shipment_summary
27
+ data[:shipments][:shipment_summary]
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,53 @@
1
+ module ShipCompliant
2
+ # == ShipCompliant::SearchSalesOrders
3
+ #
4
+ # Search orders in the ShipCompliant database on a number of different
5
+ # criteria such as date ranges, order number range, order list, status, etc...
6
+ #
7
+ # Summary details, including tracking numbers, of Sales Orders and
8
+ # Shipments are returned for the first 100 orders that meet the search criteria.
9
+ #
10
+ # Use this method to get tracking numbers for a collection of orders,
11
+ # check shipping status, check compliance status, or check fulfillment status.
12
+ #
13
+ # Results are paged, and only the first 100 results are returned with this method.
14
+ # Use the ShipCompliant::SearchSalesOrdersResult#remaining_orders_length method in
15
+ # conjunction with this method to page through the result set.
16
+ #
17
+ # _You must specify at least one of the date range options or an invoice number range in this request._
18
+ #
19
+ # orders = ShipCompliant::SearchSalesOrders.find_by({
20
+ # purchase_date_min: DateTime.new(2014, 3, 10),
21
+ # purchase_date_max: DateTime.new(2014, 3, 12)
22
+ # })
23
+ class SearchSalesOrders
24
+
25
+ # +query+ must be a Hash with the keys relating to each search criteria.
26
+ #
27
+ # To see a list of available keys take a look at OrderSearch::KEYS
28
+ #
29
+ # # find orders place within date
30
+ # orders = ShipCompliant::SearchSalesOrders.find_by({
31
+ # purchase_date_min: DateTime.new(2014, 3, 10),
32
+ # purchase_date_max: DateTime.new(2014, 3, 12)
33
+ # })
34
+ #
35
+ # # find orders by compliance_status
36
+ # orders = ShipCompliant::SearchSalesOrders.find_by({
37
+ # compliance_status: 'NotCompliant' # possible values are "Compliant", "NotCompliant", or "Any". Any is default.
38
+ # })
39
+ def self.find_by(query)
40
+ order_query = OrderSearch.new(query).to_h
41
+
42
+ sales = search_sales(order_query)
43
+ SearchSalesOrdersResult.new(sales.to_hash)
44
+ end
45
+
46
+ private
47
+
48
+ def self.search_sales(order_query)
49
+ ShipCompliant.client.call(:search_sales_orders, order_query)
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,106 @@
1
+ module ShipCompliant
2
+ # === An API wrapper for +SearchSalesOrders+ response.
3
+ #
4
+ # Converts fields into integers and ensures +order_summaries+
5
+ # is an array.
6
+ #
7
+ # orders = ShipCompliant::SearchSalesOrders.find_by({
8
+ # purchase_date_min: DateTime.new(2014, 3, 10),
9
+ # purchase_date_max: DateTime.new(2014, 3, 12)
10
+ # })
11
+ #
12
+ # puts orders.length #=> 2
13
+ #
14
+ # orders.summaries.each do |summary|
15
+ # puts summary.purchase_date #=> DateTime
16
+ # end
17
+ class SearchSalesOrdersResult
18
+ include BaseResult
19
+ attr_reader :raw
20
+ alias_method :response, :raw # for BaseResult
21
+
22
+ def initialize(data)
23
+ @raw = data
24
+ parse!
25
+ end
26
+
27
+ # The number of orders returned the current response.
28
+ def length
29
+ raw.fetch(:count_sales_orders_returned, 0)
30
+ end
31
+
32
+ # The number of orders waiting to be returned.
33
+ # Use this for paging results.
34
+ def remaining_orders_length
35
+ raw.fetch(:count_more_sales_orders_available, 0)
36
+ end
37
+
38
+ # Returns an array of ShipCompliant::SearchSalesOrderSummary.
39
+ # Use this to get information about each order.
40
+ #
41
+ # orders.summaries.each do |summary|
42
+ # puts summary.purchase_date #=> DateTime
43
+ # end
44
+ def summaries
45
+ raw[:sales_orders][:sales_order_summary].reject(&:blank?).map do |summary|
46
+ SearchSalesOrderSummary.new(summary)
47
+ end
48
+ end
49
+
50
+ # Returns the +PagingCookie+ node.
51
+ def paging_cookie
52
+ response[:paging_cookie]
53
+ end
54
+
55
+ # Returns the +PagingCookieExpires+ node as DateTime.
56
+ def paging_cookie_expires
57
+ response[:paging_cookie_expires]
58
+ end
59
+
60
+ private
61
+
62
+ # Standardizes the XML response by converting fields to integers
63
+ # and forcing the order summaries into an array.
64
+ def parse!
65
+ unless raw.has_key?(:sales_orders)
66
+ raw[:sales_orders] = {}
67
+ end
68
+
69
+ # force orders to be an array
70
+ orders = raw[:sales_orders].fetch(:sales_order_summary, {})
71
+ unless orders.kind_of?(Array)
72
+ raw[:sales_orders][:sales_order_summary] = [orders]
73
+ end
74
+
75
+ # typecast :count_more_sales_orders_available to integer
76
+ if raw.has_key?(:count_more_sales_orders_available)
77
+ convert_to_integer!(:count_more_sales_orders_available, raw)
78
+ end
79
+
80
+ # typecast :count_sales_orders_returned to integer
81
+ if raw.has_key?(:count_sales_orders_returned)
82
+ convert_to_integer!(:count_sales_orders_returned, raw)
83
+ end
84
+
85
+ raw[:sales_orders][:sales_order_summary].each do |summary|
86
+
87
+ # typecast :shipment_key to integer
88
+ if summary.fetch(:shipments, {}).fetch(:shipment_summary, {}).has_key?(:shipment_key)
89
+ convert_to_integer!(:shipment_key, summary[:shipments][:shipment_summary])
90
+ end
91
+
92
+ # typecast :zip1 to integer
93
+ if summary.fetch(:shipments, {}).fetch(:shipment_summary, {}).fetch(:ship_to, {}).has_key?(:zip1)
94
+ convert_to_integer!(:zip1, summary[:shipments][:shipment_summary][:ship_to])
95
+ end
96
+ end
97
+ end
98
+
99
+ # Typecasts an object key into to an integer.
100
+ #
101
+ # convert_to_integer(:shipment_key, order_summary[:shipments][:shipment_summary])
102
+ def convert_to_integer!(key, object)
103
+ object[key] = object[key].to_i
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,59 @@
1
+ module ShipCompliant
2
+ class Shipment < Struct.new(:shipment)
3
+
4
+ def fulfillment_house
5
+ shipment[:fulfillment_house]
6
+ end
7
+
8
+ def fulfillment_exception_reason
9
+ shipment[:fulfillment_exception_reason]
10
+ end
11
+
12
+ def fulfillment_exception_type
13
+ shipment[:fulfillment_exception_type]
14
+ end
15
+
16
+ def fulfillment_status
17
+ shipment[:fulfillment_status]
18
+ end
19
+
20
+ def handling
21
+ shipment[:handling].to_f
22
+ end
23
+
24
+ def insured_amount
25
+ shipment[:insured_amount].to_f
26
+ end
27
+
28
+ def shipping
29
+ shipment[:shipping].to_f
30
+ end
31
+
32
+ def ship_date
33
+ shipment[:ship_date]
34
+ end
35
+
36
+ def shipment_status
37
+ shipment[:shipment_status]
38
+ end
39
+
40
+ def shipping_service
41
+ shipment[:shipping_service]
42
+ end
43
+
44
+ def special_instructions
45
+ shipment[:special_instructions]
46
+ end
47
+
48
+ def packages
49
+ Array.wrap(shipment[:packages]).map do |package|
50
+ Package.new(package[:package])
51
+ end
52
+ end
53
+
54
+ def ship_to
55
+ Address.new(shipment[:ship_to])
56
+ end
57
+
58
+ end
59
+ end