PayrollManagementSystem/backend/tests/unit/test_tplus_guidance_resolution.py

104 lines
3.4 KiB
Python
Raw Normal View History

"""指导成本解析只认已登记事实:多条候选不猜、单位与封存状态必须显式匹配。"""
from decimal import Decimal
import pytest
from app.core.exceptions import BadRequestError
from app.services.tplus.guidance import check_unit_guidance_conflicts, resolve_guidance
class Fact:
"""最小事实替身:resolve_guidance 只读取 kind 与 data_json。"""
def __init__(self, data_json):
self.kind = "GUIDANCE"
self.data_json = data_json
def facts_of(*rows):
"""按 (kind, fact_key) 组装成 latest_guidance_facts 的返回结构。"""
return {("GUIDANCE", str(index)): Fact(row) for index, row in enumerate(rows)}
def final_row(**overrides):
row = {
"product_id": 9,
"month": "2026-03",
"basis": "UNIT",
"unit": "根",
"is_finalized": True,
}
row.update(overrides)
return row
def test_没有匹配事实时返回缺失():
state, guidance = resolve_guidance(facts_of(), 9, "line-1", "2026-03", "根")
assert state == "MISSING"
assert guidance is None
def test_多条候选时不选择其中一条():
rows = facts_of(final_row(), final_row(shipment_line_id="line-1"))
state, guidance = resolve_guidance(rows, 9, "line-1", "2026-03", "根")
assert state == "AMBIGUOUS"
assert guidance is None
def test_唯一候选且单位一致时返回已封存事实():
row = final_row()
state, guidance = resolve_guidance(facts_of(row), 9, "line-1", "2026-03", "根")
assert state == "FINALIZED"
assert guidance is row
def test_单位不一致时不采用该事实():
state, guidance = resolve_guidance(facts_of(final_row(unit="吨")), 9, "line-1", "2026-03", "根")
assert state == "UNIT_MISMATCH"
assert guidance is None
def test_未封存事实不能作为指导价依据():
state, guidance = resolve_guidance(facts_of(final_row(is_finalized=False)), 9, "line-1", "2026-03", "根")
assert state == "UNFINALIZED"
assert guidance is None
def test_按明细行登记的指导价只对该行生效():
rows = facts_of(final_row(basis="LINE", shipment_line_id="line-1"))
assert resolve_guidance(rows, 9, "line-1", "2026-03", "根")[0] == "FINALIZED"
assert resolve_guidance(rows, 9, "line-2", "2026-03", "根")[0] == "MISSING"
def test_同一产品同月已有事实时拒绝重复登记():
with pytest.raises(BadRequestError, match="重叠"):
check_unit_guidance_conflicts(facts_of(final_row()), 9, "2026-03", "根", "10", [])
def test_历史封存明细的成本或单位不一致时拒绝():
with pytest.raises(BadRequestError, match="不一致"):
check_unit_guidance_conflicts(
facts_of(), 9, "2026-03", "根", "10",
[{"unit_cost": "11", "unit": "根"}],
)
with pytest.raises(BadRequestError, match="不一致"):
check_unit_guidance_conflicts(
facts_of(), 9, "2026-03", "根", "10",
[{"unit_cost": "10", "unit": "吨"}],
)
def test_事实为空且历史一致时放行():
check_unit_guidance_conflicts(
facts_of(), 9, "2026-03", "根", Decimal("10"),
[{"unit_cost": "10", "unit": "根"}, {"unit_cost": "10.00", "unit": "根"}],
)
def test_金额非法时拒绝():
for bad in ("abc", "-1", "nan"):
with pytest.raises(BadRequestError, match="不一致"):
check_unit_guidance_conflicts(facts_of(), 9, "2026-03", "根", bad, [])