空运附件报价锁舱前先提示航线改发纯文字报价,避免附件金额拆不出导致锁舱失败。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -699,6 +699,9 @@ def apply_air_file(
|
||||
from agent.policy.event_exception import clear_wait
|
||||
|
||||
clear_wait(flow.ledger, work_order_no=no)
|
||||
# 附件不拆金额:锁舱常失败。产品口径改为提示航线改发纯文字报价后再锁。
|
||||
tip = copy.air_attachment_quote_lock_tip(work_order_no=no)
|
||||
send_group_text(client, chat_id, tip)
|
||||
emit_group_deal(flow=flow, ticket=view, quote=quote)
|
||||
return "airline_file_quote"
|
||||
|
||||
@@ -952,7 +955,8 @@ def apply_air_lock(
|
||||
return "no_quote"
|
||||
# 主账在出站前发现三项不齐:只请补,不当 TMS 故障,不通知 IT。
|
||||
reason_text = str(out.get("failReason") or "")
|
||||
if str(out.get("error") or "") == "lock_params_incomplete" or "锁舱参数不完整" in reason_text:
|
||||
err_code = str(out.get("error") or "")
|
||||
if err_code == "lock_params_incomplete" or "锁舱参数不完整" in reason_text:
|
||||
labels = missing or _labels_from_incomplete_reason(reason_text)
|
||||
_remember_partial_lock(
|
||||
flow,
|
||||
@@ -964,8 +968,45 @@ def apply_air_lock(
|
||||
)
|
||||
send_group_text(group_client_of(flow), chat_id, copy.air_lock_need_params(labels))
|
||||
return "wait_lock_params"
|
||||
# 附件/手工报价、运价库无舱位:引导纯文字报价,不算系统异常、不通知 IT。
|
||||
src_label = str((quote or {}).get("source_label") or (quote or {}).get("source") or "")
|
||||
need_text_quote = (
|
||||
err_code in {"lock_incomplete", "lock_fail"}
|
||||
and (
|
||||
"航线附件报价" in src_label
|
||||
or "附件" in src_label
|
||||
or any(
|
||||
x in reason_text
|
||||
for x in (
|
||||
"手工报价",
|
||||
"无匹配舱位",
|
||||
"无匹配报价",
|
||||
"运价库无匹配",
|
||||
"标准运价库无匹配",
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
if need_text_quote:
|
||||
send_group_text(
|
||||
group_client_of(flow),
|
||||
chat_id,
|
||||
copy.air_lock_need_text_quote(
|
||||
work_order_no=no, operator=name, reason=reason_text
|
||||
),
|
||||
)
|
||||
return "need_text_quote"
|
||||
if err_code == "lock_incomplete":
|
||||
send_group_text(
|
||||
group_client_of(flow),
|
||||
chat_id,
|
||||
copy.air_lock_incomplete(
|
||||
work_order_no=no, operator=name, reason=reason_text
|
||||
),
|
||||
)
|
||||
return "lock_incomplete"
|
||||
# 多段是产品限制,不是 TMS 故障。只回原因,不标系统异常、不暂停工单。
|
||||
if str(out.get("error") or "") == "multi_no_lock":
|
||||
if err_code == "multi_no_lock":
|
||||
send_group_text(
|
||||
group_client_of(flow),
|
||||
chat_id,
|
||||
|
||||
@@ -3273,13 +3273,72 @@ def air_lock_fail(*, work_order_no: str, operator: str, reason: str) -> str:
|
||||
)
|
||||
|
||||
|
||||
def air_text_quote_for_lock_example(work_order_no: str = "") -> str:
|
||||
"""
|
||||
需要锁舱时,请航线用纯文字报价的示例句。
|
||||
|
||||
附件报价不拆金额、常锁不成;产品口径改为引导航线改发文字价。
|
||||
"""
|
||||
no = (work_order_no or "").strip() or "工单号"
|
||||
return f"{no},空运段,空运费 单价CNY99.00,数量100 ,金额CNY9900.00@询价小助手"
|
||||
|
||||
|
||||
def air_attachment_quote_lock_tip(*, work_order_no: str) -> str:
|
||||
"""
|
||||
航线刚发完 Excel/PDF 附件报价后的提示。
|
||||
|
||||
附件只存档、不拆费用;若还要锁舱,必须再发一版纯文字报价。
|
||||
"""
|
||||
no = (work_order_no or "").strip() or "WO"
|
||||
example = air_text_quote_for_lock_example(no)
|
||||
return (
|
||||
f"工单{no}附件报价已收。\n"
|
||||
"如需锁舱,请航线人员改用纯文字报价(不要只发附件),例如:\n"
|
||||
f"{example}"
|
||||
)
|
||||
|
||||
|
||||
def air_lock_need_text_quote(*, work_order_no: str, operator: str = "", reason: str = "") -> str:
|
||||
"""
|
||||
附件/手工报价锁舱走不通时:引导航线先发文字报价,不算系统异常、不通知 IT。
|
||||
|
||||
故意不回主账/TMS 原文「原因」(如 AIR-OPT / 运价库无匹配),只留文字报价指引。
|
||||
reason 参数保留兼容旧调用,出站话术不用。
|
||||
"""
|
||||
_ = reason
|
||||
no = (work_order_no or "").strip() or "WO"
|
||||
who = (operator or "").strip()
|
||||
lines = [f"工单{no} 还不能锁舱。"]
|
||||
if who:
|
||||
lines.append(f"操作人:{who}")
|
||||
lines.append("如需锁舱,请航线人员先发纯文字报价,例如:")
|
||||
lines.append(air_text_quote_for_lock_example(no))
|
||||
lines.append("文字报价写入后再发锁舱口令(可带舱位、航司、航班号)。")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def air_lock_incomplete(*, work_order_no: str, operator: str, reason: str = "") -> str:
|
||||
"""
|
||||
锁舱参数不齐(纯手工价、运价库无舱位等):业务补问,不算系统异常,不惊动 IT。
|
||||
|
||||
航线按示例回舱位+航司+航班后即可再锁。
|
||||
附件/无舱位场景改引导纯文字报价;有 TMS 舱位时仍可补 AIR-OPT 三项。
|
||||
"""
|
||||
why = (reason or "").strip()
|
||||
blob = why
|
||||
if any(
|
||||
x in blob
|
||||
for x in (
|
||||
"手工报价",
|
||||
"附件",
|
||||
"无匹配舱位",
|
||||
"无匹配报价",
|
||||
"运价库无匹配",
|
||||
"标准运价库无匹配",
|
||||
)
|
||||
):
|
||||
return air_lock_need_text_quote(
|
||||
work_order_no=work_order_no, operator=operator, reason=why
|
||||
)
|
||||
lines = [
|
||||
f"工单{work_order_no} 还不能锁舱。",
|
||||
f"操作人:{operator}",
|
||||
|
||||
@@ -1476,6 +1476,8 @@ class AirGroupCollabTests(unittest.TestCase):
|
||||
self.assertEqual(ticket.quote.get("quoteId"), "QT-AIR-1")
|
||||
self.assertEqual(ticket.status, "已报价")
|
||||
self.assertTrue(any(f"工单{wo}的1个附件已保存到后台工单" in t for t in self._texts()))
|
||||
self.assertTrue(any("如需锁舱,请航线人员改用纯文字报价" in t for t in self._texts()))
|
||||
self.assertTrue(any("空运费 单价CNY99.00" in t for t in self._texts()))
|
||||
self.assertTrue(any("报价单已发送,请确认成交状态" in t for t in self._texts()))
|
||||
|
||||
def test_reactivate_after_airline_file_is_deal_not_blank_sheet(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user