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

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
+52 -18
View File
@@ -296,29 +296,22 @@ class AirTextInquiryTests(unittest.TestCase):
self.assertEqual(phase, "wait_deal")
self.assertIn("Excel", "\n".join(self.replies))
self.assertIn("咨询成交状态", "\n".join(self.replies))
deal_cards = [
x["template_card"]
for x in self.extras
if x.get("msgtype") == "template_card"
and str((x.get("template_card") or {}).get("task_id") or "").startswith("deal-")
]
self.assertTrue(deal_cards)
deal_rows = {r["keyname"]: r["value"] for r in deal_cards[-1]["horizontal_content_list"]}
file_extras = [x for x in self.extras if x.get("msgtype") == "file"]
self.assertTrue(file_extras)
follow = file_extras[-1].get("followup_card") or {}
self.assertTrue(str(follow.get("task_id") or "").startswith("deal-"))
deal_rows = {r["keyname"]: r["value"] for r in follow.get("horizontal_content_list") or []}
self.assertIn("总销售价合计", deal_rows)
self.assertNotIn("历史报价", deal_rows)
self.assertNotIn("工单状态", deal_rows)
self.assertNotIn("来源", deal_rows)
file_idx = next(
i for i, x in enumerate(self.extras) if x.get("msgtype") == "file"
)
deal_idx = next(
i
for i, x in enumerate(self.extras)
separate_deal = [
x
for x in self.extras
if x.get("msgtype") == "template_card"
and str((x.get("template_card") or {}).get("task_id") or "").startswith("deal-")
)
self.assertLess(file_idx, deal_idx)
]
self.assertEqual(separate_deal, [])
phase = self.flow.on_button(
sender_id="u1",
action=copy.BTN_DEAL,
@@ -1268,7 +1261,7 @@ class AirTextInquiryTests(unittest.TestCase):
source="test",
)
self.assertEqual(replay, "wait_deal")
self.assertIn("咨询成交状态", "\n".join(again))
self.assertNotIn("咨询成交状态", "\n".join(again))
self.assertEqual(http.session_of("u-pdf-x").phase, "wait_deal")
def test_deal_click_works_while_http_still_wait_file(self) -> None:
@@ -1315,3 +1308,44 @@ class AirTextInquiryTests(unittest.TestCase):
self.assertEqual(phase, "done")
self.assertEqual(flow.session_of("u-pdf-d").phase, "done")
self.assertTrue(any(x.get("msgtype") == "update_template_card" for x in extras))
class FileThenDealOrderTests(unittest.TestCase):
def test_send_outbound_sends_file_before_followup_card(self) -> None:
"""同一条出站必须先传文件再发成交卡。"""
from agent.channel.outbox.sender import WeComAppClient, WeComSendResult
order: list[str] = []
class _Client(WeComAppClient):
def send_file(self, **kwargs): # type: ignore[override]
order.append("file")
return WeComSendResult(ok=True)
def _post_message(self, body, preview=""): # type: ignore[override]
order.append(str(preview or body.get("msgtype")))
return WeComSendResult(ok=True)
client = _Client(corp_id="c", secret="s", agent_id=1)
client._followup_gap_sec = 0
client.send_outbound(
touser="u1",
content="file+deal",
payload={
"msgtype": "file",
"filename": "WO1.xlsx",
"file_b64": "QQ==",
"followup_card": {"task_id": "deal-WO1"},
},
)
self.assertEqual(order, ["file", "[followup_card]"])
def test_wait_outbound_stays_until_claimed_item_finishes(self) -> None:
"""已被认领的出站必须等到发完,不能中途当成功。"""
store = MemoryMessageStore()
ok, oid = store.enqueue_outbound(touser="u1", content="报价文件")
self.assertTrue(ok)
claimed = store.claim_outbound()
self.assertIsNotNone(claimed)
done = store.wait_outbound_done(oid, timeout_sec=0.45)
self.assertFalse(done)