[IMP] sale_project: add action to get all SOLs related to revenues
Before this commit, the materials row displayed in the revenues of the project profitability in the right side panel shows only the result of all SOLs containing a material product. The user cannot see which SOLs give that result. This commit adds an action to see all SOLs related to that row. If the user has access to the Sales app then the name in that row (that is, 'Material') will be clickable to redirect the user to the view of SOLs found for that row. task-2710808
This commit is contained in:
committed by
Laurent Stukkens (LTU)
parent
b187e49cb9
commit
ca8aaa0a0d
@@ -105,6 +105,24 @@ class Project(models.Model):
|
||||
})
|
||||
return action_window
|
||||
|
||||
def action_profitability_items(self, section_name, domain=None, res_id=False):
|
||||
if section_name in ['service_revenues', 'other_revenues']:
|
||||
view_types = ['list', 'kanban', 'form']
|
||||
action = {
|
||||
'name': _('Sales Order Items'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'sale.order.line',
|
||||
'context': {'no_create': True},
|
||||
}
|
||||
if res_id:
|
||||
action['res_id'] = res_id
|
||||
view_types = ['form']
|
||||
else:
|
||||
action['domain'] = domain
|
||||
action['views'] = [(False, v) for v in view_types]
|
||||
return action
|
||||
return super().action_profitability_items(section_name, domain, res_id)
|
||||
|
||||
@api.depends('sale_order_id.invoice_status', 'tasks.sale_order_id.invoice_status')
|
||||
def _compute_has_any_so_with_nothing_to_invoice(self):
|
||||
"""Has any Sale Order whose invoice_status is set as No"""
|
||||
@@ -282,7 +300,7 @@ class Project(models.Model):
|
||||
'delivered_manual': 'service_revenues',
|
||||
}
|
||||
|
||||
def _get_revenues_items_from_sol(self):
|
||||
def _get_revenues_items_from_sol(self, with_action=True):
|
||||
sale_line_read_group = self.env['sale.order.line'].read_group(
|
||||
[
|
||||
('order_id', 'in', self._get_sale_orders().ids),
|
||||
@@ -292,9 +310,10 @@ class Project(models.Model):
|
||||
('state', 'in', ['sale', 'done']),
|
||||
'|', ('qty_to_invoice', '>', 0), ('qty_invoiced', '>', 0),
|
||||
],
|
||||
['product_id', 'untaxed_amount_to_invoice', 'untaxed_amount_invoiced'],
|
||||
['product_id', 'ids:array_agg(id)', 'untaxed_amount_to_invoice', 'untaxed_amount_invoiced'],
|
||||
['product_id'],
|
||||
)
|
||||
display_sol_action = with_action and len(self) == 1 and self.user_has_groups('sales_team.group_sale_salesman')
|
||||
revenues_dict = {}
|
||||
total_to_invoice = total_invoiced = 0.0
|
||||
if sale_line_read_group:
|
||||
@@ -328,14 +347,26 @@ class Project(models.Model):
|
||||
total_to_invoice += amount_to_invoice
|
||||
revenue['invoiced'] += amount_invoiced
|
||||
total_invoiced += amount_invoiced
|
||||
if display_sol_action and invoice_type in ['service_revenues', 'other_revenues']:
|
||||
revenue.setdefault('record_ids', []).extend(sol_ids)
|
||||
|
||||
if display_sol_action:
|
||||
section_name = 'other_revenues'
|
||||
other_revenues = revenues_dict.get(section_name, {})
|
||||
sol_ids = other_revenues.pop('record_ids', [])
|
||||
if sol_ids:
|
||||
action_params = {'name': 'action_profitability_items', 'type': 'object', 'section': section_name, 'domain': json.dumps(domain)}
|
||||
if len(sol_ids) == 1:
|
||||
action_params['res_id'] = sol_ids[0]
|
||||
other_revenues['action'] = action_params
|
||||
return {
|
||||
'data': [{'id': invoice_type, **vals} for invoice_type, vals in revenues_dict.items()],
|
||||
'total': {'to_invoice': total_to_invoice, 'invoiced': total_invoiced},
|
||||
}
|
||||
|
||||
def _get_profitability_items(self):
|
||||
profitability_items = super()._get_profitability_items()
|
||||
revenue_items_from_sol = self._get_revenues_items_from_sol()
|
||||
def _get_profitability_items(self, with_action=True):
|
||||
profitability_items = super()._get_profitability_items(with_action)
|
||||
revenue_items_from_sol = self._get_revenues_items_from_sol(with_action)
|
||||
revenues = profitability_items['revenues']
|
||||
revenues['data'] += revenue_items_from_sol['data']
|
||||
revenues['total']['to_invoice'] += revenue_items_from_sol['total']['to_invoice']
|
||||
|
||||
@@ -57,7 +57,7 @@ class TestSaleProjectProfitability(TestProjectProfitabilityCommon, TestSaleCommo
|
||||
def test_project_profitability(self):
|
||||
self.assertFalse(self.project.allow_billable, 'The project should be non billable.')
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(),
|
||||
self.project._get_profitability_items(False),
|
||||
self.project_profitability_items_empty,
|
||||
'No data for the project profitability should be found since the project is not billable, so no SOL is linked to the project.'
|
||||
)
|
||||
@@ -65,7 +65,7 @@ class TestSaleProjectProfitability(TestProjectProfitabilityCommon, TestSaleCommo
|
||||
self.assertTrue(self.project.allow_billable, 'The project should be billable.')
|
||||
self.project.sale_line_id = self.delivery_service_order_line
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(),
|
||||
self.project._get_profitability_items(False),
|
||||
self.project_profitability_items_empty,
|
||||
'No data for the project profitability should be found since no product is delivered in the SO linked.'
|
||||
)
|
||||
@@ -77,7 +77,7 @@ class TestSaleProjectProfitability(TestProjectProfitabilityCommon, TestSaleCommo
|
||||
['billable_manual', 'service_revenues'],
|
||||
'invoice_type="billable_manual" if sale_timesheet is installed otherwise it is equal to "service_revenues"')
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(),
|
||||
self.project._get_profitability_items(False),
|
||||
{
|
||||
'revenues': {
|
||||
'data': [
|
||||
@@ -122,7 +122,7 @@ class TestSaleProjectProfitability(TestProjectProfitabilityCommon, TestSaleCommo
|
||||
['billable_manual', 'service_revenues'],
|
||||
'invoice_type="billable_manual" if sale_timesheet is installed otherwise it is equal to "service_revenues"')
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(),
|
||||
self.project._get_profitability_items(False),
|
||||
{
|
||||
'revenues': {
|
||||
'data': [
|
||||
@@ -163,7 +163,7 @@ class TestSaleProjectProfitability(TestProjectProfitabilityCommon, TestSaleCommo
|
||||
['billable_manual', 'service_revenues'],
|
||||
'invoice_type="billable_manual" if sale_timesheet is installed otherwise it is equal to "service_revenues"')
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(),
|
||||
self.project._get_profitability_items(False),
|
||||
{
|
||||
'revenues': {
|
||||
'data': [
|
||||
@@ -197,7 +197,7 @@ class TestSaleProjectProfitability(TestProjectProfitabilityCommon, TestSaleCommo
|
||||
credit_notes = invoices._reverse_moves()
|
||||
credit_notes.action_post()
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(),
|
||||
self.project._get_profitability_items(False),
|
||||
{
|
||||
'revenues': {
|
||||
'data': [
|
||||
@@ -226,6 +226,6 @@ class TestSaleProjectProfitability(TestProjectProfitabilityCommon, TestSaleCommo
|
||||
|
||||
self.sale_order._action_cancel()
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(),
|
||||
self.project._get_profitability_items(False),
|
||||
self.project_profitability_items_empty,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user