solidus_easypost 2.0.0 → 3.0.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.
- 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
|