[FIX] purchase: update analytic account on change of the line

Steps to reproduce:
- create two products
- create two analytic accounts
- create two new analytic rules by assigning an account to a product
- Create a new PO and select on of the product
- On the same line, change the product to the other one

Issue:
- The analytic account won't be updated

Cause:
Bypass of the `account_analytic_id` whenever there is already on defined

Solution:
For the `Sale` fix, I added the `line.state == 'draft'`.
The reason? Because the compute is triggered after confirmation of the order due to:
https://github.com/odoo/odoo/blob/14.0/addons/sale/models/sale.py#L931-L935
Therefore, the compute won't also be triggered after confirmation of the SO.

opw-2948950

closes odoo/odoo#99858

X-original-commit: 61604e18128c1cfd0e6d4e510852f780491d6e4e
Signed-off-by: William André (wan) <wan@odoo.com>
This commit is contained in:
Yolann Sabaux
2022-09-13 10:30:17 +02:00
parent 3c6060b7bb
commit 04a352ea76
4 changed files with 99 additions and 3 deletions
+2 -2
View File
@@ -1132,7 +1132,7 @@ class PurchaseOrderLine(models.Model):
@api.depends('product_id', 'date_order')
def _compute_account_analytic_id(self):
for rec in self:
if not rec.account_analytic_id:
if not rec.display_type:
default_analytic_account = rec.env['account.analytic.default'].sudo().account_get(
product_id=rec.product_id.id,
partner_id=rec.order_id.partner_id.id,
@@ -1145,7 +1145,7 @@ class PurchaseOrderLine(models.Model):
@api.depends('product_id', 'date_order')
def _compute_analytic_tag_ids(self):
for rec in self:
if not rec.analytic_tag_ids:
if not rec.display_type:
default_analytic_account = rec.env['account.analytic.default'].sudo().account_get(
product_id=rec.product_id.id,
partner_id=rec.order_id.partner_id.id,
@@ -343,6 +343,52 @@ class TestPurchaseToInvoice(AccountTestInvoicingCommon):
aml = self.env['account.move.line'].search([('purchase_line_id', '=', purchase_order.order_line.id)])
self.assertRecordValues(aml, [{'analytic_account_id': analytic_account_manual.id}])
def test_vendor_bill_analytic_account_product_change(self):
self.env.user.groups_id += self.env.ref('account.group_account_readonly')
self.env.user.groups_id += self.env.ref('analytic.group_analytic_accounting')
analytic_account_super = self.env['account.analytic.account'].create({'name': 'Super Account'})
analytic_account_great = self.env['account.analytic.account'].create({'name': 'Great Account'})
super_product = self.env['product.product'].create({'name': 'Super Product'})
great_product = self.env['product.product'].create({'name': 'Great Product'})
product_no_account = self.env['product.product'].create({'name': 'Product No Account'})
self.env['account.analytic.default'].create([
{
'analytic_id': analytic_account_super.id,
'product_id': super_product.id,
},
{
'analytic_id': analytic_account_great.id,
'product_id': great_product.id,
},
])
po_form = Form(self.env['purchase.order'].with_context(tracking_disable=True))
po_form.partner_id = self.env.ref('base.res_partner_1')
with po_form.order_line.new() as po_line_form:
po_line_form.name = super_product.name
po_line_form.product_id = super_product
purchase_order = po_form.save()
purchase_order_line = purchase_order.order_line
self.assertEqual(purchase_order_line.account_analytic_id.id, analytic_account_super.id, "The analytic account should be set to 'Super Account'")
purchase_order_line.write({'product_id': great_product.id})
self.assertEqual(purchase_order_line.account_analytic_id.id, analytic_account_great.id, "The analytic account should be set to 'Great Account'")
purchase_order_line.write({'product_id': product_no_account.id})
self.assertFalse(purchase_order_line.account_analytic_id.id, "The analytic account should not be set")
po_no_analytic_account = self.env['purchase.order'].create({
'partner_id': self.env.ref('base.res_partner_1').id,
})
pol_no_analytic_account = self.env['purchase.order.line'].create({
'name': super_product.name,
'product_id': super_product.id,
'order_id': po_no_analytic_account.id,
'account_analytic_id': False,
})
po_no_analytic_account.button_confirm()
self.assertFalse(pol_no_analytic_account.account_analytic_id.id, "The compute should not overwrite what the user has set.")
def test_sequence_invoice_lines_from_multiple_purchases(self):
"""Test if the invoice lines are sequenced by purchase order when creating an invoice
from multiple selected po's"""
+1 -1
View File
@@ -881,7 +881,7 @@ class SaleOrderLine(models.Model):
@api.depends('product_id', 'order_id.date_order', 'order_id.partner_id')
def _compute_analytic_tag_ids(self):
for line in self:
if not line.display_type and not line.analytic_tag_ids:
if not line.display_type and line.state == 'draft':
default_analytic_account = line.env['account.analytic.default'].sudo().account_get(
product_id=line.product_id.id,
partner_id=line.order_id.partner_id.id,
+50
View File
@@ -373,3 +373,53 @@ class TestSalesTeam(SaleCommon):
})
sale_order.user_id = self.user_not_in_team
self.assertEqual(sale_order.team_id.id, self.sale_team_2.id, 'Should not reset the team to default')
def test_sale_order_analytic_tag_change(self):
self.env.user.groups_id += self.env.ref('analytic.group_analytic_accounting')
self.env.user.groups_id += self.env.ref('analytic.group_analytic_tags')
analytic_account_super = self.env['account.analytic.account'].create({'name': 'Super Account'})
analytic_account_great = self.env['account.analytic.account'].create({'name': 'Great Account'})
analytic_tag_super = self.env['account.analytic.tag'].create({'name': 'Super Tag'})
analytic_tag_great = self.env['account.analytic.tag'].create({'name': 'Great Tag'})
super_product = self.env['product.product'].create({'name': 'Super Product'})
great_product = self.env['product.product'].create({'name': 'Great Product'})
product_no_account = self.env['product.product'].create({'name': 'Product No Account'})
self.env['account.analytic.default'].create([
{
'analytic_id': analytic_account_super.id,
'product_id': super_product.id,
'analytic_tag_ids': [analytic_tag_super.id],
},
{
'analytic_id': analytic_account_great.id,
'product_id': great_product.id,
'analytic_tag_ids': [analytic_tag_great.id],
},
])
sale_order = self.env['sale.order'].create({
'partner_id': self.env.ref('base.res_partner_1').id,
})
sol = self.env['sale.order.line'].create({
'name': super_product.name,
'product_id': super_product.id,
'order_id': sale_order.id,
})
self.assertEqual(sol.analytic_tag_ids.id, analytic_tag_super.id, "The analytic tag should be set to 'Super Tag'")
sol.write({'product_id': great_product.id})
self.assertEqual(sol.analytic_tag_ids.id, analytic_tag_great.id, "The analytic tag should be set to 'Great Tag'")
sol.write({'product_id': product_no_account.id})
self.assertFalse(sol.analytic_tag_ids.id, "The analytic account should not be set")
so_no_analytic_account = self.env['sale.order'].create({
'partner_id': self.env.ref('base.res_partner_1').id,
})
sol_no_analytic_account = self.env['sale.order.line'].create({
'name': super_product.name,
'product_id': super_product.id,
'order_id': so_no_analytic_account.id,
'analytic_tag_ids': False,
})
so_no_analytic_account.action_confirm()
self.assertFalse(sol_no_analytic_account.analytic_tag_ids.id, "The compute should not overwrite what the user has set.")