落地空运群内协同与锁舱出站。
群里按 BOT 通道激活当前工单、航线报价和成交跟进;没有 TMS 报价编号时用工单字段补齐仍调锁舱,避免被本地规则拦住。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -248,7 +248,7 @@ class MemoryLedger:
|
||||
quote=quote,
|
||||
)
|
||||
if picked is None:
|
||||
out = {"ok": False, "error": "NO_TEMPLATE", "message": FAIL_MESSAGE}
|
||||
out = {"ok": False, "error": "NO_TEMPLATE", "message": FAIL_MESSAGE, "facts": dict(facts or {})}
|
||||
self.last_render = out
|
||||
return out
|
||||
ext = "pdf" if str(format).lower() == "pdf" else "xlsx"
|
||||
@@ -260,6 +260,7 @@ class MemoryLedger:
|
||||
"fileName": f"{work_order_no}_quote.{ext}",
|
||||
"fileBase64": "UEsDBAoAAAAAA",
|
||||
"needsPdf": False,
|
||||
"facts": dict(facts or {}),
|
||||
}
|
||||
with self._lock:
|
||||
ticket = self._tickets.get((work_order_no or "").strip())
|
||||
@@ -359,6 +360,18 @@ class MemoryLedger:
|
||||
with self._lock:
|
||||
return dict(self._staff_by_wecom.get((wecom_id or "").strip()) or {})
|
||||
|
||||
def list_staff_by_role(self, *, role_code: str) -> list[dict[str, Any]]:
|
||||
"""按岗位列出启用员工。空运群 @ 航线用。"""
|
||||
want = (role_code or "").strip().lower()
|
||||
hits: list[dict[str, Any]] = []
|
||||
with self._lock:
|
||||
for row in self._staff_by_wecom.values():
|
||||
code = str(row.get("roleCode") or row.get("role_code") or "").strip().lower()
|
||||
status = str(row.get("status") or "active").strip().lower()
|
||||
if code == want and status not in {"disabled", "0", "停用"}:
|
||||
hits.append(dict(row))
|
||||
return hits
|
||||
|
||||
def find_staff_by_name(self, *, name: str) -> dict[str, Any]:
|
||||
"""按员工姓名取企微 userid。"""
|
||||
with self._lock:
|
||||
@@ -442,9 +455,15 @@ class MemoryLedger:
|
||||
ticket = self._tickets.get(work_order_no)
|
||||
if ticket is None:
|
||||
return {"ok": False, "error": "ticket_not_found"}
|
||||
ticket.collab_facts.update(
|
||||
{k: v for k, v in (facts or {}).items() if str(v or "").strip()}
|
||||
)
|
||||
for key, raw in (facts or {}).items():
|
||||
name = str(key or "").strip()
|
||||
if not name:
|
||||
continue
|
||||
val = str(raw or "").strip()
|
||||
if val:
|
||||
ticket.collab_facts[name] = val
|
||||
else:
|
||||
ticket.collab_facts.pop(name, None)
|
||||
return {"ok": True, "facts": dict(ticket.collab_facts)}
|
||||
|
||||
def find_by_collab_chat(self, *, chat_id: str) -> MemoryTicket | None:
|
||||
@@ -457,3 +476,81 @@ class MemoryLedger:
|
||||
if ticket.collab_chat_id == raw:
|
||||
return ticket
|
||||
return None
|
||||
|
||||
def activate_air_group(self, *, chat_id: str, work_order_no: str) -> dict[str, Any]:
|
||||
"""
|
||||
空运群当前工单:一单一群,未结案才能激活。
|
||||
|
||||
不改六态。
|
||||
"""
|
||||
no = (work_order_no or "").strip()
|
||||
room = (chat_id or "").strip()
|
||||
with self._lock:
|
||||
ticket = self._tickets.get(no)
|
||||
if ticket is None:
|
||||
return {"ok": False, "error": "ticket_not_found"}
|
||||
if (ticket.business_line or "").upper() != "AIR":
|
||||
return {"ok": False, "error": "not_air", "status": ticket.status}
|
||||
if ticket.status in {"已成交", "未成交", "已关闭"}:
|
||||
return {"ok": False, "error": "terminal", "status": ticket.status}
|
||||
if ticket.collab_chat_id and ticket.collab_chat_id != room:
|
||||
return {"ok": False, "error": "occupied", "other_chat_id": ticket.collab_chat_id}
|
||||
for other in self._tickets.values():
|
||||
if other.work_order_no != no and other.collab_chat_id == room:
|
||||
if (other.business_line or "").upper() == "AIR":
|
||||
other.collab_chat_id = ""
|
||||
ticket.collab_chat_id = room
|
||||
return {
|
||||
"ok": True,
|
||||
"work_order_no": no,
|
||||
"chat_id": room,
|
||||
"status": ticket.status,
|
||||
"business_line": ticket.business_line,
|
||||
}
|
||||
|
||||
def lock_cabin(
|
||||
self,
|
||||
*,
|
||||
work_order_no: str,
|
||||
option_no: str,
|
||||
sender_id: str = "",
|
||||
operator_name: str = "",
|
||||
instruction_text: str = "",
|
||||
) -> dict[str, Any]:
|
||||
"""单测可注入 _cabin_lock_result;默认成功。"""
|
||||
_ = sender_id, operator_name, instruction_text
|
||||
forced = getattr(self, "_cabin_lock_result", None)
|
||||
if isinstance(forced, dict):
|
||||
return dict(forced)
|
||||
no = (work_order_no or "").strip()
|
||||
ticket = self.get_ticket(work_order_no=no)
|
||||
quote = dict(ticket.quote or {}) if ticket else {}
|
||||
return {
|
||||
"ok": True,
|
||||
"status": "LOCKED",
|
||||
"lockId": f"CA-{no}-LOCK",
|
||||
"quoteId": str(quote.get("quoteId") or f"QT-{no}"),
|
||||
"optionNo": option_no,
|
||||
"tmsRequestId": f"TMS-LOCK-{no}",
|
||||
}
|
||||
|
||||
def release_cabin(
|
||||
self,
|
||||
*,
|
||||
work_order_no: str,
|
||||
lock_id: str,
|
||||
sender_id: str = "",
|
||||
operator_name: str = "",
|
||||
instruction_text: str = "",
|
||||
) -> dict[str, Any]:
|
||||
_ = lock_id, sender_id, operator_name, instruction_text
|
||||
forced = getattr(self, "_cabin_release_result", None)
|
||||
if isinstance(forced, dict):
|
||||
return dict(forced)
|
||||
no = (work_order_no or "").strip()
|
||||
return {
|
||||
"ok": True,
|
||||
"status": "RELEASED",
|
||||
"releaseId": f"CA-{no}-RLSE",
|
||||
"tmsRequestId": f"TMS-RLSE-{no}",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user