solidus_easypost 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +6 -0
- data/.github/stale.yml +4 -4
- data/.github_changelog_generator +2 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +12 -47
- data/CHANGELOG.md +113 -0
- data/LICENSE +1 -1
- data/README.md +111 -21
- data/app/controllers/spree/admin/postage_labels_controller.rb +20 -0
- data/app/decorators/models/solidus_easypost/spree/carton_decorator.rb +38 -0
- data/app/decorators/models/solidus_easypost/spree/shipment_decorator.rb +18 -23
- data/app/models/solidus_easypost/parcel_dimension.rb +34 -0
- data/app/models/solidus_easypost/return_authorization.rb +2 -13
- data/app/overrides/spree/admin/orders/_shipment/add_postage_label.html.erb.deface +10 -0
- data/bin/rails +0 -1
- data/bin/rails-engine +0 -2
- data/bin/rails-sandbox +1 -2
- data/bin/sandbox +2 -0
- data/config/initializers/webhooks.rb +7 -0
- data/config/locales/en.yml +7 -4
- data/config/routes.rb +5 -1
- data/db/migrate/20201025110912_add_tracker_id_to_cartons.rb +6 -0
- data/lib/generators/solidus_easypost/install/install_generator.rb +7 -1
- data/lib/generators/solidus_easypost/install/templates/initializer.rb +26 -0
- data/lib/solidus_easypost/address_builder.rb +45 -0
- data/lib/solidus_easypost/calculator/base_dimension_calculator.rb +28 -0
- data/lib/solidus_easypost/calculator/weight_dimension_calculator.rb +22 -0
- data/lib/solidus_easypost/configuration.rb +25 -2
- data/lib/solidus_easypost/errors/unknown_partial_resource_error.rb +11 -0
- data/lib/solidus_easypost/estimator.rb +37 -0
- data/lib/solidus_easypost/parcel_builder.rb +27 -0
- data/lib/solidus_easypost/shipment_builder.rb +32 -0
- data/lib/solidus_easypost/shipping_method_selector.rb +17 -0
- data/lib/solidus_easypost/shipping_rate_calculator.rb +9 -0
- data/lib/solidus_easypost/testing_support/factories/address_factory.rb +10 -0
- data/lib/solidus_easypost/testing_support/factories/product_factory.rb +7 -0
- data/lib/solidus_easypost/testing_support/factories/shipment_factory.rb +30 -0
- data/lib/solidus_easypost/testing_support/factories/shipping_method_factory.rb +8 -0
- data/lib/solidus_easypost/testing_support/factories/stock_location_factory.rb +10 -0
- data/lib/solidus_easypost/testing_support/factories/variant_factory.rb +7 -0
- data/lib/solidus_easypost/testing_support/factories.rb +3 -0
- data/lib/solidus_easypost/tracker_webhook_handler.rb +14 -0
- data/lib/solidus_easypost/version.rb +1 -1
- data/lib/solidus_easypost.rb +11 -0
- data/solidus_easypost.gemspec +8 -5
- data/spec/cassettes/{Spree_Address/_easypost_address/is_an_EasyPost_Address_object.yml → address_builder/from_address.yml} +19 -23
- data/spec/cassettes/{Spree_StockLocation/_easypost_address/is_an_EasyPost_Address_object.yml → address_builder/from_stock_location.yml} +19 -23
- data/spec/cassettes/{Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_exist/when_shipping_methods_are_front_end_visible/has_the_correct_costs.yml → estimator.yml} +0 -0
- data/spec/cassettes/integration/checkout.yml +377 -0
- data/spec/cassettes/integration/order_shipping/with_purchase_labels.yml +373 -0
- data/spec/cassettes/integration/order_shipping/without_purchase_labels.yml +251 -0
- data/spec/cassettes/{Spree_Stock_Package/_easypost_parcel/is_an_EasyPost_Parcel_object.yml → parcel_builder/from_package.yml} +17 -22
- data/spec/cassettes/{Spree_Stock_Package/_easypost_parcel/has_the_correct_attributes.yml → parcel_builder/from_return_authorization.yml} +17 -22
- data/spec/cassettes/postage_labels/show.yml +72 -0
- data/spec/cassettes/return_authorization.yml +310 -0
- data/spec/cassettes/{Spree_Stock_Package/_easypost_shipment/is_an_EasyPost_Shipment_object.yml → shipment_builder/from_package.yml} +74 -92
- data/spec/cassettes/{Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_exist/create_no_new_shipping_methods.yml → shipment_builder/from_return_authorization.yml} +77 -95
- data/spec/cassettes/shipment_builder/from_shipment.yml +250 -0
- data/spec/controllers/spree/admin/postage_labels_controller_spec.rb +18 -0
- data/spec/features/admin/postage_labels_spec.rb +18 -0
- data/spec/integration/checkout_spec.rb +45 -0
- data/spec/integration/order_shipping_spec.rb +33 -0
- data/spec/models/solidus_easypost/parcel_dimension_spec.rb +80 -0
- data/spec/models/solidus_easypost/return_authorization_spec.rb +7 -40
- data/spec/models/spree/carton_spec.rb +57 -0
- data/spec/models/spree/shipment_spec.rb +48 -59
- data/spec/models/spree/shipping_rate_spec.rb +14 -7
- data/spec/solidus_easypost/address_builder_spec.rb +17 -0
- data/spec/solidus_easypost/calculator/weight_dimension_calculator_spec.rb +39 -0
- data/spec/solidus_easypost/estimator_spec.rb +52 -0
- data/spec/solidus_easypost/parcel_builder_spec.rb +113 -0
- data/spec/solidus_easypost/shipment_builder_spec.rb +28 -0
- data/spec/solidus_easypost/shipping_method_selector_spec.rb +33 -0
- data/spec/solidus_easypost/shipping_rate_calculator_spec.rb +12 -0
- data/spec/solidus_easypost/tracker_webhook_handler_spec.rb +58 -0
- data/spec/spec_helper.rb +11 -7
- data/spec/support/easypost.rb +3 -1
- data/spec/support/helpers/api_stubs.rb +40 -0
- data/spec/support/helpers/configuration.rb +28 -0
- data/spec/support/helpers/shipping_methods.rb +26 -0
- data/spec/support/solidus.rb +1 -0
- data/spec/support/vcr.rb +1 -0
- metadata +118 -85
- data/app/decorators/models/solidus_easypost/spree/address_decorator.rb +0 -30
- data/app/decorators/models/solidus_easypost/spree/stock/estimator_decorator.rb +0 -15
- data/app/decorators/models/solidus_easypost/spree/stock/package_decorator.rb +0 -27
- data/app/decorators/models/solidus_easypost/spree/stock_location_decorator.rb +0 -26
- data/app/models/solidus_easypost/estimator.rb +0 -51
- data/lib/solidus_easypost/factories.rb +0 -24
- data/spec/cassettes/SolidusEasypost_ReturnAuthorization/_easypost_shipment/is_an_EasyPost_Shipment_object.yml +0 -271
- data/spec/cassettes/SolidusEasypost_ReturnAuthorization/_return_label/has_the_correct_fields.yml +0 -336
- data/spec/cassettes/SolidusEasypost_ReturnAuthorization/_return_label/is_an_EasyPost_PackageLabel_object.yml +0 -336
- data/spec/cassettes/Spree_Address/_easypost_address/has_the_correct_attributes.yml +0 -69
- data/spec/cassettes/Spree_Order/_refresh_shipment_rates/can_get_rates_from_easy_post.yml +0 -271
- data/spec/cassettes/Spree_Order/_refresh_shipment_rates/create_shipping_methods_for_the_rates.yml +0 -269
- data/spec/cassettes/Spree_Shipment/_buys_a_shipping_rate_after_transitioning_to_ship.yml +0 -403
- data/spec/cassettes/Spree_Shipment/_easypost_shipment/when_it_is_a_new_shipment/behaves_like_an_easypost_shipment/is_an_EasyPost_Shipment_object.yml +0 -271
- data/spec/cassettes/Spree_Shipment/_easypost_shipment/when_it_is_a_new_shipment/calls_the_api.yml +0 -200
- data/spec/cassettes/Spree_Shipment/_easypost_shipment/when_it_is_an_existing_shipment/behaves_like_an_easypost_shipment/is_an_EasyPost_Shipment_object.yml +0 -334
- data/spec/cassettes/Spree_Shipment/_easypost_shipment/when_it_is_an_existing_shipment/loads_the_existing_shipment.yml +0 -271
- data/spec/cassettes/Spree_StockLocation/_easypost_address/has_the_correct_attributes.yml +0 -69
- data/spec/cassettes/Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_dont_exist/creates_new_shipping_methods.yml +0 -269
- data/spec/cassettes/Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_dont_exist/is_empty.yml +0 -269
- data/spec/cassettes/Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_exist/when_shipping_methods_are_front_end_visible/has_the_correct_names.yml +0 -269
- data/spec/cassettes/Spree_Stock_Estimator/_shipping_rates/when_rates_are_found/when_shipping_methods_exist/when_shipping_methods_are_not_front_end_visible/is_empty.yml +0 -269
- data/spec/cassettes/Spree_Stock_Package/_easypost_shipment/calls_the_api.yml +0 -200
- data/spec/factories/spree_modification.rb +0 -25
- data/spec/models/spree/address_spec.rb +0 -31
- data/spec/models/spree/order_spec.rb +0 -31
- data/spec/models/spree/stock/estimator_spec.rb +0 -80
- data/spec/models/spree/stock/package_spec.rb +0 -35
- data/spec/models/spree/stock_location_spec.rb +0 -31
- data/spec/support/shipping_method_helpers.rb +0 -43
@@ -0,0 +1,10 @@
|
|
1
|
+
<!-- insert_bottom '[data-hook="stock-contents"] tbody' -->
|
2
|
+
|
3
|
+
<% if shipment.selected_easy_post_rate_id && shipment.shipped? %>
|
4
|
+
<tr class="postage-label">
|
5
|
+
<td colspan="5">
|
6
|
+
<strong><%= t('spree.postage_label') %>:</strong>
|
7
|
+
<%= link_to_with_icon('external-link', t('spree.open_postage_label'), admin_shipment_postage_label_path(shipment)) %>
|
8
|
+
</td>
|
9
|
+
</tr>
|
10
|
+
<% end %>
|
data/bin/rails
CHANGED
data/bin/rails-engine
CHANGED
data/bin/rails-sandbox
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
2
|
|
4
3
|
app_root = 'sandbox'
|
5
4
|
|
6
5
|
unless File.exist? "#{app_root}/bin/rails"
|
7
6
|
warn 'Creating the sandbox app...'
|
8
7
|
Dir.chdir "#{__dir__}/.." do
|
9
|
-
system "#{__dir__}/sandbox" or begin
|
8
|
+
system "#{__dir__}/sandbox" or begin
|
10
9
|
warn 'Automatic creation of the sandbox app failed'
|
11
10
|
exit 1
|
12
11
|
end
|
data/bin/sandbox
CHANGED
@@ -72,9 +72,11 @@ unbundled bundle exec rails generate spree:install \
|
|
72
72
|
--user_class=Spree::User \
|
73
73
|
--enforce_available_locales=true \
|
74
74
|
--with-authentication=false \
|
75
|
+
--payment-method=none \
|
75
76
|
$@
|
76
77
|
|
77
78
|
unbundled bundle exec rails generate solidus:auth:install
|
79
|
+
unbundled bundle exec rails generate ${extension_name}:install
|
78
80
|
|
79
81
|
echo
|
80
82
|
echo "🚀 Sandbox app successfully created for $extension_name!"
|
data/config/locales/en.yml
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
# Sample localization file for English. Add more files in this directory for other locales.
|
2
|
-
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
|
3
|
-
|
4
1
|
en:
|
5
|
-
|
2
|
+
spree:
|
3
|
+
postage_label: 'Postage Label'
|
4
|
+
open_postage_label: 'Open'
|
5
|
+
admin:
|
6
|
+
postage_labels:
|
7
|
+
show:
|
8
|
+
no_postage_label: 'No postage label available for shipment %{shipment_number}.'
|
data/config/routes.rb
CHANGED
@@ -3,14 +3,20 @@
|
|
3
3
|
module SolidusEasypost
|
4
4
|
module Generators
|
5
5
|
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
7
|
+
|
6
8
|
class_option :auto_run_migrations, type: :boolean, default: false
|
7
9
|
|
10
|
+
def copy_initializer
|
11
|
+
template 'initializer.rb', 'config/initializers/solidus_easypost.rb'
|
12
|
+
end
|
13
|
+
|
8
14
|
def add_migrations
|
9
15
|
run 'bin/rails railties:install:migrations FROM=solidus_easypost'
|
10
16
|
end
|
11
17
|
|
12
18
|
def run_migrations
|
13
|
-
run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
|
19
|
+
run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
|
14
20
|
if run_migrations
|
15
21
|
run 'bin/rails db:migrate'
|
16
22
|
else
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
EasyPost.api_key = 'YOUR_API_KEY_HERE'
|
4
|
+
|
5
|
+
SolidusEasypost.configure do |config|
|
6
|
+
# Purchase labels from EasyPost when shipping shipments in Solidus?
|
7
|
+
# config.purchase_labels = true
|
8
|
+
|
9
|
+
# Create a tracker in EasyPost and receive webhooks for all cartons?
|
10
|
+
# config.track_all_cartons = false
|
11
|
+
|
12
|
+
# A class that responds to `#compute`, accepting an `EasyPost::Rate`
|
13
|
+
# instance and returning the cost for that rate.
|
14
|
+
# config.shipping_rate_calculator_class = 'SolidusEasypost::ShippingRateCalculator'
|
15
|
+
|
16
|
+
# A class that responds to `#shipping_method_for`, accepting an
|
17
|
+
# `EasyPost::Rate` instance and returning the shipping method for
|
18
|
+
# that rate.
|
19
|
+
# config.shipping_method_selector_class = 'SolidusEasypost::ShippingMethodSelector'
|
20
|
+
|
21
|
+
# A class that responds to '#compute', accepting a `SolidusEasypost::ReturnAuthorization`
|
22
|
+
# instance or a `Spree::Stock::Package` instance and returing the `SolidusEasypost::ParcelDimension` object.
|
23
|
+
# The `SolidusEasypost::Calculator::BaseDimensionCalculator` class can be extended to have a common
|
24
|
+
# functionality.
|
25
|
+
# config.parcel_dimension_calculator_class = 'SolidusEasypost::Calculator::WeightDimensionCalculator'
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusEasypost
|
4
|
+
class AddressBuilder
|
5
|
+
class << self
|
6
|
+
def from_address(address)
|
7
|
+
attributes = {
|
8
|
+
street1: address.address1,
|
9
|
+
street2: address.address2,
|
10
|
+
city: address.city,
|
11
|
+
zip: address.zipcode,
|
12
|
+
phone: address.phone
|
13
|
+
}
|
14
|
+
|
15
|
+
attributes[:company] = address.company if address.respond_to?(:company)
|
16
|
+
attributes[:name] = if address.respond_to?(:name)
|
17
|
+
address.name
|
18
|
+
elsif respond_to?(:full_name)
|
19
|
+
address.full_name
|
20
|
+
end
|
21
|
+
attributes[:state] = address.state ? address.state.abbr : address.state_name
|
22
|
+
attributes[:country] = address.country&.iso
|
23
|
+
|
24
|
+
::EasyPost::Address.create attributes
|
25
|
+
end
|
26
|
+
|
27
|
+
def from_stock_location(stock_location)
|
28
|
+
attributes = {
|
29
|
+
street1: stock_location.address1,
|
30
|
+
street2: stock_location.address2,
|
31
|
+
city: stock_location.city,
|
32
|
+
zip: stock_location.zipcode,
|
33
|
+
phone: stock_location.phone,
|
34
|
+
name: stock_location.name,
|
35
|
+
company: stock_location.name
|
36
|
+
}
|
37
|
+
|
38
|
+
attributes[:state] = stock_location.state ? stock_location.state.abbr : stock_location.state_name
|
39
|
+
attributes[:country] = stock_location.country&.iso
|
40
|
+
|
41
|
+
::EasyPost::Address.create attributes
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusEasypost
|
4
|
+
module Calculator
|
5
|
+
class BaseDimensionCalculator
|
6
|
+
def compute(resource)
|
7
|
+
case resource
|
8
|
+
when ::SolidusEasypost::ReturnAuthorization
|
9
|
+
compute_for_return_authorization(resource)
|
10
|
+
when ::Spree::Stock::Package
|
11
|
+
compute_for_package(resource)
|
12
|
+
else
|
13
|
+
raise SolidusEasypost::Errors::UnknownPartialResourceError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def compute_for_return_authorization(return_authorization)
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def compute_for_package(package)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusEasypost
|
4
|
+
module Calculator
|
5
|
+
class WeightDimensionCalculator < BaseDimensionCalculator
|
6
|
+
protected
|
7
|
+
|
8
|
+
def compute_for_return_authorization(return_authorization)
|
9
|
+
total_weight = return_authorization.inventory_units.joins(:variant).sum(:weight)
|
10
|
+
SolidusEasypost::ParcelDimension.new(weight: total_weight)
|
11
|
+
end
|
12
|
+
|
13
|
+
def compute_for_package(package)
|
14
|
+
total_weight = package.contents.sum do |item|
|
15
|
+
item.quantity * item.variant.weight
|
16
|
+
end
|
17
|
+
|
18
|
+
SolidusEasypost::ParcelDimension.new(weight: total_weight)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -2,10 +2,33 @@
|
|
2
2
|
|
3
3
|
module SolidusEasypost
|
4
4
|
class Configuration
|
5
|
-
|
5
|
+
attr_accessor :purchase_labels, :track_all_cartons
|
6
|
+
attr_writer :shipping_rate_calculator_class, :shipping_method_selector_class, :parcel_dimension_calculator_class,
|
7
|
+
:webhook_handler_class
|
6
8
|
|
7
9
|
def initialize
|
8
|
-
|
10
|
+
self.purchase_labels = true
|
11
|
+
self.track_all_cartons = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def shipping_rate_calculator_class
|
15
|
+
@shipping_rate_calculator_class ||= 'SolidusEasypost::ShippingRateCalculator'
|
16
|
+
@shipping_rate_calculator_class.constantize
|
17
|
+
end
|
18
|
+
|
19
|
+
def shipping_method_selector_class
|
20
|
+
@shipping_method_selector_class ||= 'SolidusEasypost::ShippingMethodSelector'
|
21
|
+
@shipping_method_selector_class.constantize
|
22
|
+
end
|
23
|
+
|
24
|
+
def parcel_dimension_calculator_class
|
25
|
+
@parcel_dimension_calculator_class ||= 'SolidusEasypost::Calculator::WeightDimensionCalculator'
|
26
|
+
@parcel_dimension_calculator_class.constantize
|
27
|
+
end
|
28
|
+
|
29
|
+
def webhook_handler_class
|
30
|
+
@webhook_handler_class ||= 'SolidusEasypost::TrackerWebhookHandler'
|
31
|
+
@webhook_handler_class.constantize
|
9
32
|
end
|
10
33
|
end
|
11
34
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusEasypost
|
4
|
+
class Estimator
|
5
|
+
def shipping_rates(package, _frontend_only = true)
|
6
|
+
easypost_rates = ShipmentBuilder.from_package(package).rates.sort_by(&:rate)
|
7
|
+
|
8
|
+
shipping_rates = easypost_rates.map { |rate| build_shipping_rate(rate) }.compact
|
9
|
+
shipping_rates.min_by(&:cost)&.selected = true
|
10
|
+
|
11
|
+
shipping_rates
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def build_shipping_rate(rate)
|
17
|
+
shipping_method = shipping_method_selector.shipping_method_for(rate)
|
18
|
+
return unless shipping_method.available_to_users?
|
19
|
+
|
20
|
+
::Spree::ShippingRate.new(
|
21
|
+
name: "#{rate.carrier} #{rate.service}",
|
22
|
+
cost: shipping_rate_calculator.compute(rate),
|
23
|
+
easy_post_shipment_id: rate.shipment_id,
|
24
|
+
easy_post_rate_id: rate.id,
|
25
|
+
shipping_method: shipping_method,
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def shipping_rate_calculator
|
30
|
+
@shipping_rate_calculator ||= SolidusEasypost.configuration.shipping_rate_calculator_class.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def shipping_method_selector
|
34
|
+
@shipping_method_selector ||= SolidusEasypost.configuration.shipping_method_selector_class.new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusEasypost
|
4
|
+
class ParcelBuilder
|
5
|
+
class << self
|
6
|
+
def from_package(package)
|
7
|
+
parcel_dimension = SolidusEasypost
|
8
|
+
.configuration
|
9
|
+
.parcel_dimension_calculator_class
|
10
|
+
.new
|
11
|
+
.compute(package)
|
12
|
+
|
13
|
+
::EasyPost::Parcel.create(parcel_dimension.to_h)
|
14
|
+
end
|
15
|
+
|
16
|
+
def from_return_authorization(return_authorization)
|
17
|
+
parcel_dimension = SolidusEasypost
|
18
|
+
.configuration
|
19
|
+
.parcel_dimension_calculator_class
|
20
|
+
.new
|
21
|
+
.compute(return_authorization)
|
22
|
+
|
23
|
+
::EasyPost::Parcel.create(parcel_dimension.to_h)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusEasypost
|
4
|
+
class ShipmentBuilder
|
5
|
+
class << self
|
6
|
+
def from_package(package)
|
7
|
+
::EasyPost::Shipment.create(
|
8
|
+
to_address: AddressBuilder.from_address(package.order.ship_address),
|
9
|
+
from_address: AddressBuilder.from_stock_location(package.stock_location),
|
10
|
+
parcel: ParcelBuilder.from_package(package),
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def from_shipment(shipment)
|
15
|
+
::EasyPost::Shipment.create(
|
16
|
+
to_address: AddressBuilder.from_address(shipment.order.ship_address),
|
17
|
+
from_address: AddressBuilder.from_stock_location(shipment.stock_location),
|
18
|
+
parcel: ParcelBuilder.from_package(shipment.to_package),
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def from_return_authorization(return_authorization)
|
23
|
+
::EasyPost::Shipment.create(
|
24
|
+
from_address: AddressBuilder.from_stock_location(return_authorization.stock_location),
|
25
|
+
to_address: AddressBuilder.from_address(return_authorization.order.ship_address),
|
26
|
+
parcel: ParcelBuilder.from_return_authorization(return_authorization),
|
27
|
+
is_return: true
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusEasypost
|
4
|
+
class ShippingMethodSelector
|
5
|
+
def shipping_method_for(rate)
|
6
|
+
::Spree::ShippingMethod.find_or_create_by(
|
7
|
+
carrier: rate.carrier,
|
8
|
+
service_level: rate.service,
|
9
|
+
) do |shipping_method|
|
10
|
+
shipping_method.name = "#{rate.carrier} #{rate.service}"
|
11
|
+
shipping_method.calculator = ::Spree::Calculator::Shipping::FlatRate.create
|
12
|
+
shipping_method.shipping_categories = [::Spree::ShippingCategory.first]
|
13
|
+
shipping_method.available_to_users = false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
FactoryBot.modify do
|
4
|
+
factory :shipment do
|
5
|
+
transient do
|
6
|
+
inventory_units { 1 }
|
7
|
+
end
|
8
|
+
|
9
|
+
after(:create) do |shipment, e|
|
10
|
+
create_list(:inventory_unit, e.inventory_units, shipment: shipment)
|
11
|
+
end
|
12
|
+
|
13
|
+
trait :with_easypost do
|
14
|
+
transient do
|
15
|
+
easypost_shipment_id { 'sh_test' }
|
16
|
+
easypost_rate_id { 'rt_test' }
|
17
|
+
end
|
18
|
+
|
19
|
+
after(:create) do |shipment, evaluator|
|
20
|
+
create(
|
21
|
+
:shipping_rate,
|
22
|
+
shipment: shipment,
|
23
|
+
selected: true,
|
24
|
+
easy_post_shipment_id: evaluator.easypost_shipment_id,
|
25
|
+
easy_post_rate_id: evaluator.easypost_rate_id,
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusEasypost
|
4
|
+
class TrackerWebhookHandler
|
5
|
+
def self.call(payload)
|
6
|
+
return unless payload['description'] == 'tracker.updated'
|
7
|
+
|
8
|
+
carton = ::Spree::Carton.find_by(easy_post_tracker_id: payload['result']['id'])
|
9
|
+
return unless carton
|
10
|
+
|
11
|
+
::Spree::Event.fire 'solidus_easypost.tracker.updated', carton: carton, payload: payload
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/solidus_easypost.rb
CHANGED
@@ -2,11 +2,22 @@
|
|
2
2
|
|
3
3
|
require 'solidus_core'
|
4
4
|
require 'solidus_support'
|
5
|
+
require 'deface'
|
5
6
|
require 'easypost'
|
6
7
|
|
7
8
|
require 'solidus_easypost/version'
|
8
9
|
require 'solidus_easypost/engine'
|
9
10
|
require 'solidus_easypost/configuration'
|
11
|
+
require 'solidus_easypost/address_builder'
|
12
|
+
require 'solidus_easypost/parcel_builder'
|
13
|
+
require 'solidus_easypost/shipment_builder'
|
14
|
+
require 'solidus_easypost/estimator'
|
15
|
+
require 'solidus_easypost/shipping_rate_calculator'
|
16
|
+
require 'solidus_easypost/shipping_method_selector'
|
17
|
+
require 'solidus_easypost/calculator/base_dimension_calculator'
|
18
|
+
require 'solidus_easypost/calculator/weight_dimension_calculator'
|
19
|
+
require 'solidus_easypost/tracker_webhook_handler'
|
20
|
+
require 'solidus_easypost/errors/unknown_partial_resource_error'
|
10
21
|
|
11
22
|
module SolidusEasypost
|
12
23
|
class << self
|
data/solidus_easypost.gemspec
CHANGED
@@ -8,15 +8,14 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ['Brendan Deere']
|
9
9
|
spec.email = 'brendan@stembolt.com'
|
10
10
|
|
11
|
-
spec.summary = '
|
12
|
-
spec.description = 'Easy post integration for Solidus'
|
11
|
+
spec.summary = 'EasyPost integration for Solidus stores.'
|
13
12
|
spec.homepage = 'https://github.com/solidusio-contrib/solidus_easypost'
|
14
13
|
spec.license = 'BSD-3-Clause'
|
15
14
|
|
16
15
|
spec.metadata['homepage_uri'] = spec.homepage
|
17
16
|
spec.metadata['source_code_uri'] = 'https://github.com/solidusio-contrib/solidus_easypost'
|
18
17
|
|
19
|
-
spec.required_ruby_version = Gem::Requirement.new('
|
18
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.5')
|
20
19
|
|
21
20
|
# Specify which files should be added to the gem when it is released.
|
22
21
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -28,11 +27,15 @@ Gem::Specification.new do |spec|
|
|
28
27
|
spec.executables = files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
28
|
spec.require_paths = ["lib"]
|
30
29
|
|
30
|
+
spec.add_dependency 'deface'
|
31
31
|
spec.add_dependency 'easypost'
|
32
|
-
spec.add_dependency 'solidus_core', ['>= 2.0.0', '<
|
32
|
+
spec.add_dependency 'solidus_core', ['>= 2.0.0', '< 4']
|
33
33
|
spec.add_dependency 'solidus_support', '~> 0.5'
|
34
34
|
|
35
|
-
spec.add_development_dependency 'solidus_dev_support'
|
35
|
+
spec.add_development_dependency 'solidus_dev_support', '~> 2.1'
|
36
36
|
spec.add_development_dependency 'vcr'
|
37
37
|
spec.add_development_dependency 'webmock'
|
38
|
+
spec.metadata = {
|
39
|
+
'rubygems_mfa_required' => 'true'
|
40
|
+
}
|
38
41
|
end
|