陆运补问把货物品名放进选项清单,并按销售原文回显已填项。

空着的运输分类不再被菜单第一项认成已填。空运报价改为货物信息加价格方案,锁舱成功回执补起运地、目的地、航司和航班日期。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-14 17:39:54 +08:00
co-authored by Cursor
parent cc8529f569
commit 9ffba70741
21 changed files with 1129 additions and 130 deletions
+89 -2
View File
@@ -341,6 +341,59 @@ class AirGroupCollabTests(unittest.TestCase):
self.assertIn("报价有效期:2026-09-30", tms_block)
self.assertIn("请航线人员回复“确认报价”确定采用TMS报价。", text)
self.assertIn("亦可通过“纯文字”告知新报价,或直接将新报价excel表发给智能体。", text)
self.assertNotIn("询价字段:", text)
self.assertIn("备注:-", text)
def test_air_group_brief_with_tms_uses_cargo_and_price_shape(self) -> None:
"""有 TMS 报价时,群摘要换成货物信息和三种费用写法。普货含电含磁仍是「否」。"""
tms = {
"source": "TMS",
"total": "87150.0",
"currency": "CNY",
"valid_until": "2026-10-31",
"remark": "其他杂费如有实报实销",
"airlineCode": "TH",
"chargeableWeightKg": "8300",
"cargoType": "1:212",
"fee_lines": [
{"name": "空运费", "currency": "CNY", "unit": "KG", "unitPrice": 11, "amount": "91300"},
{"name": "文件费", "currency": "CNY", "unit": "票", "amount": "300"},
],
}
text = copy.air_group_brief(
work_order_no="WO202610090040",
facts={
"起运地": "NKG",
"目的地": "KUL",
"品名": "普货",
"件数": "800箱",
"毛重": "8300KG",
"体积": "39CBM",
"包装类型": "散货",
"报价日期": "2026-10-09",
},
quote=tms,
collab_facts={},
has_price=True,
tms_quote=tms,
sales_name="吴季林",
airline_names=["高芸"],
)
self.assertTrue(text.startswith("@吴季林 @高芸"))
self.assertNotIn("询价字段:", text)
self.assertIn("航司:TH", text)
self.assertIn("计费重:8300KG", text)
self.assertIn("货型:1:212", text)
self.assertIn("是否含电:否", text)
self.assertIn("是否含磁:否", text)
tms_block = text.split("TMS报价:", 1)[1]
self.assertIn("空运费:单价CNY11/KG", tms_block)
self.assertIn("文件费:CNY300/票", tms_block)
self.assertIn("备注:其他杂费如有实报实销", tms_block)
self.assertIn("费用合计:CNY 87150.0", tms_block)
self.assertIn("报价有效期:2026-10-31", tms_block)
self.assertIn("请航线人员回复“确认报价”确定采用TMS报价。", text)
self.assertLess(tms_block.find("报价有效期:"), tms_block.find("请航线人员"))
self.assertIn("附件报价单仅作为文件存储于后台,智能体不读取且不将报价内容写进系统", text)
self.assertNotIn("请产品人员回复", text)
@@ -1111,7 +1164,7 @@ class AirGroupCollabTests(unittest.TestCase):
injected_intent="air_pick_option",
)
self.assertEqual(phase, "lock_ok")
self.assertTrue(any("执行成功" in t for t in self._texts()))
self.assertTrue(any("TMS空运锁舱成功" in t for t in self._texts()))
def test_tms_quote_with_selected_cabin_locks_without_asking_params(self) -> None:
"""TMS 已有 selected_air_option:直接锁,不追问舱位/航司/航班(WO014)。"""
@@ -1162,6 +1215,40 @@ class AirGroupCollabTests(unittest.TestCase):
self.assertEqual(calls[0].get("flight_no"), "JG2719")
self.assertFalse(any("锁舱参数不完整" in t for t in self._texts()))
def test_lock_ok_reply_includes_route(self) -> None:
"""锁舱成功回执带出本次舱位的起运地、目的地、航司、航班日期。"""
wo = self._create_air(
quote={
"total": "1800",
"source": "TMS",
"source_label": "航线确认TMS",
"quoteId": "AIR-2099695579169554433-2099695579182137346",
"selected_air_option": {
"optionNo": "AIR-OPT01",
"airlineCode": "TH",
"flightNo": "TH123",
"originAirportCode": "NKG",
"destinationAirportCode": "KUL",
"flightDate": "2026-10-15",
},
},
status="已成交",
)
phase = handle_air_group(
self._msg(sender="air1", text=f"{wo}锁舱", chat="wr_air_lock_route", mid="route1"),
flow=self.flow,
ledger=self.ledger,
injected_intent="air_lock",
)
self.assertEqual(phase, "lock_ok")
text = self._texts()[-1]
self.assertIn("TMS空运锁舱成功。", text)
self.assertIn("舱位选项:AIR-OPT01", text)
self.assertIn("起运地:NKG", text)
self.assertIn("目的地:KUL", text)
self.assertIn("航司:TH", text)
self.assertIn("航班日期:2026-10-15", text)
def test_lock_missing_params_asks_and_does_not_call_tms(self) -> None:
"""无舱位明细时缺三项才请补,不锁舱、不报 TMS 失败、不通知 IT。"""
wo = self._create_air(
@@ -1318,7 +1405,7 @@ class AirGroupCollabTests(unittest.TestCase):
injected_intent="air_lock",
)
self.assertEqual(phase, "lock_ok")
self.assertTrue(any("执行成功" in t for t in self._texts()))
self.assertTrue(any("TMS空运锁舱成功" in t for t in self._texts()))
self.assertFalse(any("请确认成交状态" in t for t in self._texts()))
phase = handle_air_group(
self._msg(sender="air1", text=f"{wo}取消舱位", chat="wr_air_1", mid="l5"),