078-taxes.rst (13205B)
1 DD 78: Taxes 2 ############ 3 4 :Design status: Accepted 5 :Implementation status: Partial 6 :DD shepherd: TBD 7 :Historical contributors: Christian Grothoff 8 :First published: 2025-12-22 9 :Last substantive change: 2025-12-26 10 :Implementation evidence: ``merchant`` (2025-12-27; 2025-12-28; 2025-12-29) implements the product-group and money-pot foundation; tax rules remain future work 11 :Normative references: ``core/api-merchant.rst`` (product groups, money pots, and upcoming ``vTAXES``) 12 13 Summary 14 ======= 15 16 We've received various requests for the merchant backend to provide 17 transaction reports for accountants. While not always stated explicitly, we 18 believe this is largely also related to tax reporting. This document explains 19 the plan for tax calculation and tax data; periodic report delivery is covered 20 by DD 79. 21 22 Motivation 23 ========== 24 25 Making tax-reporting easy for merchants will lower the barrier for them to 26 adopt GNU Taler. Furthermore, customers will often require receipts which 27 state the specific tax amounts that were paid, so including tax information in 28 digital receipts (and thus the Taler contracts) is important. The current 29 situation where taxes are specified per-product is not great, as a merchant 30 would have to update all products if a tax-percentage were to change, and also 31 has to re-calculate the tax every time a product price changes. 32 33 34 Requirements 35 ============ 36 37 * Deal with the complexity of tax calculations across different jurisdictions. 38 Sure, we may not cover all cases globally, but we should at least cover the 39 most common scenarios. This likely includes different ways how taxes 40 should be computed in terms of rounding, and computing taxes given 41 prices in gross or net amounts. 42 * Make it as easy as possible for the merchant to manage taxes. If possible, 43 have some backend-wide defaults so that merchants do not have to enter 44 common taxes that apply across the currency domain. 45 * Ensure customers get correct tax receipts as part of their contracts. 46 * Incorporate the tax data when informing the merchant about their transaction 47 history, including showing which taxes applied to which purchases so that 48 merchants can easily account for applicable taxes. 49 * Treat *donations* and *gifts* as a special-cases as again special tax 50 rules likely apply. 51 * A single product may have multiple applicable taxes (say VAT and luxury 52 tax). 53 * A single order may contain multiple products (some with known tax 54 rules and others without) and thus a mix of applicable taxes. 55 * A merchant may need to override or adapt the tax details for each 56 order, for example because reverse VAT rules may shift the responsibility 57 to pay taxes to the buyer. 58 59 60 Proposed Solution 61 ================= 62 63 We borrow ideas from ERPnext. 64 65 Phase 1: Products groups 66 ------------------------ 67 68 This is inspired by ERPnext's "item groups". 69 70 A **product group** allows multiple products to be treated in the 71 same way for accounting and tax purposes, avoiding the need to 72 configure each product individually. 73 74 There can only be one group per product, all products that are not explicitly 75 in a group should be in some ``__default__`` group that always exists. The 76 product groups will be used for sales statistics (revenue per group) and will 77 be the basis for associating taxes with products in the next phase(s). 78 79 Unlike categories, product group membership is mutually exclusive and not used 80 for the point-of-sale app display. Re-using categories would confuse a feature 81 for taxes/accounting with a feature for user-interfaces of sales people. 82 83 * Add a ``product_group`` table with: 84 85 (0) product group serial number 86 (1) instance ID (foreign key) 87 (2) product group name (unique with instance ID) 88 (3) product group description 89 90 * Expand ``inventory_products`` table with: 91 92 (1) product group serial number (foreign key), allow NULL for default 93 (2) price_is_net boolean flag to indicate if the given price is the net 94 price and all taxes should be added on top of it, or if it is a 95 fixed retail price and the merchant covers all applicable taxes, 96 at the expense of profits if taxes vary (for example, to preserve 97 the price structure even if taxes vary between dine-in and take-out). 98 99 100 Phase 2: Money pots 101 ------------------- 102 103 This is inspired by ERPnext's "accounts". 104 105 A **money pot** allow users aggregate amounts over time periods for accounting. 106 107 Money pots can be for different types of taxes, but also for tips or to 108 separate out different kinds of internal accounts as well as fees paid to the 109 exchange. 110 111 When an order is created, the total amount paid by the customer will be split 112 into the various money pots based on rules that can be given per product, 113 product group or taxes, and also later overriden explicitly in the contract 114 terms. 115 116 The increments to the various pots will also be shown in the various accounting 117 statistics. 118 119 * Add a ``money_pot`` table with: 120 121 (0) money pot serial number 122 (1) instance ID (foreign key) 123 (2) money pot name (unique with instance ID) 124 (3) money pot description 125 (4) money pot total amount 126 127 * Code should update statistics whenever the money pot 128 total amount is incremented. 129 130 131 132 Phase 3: Tax Class 133 ------------------ 134 135 This is inspired by ERPnext's "item tax templates". 136 137 A **tax class** specifies a possible tax and how it is to be calculated for a 138 given product or order. 139 140 * Add a ``tax_class`` table with: 141 142 (0) tax class serial number 143 (1) instance ID (foreign key) 144 (2) tax class name (unique with instance ID) 145 (3) tax rate (percentage), for taxes charged per value 146 (4) charge amount (multiplied with quantity of the product, 147 for example for tourist overnight tax per night, 148 for taxes charged per unit and not per value) 149 (5) tax description 150 (6) i18n description 151 (7) calculation mode (net total, cummulative) 152 (8) rounding mode (up, down, nearest) 153 (9) rounding unit (amount) 154 (10) money pot (where to accumulate taxes paid under this tax class). 155 to track known tax rules. 156 Unique should be "instance+tax class name". 157 158 * When "rounding up" is used, round up from net to gross, but round 159 down from gross to net. Similarly, when "rounding down" is used, 160 round down from net to gross, but round up from gross to net. 161 Finally, "round-to-nearest" implies rounding in the same way for 162 both conversion directions, and rounding up from the exact 163 mid-point between multiples of the rounding unit. 164 165 * When cummulative calculation is used, the order in which tax classes 166 are applied starts to matter. This will become important when defining 167 tax rules later. 168 169 * Orders can specify that a particular tax class and amount is to 170 be applied to specific products or to the entire order, 171 but not both. In this case, the backend adds the exact 172 amounts to the contract terms and the respective pot-statistics. 173 174 * Orders can specify that only a particular tax class is to be applied 175 to a product or the entire order, but without giving the tax amount. 176 In this case, the backend computes the applicable 177 tax and adds the exact amounts to the contract terms and the 178 respective pot-statistics. It is also possible that for some products 179 in the order the frontend calculated the exact amount, while for 180 others the calculation is left to the backend. 181 182 * When generating the contract terms, append the tax class details 183 of applicable taxes (rates, descriptions) from the database 184 to the contract. 185 186 * Allow the client to define and use additional custom tax classes 187 per order. 188 189 * Add new configuration sections "[taxes-$ID]" that specify common tax 190 classes (name and description as string) and rates (floating point) 191 and per-quantity charges (amount) with calculation and rounding mode 192 that should be automatically provided to all instances. When creating 193 a new instance, populate the tax class table with these values. Add a 194 command-line tool to add all configured taxes to all existing 195 instances (for example, to update default taxes for the next year). 196 197 * When an order is paid, make sure to add the tax totals to each 198 of the money pots. 199 200 * For tipping, specifying a "tax" ``tip-$STAFF`` with a custom amount can 201 thus be easily assigned to the tip money pot of ``$STAFF``. 202 203 Phase 4: Tax Rules 204 ------------------ 205 206 This is inspired by ERPnext's "tax rules". 207 208 A **tax rule** specifies whether a tax class applies to a particular 209 product, group of products, or order. 210 211 * There should be an optional ``__fallback__`` tax rule that is applied to all 212 orders and products that do not match a specific rule. 213 214 * Except for the ``__fallback__`` tax rule, it is possible that multiple 215 tax rules apply, in which case they *all* apply at the same time. 216 Only the "fallback" rule only applies if no other rules apply. 217 218 * Add a table "tax_rules" with 219 220 (0) tax rule serial number 221 (1) instance ID (foreign key) 222 (2) tax rule name (unique with instance ID), ``__fallback__`` is reserved 223 for the fallback rule 224 (3) tax class serial number (foreign key) 225 (4) filter: array of product group serial IDs, NULL for all, [] for none 226 (5) filter: array of product ID serial IDs, NULL for all, [] for none 227 (6) filter: total_only (boolean), true if the tax rule only applies to the 228 final total of the order, and not individual products; if total_only 229 is true, then the product and product group arrays MUST both be empty 230 231 In the future, we *may* want to expand this to add per-order filters, 232 like on the shipping address; however, for now we will limit the 233 filters to make this more implementable. 234 235 * Orders can specify an *array* of tax rules (by tax rule name) 236 to apply to each product or the entire order (depending on the 237 filter of the tax rule). In this case, the tax rules are applied 238 in the sequence specified in the array to compute which 239 tax classes to apply to each product or the entire order. 240 Tax rules must not be specified when an order already specifies 241 a tax class for the entire order. 242 243 * However, it is possible to specify tax classes for some products 244 and then tax rules would still apply for other products 245 or the entire order. But if a product in the order is specified 246 as having an explicit tax class, the order-wide product-specific 247 tax rules will no longer apply to it. Order-wide tax rules 248 on the order total would still be applied. 249 250 * If a tax rule is specified for an order but it does not 251 apply to the order or a product in it, the rule is simply 252 ignored. 253 254 255 256 Phase 5: Tax Regimes 257 -------------------- 258 259 This is inspired by ERPnext's "tax categories". 260 261 A **tax regime** determines which set of tax rules to apply in 262 which order (with cummulative taxes, the order may matter). 263 The idea here is that for some customers or transactions completely 264 different sets of rules may apply, but still the sets of rules 265 are frequently the same. 266 267 * There should be a "default" tax regime that is applied to all 268 orders where the client did not specify a tax regime. 269 Basically, not specified implies ``__default__``. However, if 270 a default tax regime is not configured, this is not an error 271 and simply no taxes are applied. 272 273 * Add a table "tax_regime" with 274 275 (0) tax regime serial number 276 (1) instance ID (foreign key) 277 (2) tax regime name (unique with instance ID), ``__default__`` is reserved 278 for the default regime 279 (3) array of applicable tax rules 280 281 * Orders can specify a tax regime instead of an array of 282 tax rules. In this case, the array of tax rules is simply 283 obtained from the tax regime. 284 285 * Orders that specify a tax regime must not also specify an 286 array of tax rules. 287 288 289 Test Plan 290 ========= 291 292 * Unit tests for the rounding functions. 293 * Shell-script tests for the CRUD API on taxes and automatic 294 import of tax classes from the configuration. 295 * Shell-script tests to check tax calculations in created orders 296 and to test statistics on taxes paid. 297 * Manual tests for SPA. 298 * Manual tests on PDF report generation. 299 * Manual tests on rendering taxes in wallets. 300 301 302 Definition of Done 303 ================== 304 305 The product-group and money-pot foundation has landed. The tax protocol is 306 still listed as upcoming, so the tax-specific items below remain incomplete. 307 308 * [ ] Specification promoted from upcoming to current 309 * [ ] Database updated with tax definitions 310 * [ ] Merchant backend updated: 311 312 * CRUD API for tax definitions 313 * INI-based tax class importer 314 * CRUD API update for product management 315 * Order creation update 316 * Statistics update on order paid 317 318 * [ ] Merchant backend SPA updated: 319 320 * CRUD for tax class definitions 321 * CRUD for associating tax classes with products 322 * Order creation with tax-class override (at least for the entire order, 323 not necessarily per-product) 324 * Statistics page rendering tax statistics 325 326 * [ ] Wallets updated to render taxes (upon request, in detailed view 327 on payment or from order history) 328 329 330 Alternatives 331 ============ 332 333 Communism? Crypto-anarchy? 334 335 336 Drawbacks 337 ========= 338 339 * Quite a bit of extra complexity 340 341 342 Discussion / Q&A 343 ================ 344 345 (This should be filled in with results from discussions on mailing lists / personal communication.)