Before this commit, the `display_project_id` field was a bit confusing for the user to know what is the goal of this field. Also this field is available when the user wants to import his data into Odoo, if he does not know the goal of this field then he could be lost to know which field he should for his data to import (or even export). This commit removes the display_project_id field and so a task will be private one if the project and the parent fields are not set. The project to set to the timesheet will be the one set on the task or the one set on one of its parent tasks. task-3230063 X-original-commit: 22eda5a5ddcfcda9fa6597d6fe21eb20f525799f Part-of: odoo/odoo#115781
111 lines
3.8 KiB
Python
111 lines
3.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import _, api, fields, models, Command
|
|
from odoo.exceptions import ValidationError
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
class ProjectTaskRecurrence(models.Model):
|
|
_name = 'project.task.recurrence'
|
|
_description = 'Task Recurrence'
|
|
|
|
task_ids = fields.One2many('project.task', 'recurrence_id', copy=False)
|
|
|
|
repeat_interval = fields.Integer(string='Repeat Every', default=1)
|
|
repeat_unit = fields.Selection([
|
|
('day', 'Days'),
|
|
('week', 'Weeks'),
|
|
('month', 'Months'),
|
|
('year', 'Years'),
|
|
], default='week')
|
|
repeat_type = fields.Selection([
|
|
('forever', 'Forever'),
|
|
('until', 'Until'),
|
|
], default="forever", string="Until")
|
|
repeat_until = fields.Date(string="End Date")
|
|
|
|
@api.constrains('repeat_interval')
|
|
def _check_repeat_interval(self):
|
|
if self.filtered(lambda t: t.repeat_interval <= 0):
|
|
raise ValidationError(_('The interval should be greater than 0'))
|
|
|
|
@api.constrains('repeat_type', 'repeat_until')
|
|
def _check_repeat_until_date(self):
|
|
today = fields.Date.today()
|
|
if self.filtered(lambda t: t.repeat_type == 'until' and t.repeat_until < today):
|
|
raise ValidationError(_('The end date should be in the future'))
|
|
|
|
@api.model
|
|
def _get_recurring_fields_to_copy(self):
|
|
return [
|
|
'analytic_account_id',
|
|
'company_id',
|
|
'description',
|
|
'displayed_image_id',
|
|
'email_cc',
|
|
'message_partner_ids',
|
|
'name',
|
|
'parent_id',
|
|
'partner_id',
|
|
'partner_phone',
|
|
'planned_hours',
|
|
'project_id',
|
|
'project_privacy_visibility',
|
|
'recurrence_id',
|
|
'recurring_task',
|
|
'sequence',
|
|
'tag_ids',
|
|
'user_ids',
|
|
]
|
|
|
|
@api.model
|
|
def _get_recurring_fields_to_postpone(self):
|
|
return [
|
|
'date_deadline',
|
|
]
|
|
|
|
def _get_last_task_id_per_recurrence_id(self):
|
|
return {} if not self else {
|
|
record['recurrence_id'][0]: record['max_id']
|
|
for record in self.env['project.task'].sudo()._read_group(
|
|
[('recurrence_id', 'in', self.ids)],
|
|
['max_id:max(id)'],
|
|
['recurrence_id'],
|
|
)
|
|
}
|
|
|
|
def _get_recurrence_delta(self):
|
|
return relativedelta(**{
|
|
f"{self.repeat_unit}s": self.repeat_interval
|
|
})
|
|
|
|
def _create_next_occurrence(self, occurrence_from):
|
|
self.ensure_one()
|
|
if occurrence_from.allow_recurring_tasks:
|
|
self.env['project.task'].sudo().create(
|
|
self._create_next_occurrence_values(occurrence_from)
|
|
)
|
|
|
|
def _create_next_occurrence_values(self, occurrence_from):
|
|
self.ensure_one()
|
|
fields_to_copy = occurrence_from.read(self._get_recurring_fields_to_copy()).pop()
|
|
create_values = {
|
|
field: value[0] if isinstance(value, tuple) else value
|
|
for field, value in fields_to_copy.items()
|
|
}
|
|
|
|
fields_to_postpone = occurrence_from.read(self._get_recurring_fields_to_postpone()).pop()
|
|
fields_to_postpone.pop('id', None)
|
|
create_values.update({
|
|
field: value and value + self._get_recurrence_delta()
|
|
for field, value in fields_to_postpone.items()
|
|
})
|
|
|
|
create_values['stage_id'] = occurrence_from.project_id.type_ids[0].id if occurrence_from.project_id.type_ids else occurrence_from.stage_id.id
|
|
if occurrence_from.allow_subtasks:
|
|
create_values['child_ids'] = [
|
|
Command.create(self._create_next_occurrence_values(child)) for child in occurrence_from.with_context(active_test=False).child_ids
|
|
]
|
|
return create_values
|