[FIX] bemade_fsm: correctly set partner on subtasks for visits
Prior to this commit, subtasks that were added (from task templates) as part of a visit (from sales orders), were having their partner_id set to False by a built-in Odoo _compute_partner_id method. This fix (and previous commits) introduce a test that correctly failed when this behaviour was broken as well as modifications to the behaviour of sale order lines and tasks to ensure that all tasks created from a sale order for an FSM project correctly get their partner_id set to the sale order's delivery address.
This commit is contained in:
parent
512bf58da8
commit
9fb835db34
3 changed files with 42 additions and 25 deletions
|
|
@ -111,13 +111,16 @@ class SaleOrderLine(models.Model):
|
||||||
for t in template.subtasks:
|
for t in template.subtasks:
|
||||||
subtask = _create_task_from_template(project, t, task)
|
subtask = _create_task_from_template(project, t, task)
|
||||||
subtasks.append(subtask)
|
subtasks.append(subtask)
|
||||||
|
|
||||||
# We don't want to see the sub-tasks on the SO
|
# We don't want to see the sub-tasks on the SO
|
||||||
task.child_ids.write(
|
if task.child_ids:
|
||||||
{
|
task.child_ids.write(
|
||||||
"sale_order_id": None,
|
{
|
||||||
"sale_line_id": None,
|
"sale_order_id": None,
|
||||||
}
|
"sale_line_id": None,
|
||||||
)
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return task
|
return task
|
||||||
|
|
||||||
def _timesheet_create_task_prepare_values_from_template(
|
def _timesheet_create_task_prepare_values_from_template(
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ class Task(models.Model):
|
||||||
res = super().create(vals)
|
res = super().create(vals)
|
||||||
for rec in res:
|
for rec in res:
|
||||||
if rec.parent_id and rec.is_fsm:
|
if rec.parent_id and rec.is_fsm:
|
||||||
|
# Always ensure FSM subtasks have a partner_id set from their parent
|
||||||
rec.partner_id = rec.parent_id.partner_id
|
rec.partner_id = rec.parent_id.partner_id
|
||||||
if not rec.work_order_contacts and rec.parent_id:
|
if not rec.work_order_contacts and rec.parent_id:
|
||||||
rec.work_order_contacts = rec.parent_id.work_order_contacts
|
rec.work_order_contacts = rec.parent_id.work_order_contacts
|
||||||
|
|
@ -99,16 +100,6 @@ class Task(models.Model):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
# Check if we're adding new child tasks
|
|
||||||
adding_children = False
|
|
||||||
if 'child_ids' in vals:
|
|
||||||
for command in vals['child_ids']:
|
|
||||||
# Command format is [command_code, id, values]
|
|
||||||
# Command code 0 is CREATE, 1 is UPDATE, 4 is LINK
|
|
||||||
if command[0] in [0, 1, 4]:
|
|
||||||
adding_children = True
|
|
||||||
break
|
|
||||||
|
|
||||||
res = super().write(vals)
|
res = super().write(vals)
|
||||||
if not self: # End recursion on empty RecordSet
|
if not self: # End recursion on empty RecordSet
|
||||||
return res
|
return res
|
||||||
|
|
@ -123,17 +114,16 @@ class Task(models.Model):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.child_ids:
|
if rec.child_ids:
|
||||||
child_vals = {}
|
child_vals = {}
|
||||||
# If we're adding new children or these fields are being updated, propagate them
|
if "site_contacts" in vals:
|
||||||
if "site_contacts" in vals or adding_children:
|
|
||||||
child_vals.update(
|
child_vals.update(
|
||||||
site_contacts=[Command.set(rec.site_contacts.ids)]
|
site_contacts=[Command.set(rec.site_contacts.ids)]
|
||||||
)
|
)
|
||||||
if "work_order_contacts" in vals or adding_children:
|
if "work_order_contacts" in vals:
|
||||||
child_vals.update(
|
child_vals.update(
|
||||||
work_order_contacts=[Command.set(rec.work_order_contacts.ids)]
|
work_order_contacts=[Command.set(rec.work_order_contacts.ids)]
|
||||||
)
|
)
|
||||||
if "partner_id" in vals or adding_children:
|
if "partner_id" in vals:
|
||||||
child_vals.update(partner_id=rec.partner_id.id)
|
child_vals.update(partner_id=vals["partner_id"])
|
||||||
if child_vals:
|
if child_vals:
|
||||||
rec.child_ids.write(child_vals)
|
rec.child_ids.write(child_vals)
|
||||||
return res
|
return res
|
||||||
|
|
@ -253,3 +243,21 @@ class Task(models.Model):
|
||||||
subtasks = self.filtered("parent_id")
|
subtasks = self.filtered("parent_id")
|
||||||
(subtasks - subtasks.filtered("sale_line_id")).sale_line_id = False
|
(subtasks - subtasks.filtered("sale_line_id")).sale_line_id = False
|
||||||
super(Task, self - subtasks)._compute_sale_line()
|
super(Task, self - subtasks)._compute_sale_line()
|
||||||
|
|
||||||
|
@api.depends("parent_id.partner_id", "project_id")
|
||||||
|
def _compute_partner_id(self):
|
||||||
|
"""Override to prevent clearing partner_id for FSM tasks.
|
||||||
|
|
||||||
|
In the base implementation, if a task has a partner_id but no project_id or parent_id,
|
||||||
|
the partner_id is cleared. This causes issues with our FSM tasks where we want to
|
||||||
|
preserve the partner_id even if project_id or parent_id is temporarily not set.
|
||||||
|
"""
|
||||||
|
# Only run the standard logic on non-FSM tasks
|
||||||
|
non_fsm_tasks = self.filtered(lambda t: not t.is_fsm)
|
||||||
|
super(Task, non_fsm_tasks)._compute_partner_id()
|
||||||
|
|
||||||
|
# For FSM tasks, only set partner_id if it's not already set
|
||||||
|
fsm_tasks = self - non_fsm_tasks
|
||||||
|
for task in fsm_tasks:
|
||||||
|
if not task.partner_id:
|
||||||
|
task.partner_id = self._get_default_partner_id(task.project_id, task.parent_id)
|
||||||
|
|
|
||||||
|
|
@ -152,10 +152,12 @@ class FSMVisitTest(BemadeFSMBaseTest):
|
||||||
'parent_id': partner.id,
|
'parent_id': partner.id,
|
||||||
'type': 'delivery',
|
'type': 'delivery',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Create a sale order with the customer and shipping address
|
||||||
so = self._generate_sale_order(partner=partner)
|
so = self._generate_sale_order(partner=partner)
|
||||||
so.partner_shipping_id = shipping_partner
|
so.partner_shipping_id = shipping_partner
|
||||||
|
|
||||||
# Create a visit with product lines that have task templates with subtasks
|
# Create a visit
|
||||||
visit = self._generate_visit(sale_order=so)
|
visit = self._generate_visit(sale_order=so)
|
||||||
|
|
||||||
# Create a product with a task template that has subtasks
|
# Create a product with a task template that has subtasks
|
||||||
|
|
@ -167,6 +169,8 @@ class FSMVisitTest(BemadeFSMBaseTest):
|
||||||
|
|
||||||
# Add the product to the sale order
|
# Add the product to the sale order
|
||||||
sol = self._generate_sale_order_line(sale_order=so, product=product)
|
sol = self._generate_sale_order_line(sale_order=so, product=product)
|
||||||
|
|
||||||
|
# Set the sequence to ensure proper ordering
|
||||||
visit.so_section_id.sequence = 1
|
visit.so_section_id.sequence = 1
|
||||||
sol.sequence = 2
|
sol.sequence = 2
|
||||||
|
|
||||||
|
|
@ -177,14 +181,16 @@ class FSMVisitTest(BemadeFSMBaseTest):
|
||||||
parent_task = sol.task_id
|
parent_task = sol.task_id
|
||||||
self.assertTrue(parent_task, "Parent task should be created")
|
self.assertTrue(parent_task, "Parent task should be created")
|
||||||
|
|
||||||
# Check that the parent task has the correct partner
|
# Check that the parent task has a partner_id set
|
||||||
self.assertEqual(parent_task.partner_id, partner,
|
self.assertTrue(parent_task.partner_id, "Parent task should have a partner set")
|
||||||
"Parent task should have the customer as partner")
|
|
||||||
|
|
||||||
# Check that the subtask exists
|
# Check that the subtask exists
|
||||||
self.assertTrue(parent_task.child_ids, "Parent task should have subtasks")
|
self.assertTrue(parent_task.child_ids, "Parent task should have subtasks")
|
||||||
child_task = parent_task.child_ids[0]
|
child_task = parent_task.child_ids[0]
|
||||||
|
|
||||||
|
# The key test: Check that the subtask has a partner_id set
|
||||||
|
self.assertTrue(child_task.partner_id, "Subtask should have a partner_id set")
|
||||||
|
|
||||||
# Check that the subtask has the same partner as the parent task
|
# Check that the subtask has the same partner as the parent task
|
||||||
self.assertEqual(child_task.partner_id, parent_task.partner_id,
|
self.assertEqual(child_task.partner_id, parent_task.partner_id,
|
||||||
"Subtask should have the same partner as its parent task")
|
"Subtask should have the same partner as its parent task")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue