员工岗位可重新启用;调价认空运航线;会话存档跳号补拉;陆运报价按车型列回填
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user