diff --git a/guides/pricing_and_taxation.md b/guides/pricing_and_taxation.md deleted file mode 100644 index b409e00051a..00000000000 --- a/guides/pricing_and_taxation.md +++ /dev/null @@ -1,137 +0,0 @@ -# Pricing and Taxation - -Taxation and prices are two intertwined topics in Solidus, mainly because a large number of jurisdictions in the world use VAT-style taxation, which influences the price at which an item is sold. - -## Taxation - -Solidus represents taxes for an order's items by using `Spree::TaxCategory` and `Spree::TaxRate`. - -Tax rates are associated with a tax category and a zone. If an order's `tax_address` falls within a zone, that zone's tax rates will apply to all line items and shipments with respectively matching tax categories. - -### Sales tax vs. Value-Added Tax - -In eCommerce, the type of tax we care about is consumption tax. Consumption taxes can take the form of Sales tax or Value Added Tax (VAT). - -The Sales tax policies found in the USA are *additional* taxes. For Sales tax, item prices do not change when adding them to an order. Instead they are added on top of the item price just before calculating the order total. - -With Value-Added tax (VAT), as found most other parts of the world, the prices of products and line items need to be shown *including* the consumption tax. When a product is exported, the price of that product has to change: It will be lower, because there is no included tax anymore. - -Most taxes can be considered one of these two types. For instance, in Australia customers pay a Goods and Services Tax (GST). This is basically equivalent to VAT in Europe. See the example section at the bottom. - -*** -Sales tax within the United States can get exceptionally complex, with different states, counties and even cities having different taxation rates. If you are shipping interstate within the United States, we would strongly advise you to use the an external service so that you get correct tax rates. -*** - -### Tax Rates - -A tax rate consists of an (percentage) amount, a zone for which it is valid, a tax category for which it is used, and an Boolean indicating whether the tax rate represents a Value-Added Tax (VAT) or not. - -Solidus will calculate tax based on all matching tax rates for the order's tax address. It's also possible to have more than one applicable tax rate for a single zone. In order for a tax rate to apply to a particular product, that product must have a tax category that matches the tax category of the tax rate. - -To differentiate between VAT and Sales tax in Solidus, use the `included_in_price` boolean on the `Spree::TaxRate` model. If `included_in_price` is set to `true`, Solidus will assume VAT-style taxation for this tax rate, if it is set to `false`, it will assume Sales tax style taxation. - -### Tax Categories - -Products within Solidus can be linked to Tax Categories, which are then used to find the taxation rate for the products when they are purchased. One Tax Category can be set to being the default for the entire system, which means that if a product doesn't have a tax category set, then the default tax category would be used. - -Per default Solidus assumes that all products are without tax. Only if a product has a tax category set, or there is a global default tax category set, will products be taxed. The tax category is specific to taxation, and is normally never seen by the user so you could call it something generic like "Taxable Goods." If you wish to tax certain products at different rates, however, then you will want to choose something more descriptive (ex. "Clothing."). - -## Shipping vs. Billing Address - -Most tax jurisdictions base the tax on the shipping address of where the order is being shipped to. So in these cases the shipping address is used when determining the tax zone. Solidus does, however, allow you to use the billing address to determine the zone. - -To determine tax based on billing address instead of shipping address you will need to set the `Spree::Config[:tax_using_ship_address]` preference to `false`. - -### Calculators - -Every `Spree::TaxRate` has a `Spree::Calculator` that calculates the correct tax amount for a given shipment or line item. In most cases you should be able to use Solidus's `DefaultTax` calculator. It is suitable for both Sales tax and VAT scenarios. - -If you want or need to change the default tax calculation behavior, please have a look at the [Default Tax Calculator Specs](https://github.com/solidusio/solidus/blob/master/core/spec/models/spree/calculator/default_tax_spec.rb) or its [implementation](https://github.com/solidusio/solidus/blob/master/core/app/models/spree/calculator/default_tax.rb). - -### Order Taxation in Solidus - -When Solidus applies tax to an order, the following things happen: - -It iterates over all line items, selecting the tax rates matching the tax category of the line item's variant. For each of the tax rates, its percentage is multiplied with the line item's `amount` (`price * quantity - promotions`). That calculated amount will then be stored in a tax adjustment to the line item. - -Depending on whether the tax rates are `included_in_price`, Solidus will store the sum of tax adjustments in the line item's `included_tax_total` or `additional_tax_total` columns. - -The same procedure is executed on an orders shipments. - -Finally, the `included_tax_total` and `additional_tax_total` of all line items and shipments are summed up, and stored in the order's `included_tax_total` and `additional_tax_total`. The `included_tax_total` column does not affect the order's total, while the `additional_tax_total` does. - -Every time an order is changed (i.e. while proceeding the checkout), the taxation system will check whether any tax adjustments need to be changed and update all the taxation-relevant totals. - -*** -To best appreciate how Solidus' taxation system works, have a look at the [taxation integration specs](https://github.com/solidusio/solidus/blob/master/core/spec/models/spree/tax/taxation_integration_spec.rb). -*** - - -## Pricing - -In VAT-style jurisdictions prices have to be shown including the taxes to customers. That's even true for all index and product display pages as well as when items are added to the cart, not only during the check out. - -In order to comply with this requirement, you first need to configure your tax rates, tax categories, and zones, then update your products and variants with the "Rebuild VAT prices" checkbox checked. - -Solidus will then proceed to calculate the correct net price and create prices for all countries with `included_in_price` VAT rates. It will also generate a fallback "export" price, where the prices `country_iso` is `nil` (not set). New products will behave as if that checkbox is checked. You can adjust the prices in the "Prices" tab if you need to. - -Solidus can handle several prices for the same country, and will always select the most recently updated price. - -## Prices in the backend - -In the Solidus admin backend, prices will be displyes including any VATs valid for the country represented by the configuration value `Spree::Config.admin_vat_country_iso`. - -Admin users in a country with VAT expect backend prices to include their home country's VAT. For example, if your admins reside in Germany, you will want to set `Spree::Config.admin_vat_country_iso` to `"DE"`. The effect of this is that now all prices in the backend can be assumed to include German VAT rates. - -## Prices in the frontend - -When a customer first browses your store, we do not know which jurisdiction she lives in. We will, therefore, have to make an assumption about her whereabouts. This assumption is the `cart_tax_country_iso` property on the `Spree::Store` model - meaning that you can assume your customers to be from different countries depending on which store she browses. Remember the requirement to display the prices including VAT from above? This is how you comply to this. - -You can have more than one store. For example, two different stores for France and Germany (`my-shop.com/fr` and `my-shop.com/de`), where each store shows different prices to account for different VAT rates in either country. - -*** -You can customize Solidus' pricing behaviour by creating a custom `Spree::Config.variant_price_selector_class` along with a fitting `Spree::Config.pricing_options_class`. -See the [specifications](https://github.com/solidusio/solidus/blob/master/core/spec/models/spree/variant/price_selector_spec.rb) for the standard [Price Selector](https://github.com/solidusio/solidus/blob/master/core/app/models/spree/variant/price_selector.rb) as well as the [specifications](https://github.com/solidusio/solidus/blob/master/core/spec/models/spree/variant/pricing_options_spec.rb) for the standard [Pricing Options](https://github.com/solidusio/solidus/blob/master/core/app/models/spree/variant/pricing_options.rb) for inspiration. -*** - -## Examples - -### Sales Tax - -Let's say you need to charge 5% additional ("Sales") tax for all items that ship to New York and 6% on clothing items that ship to Pennsylvania. This will mean you need to construct two different zones: one zone containing just the state of New York and another zone consisting of the single state of Pennsylvania. You'll also need to create two tax categories ("All items" and "Clothing"), mark your products accordingly, and create a tax rate for "all items" in New York, and a tax rate for "clothing" in Pennsylvania. - -## Examples - -Let's take an example of a sales tax situation for the United States. Imagine that we have a zone that covers all of North America and that the zone is used for a tax rate which applies a 5% tax on products with the tax category of "Clothing". - -If the customer purchases a single clothing item for $17.99 and they live in the United States (which is within the North America zone we defined) they are required to pay sales tax. - -The sales tax calculation is $17.99 x 5% for a total tax of $0.8995, which is rounded up to two decimal places, to $0.90. This tax amount is then applied to the line item as an adjustment and added on top of the order total. - -If the quantity of the item is changed to 2, then the tax amount doubles: ($17.99 x 2) x 0.05 is $1.799, which is again rounded up to two decimal places, applying a tax adjustment of $1.80. - -Let's now assume that we have another product that's a coffee mug, which doesn't have the "Clothing" tax category applied to it. Let's also assume this product costs $13.99, and there's no default tax category set up for the system. Under these circumstances, the coffee mug will not be taxed when it's added to the order. - -### VAT-Style taxation - -Many jurisdictions have what is commonly referred to as a Value Added Tax (VAT). In these cases the tax is typically already included in the price. This means that no additional tax needs to be applied during checkout. - -When tax is included in the price adjustments do not affect the order total (unlike the sales tax case). Stores are, however, usually required to show the amount of tax the user paid. That's why Solidus lists all adjustments below the item total on the checkout summary page. - -Let's start by looking at an example where there is a 5% VAT on all products. We'll further assume that this tax should only apply to orders within the United Kingdom (UK). - -In the case where the order address is within the UK and we purchase a single clothing item for £17.99 we see an order total of £17.99. The tax rate adjustment applied is £17.99 x 5%, which is £0.8995, and that is rounded up to two decimal places, becoming £0.90. - -Now let's increase the quantity on the item from 1 to 2. The order total changes to £35.98 with a tax total of £1.799, which is again rounded up to now being £1.80. - -Next we'll add a different clothing item costing £19.99 to our order. Since both items are clothing and taxed at the same rate, they can be reduced to a single total, which means there's a single adjustment still applied to the order, calculated like this: (£17.99 + £19.99) x 0.05 = £1.899, rounded up to two decimal places: £1.90. - -Now let's assume an additional tax rate of 10% on a "Consumer Electronics" tax category. When we add a product with this tax category to our order with a price of £16.99, there will be a second adjustment added to the order, with a calculated total of £16.99 x 10%, which is £1.699. Rounded up, it's £1.70. - -### Different tax rates by tax category for the same zone - -Here's another scenario. You would like to charge 10% tax on all electronic items and 5% tax on everything else. This tax should apply to all countries in the European Union (EU). In this case you would construct just a single zone consisting of all the countries in the EU. To differentiate between "electronic" items and "other" items, use tax categories. Now setup two tax rates with the "EU" zone, and their respective tax categories. The fact that you want to charge two different rates depending on the type of good does not mean you need two zones. - -## Acknowledgements - -Parts of this guide were originally written as the [Spree guide on taxation](https://github.com/spree/spree-guides/blob/master/content/developer/core/taxation.md) with contributions by @danabrit, @radar, @gwagener and @brchristian. diff --git a/guides/taxation/custom-tax-calculator.md b/guides/taxation/custom-tax-calculator.md new file mode 100644 index 00000000000..d98c81cdb7f --- /dev/null +++ b/guides/taxation/custom-tax-calculator.md @@ -0,0 +1,32 @@ +# Custom tax calculator + +*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 +circumstances.* + +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. + +If you need to change the default tax calculation behavior, see the [default tax +calculator specs][default-tax-calculator-spec] or [its +implementation][default-tax-calculator]. + +[default-tax-calculator-spec]: https://github.com/solidusio/solidus/blob/master/core/spec/models/spree/calculator/default_tax_spec.rb +[default-tax-calculator]: https://github.com/solidusio/solidus/blob/master/core/app/models/spree/calculator/default_tax.rb + + diff --git a/guides/taxation/displaying-prices.md b/guides/taxation/displaying-prices.md new file mode 100644 index 00000000000..5afb12826f8 --- /dev/null +++ b/guides/taxation/displaying-prices.md @@ -0,0 +1,83 @@ +# Displaying prices + +Solidus allows you to display prices in a flexible way to comply with your local +tax regulations. + +For example, in most countries that use value-added taxes (VAT), prices in a +store's frontend need to include any taxes that will be charged to the customer. + +## Set up price display for value-added taxes (VAT) + +In order to comply with VAT-style tax regulations, you first need to set up the +tax rates, tax categories, and zones that your store will use in production. + +After you have set up and tested your store's tax configuration options, you can +update any of your existing products and variants with the "Rebuild VAT prices" +checkbox selected. + +Solidus can then proceed to calculate the correct consumer prices for each +country with `included_in_price` VAT rates. It also generates a fallback +"export" price, where the price's `country_iso` is `nil`. New products will +behave as if the "Rebuild VAT prices" checkbox were selected. + +If you update your tax configuration in the future, you will need to rebuild +your VAT prices again. + +Any product can have several prices for the same country. By default, Solidus +always uses the most recently updated price. + +## VAT is always included in backend prices + +In countries that use VAT, administrators expect backend prices to include their +country's VAT. + +If you use the `solidus_backend` gem for store administration, all your prices +are displayed including any valued-added tax (VAT) valid for the current +country. + +You can change the configured country represented in your admin using the Spree +`admin_vat_country_iso` configuration value. For example, if the store +administrator lives in Germany, you could change the configured value to the +ISO code for Germany: + +```ruby +Spree::Config.admin_vat_country_iso == "DE" +``` + +## Anticipate the customer's tax jurisdiction + +When a customer first browses your store, you may not know which tax +jurisdiction they live in. You can choose to make an assumption about your +customers's location using the `Spree::Store` model's `cart_tax_country_iso` +property. + +The `cart_tax_country_iso` property sets a default location for customers +depending on the store that they are browsing. For example, if you have both a +`us.store.com` and a `de.store.com` and the customer is browsing the +`us.store.com`, your customer is more likely to be in the United States. + +Using the `cart_tax_country_iso` property can help you comply with tax +jurisdictions where where it is required to display VAT as part of the price. + +Administrators can configure these values for a storefront using the "Default +currency" and "Tax Country for Empty Carts" settings on the **Settings -> +Store** page in the `solidus_backend` admin. + +Valued-added tax and price are intricately connected. If your store requires +custom tax and pricing logic, you can change Solidus's pricing behaviour by +creating a custom `Spree::Config.variant_price_selector_class` along with a +fitting `Spree::Config.pricing_options_class`. See the [`price_selector` +specifications][price-selector-spec] for the standard [price +selector][price-selector], as well as the [`pricing_options` +specifications][pricing-options-spec] for the standard [pricing +options][pricing-options] for more information. + + + +[pricing-options]: https://github.com/solidusio/solidus/blob/master/core/app/models/spree/variant/pricing_options.rb +[pricing-options-spec]: https://github.com/solidusio/solidus/blob/master/core/spec/models/spree/variant/pricing_options_spec.rb +[price-selector]: https://github.com/solidusio/solidus/blob/master/core/app/models/spree/variant/price_selector.rb +[price-selector-spec]: https://github.com/solidusio/solidus/blob/master/core/spec/models/spree/variant/price_selector_spec.rb diff --git a/guides/taxation/example-tax-setups.md b/guides/taxation/example-tax-setups.md new file mode 100644 index 00000000000..02c7f40d97f --- /dev/null +++ b/guides/taxation/example-tax-setups.md @@ -0,0 +1,74 @@ +# Example tax setups + +*The examples in this article are for illustrative purposes only. Always defer +to a tax professional before setting up taxation in a production environment.* + +Your store's tax setup may range from simple to complicated. This article +provides simplified examples for typical stores that need to comply with +value-added tax regulations, sales tax regulations, or both. + +## Sales tax + +Your U.S.-based company has [tax nexus][nexus-definition] in two states: New +York and Pennsylvania. You do not ship outside of these two states. Because of +this, you are required to charge different tax rates to anything shipped within +those states: + +- You are required to charge 5% tax on any item shipped to New York. +- You are required to charged 6% tax on any clothing item shipped to + Pennsylvania and 5% tax on non-clothing items. + +### Zones + +To simplify your taxation setup, you can create two zones: + +- **New York (NY)**: A state-based zone that contains only the state of New + York. +- **Pennsylvania (PA)**: A state-based zone that contains only the state of + Pennsylvania. + +### Tax categories + +In order to create your store's tax rates, you need to create two tax categories +for your products: + +- **Clothing**: All the clothing items that you sell should have this tax + category applied. +- **Other items**: Every non-clothing product on your store should have this tax + category applied. + +Note that if one of your products does not have either the "Clothing" or the +"Other items" tax category, any customer who buys that item would be charged no +tax on it. + +### Tax rates + +Now that you have your zones and tax categories set up, you can see what kind of +meaningful tax rates you could create for both New York and Pennsylvania: + +| Zone | Tax category | Tax rate | +|-------------------|--------------|----------| +| New York (NY) | Clothing | 5% | +| | Other items | 5% | +| Pennsylvania (PA) | Clothing | 6% | +| | Other items | 5% | + +Because there are only two distinct tax rates required (5% and 6%) you only need +to create two tax rates: + +| Tax rate | Zones | Tax categories | Tax rate | +|-------------------|--------|------------------–----|----------| +| PA Clothing | PA | Clothing | 6% | +| NY and PA General | NY, PA | Clothing; Other items | 5% | + +Provided your products have the correct tax categories added, your store now +complies with the Pennsylvania and New York tax regulations for the products +that you sell. + +[nexus-definition]: http://www.salestaxinstitute.com/Sales_Tax_FAQs/What_is_nexus + + diff --git a/guides/taxation/overview-of-taxation.md b/guides/taxation/overview-of-taxation.md new file mode 100644 index 00000000000..6bd7192bbd0 --- /dev/null +++ b/guides/taxation/overview-of-taxation.md @@ -0,0 +1,169 @@ +# Overview of taxation + +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 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](#order-taxation) section for an overview of the order +taxation process. + +## Tax categories + +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 + +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](#tax-addresses). + +## Tax addresses + +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: + +```ruby +Spree::Config[:tax_using_ship_address] = true +``` + +### Use `Spree::TaxLocation` as the tax address + +An order's `tax_address` can – through [duck typing][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 it is has a country. The other +address fields might be empty or raise errors. + + + +[duck-typing]: https://en.wikipedia.org/wiki/Duck_typing + +## Sales tax and value-added tax + +In ecommerce, [consumption tax][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)][vat]. + +[consumption-tax]: https://en.wikipedia.org/wiki/Consumption_tax +[vat]: value-added-tax.md + +### Tax in the United States + +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][avatax] or [Tax Cloud][tax-cloud] to automate your U.S. tax rates. +Solidus has extensions for both of these services: +[`solidus_avatax_certified`][solidus-avatax-certified] and +[`solidus_tax_cloud`][solidus-tax-cloud]. + +[avatax]: https://www.avalara.com/ +[tax-cloud]: https://taxcloud.net/ +[solidus-avatax-certified]: https://github.com/boomerdigital/solidus_avatax_certified +[solidus-tax-cloud]: https://github.com/solidusio-contrib/solidus_tax_cloud + +## Order taxation + +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][uk-vat-discounts] and for sales tax [as +outlined by the California State Board of Equalization][ca-tax-discounts]. + +1. Solidus iterates over all of the order's line items. It selects the + tax rates that match each item's tax category. +2. For each line item, the tax rate (a percentage value) is multiplied with the + item's `amount` value. (`price ✕ quantity ➖ promotions`.) +3. The calculated amounts are stored in a `Spree::Adjustment` object that is + associated with the order's ID. +4. The line item's `included_tax_total` or `additional_tax_total` are updated. + (If the `Spree::TaxRate`'s `included_in_price` value is set to `true`, + Solidus uses the `included_tax_total` column to store the sum of VAT-style + taxes. Otherwise, it uses the `additional_tax_total` to store the sum of + sales tax-style taxes.) +5. The same process is executed on the order's `Spree::Shipments`. +6. The sum of the `included_tax_total` and `additional_tax_total` on all line + items and shipments a stored in the order's `included_tax_total` and + `additional_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][taxation-spec] for more information on +Solidus's taxation system. + +[uk-vat-discounts]: https://www.gov.uk/vat-businesses/discounts-and-free-gifts#1 +[ca-tax-discounts]: http://www.boe.ca.gov/formspubs/pub113/ +[taxation-spec]: https://github.com/solidusio/solidus/blob/master/core/spec/models/spree/tax/taxation_integration_spec.rb diff --git a/guides/taxation/value-added-tax.md b/guides/taxation/value-added-tax.md new file mode 100644 index 00000000000..eb2c65add75 --- /dev/null +++ b/guides/taxation/value-added-tax.md @@ -0,0 +1,107 @@ +# Value-added tax (VAT) + +Many countries have what is referred to as a value-added tax (VAT). When a +country uses VAT, tax is included in the price of each item. This means that +no additional tax needs to be applied during checkout. However, most tax +jurisdictions still require stores to show the amount of VAT that the customer +paid. + +In the admin, the **Settings -> Taxes -> Tax Rates** page allows administrators +to create any tax rate. They can create VAT-style taxes by using the "Included +in price" checkbox. + +Solidus's `solidus_frontend` gem lists all of the VAT and other price +adjustments below the item total on the checkout summary page. + +## Calculating VAT + +When you set up products in Solidus, you can set the price to the exactly what +you want the customer to pay. Then, you can use your VAT-style tax rates to +allocate a percentage of the gross price to taxes. + +``` +consumer_price / (1 + tax_rate) = expected_revenue +consumer_price - expected_revenue = vat +``` + +Solidus's [Spree::Calculator::DefaultTax][default-tax-calculator] handles +sales tax and VAT. If a tax rate is VAT and should be included in the price, it +calculates all of the line items that share that tax rate on the order: + +``` +if rate.included_in_price + round_to_two_places(line_items_total - ( line_items_total / (1 + rate.amount) ) ) +... +end +``` + +[default-tax-calculator]: https://github.com/solidusio/solidus/blob/master/core/app/models/spree/calculator/default_tax.rb + +### VAT amounts are stored in `Spree::Adjustment`s + +Note that while VAT does not adjust an order's total, Solidus still creates +`Spree::Adjustment` objects to store tax amount. These objects have an +`included` value of `true` so that the tax is not added to the price. + +## Example order with multiple VAT rates + +In the following example, we will still refer to VAT as "adjustments", +since that is how Solidus stores the tax amounts. + +Our United Kingdom-based company is required to follow these tax regulations: + +- Items of clothing should be taxed at a 5% rate. +- Consumer electronics should be taxed at a 10% rate. +- We are required to display the VAT paid to the customer. + +If a customer orders a single clothing item: + +- A customer within the UK adds one £17.99 t-shirt to their order. +- The tax calculator calculates the VAT: `17.99 - (17.99 / (1 + 0.05)) = 0.86`. + +``` + £17.99 – 1 x T-shirt + £0.86 – Clothing tax (5%) + + £17.99 – TOTAL +``` + +If a customer adds a second clothing item to the order: + +- The customer adds a £19.99 t-shirt to the existing order. +- The total cost for the two items is £37.98. +- Because the order only includes clothing items, the included tax is calculated + as a single adjustment (5%). +- The tax calculator calculates the VAT: `37.98 - (37.98 / (1 + 0.05)) = 1.81`. + +``` + £17.99 – 1 x T-shirt + £19.99 – 1 x T-shirt + £1.81 – Clothing tax (5%) + + £37.98 – TOTAL +``` + +If a customer adds a consumer electronics product to the order: + +- The customer adds a £16.99 power adapter to the existing order. +- The total cost for the three items is £54.97. +- Because the order includes both clothing items and consumer electronics, the + tax must be calculated as two adjustments at two different tax rates. +- The tax calculator calculates the VAT for the clothing items: `37.98 - (37.98 + / (1 + 0.05)) = 1.81`. +- The tax calculator calculates the VAT for the consumer electronics item: + `16.99 - (16.99 / (1 + 0.10)) = 1.54`. + +We can now show the display the final included VAT in the price when the +UK-based customer arrives at the checkout summary page: + +``` + £17.99 – 1 x T-shirt + £19.99 – 1 x T-shirt + £16.99 – 1 x Power adapter + £1.81 – Clothing tax (5%) + £1.54 – Consumer electronics tax (10%) + + £54.97 – TOTAL +```