PayrollManagementSystem/backend/tests/unit/test_tplus_guidance_resolution.py
liuwenxin 1e53792ad6 feat(T+): 完成数据贯通与自动接入闭环
打通 T+ 快照、业务、发货、回款和核算准备链路,保留来源差异并提供待补状态。
新增业务自动接入任务、跨平台读取服务托管、权限复核、来源关联和前端核对页面。
补充迁移、隔离集成测试、浏览器模拟验收及角色授权边界修复。
2026-11-05 18:47:13 +08:00

104 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""指导成本解析只认已登记事实:多条候选不猜、单位与封存状态必须显式匹配。"""
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, [])