feat: multi-region rule isolation — region column + config + queries
- DB: add region column to leaudit_rule_sets + leaudit_rule_type_bindings - DB: change UNIQUE constraint from (rule_type) to (rule_type, region) - Config: add APP_REGION to app.toml + AppSettings + __init__.pyi - AuditServiceImpl: filter bindings by APP_REGION - RuleServiceImpl: ListBindings/CreateBinding use APP_REGION - Seed script: accept --region arg, tag rules by region - OssPathUtils: BuildRuleYamlKey already accepts Region parameter Each region can now have its own independent copy of the same rule_type, stored in separate OSS paths and DB rows, keyed by region.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi_admin.config import APP_REGION
|
||||
from fastapi_common.fastapi_common_logger import logger
|
||||
from fastapi_common.fastapi_common_sqlalchemy.database import GetAsyncSession
|
||||
from fastapi_common.fastapi_common_web.domain.responses import StatusCodeEnum
|
||||
@@ -72,11 +73,12 @@ class AuditServiceImpl(IAuditService):
|
||||
LEFT JOIN leaudit_rule_versions rv ON rv.id = rs.current_version_id
|
||||
WHERE b.doc_type_id = :doc_type_id
|
||||
AND b.is_active = true
|
||||
AND b.region = :region
|
||||
ORDER BY b.priority DESC, b.id DESC
|
||||
LIMIT 1
|
||||
"""
|
||||
),
|
||||
{"doc_type_id": document.typeId},
|
||||
{"doc_type_id": document.typeId, "region": APP_REGION},
|
||||
)
|
||||
binding = bindingResult.mappings().first()
|
||||
if not binding or not binding["rule_set_id"] or not binding["rule_version_id"]:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from fastapi_admin.config import APP_REGION
|
||||
from fastapi_common.fastapi_common_sqlalchemy.database import GetAsyncSession
|
||||
from fastapi_common.fastapi_common_web.domain.responses import StatusCodeEnum
|
||||
from fastapi_common.fastapi_common_web.exception.LeauditException import LeauditException
|
||||
@@ -362,10 +363,11 @@ class RuleServiceImpl(IRuleService):
|
||||
JOIN leaudit_rule_sets rs ON rs.id = b.rule_set_id
|
||||
WHERE rs.rule_type = :rule_type
|
||||
AND rs.deleted_at IS NULL
|
||||
AND b.region = :region
|
||||
ORDER BY b.priority DESC, b.id DESC
|
||||
"""
|
||||
),
|
||||
{"rule_type": RuleType},
|
||||
{"rule_type": RuleType, "region": APP_REGION},
|
||||
)
|
||||
else:
|
||||
Result = await Session.execute(
|
||||
@@ -385,9 +387,11 @@ class RuleServiceImpl(IRuleService):
|
||||
FROM leaudit_rule_type_bindings b
|
||||
JOIN leaudit_rule_sets rs ON rs.id = b.rule_set_id
|
||||
WHERE rs.deleted_at IS NULL
|
||||
AND b.region = :region
|
||||
ORDER BY rs.rule_type, b.priority DESC, b.id DESC
|
||||
"""
|
||||
),
|
||||
{"region": APP_REGION},
|
||||
)
|
||||
return [
|
||||
RuleBindingVO(
|
||||
@@ -447,6 +451,7 @@ class RuleServiceImpl(IRuleService):
|
||||
binding_mode,
|
||||
priority,
|
||||
is_active,
|
||||
region,
|
||||
note
|
||||
) VALUES (
|
||||
:doc_type_id,
|
||||
@@ -455,10 +460,11 @@ class RuleServiceImpl(IRuleService):
|
||||
:binding_mode,
|
||||
:priority,
|
||||
true,
|
||||
:region,
|
||||
:note
|
||||
)
|
||||
RETURNING id, doc_type_id, doc_type_code, rule_set_id,
|
||||
binding_mode, priority, is_active, note
|
||||
binding_mode, priority, is_active, region, note
|
||||
"""
|
||||
),
|
||||
{
|
||||
@@ -467,6 +473,7 @@ class RuleServiceImpl(IRuleService):
|
||||
"rule_set_id": RuleSetId,
|
||||
"binding_mode": BindingMode,
|
||||
"priority": Priority,
|
||||
"region": APP_REGION,
|
||||
"note": Note,
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user