14.78. DD 78: Taxes#

14.78.1. Summary#

We’ve received various requests for the merchant backend to provide transaction reports for accountants. While not always stated explicitly, we believe this is largely also related to tax reporting. This document explains the plan for how we intend to deal with periodic reporting.

14.78.2. Motivation#

Making tax-reporting easy for merchants will lower the barrier for them to adopt GNU Taler. Furthermore, customers will often require receipts which state the specific tax amounts that were paid, so including tax information in digital receipts (and thus the Taler contracts) is important. The current situation where taxes are specified per-product is not great, as a merchant would have to update all products if a tax-percentage were to change, and also has to re-calculate the tax every time a product price changes.

14.78.3. Requirements#

  • Deal with the complexity of tax calculations across different jurisdictions. Sure, we may not cover all cases globally, but we should at least cover the most common scenarios. This likely includes different ways how taxes should be computed in terms of rounding, and computing taxes given prices in gross or net amounts.

  • Make it as easy as possible for the merchant to manage taxes. If possible, have some backend-wide defaults so that merchants do not have to enter common taxes that apply across the currency domain.

  • Ensure customers get correct tax receipts as part of their contracts.

  • Incorporate the tax data when informing the merchant about their transaction history, including showing which taxes applied to which purchases so that merchants can easily account for applicable taxes.

  • Treat donations and gifts as a special-cases as again special tax rules likely apply.

  • A single product may have multiple applicable taxes (say VAT and luxury tax).

  • A single order may contain multiple products (some with known tax rules and others without) and thus a mix of applicable taxes.

  • A merchant may need to override or adapt the tax details for each order, for example because reverse VAT rules may shift the responsibility to pay taxes to the buyer.

14.78.4. Proposed Solution#

  • Add a table with (0) tax serial number, (1) instance ID, (2) year, (3) tax name, (4) tax rate, (5) tax description, (6) I18n description, (7) rounding mode (up, down, nearest) and (8) rounding unit (amount). to track known tax rules. Unique should be “instance+year+name”.

  • When “rounding up” is used, round up from net to gross, but round down from gross to net. Similarly, when “rounding down” is used, round down from net to gross, but round up from gross to net. Finally, “round-to-nearest” implies rounding in the same way for both conversion directions, and rounding up from the exact mid-point between multiples of the rounding unit.

  • Add a new array of applicable taxes to each product, referencing the tax serial numbers.

  • Add a global taxes object to the order/contract terms which maps “year||tax name” to the rates, descriptions, and internationalized descriptions.

  • In addition to the “taxes” array on each product, also have a “taxes” array on each order, giving the total taxes actually applied for the specific order.

  • When creating orders, compute taxes from the product array if possible, but allow client to override the entire array.

  • When overriding, generally allow the client to simply only specify which taxes to apply while doing the calculations in the backend. But do allow a form where the client also does the calculations. The latter should be discouraged as it is likely more error-prone.

  • When generating the contract terms, append the tax details of applicable taxes (rates, descriptions) from the database to the contract. As usual, allow the client to define additional custom tax classes in the order.

  • Add new configuration sections “[taxes-$YEAR-$ID]” that specify common tax classes (name and description as string) and rates (floating point) that should be automatically provided to all instances. When creating a new instance, populate the tax table with these values. Add a command-line tool to add all configured taxes to all existing instances (for example, to update default taxes for the next year).

  • Expand the statistics to include total taxes applied by year and name for the various time intervals for paid orders.

  • Expand the statistics to add up the various brut amounts of products (or orders, given a per-order override) for which a tax was applied. Note that a tax counts as applied if it is listed in the “taxes” array, even if the tax rate is zero (for example, to ensure donations are also totaled up). If a given order or product has multiple taxes associated, the respective total is added to all of those tax classes. If an order consists of taxed products, the taxes for the order are added per product. If the taxes are overriden only for an entire order, the total of the entire order is added to the respective statistics and the individual products and their taxes are ignored (and not reproduced in the contract).

14.78.5. Test Plan#

  • Unit tests for the rounding functions.

  • Shell-script tests for the CRUD API on taxes and automatic import of tax classes from the configuration.

  • Shell-script tests to check tax calculations in created orders and to test statistics on taxes paid.

  • Manual tests for SPA.

  • Manual tests on PDF report generation.

  • Manual tests on rendering taxes in wallets.

14.78.6. Definition of Done#

  • Specification updated

  • Database updated

  • Merchant backend updated:

    • CRUD API for tax definitions

    • INI-based tax class importer

    • CRUD API update for product management

    • Order creation update

    • Statistics update on order paid

  • Merchant backend SPA updated:

    • CRUD for tax class definitions

    • CRUD for associating tax classes with products

    • Order creation with tax-class override (at least for the entire order, not necessarily per-product)

    • Statistics page rendering tax statistics

  • Wallets updated to render taxes (upon request, in detailed view on payment or from order history)

14.78.7. Alternatives#

Communism? Crypto-anarchy?

14.78.8. Drawbacks#

  • Quite a bit of extra complexity

14.78.9. Discussion / Q&A#

(This should be filled in with results from discussions on mailing lists / personal communication.)