补齐成交跟进:按线路推成交通知、收下未成交原因、协商中按工作日再问。
成交走询价消息服务;陆运/海运私聊下一句能记下原因;协商中回执写明顺延三个工作日和下次 9:00。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -64,6 +64,7 @@ def ticket_view(ticket: object) -> dict[str, Any]:
|
||||
view.get("productNames") or view.get("product_names") or [],
|
||||
)
|
||||
view.setdefault("sales_name", view.get("salesName") or view.get("sales_name") or "")
|
||||
view.setdefault("lost_reason", view.get("lostReason") or view.get("lost_reason") or "")
|
||||
facts = dict(view.get("collab_facts") or view.get("collabFacts") or {})
|
||||
view.setdefault("collab_facts", facts)
|
||||
flag = str(facts.get("__ended") or view.get("collab_ended") or view.get("collabEnded") or "").strip().lower()
|
||||
@@ -89,6 +90,7 @@ def ticket_view(ticket: object) -> dict[str, Any]:
|
||||
"product_ids": list(getattr(ticket, "product_ids", []) or []),
|
||||
"product_names": list(getattr(ticket, "product_names", []) or []),
|
||||
"sales_name": str(getattr(ticket, "sales_name", "") or ""),
|
||||
"lost_reason": str(getattr(ticket, "lost_reason", "") or ""),
|
||||
}
|
||||
|
||||
|
||||
@@ -987,18 +989,75 @@ def apply_group_deal(
|
||||
if not (quote.get("total") or _quote_fee_rows(quote) or status_now in {"已报价", "协商中"}):
|
||||
send_group_text(client, chat_id, copy.group_deal_need_quote())
|
||||
return "deal_need_quote"
|
||||
writer = getattr(flow.ledger, "transition", None)
|
||||
if callable(writer):
|
||||
result = writer(work_order_no=no, to_status=outcome) or {}
|
||||
if not result.get("ok"):
|
||||
send_group_text(client, chat_id, "主账状态更新失败,成交结果未入账。")
|
||||
return "ledger_fail"
|
||||
from agent.policy.deal_outcome import finish_deal_outcome
|
||||
|
||||
result = finish_deal_outcome(
|
||||
ledger=flow.ledger,
|
||||
work_order_no=no,
|
||||
outcome=outcome,
|
||||
facts=facts_of_group(view, sess),
|
||||
quote=quote,
|
||||
business_line=str(view.get("business_line") or (sess.business_line if sess else "SEA") or "SEA"),
|
||||
sales_name=str(view.get("sales_name") or (getattr(sess, "invited_sales_name", "") if sess else "") or ""),
|
||||
)
|
||||
if not result.get("ok"):
|
||||
send_group_text(client, chat_id, "主账状态更新失败,成交结果未入账。")
|
||||
return "ledger_fail"
|
||||
phase = str(result.get("phase") or "done")
|
||||
if sess is not None:
|
||||
sess.status = outcome
|
||||
sess.phase = phase
|
||||
if phase == "wait_deal":
|
||||
sess.allowed = (copy.BTN_DEAL, copy.BTN_LOST, copy.BTN_NEGOTIATE)
|
||||
else:
|
||||
sess.allowed = ()
|
||||
flow._save(sess)
|
||||
send_group_text(client, chat_id, copy.deal_ack(outcome, no, str(result.get("next_followup_at") or "")))
|
||||
return phase
|
||||
|
||||
|
||||
def facts_of_group(view: dict[str, Any], sess: Any = None) -> dict[str, str]:
|
||||
"""主账字段打底,书签覆盖;给负责人匹配和成交通知卡用。"""
|
||||
facts = dict(view.get("facts") or {})
|
||||
if sess is not None and getattr(sess, "facts", None):
|
||||
facts.update(dict(sess.facts or {}))
|
||||
return facts
|
||||
|
||||
|
||||
def capture_group_lost_reason(
|
||||
*,
|
||||
flow: Any,
|
||||
ticket: object,
|
||||
sender_id: str,
|
||||
text: str,
|
||||
sess: Any = None,
|
||||
) -> str:
|
||||
"""
|
||||
群里未成交后,本单销售下一句任意文字即原因。
|
||||
空运群是否要 @ 由入站通道先拦,这里不再判。
|
||||
"""
|
||||
ticket = hydrate_ticket(flow, ticket)
|
||||
view = ticket_view(ticket)
|
||||
no = ticket_no(ticket)
|
||||
chat_id = str((sess.collab_chat_id if sess else "") or view.get("collab_chat_id") or "")
|
||||
client = group_client_of(flow)
|
||||
if ticket_status(ticket) != "未成交":
|
||||
return ""
|
||||
if str(view.get("lost_reason") or "").strip():
|
||||
return ""
|
||||
if not is_sales(ticket, sender_id):
|
||||
return ""
|
||||
from agent.policy.deal_outcome import capture_lost_reason
|
||||
|
||||
result = capture_lost_reason(ledger=flow.ledger, work_order_no=no, reason=text)
|
||||
if not result.get("ok"):
|
||||
send_group_text(client, chat_id, "未成交原因没有记下,请再发一句。")
|
||||
return "wait_lost_reason"
|
||||
if sess is not None:
|
||||
sess.phase = "done"
|
||||
sess.allowed = ()
|
||||
flow._save(sess)
|
||||
send_group_text(client, chat_id, copy.deal_ack(outcome, no))
|
||||
send_group_text(client, chat_id, copy.lost_reason_ack(text))
|
||||
return "done"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user