落地多段联运私聊:齐了才建单拉群,附件只收格子值,核对改正不再整单重开。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 15:08:15 +08:00
co-authored by Cursor
parent 6e3e09a316
commit 2334524bb8
30 changed files with 4033 additions and 40 deletions
+50 -6
View File
@@ -286,18 +286,21 @@ def resolve_group_mentions(
flow: Any,
ticket: object,
sess: Any = None,
fallback_sales_id: str = "",
) -> tuple[str, list[str], list[str]]:
"""
群摘要必须 @ 到具体销售和每位产品,禁止只写岗位词「销售」。
进程重启后内存会话没了,主账 byCollabChat 也可能不带姓名:
用销售 userid + 群成员(去掉存档账号)反查员工管理。
进程重启后内存会话没了,主账 byCollabChat / getForAgent 也可能不带姓名或企微号:
用销售 userid(没有则用发言人)+ 群成员(去掉存档账号)反查员工管理。
查不到姓名就用 userid,仍然是具体人。
返回:(销售展示名, 产品展示名列表, 要点到的 userid)。
"""
view = ticket_view(ticket)
sales_id = str(view.get("sales_wecom_id") or view.get("salesWecomId") or "").strip()
if sess is not None:
sales_id = sales_id or str(getattr(sess, "sales_wecom_id", "") or getattr(sess, "sender_id", "") or "").strip()
sales_id = sales_id or (fallback_sales_id or "").strip()
members = [
str(x).strip()
for x in (view.get("collab_member_ids") or view.get("memberIds") or [])
@@ -323,10 +326,10 @@ def resolve_group_mentions(
sales_name = sales_name or str(view.get("sales_name") or view.get("salesName") or "").strip()
if not sales_name or sales_name == "销售":
looked = _staff_display_name(flow, sales_id) if sales_id else ""
if looked:
if looked and looked != "销售":
sales_name = looked
if not sales_name:
sales_name = sales_id or "销售"
if not sales_name or sales_name == "销售":
sales_name = sales_id
products: list[str] = []
if sess is not None:
@@ -383,7 +386,19 @@ def hydrate_ticket(flow: Any, ticket: object) -> object:
facts = dict(view.get("facts") or {})
has_facts = any(
str(facts.get(k) or "").strip()
for k in ("起运港", "目的港", "品名", "货量", "起运地", "目的地", "件数", "毛重")
for k in (
"起运港",
"目的港",
"品名",
"货量",
"起运地",
"目的地",
"件数",
"毛重",
"运输类型",
"始发站",
"目的站",
)
)
quote = dict(view.get("quote") or {})
has_quote = bool(quote.get("total") or _quote_fee_rows(quote))
@@ -515,6 +530,28 @@ def send_brief_and_sheet(
return "brief_and_sheet"
def _has_sheet_inquiry_facts(facts: dict[str, Any]) -> bool:
"""段票/填表票是否已带可匹配模板的询价字段。"""
src = dict(facts or {})
return any(
str(src.get(k) or "").strip()
for k in (
"起运港",
"目的港",
"品名",
"货量",
"起运地",
"目的地",
"件数",
"毛重",
"运输类型",
"线路类别",
"始发站",
"目的站",
)
)
def send_filled_sheet(
*,
flow: Any,
@@ -529,6 +566,8 @@ def send_filled_sheet(
business_line 决定匹配哪套后台模板;空运必须传 AIR,禁止落到海运默认模板。
"""
incoming_view = ticket_view(ticket) if ticket is not None else {}
incoming_facts = dict(incoming_view.get("facts") or {})
ticket = hydrate_ticket(flow, ticket)
view = ticket_view(ticket) if ticket is not None else {}
no = (sess.work_order_no if sess else "") or ticket_no(ticket)
@@ -539,6 +578,11 @@ def send_filled_sheet(
or ""
).strip()
facts = dict(view.get("facts") or {})
# 段票已带询价字段时,禁止被主账 MULTI 快照(往往只有 segments_json)盖掉。
if _has_sheet_inquiry_facts(incoming_facts):
merged = dict(facts)
merged.update({k: v for k, v in incoming_facts.items() if str(v or "").strip()})
facts = merged
if sess is not None and getattr(sess, "facts", None):
facts.update(dict(sess.facts or {}))
collab = dict(view.get("collab_facts") or {})