From b187e49cb98b46ffa4d37530ec2f880fb7a5d510 Mon Sep 17 00:00:00 2001 From: "Xavier BOL (xbo)" Date: Tue, 29 Mar 2022 09:59:29 +0200 Subject: [PATCH] [IMP] project_sale_expense: add action to see the expenses Before this commit, the expenses inscreasing the revenues or the costs in the project profitability are not visible for the user because he can just see the result and not which expenses are related to that result. This commit adds the action to see the expenses related to the revenues that is, all expenses reinvoiced to the customer for that project or the expenses related to the costs of the project. However, the user needs to have access to the expenses to access to the action, otherwise the name section is not clickable. task-2710808 --- addons/project_sale_expense/__init__.py | 1 + .../models/project_project.py | 21 +++++++++++++++++-- addons/project_sale_expense/tests/__init__.py | 4 ++++ .../tests/test_project_profitability.py | 14 ++++++------- 4 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 addons/project_sale_expense/tests/__init__.py diff --git a/addons/project_sale_expense/__init__.py b/addons/project_sale_expense/__init__.py index dc5e6b693d1..90b17558ffc 100644 --- a/addons/project_sale_expense/__init__.py +++ b/addons/project_sale_expense/__init__.py @@ -2,3 +2,4 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import models +from . import tests diff --git a/addons/project_sale_expense/models/project_project.py b/addons/project_sale_expense/models/project_project.py index cc4481055d3..04ee75323f0 100644 --- a/addons/project_sale_expense/models/project_project.py +++ b/addons/project_sale_expense/models/project_project.py @@ -1,33 +1,39 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import json + from odoo import models, _ class Project(models.Model): _inherit = 'project.project' - def _get_expenses_profitability_items(self): + def _get_expenses_profitability_items(self, with_action=True): if not self.analytic_account_id: return {} + can_see_expense = with_action and self.user_has_groups('hr_expense.group_hr_expense_team_approver') expenses_read_group = self.env['hr.expense'].sudo()._read_group( [ ('analytic_account_id', 'in', self.analytic_account_id.ids), ('is_refused', '=', False), ('state', 'in', ['approved', 'done']), ], - ['sale_order_id', 'product_id', 'untaxed_amount'], + ['sale_order_id', 'product_id', 'ids:array_agg(id)', 'untaxed_amount'], ['sale_order_id', 'product_id'], lazy=False, ) if not expenses_read_group: return {} expenses_per_so_id = {} + expense_ids = [] amount_billed = 0.0 for res in expenses_read_group: so_id = res['sale_order_id'] and res['sale_order_id'][0] product_id = res['product_id'] and res['product_id'][0] expenses_per_so_id.setdefault(so_id, {})[product_id] = res['ids'] + if can_see_expense: + expense_ids.extend(res['ids']) amount_billed += res['untaxed_amount'] sol_read_group = self.env['sale.order.line'].sudo()._read_group( [ @@ -64,4 +70,15 @@ class Project(models.Model): 'invoiced': total_amount_expense_invoiced, 'to_invoice': total_amount_expense_to_invoice, } + if can_see_expense: + def get_action(res_ids): + action = {'name': 'action_profitability_items', 'type': 'object', 'section': section_id, 'domain': json.dumps([('id', 'in', res_ids)])} + if len(res_ids) == 1: + action['res_id'] = res_ids[0] + return action + + if reinvoice_expense_ids: + expense_data['revenues']['action'] = get_action(reinvoice_expense_ids) + if expense_ids: + expense_data['costs']['action'] = get_action(expense_ids) return expense_data diff --git a/addons/project_sale_expense/tests/__init__.py b/addons/project_sale_expense/tests/__init__.py new file mode 100644 index 00000000000..4fa67e8be11 --- /dev/null +++ b/addons/project_sale_expense/tests/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import test_project_profitability diff --git a/addons/project_sale_expense/tests/test_project_profitability.py b/addons/project_sale_expense/tests/test_project_profitability.py index 2bd7fe074e4..828ad467700 100644 --- a/addons/project_sale_expense/tests/test_project_profitability.py +++ b/addons/project_sale_expense/tests/test_project_profitability.py @@ -26,7 +26,7 @@ class TestProjectSaleExpenseProfitability(TestProjectProfitabilityCommon, TestPr self.project, self.project_profitability_items_empty) - expense_profitability = self.project._get_expenses_profitability_items() + expense_profitability = self.project._get_expenses_profitability_items(False) self.assertDictEqual( expense_profitability.get('revenues', {}), @@ -56,7 +56,7 @@ class TestProjectSaleExpenseProfitability(TestProjectProfitabilityCommon, TestPr ]) expense_sol = self.sale_order.order_line.filtered(lambda sol: sol.product_id == self.company_data['product_order_sales_price']) - expense_profitability = self.project._get_expenses_profitability_items() + expense_profitability = self.project._get_expenses_profitability_items(False) self.assertDictEqual( expense_profitability.get('revenues', {}), {'id': 'expenses', 'invoiced': 0.0, 'to_invoice': expense_sol.untaxed_amount_to_invoice}, @@ -67,7 +67,7 @@ class TestProjectSaleExpenseProfitability(TestProjectProfitabilityCommon, TestPr ) self.assertDictEqual( - self.project._get_profitability_items(), + self.project._get_profitability_items(False), { 'revenues': { 'data': [expense_profitability['revenues']], @@ -89,7 +89,7 @@ class TestProjectSaleExpenseProfitability(TestProjectProfitabilityCommon, TestPr })._create_invoices(self.sale_order) invoice.action_post() - expense_profitability = self.project._get_expenses_profitability_items() + expense_profitability = self.project._get_expenses_profitability_items(False) self.assertDictEqual( expense_profitability.get('revenues', {}), {'id': 'expenses', 'invoiced': expense_sol.untaxed_amount_invoiced, 'to_invoice': 0.0}, @@ -98,14 +98,14 @@ class TestProjectSaleExpenseProfitability(TestProjectProfitabilityCommon, TestPr credit_note = invoice._reverse_moves() credit_note.action_post() - expense_profitability = self.project._get_expenses_profitability_items() + expense_profitability = self.project._get_expenses_profitability_items(False) self.assertDictEqual( expense_profitability.get('revenues', {}), {'id': 'expenses', 'invoiced': 0.0, 'to_invoice': expense_sol.untaxed_amount_to_invoice}, ) self.sale_order.action_cancel() - expense_profitability = self.project._get_expenses_profitability_items() + expense_profitability = self.project._get_expenses_profitability_items(False) self.assertDictEqual( expense_profitability.get('revenues', {}), {}, @@ -116,7 +116,7 @@ class TestProjectSaleExpenseProfitability(TestProjectProfitabilityCommon, TestPr ) expense_sheet.refuse_sheet('Test Cancel Expense') - expense_profitability = self.project._get_expenses_profitability_items() + expense_profitability = self.project._get_expenses_profitability_items(False) self.assertDictEqual( expense_profitability.get('revenues', {}), {},