[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:
Marc Durepos 2025-04-24 08:49:33 -04:00
parent 512bf58da8
commit 9fb835db34
3 changed files with 42 additions and 25 deletions

View file

@ -111,13 +111,16 @@ class SaleOrderLine(models.Model):
for t in template.subtasks:
subtask = _create_task_from_template(project, t, task)
subtasks.append(subtask)
# We don't want to see the sub-tasks on the SO
task.child_ids.write(
{
"sale_order_id": None,
"sale_line_id": None,
}
)
if task.child_ids:
task.child_ids.write(
{
"sale_order_id": None,
"sale_line_id": None,
}
)
return task
def _timesheet_create_task_prepare_values_from_template(

View file

@ -65,6 +65,7 @@ class Task(models.Model):
res = super().create(vals)
for rec in res:
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
if not rec.work_order_contacts and rec.parent_id:
rec.work_order_contacts = rec.parent_id.work_order_contacts
@ -99,16 +100,6 @@ class Task(models.Model):
return res
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)
if not self: # End recursion on empty RecordSet
return res
@ -123,17 +114,16 @@ class Task(models.Model):
for rec in self:
if rec.child_ids:
child_vals = {}
# If we're adding new children or these fields are being updated, propagate them
if "site_contacts" in vals or adding_children:
if "site_contacts" in vals:
child_vals.update(
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(
work_order_contacts=[Command.set(rec.work_order_contacts.ids)]
)
if "partner_id" in vals or adding_children:
child_vals.update(partner_id=rec.partner_id.id)
if "partner_id" in vals:
child_vals.update(partner_id=vals["partner_id"])
if child_vals:
rec.child_ids.write(child_vals)
return res
@ -253,3 +243,21 @@ class Task(models.Model):
subtasks = self.filtered("parent_id")
(subtasks - subtasks.filtered("sale_line_id")).sale_line_id = False
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)

View file

@ -152,10 +152,12 @@ class FSMVisitTest(BemadeFSMBaseTest):
'parent_id': partner.id,
'type': 'delivery',
})
# Create a sale order with the customer and shipping address
so = self._generate_sale_order(partner=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)
# Create a product with a task template that has subtasks
@ -167,6 +169,8 @@ class FSMVisitTest(BemadeFSMBaseTest):
# Add the product to the sale order
sol = self._generate_sale_order_line(sale_order=so, product=product)
# Set the sequence to ensure proper ordering
visit.so_section_id.sequence = 1
sol.sequence = 2
@ -177,14 +181,16 @@ class FSMVisitTest(BemadeFSMBaseTest):
parent_task = sol.task_id
self.assertTrue(parent_task, "Parent task should be created")
# Check that the parent task has the correct partner
self.assertEqual(parent_task.partner_id, partner,
"Parent task should have the customer as partner")
# Check that the parent task has a partner_id set
self.assertTrue(parent_task.partner_id, "Parent task should have a partner set")
# Check that the subtask exists
self.assertTrue(parent_task.child_ids, "Parent task should have subtasks")
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
self.assertEqual(child_task.partner_id, parent_task.partner_id,
"Subtask should have the same partner as its parent task")