From 4374e767b9cec52c68c5306382ba6668313ce52b Mon Sep 17 00:00:00 2001 From: Benjamin Willems Date: Wed, 17 Jan 2018 15:13:13 -0800 Subject: [PATCH 1/6] Add overview documentation for Spree::Calculators --- guides/calculators/overview.md | 104 +++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 guides/calculators/overview.md diff --git a/guides/calculators/overview.md b/guides/calculators/overview.md new file mode 100644 index 00000000000..9b48a9e2975 --- /dev/null +++ b/guides/calculators/overview.md @@ -0,0 +1,104 @@ +# Overview + +All calculators in Solidus inherit from the `Spree::Calculator` base class. They +calculate and return the value of promotions, taxes, and shipping charges. +Solidus includes built-in calculators for common types of calculations, such as +flat rate shipping, percentage discounts, sales tax, and value-added tax (VAT). + +Whenever you create a new shipping method, tax rate, or promotion action, you +also create a new instance of a `Spree::Calculator`. + +For example, if you create a new shipping method called "USPS Ground" that +charges a flat rate of $10 USD, you would be creating an instance of the +`Spree::Calculator::Shipping::FlatRate` calculator: + +- The new calculator instance would have `calculable_type` of + `Spree::ShippingMethod` (because it is associated with a shipping method, not a + tax rate or promotion action). +- The new calculator instance's `preferences` attribute would have a value of + `{:preference=>10, :currency=>"USD"}`. + +## Attributes + +`Spree::Calculator` objects have the following attributes: + +- `type`: The type of calculator being used. For example, if the object + calculates shipping, it could be any available shipping calculator, such as + `Spree::Calculator::Shipping::FlatRate`. +- `calculable_type` and `calculable_id`: The calculable type and its matching + ID. For example, if the object calculates shipping, the calculable would be + from the `Spree::ShippingMethod` model. See [calculables](#calculables) for + more information. +- `preferences`: A hash of the calculator's preferences and the values of those + preferences. Each type of calculator has its own preferences. See + [preferences](#preferences) for more information. + +## Calculables + +A calculable is an object that can be calculated (by a `Spree::Calculator`). +The following classes are each a different `calculable_type`: + +- `Spree::ShippingMethod` +- `Spree::TaxRate` +- `Spree::PromotionAction` + +A calculable `include`s the `Spree::CalculatedAdjustments` module. This module +requires that each calculable has one calculator object. So, for each calculable +object, an instance of a `Spree::Calculator` should also be created. + +For example, a shipping method called "USPS Ground" charges a flat rate of $10 +USD. The shipping method is calculable and requires an associated calculator. +So, the rate for each shipment is calculated by the associated +`Spree::Calculator::Shipping::FlatRate` object. + +Similarly, each tax rate in your store is calculable. So, instance of the +`Spree::Calculator::DefaultTax` calculator is created and calculates the amount +of tax that should be applied to line items, shipments, or orders. + +## Preferences + +Each `Spree::Calculator` has a `preferences` attribute. Its value is a hash that +stores the preferences for that instance of the calculator. + +For example, you may have two `Spree::Calculator::Shipping::FlatRate` +calculators with different preferences: + +```ruby +Spree::Calculator::Shipping::FlatRate.find(1).preferences +# => {:amount=>8, :currency=>"USD"} + +Spree::Calculator::Shipping::FlatRate.find(2).preferences +# => {:amount=>4, :currency=>"EUR"} +``` + +Because each calculator has different functionality, each calculator has its own +set of preferences. For example, a calculator that uses a percentage for +calculations would not have a `:currency` preference, but any calculator that +uses a specific amount of currency would: + +```ruby +Spree::Calculator::Shipping::FlatRate.find(2).preferences +# => {:amount=>4, :currency=>"EUR"} + +Spree::Calculators::Shipping::FlatPercentItemTotal.find(3).preferences +# => {:flat_percent=>0.2e1} +``` + + + +## Custom calculators + +If Solidus's built-in calculators are not sufficient for your store, you can +create your own custom calculators. Because promotion, shipping, and tax +calculators have different requirements, we have an article describing each type +of custom calculator you may want to build: + +- Custom promotions calculator [Note: work in progress] +- [Custom shipping calculators][custom-shipping-calculators] +- [Custom tax calculators][custom-tax-calculators] + +[custom-shipping-calculators]: ../shipments/custom-shipping-calculators.md +[custom-tax-calculators]: ../taxation/custom-tax-calculators.md From 7c32b0bcd012da72e9779b304451e251e0dd91ae Mon Sep 17 00:00:00 2001 From: Benjamin Willems Date: Wed, 17 Jan 2018 15:14:10 -0800 Subject: [PATCH 2/6] Rename and tweak custom tax calculator article --- ...om-tax-calculator.md => custom-tax-calculators.md} | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) rename guides/taxation/{custom-tax-calculator.md => custom-tax-calculators.md} (77%) diff --git a/guides/taxation/custom-tax-calculator.md b/guides/taxation/custom-tax-calculators.md similarity index 77% rename from guides/taxation/custom-tax-calculator.md rename to guides/taxation/custom-tax-calculators.md index d98c81cdb7f..9403bfd08d4 100644 --- a/guides/taxation/custom-tax-calculator.md +++ b/guides/taxation/custom-tax-calculators.md @@ -1,4 +1,4 @@ -# Custom tax calculator +# Custom tax calculators *Note that Solidus supports value-added tax (VAT) and sales tax out of the box. You would only need to create a custom tax calculator in extraordinary @@ -8,12 +8,9 @@ By default, Solidus uses a simple tax rate calculator. It multiples against an item price and adjusts for any promotions to determine tax. However, this tax calculator can be changed if you need to develop a more specialized tax calculator for your application. - -Every `Spree::TaxRate` you create will be connected to a `Spree::Calculator` -instance that calculates the correct tax amount for a given shipment or line -item. In most cases, you should be able to use the -`Spree::Calculator::DefaultTax` calculator. It is suitable for both sales tax -and VAT scenarios. + +But in most cases, you should be able to use the `Spree::Calculator::DefaultTax` +calculator. It is suitable for both sales tax and VAT scenarios. If you need to change the default tax calculation behavior, see the [default tax calculator specs][default-tax-calculator-spec] or [its From bda11f9aa72ebe5fa9bab67c88d70940fbccb58a Mon Sep 17 00:00:00 2001 From: Benjamin Willems Date: Wed, 17 Jan 2018 15:14:21 -0800 Subject: [PATCH 3/6] Add detail to custom shipping calculator article --- .../shipments/custom-shipping-calculators.md | 106 +++++++++++++++++- 1 file changed, 103 insertions(+), 3 deletions(-) diff --git a/guides/shipments/custom-shipping-calculators.md b/guides/shipments/custom-shipping-calculators.md index ca88290c466..cbff6653026 100644 --- a/guides/shipments/custom-shipping-calculators.md +++ b/guides/shipments/custom-shipping-calculators.md @@ -50,15 +50,115 @@ Typically, a calculator uses the following order information: 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][flat-rate-source]. For a more complicated -example of what is possible with custom calculators, see the -[`solidus_active_shipping` base calculator][base-calculator-source]. This +Solidus's [stock flat rate calculator][flat-rate-source]. + +For a more complicated example of what is possible with custom calculators, see +the [`solidus_active_shipping` base calculator][base-calculator-source]. This calculator collects enough information about an order to send to a carrier and get a rate quote back. [flat-rate-source]: https://github.com/solidusio/solidus/blob/master/core/app/models/spree/calculator/shipping/flat_rate.rb [base-calculator-source]: https://github.com/solidusio-contrib/solidus_active_shipping/blob/master/app/models/spree/calculator/shipping/active_shipping/base.rb +### Inherit from the `Spree::ShippingCalculator` class + +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: + +```shell +/app/models/my_store/calculator/shipping/custom_shipping_calculator.rb +``` + +Then, follow the pattern of Spree's built-in calculators and inherit from +`Spree::ShippingCalculator`: + +```ruby +module MyStore + class Calculator::Shipping::CustomShippingCalculator < Spree::ShippingCalculator + end +end +``` + +### Required methods + +Your custom shipping calculator requires at least two methods: + +1. A `self.description` method that provides a name for the custom calculator. +2. A `compute_package(package)` that provides the return value for a package + being shipped. + +For example: + +```ruby +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 `/config/application.rb` initializer: + +```ruby +# /config/application.rb +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 +``` + +## Calculator availability + +By default, shipping calculators are always available to be used by shipping +methods. This is because the `available?` method on the base +[`Spree::Calculator` class][calculator-class] returns `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: + +```ruby +module MyStore + class Calculator::Shipping::CustomShippingCalculator < Spree::ShippingCalculator + ... + + def available?(object) + object.currency == "USD" + end + end +end +``` + +For more information about availability and filtering shipping methods, see the +[Shipping method filters][shipping-method-filters] article. + +[calculator-class]: https://github.com/solidusio/solidus/blob/master/core/app/models/spree/calculator.rb +[shipping-method-filters]: shipping-method-filters.html + ## Use additional product information In addition to providing relevant information about shipping addresses and From 2bd4ef750f564826c4539eafc4408dc65373f2ac Mon Sep 17 00:00:00 2001 From: Benjamin Willems Date: Wed, 17 Jan 2018 15:13:13 -0800 Subject: [PATCH 4/6] Add overview documentation for Spree::Calculators --- guides/calculators/overview.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/guides/calculators/overview.md b/guides/calculators/overview.md index 9b48a9e2975..c64f27b58a8 100644 --- a/guides/calculators/overview.md +++ b/guides/calculators/overview.md @@ -84,6 +84,16 @@ Spree::Calculators::Shipping::FlatPercentItemTotal.find(3).preferences # => {:flat_percent=>0.2e1} ``` +### Preferred methods + +For each preference on a calculator, you can use a `preferred_` +method to get or set the value of the preference (where `` is the +name of the preference). For example + +```ruby +Spree::Calculator.find(1).update(preferred_amount: 20) +``` +