valken-shipping 2.0.0 → 2.0.6

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