空运人工价锁舱现拉补全舱位并拦清缺参;成交/报价填表与工单陆运费率展示同步收紧。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1023,7 +1023,12 @@ def quote_fee_lines(quote: dict[str, Any] | None) -> list[tuple[str, str]]:
|
||||
amount = str(item.get("amount") or item.get("value") or "").strip()
|
||||
line_ccy = str(item.get("currency") or item.get("currencyCode") or header_ccy).strip()
|
||||
if name and amount and amount != "-":
|
||||
lines.append((name, money_text(amount, line_ccy)))
|
||||
# 燃油附加费率 / 税率是百分比,禁止套成「CNY 1%」。
|
||||
if "%" in amount or name.endswith("费率") or name in {"税率", "燃油附加费率"}:
|
||||
shown = amount if "%" in amount else f"{amount}%"
|
||||
lines.append((name, shown))
|
||||
else:
|
||||
lines.append((name, money_text(amount, line_ccy)))
|
||||
if lines:
|
||||
return lines
|
||||
freight = str(src.get("freight") or "").strip()
|
||||
@@ -1219,10 +1224,21 @@ def sea_quote_detail_text(
|
||||
|
||||
|
||||
def collab_hint(work_order_no: str) -> str:
|
||||
"""价格卡协同说明:无「内部协同」前缀,紧挨生成报价单按钮上方。"""
|
||||
return (
|
||||
f"若需要咨询内部航线人员,请手动拉新人与智能体到原有群,"
|
||||
f"并在群聊发送工单编号{work_order_no}。"
|
||||
"""
|
||||
空运价格卡协同说明:紧挨「不需要协同,直接生成报价单」上方。
|
||||
|
||||
后台 inquiring.air_collab_hint;库内模板可用 {{ticket_no}}。
|
||||
无后台模板时用本默认句(已带工单号)。销售侧示例:
|
||||
…发送“ WO202610060030@询价小助手”,谢谢。
|
||||
"""
|
||||
no = (work_order_no or "").strip()
|
||||
return _r(
|
||||
"inquiring.air_collab_hint",
|
||||
(
|
||||
f"若需要咨询内部航线人员,请手动将相关方拉到空运原有协同群,"
|
||||
f"并在空运协同群中发送“ {no}@询价小助手”,谢谢。"
|
||||
),
|
||||
ticket_no=no,
|
||||
)
|
||||
|
||||
|
||||
@@ -2661,8 +2677,24 @@ def group_deal_stale(*, work_order_no: str) -> str:
|
||||
return f"这张成交确认已过期。工单{no}已有更新的报价,请点击群里最新一条成交跟进。"
|
||||
|
||||
|
||||
def group_deal_need_quote() -> str:
|
||||
return "还没有可确认的报价,请先完成报价再确认成交状态。"
|
||||
def group_deal_need_quote(*, work_order_no: str = "") -> str:
|
||||
"""
|
||||
群里确认成交/未成交时,主账还没有可确认报价。
|
||||
|
||||
空运 WO027:询价中且无 inq_quote,旧句「主账状态更新失败」不说明原因。
|
||||
"""
|
||||
no = (work_order_no or "").strip()
|
||||
if no:
|
||||
return (
|
||||
f"工单{no}状态更新失败,原因:没有报价。\n"
|
||||
f"请先报价,然后再更新工单状态。"
|
||||
)
|
||||
return "工单状态更新失败,原因:没有报价。\n请先报价,然后再更新工单状态。"
|
||||
|
||||
|
||||
def deal_fail_no_quote(*, work_order_no: str = "") -> str:
|
||||
"""成交三态写入失败且判定为没有报价时的销售可见说明。与群门禁同句。"""
|
||||
return group_deal_need_quote(work_order_no=work_order_no)
|
||||
|
||||
|
||||
def group_deal_sales_only() -> str:
|
||||
@@ -2717,7 +2749,7 @@ def deal_ack(
|
||||
if outcome == "未成交":
|
||||
reason = (lost_reason or "").strip()
|
||||
if reason:
|
||||
return f"已记录为「未成交」。{lost_reason_ack(reason)}"
|
||||
return f"已记录为「未成交」。{lost_reason_ack(reason, work_order_no=no)}"
|
||||
return _r("lost.ask_reason", "已记录为「未成交」。请补充未成交原因。", ticket_no=no)
|
||||
when = _followup_month_day(next_followup_at) or "第四个工作日"
|
||||
return _r(
|
||||
@@ -2744,14 +2776,19 @@ def _followup_month_day(raw: str) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def lost_reason_ack(reason: str = "") -> str:
|
||||
"""收下未成交原因后回显原句。后台 lost.reason_ack。"""
|
||||
def lost_reason_ack(reason: str = "", work_order_no: str = "") -> str:
|
||||
"""
|
||||
收下未成交原因后回显。后台 lost.reason_ack。
|
||||
|
||||
测服文案含 {{ticket_no}} / {{lost_reason}};缺 ticket_no 会原样打出占位符。
|
||||
"""
|
||||
text = (reason or "").strip()
|
||||
no = (work_order_no or "").strip()
|
||||
if text.endswith(("。", ".", "!", "!", "?", "?")):
|
||||
default = f"已记下未成交原因:{text}"
|
||||
else:
|
||||
default = f"已记下未成交原因:{text}。" if text else "已记下未成交原因。"
|
||||
return _r("lost.reason_ack", default, lost_reason=text)
|
||||
return _r("lost.reason_ack", default, lost_reason=text, ticket_no=no)
|
||||
|
||||
|
||||
def deal_notify_card(
|
||||
@@ -3044,6 +3081,53 @@ def air_ask_lock_option(options: list) -> str:
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def air_ask_manual_lock_fields(
|
||||
*,
|
||||
need_option: bool = False,
|
||||
need_airline: bool = False,
|
||||
need_chargeable: bool = False,
|
||||
need_flight: bool = False,
|
||||
options: list | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
手动报价锁舱缺 TMS MANUAL 必填项时,群里补问,禁止空壳出站。
|
||||
|
||||
例:请回复「AIR-OPT01 CZ 航班CZ327」。
|
||||
"""
|
||||
bits: list[str] = []
|
||||
if need_option:
|
||||
bits.append("舱位编号(如 AIR-OPT01)")
|
||||
if need_airline:
|
||||
bits.append("航司两位码(如 CZ)")
|
||||
if need_flight:
|
||||
bits.append("航班号(如 CZ327)")
|
||||
if need_chargeable:
|
||||
bits.append("计费重(公斤)")
|
||||
need = "、".join(bits) if bits else "舱位编号、航司和航班号"
|
||||
lines = [
|
||||
f"锁舱还缺:{need}。",
|
||||
"请按「AIR-OPT01 CZ 航班CZ327」回复;",
|
||||
]
|
||||
if need_chargeable:
|
||||
lines.append("若还缺计费重,请再写「计费重xx公斤」。")
|
||||
else:
|
||||
lines.append("例如:AIR-OPT01 CZ 航班CZ327")
|
||||
opts = options or []
|
||||
shown = False
|
||||
for item in opts:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
no = str(item.get("optionNo") or item.get("option_no") or "").strip()
|
||||
airline = str(item.get("airlineCode") or item.get("airlineName") or "").strip()
|
||||
if not no:
|
||||
continue
|
||||
if not shown:
|
||||
lines.append("可选舱位:")
|
||||
shown = True
|
||||
lines.append(f"{no} {airline}".strip() if airline else no)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def air_lock_ok(
|
||||
*,
|
||||
work_order_no: str,
|
||||
@@ -3072,7 +3156,7 @@ def air_lock_ok(
|
||||
|
||||
|
||||
def air_lock_fail(*, work_order_no: str, operator: str, reason: str) -> str:
|
||||
"""空运锁舱失败。后台 inquiring.air_lock_fail。"""
|
||||
"""空运锁舱失败(接口/系统类)。后台 inquiring.air_lock_fail。"""
|
||||
why = (reason or "").strip() or "TMS未返回原因"
|
||||
default = (
|
||||
f"工单{work_order_no} 空运锁舱失败。\n"
|
||||
@@ -3089,6 +3173,25 @@ def air_lock_fail(*, work_order_no: str, operator: str, reason: str) -> str:
|
||||
)
|
||||
|
||||
|
||||
def air_lock_incomplete(*, work_order_no: str, operator: str, reason: str = "") -> str:
|
||||
"""
|
||||
锁舱参数不齐(纯手工价、运价库无舱位等):业务补问,不算系统异常,不惊动 IT。
|
||||
|
||||
航线按示例回舱位+航司+航班后即可再锁。
|
||||
"""
|
||||
why = (reason or "").strip()
|
||||
lines = [
|
||||
f"工单{work_order_no} 还不能锁舱。",
|
||||
f"操作人:{operator}",
|
||||
]
|
||||
if why:
|
||||
lines.append(f"原因:{why}")
|
||||
else:
|
||||
lines.append("原因:本单没有可引用的 TMS 舱位(手工价或运价库无匹配)。")
|
||||
lines.append("请直接回复「AIR-OPT01 CZ 航班CZ327」(换成实际舱位、航司、航班号)后再锁。")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def air_cabin_fail_reason(*, tms_reason: str = "", flight_date: str = "", today: str = "") -> str:
|
||||
"""
|
||||
锁舱/释放失败原因:原样回 TMS 的 failReason。
|
||||
|
||||
Reference in New Issue
Block a user