""" 空运询价字段合同:起运港非必填,5 个新非必填,贸易条款不进出站。 """ 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("YTD_ENV", "test") from agent.ledger.memory_ledger import MemoryLedger from agent.policy import inquiry_copy as copy from agent.policy.air_text_flow import AirTextInquiryFlow from agent.schema.field_validate import ( air_general_cargo_collab_defaults, validate_required_fields, ) from agent.schema.tms_air_query import assemble_air_query class AirFieldContractTests(unittest.TestCase): def test_origin_optional_still_ok(self) -> None: result = validate_required_fields( facts={ "目的港": "克拉克", "品名": "茶叶", "件数": "10", "毛重": "100", "体积": "2", "包装方式": "托盘", }, business_line="AIR", ) self.assertTrue(result["ok"]) self.assertNotIn("起运港", result["missing"]) def test_dest_still_required(self) -> None: result = validate_required_fields( facts={ "品名": "茶叶", "件数": "10", "毛重": "100", "体积": "2", "包装方式": "托盘", }, business_line="AIR", ) self.assertFalse(result["ok"]) self.assertIn("目的港", result["missing"]) def test_assemble_without_origin_ok_and_keeps_optional(self) -> None: out = assemble_air_query( { "目的港": "克拉克", "品名": "茶叶", "件数": "10件", "毛重": "100KGS", "体积": "2CBM", "包装方式": "托盘", "报价日期": "2026-09-22", "货源地": "东莞", "货好时间": "随时", "提货地址": "东莞仓库", "收货地址": "马尼拉", "贸易条款": "FOB", } ) self.assertTrue(out["ok"]) self.assertNotIn("起运港", out["missing"]) facts = out["facts"] self.assertEqual(facts["货源地"], "东莞") self.assertEqual(facts["货好时间"], "随时") self.assertEqual(facts["提货地址"], "东莞仓库") self.assertEqual(facts["收货地址"], "马尼拉") self.assertEqual(facts["贸易条款"], "FOB") self.assertNotIn("tradeTerms", facts) self.assertNotIn("transportTerms", facts) def test_confirm_card_lists_optional_and_has_no_work_order(self) -> None: text = copy.air_confirm_card( { "目的港": "克拉克", "品名": "茶叶", "件数": "10", "毛重": "100", "体积": "2", "包装方式": "托盘", "报价日期": "2026-09-22", } ) self.assertNotIn("工单号", text) self.assertIn("目的地(必填):克拉克", text) self.assertIn("起运港(非必填):", text) self.assertIn("货源地(非必填):", text) self.assertIn("贸易条款(非必填):", text) self.assertIn(copy.AIR_CONFIRM_TAIL, text) def test_empty_origin_confirm_then_quote(self) -> None: flow = AirTextInquiryFlow(MemoryLedger()) replies: list[str] = [] def reply(text: str, extra=None) -> None: replies.append(text) _ = extra phase = flow.on_text( sender_id="u_no_pol", text="空运", reply=reply, injected_facts={ "目的港": "克拉克", "品名": "茶叶", "件数": "10", "毛重": "100", "体积": "2", "包装方式": "托盘", }, injected_mode="AIR", ) self.assertEqual(phase, "wait_confirm") self.assertFalse(flow.session_of("u_no_pol").work_order_no) self.assertIn(copy.AIR_CONFIRM_TAIL, replies[-1]) phase = flow.on_text(sender_id="u_no_pol", text="确定", reply=reply) self.assertEqual(phase, "wait_collab") self.assertTrue(flow.session_of("u_no_pol").work_order_no) def test_assemble_keeps_raw_package_not_code(self) -> None: """包装出站跟销售原文,禁止编成 1/2/3。""" out = assemble_air_query( { "起运港": "珠海", "目的港": "克拉克", "品名": "茶叶", "件数": "10件", "毛重": "100KGS", "体积": "2CBM", "包装方式": "托盘", "报价日期": "2026-09-22", } ) self.assertTrue(out["ok"]) facts = out["facts"] self.assertEqual(facts["包装方式"], "托盘") self.assertEqual(facts["packageType"], "托盘") self.assertEqual(facts["originCode"], "ZUH") self.assertEqual(facts["destinationCode"], "CRK") self.assertNotIn("origin", facts) self.assertNotIn("destination", facts) def test_assemble_missing_dest_still_blocks(self) -> None: out = assemble_air_query( { "品名": "茶叶", "件数": "10", "毛重": "100", "体积": "2", "包装方式": "托盘", "报价日期": "2026-09-22", } ) self.assertFalse(out["ok"]) self.assertIn("目的港", out["missing"]) def test_general_cargo_defaults_battery_and_magnet(self) -> None: """品名正好是普货,含电含磁还空着才默认否。""" self.assertEqual( air_general_cargo_collab_defaults({"品名": "普货"}), {"是否含电": "否", "是否含磁": "否"}, ) self.assertEqual( air_general_cargo_collab_defaults({"货物品名": "普货"}), {"是否含电": "否", "是否含磁": "否"}, ) self.assertEqual( air_general_cargo_collab_defaults({"品名": "普货", "是否含电": "是"}), {"是否含磁": "否"}, ) self.assertEqual(air_general_cargo_collab_defaults({"品名": "配件"}), {}) self.assertEqual(air_general_cargo_collab_defaults({"品名": "普货纸箱"}), {}) if __name__ == "__main__": unittest.main()