员工岗位可重新启用;调价认空运航线;会话存档跳号补拉;陆运报价按车型列回填

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-10-28 19:48:47 +08:00
co-authored by Cursor
parent 2b528758b4
commit 56ba8e93b5
62 changed files with 2960 additions and 793 deletions
+227
View File
@@ -22,6 +22,7 @@ from agent.schema.quote_adjust import (
apply_adjust,
effective_quote,
extract_adjust,
parse_money,
private_session_can_adjust,
total_price_label,
)
@@ -48,6 +49,151 @@ class QuoteAdjustTests(unittest.TestCase):
self.assertEqual(str(got.quote["total"]), "1300.00")
self.assertFalse(got.currency_hint)
def test_increase_to_percent_is_set_not_up(self) -> None:
"""「运输费用增加到110%」= 原价×1.1,不是上调 110%(×2.1)。"""
src = _quote(("运输费", "CNY 7500.00", "CNY"), total="CNY 7500.00")
ext = extract_adjust(
"运输费用增加到110%",
fee_names=["运输费"],
allow_model=False,
)
self.assertTrue(ext.is_adjust)
self.assertEqual(len(ext.items), 1)
self.assertEqual(ext.items[0].kind, "percent")
self.assertEqual(ext.items[0].direction, "set")
self.assertEqual(ext.items[0].value, 110.0)
got = apply_adjust(src, ext, business_line="LAND", tms_cost="7500")
self.assertTrue(got.ok)
self.assertEqual(got.quote["fee_rows"][0]["amount"], "CNY 8250.00")
self.assertEqual(str(got.quote["total"]), "CNY 8250.00")
self.assertIn("调到 110%", got.applied[0]["how"])
def test_air_unit_price_percent_keeps_per_kg_not_line_total(self) -> None:
"""空运「单价增加到110%」:单价 19→20.9,行金额=20.9×162;禁止把合计写进单价。"""
src = {
"currency": "CNY",
"total": "3438",
"fee_rows": [
{
"name": "空运费",
"amount": "3078",
"currency": "CNY",
"unit": "KG",
"unit_price": "19",
"quantity": "162",
},
{
"name": "人工费",
"amount": "200",
"currency": "CNY",
"unit": "人",
"unit_price": "200",
"quantity": "1",
},
{
"name": "打板费",
"amount": "160",
"currency": "CNY",
"unit": "个",
"unit_price": "160",
"quantity": "1",
},
],
}
ext = extract_adjust(
"空运费单价增加到110%/KG",
fee_names=["空运费", "人工费", "打板费"],
allow_model=False,
)
got = apply_adjust(src, ext, business_line="AIR")
self.assertTrue(got.ok)
air = next(r for r in got.quote["fee_rows"] if r["name"] == "空运费")
self.assertEqual(air["amount"], "3385.80")
self.assertEqual(str(air.get("unit_price") or ""), "20.90")
self.assertNotEqual(str(air.get("unit_price") or ""), "3385.80")
def test_air_unit_percent_uses_chargeable_weight_when_qty_missing(self) -> None:
"""费用行无 quantity 时,用工单计费重:单价15→16.5,禁止把行合计写进单价。"""
src = {
"currency": "CNY",
"total": "38757.75",
"chargeableWeightKg": "2583.85",
"fee_rows": [
{
"name": "空运费",
"amount": "38757.75",
"currency": "CNY",
"unit": "KG",
"unit_price": "15",
"unitPrice": "15",
}
],
"selected_air_option": {
"chargeableWeightKg": 2583.85,
"airlineCode": "TH",
"feeItems": [
{
"chargeName": "空运费",
"unitPrice": 15,
"amount": 38757.75,
"unit": "KG",
"currency": "CNY",
}
],
},
}
ext = extract_adjust(
"空运费单价增加到110%/KG",
fee_names=["空运费"],
allow_model=False,
)
got = apply_adjust(src, ext, business_line="AIR")
self.assertTrue(got.ok)
air = next(r for r in got.quote["fee_rows"] if r["name"] == "空运费")
self.assertEqual(str(air.get("unit_price") or ""), "16.50")
self.assertNotEqual(str(air.get("unit_price") or ""), "42633.53")
amt, _ = parse_money(air.get("amount"))
self.assertAlmostEqual(float(amt or 0), 42633.525, places=2)
def test_model_up_coerced_when_text_says_to_percent(self) -> None:
"""模型误抽成 up 时,按原话「增加到X%」纠正为 set。"""
src = _quote(("运输费", "7500", "CNY"), total="7500")
injected = {
"is_adjust": True,
"wants_total": False,
"items": [{"fee_name": "运输费", "kind": "percent", "direction": "up", "value": 110}],
}
ext = extract_adjust(
"运输费用增加到110%",
fee_names=["运输费"],
injected=injected,
allow_model=False,
)
self.assertEqual(ext.items[0].direction, "set")
got = apply_adjust(src, ext, business_line="LAND")
self.assertEqual(got.quote["fee_rows"][0]["amount"], "8250.00")
def test_to_percent_phrase_variants(self) -> None:
"""调整到/涨到/升到/增至/变为/上浮到 X% 一律按改到原价比例。"""
src = _quote(("运输费", "CNY 7500.00", "CNY"), total="CNY 7500.00")
phrases = (
"运输费调整到110%",
"运输费涨到110%",
"运输费升到110%",
"运输费增至110%",
"运输费变为110%",
"运输费上浮到110%",
)
for text in phrases:
with self.subTest(text=text):
ext = extract_adjust(text, fee_names=["运输费"], allow_model=False)
self.assertTrue(ext.is_adjust, text)
self.assertEqual(ext.items[0].kind, "percent", text)
self.assertEqual(ext.items[0].direction, "set", text)
got = apply_adjust(src, ext, business_line="LAND")
self.assertTrue(got.ok, text)
self.assertEqual(got.quote["fee_rows"][0]["amount"], "CNY 8250.00", text)
def test_percent_down_and_target_in_one_sentence(self) -> None:
src = _quote(("提货费", "1000", "CNY"), ("送货费", "200", "CNY"), total="1200")
ext = extract_adjust("提货费减 5%,送货费提升到 180 元", fee_names=["提货费", "送货费"])
@@ -573,6 +719,87 @@ class QuoteAdjustTests(unittest.TestCase):
self.assertTrue(copy.quote_is_tms(sess.tms_quote))
self.assertFalse(copy.quote_is_tms(sess.quote))
def test_private_air_adjust_emits_facts_so_cargo_not_blank(self) -> None:
"""空运私聊调价出卡必须带 sess.facts,否则起运地/品名会整段变「-」。"""
from agent.policy.quote_adjust_ops import try_private_adjust
class _Sess:
status = "已报价"
phase = "wait_collab"
work_order_no = "WO202610280072"
business_line = "AIR"
collab_chat_id = ""
wait_version = 1
first_or_same = "first"
history_work_order_no = ""
facts = {
"起运地": "南京",
"目的地": "吉隆坡",
"品名": "普货",
"件数": "15",
"毛重": "2403",
"体积": "15.5",
"包装类型": "托盘",
}
quote = {
"currency": "CNY",
"total": "38757.75",
"chargeableWeightKg": "2583.85",
"fee_rows": [
{
"name": "空运费",
"amount": "38757.75",
"currency": "CNY",
"unit": "KG",
"unit_price": "15",
}
],
}
tms_quote = {}
class _Flow:
def __init__(self) -> None:
self.emitted = None
class _Ledger:
def upsert_product_quote(self, **kwargs):
return {"ok": True}
self.ledger = _Ledger()
def _save(self, sess) -> None:
return None
def _emit_air_hit(self, reply, **kwargs) -> None:
self.emitted = kwargs
sess = _Sess()
flow = _Flow()
out = try_private_adjust(
flow,
sess,
"空运费单价增加到110%/KG",
lambda *_a, **_k: None,
injected_adjust={
"is_adjust": True,
"items": [
{
"fee_name": "空运费",
"kind": "percent",
"direction": "set",
"value": 110,
}
],
},
)
self.assertEqual(out, "wait_collab")
self.assertIsNotNone(flow.emitted)
facts = dict(flow.emitted.get("facts") or {})
self.assertEqual(facts.get("起运地"), "南京")
self.assertEqual(facts.get("品名"), "普货")
air = next(r for r in sess.quote["fee_rows"] if r["name"] == "空运费")
self.assertEqual(str(air.get("unit_price") or ""), "16.50")
def test_group_brief_keeps_tms_when_current_is_adjust(self) -> None:
"""拉群摘要:TMS 段必须是原价,调后价另写销售调价,禁止替换。"""
tms = _quote(("运输费", "110.00", "CNY"), total="110.00")