Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0][ADD] account_fiscal_product_rule #305

Closed

Conversation

chafique-delli
Copy link

No description provided.

@chafique-delli chafique-delli force-pushed the 14.0-ADD-account_fiscal_product_rule branch 4 times, most recently from 6c35545 to fbc3b99 Compare July 28, 2022 09:14
@chafique-delli
Copy link
Author

@sebastienbeau

@sebastienbeau sebastienbeau self-requested a review July 29, 2022 20:55
@chafique-delli chafique-delli force-pushed the 14.0-ADD-account_fiscal_product_rule branch 2 times, most recently from 620d6cd to 711492b Compare August 9, 2022 14:39
from odoo.tests.common import SavepointCase


class TestAccountFiscalProductRule(SavepointCase):
Copy link
Member

@sebastienbeau sebastienbeau Aug 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to reduce the setup, it will be better to re-use the existing setup class of odoo.
https://github.com/odoo/odoo/blob/657fd6653705255f319756cba6406cefed9649d4/addons/account/tests/common.py#L11

You can do

from odoo.addons.account.tests.common import AccountTestInvoicingCommon

Then for the test you can use

self.product_a
self.partner_b (that have the fiscal position a) : https://github.com/odoo/odoo/blob/657fd6653705255f319756cba6406cefed9649d4/addons/account/tests/common.py#L148
and you can use the method : init_invoice (with the partner_b and the product a : https://github.com/odoo/odoo/blob/657fd6653705255f319756cba6406cefed9649d4/addons/account/tests/common.py#L366)

Then in your setup you only need to create

For the test the aim is to test the impact of the fiscal_product_rule

So you should write 3 tests

def test_no_rule(self):
    invoice = self.init_invoice(partner=self.partner_b, products=self.product_a)
    # check the tax/account

def test_rule_on_categ(self):
    self.product.categ_id.fiscal_position_product_rule_ids = self.fiscal_product_rule
    invoice = self.init_invoice(partner=self.partner_b, products=self.product_a)
    # check the tax/account is the on define by the rule

def test_rule_on_product(self):
    self.product.fiscal_position_product_rule_ids = self.fiscal_product_rule
    invoice = self.init_invoice(partner=self.partner_b, products=self.product_a)
    # check the tax/account is the on define by the rule

With that solution you should reduce a lot the number of line of your test

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebastienbeau , modifications made on the tests following your comments.

@chafique-delli chafique-delli force-pushed the 14.0-ADD-account_fiscal_product_rule branch from 711492b to 62de0e1 Compare September 6, 2022 10:36
@chafique-delli chafique-delli force-pushed the 14.0-ADD-account_fiscal_product_rule branch from 62de0e1 to 36eb62b Compare September 6, 2022 11:02
self.env.context.get("product_id", False)
)
for fp in self:
fiscal_product_rules = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can rename rule instead of fiscal_product_rules

