fix(qc-race): 末轮QC在办期间误判轮次用尽+纯技术方案分支缺升级待办自动关闭(2026-09-18银联实锤)——①共用段/标准A2:在办守卫先于轮次用尽判定(start_qc开轮即建passed=0记录,评分完成才UPDATE;旧顺序在末轮审核在办时误发qc_escalation待办,银联16:21:40误发实录,16:24:20第3轮8.60分通过);A2过滤同加_open_qc_type_tasks在办豁免;②纯技术方案分支T2b:补qc_escalation待办自动关闭段(标准流程有A2b,tech_proposal分支reconcile提前return不经过→误发/过期升级待办永久挂角标)
This commit is contained in:
parent
09caa11802
commit
cdc87f6a6d
@ -913,6 +913,12 @@ async def reconcile_project(sor, project_id, project_name=""):
|
||||
if qc_pending:
|
||||
_kept = []
|
||||
for _qp in qc_pending:
|
||||
# 审核任务在办 → 最新一轮记录尚未落定(start_qc 开轮即建 passed=0 记录,
|
||||
# 评分在完成时才 UPDATE),不得参与「轮次用尽」判定或派发,一律等待
|
||||
# (2026-09-18 银联末轮误报修复的标准流程同款守卫)。
|
||||
if await _open_qc_type_tasks(sor, project_id, _qp[0]) > 0:
|
||||
acts.append("waiting: 类型「%s」审核任务在办,最新一轮尚未落定" % _qp[0])
|
||||
continue
|
||||
_d = QC_TYPE_TO_DIM.get(_qp[0], "")
|
||||
if _d and await _open_dim_tasks(sor, project_id, _d) > 0:
|
||||
acts.append("waiting: 维度「%s」分析任务在办,%s 暂缓 QC 审核(防审半成品)"
|
||||
@ -1598,6 +1604,19 @@ async def _reconcile_tech_analysis_qc(sor, project_id, pname, n_items, latest_qc
|
||||
if latest_qc and str(latest_qc.get("passed")) == "1":
|
||||
return True, False, False
|
||||
|
||||
# 在办守卫必须先于「轮次用尽」判定(2026-09-18 银联末轮误报修复):
|
||||
# start_qc 在末轮审核开轮时即建记录(passed=0、未评分),此刻任务仍在办;
|
||||
# 旧顺序会先判 rnd>=qc_max_round 命中「轮次用尽」误发 qc_escalation 待办,
|
||||
# 而实际末轮审核正在跑、随时可能评分通过。QC 任务在办 → 最新轮尚未落定,一律等待。
|
||||
if await _open_tech_tasks(sor, project_id, "bid_qc") > 0:
|
||||
acts.append("waiting: 技术评估项 QC 任务在办")
|
||||
return False, False, True
|
||||
# 竞态守卫:抽取/重做任务在办 → 不派审核(防对半成品打分),
|
||||
# 同样不得判「轮次用尽」(重做正在跑,不是最终失败)。
|
||||
if await _open_tech_tasks(sor, project_id, "bid_tech_analysis") > 0:
|
||||
acts.append("waiting: 技术评估项抽取任务在办,暂不派 tech QC")
|
||||
return False, False, True
|
||||
|
||||
rnd = to_int(latest_qc.get("round"), 0) if latest_qc else 0
|
||||
if latest_qc and rnd >= th["qc_max_round"]:
|
||||
# 轮次用尽:产出未更新则不空转,抛人工(同标准流程逃逸阀)
|
||||
@ -1614,13 +1633,6 @@ async def _reconcile_tech_analysis_qc(sor, project_id, pname, n_items, latest_qc
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
acts.append("escalated: 技术评估项 QC 轮次用尽 → 人工介入")
|
||||
return False, True, True
|
||||
if await _open_tech_tasks(sor, project_id, "bid_qc") > 0:
|
||||
acts.append("waiting: 技术评估项 QC 任务在办")
|
||||
return False, False, True
|
||||
# 竞态守卫:抽取/重做任务在办 → 不派审核(防对半成品打分)
|
||||
if await _open_tech_tasks(sor, project_id, "bid_tech_analysis") > 0:
|
||||
acts.append("waiting: 技术评估项抽取任务在办,暂不派 tech QC")
|
||||
return False, False, True
|
||||
tid = await create_role_task(
|
||||
sor, project_id, R_QC,
|
||||
"%s 技术评估项契合度审核(对标招标技术需求原文)" % pname,
|
||||
@ -1686,6 +1698,22 @@ async def _reconcile_tech_proposal(sor, project_id, pname, stage_table):
|
||||
qc_passed, _tech_over, _blocked = await _reconcile_tech_analysis_qc(
|
||||
sor, project_id, pname, n_items, latest_qc, th, _on,
|
||||
FLOW_KEY_TECH_PROPOSAL, acts)
|
||||
|
||||
# ── T2b. qc_escalation 待办自动关闭(2026-09-18 银联实锤缺口)──
|
||||
# 标准流程有 A2b 段,纯技术方案分支在 reconcile_project 提前 return 不经过它 →
|
||||
# tech_items 轮次用尽发的升级待办在问题解决后(QC 通过/人工放行/重做恢复)
|
||||
# 永远挂着,角标常驻误导。逃逸阀闭环的另一半:问题解决 → 待办自动收。
|
||||
if not _tech_over:
|
||||
_ht_esc = await find_human_task(sor, project_id, HT_QC_ESCALATION, status="pending")
|
||||
if _ht_esc:
|
||||
await sor.sqlExe(
|
||||
"UPDATE pipeline_human_tasks SET status='done', qc_status='passed', "
|
||||
"qc_comment='对账器自动关闭:技术评估项 QC 已通过/放行或流程已恢复', "
|
||||
"submitted_at=NOW() WHERE id=${h}$ AND status='pending'",
|
||||
{"h": _ht_esc.get("id")})
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
acts.append("auto-closed: qc_escalation 待办(tech_items 已通过/流程已恢复)")
|
||||
|
||||
if not qc_passed:
|
||||
return acts or ["idle: 技术需求解析/审核中"]
|
||||
if _blocked:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user