From 2d6d31c48d2801d1e6ee1268fcd2c0589dc249e6 Mon Sep 17 00:00:00 2001 From: Saran440 Date: Thu, 21 Aug 2025 17:50:02 +0700 Subject: [PATCH] [FIX] base_tier_validation: approve by pass sequence continue only --- base_tier_validation/__manifest__.py | 2 +- .../models/tier_validation.py | 14 +++- .../tests/test_tier_validation.py | 66 +++++++++++++++++-- 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/base_tier_validation/__manifest__.py b/base_tier_validation/__manifest__.py index 3d2ad910..e826d37b 100644 --- a/base_tier_validation/__manifest__.py +++ b/base_tier_validation/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Base Tier Validation", "summary": "Implement a validation process based on tiers.", - "version": "19.0.1.0.2", + "version": "19.0.1.0.3", "development_status": "Mature", "maintainers": ["LoisRForgeFlow"], "category": "Tools", diff --git a/base_tier_validation/models/tier_validation.py b/base_tier_validation/models/tier_validation.py index 29896f80..2356fc85 100644 --- a/base_tier_validation/models/tier_validation.py +++ b/base_tier_validation/models/tier_validation.py @@ -531,9 +531,19 @@ def _validate_tier(self, tiers=False): } ) - user_reviews = tier_reviews.filtered( - lambda r: r.status == "pending" and (self.env.user in r.reviewer_ids) + # Only approve consecutive pending reviews (by sequence) for the + # current user. Stop at the first review not assigned to the user, + # so intermediate reviewers are not skipped. + sorted_pending = tier_reviews.filtered(lambda r: r.status == "pending").sorted( + "sequence" ) + user_reviews = self.env["tier.review"] + for review in sorted_pending: + if self.env.user in review.reviewer_ids: + user_reviews |= review + else: + break + user_reviews.write( { "status": "approved", diff --git a/base_tier_validation/tests/test_tier_validation.py b/base_tier_validation/tests/test_tier_validation.py index 344004fd..01fcffaf 100644 --- a/base_tier_validation/tests/test_tier_validation.py +++ b/base_tier_validation/tests/test_tier_validation.py @@ -365,10 +365,26 @@ def test_12_approve_sequence_same_user(self): def test_12_approve_sequence_same_user_bypassed(self): """Similar to test_12_approve_sequence, with all same users, - but approve_sequence_bypass is True""" + but approve_sequence_bypass is True + Sequence of reviewers: A, A, B, A. + When A validates, it should only validate the first two (A, A) and stop at B. + """ # Create new test record test_record = self.test_model.create({"test_field": 2.5}) # Create tier definitions + # sequence 40 (User 1) + self.tier_def_obj.create( + { + "model_id": self.tester_model.id, + "review_type": "individual", + "reviewer_id": self.test_user_1.id, + "definition_domain": "[('test_field', '>', 1.0)]", + "approve_sequence": True, + "approve_sequence_bypass": True, + "sequence": 40, + } + ) + # sequence 30 (User 1) self.tier_def_obj.create( { "model_id": self.tester_model.id, @@ -377,9 +393,22 @@ def test_12_approve_sequence_same_user_bypassed(self): "definition_domain": "[('test_field', '>', 1.0)]", "approve_sequence": True, "approve_sequence_bypass": True, + "sequence": 30, + } + ) + # sequence 20 (User 2) + self.tier_def_obj.create( + { + "model_id": self.tester_model.id, + "review_type": "individual", + "reviewer_id": self.test_user_2.id, + "definition_domain": "[('test_field', '>', 1.0)]", + "approve_sequence": True, + "approve_sequence_bypass": True, "sequence": 20, } ) + # sequence 10 (User 1) self.tier_def_obj.create( { "model_id": self.tester_model.id, @@ -399,16 +428,18 @@ def test_12_approve_sequence_same_user_bypassed(self): record1 = test_record.with_user(self.test_user_1.id) self.assertTrue(record1.can_review) # When the first tier is validated, all the rest will be approved. - self.assertEqual(len(record1.review_ids), 2) + self.assertEqual(len(record1.review_ids), 4) self.assertEqual( - 1, len(record1.review_ids.filtered(lambda x: x.status == "waiting")) + 3, len(record1.review_ids.filtered(lambda x: x.status == "waiting")) ) self.assertEqual( 1, len(record1.review_ids.filtered(lambda x: x.status == "pending")) ) record1.validate_tier() + # After user 1 validates, they should have approved exactly 2 tiers: 40 and 30 + # 20 and 10 should be pending. self.assertEqual( - 0, len(record1.review_ids.filtered(lambda x: x.status == "pending")) + 2, len(record1.review_ids.filtered(lambda x: x.status == "pending")) ) self.assertEqual( 0, len(record1.review_ids.filtered(lambda x: x.status == "waiting")) @@ -416,6 +447,33 @@ def test_12_approve_sequence_same_user_bypassed(self): self.assertEqual( 2, len(record1.review_ids.filtered(lambda x: x.status == "approved")) ) + self.assertFalse(record1.can_review) + # User 2 validates. + record2 = test_record.with_user(self.test_user_2.id) + self.assertTrue(record2.can_review) + record2.validate_tier() + self.assertEqual( + 1, len(record1.review_ids.filtered(lambda x: x.status == "pending")) + ) + self.assertEqual( + 0, len(record1.review_ids.filtered(lambda x: x.status == "waiting")) + ) + self.assertEqual( + 3, len(record1.review_ids.filtered(lambda x: x.status == "approved")) + ) + # User 1 validates the final tier. + self.assertTrue(record1.can_review) + record1.validate_tier() + self.assertEqual( + 0, len(record1.review_ids.filtered(lambda x: x.status == "pending")) + ) + self.assertEqual( + 0, len(record1.review_ids.filtered(lambda x: x.status == "waiting")) + ) + self.assertEqual( + 4, len(record1.review_ids.filtered(lambda x: x.status == "approved")) + ) + self.assertEqual(record1.validation_status, "validated") def test_13_onchange_review_type(self): tier_def_id = self.tier_def_obj.create(