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,47 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+ describe ErrorResult do
5
+ let(:error) do
6
+ {
7
+ code: "404",
8
+ key: "OrderId",
9
+ message: "I'm smarter than the average bear, Boo Boo",
10
+ target: "SalesOrder",
11
+ type: "Validation"
12
+ }
13
+ end
14
+
15
+ subject { ErrorResult.new(error) }
16
+
17
+ context "code" do
18
+ it "returns the code as an integer" do
19
+ subject.code.should == 404
20
+ end
21
+ end
22
+
23
+ context "key" do
24
+ it "gets the key" do
25
+ subject.key.should == "OrderId"
26
+ end
27
+ end
28
+
29
+ context "message" do
30
+ it "gets the message" do
31
+ subject.message.should == "I'm smarter than the average bear, Boo Boo"
32
+ end
33
+ end
34
+
35
+ context "target" do
36
+ it "gets the target" do
37
+ subject.target.should == "SalesOrder"
38
+ end
39
+ end
40
+
41
+ context "type" do
42
+ it "gets the type" do
43
+ subject.type.should == "Validation"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+ describe FreightSalesTaxRate do
5
+ it { should be_kind_of(SalesTaxRate) }
6
+ end
7
+ end
@@ -0,0 +1,87 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+
5
+ describe GetInventoryDetailsResult do
6
+ it_behaves_like "BaseResult"
7
+
8
+ context "locations" do
9
+ it "returns an array of locations" do
10
+ subject.locations.should == [
11
+ inventory_location[:inventory_location]
12
+ ]
13
+ end
14
+
15
+ it "handles a single location" do
16
+ result = GetInventoryDetailsResult.new({
17
+ inventory_locations: inventory_location
18
+ })
19
+
20
+ result.locations.should == [
21
+ inventory_location[:inventory_location]
22
+ ]
23
+ end
24
+ end
25
+
26
+ context "location" do
27
+ it "finds a location" do
28
+ subject.location('WineShipping').should == inventory_location[:inventory_location]
29
+ end
30
+
31
+ it "returns an empty hash when invalid" do
32
+ subject.location('toys-r-us').should == {}
33
+ end
34
+ end
35
+
36
+ context "products_for_location" do
37
+ it "returns an array of products" do
38
+ subject.products_for_location('WineShipping').should == [
39
+ InventoryProduct.new(product_key: 'PRODUCT-KEY', inventory_levels: inventory_level)
40
+ ]
41
+ end
42
+
43
+ it "returns empty array for invalid location" do
44
+ subject.products_for_location('toys-r-us').should == []
45
+ end
46
+ end
47
+
48
+ let(:inventory_level) do
49
+ {
50
+ inventory_level: {
51
+ effective_date: DateTime.new(2014, 3, 13, 18, 0, 6),
52
+ inventory_type: "Available",
53
+ quantity: "25",
54
+ synchronization_date: DateTime.new(2014, 3, 13, 18, 0, 6)
55
+ }
56
+ }
57
+ end
58
+
59
+ let(:inventory_location) do
60
+ {
61
+ inventory_location: {
62
+ fulfillment_account: nil,
63
+ fulfillment_location: "WineShipping",
64
+ inventory_products: [
65
+ {
66
+ inventory_product: {
67
+ product_key: 'PRODUCT-KEY',
68
+ inventory_levels: inventory_level
69
+ }
70
+ }
71
+ ],
72
+ sub_inventory_code: nil,
73
+ supplier: "ShipC Library Wines"
74
+ }
75
+ }
76
+ end
77
+
78
+ subject do
79
+ GetInventoryDetailsResult.new({
80
+ inventory_locations: [
81
+ inventory_location
82
+ ],
83
+ response_status: "Success"
84
+ })
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,35 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+
5
+ describe GetInventoryDetails do
6
+
7
+ before { savon.mock! }
8
+ after { savon.unmock! }
9
+
10
+ it "gets inventory details" do
11
+ message = {
12
+ 'Request' => {
13
+ 'Security' => {
14
+ 'PartnerKey' => 'abc-123',
15
+ 'Username' => 'bob@example.com',
16
+ 'Password' => 'secret'
17
+ },
18
+ 'BrandKey' => 'BRAND-KEY',
19
+ 'FulfillmentLocation' => 'FULFILLMENT-LOCATION',
20
+ }
21
+ }
22
+
23
+ savon.expects(:get_inventory_details)
24
+ .with(message: message)
25
+ .returns(File.read('spec/fixtures/void_order_success.xml'))
26
+
27
+ result = GetInventoryDetails.call(
28
+ brand_key: 'BRAND-KEY',
29
+ fulfillment_location: 'FULFILLMENT-LOCATION'
30
+ )
31
+
32
+ result.should be_kind_of(GetInventoryDetailsResult)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,84 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+ describe GetSalesOrderExtendedResult do
5
+ it_behaves_like "BaseResult"
6
+
7
+ context "shipment_compliance_rules" do
8
+ it "returns compliance rules as an array" do
9
+ subject.shipment_compliance_rules.should == [
10
+ {
11
+ is_compliant: true,
12
+ key: 'SHIPMENT-KEY',
13
+ }
14
+ ]
15
+ end
16
+ end
17
+
18
+ context "compliance_rules_for_shipment" do
19
+ it "finds compliance rules for shipment" do
20
+ subject.compliance_rules_for_shipment('SHIPMENT-KEY').should == ShipmentCompliance.new({
21
+ is_compliant: true,
22
+ key: 'SHIPMENT-KEY'
23
+ })
24
+ end
25
+ end
26
+
27
+ context "bill_to" do
28
+ it "returns an Address" do
29
+ subject.bill_to.should == Address.new({
30
+ city: 'Jellystone Park',
31
+ state: 'WY'
32
+ })
33
+ end
34
+ end
35
+
36
+ context "shipments" do
37
+ it "returns an array of shipments" do
38
+ subject.shipments.should == [{
39
+ shipment_key: 'SHIPMENT-KEY',
40
+ shipment_items: []
41
+ }]
42
+ end
43
+ end
44
+
45
+ context "find_shipment" do
46
+ it "returns the shipment" do
47
+ subject.find_shipment('SHIPMENT-KEY').should == Shipment.new({
48
+ shipment_key: 'SHIPMENT-KEY',
49
+ shipment_items: []
50
+ })
51
+ end
52
+ end
53
+
54
+ context "channel_details" do
55
+ it "returns the details" do
56
+ subject.channel_details.should == ChannelDetails.new(some_details: 'online sales')
57
+ end
58
+ end
59
+
60
+ subject do
61
+ GetSalesOrderExtendedResult.new({
62
+ compliance_results: {
63
+ sales_order: {
64
+ shipments: {shipment_compliance_response: [{ is_compliant: true, key: 'SHIPMENT-KEY' }]}
65
+ }
66
+ },
67
+ sales_order: {
68
+ bill_to: {
69
+ city: 'Jellystone Park',
70
+ state: 'WY'
71
+ },
72
+ shipments: [shipment]
73
+ },
74
+ order_channel_details: {
75
+ some_details: 'online sales'
76
+ }
77
+ })
78
+ end
79
+
80
+ let(:shipment) do
81
+ {shipment: { shipment_key: 'SHIPMENT-KEY', shipment_items: [] }}
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,39 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+ describe GetSalesOrderExtended do
5
+
6
+ before { savon.mock! }
7
+ after { savon.unmock! }
8
+
9
+ let(:message) do
10
+ {
11
+ 'Request' => {
12
+ 'Security' => {
13
+ 'PartnerKey' => 'abc-123',
14
+ 'Username' => 'bob@example.com',
15
+ 'Password' => 'secret'
16
+ },
17
+ 'SalesOrderKey' => 'SomeOrderId'
18
+ }
19
+ }
20
+ end
21
+
22
+ let(:success_response) { File.read('spec/fixtures/void_order_success.xml') }
23
+
24
+ context "by_order_key" do
25
+ it "queries the client" do
26
+ savon.expects(:get_sales_order_extended)
27
+ .with(message: message).returns(success_response)
28
+
29
+ GetSalesOrderExtended.by_order_key('SomeOrderId')
30
+ end
31
+
32
+ it "returns GetSalesOrderExtendedResult" do
33
+ ShipCompliant.client.stub(:call) { {} }
34
+ result = GetSalesOrderExtended.by_order_key('order-id')
35
+ result.should be_kind_of(GetSalesOrderExtendedResult)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,116 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+ describe InventoryProduct do
5
+
6
+ context "default_case" do
7
+ it "returns the default case" do
8
+ subject.default_case.should == 'DEFAULT-CASE'
9
+ end
10
+ end
11
+
12
+ context "description" do
13
+ it "returns the description" do
14
+ subject.description.should == 'PRODUCT-DESCRIPTION'
15
+ end
16
+ end
17
+
18
+ context "fulfillment_sku" do
19
+ it "returns the fulfillment_sku" do
20
+ subject.fulfillment_sku.should == 'FULFILLMENT-SKU'
21
+ end
22
+ end
23
+
24
+ context "percent_alcohol" do
25
+ it "returns the percent_alcohol" do
26
+ subject.percent_alcohol.should == 98.43
27
+ end
28
+ end
29
+
30
+ context "product_key" do
31
+ it "returns the product_key" do
32
+ subject.product_key.should == 'PRODUCT-KEY'
33
+ end
34
+ end
35
+
36
+ context "product_type" do
37
+ it "returns the product_key" do
38
+ subject.product_type.should == 'PRODUCT-TYPE'
39
+ end
40
+ end
41
+
42
+ context "unit_price" do
43
+ it "returns the unit_price" do
44
+ subject.unit_price.should == 873.21
45
+ end
46
+ end
47
+
48
+ context "vintage" do
49
+ it "returns the vintage" do
50
+ subject.vintage.should == 1922
51
+ end
52
+ end
53
+
54
+ context "volume_amount" do
55
+ it "returns the volume_amount" do
56
+ subject.volume_amount.should == 944.0
57
+ end
58
+ end
59
+
60
+ context "volume_ml" do
61
+ it "returns the volume_ml" do
62
+ subject.volume_ml.should == 944.0
63
+ end
64
+ end
65
+
66
+ context "volume_unit" do
67
+ it "returns the volume_unit" do
68
+ subject.volume_unit.should == 'Milliliter'
69
+ end
70
+ end
71
+
72
+ context "inventory_levels" do
73
+ it "returns a hash of inventory levels" do
74
+ subject.inventory_levels.should == {
75
+ available: 100,
76
+ on_hand: 20,
77
+ some_amazing_type: 1000
78
+ }
79
+ end
80
+ end
81
+
82
+ subject do
83
+ InventoryProduct.new({
84
+ default_case: 'DEFAULT-CASE',
85
+ description: 'PRODUCT-DESCRIPTION',
86
+ fulfillment_sku: 'FULFILLMENT-SKU',
87
+ percent_alcohol: '98.43',
88
+ product_key: 'PRODUCT-KEY',
89
+ product_type: 'PRODUCT-TYPE',
90
+ unit_price: '873.21',
91
+ vintage: '1922',
92
+ volume_amount: '944',
93
+ volume_ml: '944',
94
+ volume_unit: 'Milliliter',
95
+ inventory_levels: {
96
+ inventory_level: [
97
+ {
98
+ random_key: 'PleaseIgnore',
99
+ inventory_type: 'Available',
100
+ quantity: '100'
101
+ },
102
+ {
103
+ inventory_type: 'OnHand',
104
+ quantity: '20'
105
+ },
106
+ {
107
+ inventory_type: 'SomeAmazingType',
108
+ quantity: '1000'
109
+ }
110
+ ]
111
+ }
112
+ })
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+ describe OrderSearch do
5
+
6
+ context "to_h" do
7
+ it "converts keys to pascal case" do
8
+ order = OrderSearch.new(sales_order_key_min: 10)
9
+ order.to_h.should == {
10
+ "SalesOrderKeyMin" => 10
11
+ }
12
+ end
13
+
14
+ it "ignores invalid keys" do
15
+ order = OrderSearch.new(xyz: 5)
16
+ order.to_h.should == {}
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ module ShipCompliant
4
+ describe Package do
5
+
6
+ context "tracking_number" do
7
+ it "gets the tracking_number" do
8
+ subject.tracking_number.should == 'tracking-number'
9
+ end
10
+ end
11
+
12
+ context "tracking_status" do
13
+ it "gets the tracking_status" do
14
+ subject.tracking_status.should == 'Lost in Transit'
15
+ end
16
+ end
17
+
18
+ subject do
19
+ Package.new(
20
+ tracking_number: 'tracking-number',
21
+ tracking_status: 'Lost in Transit'
22
+ )
23
+ end
24
+
25
+ end
26
+ end