refactor: region from document, not app config
- Add region column to leaudit_documents + LeauditDocument model - AuditServiceImpl: read region from document.region, not APP_REGION - RuleServiceImpl: ListBindings/CreateBinding accept Region parameter - RuleBindingCreateDTO: add region field - RuleController: pass region from query param/DTO to service - APP_REGION removed from binding queries; region flows from document Region is now per-document: each document carries its region at upload time, and rules are matched to the document's region at run time.
This commit is contained in:
@@ -89,9 +89,9 @@ class RuleController(BaseController):
|
||||
# ── 规则类型绑定 ──────────────────────────────────────────
|
||||
|
||||
@self.router.get("/bindings", response_model=Result[list[RuleBindingVO]])
|
||||
async def ListBindings(ruleType: str | None = None):
|
||||
"""列出规则类型绑定。可按规则类型过滤。"""
|
||||
Data = await self.RuleService.ListBindings(RuleType=ruleType)
|
||||
async def ListBindings(ruleType: str | None = None, region: str | None = None):
|
||||
"""列出规则类型绑定。可按规则类型/地区过滤。"""
|
||||
Data = await self.RuleService.ListBindings(RuleType=ruleType, Region=region)
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.post("/{RuleType}/bindings", response_model=Result[RuleBindingVO])
|
||||
@@ -100,6 +100,7 @@ class RuleController(BaseController):
|
||||
Data = await self.RuleService.CreateBinding(
|
||||
DocTypeId=body.docTypeId,
|
||||
RuleSetId=body.ruleSetId,
|
||||
Region=body.region,
|
||||
BindingMode=body.bindingMode,
|
||||
Priority=body.priority,
|
||||
DocTypeCode=body.docTypeCode,
|
||||
|
||||
@@ -9,6 +9,7 @@ class RuleBindingCreateDTO(BaseModel):
|
||||
docTypeId: int = Field(..., description="文档类型ID → leaudit_document_types.id")
|
||||
docTypeCode: str | None = Field(None, description="文档类型编码(冗余快速匹配)")
|
||||
ruleSetId: int = Field(..., description="规则集ID → leaudit_rule_sets.id")
|
||||
region: str = Field("default", description="适用地区")
|
||||
bindingMode: str = Field("explicit", description="绑定模式: explicit / wildcard / fallback")
|
||||
priority: int = Field(0, description="优先级(数值越大优先级越高)")
|
||||
note: str | None = Field(None, description="备注说明")
|
||||
|
||||
@@ -22,6 +22,7 @@ class LeauditDocument(BaseModel):
|
||||
typeId: Mapped[int | None] = mapped_column(BigInteger, comment="文档类型ID")
|
||||
processingStatus: Mapped[str | None] = mapped_column(String(64), default="waiting", comment="waiting/processing/completed/failed")
|
||||
currentRunId: Mapped[int | None] = mapped_column(BigInteger, comment="最新有效 run id")
|
||||
region: Mapped[str] = mapped_column(String(32), default="default", comment="所属地区: mz/yf/jy/cz/default")
|
||||
|
||||
@classmethod
|
||||
async def get_by_biz_id(cls, session: AsyncSession, bizDocumentId: int) -> "LeauditDocument | None":
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
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
|
||||
@@ -78,7 +77,7 @@ class AuditServiceImpl(IAuditService):
|
||||
LIMIT 1
|
||||
"""
|
||||
),
|
||||
{"doc_type_id": document.typeId, "region": APP_REGION},
|
||||
{"doc_type_id": document.typeId, "region": document.region},
|
||||
)
|
||||
binding = bindingResult.mappings().first()
|
||||
if not binding or not binding["rule_set_id"] or not binding["rule_version_id"]:
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
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
|
||||
@@ -341,10 +340,11 @@ class RuleServiceImpl(IRuleService):
|
||||
Rollback=True,
|
||||
)
|
||||
|
||||
async def ListBindings(self, RuleType: str | None = None) -> list[RuleBindingVO]:
|
||||
"""列出规则类型绑定,可按规则类型过滤。"""
|
||||
async def ListBindings(self, RuleType: str | None = None, Region: str | None = None) -> list[RuleBindingVO]:
|
||||
"""列出规则类型绑定,可按规则类型/地区过滤。"""
|
||||
region = Region or ""
|
||||
async with GetAsyncSession() as Session:
|
||||
if RuleType:
|
||||
if RuleType and region:
|
||||
Result = await Session.execute(
|
||||
text(
|
||||
"""
|
||||
@@ -367,9 +367,9 @@ class RuleServiceImpl(IRuleService):
|
||||
ORDER BY b.priority DESC, b.id DESC
|
||||
"""
|
||||
),
|
||||
{"rule_type": RuleType, "region": APP_REGION},
|
||||
{"rule_type": RuleType, "region": region},
|
||||
)
|
||||
else:
|
||||
elif region:
|
||||
Result = await Session.execute(
|
||||
text(
|
||||
"""
|
||||
@@ -391,7 +391,53 @@ class RuleServiceImpl(IRuleService):
|
||||
ORDER BY rs.rule_type, b.priority DESC, b.id DESC
|
||||
"""
|
||||
),
|
||||
{"region": APP_REGION},
|
||||
{"region": region},
|
||||
)
|
||||
elif RuleType:
|
||||
Result = await Session.execute(
|
||||
text(
|
||||
"""
|
||||
SELECT
|
||||
b.id,
|
||||
b.doc_type_id,
|
||||
b.doc_type_code,
|
||||
b.rule_set_id,
|
||||
b.binding_mode,
|
||||
b.priority,
|
||||
b.is_active,
|
||||
b.note,
|
||||
rs.rule_type,
|
||||
rs.rule_name
|
||||
FROM leaudit_rule_type_bindings b
|
||||
JOIN leaudit_rule_sets rs ON rs.id = b.rule_set_id
|
||||
WHERE rs.rule_type = :rule_type
|
||||
AND rs.deleted_at IS NULL
|
||||
ORDER BY b.priority DESC, b.id DESC
|
||||
"""
|
||||
),
|
||||
{"rule_type": RuleType},
|
||||
)
|
||||
else:
|
||||
Result = await Session.execute(
|
||||
text(
|
||||
"""
|
||||
SELECT
|
||||
b.id,
|
||||
b.doc_type_id,
|
||||
b.doc_type_code,
|
||||
b.rule_set_id,
|
||||
b.binding_mode,
|
||||
b.priority,
|
||||
b.is_active,
|
||||
b.note,
|
||||
rs.rule_type,
|
||||
rs.rule_name
|
||||
FROM leaudit_rule_type_bindings b
|
||||
JOIN leaudit_rule_sets rs ON rs.id = b.rule_set_id
|
||||
WHERE rs.deleted_at IS NULL
|
||||
ORDER BY rs.rule_type, b.priority DESC, b.id DESC
|
||||
"""
|
||||
),
|
||||
)
|
||||
return [
|
||||
RuleBindingVO(
|
||||
@@ -413,6 +459,7 @@ class RuleServiceImpl(IRuleService):
|
||||
self,
|
||||
DocTypeId: int,
|
||||
RuleSetId: int,
|
||||
Region: str = "default",
|
||||
BindingMode: str = "explicit",
|
||||
Priority: int = 0,
|
||||
DocTypeCode: str | None = None,
|
||||
@@ -473,7 +520,7 @@ class RuleServiceImpl(IRuleService):
|
||||
"rule_set_id": RuleSetId,
|
||||
"binding_mode": BindingMode,
|
||||
"priority": Priority,
|
||||
"region": APP_REGION,
|
||||
"region": Region,
|
||||
"note": Note,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -66,8 +66,8 @@ class IRuleService(ABC):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
async def ListBindings(self, RuleType: str | None = None) -> list[RuleBindingVO]:
|
||||
"""列出规则类型绑定。可按规则类型过滤。"""
|
||||
async def ListBindings(self, RuleType: str | None = None, Region: str | None = None) -> list[RuleBindingVO]:
|
||||
"""列出规则类型绑定。可按规则类型/地区过滤。"""
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
@@ -75,6 +75,7 @@ class IRuleService(ABC):
|
||||
self,
|
||||
DocTypeId: int,
|
||||
RuleSetId: int,
|
||||
Region: str = "default",
|
||||
BindingMode: str = "explicit",
|
||||
Priority: int = 0,
|
||||
DocTypeCode: str | None = None,
|
||||
|
||||
Reference in New Issue
Block a user