valken-shipping 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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