fix: 如实显示型号不存在提示并简化飞书异常回复
This commit is contained in:
@@ -469,45 +469,56 @@ def model_difference_text(source_model: str, candidate_model: str) -> str:
|
||||
return ";".join(differences) if differences else "无"
|
||||
|
||||
|
||||
def business_unavailable_reason(payload: dict[str, Any]) -> str | None:
|
||||
"""Recognize verified business notices without echoing arbitrary response text."""
|
||||
data = payload.get("data")
|
||||
if (
|
||||
isinstance(data, str)
|
||||
and data.strip().rstrip("。.") == "产品型号不存在,请检查产品型号是否正确"
|
||||
):
|
||||
return "查询系统提示:产品型号不存在,请检查产品型号是否正确。"
|
||||
return None
|
||||
|
||||
|
||||
def query_failure_reason(payload: dict[str, Any]) -> str:
|
||||
"""Translate known failure categories without echoing raw API bodies or secrets."""
|
||||
error = payload.get("error")
|
||||
error = error.lower() if isinstance(error, str) else ""
|
||||
if error.startswith("missing api key:"):
|
||||
return "运行环境未配置交期预测 API Key,请由运行维护人员完成配置后重试。"
|
||||
return "交期查询尚未配置好,请联系维护人员处理后重试。"
|
||||
if error == "tls certificate verification failed":
|
||||
return "TLS 证书验证失败,请检查运行环境的证书信任配置。"
|
||||
return "暂时无法安全连接交期查询系统,请联系维护人员检查。"
|
||||
if error == "tls verification bypass is not permitted for this target host":
|
||||
return "请求目标不满足已批准的域名和 TLS 校验要求,请检查接口配置。"
|
||||
return "交期查询的连接设置不符合要求,请联系维护人员检查。"
|
||||
status = payload.get("status_code")
|
||||
http_reasons = {
|
||||
400: "接口拒绝请求参数",
|
||||
401: "接口身份认证失败,请检查 API Key 是否有效",
|
||||
403: "接口拒绝访问,请检查账号或 API Key 权限",
|
||||
404: "请求的接口或资源未找到;接口未说明是否为型号不存在",
|
||||
422: "请求参数未通过接口校验",
|
||||
429: "接口请求频率受限,请稍后重试",
|
||||
400: "查询信息未被系统接受,请核对型号和数量后重试。",
|
||||
401: "交期查询身份验证未通过,请联系维护人员处理。",
|
||||
403: "当前没有交期查询权限,请联系维护人员处理。",
|
||||
404: "暂未找到查询服务或所需数据,无法确认是否与型号有关,请联系维护人员核查。",
|
||||
422: "查询信息未通过系统检查,请核对型号和数量后重试。",
|
||||
429: "查询过于频繁,请稍后重试。",
|
||||
}
|
||||
if isinstance(status, int) and not isinstance(status, bool):
|
||||
if status in http_reasons:
|
||||
return f"HTTP {status}:{http_reasons[status]}。"
|
||||
return http_reasons[status]
|
||||
if 500 <= status <= 599:
|
||||
return f"HTTP {status}:交期预测服务异常,请稍后重试。"
|
||||
return f"接口返回 HTTP {status},未提供可安全展示的具体原因。"
|
||||
return "交期查询系统暂时异常,请稍后重试。"
|
||||
return "交期查询未成功,系统未说明具体原因,请联系维护人员核查。"
|
||||
if error.startswith("request failed:"):
|
||||
if "timed out" in error or "timeout" in error:
|
||||
return "交期预测接口请求超时,请稍后重试。"
|
||||
return "交期查询等待时间过长,请稍后重试。"
|
||||
if any(
|
||||
token in error
|
||||
for token in ("name or service not known", "nodename nor servname", "name resolution", "getaddrinfo")
|
||||
):
|
||||
return "接口域名解析失败,请检查运行环境的网络和 DNS 配置。"
|
||||
return "网络连接失败,请检查运行环境的网络、代理和接口可达性。"
|
||||
return "暂时无法找到交期查询系统,请联系维护人员检查网络。"
|
||||
return "暂时无法连接交期查询系统,请检查网络或稍后重试。"
|
||||
if error.startswith("response is not valid json:"):
|
||||
return "接口响应不是有效 JSON,无法读取交期结果。"
|
||||
return "交期查询系统返回的内容无法读取,请联系维护人员核查。"
|
||||
if payload.get("success") is False:
|
||||
return "接口标记本次查询失败(success=false),未提供可安全展示的具体原因,需核对服务端日志。"
|
||||
return "受控查询脚本执行失败,未提供可安全展示的具体原因,需核对运行日志。"
|
||||
return business_unavailable_reason(payload) or "交期查询未成功,系统未说明具体原因,请联系维护人员核查。"
|
||||
return "交期查询未完成,暂未查明具体原因,请联系维护人员核查。"
|
||||
|
||||
|
||||
def run_controlled_query(request: RequestInput) -> dict[str, Any]:
|
||||
@@ -530,17 +541,17 @@ def run_controlled_query(request: RequestInput) -> dict[str, Any]:
|
||||
json_start = output.find("{")
|
||||
if json_start < 0:
|
||||
reason = (
|
||||
"受控查询脚本缺少运行依赖,请检查 Python 环境。"
|
||||
"交期查询的运行环境不完整,请联系维护人员处理。"
|
||||
if "ModuleNotFoundError" in completed.stderr
|
||||
else "受控查询脚本未输出 JSON 结果,请检查运行环境和脚本日志。"
|
||||
else "未收到交期查询结果,请联系维护人员核查。"
|
||||
)
|
||||
raise RuntimeError(f"未生成候选结果。\n原因:{reason}")
|
||||
try:
|
||||
payload = json.loads(output[json_start:])
|
||||
except json.JSONDecodeError as exc:
|
||||
raise RuntimeError("未生成候选结果。\n原因:受控查询脚本输出的 JSON 格式异常。") from exc
|
||||
raise RuntimeError("未生成候选结果。\n原因:交期查询返回的内容无法读取,请联系维护人员核查。") from exc
|
||||
if not isinstance(payload, dict):
|
||||
raise RuntimeError("未生成候选结果。\n原因:接口响应的顶层数据不是对象。")
|
||||
raise RuntimeError("未生成候选结果。\n原因:交期查询返回的内容无法读取,请联系维护人员核查。")
|
||||
if completed.returncode != 0 or not payload.get("ok", True):
|
||||
status_code = payload.get("status_code")
|
||||
if isinstance(status_code, int) and status_code in {400, 404, 422}:
|
||||
@@ -571,38 +582,41 @@ def valid_delivery_date(value: Any) -> str | None:
|
||||
|
||||
|
||||
def lead_time_unavailable_reason(payload: dict[str, Any]) -> str | None:
|
||||
business_reason = business_unavailable_reason(payload)
|
||||
if business_reason:
|
||||
return business_reason
|
||||
if "data" not in payload:
|
||||
return "接口响应缺少 data 字段,无法读取交期汇总。"
|
||||
return "查询系统未返回查询结果,暂时无法提供交期。"
|
||||
data = payload.get("data")
|
||||
if data is None:
|
||||
return "接口响应的 data 为空,无法读取交期汇总。"
|
||||
return "查询结果为空,暂时无法提供交期。"
|
||||
if not isinstance(data, dict):
|
||||
return "接口响应的 data 格式错误(应为数据对象),无法读取交期汇总。"
|
||||
return "查询系统未返回可用的交期信息,请联系维护人员核查。"
|
||||
if "交期汇总" not in data:
|
||||
return "接口数据缺少“交期汇总”字段。"
|
||||
return "查询系统未返回交期汇总,暂时无法提供交期。"
|
||||
summary = data.get("交期汇总")
|
||||
if summary is None:
|
||||
return "接口返回的“交期汇总”为空。"
|
||||
return "查询系统返回的交期汇总为空,暂时无法提供交期。"
|
||||
if not isinstance(summary, dict):
|
||||
return "接口返回的“交期汇总”格式错误(应为数据对象)。"
|
||||
return "查询系统返回的交期汇总无法读取,请联系维护人员核查。"
|
||||
reasons: list[str] = []
|
||||
for field, validator, requirement in (
|
||||
("AM516工作日交期", whole_day_count, "应为非负整数工作日"),
|
||||
("AM516最终交货日期", valid_delivery_date, "应为有效的 YYYY-MM-DD 日期"),
|
||||
for field, validator, label in (
|
||||
("AM516工作日交期", whole_day_count, "工作日交期"),
|
||||
("AM516最终交货日期", valid_delivery_date, "最终交货日期"),
|
||||
):
|
||||
if field not in summary:
|
||||
reasons.append(f"缺少“{field}”字段")
|
||||
reasons.append(f"查询系统未返回{label}")
|
||||
elif summary[field] is None or summary[field] == "":
|
||||
reasons.append(f"“{field}”返回空值")
|
||||
reasons.append(f"查询系统返回的{label}为空")
|
||||
elif validator(summary[field]) is None:
|
||||
reasons.append(f"“{field}”值无效({requirement})")
|
||||
reasons.append(f"查询系统返回的{label}无效,请联系维护人员核查")
|
||||
if not reasons:
|
||||
return None
|
||||
if any(field in summary for field in ("AM516预测交期", "AM516总交期", "总交期")):
|
||||
reasons.append("已返回旧交期或自然日字段,无法替代上述必需字段")
|
||||
reasons.append("已有的其他交期信息不能代替工作日交期和最终交货日期")
|
||||
bom = data.get("BOM信息")
|
||||
if isinstance(bom, dict) and bom.get("是否有BOM(False则需提醒无BOM)") is False:
|
||||
reasons.append("接口同时标记无有效 BOM,需核对 BOM 数据")
|
||||
reasons.append("查询系统同时提示缺少有效的产品物料清单,请联系维护人员核查")
|
||||
return ";".join(reasons) + "。"
|
||||
|
||||
|
||||
@@ -1019,7 +1033,7 @@ def build_report(request: RequestInput, candidate_offset: int = 0) -> str:
|
||||
raise RuntimeError(
|
||||
"原型号未生成可用交期结果,未生成候选结果。\n"
|
||||
f"原因:{baseline['unavailable_reason']}\n"
|
||||
"处理建议:请接口维护人员核对上述原因、库存口径及服务端计算结果后重试。"
|
||||
"处理建议:请按上述提示核对;如确认信息无误,请联系维护人员核查。"
|
||||
)
|
||||
candidates.append(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user