合并 feat/continue-deal-card-20261009:报价发出后继续工单重发成交卡;空运锁舱补参与看板滚动一并收下。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-10-09 09:06:43 +08:00
co-authored by Cursor
50 changed files with 2173 additions and 320 deletions
+33 -4
View File
@@ -882,8 +882,11 @@ class AirTextInquiryFlow:
reply(copy.quote_generating())
return "wait_file"
if sess.phase == "wait_deal":
# 成交卡已经绑在报价文件那条出站上。只续办、没说成交结果时不再另发一张卡。
# 原话写了已成交/未成交/协商中时,由 _close_spoken_deal 先入账,不会走到这里。
# 成交卡原来挂在报价单那条消息上,聊天一上滑就找不到。
# 销售再说继续工单、又没写成交结果时,再发一次成交/未成交/协商中。
# 原话已经写了结果时,_close_spoken_deal 会先入账,不会走到这里。
sess.allowed = (copy.BTN_DEAL, copy.BTN_LOST, copy.BTN_NEGOTIATE)
self._emit_deal(reply, sess)
return "wait_deal"
if sess.phase == "wait_lost_reason":
reply(copy.deal_ack("未成交", sess.work_order_no))
@@ -1260,13 +1263,39 @@ class AirTextInquiryFlow:
quote = tms["quote"]
from agent.schema.air_route_options import (
choose_stated_origin_option,
needs_route_pick,
options_matching_origin,
parse_air_options,
project_selected_quote,
)
options = parse_air_options(quote)
if options and not needs_route_pick(quote):
stated_origin = str(
(sess.facts or {}).get("起运港") or (sess.facts or {}).get("起运地") or ""
).strip()
# 写了起运地:只认这个起运地的线路,直接报价,不让销售再选。
# 没写起运地:TMS 按目的地回多条时,才进选线页。
if stated_origin:
matched = options_matching_origin(options, stated_origin)
if options and not matched:
logger.info(
"air 起运地对不上回包线路 origin=%s wo=%s options=%s",
stated_origin,
no,
len(options),
)
self._emit_tms_miss(reply, no)
sess.phase = "tms_miss"
sess.status = "询价中"
sess.allowed = ()
self._save(sess)
return "tms_miss"
if matched:
quote = project_selected_quote(
quote, choose_stated_origin_option(matched, quote)
)
elif options and not needs_route_pick(quote):
quote = project_selected_quote(quote, options[0])
up = self._ledger.upsert_quote(work_order_no=no, quote=quote, to_status="已报价")
if not up.get("ok"):
@@ -1278,7 +1307,7 @@ class AirTextInquiryFlow:
copy.remember_tms_quote(sess, quote)
sess.tms_quote = dict(quote)
sess.status = "已报价"
if needs_route_pick(quote):
if not stated_origin and needs_route_pick(quote):
return self._offer_air_routes(
sess=sess,
work_order_no=no,