From abfa921009dd39b50d66763913822086d73f8554 Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Thu, 15 Feb 2018 14:04:35 +0100 Subject: [PATCH] [IMP] sale_timesheet: tasks linked to SOL of project When selling a project from a sale order, the SO line creates the project. When we create a task in that kind of project, by default, the task will be linked to the SO line of its project. However, for the SO line field to be visible on the task form view, the customer must be set. This commit set the customer from the SO line when changing the project (billable project only). --- addons/sale_timesheet/models/project.py | 16 ++++++++ .../sale_timesheet/tests/test_sale_service.py | 41 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/addons/sale_timesheet/models/project.py b/addons/sale_timesheet/models/project.py index 2a28a279393..d8b4cca03a2 100644 --- a/addons/sale_timesheet/models/project.py +++ b/addons/sale_timesheet/models/project.py @@ -56,6 +56,13 @@ class Project(models.Model): class ProjectTask(models.Model): _inherit = "project.task" + def _get_default_partner(self): + partner = super(ProjectTask, self)._get_default_partner() + if 'default_project_id' in self.env.context: # partner from SO line is prior on one from project + project = self.env['project.project'].browse(self.env.context['default_project_id']) + partner = project.sale_line_id.order_partner_id + return partner + @api.model def _default_sale_line_id(self): sale_line_id = False @@ -67,6 +74,15 @@ class ProjectTask(models.Model): sale_line_id = fields.Many2one('sale.order.line', 'Sales Order Item', default=_default_sale_line_id, domain="[('is_service', '=', True), ('order_partner_id', '=', partner_id), ('is_expense', '=', False)]") + @api.onchange('project_id') + def _onchange_project(self): + result = super(ProjectTask, self)._onchange_project() + if self.project_id: + self.sale_line_id = self.project_id.sale_line_id + if not self.partner_id: + self.partner_id = self.sale_line_id.order_partner_id + return result + @api.multi @api.constrains('sale_line_id') def _check_sale_line_type(self): diff --git a/addons/sale_timesheet/tests/test_sale_service.py b/addons/sale_timesheet/tests/test_sale_service.py index 98378df0041..49cc195da90 100644 --- a/addons/sale_timesheet/tests/test_sale_service.py +++ b/addons/sale_timesheet/tests/test_sale_service.py @@ -332,3 +332,44 @@ class TestSaleService(TestCommonSaleTimesheetNoChart): self.assertEqual(so_line1.project_id.sale_line_id, so_line1, "SO line of project with template A should be the one that create it.") self.assertEqual(so_line2.project_id.sale_line_id, so_line2, "SO line of project should be the one that create it.") self.assertEqual(so_line5.project_id.sale_line_id, so_line5, "SO line of project with template B should be the one that create it.") + + def test_billable_task_and_subtask(self): + """ Test if subtasks and tasks are billed on the correct SO line """ + # create SO line and confirm it + so_line_deliver_new_task_project = self.env['sale.order.line'].create({ + 'name': self.product_delivery_timesheet3.name, + 'product_id': self.product_delivery_timesheet3.id, + 'product_uom_qty': 10, + 'product_uom': self.product_delivery_timesheet3.uom_id.id, + 'price_unit': self.product_delivery_timesheet3.list_price, + 'order_id': self.sale_order.id, + }) + so_line_deliver_new_task_project.product_id_change() + self.sale_order.action_confirm() + + project = so_line_deliver_new_task_project.project_id + task = so_line_deliver_new_task_project.task_id + + self.assertEqual(project.sale_line_id, so_line_deliver_new_task_project, "The created project should be linked to the so line") + self.assertEqual(task.sale_line_id, so_line_deliver_new_task_project, "The created task should be linked to the so line") + + # create a new task and subtask + subtask = self.env['project.task'].create({ + 'parent_id': task.id, + 'project_id': project.id, + 'name': '%s: substask1' % (task.name,), + 'sale_line_id': False # forcing, but should have not effect + }) + task2 = self.env['project.task'].create({ + 'project_id': project.id, + 'name': '%s: substask1' % (task.name,) + }) + + self.assertEqual(subtask.sale_line_id, task.sale_line_id, "A child task should have the same SO line than its mother") + self.assertEqual(task2.sale_line_id, project.sale_line_id, "A new task in a billable project should have the same SO line than its project") + self.assertEqual(task2.partner_id, so_line_deliver_new_task_project.order_partner_id, "A new task in a billable project should have the same SO line than its project") + + # moving subtask in another project + subtask.write({'project_id': self.project_global.id}) + + self.assertEqual(subtask.sale_line_id, task.sale_line_id, "A child task should always have the same SO line than its mother, even when changing project")