-
-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[REF] sale_margin_tax: refactor for correct accounting
When accounting for margin tax sales, the purchase price and margin (that form the base for the tax lines) need to be split. This is because a different tax grid should be applied on both line. However, Odoo does not provide a way to split the base as it does to split the tax. Furthermore, adding a 'margin' line type does not work because the functions that apply the repartition lines etc are basically impossible to override (they do not provide any hook, and the arbitrary compute order would make any tentative very brittle). To avoid these difficulty, another line is created on a "margin" product (a service), so that both the purchase and the margin can be accounted as base lines. This provide the advantage that no further override of basic accounting functions are needed, and that the tax rate of the margin tax is always either the initial rate (say 21) or 0. The downside is that it makes so statistics harder. Since the margin line and the product lines are linked by a many2one, it is still possible to extract the relevant info, just a bit harder. This refactoring also merges the margin behaviour from invoice and sale into a mixin to avoid desync of the essentially duplicated code (if only both line/tax fields had the same name...). This solved a bug where an invoice would think to be margin-based but without finding a witness margin tax. Last, this now handles the case where the margin is negative, in which case no tax is due.
- Loading branch information
Showing
17 changed files
with
389 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<odoo noupdate="1"> | ||
<record id="product_margin" model="product.product"> | ||
<field name="name">Margin on secondhand sales</field> | ||
<field name="type">service</field> | ||
</record> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# Translation of Odoo Server. | ||
# This file contains the translation of the following modules: | ||
# * sale_margin_tax | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: Odoo Server 16.0+e\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"Last-Translator: \n" | ||
"Language-Team: \n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: \n" | ||
"Plural-Forms: \n" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,help:sale_margin_tax.field_account_tax__amount_type | ||
msgid "" | ||
"\n" | ||
" - Group of Taxes: The tax is a set of sub taxes.\n" | ||
" - Fixed: The tax amount stays the same whatever the price.\n" | ||
" - Percentage of Price: The tax amount is a % of the price:\n" | ||
" e.g 100 * (1 + 10%) = 110 (not price included)\n" | ||
" e.g 110 / (1 + 10%) = 100 (price included)\n" | ||
" - Percentage of Price Tax Included: The tax amount is a division of the price:\n" | ||
" e.g 180 / (1 - 10%) = 200 (not price included)\n" | ||
" e.g 200 * (1 - 10%) = 180 (price included)\n" | ||
" " | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_bank_statement_line__has_margin_taxes | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_move__has_margin_taxes | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_move_line__has_margin_taxes | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_payment__has_margin_taxes | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_sale_order__has_margin_taxes | ||
msgid "Has Margin Taxes" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model,name:sale_margin_tax.model_account_move | ||
msgid "Journal Entry" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model,name:sale_margin_tax.model_account_move_line | ||
msgid "Journal Item" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:account.tax,name:sale_margin_tax.tax_margin | ||
msgid "Margin 21%" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:account.tax,margin_mention:sale_margin_tax.tax_margin | ||
msgid "Margin EN mention" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:account.tax,margin_description_template:sale_margin_tax.tax_margin | ||
msgid "Margin Tax" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:account.tax,margin_name_template:sale_margin_tax.tax_margin | ||
msgid "Margin: {}%" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_tax__margin_mention | ||
msgid "Mention on invoice" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model,name:sale_margin_tax.model_sale_order | ||
msgid "Sales Order" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model,name:sale_margin_tax.model_sale_order_line | ||
msgid "Sales Order Line" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_move_line__price_subtotal_report | ||
msgid "Subtotal (Report)" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model,name:sale_margin_tax.model_account_tax | ||
msgid "Tax" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_tax__amount_type | ||
msgid "Tax Computation" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields.selection,name:sale_margin_tax.selection__account_tax__amount_type__margin | ||
msgid "Tax on margin" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_tax__margin_description_template | ||
msgid "Template used for the generated tax description" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,field_description:sale_margin_tax.field_account_tax__margin_name_template | ||
msgid "Template used for the generated tax names" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,help:sale_margin_tax.field_account_tax__margin_mention | ||
msgid "This mention will be automatically added to the invoice." | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,help:sale_margin_tax.field_account_tax__margin_description_template | ||
msgid "This name can accept the rate as parameter, e.g. use 'Margin: {:.2f}%'" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:ir.model.fields,help:sale_margin_tax.field_account_tax__margin_name_template | ||
msgid "This name must accept the rate as parameter, e.g. use 'Margin: {}%'" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#. odoo-python | ||
#: code:addons/sale_margin_tax/models/account_tax.py:0 | ||
#, python-format | ||
msgid "Untaxed Amount" | ||
msgstr "" | ||
|
||
#. module: sale_margin_tax | ||
#: model:account.tax.group,name:sale_margin_tax.tax_group_margin | ||
msgid "[Margin Tax]" | ||
msgstr "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from . import margin_mixin | ||
from . import account_tax | ||
from . import sale_order_line | ||
from . import sale_order | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Copyright 2023 len-foss/Financial Way | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
|
||
|
||
from odoo import api, fields, models | ||
|
||
|
||
class MarginLineMixin(models.AbstractModel): | ||
_name = "margin.line.mixin" | ||
_description = "Margin Line Mixin" | ||
|
||
has_margin_taxes = fields.Boolean(compute="_compute_has_margin_taxes") | ||
|
||
@api.model | ||
def _get_tax_field(self): | ||
return "tax_id" if self._name == "sale.order.line" else "tax_ids" | ||
|
||
@api.model | ||
def _get_margin_depends(self): | ||
tax_field = self._get_tax_field() | ||
return [tax_field + ".is_margin_tax"] | ||
|
||
def _get_line_taxes(self): | ||
tax_field = self._get_tax_field() | ||
return self[tax_field] | ||
|
||
def _get_margin_taxes(self): | ||
taxes = self._get_line_taxes() | ||
return taxes.filtered("is_margin_tax") | ||
|
||
@api.depends(lambda self: self._get_margin_depends()) | ||
def _compute_has_margin_taxes(self): | ||
for line in self: | ||
line.has_margin_taxes = line._get_margin_taxes() | ||
|
||
|
||
class MarginMixin(models.AbstractModel): | ||
_name = "margin.mixin" | ||
_description = "Margin Mixin" | ||
|
||
has_margin_taxes = fields.Boolean(compute="_compute_has_margin_taxes") | ||
|
||
@api.model | ||
def _get_margin_depends(self): | ||
line_field = self._get_lines_field() | ||
return [line_field + ".has_margin_taxes"] | ||
|
||
def _get_lines_field(self): | ||
return "order_line" if self._name == "sale.order" else "line_ids" | ||
|
||
def _get_lines(self): | ||
line_field = self._get_lines_field() | ||
return self[line_field] | ||
|
||
@api.depends(lambda self: self._get_margin_depends()) | ||
def _compute_has_margin_taxes(self): | ||
for record in self: | ||
lines = record._get_lines() | ||
record.has_margin_taxes = any(lines.mapped("has_margin_taxes")) | ||
|
||
def _get_margin_taxes(self): | ||
lines = self._get_lines() | ||
return lines._get_margin_taxes() | ||
|
||
def _get_margin_mention(self): | ||
margin_tax = self._get_margin_taxes()[0] | ||
margin_tax = margin_tax.with_context(lang=self.partner_id.lang) | ||
return margin_tax.margin_mention |
Oops, something went wrong.