diff --git a/addons/project/models/project.py b/addons/project/models/project.py index 9629d9c7d5a..53a5befe9f1 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -436,9 +436,13 @@ class Task(models.Model): @api.model def default_get(self, fields_list): result = super(Task, self).default_get(fields_list) - # force some parent values, if needed - if 'parent_id' in result and result['parent_id']: - result.update(self._subtask_values_from_parent(result['parent_id'])) + # find default value from parent for the not given ones + parent_task_id = result.get('parent_id') or self._context.get('default_parent_id') + if parent_task_id: + parent_values = self._subtask_values_from_parent(parent_task_id) + for fname, value in parent_values.items(): + if fname not in result: + result[fname] = value return result @api.model @@ -538,11 +542,6 @@ class Task(models.Model): # customer portal: include comment and incoming emails in communication history website_message_ids = fields.One2many(domain=lambda self: [('model', '=', self._name), ('message_type', 'in', ['email', 'comment'])]) - @api.constrains('parent_id') - def _check_parent_id(self): - if not self._check_recursion(): - raise ValidationError(_('You cannot create recursive tasks.')) - def _compute_attachment_ids(self): for task in self: attachment_ids = self.env['ir.attachment'].search([('res_id', '=', task.id), ('res_model', '=', 'project.task')]).ids @@ -619,14 +618,17 @@ class Task(models.Model): @api.onchange('parent_id') def _onchange_parent_id(self): if self.parent_id: - for field_name in self._subtask_implied_fields(): - self[field_name] = self.parent_id[field_name] + for field_name, value in self._subtask_values_from_parent(self.parent_id.id).items(): + if not self[field_name]: + self[field_name] = value @api.onchange('project_id') def _onchange_project(self): if self.project_id: - if not self.parent_id and self.project_id.partner_id: + # find partner + if self.project_id.partner_id: self.partner_id = self.project_id.partner_id + # find stage if self.project_id not in self.stage_id.project_ids: self.stage_id = self.stage_find(self.project_id.id, [('fold', '=', False)]) # keep multi company consistency @@ -709,10 +711,6 @@ class Task(models.Model): def create(self, vals): # context: no_log, because subtype already handle this context = dict(self.env.context) - # force some parent values, if needed - if 'parent_id' in vals and vals['parent_id']: - vals.update(self._subtask_values_from_parent(vals['parent_id'])) - context.pop('default_parent_id', None) # for default stage if vals.get('project_id') and not context.get('default_project_id'): context['default_project_id'] = vals.get('project_id') @@ -723,14 +721,16 @@ class Task(models.Model): if vals.get('stage_id'): vals.update(self.update_date_end(vals['stage_id'])) vals['date_last_stage_update'] = fields.Datetime.now() + # substask default values + if vals.get('parent_id'): + for fname, value in self._subtask_values_from_parent(vals['parent_id']).items(): + if fname not in vals: + vals[fname] = value task = super(Task, self.with_context(context)).create(vals) return task def write(self, vals): now = fields.Datetime.now() - # subtask: force some parent values, if needed - if 'parent_id' in vals and vals['parent_id']: - vals.update(self._subtask_values_from_parent(vals['parent_id'])) # stage change: update date_last_stage_update if 'stage_id' in vals: vals.update(self.update_date_end(vals['stage_id'])) @@ -746,12 +746,6 @@ class Task(models.Model): # rating on stage if 'stage_id' in vals and vals.get('stage_id'): self.filtered(lambda x: x.project_id.rating_status == 'stage')._send_task_rating_mail(force_send=True) - # subtask: update subtask according to parent values - subtask_values_to_write = self._subtask_write_values(vals) - if subtask_values_to_write: - subtasks = self.filtered(lambda task: not task.parent_id).mapped('child_ids') - if subtasks: - subtasks.write(subtask_values_to_write) return result def update_date_end(self, stage_id): @@ -764,27 +758,18 @@ class Task(models.Model): # Subtasks # --------------------------------------------------- - @api.model - def _subtask_implied_fields(self): - """ Return the list of field name to apply on subtask when changing parent_id or when updating parent task. """ + def _subtask_default_fields(self): + """ Return the list of field name for default value when creating a subtask """ return ['partner_id', 'email_from'] - def _subtask_write_values(self, values): - """ Return the values to write on subtask when `values` is written on parent tasks - :param values: dict of values to write on parent - """ - result = {} - for field_name in self._subtask_implied_fields(): - if field_name in values: - result[field_name] = values[field_name] - return result - def _subtask_values_from_parent(self, parent_id): """ Get values for substask implied field of the given""" result = {} parent_task = self.env['project.task'].browse(parent_id) - for field_name in self._subtask_implied_fields(): + for field_name in self._subtask_default_fields(): result[field_name] = parent_task[field_name] + # special case for the subtask default project + result['project_id'] = parent_task.project_id.subtask_project_id return self._convert_to_write(result) # --------------------------------------------------- @@ -942,16 +927,28 @@ class Task(models.Model): def action_subtask(self): action = self.env.ref('project.project_task_action_sub_task').read()[0] - ctx = self.env.context.copy() - ctx.update({ - 'default_parent_id': self.id, - 'default_project_id': self.env.context.get('project_id', self.project_id.id), - 'default_name': self.env.context.get('name', self.name) + ':', - 'default_partner_id': self.env.context.get('partner_id', self.partner_id.id), - 'search_default_project_id': self.env.context.get('project_id', self.project_id.id), - }) - action['context'] = ctx + + # only display subtasks of current task action['domain'] = [('id', 'child_of', self.id), ('id', '!=', self.id)] + + # update context, with all default values as 'quick_create' does not contains all field in its view + if self._context.get('default_project_id'): + default_project = self.env['project.project'].browse(self.env.context['default_project_id']) + else: + default_project = self.project_id.subtask_project_id or self.project_id + ctx = dict(self.env.context) + ctx.update({ + 'default_name': self.env.context.get('name', self.name) + ':', + 'default_parent_id': self.id, # will give default subtask field in `default_get` + 'default_company_id': default_project.company_id.id if default_project else self.env.company.id, + 'search_default_parent_id': self.id, + }) + parent_values = self._subtask_values_from_parent(self.id) + for fname, value in parent_values.items(): + if 'default_' + fname not in ctx: + ctx['default_' + fname] = value + action['context'] = ctx + return action # --------------------------------------------------- diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index 7940111441a..f8abdfd8e80 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -22,6 +22,7 @@ + @@ -449,8 +450,7 @@