From 03d7e0eb189b55121696780258e19aa6ee0a6f3d Mon Sep 17 00:00:00 2001 From: sbel-odoo Date: Wed, 14 Feb 2024 11:08:03 +0000 Subject: [PATCH] [FIX] sale_expense: compute expense policy for expense products MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, an analytic account is created when confirming a quotation for a product created as follow: 1. Enable `Can be Expensed` 2. Select `At cost` for Re-invoice expenses 3. Disable `Can be expensed` Steps to reproduce: ------------------- * Install **sale_management** and **hr_expense** * Go to **Settings** * Under `Customer Invoices`, enable `Intrastat` -> Save * Under `Analytics`, enable `Analytic Accounting` * Go to **Sales** * Create 3 products * Product 1: Default * Product 2: * Enable `Can be Expensed` * Select `At cost` for Re-invoice expenses * Product 3: * Enable `Can be Expensed` * Select `At cost` for Re-invoice expenses * Disable `Can be expensed` * For each product, repeat: * Create a quotation, select a customer * Add the product * Confirm * Select tab `Other Info` * Check the analytic account **Observations:** * Product 1: No analytic account created * Product 2: Analytic account created * Product 3: Analytic account created Why the fix: ------------ The creation of the analytic account depends on the value of `expense_policy`. When the value is `no`, no analytic account is created. Whereas when the value is `cost`, an analytic account is created. https://github.com/odoo/odoo/blob/57ad9c05014ca0219d7892c1ff8a2e949fab3c49/addons/sale/models/sale_order.py#L853-L856 In this workflow, `expense_policy` is visible only when `Can be expensed` is enabled. If you select an `expense_policy` then disable `Can be expensed`, the value for the `expense_policy` stays as previously selected. https://github.com/odoo/odoo/blob/3e320ffe0ff4d1c6bb7d0314f36dd13ad1cf23f4/addons/sale_expense/models/product_template.py#L33-L41 opw-3706305 closes odoo/odoo#159084 X-original-commit: 4b8e0559248d75ef27f47903041e5cca2059fa80 Signed-off-by: de Wouters de Bouchout Jean-BenoƮt (jbw) Signed-off-by: Sarah Bellefroid (sbel) --- .../sale_expense/models/product_template.py | 5 ++++ .../sale_expense/tests/test_sale_expense.py | 23 ++++++++++++++++++- addons/sale_timesheet/tests/test_reinvoice.py | 4 +++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/addons/sale_expense/models/product_template.py b/addons/sale_expense/models/product_template.py index 686dc7e7be5..54a5058e8d1 100644 --- a/addons/sale_expense/models/product_template.py +++ b/addons/sale_expense/models/product_template.py @@ -39,3 +39,8 @@ class ProductTemplate(models.Model): for product_template in expense_products: if not product_template.visible_expense_policy: product_template.visible_expense_policy = visibility + + @api.depends('can_be_expensed') + def _compute_expense_policy(self): + super()._compute_expense_policy() + self.filtered(lambda t: not t.can_be_expensed).expense_policy = 'no' diff --git a/addons/sale_expense/tests/test_sale_expense.py b/addons/sale_expense/tests/test_sale_expense.py index 4081e7baef6..04b78bb31d5 100644 --- a/addons/sale_expense/tests/test_sale_expense.py +++ b/addons/sale_expense/tests/test_sale_expense.py @@ -2,7 +2,7 @@ from odoo import Command, fields from odoo.addons.hr_expense.tests.common import TestExpenseCommon from odoo.addons.sale.tests.common import TestSaleCommon -from odoo.tests import tagged +from odoo.tests import Form, tagged @tagged('post_install', '-at_install') @@ -149,3 +149,24 @@ class TestSaleExpense(TestExpenseCommon, TestSaleCommon): expense_sheet.action_sheet_move_create() self.assertTrue(self.env['account.move'].search([('expense_sheet_id', '=', expense_sheet.id)], limit=1)) + + def test_analytic_account_expense_policy(self): + with Form(self.product_a.product_tmpl_id) as product_form: + product_form.can_be_expensed = True + product_form.expense_policy = 'cost' + product_form.can_be_expensed = False + + self.product_a.product_tmpl_id = product_form.save() + + so = self.env['sale.order'].create({ + 'partner_id': self.partner_a.id, + 'order_line': [(0, 0, { + 'name': self.product_a.name, + 'product_id': self.product_a.id, + 'product_uom_qty': 2, + 'product_uom': self.product_a.uom_id.id, + 'price_unit': self.product_a.list_price, + })], + }) + so.action_confirm() + self.assertFalse(so.analytic_account_id) diff --git a/addons/sale_timesheet/tests/test_reinvoice.py b/addons/sale_timesheet/tests/test_reinvoice.py index 30449c6fb97..e33fb6b2fa7 100644 --- a/addons/sale_timesheet/tests/test_reinvoice.py +++ b/addons/sale_timesheet/tests/test_reinvoice.py @@ -21,11 +21,13 @@ class TestReInvoice(TestCommonSaleTimesheet): 'service_type': 'timesheet', 'service_tracking': 'task_in_project' } + cls.company_data['product_order_no'].write(service_values) + service_values['expense_policy'] = 'cost' cls.company_data['product_order_cost'].write(service_values) cls.company_data['product_delivery_cost'].write(service_values) + service_values['expense_policy'] = 'sales_price' cls.company_data['product_order_sales_price'].write(service_values) cls.company_data['product_delivery_sales_price'].write(service_values) - cls.company_data['product_order_no'].write(service_values) # create AA, SO and invoices cls.analytic_plan = cls.env['account.analytic.plan'].create({