Solidus's taxation system supports both sales- and VAT-style taxes. You can use
tax rates, tax categories, and the built-in tax calculator to handle your
store's tax logic. Solidus uses the Spree::Adjustment
model to apply taxes to
orders. This way, there can be multiple tax adjustments applied to each order.
Using adjustments helps account for some of the complexities of tax, especially if a store sells internationally:
- Orders may include products with different tax categories or rates.
- Shipments may require special calculations if you are shipping to or from locations where there are specific taxation rules for shipments.
- Taxes may or may not be included in a product's price depending on a country's taxation rules.
Solidus uses the Spree::TaxCategory
and Spree::TaxRate
models to specify the
rules for how tax adjustments are calculated. Tax adjustments are created for
each line item in an order.
See the Order taxation section for an overview of the order taxation process.
Tax categories can be used to ensure particular products are taxed as required. For example, if your business is based in Minnesota, you need to charge tax on tech products but do not need to charge tax on clothing. You could set up two tax categories, Clothing and Tech which you would apply to products of either type.
By default, new products do not have a set tax category. Administrators can set the tax category while creating the product or set it later while editing the product.
Tax rates define the amount of tax that should be charged on items. You might configure different tax rates for different zones and tax categories, or even for specific dates. You could also create more complex tax rates with a custom tax calculator.
In Solidus, a tax rate consists of at least four values:
- The descriptive name for the tax rate. For example, "Minnesota Sales Tax" for a Minnesota state tax rate.
- The zone that the tax rate should apply to.
- The rate (in the form of a percentage of the price).
- The "Included in price" boolean. This indicates whether the tax is included in the price (for value-added taxes) or added to the price (U.S. taxes).
Solidus calculates tax based on the matching tax rate(s) for the order's tax address.
If an order's tax_address
falls within a specific zone, the tax rates that you
have configured would apply for all the line items and shipments in that zone
that have a matching tax category.
By default, the tax_address
used for orders is the customer's shipping
address. This is how most tax jurisdictions require taxes to be calculated.
However, you can configure your store to globally use customer billing
addresses instead in any initializer file inside the config/initializers/
directory:
Spree::Config[:tax_using_ship_address] = true
An order's tax_address
can – through duck typing – be a
Spree::TaxLocation
instead of the shipping address. The tax location is
computed from the store's Spree.config.cart_tax_country_iso
setting.
Note that you can only trust the tax address if it has a country. The other address fields might be empty or raise errors.
In ecommerce, consumption tax either takes the form of sales tax or value-added tax. Some countries use other names for their taxes, but generally all modern consumption taxes would be considered one of these two types.
Solidus's models support both types of taxes. In the case of a product or shipment:
- Sales tax is calculated as additional taxes on top of the listed price. (U.S.-style taxation.)
- Value-added tax (VAT) is calculated as included in the listed price. Solidus lists all VAT amounts below the item total on checkout summary pages. For more information about VAT, see Value-added tax (VAT).
Note that sales tax in the United States can get exceptionally complex. Each state, county, and municipality might have a different tax rate.
If you intend to ship products between states, and your store is based in the
United States, we recommend that you use an external service like
Avatax or Tax Cloud to automate your U.S. tax rates.
Solidus has extensions for both of these services:
solidus_avatax_certified
and
solidus_tax_cloud
.
Once the order has a tax_address
specified, tax can be calculated for all of
the line items and shipments associated with a Spree::Order
:
Note that any promotional adjustments are applied before tax adjustments. This is to comply with tax regulations for value-added taxation as outlined by the Government of the United Kingdom and for sales tax as outlined by the California State Board of Equalization.
- Solidus iterates over all of the order's line items. It selects the tax rates that match each item's tax category.
- For each line item, the tax rate (a percentage value) is multiplied with the
item's
amount
value. (price ✕ quantity ➖ promotions
.) - The calculated amounts are stored in a
Spree::Adjustment
object that is associated with the order's ID. - The line item's
included_tax_total
oradditional_tax_total
are updated. (If theSpree::TaxRate
'sincluded_in_price
value is set totrue
, Solidus uses theincluded_tax_total
column to store the sum of VAT-style taxes. Otherwise, it uses theadditional_tax_total
to store the sum of sales tax-style taxes.) - The same process is executed on the order's
Spree::Shipments
. - The sum of the
included_tax_total
andadditional_tax_total
on all line items and shipments a stored in the order'sincluded_tax_total
andadditional_tax_total
values.
The included_tax_total
column does not affect the order's total, while the
additional_tax_total
does.
Every time an order is changed, the taxation system checks whether tax adjustments need to be changed and updates all of the taxation-relevant totals.
See the taxation integration spec for more information on Solidus's taxation system.