From 5261cdceae58359ee08a0170fd5d27f4d84c39ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Maes?= Date: Thu, 29 Jun 2017 13:49:11 +0200 Subject: [PATCH] [REF] sale_timesheet: clean task creation from so line Make the code more readable and callable on a recordset. This commit prepare the so line to also generate a project (and not simply a task). --- addons/sale_timesheet/models/sale_order.py | 69 +++++++++++++++++----- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/addons/sale_timesheet/models/sale_order.py b/addons/sale_timesheet/models/sale_order.py index 37e2f4bf9fe..a11e320a645 100644 --- a/addons/sale_timesheet/models/sale_order.py +++ b/addons/sale_timesheet/models/sale_order.py @@ -67,7 +67,7 @@ class SaleOrder(models.Model): order._create_analytic_account(prefix=line.product_id.default_code or None) order.project_id.project_create({'name': order.project_id.name}) break - order.order_line.filtered(lambda line: line._is_task())._create_task() + order.order_line.filtered(lambda line: line.is_service_task)._timesheet_find_task() return result @api.multi @@ -134,13 +134,19 @@ class SaleOrderLine(models.Model): _inherit = "sale.order.line" task_id = fields.Many2one('project.task', 'Task') + is_service_task = fields.Boolean("Will create a task", compute='_compute_is_service_task') + + @api.multi + def _compute_is_service_task(self): + for so_line in self: + so_line.is_service_task = so_line.product_id.type == 'service' and so_line.product_id.track_service == 'task' @api.model def create(self, values): line = super(SaleOrderLine, self).create(values) if line.state == 'sale' and not line.order_id.project_id and line.product_id.track_service in ['timesheet', 'task']: line.order_id._create_analytic_account() - line._create_task() + line._timesheet_find_task() return line def _timesheet_compute_delivered_quantity_domain(self): @@ -163,7 +169,7 @@ class SaleOrderLine(models.Model): planned_hours = self.product_uom_qty return planned_hours - def _get_project(self): + def _timesheet_find_project(self): Project = self.env['project.project'] project = self.product_id.with_context(force_company=self.company_id.id).project_id if not project: @@ -174,13 +180,13 @@ class SaleOrderLine(models.Model): account = self.order_id.project_id project = Project.search([('analytic_account_id', '=', account.id)], limit=1) if not project: - project_id = account.project_create({'name': account.name, 'use_tasks': True}) + project_id = account.project_create({'name': account.name}) project = Project.browse(project_id) return project - def _prepare_service_task_values(self): + def _timesheet_create_task_prepare_values(self): self.ensure_one() - project = self._get_project() + project = self._timesheet_find_project() planned_hours = self._convert_qty_company_hours() return { 'name': '%s:%s' % (self.order_id.name or '', self.product_id.name), @@ -193,12 +199,47 @@ class SaleOrderLine(models.Model): 'company_id': self.company_id.id, } - def _create_task(self): - for line in self: - task_values = line._prepare_service_task_values() - task = self.env['project.task'].create(task_values) - self.write({'task_id': task.id}) + @api.multi + def _timesheet_create_task(self): + """ Generate task for the given so line, and link it. - def _is_task(self): - self.ensure_one() - return self.product_id.type == 'service' and self.product_id.track_service == 'task' + :return a mapping with the so line id and its linked task + :rtype dict + """ + result = {} + for so_line in self: + # create task + values = so_line._timesheet_create_task_prepare_values() + task = self.env['project.task'].sudo().create(values) + so_line.write({'task_id': task.id}) + # post message on SO + msg_body = _("Task Created (%s): %s") % (so_line.product_id.name, task.id, task.name) + so_line.order_id.message_post(body=msg_body) + # post message on task + task_msg = _("This task has been created from: %s (%s)") % (so_line.order_id.id, so_line.order_id.name, so_line.product_id.name) + task.message_post(body=task_msg) + + result[so_line.id] = task + return result + + @api.multi + def _timesheet_find_task(self): + """ Find the task generated by the so lines. If no task linked, it will be + created automatically. + + :return a mapping with the so line id and its linked task + :rtype dict + """ + # one search for all so lines + tasks = self.env['project.task'].search([('sale_line_id', 'in', self.ids)]) + task_sol_mapping = {task.sale_line_id.id: task for task in tasks} + + result = {} + for so_line in self: + # If the SO was confirmed, cancelled, set to draft then confirmed, avoid creating a new task. + task = task_sol_mapping.get(so_line.id) + # If not found, create one task for the so line + if not task: + task = so_line._timesheet_create_task()[so_line.id] + result[so_line.id] = task + return result