[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
This commit is contained in:
Xavier BOL (xbo)
2022-04-01 15:33:00 +02:00
committed by Laurent Stukkens (LTU)
parent 5558d2a578
commit b187e49cb9
4 changed files with 31 additions and 9 deletions
+1
View File
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
from . import tests
@@ -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
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_project_profitability
@@ -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', {}),
{},