feat: 海运查价带贸易条款且不带运输分类

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-20 17:47:12 +08:00
co-authored by Cursor
parent 27aeebb593
commit 3a6884e27d
6 changed files with 67 additions and 5 deletions
+2 -1
View File
@@ -249,7 +249,8 @@ class SeaTextInquiryFlow(AirTextInquiryFlow):
) or ""
self._wait_inquiry_sent(str(out_id), work_order_no=no)
tms = self._ledger.query_tms(work_order_no=no, facts=facts, business_line="SEA")
tms_facts = dict(assemble_sea_query(facts).get("tms_facts") or facts)
tms = self._ledger.query_tms(work_order_no=no, facts=tms_facts, business_line="SEA")
sess = FlowSession(
sender_id=sender_id,
thread_id=sender_id,
+12 -1
View File
@@ -1,8 +1,9 @@
"""
海运查价参数:对照 TMS V2 /quote/v2/query 是否带全。
本文件职责:询价卡片出现前,确认海运七项能拼出查价正文。
本文件职责:询价卡片出现前,确认海运十项里查出站项能拼出查价正文。
港口只带名称,不做港口字典对应;箱型箱量保持原文字段,containerItems 只透传模型投影。
贸易条款必带出站;运输分类只留在工单 facts,不进 tms_facts。
禁止:本地拆箱型;因对不上港口字典跳过 TMS;改六态。
"""
@@ -62,6 +63,8 @@ def assemble_sea_query(facts: dict[str, Any] | None) -> dict[str, Any]:
load = _load_type(str(src.get("整柜或拼柜") or ""))
box = str(src.get("箱型箱量") or "").strip()
quote_date = str(src.get("报价日期") or "").strip()
trade = str(src.get("贸易条款") or src.get("trade_terms") or src.get("tradeTerms") or "").strip()
klass = str(src.get("运输分类") or "").strip()
missing: list[str] = []
missing_display: list[str] = []
@@ -72,6 +75,7 @@ def assemble_sea_query(facts: dict[str, Any] | None) -> dict[str, Any]:
("货量", "货物数量", qty),
("整柜或拼柜", "整柜或拼柜", load),
("箱型箱量", "箱型箱量", box),
("贸易条款", "贸易条款", trade),
("报价日期", "报价日期", quote_date),
)
for key, label, val in pairs:
@@ -93,12 +97,18 @@ def assemble_sea_query(facts: dict[str, Any] | None) -> dict[str, Any]:
out_facts["整柜或拼柜"] = load
if box:
out_facts["箱型箱量"] = box
if trade:
out_facts["贸易条款"] = trade
if klass:
out_facts["运输分类"] = klass
if quote_date:
out_facts["报价日期"] = quote_date
items = parse_container_items(src)
if items:
out_facts["containerItems"] = items
tms_facts = dict(out_facts)
tms_facts.pop("运输分类", None)
logger.info(
"tms.sea.assemble ok=%s origin=%s dest=%s load=%s missing=%s",
ok,
@@ -112,4 +122,5 @@ def assemble_sea_query(facts: dict[str, Any] | None) -> dict[str, Any]:
"missing": missing,
"missing_display": missing_display,
"facts": out_facts,
"tms_facts": tms_facts,
}
+23 -1
View File
@@ -273,11 +273,33 @@ class SeaTmsCardTests(unittest.TestCase):
self.extras.append(dict(extra) if extra else {})
def test_assemble_sea_query_does_not_need_air_measures(self) -> None:
ready = assemble_sea_query(COMPLETE_SEA)
ready = assemble_sea_query({**COMPLETE_SEA, "贸易条款": "FOB", "运输分类": "Port to Port"})
self.assertTrue(ready["ok"])
self.assertEqual(ready["missing"], [])
self.assertNotIn("件数", ready.get("missing") or [])
def test_assemble_requires_trade_terms_not_class(self) -> None:
src = {
"起运港": "上海",
"目的港": "洛杉矶",
"品名": "普货",
"货量": "20吨",
"整柜或拼柜": "整柜",
"箱型箱量": "1x40HQ",
"运输分类": "Port to Port",
}
missing = assemble_sea_query(src)
self.assertFalse(missing["ok"])
self.assertIn("贸易条款", missing["missing"])
self.assertNotIn("运输分类", missing["missing"])
src["贸易条款"] = "FOB"
ready = assemble_sea_query(src)
self.assertTrue(ready["ok"])
self.assertEqual(ready["tms_facts"]["贸易条款"], "FOB")
self.assertNotIn("运输分类", ready["tms_facts"])
self.assertEqual(ready["facts"]["运输分类"], "Port to Port")
def test_long_fee_lines_go_to_text_not_clipped_card(self) -> None:
"""海运多项费用:完整明细必须在文本里,卡片引用条不得半截。"""
long_quote = {