Custom shipping calculators
This article provides context about creating custom shipping calculators in the case that the provided calculators do not meet your store's needs.
Before developing a custom calculator, you should make sure that the calculator you need doesn't already exist in Solidus or one of its extensions.
Solidus comes with a set of default calculators that account for typical shipping scenarios:
- Flat percent
- Flat rate (per order)
- Flat rate per package item
- Flexible rate per package item
- Price sack
If the calculators that come with Solidus are not enough for your needs, you
might want to use an extension like
that provides additional
API-based rate calculation functionality for common carriers like UPS, USPS, and
FedEx. Alternatively, you could develop your own custom calculator.
Custom calculator requirements
A custom calculator should accept a
return a cost.
package.order method to access the current order's information, and
package.contents methods to access the current package's contents. As a
developer, you should always deal with the
package.contents. Otherwise, you
may be quoting an entire order when you only want to quote one of many shipments
on an order.
Typically, a calculator uses the following order information:
Spree::Addressused as the order's shipping address.
Spree::LineItemobjects associated with the order.
Spree::Variantproduct information (such as the weight and dimensions) associated with each line item in the order.
For an example of a typical calculator, we recommend reading the source code for Solidus's stock flat rate calculator .
For a more complicated example of what is possible with custom calculators, see
solidus_active_shipping base calculator
calculator collects enough information about an order to send to a carrier and
get a rate quote back.
Inherit from the
Your custom shipping calculator should inherit from the existing
Spree::ShippingCalculator class. We recommend following the same directory
structure that Spree models do, so your new calculator would be created at:
Then, follow the pattern of Spree's built-in calculators and inherit from
module MyStore class Calculator::Shipping::CustomShippingCalculator < Spree::ShippingCalculator end end
Your custom shipping calculator requires at least two methods:
self.descriptionmethod that provides a name for the custom calculator.
compute_package(package)that provides the return value for a package being shipped.
module MyStore class Calculator::Shipping::CustomShippingCalculator < Spree::ShippingCalculator def self.description "Custom Shipping Calculator" end def compute_package(package) 12.00 end end end
Register the new shipping calculator
Once you have created the logic for the new shipping calculator, you need to register it so that administrators can create new shipping methods that use the custom calculator.
For example, you can register it in your
module MyStore class Application < Rails::Application ... initializer 'spree.register.calculators' do |app| app.config.spree.calculators.shipping_methods << MyStore::Calculator::Shipping::CustomShippingCalculator end end end
By default, shipping calculators are always available to be used by shipping
methods. This is because the
available? method on the base
true by default.
You may want to make the calculator availability change depending on some aspect
of the current order. To do this, you can override the
available? method in
your custom calculator:
module MyStore class Calculator::Shipping::CustomShippingCalculator < Spree::ShippingCalculator ... def available?(order) order.currency == "USD" end end end
For more information about availability and filtering shipping methods, see the Shipping method filters article.
Use additional product information
In addition to providing relevant information about shipping addresses and product variants, you can use information about the product itself to inform a calculator's results. A product's tax category or shipping category could be meaningful information for shipping calculations. By default, each package contains only items in the same shipping category.
For example, you might want your calculator to handle your product with a shipping category of "Oversized" differently than it would a product with the "Default" shipping category.
For example, you might want your calculator to handle products with different shipping categories in specific ways: an product with the "Oversized" category should not be treated like a product with the "Default" category.
Solidus is an open source platform supported by the community. We encourage everyone using Solius to contribute back to the documentation and the code.