确定运输方式前的多句询价带到所选方式并按该方式抽字段;成交已定后放舱不再推跟进,未成交原因不再被当成新询价。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -414,6 +414,148 @@ class LandDispatchTests(unittest.TestCase):
|
||||
self.assertNotIn("你好,我是询价机器人", last)
|
||||
self.assertNotIn("请直接描述客户需求", last)
|
||||
|
||||
def test_lost_reason_not_taken_as_new_inquiry(self) -> None:
|
||||
"""未成交后下一句是原因。旧报价单被判成调价时,不能改问运输方式。"""
|
||||
from agent.policy.air_text_flow import FlowSession
|
||||
|
||||
sea = get_sea_text_flow()
|
||||
created = sea._ledger.create_ticket(
|
||||
sender_id="lost-1",
|
||||
business_line="SEA",
|
||||
facts={"起运港": "广州港", "目的港": "巴生港", "品名": "机器设备"},
|
||||
)
|
||||
wo = str(created.get("work_order_no") or "")
|
||||
sea._ledger.transition(work_order_no=wo, to_status="未成交")
|
||||
sea._save(
|
||||
FlowSession(
|
||||
sender_id="lost-1",
|
||||
thread_id="lost-1",
|
||||
phase="wait_lost_reason",
|
||||
business_line="SEA",
|
||||
work_order_no=wo,
|
||||
status="未成交",
|
||||
wait_version=2,
|
||||
)
|
||||
)
|
||||
get_land_text_flow()._save(
|
||||
FlowSession(
|
||||
sender_id="lost-1",
|
||||
thread_id="lost-1",
|
||||
phase="wait_deal",
|
||||
business_line="LAND",
|
||||
work_order_no="WO202609240045",
|
||||
status="已报价",
|
||||
quote={"total": "CNY 1"},
|
||||
)
|
||||
)
|
||||
phase = handle_text_inquiry(
|
||||
InboundMessage(sender_id="lost-1", message_id="m-lost", content="客户不需要了"),
|
||||
prefer_quoted=True,
|
||||
store=self.store,
|
||||
)
|
||||
self.assertEqual(phase, "done")
|
||||
body = self._outbox_text()
|
||||
self.assertIn("已记下未成交原因:客户不需要了", body)
|
||||
self.assertNotIn("告知我询价的运输方式", body)
|
||||
|
||||
def test_several_turns_before_mode_follow_the_chosen_line(self) -> None:
|
||||
"""定运输方式前连续几句询价字段都要留下,选定后再整份带上。不只认上一句。"""
|
||||
from agent.policy.air_text_flow import FlowSession, get_air_text_flow
|
||||
|
||||
turns = (
|
||||
(
|
||||
"a",
|
||||
"10月1日,深圳-吉隆坡,散货、普货报价",
|
||||
{
|
||||
"起运港": "深圳",
|
||||
"目的港": "吉隆坡",
|
||||
"品名": "普货",
|
||||
"包装方式": "散货",
|
||||
"报价日期": "2026-10-01",
|
||||
},
|
||||
),
|
||||
(
|
||||
"b",
|
||||
"10件,毛重100公斤,体积2方",
|
||||
{"件数": "10", "毛重": "100", "体积": "2"},
|
||||
),
|
||||
)
|
||||
for label, reply, mode in (
|
||||
("空运", "3", "AIR"),
|
||||
("海运", "海运", "SEA"),
|
||||
("陆运", "1", "LAND"),
|
||||
):
|
||||
reset_sea_text_flow_for_test()
|
||||
reset_land_text_flow_for_test()
|
||||
reset_air_text_flow_for_test()
|
||||
sid = "premode-" + mode
|
||||
# 上一单还在海运,新的几句里没有运输方式,不能把这些字段丢掉。
|
||||
get_sea_text_flow()._save(
|
||||
FlowSession(
|
||||
sender_id=sid,
|
||||
thread_id=sid,
|
||||
phase="tms_miss",
|
||||
business_line="SEA",
|
||||
work_order_no="WO-OLD",
|
||||
facts={"目的港": "旧港口"},
|
||||
)
|
||||
)
|
||||
for mid, content, facts in turns:
|
||||
phase = handle_text_inquiry(
|
||||
InboundMessage(sender_id=sid, message_id=sid + mid, content=content),
|
||||
injected_facts=facts,
|
||||
injected_mode="",
|
||||
store=self.store,
|
||||
)
|
||||
self.assertEqual(phase, "need_mode", label)
|
||||
waiting = get_sea_text_flow().session_of(sid)
|
||||
self.assertEqual(waiting.facts.get("目的港"), "吉隆坡", label)
|
||||
self.assertIn("10", waiting.facts.get("件数") or "", label)
|
||||
self.assertIn("深圳-吉隆坡", waiting.immutable_text)
|
||||
self.assertIn("10件", waiting.immutable_text)
|
||||
before = len(self.store._outbox)
|
||||
phase = handle_text_inquiry(
|
||||
InboundMessage(sender_id=sid, message_id=sid + "mode", content=reply),
|
||||
store=self.store,
|
||||
)
|
||||
self.assertNotEqual(phase, "need_mode", label)
|
||||
added = "\n".join(i.content for i in list(self.store._outbox.values())[before:])
|
||||
owner = {
|
||||
"AIR": get_air_text_flow(),
|
||||
"SEA": get_sea_text_flow(),
|
||||
"LAND": get_land_text_flow(),
|
||||
}[mode]
|
||||
sess = owner.session_of(sid)
|
||||
self.assertIsNotNone(sess, label)
|
||||
self.assertEqual((sess.business_line or "").upper(), mode, label)
|
||||
self.assertEqual(sess.facts.get("起运港"), "深圳", label)
|
||||
self.assertEqual(sess.facts.get("目的港"), "吉隆坡", label)
|
||||
self.assertEqual(sess.facts.get("品名"), "普货", label)
|
||||
self.assertEqual(sess.facts.get("报价日期"), "2026-10-01", label)
|
||||
self.assertNotEqual(sess.facts.get("目的港"), "旧港口", label)
|
||||
if mode == "AIR":
|
||||
self.assertIn("10", sess.facts.get("件数") or "", label)
|
||||
self.assertNotIn("整柜或拼柜", sess.facts, label)
|
||||
self.assertNotIn("箱型箱量", sess.facts, label)
|
||||
elif mode == "SEA":
|
||||
self.assertIn("10", sess.facts.get("货量") or "", label)
|
||||
self.assertNotIn("件数", sess.facts, label)
|
||||
self.assertNotIn("毛重", sess.facts, label)
|
||||
self.assertNotIn("包装方式", sess.facts, label)
|
||||
self.assertIn("货物数量", added)
|
||||
self.assertIn("整柜或拼柜", added)
|
||||
self.assertIn("箱型箱量", added)
|
||||
self.assertIn("贸易条款", added)
|
||||
self.assertNotIn("件数(必填)", added)
|
||||
else:
|
||||
self.assertIn("100", sess.facts.get("毛重") or "", label)
|
||||
self.assertIn("2", sess.facts.get("体积") or "", label)
|
||||
self.assertNotIn("件数", sess.facts, label)
|
||||
self.assertNotIn("箱型箱量", sess.facts, label)
|
||||
self.assertNotIn("贸易条款", sess.facts, label)
|
||||
self.assertIn("运输类型", added)
|
||||
self.assertNotIn("件数(必填)", added)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user