ASK-20260924-15/17: Bot 通道缺省账套→400 + 差异/趋势入口期间口径回落

- deps.get_entity_id: Bot 通道(带 X-BOT-KEY)无显式账套 → 400(旧为兜底 entity 1=酣客);
  无 key 的存量公开/用户端点行为不变(仍 401/兜底 1)
- 新增 deps.require_bot_entity_id():写端点缺省账套一处收口 → 400(406/422 同族)
  接入 bot_bridge(×2) / bot_bridge_v2 / bot_suggestions / cash_vouchers_json,并同步文档口径
- deviation_engine.run_deviation_check: period=None 不再硬编码当月,逐 KPI 回落
  「该 KPI 自己的最近可用期间」(裁定2b,单一实现收口到 alert_entity_scope);(当月无
  kpi_values ⇒ 差异/趋势入口永久 0 新增);R2/R3 窗口判定改为逐 KPI;显式 period 语义不变
- alert_generator.resolve_latest_period 委托同一实现(消除期间口径两份)
- 测试:新增 tests/test_ask15_17_engine_and_entity_required_20260925.py(12 例);
  4 个既有测试文件把「旧兜底账套 1」显式化(断言未改)
This commit is contained in:
wecom-fullstack
2026-09-25 22:42:25 +08:00
parent 38787a006f
commit 52b693ddbb
13 changed files with 353 additions and 43 deletions
+13 -5
View File
@@ -29,7 +29,9 @@
—— period 是 voucher_date 派生属性,**不进幂等键**(2026-09-11 加固:日期口径
在 summary 派生/主表 VoucherDate 之间切换时,含 period 会判重失效导致重复入库)。
命中既有行即跳过;仅当命中行 period 与新行不一致时计入 period_conflict 留痕(不覆盖)。
7. entity_id:默认 1(陕西酣客,source=zxt-sxzxb20210228),Bot 通道可传 X-Entity-Id 或 body entity_id。
7. entity_id:**必传**(ASK-20260924-17,任总 2026-09-24 放行)——body `entity_id` 或
header `X-Entity-Id`(1=陕西酣客、2=陕西博海);**缺省 → 400**,
不再兜底默认账套 1(原口径:默认 1 陕西酣客,source=zxt-sxzxb20210228)。
8. 入库后不触发现金流/ledger 联动(凭证完整性未证实前不作为权威来源,见财务口径警示);
也不影响 Excel multipart 导入(原端点不动)。
"""
@@ -45,7 +47,7 @@ from sqlalchemy import text as sa_text
from sqlalchemy.orm import Session
from app.database import get_db
from app.deps import resolve_entity_for_request
from app.deps import resolve_entity_for_request, require_bot_entity_id
from app.models import Entity, ImportLog, VoucherDetail
from app.api.bot_bridge import verify_bot_key
@@ -225,12 +227,18 @@ def api_import_vouchers_json(
nr["CwAccountID"] = v
norm_rows.append(nr)
# ── entity 解析 + active 校验 ──
entity_id = resolve_entity_for_request(request, req_entity if req_entity not in (None, "") else 1)
# ── entity 解析 + active 校验(ASK-20260924-17:Bot 通道必须显式传账套)──
entity_id = resolve_entity_for_request(
request,
require_bot_entity_id(
{"entity_id": req_entity if req_entity not in (None, "") else request.headers.get("X-Entity-Id")},
source="cash_vouchers_json.import/vouchers-json",
),
)
try:
entity_id = int(entity_id)
except Exception:
entity_id = 1
raise HTTPException(422, f"entity_id 无效: {entity_id!r}")
if not _entity_active(db, entity_id):
raise HTTPException(403, f"企业ID={entity_id} 不存在或未激活")