重启后仍能跳过协同出方案,未成交可同一句带原因;海陆有价卡改为直接生成报价单。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user