"""产品 schema 的金额口径单测(秒级,无外部依赖)。 守:产品 sale_price/stock_quantity 若私写校验不查小数位与容量,5 位小数 会被 Numeric 列静默截断(舍入即算错钱)、超容量会以 500 暴露 —— 校验 口径必须与 schemas/business._check_amount 一致(shipment/receipt 同源)。 """ import pytest from pydantic import ValidationError from app.schemas.product import ProductCreateIn class TestSalePrice: """单价校验:scale=4 对齐 Numeric(14,4) 列。""" def test_四位小数通过_回显原样提交(self) -> None: """带精度的历史单价必须能原样提交(fba8cfc 教训:编辑被永远拒收)。""" body = ProductCreateIn( product_name="t_产品", product_category="municipal_water", sale_price="5000.1234", ) assert body.sale_price == "5000.1234" def test_五位小数拒绝而非静默截断(self) -> None: with pytest.raises(ValidationError) as exc: ProductCreateIn( product_name="t_产品", product_category="municipal_water", sale_price="1.23456", ) assert "最多四位小数" in str(exc.value) def test_超容量拒绝(self) -> None: """DECIMAL(14,4) 整数部分 10 位:超出即拒绝而非溢出 500。""" with pytest.raises(ValidationError): ProductCreateIn( product_name="t_产品", product_category="municipal_water", sale_price="99999999999.0000", ) def test_空串归一None_负数拒绝(self) -> None: empty = ProductCreateIn( product_name="t_产品", product_category="municipal_water", sale_price="" ) assert empty.sale_price is None with pytest.raises(ValidationError): ProductCreateIn( product_name="t_产品", product_category="municipal_water", sale_price="-1" ) class TestStockQuantity: """数量校验:默认 scale=2 对齐 Numeric(14,2) 列。""" def test_三位小数拒绝(self) -> None: with pytest.raises(ValidationError): ProductCreateIn( product_name="t_产品", product_category="municipal_water", stock_quantity="1.001", ) def test_两位小数通过(self) -> None: body = ProductCreateIn( product_name="t_产品", product_category="municipal_water", stock_quantity="1.55", ) assert body.stock_quantity == "1.55"