Add or Replace a Pricing Calculator
In this article, you'll learn how to extend the pricing logic in Workarea to fit the needs of your application, by generating and configuring its pricing calculators. Workarea's pricing system is constructed in such a way that it is possible to replace, rather than decorate, the way by which pricing is calculated on items and products. This includes adding pricing calculators for adjusting price, removing pricing calculators to omit certain price adjustments, and replacing out-of-box pricing calculators with your additional functionality.
But before diving into creating your own pricing calculators, let's have a look at the calculators Workarea provides for you out-of-the-box...
Four pricing calculators are included in Workarea, each addressing a different portion of the price which are added together to formulate the final grand total. They are as follows, and perform their pricing adjustments in the following order:
- Workarea::Pricing::Calculators::ItemCalculator sets the base unit price of the item. Override this to change the base item price, such as when working within segmentation.
- Workarea::Pricing::Calculators::CustomizationsCalculator adjusts the price based on whether any customizations to the item were set.
- Workarea::Pricing::Calculators::DiscountCalculator uses the discounts subsystem to apply discounts to the order. This should typically not be overridden or replaced. Instead, admins can create discounts that surpass the functionality of a simple pricing calculator.
- Workarea::Pricing::Calculators::TaxCalculator applies tax to the order using the built-in tax tables that are available in the database. These tax tables can be imported by the user in Avalara format, or created manually through the admin. This also does not typically need to be changed, since the default functionality is to not charge tax when there are no tax tables present for your locale.
Generating Pricing Calculators
To extend the functionality of pricing, new pricing calculators can be created in your Workarea application that are either entirely new, or replace an existing calculator to apply additional functionality. It's always recommended to add a new calculator somewhere in the chain, creating an additional PriceAdjustment
, and thus creating a "paper trail" of price changes for each item in the order. This helps when debugging why items are priced in certain ways within the order, as well as when you need additional data from the pricing system for integrations (such as to an OMS).
To create a new calculator, use the workarea:pricing_calculator
generator:
$ rails generate workarea:pricing_calculator Tariff
This will create a file in your application at app/models/workarea/pricing/calculators/tariff_calculator.rb:
module Workarea
module Pricing
module Calculators
class TariffCalculator
include Calculator
def adjust
# TODO implement me
end
end
end
end
end
The generator will also create a corresponding test class in test/models/workarea/pricing/calculators/tariff_calculator_test.rb:
require 'test_helper'
module Workarea
module Pricing
module Calculators
class TariffCalculatorTest < TestCase
def test_adjust
# TODO assert that the calculator adds price adjustments
end
end
end
end
end
In this test class, you can use TariffCalculator.test_adjust(order, shipping)
to simulate a pricing adjustment on the order without necessarily having to perform a Pricing::Request
. Create a Workarea::Order
(and optionally a Workarea::Shipping
) that will have tariffs charged on it, as well as one that shouldn't have tariffs charged, in order to ensure your new functionality works. Here's an example of how you might do that:
require 'test_helper'
module Workarea
module Pricing
module Calculators
class TariffCalculatorTest < TestCase
def test_adjust
order = create_order
order.add_item(product_id: 'PRODUCT', sku: 'SKU', quantity: 1)
TariffCalculator.test_adjust(order)
adjustment = order.items.first.price_adjustments.last
refute_nil(adjustment)
assert_equal('item', adjustment.price)
assert_equal(10.to_m, adjustment.amount)
end
end
end
end
end
To make this example test pass, implement the #adjust
method on your calculator:
def adjust
order.items.each do |item|
next unless shipping.charges_tariff?
item.adjust_pricing(
price: 'tax',
amount: shipping.address.tariff.amount,
quantity: item.quantity,
calculator: self.class.name,
description: 'A Very Draconian Tariff',
data: { 'tariff_id' => shipping.address.tariff.id }
)
end
end
Configuring Pricing Calculators
Now that you made a new pricing calculator, it must be added to your application's pricing_calculators
configuration in order to take effect. This configuration setting is a Workarea::SwappableList
.
In most cases, it's best to add your calculator somewhere in the list, typically after the default calculator for the price type. In the case of the previously-generated TariffCalculator
, which makes a tax price adjustment, here's an example of adding the calculator before tax is calculated on the item:
Workarea.configure do |config|
# Charge tariff in addition to tax on some orders
config.pricing_calculators.insert_before(
'Workarea::Pricing::Calculators::TaxCalculator',
'Workarea::Pricing::Calculators::TariffCalculator'
)
end
Situations may also arise where you need pricing to be calculated in a special way adjacent to the existing pricing infrastructure. For this scenario, add your new calculator to the end of the list:
Workarea.configure do |config|
# Charge tariff after shipping/tax/customizations
config.pricing_calculators.push('Workarea::Pricing::Calculators::TariffCalculator')
end
In rare cases, you may need to wholly replace the existing calculator. This is generally not necessary, and can cause compatibility issues if other plugins leveraging the pricing system are expecting the out-of-box calculator to work a certain way. However, if you want to replace a calculator in the chain, use the #swap
method like so:
Workarea.configure do |config|
# Calculate interest on the order if necessary
config.pricing_calculators.swap(
'Workarea::Pricing::Calculators::TaxCalculator',
'Workarea::Pricing::Calculators::TariffCalculator'
)
end
Make sure you restart your server to see changes take effect.
NOTE: It's also possible to remove calculators from the config, but it is not advisable as doing so will cause issues in testing.
Help Us Improve this Doc
Was this helpful? Open a GitHub issue to report a problem with this doc, suggest an improvement, or otherwise provide feedback. Thanks!