[FIX] sale_project: link subtask to sale order line of parent
Steps to reproduce: ------------------- - create two product of type "service"; - field "Create on Order" is set to "Project & Task"; - create a Sale Order with these two products; - condirm the Sale Order; Two tasks are created in a project and each task has its own Sale Order Line Item. - create a subtask from both tasks respectively; - select a project for the subtask. Issue: ------ The same Sale Order Line is selected for the two subtasks. It always take the first Sale Order line. Cause: ------ To choose the sale order line, we first look to see if the subtask belongs to a project. If so, we take the sale order line which created the project. Unfortunately, a subtask can belong to a project created with a sale order line without belonging to the same sale order line (in the case where a task is added to a project via another product and therefore another sale order line). Solution: --------- - A project without parent --> use project's sale order line - A parent without project --> no sale order line defined - A parent in the same project --> use parent's sale order line - A parent in an other project --> use parent's sale order line opw-3333936 closes odoo/odoo#124260 X-original-commit: 323d7f631916f5acc5ab34f8531ae59bb0455828 Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com> Signed-off-by: Lefebvre Thomas (thle) <thle@odoo.com>
This commit is contained in:
@@ -738,11 +738,13 @@ class ProjectTask(models.Model):
|
||||
continue
|
||||
if not task.sale_line_id:
|
||||
# if the project_id is set then it means the task is classic task or a subtask with another project than its parent.
|
||||
# To determine the sale_line_id, we first need to look at the parent before the project to manage the case of subtasks.
|
||||
# Two sub-tasks in the same project do not necessarily have the same sale_line_id (need to look at the parent task).
|
||||
sale_line = False
|
||||
if task.project_id.sale_line_id and task.project_id.partner_id.commercial_partner_id == task.partner_id.commercial_partner_id:
|
||||
sale_line = task.project_id.sale_line_id
|
||||
elif task.parent_id.sale_line_id and task.parent_id.partner_id.commercial_partner_id == task.partner_id.commercial_partner_id:
|
||||
if task.parent_id.sale_line_id and task.parent_id.partner_id.commercial_partner_id == task.partner_id.commercial_partner_id:
|
||||
sale_line = task.parent_id.sale_line_id
|
||||
elif task.project_id.sale_line_id and task.project_id.partner_id.commercial_partner_id == task.partner_id.commercial_partner_id:
|
||||
sale_line = task.project_id.sale_line_id
|
||||
task.sale_line_id = sale_line or task.milestone_id.sale_line_id
|
||||
# check sale_line_id and customer are coherent
|
||||
if task.sale_line_id.order_partner_id.commercial_partner_id != task.partner_id.commercial_partner_id:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import Command
|
||||
from odoo.tests.common import new_test_user
|
||||
from .common import TestSaleProjectCommon
|
||||
from odoo.tests.common import tagged
|
||||
@@ -236,6 +237,103 @@ class TestSaleProject(TestSaleProjectCommon):
|
||||
sale_order.with_context({'disable_cancel_warning': True}).action_cancel()
|
||||
self.assertFalse(self.project_global.sale_line_id, "The project should not be linked to the SOL anymore")
|
||||
|
||||
def test_links_with_sale_order_line(self):
|
||||
"""
|
||||
Check that the subtasks are linked to the correct sale order line.
|
||||
"""
|
||||
product_A, product_B, product_C = self.env['product.product'].create([
|
||||
{
|
||||
'name': 'product_A',
|
||||
'lst_price': 100.0,
|
||||
'detailed_type': 'service',
|
||||
'service_tracking': 'task_in_project',
|
||||
},
|
||||
{
|
||||
'name': 'product_B',
|
||||
'lst_price': 100.0,
|
||||
'detailed_type': 'service',
|
||||
'service_tracking': 'task_in_project',
|
||||
},
|
||||
{
|
||||
'name': 'product_C',
|
||||
'lst_price': 100.0,
|
||||
'detailed_type': 'service',
|
||||
'service_tracking': 'task_in_project',
|
||||
},
|
||||
])
|
||||
sale_order_first, sale_order_second = self.env['sale.order'].create([
|
||||
{
|
||||
'partner_id': self.partner.id,
|
||||
'order_line': [
|
||||
Command.create({'product_id': product_A.id}),
|
||||
Command.create({'product_id': product_B.id}),
|
||||
]
|
||||
},
|
||||
{
|
||||
'partner_id': self.partner.id,
|
||||
'order_line': [
|
||||
Command.create({'product_id': product_C.id}),
|
||||
]
|
||||
}
|
||||
])
|
||||
(sale_order_first + sale_order_second).action_confirm()
|
||||
|
||||
sale_order_line_A = sale_order_first.order_line.filtered(lambda sol: sol.product_id == product_A)
|
||||
sale_order_line_B = sale_order_first.order_line - sale_order_line_A
|
||||
sale_order_line_C = sale_order_second.order_line
|
||||
|
||||
project_first = sale_order_first.project_ids
|
||||
project_second = sale_order_second.project_ids
|
||||
|
||||
task_A = sale_order_first.tasks_ids.filtered(lambda task: task.sale_line_id == sale_order_line_A)
|
||||
task_B = sale_order_first.tasks_ids - task_A
|
||||
task_C = sale_order_second.tasks_ids
|
||||
|
||||
# [CASE 1] Parent in the same project --> use parent's sale order line
|
||||
task_A.write({
|
||||
'child_ids': [
|
||||
Command.create({'name': 'Sub A in first project', 'project_id': project_first.id}),
|
||||
]
|
||||
})
|
||||
task_B.write({
|
||||
'child_ids': [
|
||||
Command.create({'name': 'Sub B in first project', 'project_id': project_first.id}),
|
||||
]
|
||||
})
|
||||
task_C.write({
|
||||
'child_ids': [
|
||||
Command.create({'name': 'Sub C in second project', 'project_id': project_second.id}),
|
||||
]
|
||||
})
|
||||
self.assertEqual(task_A.child_ids.sale_line_id, sale_order_line_A)
|
||||
self.assertEqual(task_B.child_ids.sale_line_id, sale_order_line_B)
|
||||
self.assertEqual(task_C.child_ids.sale_line_id, sale_order_line_C)
|
||||
|
||||
# [CASE 2] Parent in an other project --> use parent's sale_order line
|
||||
task_B.write({
|
||||
'child_ids': [
|
||||
Command.create({'name': 'Sub B in second project', 'project_id': project_second.id}),
|
||||
]
|
||||
})
|
||||
sub_B_second = task_B.child_ids.filtered(lambda sub: sub.name == 'Sub B in second project')
|
||||
self.assertEqual(sub_B_second.sale_line_id, sale_order_line_B)
|
||||
|
||||
# [CASE 3] Without project --> no sale order line defined
|
||||
task_B.write({
|
||||
'child_ids': [
|
||||
Command.create({'name': 'Sub B without project'}),
|
||||
]
|
||||
})
|
||||
sub_B_without = task_B.child_ids.filtered(lambda sub: sub.name == 'Sub B without project')
|
||||
self.assertEqual(len(sub_B_without.sale_line_id), 0)
|
||||
|
||||
# [CASE 4] Without parent --> use sale order line of the project
|
||||
task_D = self.env['project.task'].create({
|
||||
'name': 'Task D',
|
||||
'project_id': project_first.id,
|
||||
})
|
||||
self.assertEqual(task_D.sale_line_id, project_first.sale_line_id)
|
||||
|
||||
def test_compute_project_and_task_button(self):
|
||||
"""
|
||||
Ensures that when a sale order has at least one sol with a service product whose service-policy is either delivered on milestone or ordered prepaid, then the
|
||||
|
||||
Reference in New Issue
Block a user