[FIX] account : apply analytic rule on invoice

Steps:
- Create an Analytic Account AA
- Create an Analytic Default Rule : when Product P > AA
- Create a Quotation including P, confirm and invoice

Issue:
- AA is not set for the invoice line of P

Cause:
- AA is computed on the invoice line when the product is added,
	but it is recomputed afterward from cache, where it is None

Fix:
- Not allow it to be recomputed afterward.

opw-2714340

closes odoo/odoo#82639

X-original-commit: 34b7c834cb67e1dc1f3727f103489e084c4788bf
Signed-off-by: Onockx Audric (auon) <auon@odoo.com>
Signed-off-by: William André (wan) <wan@odoo.com>
This commit is contained in:
Audric Onockx (auon)
2022-01-17 15:00:45 +00:00
parent 54c5160264
commit acfeac68d5
3 changed files with 73 additions and 2 deletions
+2 -1
View File
@@ -598,10 +598,11 @@ class SaleOrderLine(models.Model):
'discount': self.discount,
'price_unit': self.price_unit,
'tax_ids': [(6, 0, self.tax_id.ids)],
'analytic_account_id': self.order_id.analytic_account_id.id,
'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)],
'sale_line_ids': [(4, self.id)],
}
if self.order_id.analytic_account_id:
res['analytic_account_id'] = self.order_id.analytic_account_id.id
if optional_values:
res.update(optional_values)
if self.display_type:
+70
View File
@@ -405,3 +405,73 @@ class TestSaleToInvoice(TestSaleCommon):
})
downpayment.create_invoices()
self.assertEqual(so_for_downpayment.invoice_ids[0].company_id.id, so_company_id, "The company of the downpayment invoice should be the same as the one from the SO")
def test_invoice_analytic_account_default(self):
""" Tests whether, when an analytic account rule is set and the so has no analytic account,
the default analytic acount is correctly computed in the invoice.
"""
analytic_account_default = self.env['account.analytic.account'].create({'name': 'default'})
self.env['account.analytic.default'].create({
'analytic_id': analytic_account_default.id,
'product_id': self.product_a.id,
})
so_form = Form(self.env['sale.order'])
so_form.partner_id = self.partner_a
with so_form.order_line.new() as sol:
sol.product_id = self.product_a
sol.product_uom_qty = 1
so = so_form.save()
so.action_confirm()
so._force_lines_to_invoice_policy_order()
so_context = {
'active_model': 'sale.order',
'active_ids': [so.id],
'active_id': so.id,
'default_journal_id': self.company_data['default_journal_sale'].id,
}
down_payment = self.env['sale.advance.payment.inv'].with_context(so_context).create({})
down_payment.create_invoices()
aml = self.env['account.move.line'].search([('move_id', 'in', so.invoice_ids.ids)])[0]
self.assertRecordValues(aml, [{'analytic_account_id': analytic_account_default.id}])
def test_invoice_analytic_account_so_not_default(self):
""" Tests whether, when an analytic account rule is set and the so has an analytic account,
the default analytic acount doesn't replace the one from the so in the invoice.
"""
analytic_account_default = self.env['account.analytic.account'].create({'name': 'default'})
analytic_account_so = self.env['account.analytic.account'].create({'name': 'so'})
self.env['account.analytic.default'].create({
'analytic_id': analytic_account_default.id,
'product_id': self.product_a.id,
})
so_form = Form(self.env['sale.order'])
so_form.partner_id = self.partner_a
so_form.analytic_account_id = analytic_account_so
with so_form.order_line.new() as sol:
sol.product_id = self.product_a
sol.product_uom_qty = 1
so = so_form.save()
so.action_confirm()
so._force_lines_to_invoice_policy_order()
so_context = {
'active_model': 'sale.order',
'active_ids': [so.id],
'active_id': so.id,
'default_journal_id': self.company_data['default_journal_sale'].id,
}
down_payment = self.env['sale.advance.payment.inv'].with_context(so_context).create({})
down_payment.create_invoices()
aml = self.env['account.move.line'].search([('move_id', 'in', so.invoice_ids.ids)])[0]
self.assertRecordValues(aml, [{'analytic_account_id': analytic_account_so.id}])
+1 -1
View File
@@ -357,7 +357,7 @@ class SaleOrderLine(models.Model):
to this sale order line, or the analytic account of the project which uses this sale order line, if it exists.
"""
values = super(SaleOrderLine, self)._prepare_invoice_line(**optional_values)
if not values['analytic_account_id']:
if not values.get('analytic_account_id'):
if self.task_id.analytic_account_id:
values['analytic_account_id'] = self.task_id._get_task_analytic_account_id().id
elif self.project_id.analytic_account_id: