落地空运单聊询价字段与线路选择。
必填核对后再建单;多条线路走 H5 点选;费用只展示该线路 TMS 回包,不套用整单空运费。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
"""
|
||||
空运询价字段合同:起运港非必填,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 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"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user