重启后仍能跳过协同出方案,未成交可同一句带原因;海陆有价卡改为直接生成报价单。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 18:45:28 +08:00
co-authored by Cursor
parent 378bb892b3
commit 84207bb4e5
18 changed files with 414 additions and 32 deletions
+51 -4
View File
@@ -560,7 +560,15 @@ class AirTextInquiryFlow:
if phase == "wait_collab":
allowed = (copy.BTN_SKIP_COLLAB,)
elif phase == "wait_adopt":
allowed = (copy.BTN_ADOPT_EXCEL, copy.BTN_ADOPT_PDF, copy.BTN_REJECT)
# skip_collab_on_wait_adopt:主账把空运/陆运「已报价未出文件」收成方案卡,
# 但手机上协同卡还在。进程重启后点「不需要协同」必须还能出方案,不能静默丢掉。
# 报价文件已发出时主账会改 wait_deal,这里不会走到。
allowed = (
copy.BTN_SKIP_COLLAB,
copy.BTN_ADOPT_EXCEL,
copy.BTN_ADOPT_PDF,
copy.BTN_REJECT,
)
elif phase == "wait_deal":
allowed = (copy.BTN_DEAL, copy.BTN_LOST, copy.BTN_NEGOTIATE)
elif phase == "wait_lost_reason":
@@ -707,6 +715,9 @@ class AirTextInquiryFlow:
reply=reply,
card_meta=inbound_raw,
)
oral_lost = self.try_deal_oral(sess, text, reply, inbound_raw)
if oral_lost:
return oral_lost
# 未成交后下一句任意文字即原因;完整新询价(注入字段)则空着原因开新单。
if (
sess
@@ -1612,17 +1623,44 @@ class AirTextInquiryFlow:
logger.exception("报价 PDF 入队失败 wo=%s", work_order_no)
return False
def try_deal_oral(
self,
sess: Optional[FlowSession],
text: str,
reply: ReplyFn,
card_meta: Optional[dict[str, Any]] = None,
) -> str:
"""
成交跟进阶段口播未成交;同一句可带原因。
点卡仍走 match_button。返回阶段名;不是未成交口播则空串。
"""
from agent.policy.deal_outcome import looks_like_lost_outcome
if sess is None or not (text or "").strip():
return ""
allowed = sess.allowed or ()
if copy.BTN_LOST not in allowed and sess.phase not in {"wait_deal", "wait_file"}:
return ""
if not looks_like_lost_outcome(text):
return ""
if sess.phase == "wait_file":
self._promote_wait_deal(sess)
return self._close(sess, reply, "未成交", card_meta=card_meta, source_text=text)
def _close(
self,
sess: FlowSession,
reply: ReplyFn,
status: str,
card_meta: Optional[dict[str, Any]] = None,
source_text: str = "",
) -> str:
"""点成交/未成交/协商中:先整卡置灰,再入主账。"""
"""点成交/未成交/协商中:先整卡置灰,再入主账。未成交同一句带原因则一次记完。"""
self._grey_clicked_card(reply, card_meta, replace_name=status)
from agent.policy.deal_outcome import finish_deal_outcome
from agent.policy.deal_outcome import finish_deal_outcome, harvest_inline_lost_reason
inline = harvest_inline_lost_reason(source_text) if status == "未成交" else ""
result = finish_deal_outcome(
ledger=self._ledger,
work_order_no=sess.work_order_no,
@@ -1631,6 +1669,7 @@ class AirTextInquiryFlow:
quote=sess.quote,
business_line=sess.business_line,
sales_name=sess.invited_sales_name,
lost_reason=inline,
)
if not result.get("ok"):
reply("主账状态更新失败,成交结果未入账。")
@@ -1644,7 +1683,15 @@ class AirTextInquiryFlow:
sess.allowed = ()
sess.wait_version += 1
self._save(sess)
reply(copy.deal_ack(status, sess.work_order_no, str(result.get("next_followup_at") or "")))
ack_reason = inline if phase == "done" and status == "未成交" else ""
reply(
copy.deal_ack(
status,
sess.work_order_no,
str(result.get("next_followup_at") or ""),
lost_reason=ack_reason,
)
)
return phase
def _capture_lost_reason(self, sess: FlowSession, text: str, reply: ReplyFn) -> str: