销售侧汇总统一叫费用合计,并认准空运费的金额。
企微跳转改为账号密码登录,报价卡上的费用按原金额改回;航线按单价数量金额报价时不再记成海运费。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -15,6 +15,8 @@ if ROOT not in sys.path:
|
||||
|
||||
from agent.policy import inquiry_copy as copy
|
||||
from agent.schema.quote_adjust import (
|
||||
AdjustExtract,
|
||||
AdjustItem,
|
||||
apply_adjust,
|
||||
effective_quote,
|
||||
extract_adjust,
|
||||
@@ -164,6 +166,85 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
self.assertFalse(got.ok)
|
||||
self.assertEqual(got.code, "none_matched")
|
||||
|
||||
def test_sea_subtotal_and_bucket_lines(self) -> None:
|
||||
src = {
|
||||
"currency": "CNY",
|
||||
"total": "2000",
|
||||
"fee_lines": [
|
||||
{"name": "操作费", "amount": "1000", "currency": "CNY"},
|
||||
{"name": "箱单费", "amount": "200", "currency": "CNY"},
|
||||
],
|
||||
"polCostItems": [
|
||||
{"name": "操作费", "amount": "1000", "currency": "CNY"},
|
||||
{"name": "箱单费", "amount": "200", "currency": "CNY"},
|
||||
],
|
||||
"fee_total_polCostItems": "1200",
|
||||
}
|
||||
ext = AdjustExtract(
|
||||
is_adjust=True,
|
||||
items=[
|
||||
AdjustItem("操作费", "percent", "up", 10),
|
||||
AdjustItem("箱单费", "percent", "up", 5),
|
||||
AdjustItem("始发港费用小计", "percent", "up", 12),
|
||||
],
|
||||
)
|
||||
got = apply_adjust(src, ext, business_line="SEA")
|
||||
self.assertTrue(got.ok)
|
||||
self.assertEqual(got.unmatched, [])
|
||||
names = {row["name"]: row["amount"] for row in got.quote["polCostItems"]}
|
||||
self.assertEqual(names["操作费"], "1100.00")
|
||||
self.assertEqual(names["箱单费"], "210.00")
|
||||
self.assertEqual(got.quote["fee_total_polCostItems"], "1344.00")
|
||||
|
||||
def test_same_fee_name_keeps_its_own_amount(self) -> None:
|
||||
src = {
|
||||
"currency": "USD",
|
||||
"total": "500",
|
||||
"fee_lines": [
|
||||
{"name": "文件费", "amount": "450", "currency": "USD"},
|
||||
{"name": "文件费", "amount": "50", "currency": "USD"},
|
||||
],
|
||||
"polCostItems": [
|
||||
{"name": "文件费", "amount": "450", "currency": "USD"},
|
||||
{"name": "文件费", "amount": "50", "currency": "USD"},
|
||||
],
|
||||
}
|
||||
ext = AdjustExtract(is_adjust=True, items=[AdjustItem("文件费", "percent", "up", 10)])
|
||||
got = apply_adjust(src, ext, business_line="SEA")
|
||||
self.assertTrue(got.ok)
|
||||
amounts = [row["amount"] for row in got.quote["polCostItems"]]
|
||||
self.assertEqual(amounts, ["495.00", "55.00"])
|
||||
|
||||
def test_land_same_fee_name_each_leg_and_total(self) -> None:
|
||||
src = {
|
||||
"business_line": "LAND",
|
||||
"currency": "CNY",
|
||||
"total": "10000",
|
||||
"fee_lines": [
|
||||
{"name": "运输费", "amount": "7000", "currency": "CNY"},
|
||||
{"name": "运输费", "amount": "3000", "currency": "CNY"},
|
||||
],
|
||||
"landSegments": [
|
||||
{"origin": "上海", "destination": "谅山", "costPrice": "7000", "segmentSequence": 1, "routeLegSequence": 1},
|
||||
{"origin": "谅山", "destination": "河内", "costPrice": "3000", "segmentSequence": 1, "routeLegSequence": 2},
|
||||
],
|
||||
}
|
||||
ext = AdjustExtract(
|
||||
is_adjust=True,
|
||||
items=[
|
||||
AdjustItem("运输费", "percent", "up", 10),
|
||||
AdjustItem("总成本价", "percent", "up", 10),
|
||||
],
|
||||
)
|
||||
got = apply_adjust(src, ext, business_line="LAND")
|
||||
self.assertTrue(got.ok)
|
||||
self.assertEqual(got.unmatched, [])
|
||||
amounts = sorted(row["amount"] for row in got.quote["fee_lines"])
|
||||
self.assertEqual(amounts, ["3300.00", "7700.00"])
|
||||
costs = [leg["costPrice"] for leg in got.quote["landSegments"]]
|
||||
self.assertEqual(costs, ["7700.00", "3300.00"])
|
||||
self.assertEqual(got.quote["total"], "11000.00")
|
||||
|
||||
def test_overlay_manual_wins(self) -> None:
|
||||
tms = _quote(("运输费", "1000", "CNY"), ("卸货费", "200", "CNY"), total="1200")
|
||||
manual = _quote(("卸货费", "300", "CNY"), ("配送费", "20", "CNY"), total="320")
|
||||
@@ -219,17 +300,18 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
)
|
||||
self.assertAlmostEqual(second.profit_point or 0, 30.0)
|
||||
|
||||
def test_total_label_cost_until_sales_adjust(self) -> None:
|
||||
self.assertEqual(total_price_label("AIR"), "总销售价")
|
||||
self.assertEqual(total_price_label("SEA"), "总成本价")
|
||||
self.assertEqual(total_price_label("LAND"), "总成本价")
|
||||
self.assertEqual(total_price_label("", transport_mode="空运"), "总销售价")
|
||||
self.assertEqual(total_price_label("", transport_mode="陆运"), "总成本价")
|
||||
def test_total_label_is_fee_total_for_every_line(self) -> None:
|
||||
"""销售侧汇总一律叫费用合计,空运/海运/陆运、TMS/调价都一样。"""
|
||||
self.assertEqual(total_price_label("AIR"), "费用合计")
|
||||
self.assertEqual(total_price_label("SEA"), "费用合计")
|
||||
self.assertEqual(total_price_label("LAND"), "费用合计")
|
||||
self.assertEqual(total_price_label("", transport_mode="空运"), "费用合计")
|
||||
self.assertEqual(total_price_label("", transport_mode="陆运"), "费用合计")
|
||||
tms = {"source": "TMS", "source_label": "TMS标准报价"}
|
||||
self.assertEqual(total_price_label("LAND", quote=tms), "总成本价")
|
||||
self.assertEqual(total_price_label("SEA", quote={"source": "PRODUCT"}), "总成本价")
|
||||
self.assertEqual(total_price_label("LAND", quote={"source": "SALES_ADJUST"}), "总销售价")
|
||||
self.assertEqual(total_price_label("AIR", quote=tms), "总销售价")
|
||||
self.assertEqual(total_price_label("LAND", quote=tms), "费用合计")
|
||||
self.assertEqual(total_price_label("SEA", quote={"source": "PRODUCT"}), "费用合计")
|
||||
self.assertEqual(total_price_label("LAND", quote={"source": "SALES_ADJUST"}), "费用合计")
|
||||
self.assertEqual(total_price_label("AIR", quote=tms), "费用合计")
|
||||
|
||||
def test_tms_land_card_uses_cost_not_sale(self) -> None:
|
||||
q = _quote(("运输费", "121.00", "CNY"), total="121.00")
|
||||
@@ -239,7 +321,7 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
work_order_no="WO202609200005", quote=q, business_line="LAND"
|
||||
)
|
||||
self.assertEqual(detail["template_card"]["source"]["desc"], "TMS标准报价")
|
||||
self.assertIn("总成本价:CNY 121.00", detail["template_card"]["quote_area"]["quote_text"])
|
||||
self.assertIn("费用合计:CNY 121.00", detail["template_card"]["quote_area"]["quote_text"])
|
||||
self.assertNotIn("总销售价", detail["template_card"]["quote_area"]["quote_text"])
|
||||
scheme = copy.scheme_wecom_payload(
|
||||
work_order_no="WO202609200005",
|
||||
@@ -248,9 +330,9 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
transport_mode="陆运",
|
||||
)
|
||||
self.assertEqual(scheme["template_card"]["source"]["desc"], "TMS标准报价")
|
||||
self.assertIn("总成本价:CNY 121.00", scheme["template_card"]["quote_area"]["quote_text"])
|
||||
self.assertIn("费用合计:CNY 121.00", scheme["template_card"]["quote_area"]["quote_text"])
|
||||
deal = copy.deal_horizontal_rows(quote=q, business_line="LAND")
|
||||
self.assertEqual(deal[0]["keyname"], "总成本价")
|
||||
self.assertEqual(deal[0]["keyname"], "费用合计")
|
||||
|
||||
def test_adjust_confirm_uses_sale_total_name(self) -> None:
|
||||
src = _quote(("运输费", "110", "CNY"), total="110")
|
||||
@@ -261,24 +343,22 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
)
|
||||
self.assertTrue(land.ok)
|
||||
names = [x.get("name") for x in land.applied]
|
||||
self.assertIn("总销售价", names)
|
||||
self.assertNotIn("合计", names)
|
||||
self.assertIn("费用合计", names)
|
||||
self.assertNotIn("总销售价", names)
|
||||
self.assertNotIn("总成本价", names)
|
||||
text = copy.adjust_confirm(land.applied)
|
||||
self.assertIn("总销售价在当前报价基础上", text)
|
||||
self.assertNotIn("合计在当前报价基础上", text)
|
||||
self.assertIn("费用合计在当前报价基础上", text)
|
||||
body = copy.adjust_group_body(land.quote, business_line="LAND")
|
||||
self.assertIn("总销售价:", body)
|
||||
self.assertNotIn("合计:", body)
|
||||
self.assertIn("费用合计:", body)
|
||||
air = apply_adjust(
|
||||
src,
|
||||
extract_adjust("总销售价改为100CNY", fee_names=["运输费"], allow_model=False),
|
||||
business_line="AIR",
|
||||
)
|
||||
self.assertIn("总销售价", [x.get("name") for x in air.applied])
|
||||
self.assertNotIn("合计", [x.get("name") for x in air.applied])
|
||||
self.assertIn("费用合计", [x.get("name") for x in air.applied])
|
||||
note = copy.adjust_ledger_remark(land.applied)
|
||||
self.assertTrue(note.startswith("销售调价:"))
|
||||
self.assertIn("总销售价", note)
|
||||
self.assertIn("费用合计", note)
|
||||
|
||||
def test_quote_copy_uses_line_and_source_total_name(self) -> None:
|
||||
sea = {
|
||||
@@ -293,16 +373,17 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
"source": "TMS",
|
||||
"fee_rows": [{"name": "空运费", "amount": "700", "currency": "CNY"}],
|
||||
}
|
||||
self.assertIn("总成本价:CNY 2287.65", copy.quote_area_fee_text(sea, business_line="SEA"))
|
||||
self.assertIn("总销售价:CNY 722.5", copy.quote_area_fee_text(air, business_line="AIR"))
|
||||
self.assertIn("费用合计:CNY 2287.65", copy.quote_area_fee_text(sea, business_line="SEA"))
|
||||
self.assertIn("费用合计:CNY 722.5", copy.quote_area_fee_text(air, business_line="AIR"))
|
||||
self.assertNotIn("总销售价合计", copy.quote_area_fee_text(air, business_line="AIR"))
|
||||
self.assertNotIn("总销售价:CNY 2287.65", copy.quote_area_fee_text(sea, business_line="SEA"))
|
||||
self.assertIn("总成本价:CNY 2287.65", "\n".join(copy.quote_detail_lines(sea, business_line="SEA")))
|
||||
self.assertNotIn("总销售价", copy.quote_area_fee_text(sea, business_line="SEA"))
|
||||
self.assertNotIn("总成本价", copy.quote_area_fee_text(sea, business_line="SEA"))
|
||||
self.assertIn("费用合计:CNY 2287.65", "\n".join(copy.quote_detail_lines(sea, business_line="SEA")))
|
||||
rows = copy.deal_horizontal_rows(quote=air, business_line="AIR")
|
||||
self.assertEqual(rows[0]["keyname"], "总销售价")
|
||||
self.assertEqual(rows[0]["keyname"], "费用合计")
|
||||
self.assertNotIn("时效", [x["keyname"] for x in rows])
|
||||
land_rows = copy.deal_horizontal_rows(quote=sea, business_line="LAND")
|
||||
self.assertEqual(land_rows[0]["keyname"], "总成本价")
|
||||
self.assertEqual(land_rows[0]["keyname"], "费用合计")
|
||||
self.assertIn("时效", [x["keyname"] for x in land_rows])
|
||||
|
||||
def test_adjust_cards_use_sales_adjust_not_tms(self) -> None:
|
||||
@@ -314,7 +395,7 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
work_order_no="WO202609200004", quote=q, business_line="LAND"
|
||||
)
|
||||
self.assertEqual(detail["template_card"]["source"]["desc"], "销售调价")
|
||||
self.assertIn("总销售价:CNY 121.00", detail["template_card"]["quote_area"]["quote_text"])
|
||||
self.assertIn("费用合计:CNY 121.00", detail["template_card"]["quote_area"]["quote_text"])
|
||||
self.assertNotIn("总成本价", detail["template_card"]["quote_area"]["quote_text"])
|
||||
scheme = copy.scheme_wecom_payload(
|
||||
work_order_no="WO202609200004",
|
||||
@@ -323,7 +404,7 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
transport_mode="陆运",
|
||||
)
|
||||
self.assertEqual(scheme["template_card"]["source"]["desc"], "销售调价")
|
||||
self.assertIn("总销售价:CNY 121.00", scheme["template_card"]["quote_area"]["quote_text"])
|
||||
self.assertIn("费用合计:CNY 121.00", scheme["template_card"]["quote_area"]["quote_text"])
|
||||
|
||||
def test_private_eligibility(self) -> None:
|
||||
self.assertEqual(private_session_can_adjust("已报价", True, ""), "")
|
||||
@@ -469,10 +550,10 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
transport_mode="陆运",
|
||||
)
|
||||
tms_block = text.split("TMS报价:", 1)[1]
|
||||
self.assertIn("总成本价:CNY 110.00", tms_block.split("销售调价:", 1)[0])
|
||||
self.assertIn("费用合计:CNY 110.00", tms_block.split("销售调价:", 1)[0])
|
||||
self.assertIn("销售调价:", text)
|
||||
self.assertIn("总销售价:CNY 100.00", text.split("销售调价:", 1)[1])
|
||||
self.assertNotIn("总销售价:CNY 100.00", tms_block.split("销售调价:", 1)[0])
|
||||
self.assertIn("费用合计:CNY 100.00", text.split("销售调价:", 1)[1])
|
||||
self.assertNotIn("费用合计:CNY 100.00", tms_block.split("销售调价:", 1)[0])
|
||||
|
||||
def test_group_brief_adjust_alone_does_not_become_tms(self) -> None:
|
||||
"""没单独传入 TMS 时,调后价也不能写进 TMS 段。"""
|
||||
@@ -492,7 +573,7 @@ class QuoteAdjustTests(unittest.TestCase):
|
||||
self.assertIn("TMS报价:\nTMS 暂无匹配报价", text)
|
||||
self.assertIn("产品人员可通过“纯文字”告知新报价,或直接将新报价excel表发给智能体。", text)
|
||||
self.assertIn("销售调价:", text)
|
||||
self.assertIn("总销售价:CNY 100.00", text.split("销售调价:", 1)[1])
|
||||
self.assertIn("费用合计:CNY 100.00", text.split("销售调价:", 1)[1])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user