bemade_fsm: completing an FSM tasks completes all its descendants as well.

This commit is contained in:
Marc Durepos 2023-11-21 10:00:30 -05:00
parent 0ddb7c8160
commit 8b8250ffbb
3 changed files with 30 additions and 12 deletions

View file

@ -184,17 +184,21 @@ class Task(models.Model):
rec.allow_billable = rec.project_id.allow_billable
def action_fsm_validate(self):
visits = self.filtered(lambda t: t.visit_id)
non_visits = self - visits
# Override to make sure all descendant tasks are validated as well
full_hierarchy = self._get_full_hierarchy()
visits = self.filtered(lambda t: bool(t.visit_id))
non_visits = full_hierarchy - visits
super(Task, non_visits).action_fsm_validate()
visits._stop_all_timers_and_create_timesheets()
closed_stage_by_project = visits._get_closed_stage_by_project()
super(Task, visits.child_ids).action_fsm_validate()
for visit in visits:
stage = closed_stage_by_project[visit.project_id]
visits.write({'stage_id': stage.id, 'fsm_done': True})
def _get_full_hierarchy(self):
if self.child_ids:
return self | self.child_ids._get_full_hierarchy()
return self
def synchronize_name_fsm(self):
""" Applies naming to the entire task tree for tasks that are part of this
recordset. Root tasks are named:

View file

@ -192,3 +192,16 @@ class BemadeFSMBaseTest(TransactionCase):
sol1.sequence = 2
sol2.sequence = 3
return so, visit, sol1, sol2
def _generate_so_with_one_visit_two_lines_and_descendants(self):
so = self._generate_sale_order()
visit = self._generate_visit(sale_order=so)
task_template = self._generate_task_template(structure=[2, 2, 2],
names=['Parent', 'Child', 'Grandchild', 'Great-grandchild'])
product = self._generate_product(task_template=task_template)
sol1 = self._generate_sale_order_line(sale_order=so, product=product)
sol2 = self._generate_sale_order_line(sale_order=so, product=product)
visit.so_section_id.sequence = 1
sol1.sequence = 2
sol2.sequence = 3
return so, visit, sol1, sol2

View file

@ -102,18 +102,19 @@ class FSMVisitTest(BemadeFSMBaseTest):
self.assertEqual(len(so.order_line), 3)
def test_marking_visit_task_done_completes_descendants(self):
so, visit, sol1, sol2 = self._generate_so_with_one_visit_two_lines()
so, visit, sol1, sol2 = self._generate_so_with_one_visit_two_lines_and_descendants()
so.action_confirm()
parent, child1, child2 = visit.task_id, sol1.task_id, sol2.task_id
parent = visit.task_id
parent.action_fsm_validate()
self.assertTrue(parent.is_closed)
self.assertTrue(child1.is_closed)
self.assertTrue(child2.is_closed)
self.assertEqual(sol1.qty_to_deliver, 0)
self.assertEqual(sol2.qty_to_deliver, 0)
self.assertTrue(visit.is_completed)
self._assert_is_done(parent)
def _assert_is_done(self, task):
""" Recursively assert all tasks in a hierarchy are complete """
self.assertTrue(task.is_closed)
for child in task.child_ids:
self._assert_is_done(child)
def test_marking_visit_task_done_does_not_create_sale_order_line(self):
so, visit, sol1, sol2 = self._generate_so_with_one_visit_two_lines()