角色业务范围收紧工单与模板;报价日期不当费用;未选舱不迁已报价;另开一票可清违禁 hold

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-10-15 21:00:01 +08:00
co-authored by Cursor
parent a0c705683f
commit 277cdc1c28
39 changed files with 2083 additions and 217 deletions
@@ -51,6 +51,16 @@ class AirAddedServicesTests(unittest.TestCase):
self.assertEqual(comma, ["托盘", "前置仓", "带电"])
spoken = harvest_added_services("这票 must go,要dg和tc")
self.assertEqual(spoken, ["MUST GO", "DG", "TC"])
# 服务名后的 +数量要跟进同一项,不能只剩 TC、托盘。
self.assertEqual(
harvest_added_services("查一下香港到吉隆坡书籍TC +1.5、托盘 +1的报价"),
["TC+1.5", "托盘+1"],
)
self.assertEqual(
harvest_added_services("增值服务:TC+1.5、托盘 +1"),
["TC+1.5", "托盘+1"],
)
def test_longest_match_and_negation(self) -> None:
self.assertEqual(harvest_added_services("要卡转低消"), ["卡转低消"])
@@ -369,11 +369,41 @@ class LandGroupCollabTests(unittest.TestCase):
self.assertTrue(rows)
self.assertEqual(str(rows[0].get("name") or ""), "陆运费")
self.assertEqual(str(land.get("total") or ""), "1")
self.assertEqual(str(land.get("currency") or ""), "CNY")
sea = extract_product_quote("价格为1RMB/KG", business_line="SEA")
self.assertEqual(str((sea.get("fee_rows") or [{}])[0].get("name") or ""), "海运费")
air = extract_product_quote("价格为1RMB/KG", business_line="AIR")
self.assertEqual(str((air.get("fee_rows") or [{}])[0].get("name") or ""), "空运费")
def test_land_rmb_overrides_tms_hkd_baseline(self) -> None:
"""WO040:TMS 已是 HKD 时,产品写「价格为1RMB/KG」必须落 CNY,禁止 hint 盖成 HKD。"""
from agent.llm.extract_text import extract_product_quote
from agent.policy.sea_group_ops import _quote_currency_hint, merge_quote_fees
tms = {
"currency": "HKD",
"cost": "HKD 1000",
"total": "1000",
"source": "TMS",
"fee_lines": [
{"name": "运输费", "amount": "1000", "currency": "HKD"},
],
}
self.assertEqual(_quote_currency_hint(tms), "HKD")
quote = extract_product_quote(
"价格为1RMB/KG",
business_line="LAND",
baseline_currency=_quote_currency_hint(tms),
)
self.assertEqual(str(quote.get("currency") or ""), "CNY")
self.assertEqual(str((quote.get("fee_rows") or [{}])[0].get("currency") or ""), "CNY")
merged = merge_quote_fees(tms, quote)
self.assertEqual(str(merged.get("currency") or ""), "CNY")
self.assertEqual(
str((merged.get("fee_rows") or [{}])[-1].get("currency") or ""),
"CNY",
)
def test_land_adjust_without_currency_inherits_tms_hkd(self) -> None:
"""WO202610090107:TMS 港币,产品只写「运输费调整为1100」时继承 HKD,禁止默认 USD。"""
from agent.llm.extract_text import extract_product_quote
@@ -68,6 +68,19 @@ class JudgeTests(unittest.TestCase):
self.assertEqual(hold3, "")
self.assertEqual(edits.get("品名"), "服装")
def test_fresh_inquiry_clears_hold_without_cargo_rename(self) -> None:
"""问过炸弹被拦后,再查吉隆坡费用应放行;不能继续套旧 hold。"""
hold = "查一下广西到胡志明炸弹的费用"
facts = {"品名": "炸弹", "起运港": "广西"}
blocked, new_hold, _edits = judge(
text="查一下目的地吉隆坡的费用",
facts=facts,
hold=hold,
)
self.assertFalse(blocked)
self.assertEqual(new_hold, "")
self.assertFalse(contains_blocked(str(facts.get("品名") or "")))
def test_rename_sentence_that_still_says_the_word_stays_blocked(self) -> None:
blocked, hold, _edits = judge(text="不是炸弹,品名服装", facts={"品名": "服装"}, hold="")
self.assertTrue(blocked)