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]])
|
@self.router.get("/bindings", response_model=Result[list[RuleBindingVO]])
|
||||||
async def ListBindings(ruleType: str | None = None):
|
async def ListBindings(ruleType: str | None = None, region: str | None = None):
|
||||||
"""列出规则类型绑定。可按规则类型过滤。"""
|
"""列出规则类型绑定。可按规则类型/地区过滤。"""
|
||||||
Data = await self.RuleService.ListBindings(RuleType=ruleType)
|
Data = await self.RuleService.ListBindings(RuleType=ruleType, Region=region)
|
||||||
return Result.success(data=Data)
|
return Result.success(data=Data)
|
||||||
|
|
||||||
@self.router.post("/{RuleType}/bindings", response_model=Result[RuleBindingVO])
|
@self.router.post("/{RuleType}/bindings", response_model=Result[RuleBindingVO])
|
||||||
@@ -100,6 +100,7 @@ class RuleController(BaseController):
|
|||||||
Data = await self.RuleService.CreateBinding(
|
Data = await self.RuleService.CreateBinding(
|
||||||
DocTypeId=body.docTypeId,
|
DocTypeId=body.docTypeId,
|
||||||
RuleSetId=body.ruleSetId,
|
RuleSetId=body.ruleSetId,
|
||||||
|
Region=body.region,
|
||||||
BindingMode=body.bindingMode,
|
BindingMode=body.bindingMode,
|
||||||
Priority=body.priority,
|
Priority=body.priority,
|
||||||
DocTypeCode=body.docTypeCode,
|
DocTypeCode=body.docTypeCode,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class RuleBindingCreateDTO(BaseModel):
|
|||||||
docTypeId: int = Field(..., description="文档类型ID → leaudit_document_types.id")
|
docTypeId: int = Field(..., description="文档类型ID → leaudit_document_types.id")
|
||||||
docTypeCode: str | None = Field(None, description="文档类型编码(冗余快速匹配)")
|
docTypeCode: str | None = Field(None, description="文档类型编码(冗余快速匹配)")
|
||||||
ruleSetId: int = Field(..., description="规则集ID → leaudit_rule_sets.id")
|
ruleSetId: int = Field(..., description="规则集ID → leaudit_rule_sets.id")
|
||||||
|
region: str = Field("default", description="适用地区")
|
||||||
bindingMode: str = Field("explicit", description="绑定模式: explicit / wildcard / fallback")
|
bindingMode: str = Field("explicit", description="绑定模式: explicit / wildcard / fallback")
|
||||||
priority: int = Field(0, description="优先级(数值越大优先级越高)")
|
priority: int = Field(0, description="优先级(数值越大优先级越高)")
|
||||||
note: str | None = Field(None, description="备注说明")
|
note: str | None = Field(None, description="备注说明")
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class LeauditDocument(BaseModel):
|
|||||||
typeId: Mapped[int | None] = mapped_column(BigInteger, comment="文档类型ID")
|
typeId: Mapped[int | None] = mapped_column(BigInteger, comment="文档类型ID")
|
||||||
processingStatus: Mapped[str | None] = mapped_column(String(64), default="waiting", comment="waiting/processing/completed/failed")
|
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")
|
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
|
@classmethod
|
||||||
async def get_by_biz_id(cls, session: AsyncSession, bizDocumentId: int) -> "LeauditDocument | None":
|
async def get_by_biz_id(cls, session: AsyncSession, bizDocumentId: int) -> "LeauditDocument | None":
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from fastapi_admin.config import APP_REGION
|
|
||||||
from fastapi_common.fastapi_common_logger import logger
|
from fastapi_common.fastapi_common_logger import logger
|
||||||
from fastapi_common.fastapi_common_sqlalchemy.database import GetAsyncSession
|
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.domain.responses import StatusCodeEnum
|
||||||
@@ -78,7 +77,7 @@ class AuditServiceImpl(IAuditService):
|
|||||||
LIMIT 1
|
LIMIT 1
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
{"doc_type_id": document.typeId, "region": APP_REGION},
|
{"doc_type_id": document.typeId, "region": document.region},
|
||||||
)
|
)
|
||||||
binding = bindingResult.mappings().first()
|
binding = bindingResult.mappings().first()
|
||||||
if not binding or not binding["rule_set_id"] or not binding["rule_version_id"]:
|
if not binding or not binding["rule_set_id"] or not binding["rule_version_id"]:
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
from fastapi_admin.config import APP_REGION
|
|
||||||
from fastapi_common.fastapi_common_sqlalchemy.database import GetAsyncSession
|
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.domain.responses import StatusCodeEnum
|
||||||
from fastapi_common.fastapi_common_web.exception.LeauditException import LeauditException
|
from fastapi_common.fastapi_common_web.exception.LeauditException import LeauditException
|
||||||
@@ -341,10 +340,11 @@ class RuleServiceImpl(IRuleService):
|
|||||||
Rollback=True,
|
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:
|
async with GetAsyncSession() as Session:
|
||||||
if RuleType:
|
if RuleType and region:
|
||||||
Result = await Session.execute(
|
Result = await Session.execute(
|
||||||
text(
|
text(
|
||||||
"""
|
"""
|
||||||
@@ -367,9 +367,9 @@ class RuleServiceImpl(IRuleService):
|
|||||||
ORDER BY b.priority DESC, b.id DESC
|
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(
|
Result = await Session.execute(
|
||||||
text(
|
text(
|
||||||
"""
|
"""
|
||||||
@@ -391,7 +391,53 @@ class RuleServiceImpl(IRuleService):
|
|||||||
ORDER BY rs.rule_type, b.priority DESC, b.id DESC
|
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 [
|
return [
|
||||||
RuleBindingVO(
|
RuleBindingVO(
|
||||||
@@ -413,6 +459,7 @@ class RuleServiceImpl(IRuleService):
|
|||||||
self,
|
self,
|
||||||
DocTypeId: int,
|
DocTypeId: int,
|
||||||
RuleSetId: int,
|
RuleSetId: int,
|
||||||
|
Region: str = "default",
|
||||||
BindingMode: str = "explicit",
|
BindingMode: str = "explicit",
|
||||||
Priority: int = 0,
|
Priority: int = 0,
|
||||||
DocTypeCode: str | None = None,
|
DocTypeCode: str | None = None,
|
||||||
@@ -473,7 +520,7 @@ class RuleServiceImpl(IRuleService):
|
|||||||
"rule_set_id": RuleSetId,
|
"rule_set_id": RuleSetId,
|
||||||
"binding_mode": BindingMode,
|
"binding_mode": BindingMode,
|
||||||
"priority": Priority,
|
"priority": Priority,
|
||||||
"region": APP_REGION,
|
"region": Region,
|
||||||
"note": Note,
|
"note": Note,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ class IRuleService(ABC):
|
|||||||
...
|
...
|
||||||
|
|
||||||
@abstractmethod
|
@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
|
@abstractmethod
|
||||||
@@ -75,6 +75,7 @@ class IRuleService(ABC):
|
|||||||
self,
|
self,
|
||||||
DocTypeId: int,
|
DocTypeId: int,
|
||||||
RuleSetId: int,
|
RuleSetId: int,
|
||||||
|
Region: str = "default",
|
||||||
BindingMode: str = "explicit",
|
BindingMode: str = "explicit",
|
||||||
Priority: int = 0,
|
Priority: int = 0,
|
||||||
DocTypeCode: str | None = None,
|
DocTypeCode: str | None = None,
|
||||||
|
|||||||
Reference in New Issue
Block a user