valken-shipping 2.0.0 → 2.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab3690dda426e4cf2d007e9c44872957323960c8457434bef1134c1f373194f4
4
- data.tar.gz: 38f098df1c9aa7a8a83bbbb8fd52a34984aa0329fc8e248dc9337f5aeacb3d05
3
+ metadata.gz: f92653930081ded5658da35cbc0c04e556b15cf001fab963f589ebaf86501a88
4
+ data.tar.gz: 7996b9957c6aec16a394f4a772aa650410613c88819569536a8cf1585567c5a2
5
5
  SHA512:
6
- metadata.gz: c629f3bc576ff4f7019966324569b77424d5d09e4af73928f5587c025fb1c2152d3224ca284d004b182b57ebaa736327d1ceb4683a022ed6299f8f3305a10ce1
7
- data.tar.gz: eea6eb560252fef7fdd359b4ae4d59a277a7694c6dfa6c79708b5141d9f29ed1d4663e0782d8b5e02c075432b4f3a5b824bc4a0a8849bf92a4fb32f9b84ea1a1
6
+ metadata.gz: 24df18e3b0c8db49d6074ecb675c59aa450b62cbfd7849a3446a65e21474f817ea51b82aef96b25a857dc2cd4b9fc7934edb59d465aeef8fe87954b91e38d492
7
+ data.tar.gz: 8e6b3cce596b96e97f1ade2081b0fa54ed429581806e0d45f776d1a89ced2cb8279fc685341823628d901b839c74b90a1a9879d8d565319ff7da75f0de789828
@@ -0,0 +1,57 @@
1
+ module Workarea
2
+ module AddressesHelper
3
+ def country_options
4
+ return [[Country['US'].name, Country['US'].alpha2]] if is_usa_only?
5
+ Workarea.config.countries.map do |country|
6
+ [country.name, country.alpha2]
7
+ end
8
+ end
9
+
10
+ def region_options
11
+ @region_options ||= Workarea.config.countries.reduce([]) do |memo, country|
12
+ regions = country.subdivisions
13
+ .map { |id, region| [region.translations[I18n.locale.to_s] || region.name, id] }
14
+ .sort_by { |name, id| name || id }
15
+
16
+ memo << [country.name, regions]
17
+ memo
18
+ end
19
+ end
20
+
21
+ def is_usa_only?
22
+ return false if current_order.blank? || current_order.items.blank?
23
+
24
+ usa_only_attribute = Workarea.config.shipping_attributes[:usa_only]
25
+ product_attributes = current_order.items.map(&:product_attributes)
26
+ return product_attributes.map{ |item| item[:details][:en][usa_only_attribute] }.flatten.include?("true")
27
+ end
28
+
29
+ def formatted_address(address)
30
+ pieces = {
31
+ recipient: "#{address.first_name} #{address.last_name}\n#{address.company}".strip,
32
+ street: "#{address.street} #{address.street_2}".strip,
33
+ city: address.city,
34
+ region: address.region_name,
35
+ region_short: address.region,
36
+ postalcode: address.postal_code,
37
+ country: address.country.alpha2
38
+ }
39
+
40
+ address_format = address.country.address_format || Country['US'].address_format
41
+ result = pieces.reduce(address_format) do |memo, (name, value)|
42
+ memo.gsub(/{{#{name}}}/, html_escape(value.to_s))
43
+ end
44
+
45
+ if address.phone_number.present?
46
+ formatted_phone = number_to_phone(
47
+ address.phone_number,
48
+ extension: address.phone_extension
49
+ )
50
+
51
+ result << "\n#{formatted_phone}"
52
+ end
53
+
54
+ result.gsub(/\n/, tag(:br)).html_safe
55
+ end
56
+ end
57
+ end
@@ -1,192 +1,16 @@
1
1
  module Workarea
2
2
  decorate Checkout::ShippingOptions, with: :valken do
3
3
  decorated do
4
+ class NoAvailableShippingOption < RuntimeError; end
4
5
  end
5
6
 
6
7
  def all_options
7
8
  @all_options ||=
8
9
  begin
9
10
  packaging = Packaging.new(order, shipping)
10
- shipping_option
11
+ shipping.find_method_options(order, shipping)
11
12
  end
12
13
  end
13
14
 
14
- def shipping_option
15
- carrier_data = collect_carrier_data(selected_carrier)
16
- if Workarea.config.gateways.ups_carrier.class != ActiveShipping::Workarea
17
- carrier_data.push(get_ltl_shipping)
18
- carrier_data.push(get_free_shipping) if Workarea.config.show_free_shipping
19
- end
20
- carrier_data
21
- end
22
-
23
- # Selecting the shipping carrier based on order items
24
- #
25
- # If the product is type hazmat then it returns ups...or if product is type gun then it returns fedex
26
- # else if product is not both type then it returns none
27
- def selected_carrier
28
- product_ids = order.items.to_a.map(&:product_id)
29
- product_details = Catalog::Product.in(id: product_ids).pluck(:details)
30
- is_ups = product_details.any? {|item| item["en"]["Type"] && item["en"]["Type"].first == "UPS"}
31
- is_fedex = product_details.any? {|item| item["en"]["Type"] && item["en"]["Type"].first == "FEDEX"}
32
- return "UPS" if is_ups
33
- return "FedEx" if is_fedex
34
- return "none" unless is_ups && is_fedex
35
- end
36
-
37
- # If the carrier is ups then it will print ups data...or if carrier is fedex then prinnt fedex data...
38
- # else if it is not both then choose cheapest price.
39
- def collect_carrier_data(carrier)
40
- return get_ups_data if carrier == "UPS"
41
- return get_fedex_data if carrier == "FedEx"
42
- return get_none_data if carrier == "none"
43
- end
44
-
45
- # UPS data.
46
- def get_ups_data
47
- @ups_options ||= get_options(Workarea.config.gateways.ups_carrier, Workarea.config.shipping_rates)
48
- end
49
-
50
- # FedEx data.
51
- def get_fedex_data
52
- @fedex_response ||= get_options(Workarea.config.gateways.fedex_carrier, Workarea.config.shipping_rates)
53
- end
54
-
55
- # If the product is not ups or fedex then it will choose the cheapest price among ups and fedex annd print the value.
56
- def get_none_data
57
- ups = get_ups_data.sort_by(&:price).first
58
- fedex = get_fedex_data.sort_by(&:price).first
59
-
60
- if ups.present? && fedex.present?
61
- if ups.price > fedex.price
62
- return get_fedex_data
63
- elsif ups.price < fedex.price
64
- return get_ups_data
65
- else
66
- return get_ups_data
67
- end
68
- elsif ups.blank?
69
- return get_fedex_data
70
- elsif fedex.blank?
71
- return get_ups_data
72
- else
73
- return []
74
- end
75
-
76
- end
77
-
78
- # Free shipping option.
79
- def get_free_shipping
80
- ShippingOption.new(
81
- carrier: "Free Shipping",
82
- name: "Valken Economy",
83
- sub_name: "5 - 9 Business Days",
84
- service_code: "Free",
85
- price: Money.new(0.0, "USD"),
86
- tax_code: "TAX01"
87
- )
88
- end
89
-
90
- # Calculating the ltl shipping rates based on the conditions.
91
- def get_ltl_shipping
92
- weight_price = 0
93
- case weight_convertion
94
- when 0..2
95
- weight_price = 5
96
- when 2..15
97
- weight_price = 15
98
- when 15..200
99
- weight_price = (1 * weight_convertion)
100
- when 200..2500
101
- weight_price = 200
102
- else
103
- weight_price = ((weight_convertion / 2500).ceil()) * 200
104
- end
105
-
106
- ShippingOption.new(
107
- carrier: "LTL Shipping",
108
- name: "Valken Standard",
109
- sub_name: "3 - 5 Business Days",
110
- service_code: "LTL01",
111
- price: Money.new(weight_price * 100, "USD"),
112
- tax_code: "TAX01"
113
- )
114
- end
115
-
116
- # Returns the total weight.
117
- def weight_convertion
118
- packaging = Packaging.new(order, shipping)
119
- return 0 if packaging.packages.blank?
120
- full_weight = 0
121
- packaging.packages.each do |item_package|
122
- new_weight = item_package.weight.convert_to(:lb)
123
- full_weight += new_weight.value
124
- end
125
- full_weight
126
- end
127
-
128
- # 1. Sending a call to carrier and get shipping rates
129
- # 2. Based on service codes in config, filter the shipping rates
130
- # 3. If error, return empty array
131
- def get_options(carrier, service_code)
132
- packaging = Packaging.new(order, shipping)
133
- return [] if shipping.address.blank? || packaging.packages.blank?
134
- shipping_option = carrier || Workarea.config.gateways.shipping
135
-
136
- origin = ActiveShipping::Location.new(Workarea.config.shipping_origin)
137
- begin
138
- response = shipping_option.find_rates(
139
- origin,
140
- shipping.address.to_active_shipping,
141
- packaging.packages
142
- )
143
- if carrier.class == ActiveShipping::Workarea
144
- response.rates.sort_by(&:price).map do |rate|
145
- ShippingOption.from_rate_estimate(rate)
146
- end
147
- else
148
- filter_shipping_rates(response.rates, service_code)
149
- end
150
- rescue ActiveShipping::ResponseError => e
151
- return []
152
- end
153
- end
154
-
155
- # Sort rates by delevry date and pick 1st three rates
156
- # Find cheapest rate for those three rates
157
- # Push all the cheap option for 1, 2, & 3 days into an array and return
158
- def filter_shipping_rates(rates, service_code)
159
- filtered_rates = []
160
-
161
- # find and sort all delivery dates and pick 1st three
162
- all_delivery_dates = rates.map { |rate| rate.delivery_date }
163
- uniq_delivery_dates = all_delivery_dates.compact.sort.uniq[0..2]
164
-
165
- # For each delivery dates, find cheapest rates and create shipping option and push
166
- uniq_delivery_dates.each_with_index do |date, index|
167
- selected_rates = rates.select {|rate| rate.delivery_date.present? && rate.delivery_date == date}
168
- cheap_rate = selected_rates.sort_by(&:price).first
169
- description = "#{cheap_rate.delivery_date.strftime('%A, %B %d, %Y')}"
170
- shipping_option = create_shipping_options(cheap_rate, service_code[index], description, Workarea.config.shipping_rates[index])
171
- filtered_rates.push(shipping_option)
172
- end
173
- filtered_rates
174
- end
175
-
176
- # creating a ShippingOption
177
- def create_shipping_options(rate, rate_label = nil, description = nil, sub_name)
178
- ShippingOption.new(
179
- carrier: rate.carrier,
180
- name: rate_label.keys.join || rate.service_name,
181
- sub_name: sub_name.values.join,
182
- service_code: rate.service_code,
183
- description: description,
184
- price: Money.new(rate.price, rate.currency),
185
- tax_code: Shipping::Service.find_tax_code(
186
- rate.carrier,
187
- rate.service_name
188
- )
189
- )
190
- end
191
15
  end
192
16
  end
@@ -7,21 +7,235 @@ module Workarea
7
7
  class_methods do
8
8
  end
9
9
 
10
- def find_method_options(packages, shipping_option)
11
- return [] if address.blank? || packages.blank?
12
- shipping_option = shipping_option || Workarea.config.gateways.shipping
10
+ def order
11
+ @order
12
+ end
13
13
 
14
- origin = ActiveShipping::Location.new(Workarea.config.shipping_origin)
15
- response = shipping_option.find_rates(
16
- origin,
17
- address.to_active_shipping,
18
- packages
14
+ def shipping
15
+ @shipping
16
+ end
17
+
18
+ def find_method_options(order, shipping)
19
+ @order ||= order
20
+ @shipping ||= shipping
21
+ carrier_data = []
22
+ shipping_options_api = get_final_shipping_options(collect_carrier_data)
23
+
24
+ return [] if @error.present?
25
+
26
+ carrier_data.push(shipping_options_api) if shipping_options_api.present? && shipping_options_api.any?
27
+
28
+ if Workarea.config.gateways.ups_carrier.class != ActiveShipping::Workarea
29
+ carrier_data.push(get_ltl_shipping)
30
+ carrier_data.push(get_free_shipping) if Workarea.config.show_free_shipping
31
+ else
32
+ return []
33
+ end
34
+
35
+ carrier_data.flatten.reverse
36
+ end
37
+
38
+ def get_final_shipping_options(rates)
39
+ options = []
40
+
41
+ if is_ground
42
+ ground_rate = rates.detect{|rate| rate.service_code == "GROUND_HOME_DELIVERY" || rate.service_code == "03" }
43
+ return [] if ground_rate.blank?
44
+
45
+ description = "#{ground_rate.delivery_date.strftime('%A, %B %d, %Y')}"
46
+ days_to_deliver = (ground_rate.delivery_date - Date.today).to_i
47
+
48
+ label = Workarea.config.shipping_rates[(days_to_deliver - 1)]
49
+ return options.push(create_shipping_options(ground_rate, label, description))
50
+ end
51
+
52
+ rates.each_with_index do |rate, index|
53
+ description = "#{rate.delivery_date.strftime('%A, %B %d, %Y')}"
54
+ label = Workarea.config.shipping_rates[index]
55
+ options.push(create_shipping_options(rate, label, description))
56
+ end
57
+ options
58
+ end
59
+
60
+ # If the carrier is ups then it will print ups data...or if carrier is fedex then prinnt fedex data...
61
+ # else if it is not both then choose cheapest price.
62
+ def collect_carrier_data
63
+ return get_ups_data if is_ups
64
+ return get_fedex_data if is_fedex
65
+ return get_none_data unless is_ups && is_fedex
66
+ end
67
+
68
+ # UPS data.
69
+ def get_ups_data
70
+ @ups_options ||= get_options(Workarea.config.gateways.ups_carrier, Workarea.config.shipping_rates)
71
+ end
72
+
73
+ # FedEx data.
74
+ def get_fedex_data
75
+ @fedex_response ||= get_options(Workarea.config.gateways.fedex_carrier, Workarea.config.shipping_rates)
76
+ end
77
+
78
+ # If the product is not ups or fedex then it will choose the cheapest price among ups and fedex annd print the value.
79
+ def get_none_data
80
+ return [] if get_ups_data.blank? || get_fedex_data.blank?
81
+ final_options = []
82
+ temp_options = get_fedex_data + get_ups_data
83
+ return [] unless temp_options.any?
84
+
85
+ delivery_dates = temp_options.map(&:delivery_date).uniq.sort
86
+ delivery_dates.each_with_index do |date, index|
87
+ selected_rates = temp_options.select {|rate| rate.delivery_date == date}
88
+ final_options.push(selected_rates.sort_by(&:price).first)
89
+ end
90
+ return final_options
91
+
92
+ end
93
+
94
+ # Free shipping option.
95
+ def get_free_shipping
96
+ ShippingOption.new(
97
+ carrier: "Free Shipping",
98
+ name: "Valken Economy",
99
+ sub_name: "5 - 9 Business Days",
100
+ service_code: "Free",
101
+ price: Money.new(0.0, "USD"),
102
+ tax_code: "TAX01"
19
103
  )
104
+ end
105
+
106
+ # Calculating the ltl shipping rates based on the conditions.
107
+ def get_ltl_shipping
108
+ weight_price = 0
109
+ case weight_convertion
110
+ when 0..2
111
+ weight_price = 5
112
+ when 2..15
113
+ weight_price = 15
114
+ when 15..200
115
+ weight_price = (1 * weight_convertion)
116
+ when 200..2500
117
+ weight_price = 200
118
+ else
119
+ weight_price = ((weight_convertion / 2500).ceil()) * 200
120
+ end
121
+
122
+ ShippingOption.new(
123
+ carrier: "LTL Shipping",
124
+ name: "Valken Standard",
125
+ sub_name: "3 - 5 Business Days",
126
+ service_code: "LTL01",
127
+ price: Money.new(weight_price * 100, "USD"),
128
+ tax_code: "TAX01"
129
+ )
130
+ end
131
+
132
+ # Returns the total weight.
133
+ def weight_convertion
134
+ packaging = Packaging.new(order, shipping)
135
+ return 0 if packaging.packages.blank?
136
+ full_weight = 0
137
+ packaging.packages.each do |item_package|
138
+ new_weight = item_package.weight.convert_to(:lb)
139
+ full_weight += new_weight.value
140
+ end
141
+ full_weight
142
+ end
143
+
144
+ # 1. Sending a call to carrier and get shipping rates
145
+ # 2. Based on service codes in config, filter the shipping rates
146
+ # 3. If error, return empty array
147
+ def get_options(carrier, service_code)
148
+ packaging = Packaging.new(order, shipping)
149
+ return [] if @shipping.address.blank? || packaging.packages.blank?
150
+ shipping_option = carrier || Workarea.config.gateways.shipping
151
+
152
+ origin = ActiveShipping::Location.new(Workarea.config.shipping_origin)
153
+ begin
154
+ response = shipping_option.find_rates(
155
+ origin,
156
+ @shipping.address.to_active_shipping,
157
+ packaging.packages
158
+ )
159
+ if carrier.class == ActiveShipping::Workarea
160
+ response.rates.sort_by(&:price).map do |rate|
161
+ ShippingOption.from_rate_estimate(rate)
162
+ end
163
+ else
164
+ filter_shipping_rates(response.rates, service_code)
165
+ end
166
+ rescue ActiveShipping::ResponseError => e
167
+ @error = e
168
+ return []
169
+ end
170
+ end
171
+
172
+ # Sort rates by delevry date and pick 1st three rates
173
+ # Find cheapest rate for those three rates
174
+ # Push all the cheap option for 1, 2, & 3 days into an array and return
175
+ def filter_shipping_rates(rates, service_code)
176
+ filtered_rates = []
177
+ # find and sort all delivery dates and pick 1st three
178
+ all_delivery_dates = rates.map { |rate| rate.delivery_date }
179
+ # sorting the uniq delivery dates and reversing those delivery dates.
180
+ uniq_delivery_dates = all_delivery_dates.compact.sort.uniq[0..2]
181
+
182
+ # removing overnight. Assuming the 3rd option is always overnight
183
+ uniq_delivery_dates.pop if uniq_delivery_dates.length == 3
184
+
185
+ # For each delivery dates, find cheapest rates and create shipping option and push
186
+ uniq_delivery_dates.each_with_index do |date, index|
187
+ selected_rates = rates.select {|rate| rate.delivery_date.present? && rate.delivery_date == date}
188
+ cheap_rate = selected_rates.sort_by(&:price).first
189
+ description = "#{cheap_rate.delivery_date.strftime('%A, %B %d, %Y')}"
20
190
 
21
- response.rates.sort_by(&:price).map do |rate|
22
- ShippingOption.from_rate_estimate(rate)
191
+ filtered_rates.push(cheap_rate)
23
192
  end
193
+ filtered_rates
194
+ end
195
+
196
+ # creating a ShippingOption
197
+ def create_shipping_options(rate, rate_label = nil, description = nil)
198
+ ShippingOption.new(
199
+ carrier: rate.carrier,
200
+ name: rate_label.keys.join || rate.service_name,
201
+ sub_name: rate_label.values.join,
202
+ service_code: rate.service_code,
203
+ description: description,
204
+ delivery_date: rate.delivery_date,
205
+ price: Money.new(rate.price, rate.currency),
206
+ tax_code: Shipping::Service.find_tax_code(
207
+ rate.carrier,
208
+ rate.service_name
209
+ )
210
+ )
211
+ end
212
+
213
+ # Selecting the shipping carrier based on order items
214
+ #
215
+ # If the product is type hazmat then it returns ups...or if product is type gun then it returns fedex
216
+ # else if product is not both type then it returns none
217
+ def is_fedex
218
+ carrier_type_attribute = Workarea.config.shipping_attributes[:carrier_type]
219
+ product_carrier_type = product_details.map{ |item| item[:en][carrier_type_attribute] }.flatten
220
+ product_carrier_type.include?("FEDEX")
221
+ end
222
+
223
+ def is_ups
224
+ carrier_type_attribute = Workarea.config.shipping_attributes[:carrier_type]
225
+ product_carrier_type = product_details.map{ |item| item[:en][carrier_type_attribute] }.flatten
226
+ product_carrier_type.include?("UPS")
227
+ end
228
+
229
+ def is_ground
230
+ ground_ship_attribute = Workarea.config.shipping_attributes[:ground_shipping_only]
231
+ product_carrier_type = product_details.map{ |item| item[:en][ground_ship_attribute] }.flatten
232
+ product_carrier_type.include?("true")
233
+ end
234
+
235
+ def product_details
236
+ # product_attributes = @order.items.map(&:product_attributes)
24
237
 
238
+ @product_details ||= Catalog::Product.in(id: @order.items.to_a.map(&:product_id)).pluck(:details)
25
239
  end
26
240
  end
27
241
  end
@@ -1,7 +1,7 @@
1
1
  module Workarea
2
2
  decorate ShippingOption, with: :valken do
3
3
  decorated do
4
- attr_reader :description, :sub_name
4
+ attr_reader :description, :sub_name, :delivery_date
5
5
  end
6
6
 
7
7
  class_methods do
@@ -0,0 +1,12 @@
1
+ Workarea::Configuration.define_fields do
2
+ fieldset 'Shipping', namespaced: false do
3
+ field 'Shipping Attributes',
4
+ type: :hash,
5
+ default: {
6
+ 'usa_only' => 'usa only',
7
+ 'carrier_type' => 'Type',
8
+ 'ground_shipping_only' => 'ground shipping only'
9
+ },
10
+ description: 'Mapping of product details keys with shipping logic. Note: This maps only the keys not the values.'
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  module Valken
2
2
  module Shipping
3
- VERSION = '2.0.0'
3
+ VERSION = '2.0.1'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valken-shipping
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - sushmitha02
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-31 00:00:00.000000000 Z
11
+ date: 2020-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -41,10 +41,12 @@ files:
41
41
  - README.md
42
42
  - Rakefile
43
43
  - app/assets/config/valken_shipping_manifest.js
44
+ - app/helpers/workarea/addresses_helper.rb
44
45
  - app/models/workarea/checkout/shipping_options.decorator
45
46
  - app/models/workarea/shipping.decorator
46
47
  - app/models/workarea/shipping_option.decorator
47
48
  - app/services/workarea/packaging.decorator
49
+ - config/initializers/shipping_configuration.rb
48
50
  - config/initializers/workarea.rb
49
51
  - config/routes.rb
50
52
  - lib/tasks/valken/shipping_tasks.rake
@@ -70,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
72
  - !ruby/object:Gem::Version
71
73
  version: '0'
72
74
  requirements: []
73
- rubygems_version: 3.0.8
75
+ rubygems_version: 3.0.6
74
76
  signing_key:
75
77
  specification_version: 4
76
78
  summary: shipping options