From 8df03f857dca6b885d643cd50f676240634eb5b6 Mon Sep 17 00:00:00 2001 From: yuqei Date: Sat, 16 May 2026 13:18:39 +0800 Subject: [PATCH] fix: delete governance versions before parent rows --- .../contract_template_version_repository.py | 11 +++++++++++ .../repositories/review_rule_version_repository.py | 11 +++++++++++ backend/app/services/review_rule_service.py | 1 + backend/app/services/template_service.py | 2 ++ backend/tests/test_review_rule_service.py | 2 ++ backend/tests/test_template_service.py | 8 ++++++++ 6 files changed, 35 insertions(+) diff --git a/backend/app/repositories/contract_template_version_repository.py b/backend/app/repositories/contract_template_version_repository.py index dc584296..c8b4aa8b 100644 --- a/backend/app/repositories/contract_template_version_repository.py +++ b/backend/app/repositories/contract_template_version_repository.py @@ -48,3 +48,14 @@ class ContractTemplateVersionRepository: .update({"is_current": False}, synchronize_session=False) ) self.db.commit() + + def delete_by_template_id(self, tenant_id: str, template_id: str) -> None: + ( + self.db.query(ContractTemplateVersion) + .filter( + ContractTemplateVersion.tenant_id == tenant_id, + ContractTemplateVersion.template_id == template_id, + ) + .delete(synchronize_session=False) + ) + self.db.commit() diff --git a/backend/app/repositories/review_rule_version_repository.py b/backend/app/repositories/review_rule_version_repository.py index 6446a970..ccdf836f 100644 --- a/backend/app/repositories/review_rule_version_repository.py +++ b/backend/app/repositories/review_rule_version_repository.py @@ -39,6 +39,17 @@ class ReviewRuleVersionRepository: item.is_current = False self.db.commit() + def delete_by_rule_id(self, tenant_id: str, rule_id: str) -> None: + ( + self.db.query(ReviewRuleVersion) + .filter( + ReviewRuleVersion.tenant_id == tenant_id, + ReviewRuleVersion.rule_id == rule_id, + ) + .delete(synchronize_session=False) + ) + self.db.commit() + def get_by_version_label(self, tenant_id: str, rule_id: str, version_label: str) -> Optional[ReviewRuleVersion]: return ( self.db.query(ReviewRuleVersion) diff --git a/backend/app/services/review_rule_service.py b/backend/app/services/review_rule_service.py index 09442463..3c880096 100644 --- a/backend/app/services/review_rule_service.py +++ b/backend/app/services/review_rule_service.py @@ -159,6 +159,7 @@ class ReviewRuleService: self._require_admin(current_user) rule = self._require_rule(current_user, rule_id) deleted_item = self._to_item(rule) + self.version_repository.delete_by_rule_id(current_user["tenant_id"], rule_id) self.repository.delete(rule_id) return deleted_item diff --git a/backend/app/services/template_service.py b/backend/app/services/template_service.py index bc5fed1a..62d80d1a 100644 --- a/backend/app/services/template_service.py +++ b/backend/app/services/template_service.py @@ -258,8 +258,10 @@ class TemplateService: def delete_template(self, current_user: Dict[str, Any], template_id: str) -> dict: self._require_admin(current_user) repository = self._require_repository() + version_repository = self._require_version_repository() contract_template = self._require_template(current_user, template_id) template_data = self._to_item(contract_template) + version_repository.delete_by_template_id(current_user["tenant_id"], template_id) repository.delete(contract_template) return template_data diff --git a/backend/tests/test_review_rule_service.py b/backend/tests/test_review_rule_service.py index 33858e1e..4e39dbf4 100644 --- a/backend/tests/test_review_rule_service.py +++ b/backend/tests/test_review_rule_service.py @@ -297,6 +297,7 @@ class ReviewRuleServiceTestCase(unittest.TestCase): # Mock repository methods self.service.repository.get_by_id = Mock(return_value=mock_existing_rule) self.service.repository.delete = Mock() + self.service.version_repository.delete_by_rule_id = Mock() # Call method result = self.service.delete_rule( @@ -308,6 +309,7 @@ class ReviewRuleServiceTestCase(unittest.TestCase): self.assertEqual(result["id"], "rule-123") self.assertEqual(result["name"], "自动续约预警") # Verify delete was called + self.service.version_repository.delete_by_rule_id.assert_called_once_with("tenant-demo-001", "rule-123") self.service.repository.delete.assert_called_once_with("rule-123") def test_delete_rule_not_found(self): diff --git a/backend/tests/test_template_service.py b/backend/tests/test_template_service.py index 5df51ad7..7defaa37 100644 --- a/backend/tests/test_template_service.py +++ b/backend/tests/test_template_service.py @@ -74,6 +74,13 @@ class StubVersionRepository: if item.tenant_id == tenant_id and item.template_id == template_id: item.is_current = False + def delete_by_template_id(self, tenant_id, template_id): + self.items = [ + item + for item in self.items + if not (item.tenant_id == tenant_id and item.template_id == template_id) + ] + class StubGovernanceAsset: def __init__(self, asset_id: str, production_status: str = "ready"): @@ -179,6 +186,7 @@ class TemplateServiceTestCase(unittest.TestCase): self.assertEqual(listed["total"], 0) self.assertEqual(listed["items"], []) + self.assertEqual(self.service.version_repository.list_by_template_id(self.current_user["tenant_id"], created["id"]), []) def test_member_cannot_manage_templates(self): with self.assertRaises(HTTPException) as context: