调价后的新价格写入报价单;多段段前的货物带到各段,协同群不再把体积里的星号吃掉。海运字段齐了先核对再查价。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-03 22:39:54 +08:00
co-authored by Cursor
parent 0a14b4cc15
commit 7c77e45e03
32 changed files with 1384 additions and 75 deletions
+38 -16
View File
@@ -51,6 +51,9 @@ _AIR_OPTIONAL_CLARIFY = tuple(
)
AIR_CONFIRM_TAIL = "请回复“确定”进行TMS查价,内容有误时,请重新发内容。"
AIR_CONFIRM_EXPIRED = "刚才的空运核对已过期,请把空运需求再发一次,出核对卡后再回复确定。"
# 海运私聊与空运同一句。核对卡没有工单号,回复确定后才建单查价。
SEA_CONFIRM_TAIL = "请回复“确定”进行TMS查价,内容有误时,请重新发内容。"
SEA_CONFIRM_EXPIRED = "刚才的海运核对已过期,请把海运需求再发一次,出核对卡后再回复确定。"
# 海运补问:与合同 10 项一致。报价日期默认当天,不进待补充。
_SEA_EXAMPLES = {
@@ -478,6 +481,26 @@ def air_confirm_card(facts: dict[str, str] | None) -> str:
return "\n".join(lines)
def sea_confirm_card(facts: dict[str, str] | None) -> str:
"""
海运确定查价前的核对卡。没有工单号。
销售侧必填都列出(货物数量对应内部键货量)。报价日期没说则用已经填上的当天。
协同字段不在这张卡上,不挡首次查价。
"""
src = dict(facts or {})
lines = ["运输方式(必填):海运"]
for key, label in SEA_REQUIRED_FIELDS:
if key == "货量":
val = (src.get("货量") or src.get("货物数量") or "").strip()
else:
val = (src.get(key) or "").strip()
lines.append(f"{label}(必填):{val}")
lines.append("")
lines.append(SEA_CONFIRM_TAIL)
return "\n".join(lines)
def ask_clarify(
*,
facts: dict[str, str] | None = None,
@@ -1032,34 +1055,28 @@ def quote_area_fee_text(
return "\n".join(fee_lines)
# 企微引用条过长会被客户端裁成省略号。海运常有 6~8 项费用,必须走文本明细。
_QUOTE_AREA_SAFE_CHARS = 80
def quote_area_safe_text(
quote: dict[str, Any] | None,
business_line: str = "",
transport_mode: str = "",
) -> str:
"""
卡片引用条:空运有费用行就只留总价,禁止再塞费用。
价格明细卡的引用条只留两行:费用合计、共几项费用。
三项短费用也会被企微裁成「人工费:CNY 123...」。完整明细走文本。
海运/陆运仍按字数:短的原样,超长同样只留总价。
空运、海运、陆运都这样。完整路段和逐项费用在上一条文字里。
引用条再塞路段名或费用明细,企微会裁成半句。
"""
src = dict(quote or {})
header_ccy = str(src.get("currency") or src.get("currencyCode") or "").strip()
total = money_text(str(src.get("total") or "-").strip() or "-", header_ccy)
n = len(quote_fee_lines(src))
if _is_land_surface(quote=src, business_line=business_line, transport_mode=transport_mode):
from agent.schema.land_route_options import land_leg_fee_blocks
block_n = sum(len(fees) for _title, fees, _eta in land_leg_fee_blocks(src))
if block_n:
n = block_n
label = _total_label(src, business_line, transport_mode)
line = (business_line or "").upper()
mode = (transport_mode or "").strip()
is_air = line == "AIR" or mode == "空运"
if is_air and n:
return f"{label}:{total}\n共{n}项费用,详见上一条明细"
full = quote_area_fee_text(quote, business_line=business_line, transport_mode=transport_mode)
if len(full) <= _QUOTE_AREA_SAFE_CHARS:
return full
if n:
return f"{label}:{total}\n共{n}项费用,详见上一条明细"
return f"{label}:{total}"
@@ -1094,8 +1111,13 @@ def sea_quote_detail_text(
if route:
lines.append(route)
if line == "LAND":
from agent.schema.land_route_options import land_leg_fee_blocks
# 只有一段时,费用前的「始发 → 目的」已经是这条线路。
# 再写横杠全程(上海-谅山…)就是同一条路出现两次。多段仍保留全程,方便看中转。
blocks = land_leg_fee_blocks(src)
land_line = str(src.get("route_line") or "").strip()
if land_line:
if land_line and len(blocks) != 1:
lines.append(land_line)
lines.append(quote_area_fee_text(src, business_line=business_line or "SEA"))
# 空运、陆运的价格明细正文都要带有效期。海运仍放在按钮卡副标题,避免和原口径打架。