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

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
+60 -6
View File
@@ -44,6 +44,16 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
super().__init__(ledger=ledger)
self._group_client = group_client
def group_client(self) -> Any:
"""
企微应用群客户端。测服正式不注入,现场再取默认 WeCom 客户端。
单测可注入 FakeGroupClient。取到后挂在流程上,后续补字段/发文件共用。
"""
if self._group_client is None:
self._group_client = _default_group_client()
return self._group_client
def on_text(
self,
*,
@@ -374,6 +384,23 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
sess = self.session_for_action(sender_id, card_meta)
if sess and action == copy.BTN_PULL_COLLAB and action in sess.allowed:
return self._pull_collab_group(sess, reply, card_meta=card_meta)
if action in {copy.BTN_DEAL, copy.BTN_LOST, copy.BTN_NEGOTIATE}:
from agent.policy.sea_group_ops import explain_deal_click
ticket_sess = sess
if ticket_sess is None:
wo = copy.work_order_from_card_meta(card_meta)
ticket_sess = self.session_by_work_order(wo)
if ticket_sess and (ticket_sess.collab_chat_id or "").strip():
reason = explain_deal_click(
flow=self,
sender_id=sender_id,
action=action,
card_meta=card_meta,
sess=ticket_sess,
)
if reason:
return reason
return super().on_button(
sender_id=sender_id, action=action, reply=reply, card_meta=card_meta
)
@@ -390,10 +417,22 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
没人可拉 / 建群失败:说明原因,按钮保持可点。已有群:不新建,置灰。
"""
no = (sess.work_order_no or "").strip()
if sess.collab_ended:
reply(copy.group_cannot_recreate(work_order_no=no))
return "collab_ended"
getter = getattr(self._ledger, "get_ticket", None)
ticket = getter(work_order_no=no) if callable(getter) else None
if ticket is not None:
facts = dict(getattr(ticket, "collab_facts", {}) or {})
if bool(getattr(ticket, "collab_ended", False)) or str(
facts.get("__ended") or ""
).strip() in {"1", "true"}:
sess.collab_ended = True
self._save(sess)
reply(copy.group_cannot_recreate(work_order_no=no))
return "collab_ended"
existing = (sess.collab_chat_id or "").strip()
if not existing:
getter = getattr(self._ledger, "get_ticket", None)
ticket = getter(work_order_no=no) if callable(getter) else None
if not existing and ticket is not None:
existing = str(getattr(ticket, "collab_chat_id", "") or "")
if existing:
sess.collab_chat_id = existing
@@ -402,6 +441,12 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
self._save(sess)
self._grey_clicked_card(reply, card_meta)
self._ensure_archive_seats_in_group(existing)
try:
from agent.channel.wshoto.rooms import watch_collab_room
watch_collab_room(existing, work_order_no=no)
except Exception:
logger.exception("登记已有存档监听群失败 chat=%s", existing)
reply(copy.sea_group_exists(work_order_no=no))
return "collab_group"
@@ -429,13 +474,19 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
if uid not in userids:
userids.append(uid)
client = self._group_client or _default_group_client()
client = self.group_client()
created = client.create_group(name=no, userids=userids) or {}
if not created.get("ok") or not created.get("chat_id"):
reply(copy.sea_group_create_fail(reason=str(created.get("error") or "")))
return sess.phase or "wait_collab"
chat_id = str(created.get("chat_id") or "").strip()
try:
from agent.channel.wshoto.rooms import watch_collab_room
watch_collab_room(chat_id, work_order_no=no)
except Exception:
logger.exception("登记存档监听群失败 chat=%s", chat_id)
sales_name = self._sales_display_name(sess.sender_id)
binder = getattr(self._ledger, "bind_collab_group", None)
if callable(binder):
@@ -444,6 +495,7 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
chat_id=chat_id,
member_ids=userids,
product_names=product_names,
product_ids=product_ids,
)
brief = copy.sea_group_brief(
@@ -456,8 +508,10 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
has_price=bool(sess.quote and sess.status == "已报价"),
)
client.send_group(chat_id=chat_id, content=brief)
sess.collab_chat_id = chat_id
from agent.policy.sea_group_ops import send_filled_sheet
send_filled_sheet(flow=self, ticket=None, sess=sess)
sess.invited_userids = tuple(userids)
sess.invited_sales_name = sales_name
sess.invited_product_names = tuple(product_names)
@@ -525,7 +579,7 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
seats = self._archive_seat_userids()
if not chat_id or not seats:
return
client = self._group_client or _default_group_client()
client = self.group_client()
adder = getattr(client, "add_group_members", None)
if not callable(adder):
return