Suggested change
fiscal_product_rules = (
rule = (

Note we should have only one rule (see python constraint in product.py)

self.parent_id
and self.parent_id.get_matching_product_fiscal_rule(fiscal_pos)
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a python constraint to be sure to not put 2 account.fiscal.position.rule related to the same fiscal position

something like

def check_no_duplicate_fiscal_position(self):
    for record in self:
        fps = []
        for rule in record.fiscal_position_product_rule_ids:
            if rule.fiscal_position_id in fps:
                raise ValidationError(...)
            else:
                fps.append(rule.fiscal_position_id)

To avoid duplicated code for this constraint. You can create a mixin (fiscal.position.product.rule.owner) and put the code for the field definition "fiscal_position_product_rule_ids" and the constrainte

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • add the test that add 2 fiscal rule with the same fiscal position, it should raise an error (you can test only the product or the categ as the code is the same).

product = self.env["product.product"].browse(
self.env.context.get("product_id", False)
)
for fp in self:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/!\ BE CAREFUL /!\
When doing a loop for and inside this loop you use return, in most of the time you do something really wrong !

Because if somebody call with method with several record it will return after processing the first element.

In that case it do not produce a bug because we always call map_tax with only one fiscal position. But adding a loop for mean that you expect several and make harder to understand the code (and also will avoid to raise an error if somewhere the code use an ensure_one)

So remove the loop and use self direct as there is only one element

Comment on lines 44 to 57
if fiscal_product_rules:
res = self.env["account.tax"]
if (
taxes[0].type_tax_use == "sale"
and fiscal_product_rules[0].seller_tax_ids
):
res = fiscal_product_rules[0].seller_tax_ids[0]
if (
taxes[0].type_tax_use == "purchase"
and fiscal_product_rules[0].supplier_tax_ids
):
res = fiscal_product_rules[0].supplier_tax_ids[0]
if res:
return res
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can write shorter/cleaner code

Something like

Suggested change
if fiscal_product_rules:
res = self.env["account.tax"]
if (
taxes[0].type_tax_use == "sale"
and fiscal_product_rules[0].seller_tax_ids
):
res = fiscal_product_rules[0].seller_tax_ids[0]
if (
taxes[0].type_tax_use == "purchase"
and fiscal_product_rules[0].supplier_tax_ids
):
res = fiscal_product_rules[0].supplier_tax_ids[0]
if res:
return res
if rule and taxes:
tax_use = taxes[0].type_tax_use
if tax_use == "sale" and rule.seller_tax_ids:
return rule.seller_tax_ids
elif tax_use == "purchase" and rule.supplier_tax_ids:
return rule.supplier_tax_ids

And please use if/elif and not only if

)

def map_tax(self, taxes, product=None, partner=None):
if product or self.env.context.get("product_id", False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just do

prod = product or self._context.get("product")

avoid to set in the variable "product" the value passed by the context, as if we call super we will inject the product and this may produce error (as odoo do not pass it)

Comment on lines 12 to 32
super()._onchange_product_id()
for line in self:
if not line.product_id or line.display_type in (
"line_section",
"line_note",
):
continue

taxes = line._get_computed_taxes()
if (
taxes
and line.move_id.fiscal_position_id.fiscal_position_product_rule_ids
):
taxes = line.move_id.fiscal_position_id.map_tax(
taxes, line.product_id, line.partner_id
)
line.tax_ids = taxes
line.product_uom_id = line._get_computed_uom()
line.price_unit = line.with_context(
product_id=line.product_id.id
)._get_computed_price_unit()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code is toooooo complex

just do this and the taxes will be the right one directly in the native code, we should avoid to call twice map taxes

Suggested change
super()._onchange_product_id()
for line in self:
if not line.product_id or line.display_type in (
"line_section",
"line_note",
):
continue
taxes = line._get_computed_taxes()
if (
taxes
and line.move_id.fiscal_position_id.fiscal_position_product_rule_ids
):
taxes = line.move_id.fiscal_position_id.map_tax(
taxes, line.product_id, line.partner_id
)
line.tax_ids = taxes
line.product_uom_id = line._get_computed_uom()
line.price_unit = line.with_context(
product_id=line.product_id.id
)._get_computed_price_unit()
for record in self:
super(
AccountMoveLine, record.with_context(product=line.product_id)
)._onchange_product_id()

/>
<field name="seller_tax_ids" widget="many2many_tags" />
<field name="supplier_tax_ids" widget="many2many_tags" />
<field name="account_income_id" optional="hide" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not make them optionnal, user will forget to fill it

@@ -0,0 +1,11 @@
<odoo>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not need a menu, we will fill it from the fiscal position

</field>
</record>

<record id="action_account_product_fiscal_rule" model="ir.actions.act_window">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not need action/menu, we will fill it from the fiscal position

string="Product Fiscal Rules",
)

def map_tax(self, taxes, product=None, partner=None):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the rule is not dependent anymore from the (product) source tax, what about price included or not?
I think you need to ensure the new tax has the same price_include state

@github-actions
Copy link

There hasn't been any activity on this pull request in the past 4 months, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 30 days.
If you want this PR to never become stale, please ask a PSC member to apply the "no stale" label.

@github-actions github-actions bot added the stale PR/Issue without recent activity, it'll be soon closed automatically. label Jan 29, 2023
@github-actions github-actions bot closed this Mar 5, 2023
@sebastienbeau sebastienbeau reopened this Nov 27, 2023
@sebastienbeau sebastienbeau removed the stale PR/Issue without recent activity, it'll be soon closed automatically. label Nov 27, 2023
Copy link

There hasn't been any activity on this pull request in the past 4 months, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 30 days.
If you want this PR to never become stale, please ask a PSC member to apply the "no stale" label.

@github-actions github-actions bot added the stale PR/Issue without recent activity, it'll be soon closed automatically. label Mar 31, 2024
@github-actions github-actions bot closed this May 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale PR/Issue without recent activity, it'll be soon closed automatically.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants