From 181878ca0a0172c0501517cdb24de4674daa7880 Mon Sep 17 00:00:00 2001 From: Justine Doutreloux Date: Tue, 8 Aug 2023 13:41:34 +0200 Subject: [PATCH 1/3] [IMP] stachechat_mixin: make it possible to ignore some events in the has_allowed_event compute --- statechart/models/statechart_mixin.py | 7 ++++- test_statechart/models/test_statechart.yml | 8 ++++++ test_statechart/tests/test_basic.py | 31 ++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/statechart/models/statechart_mixin.py b/statechart/models/statechart_mixin.py index 0a3487e..3d0bebc 100644 --- a/statechart/models/statechart_mixin.py +++ b/statechart/models/statechart_mixin.py @@ -331,9 +331,14 @@ class can override the statechart with another one adding new events, @api.model def _get_sc_event_allowed_field_names(self): + ignore_for_has_allowed_events = self.env.context.get( + "ignore_for_has_allowed_events", [] + ) event_names = self._statechart.events_for() return [ - _sc_make_event_allowed_field_name(event_name) for event_name in event_names + _sc_make_event_allowed_field_name(event_name) + for event_name in event_names + if event_name not in ignore_for_has_allowed_events ] @api.depends("sc_state") diff --git a/test_statechart/models/test_statechart.yml b/test_statechart/models/test_statechart.yml index 39a63a0..0b26470 100644 --- a/test_statechart/models/test_statechart.yml +++ b/test_statechart/models/test_statechart.yml @@ -10,10 +10,18 @@ statechart: target: confirmed1 - target: confirmed1 guard: o.amount < 1 + - target: canceled + event: cancel - name: confirmed1 transitions: - target: confirmed2 guard: o.amount < 100 - target: confirmed2 event: confirm2 + - target: canceled + event: cancel - name: confirmed2 + transitions: + - target: canceled + event: cancel + - name: canceled diff --git a/test_statechart/tests/test_basic.py b/test_statechart/tests/test_basic.py index 90e915b..b57b2a0 100644 --- a/test_statechart/tests/test_basic.py +++ b/test_statechart/tests/test_basic.py @@ -35,3 +35,34 @@ def test_automatic_transition_on_create(self): record = model.create({"amount": 0.5}) # very small amount, step 1 and 2 done automatically self.assertScState(record.sc_state, ["confirmed2", "root"]) + + def test_get_sc_event_allowed_field_names(self): + """ + Test that we can ignore certain events based on a context + key (ignore_for_has_allowed_events) + """ + model = self.env["scobidoo.test.model"] + record = model.create({"amount": 200}) + record.confirm1() + self.assertScState(record.sc_state, ["confirmed1", "root"]) + + # 2 events are allowed: confirmed2 and cancel + self.assertEqual(record.sc_has_allowed_events, True) + + # 1 event is allowed: confirmed2 + record.invalidate_cache() + self.assertEqual( + record.with_context( + ignore_for_has_allowed_events=["cancel"] + ).sc_has_allowed_events, + True, + ) + + # no event allowed + record.invalidate_cache() + self.assertEqual( + record.with_context( + ignore_for_has_allowed_events=["cancel", "confirm2"] + ).sc_has_allowed_events, + False, + ) From 47204a79953d8e5ae80d7bd64eb261e1de12738b Mon Sep 17 00:00:00 2001 From: Thomas Binsfeld Date: Wed, 13 Aug 2025 11:02:33 +0200 Subject: [PATCH 2/3] [MIG] statechart 18.0: make it possible to ignore some events in the has_allowed_event compute From https://github.com/acsone/scobidoo/pull/47 --- test_statechart/tests/test_basic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_statechart/tests/test_basic.py b/test_statechart/tests/test_basic.py index b57b2a0..aac7fe6 100644 --- a/test_statechart/tests/test_basic.py +++ b/test_statechart/tests/test_basic.py @@ -50,7 +50,7 @@ def test_get_sc_event_allowed_field_names(self): self.assertEqual(record.sc_has_allowed_events, True) # 1 event is allowed: confirmed2 - record.invalidate_cache() + record.invalidate_recordset() self.assertEqual( record.with_context( ignore_for_has_allowed_events=["cancel"] @@ -59,7 +59,7 @@ def test_get_sc_event_allowed_field_names(self): ) # no event allowed - record.invalidate_cache() + record.invalidate_recordset() self.assertEqual( record.with_context( ignore_for_has_allowed_events=["cancel", "confirm2"] From 811d753fe96af1043770cae25c96e2c9e560049b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Wed, 13 Aug 2025 12:51:58 +0200 Subject: [PATCH 3/3] [IMP] handle ignore_for_has_allowed_events only in the compute method There is no need to leak this context handling to _get_sc_event_allowed_field_names, where this can be handled with a new argument. --- statechart/models/statechart_mixin.py | 14 +++++--------- test_statechart/tests/test_basic.py | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/statechart/models/statechart_mixin.py b/statechart/models/statechart_mixin.py index 3d0bebc..8e68b5c 100644 --- a/statechart/models/statechart_mixin.py +++ b/statechart/models/statechart_mixin.py @@ -330,20 +330,16 @@ class can override the statechart with another one adding new events, return res @api.model - def _get_sc_event_allowed_field_names(self): - ignore_for_has_allowed_events = self.env.context.get( - "ignore_for_has_allowed_events", [] - ) - event_names = self._statechart.events_for() + def _get_sc_event_allowed_field_names(self, events_to_ignore=None): + event_names = set(self._statechart.events_for()) - set(events_to_ignore or []) return [ - _sc_make_event_allowed_field_name(event_name) - for event_name in event_names - if event_name not in ignore_for_has_allowed_events + _sc_make_event_allowed_field_name(event_name) for event_name in event_names ] @api.depends("sc_state") def _compute_sc_has_allowed_events(self): - sc_fields = self._get_sc_event_allowed_field_names() + events_to_ignore = self.env.context.get("ignore_for_has_allowed_events") + sc_fields = self._get_sc_event_allowed_field_names(events_to_ignore) for rec in self: rec.sc_has_allowed_events = any([rec[f] for f in sc_fields]) diff --git a/test_statechart/tests/test_basic.py b/test_statechart/tests/test_basic.py index aac7fe6..56adcd7 100644 --- a/test_statechart/tests/test_basic.py +++ b/test_statechart/tests/test_basic.py @@ -36,7 +36,7 @@ def test_automatic_transition_on_create(self): # very small amount, step 1 and 2 done automatically self.assertScState(record.sc_state, ["confirmed2", "root"]) - def test_get_sc_event_allowed_field_names(self): + def test_get_sc_sc_has_allowed_events(self): """ Test that we can ignore certain events based on a context key (ignore_for_has_allowed_events)