落地海运协同群:测服靠会话存档听群话,报价单能带上协同字段。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-15 18:12:45 +08:00
co-authored by Cursor
parent 235ecd8c83
commit 12219cacb1
39 changed files with 4436 additions and 256 deletions
+36 -8
View File
@@ -50,6 +50,8 @@ class FlowSession:
invited_userids: tuple[str, ...] = ()
invited_sales_name: str = ""
invited_product_names: tuple[str, ...] = ()
deal_version: int = 0
collab_ended: bool = False
class AirTextInquiryFlow:
@@ -74,6 +76,14 @@ class AirTextInquiryFlow:
with self._lock:
return self._by_sender.get(sender_id)
def session_by_work_order(self, work_order_no: str) -> Optional[FlowSession]:
"""用工单号找回书签,不校验 sender。群成交卡校验用。"""
no = (work_order_no or "").strip()
if not no:
return None
with self._lock:
return self._by_ticket.get(no)
def session_by_ticket(self, sender_id: str, work_order_no: str) -> Optional[FlowSession]:
"""
只查进程内该书签,不读主账。
@@ -298,7 +308,8 @@ class AirTextInquiryFlow:
reply("报价单正在生成,请稍候。")
return "wait_file"
if sess.phase == "wait_deal":
self._emit_deal(reply, sess)
# 成交卡已经绑在报价文件那条出站上。这里再发一张独立卡,
# 会在文件还在上传时被另一条出站线程抢走,销售又先看到成交跟进。
return "wait_deal"
if sess.phase == "done":
reply(copy.deal_ack(sess.status or "已关闭", sess.work_order_no))
@@ -814,15 +825,33 @@ class AirTextInquiryFlow:
file_extra: dict[str, Any],
) -> str:
"""
先发报价文件,等这条出站真正发出,再出成交跟进卡。
报价文件与成交跟进走同一条出站:先传文件,成功后再发卡。
避免卡片比文件先到销售手机。单测 reply 不回 id 则不等待。
两张消息分两条出站时,另一条消费线程会在上传期间把成交卡发出去。
单测 reply 不回 id 则不等待。
"""
out_id = reply(
copy.file_ready(kind=kind, work_order_no=sess.work_order_no, filename=filename),
file_extra,
extra = dict(file_extra or {})
extra["followup_card"] = copy.deal_wecom_payload(
work_order_no=sess.work_order_no,
quote=sess.quote,
facts=sess.facts,
).get("template_card") or {}
reply(
"\n".join(
[
copy.file_ready(
kind=kind, work_order_no=sess.work_order_no, filename=filename
),
copy.deal_card(
work_order_no=sess.work_order_no,
status=sess.status or "已报价",
quote=sess.quote,
facts=sess.facts,
),
]
),
extra,
)
self._wait_outbound_sent(str(out_id or ""), work_order_no=sess.work_order_no, what="报价文件")
from agent.redis_coord.quote_file import mark_quote_file_ready
mark_quote_file_ready(sess.work_order_no)
@@ -830,7 +859,6 @@ class AirTextInquiryFlow:
sess.allowed = (copy.BTN_DEAL, copy.BTN_LOST, copy.BTN_NEGOTIATE)
sess.wait_version += 1
self._save(sess)
self._emit_deal(reply, sess)
return "wait_deal"
def _emit_deal(self, reply: ReplyFn, sess: FlowSession) -> None: