[IMP] project : gantt view improvements

Before this commit, the group by in the gantt view of project didn't
allow the user to find records for which there were not scheduled tasks.
For example, if a Sale Order didn't have a scheduled task, when grouping
by Sale Order, the latter was not displayed. And searching for its name
was not displaying it either.

After this commit, when a user is searching for a sale order, even if
the latter does not have any scheduled task, it is displayed in order to
facilitate the scheduling of new tasks.

In order to do so, a group expand on sale_order_id for the project.task
model have been introduced.

closes odoo/odoo#121819

Taskid: 3251630
Related: odoo/enterprise#41257
Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
This commit is contained in:
luve-odoo
2023-09-06 14:42:14 +00:00
parent 66a9262009
commit e96fc7d3fe
4 changed files with 50 additions and 4 deletions
+34
View File
@@ -12,6 +12,7 @@ from odoo.addons.web_editor.controllers.main import handle_history_divergence
from odoo.exceptions import UserError, ValidationError, AccessError
from odoo.osv import expression
from odoo.tools.misc import get_lang
from odoo.addons.resource.models.utils import filter_domain_leaf
PROJECT_TASK_READABLE_FIELDS = {
@@ -1122,6 +1123,39 @@ class Task(models.Model):
return {'date_end': fields.Datetime.now()}
return {'date_end': False}
def _search_on_comodel(self, domain, field, comodel, order=None, additional_domain=None):
def _change_operator(domain):
new_domain = []
for dom in domain:
if len(dom) == 3:
_, op, value = dom
op = "ilike" if op == "child_of" else op
if isinstance(value, list) and all(isinstance(val, int) for val in value):
new_domain.append(("id", op, value))
if isinstance(value, str) or (isinstance(value, list) and not all(isinstance(val, str) for val in value)):
new_domain.append(("name", op, value))
if isinstance(value, int):
new_domain.append(("id", op, [value]))
else:
new_domain.append(dom)
return new_domain
filtered_domain = filter_domain_leaf(domain, lambda field_to_check: field_to_check in [
field,
f"{field}.id",
f"{field}.name",
], {
field: "name",
f"{field}.id": "id",
f"{field}.name": "name",
})
if not filtered_domain:
return False
if additional_domain:
filtered_domain = expression.AND([filtered_domain, additional_domain])
return self.env[comodel].search(_change_operator(filtered_domain), order=order)
# ---------------------------------------------------
# Subtasks
# ---------------------------------------------------
+1 -1
View File
@@ -84,8 +84,8 @@ def filter_domain_leaf(domain, field_check, field_name_mapping=None):
next_elem = domain.pop() # Browsing the domain backward simplifies the filtering
if is_leaf(next_elem):
field_name, op, value = next_elem
field_name = field_name_mapping.get(field_name, field_name)
if field_check(field_name):
field_name = field_name_mapping.get(field_name, field_name)
stack.append((field_name, op, value))
ignored_elems.append(False)
else:
+2 -2
View File
@@ -50,10 +50,10 @@ class TestExpression(TransactionCase):
# Testing field mapping 1
self.assertEqual(
['&', '!', ('field3', '=', False), ('field3', '!=', 'test')],
[('field4', '!=', 'test')],
normalize_domain(utils.filter_domain_leaf(
['|', ('field1', 'in', [1, 2]), '!', ('field2', '=', False), ('field3', '!=', 'test')],
lambda field: field == 'field3',
field_name_mapping={'field2': 'field3'},
field_name_mapping={'field3': 'field4'},
))
)
+13 -1
View File
@@ -9,6 +9,7 @@ from odoo import api, fields, models, _, _lt
from odoo.exceptions import ValidationError, AccessError
from odoo.osv import expression
from odoo.tools import Query
from functools import reduce
from odoo.addons.project.models.project_task import CLOSED_STATES
@@ -752,7 +753,7 @@ class Project(models.Model):
class ProjectTask(models.Model):
_inherit = "project.task"
sale_order_id = fields.Many2one('sale.order', 'Sales Order', compute='_compute_sale_order_id', store=True, help="Sales order to which the task is linked.")
sale_order_id = fields.Many2one('sale.order', 'Sales Order', compute='_compute_sale_order_id', store=True, help="Sales order to which the task is linked.", group_expand="_group_expand_sales_order")
sale_line_id = fields.Many2one(
'sale.order.line', 'Sales Order Item',
copy=True, tracking=True, index='btree_not_null', recursive=True,
@@ -776,6 +777,17 @@ class ProjectTask(models.Model):
def SELF_READABLE_FIELDS(self):
return super().SELF_READABLE_FIELDS | {'allow_billable', 'sale_order_id', 'sale_line_id', 'display_sale_order_button'}
@api.model
def _group_expand_sales_order(self, sales_orders, domain, order):
start_date = self._context.get('gantt_start_date')
scale = self._context.get('gantt_scale')
if not (start_date and scale):
return sales_orders
search_on_comodel = self._search_on_comodel(domain, "sale_order_id", "sale.order", order)
if search_on_comodel:
return search_on_comodel
return sales_orders
@api.depends('sale_line_id', 'project_id', 'partner_id.commercial_partner_id', 'allow_billable')
def _compute_sale_order_id(self):
for task in self: