112 lines
3.7 KiB
Python
112 lines
3.7 KiB
Python
|
|
"""二次分配方案入参校验(schema 层,秒级)。
|
|||
|
|
|
|||
|
|
守的是:比例红线(字符串入参、两位小数、超限拒绝不静默舍入)与
|
|||
|
|
参与人去重——uk(business_id, personnel_id) 的友好前置校验。
|
|||
|
|
明细行同批创建的正常路径由集成测试覆盖,这里集中打边界。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import pytest
|
|||
|
|
from pydantic import ValidationError
|
|||
|
|
|
|||
|
|
from app.schemas.business import SecondaryAllocationIn
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _make(personnel_id: int = 1, ratio: str = "50.00") -> dict:
|
|||
|
|
return {"personnel_id": personnel_id, "ratio": ratio}
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestRatioBoundary:
|
|||
|
|
"""比例边界:0 / 满额 / 超限 / 精度 / 非数字。"""
|
|||
|
|
|
|||
|
|
@pytest.mark.parametrize(
|
|||
|
|
("ratio", "ok"),
|
|||
|
|
[
|
|||
|
|
("0", False), # 必须大于 0
|
|||
|
|
("0.01", True),
|
|||
|
|
("33.33", True),
|
|||
|
|
("100", True),
|
|||
|
|
("100.00", True),
|
|||
|
|
("100.01", False), # 超上限
|
|||
|
|
("-5", False), # 负数
|
|||
|
|
("33.333", False), # 三位小数:拒绝不静默舍入
|
|||
|
|
("abc", False), # 非数字
|
|||
|
|
("", False), # 空串
|
|||
|
|
],
|
|||
|
|
)
|
|||
|
|
def test_比例边界(self, ratio: str, *, ok: bool) -> None:
|
|||
|
|
if ok:
|
|||
|
|
assert SecondaryAllocationIn(**_make(ratio=ratio)).ratio == ratio
|
|||
|
|
else:
|
|||
|
|
with pytest.raises(ValidationError):
|
|||
|
|
SecondaryAllocationIn(**_make(ratio=ratio))
|
|||
|
|
|
|||
|
|
def test_人员id必须为正整数(self) -> None:
|
|||
|
|
with pytest.raises(ValidationError):
|
|||
|
|
SecondaryAllocationIn(**_make(personnel_id=0))
|
|||
|
|
with pytest.raises(ValidationError):
|
|||
|
|
SecondaryAllocationIn(**_make(personnel_id=-1))
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestDuplicate:
|
|||
|
|
"""参与人去重(Create/Update 两个入参模型同款校验)。"""
|
|||
|
|
|
|||
|
|
def test_创建入参_重复参与人被拒(self) -> None:
|
|||
|
|
from app.schemas.business import BusinessCreateIn
|
|||
|
|
|
|||
|
|
payload = {
|
|||
|
|
"customer_id": 1,
|
|||
|
|
"items": [
|
|||
|
|
{
|
|||
|
|
"product_name": "t_产品",
|
|||
|
|
"product_category": "municipal_water",
|
|||
|
|
"quantity": "1.00",
|
|||
|
|
"sale_price": "10.00",
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"secondary_allocations": [
|
|||
|
|
_make(personnel_id=5, ratio="30.00"),
|
|||
|
|
_make(personnel_id=5, ratio="20.00"),
|
|||
|
|
],
|
|||
|
|
}
|
|||
|
|
with pytest.raises(ValidationError, match="重复"):
|
|||
|
|
BusinessCreateIn(**payload)
|
|||
|
|
|
|||
|
|
def test_编辑入参_重复参与人被拒(self) -> None:
|
|||
|
|
from app.schemas.business import BusinessUpdateIn
|
|||
|
|
|
|||
|
|
payload = {
|
|||
|
|
"customer_id": 1,
|
|||
|
|
"items": [
|
|||
|
|
{
|
|||
|
|
"product_name": "t_产品",
|
|||
|
|
"product_category": "municipal_water",
|
|||
|
|
"quantity": "1.00",
|
|||
|
|
"sale_price": "10.00",
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"secondary_allocations": [_make(personnel_id=5), _make(personnel_id=5)],
|
|||
|
|
}
|
|||
|
|
with pytest.raises(ValidationError, match="重复"):
|
|||
|
|
BusinessUpdateIn(**payload)
|
|||
|
|
|
|||
|
|
def test_不同参与人合法(self) -> None:
|
|||
|
|
from app.schemas.business import BusinessCreateIn
|
|||
|
|
|
|||
|
|
payload = {
|
|||
|
|
"customer_id": 1,
|
|||
|
|
"items": [
|
|||
|
|
{
|
|||
|
|
"product_name": "t_产品",
|
|||
|
|
"product_category": "municipal_water",
|
|||
|
|
"quantity": "1.00",
|
|||
|
|
"sale_price": "10.00",
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"secondary_allocations": [
|
|||
|
|
_make(personnel_id=5, ratio="30.00"),
|
|||
|
|
_make(personnel_id=6, ratio="20.00"),
|
|||
|
|
],
|
|||
|
|
}
|
|||
|
|
model = BusinessCreateIn(**payload)
|
|||
|
|
assert len(model.secondary_allocations) == 2
|