55 lines
1.9 KiB
Python
55 lines
1.9 KiB
Python
"""规则域租户作用域解析工具。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable, Mapping
|
|
from typing import Any
|
|
|
|
|
|
def normalize_scoped_tenant_code(value: str | None, default: str = "PROVINCIAL") -> str:
|
|
"""标准化规则域作用域租户编码。"""
|
|
normalized = str(value or "").strip().upper()
|
|
return normalized or default
|
|
|
|
|
|
def candidate_scope_tenant_codes(tenant_code: str | None) -> list[str]:
|
|
"""返回规则域作用域命中顺序: TENANT -> PUBLIC -> PROVINCIAL。
|
|
|
|
PUBLIC 是新的平台级模板源;PROVINCIAL 仅作为历史兼容兜底。
|
|
"""
|
|
normalized = normalize_scoped_tenant_code(tenant_code)
|
|
candidates: list[str] = []
|
|
if normalized not in {"PROVINCIAL", "PUBLIC"}:
|
|
candidates.append(normalized)
|
|
candidates.append("PUBLIC")
|
|
if normalized != "PUBLIC":
|
|
candidates.append("PROVINCIAL")
|
|
return list(dict.fromkeys(candidates))
|
|
|
|
|
|
def pick_effective_scoped_row(
|
|
rows: Iterable[Mapping[str, Any]],
|
|
tenant_code: str | None,
|
|
*,
|
|
tenant_code_key: str = "tenant_code",
|
|
) -> Mapping[str, Any] | None:
|
|
"""按租户继承顺序挑选一条实际生效记录。"""
|
|
row_by_tenant: dict[str, Mapping[str, Any]] = {}
|
|
legacy_provincial_row: Mapping[str, Any] | None = None
|
|
|
|
for row in rows:
|
|
normalized = normalize_scoped_tenant_code(str(row.get(tenant_code_key) or ""), default="")
|
|
if not normalized:
|
|
if legacy_provincial_row is None:
|
|
legacy_provincial_row = row
|
|
continue
|
|
row_by_tenant.setdefault(normalized, row)
|
|
|
|
for candidate in candidate_scope_tenant_codes(tenant_code):
|
|
matched = row_by_tenant.get(candidate)
|
|
if matched is not None:
|
|
return matched
|
|
if candidate == "PROVINCIAL" and legacy_provincial_row is not None:
|
|
return legacy_provincial_row
|
|
return legacy_provincial_row
|