fix(T+): 补齐指导成本与读取服务保护
补充业务详情指导成本入口、来源版本和历史封存保护,接入月份锁并完善权限复核。 同步接入读取服务运行状态到页面,补充前端控制、回归测试和服务端只读连接授权校验。 定向隔离测试:89 项通过,1 条既有 Starlette 弃用警告。
这个提交包含在:
1 父节点
68e70fd6e2
当前提交
b8920c0d28
17 个文件已更改
+375
-47
没有与搜索条件相匹配的文件
@@ -64,9 +64,21 @@ def save_fact(session, payload, actor_id):
|
||||
try:
|
||||
with sync_lock(session):
|
||||
session.rollback()
|
||||
current = latest_facts(session, source).get((payload.kind, payload.fact_key))
|
||||
facts = latest_facts(session, source)
|
||||
current = facts.get((payload.kind, payload.fact_key))
|
||||
if payload.kind == "GUIDANCE" and current and current.data_json.get("is_finalized"):
|
||||
raise BadRequestError("该发货月份指导成本已封存,后续回款不得修改原指导成本")
|
||||
if payload.kind == "GUIDANCE":
|
||||
if payload.data.get("is_finalized"):
|
||||
raise BadRequestError("请在业务详情中核对来源并封存指导成本")
|
||||
if any(
|
||||
kind == "GUIDANCE"
|
||||
and fact.data_json.get("is_finalized")
|
||||
and fact.data_json.get("product_id") == payload.data.get("product_id")
|
||||
and fact.data_json.get("month") == payload.data.get("month")
|
||||
for (kind, _), fact in facts.items()
|
||||
):
|
||||
raise BadRequestError("该产品发货月份已有封存指导成本,请先核对")
|
||||
if (current.version if current else 0) != payload.expected_version:
|
||||
raise BadRequestError("补充资料已经变化,请刷新后再保存")
|
||||
fact = TPlusFact(
|
||||
@@ -452,11 +464,14 @@ def report_csv(session, run_no):
|
||||
return rows()
|
||||
|
||||
|
||||
def execute_next(session):
|
||||
def execute_next(session, *, may_claim=None):
|
||||
"""调用方持有原有全局锁;中断任务保留明细,禁止不明状态自动应用。"""
|
||||
for old in session.scalars(select(TPlusWorkRun).where(TPlusWorkRun.status == "RUNNING")):
|
||||
old.status, old.error_code, old.finished_at = "FAILED", "INTERRUPTED", datetime.now()
|
||||
session.commit()
|
||||
if may_claim is not None and not may_claim(session):
|
||||
session.rollback()
|
||||
return None
|
||||
run = session.scalar(
|
||||
select(TPlusWorkRun)
|
||||
.where(TPlusWorkRun.status == "QUEUED")
|
||||
|
||||
在新工单中引用
屏蔽一个用户