"""后台回复语:按调用编码填句,失败回退默认。""" from __future__ import annotations import os import sys import unittest ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) if ROOT not in sys.path: sys.path.insert(0, ROOT) os.environ.setdefault("LEDGER_BACKEND", "memory") from agent.policy import inquiry_copy as copy from agent.policy.bot_reply import fill, override_catalog, render class BotReplyRenderTests(unittest.TestCase): def tearDown(self) -> None: override_catalog(None) def test_fill_placeholder(self) -> None: self.assertEqual(fill("工单{{ticket_no}}。", {"ticket_no": "WO1"}), "工单WO1。") self.assertEqual(fill("工单{{ ticket_no }}。", {"ticket_no": "WO1"}), "工单WO1。") self.assertIn("{{lost_reason}}", fill("因{{lost_reason}}", {})) def test_default_when_empty(self) -> None: override_catalog({}) self.assertEqual(copy.first_chat(), copy.FIRST_CHAT) self.assertEqual(copy.ask_transport(), copy.ASK_TRANSPORT) self.assertEqual(copy.deal_ack("未成交", "WO1"), "已记录为「未成交」。请补充未成交原因。") def test_override_first_chat(self) -> None: override_catalog({"inquiring.first_chat": "你好,测试问候。"}) self.assertEqual(copy.first_chat(), "你好,测试问候。") self.assertEqual(copy.FIRST_CHAT, "你好,我是询价机器人。请直接描述客户需求,例如「上海到洛杉矶空运,3 件 180kg,下周三前到」,我会解析需求并查询 TMS 标准报价。") def test_group_created_fills_names(self) -> None: override_catalog( { "inquiring.group_created": ( "协同群已创建,群名与工单号一致:{{ticket_no}}。" "已邀请:销售{{sales_name}}、产品{{product_names}}。请在群聊中继续确认报价。" ) } ) text = copy.sea_group_created( work_order_no="WO202610060001", sales_name="张三", product_names=["李四"], ) self.assertIn("WO202610060001", text) self.assertIn("销售张三", text) self.assertIn("产品李四", text) self.assertNotIn("销售销售", text) def test_disabled_falls_back(self) -> None: override_catalog({"quoted.adopt_excel": ""}) self.assertEqual(copy.adopt_excel_ack(), "已确认采用该方案,正在生成 Excel 最终报价单…") def test_group_file_saved_uses_admin(self) -> None: override_catalog({"inquiring.group_file_saved": "附件已保存后台"}) self.assertEqual( copy.quote_attachment_saved_app("WO202610060001", 2), "附件已保存后台", ) override_catalog({}) self.assertEqual( copy.quote_attachment_saved_app("WO202610060001", 2), "工单WO202610060001的2个附件已保存到后台工单", ) def test_negotiate_without_date_still_reads_admin(self) -> None: override_catalog( { "negotiating.recorded": ( "已记录为「协商中」。已顺延三个工作日,{{followup_when}}的9:00再次发起成交状态询问。" ) } ) text = copy.deal_ack("协商中", "WO1", next_followup_at="") self.assertIn("第四个工作日", text) self.assertIn("9:00", text) def test_group_add_fail_empty_names_reads_admin(self) -> None: override_catalog( {"sys.group_add_fail": "无法添加 {{staff_name}} 同事,请联系管理员检查企业微信配置。"} ) text = copy.system_exception_fallback(copy.TYPE_GROUP, names=[]) self.assertEqual(text, "无法添加同事,请联系管理员检查企业微信配置。") named = copy.system_exception_fallback(copy.TYPE_GROUP, names=["张三"]) self.assertIn("张三", named) if __name__ == "__main__": unittest.main()