后台成本价、销售价、利润点按费用逐行展示,费用合计用报价官方总价。选完线路只关页面。报价单文件名带上模板名,空运起运地和转人工跟对应工单走。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-05 12:33:34 +08:00
co-authored by Cursor
parent 7c77e45e03
commit e95e8869a6
30 changed files with 1926 additions and 75 deletions
+226
View File
@@ -345,5 +345,231 @@ class HandoffFlowOfferTests(unittest.TestCase):
self.assertIn(copy.BTN_PULL_COLLAB, bodies)
class NamedTicketHandoffTests(unittest.TestCase):
"""点名工单号转人工时,只看那一张单,不看私聊里另一张已建群的单。"""
def _flow(self):
from agent.policy.land_text_flow import LandTextInquiryFlow
from agent.ledger.memory_ledger import MemoryLedger
return LandTextInquiryFlow(MemoryLedger())
def test_deal_followup_not_blocked_by_other_group(self) -> None:
flow = self._flow()
flow._save(
FlowSession(
sender_id="s1",
thread_id="s1",
phase="wait_deal",
business_line="LAND",
work_order_no="WO202610040002",
status="已报价",
quote={"total": "CNY 800", "quoteFileIssued": True},
)
)
flow._save(
FlowSession(
sender_id="s1",
thread_id="s1",
phase="collab_group",
business_line="LAND",
work_order_no="WO202610040004",
collab_chat_id="wr_other",
status="询价中",
)
)
replies: list[str] = []
def reply(text: str, extra=None) -> str:
replies.append(text)
_ = extra
return ""
phase = flow.offer_handoff(
sender_id="s1", text="WO202610040002转人工", reply=reply
)
self.assertEqual(phase, "handoff_offer")
self.assertIn("运输方式:陆运", replies[-1])
self.assertIn("是否拉产品人员进群协同", replies[-1])
self.assertNotIn("原有空运群", replies[-1])
self.assertNotEqual(replies[-1], copy.HANDOFF_ALREADY_COLLAB)
named = flow.session_by_ticket("s1", "WO202610040002")
self.assertEqual(named.phase, "handoff_offer")
self.assertFalse((named.collab_chat_id or "").strip())
def test_named_ticket_with_group_still_blocked(self) -> None:
flow = self._flow()
flow._save(
FlowSession(
sender_id="s1",
thread_id="s1",
phase="collab_group",
business_line="LAND",
work_order_no="WO202610040002",
collab_chat_id="wr_real",
status="询价中",
)
)
replies: list[str] = []
def reply(text: str, extra=None) -> str:
replies.append(text)
_ = extra
return ""
phase = flow.offer_handoff(
sender_id="s1", text="WO202610040002转人工", reply=reply
)
self.assertEqual(phase, "handoff_already")
self.assertEqual(replies[-1], copy.HANDOFF_ALREADY_COLLAB)
def test_ledger_deal_ticket_without_group_offers_card(self) -> None:
from agent.ledger.memory_ledger import MemoryTicket
flow = self._flow()
no = "WO202610040012"
flow.ledger._tickets[no] = MemoryTicket(
work_order_no=no,
sales_wecom_id="s1",
business_line="LAND",
facts={"运输方式": "陆运"},
fingerprint="land-deal",
status="已报价",
quote={"total": "CNY 800", "quoteFileIssued": True},
quote_file_ready=True,
)
flow._save(
FlowSession(
sender_id="s1",
thread_id="s1",
phase="collab_group",
business_line="LAND",
work_order_no="WO202610040004",
collab_chat_id="wr_other",
status="询价中",
)
)
replies: list[str] = []
def reply(text: str, extra=None) -> str:
replies.append(text)
_ = extra
return ""
phase = flow.offer_handoff(sender_id="s1", text=f"{no}转人工", reply=reply)
self.assertEqual(phase, "handoff_offer")
self.assertIn("是否拉产品人员进群协同", "\n".join(replies))
self.assertNotIn(copy.HANDOFF_ALREADY_COLLAB, replies)
def test_air_deal_ticket_ignores_other_land_group(self) -> None:
"""空运成交跟进没有协同群时,不能被另一张陆运已拉群的单挡成「已拉产品进群」。"""
from agent.ledger.memory_ledger import MemoryTicket
flow = self._flow()
no = "WO202610040002"
flow.ledger._tickets[no] = MemoryTicket(
work_order_no=no,
sales_wecom_id="s1",
business_line="AIR",
facts={"运输方式": "空运", "目的港": "CRK"},
fingerprint="air-deal",
status="已报价",
quote={"total": "CNY 800", "quoteFileIssued": True},
quote_file_ready=True,
)
flow._save(
FlowSession(
sender_id="s1",
thread_id="s1",
phase="collab_group",
business_line="LAND",
work_order_no="WO202610040004",
collab_chat_id="wr_other",
status="询价中",
)
)
replies: list[str] = []
def reply(text: str, extra=None) -> str:
replies.append(text)
_ = extra
return ""
phase = flow.offer_handoff(sender_id="s1", text=f"{no}转人工", reply=reply)
joined = "\n".join(replies)
self.assertEqual(phase, "handoff_offer")
self.assertIn("原有空运群", joined)
self.assertNotIn("是否拉产品人员进群协同", joined)
self.assertNotIn(copy.HANDOFF_ALREADY_COLLAB, joined)
def test_ledger_mode_wins_over_stale_bookmark(self) -> None:
"""主账是空运时,进程里标成陆运的旧书签也不能改成陆运拉群卡。"""
from agent.ledger.memory_ledger import MemoryTicket
flow = self._flow()
no = "WO202610040002"
flow.ledger._tickets[no] = MemoryTicket(
work_order_no=no,
sales_wecom_id="s1",
business_line="AIR",
facts={},
fingerprint="air-wins",
status="已报价",
quote={"total": "CNY 800", "quoteFileIssued": True},
quote_file_ready=True,
)
flow._save(
FlowSession(
sender_id="s1",
thread_id="s1",
phase="wait_deal",
business_line="LAND",
work_order_no=no,
status="已报价",
)
)
replies: list[str] = []
def reply(text: str, extra=None) -> str:
replies.append(text)
_ = extra
return ""
phase = flow.offer_handoff(sender_id="s1", text=f"{no}转人工", reply=reply)
joined = "\n".join(replies)
self.assertEqual(phase, "handoff_offer")
self.assertIn("原有空运群", joined)
self.assertNotIn("运输方式:陆运", joined)
def test_sea_deal_ticket_uses_sea_card(self) -> None:
from agent.ledger.memory_ledger import MemoryTicket
flow = self._flow()
no = "WO202610040013"
flow.ledger._tickets[no] = MemoryTicket(
work_order_no=no,
sales_wecom_id="s1",
business_line="SEA",
facts={"运输方式": "海运"},
fingerprint="sea-deal",
status="已报价",
quote={"total": "USD 100", "quoteFileIssued": True},
quote_file_ready=True,
)
replies: list[str] = []
def reply(text: str, extra=None) -> str:
replies.append(text)
_ = extra
return ""
phase = flow.offer_handoff(sender_id="s1", text=f"{no}转人工", reply=reply)
joined = "\n".join(replies)
self.assertEqual(phase, "handoff_offer")
self.assertIn("运输方式:海运", joined)
self.assertIn("是否拉产品人员进群协同", joined)
self.assertNotIn("原有空运群", joined)
if __name__ == "__main__":
unittest.main()