26 lines
945 B
Python
26 lines
945 B
Python
from __future__ import annotations
|
|
|
|
from decimal import Decimal, InvalidOperation
|
|
|
|
from app.domain.units import decimal_from_float, to_decimal
|
|
|
|
|
|
def boundary_decimal(value: object, *, field_name: str) -> Decimal:
|
|
if value is None:
|
|
raise ValueError(f"{field_name} must be present")
|
|
if isinstance(value, bool):
|
|
raise TypeError(f"{field_name} must be numeric, got bool")
|
|
if isinstance(value, float):
|
|
return decimal_from_float(value)
|
|
if isinstance(value, (Decimal, int)):
|
|
return to_decimal(value)
|
|
if isinstance(value, str):
|
|
stripped = value.strip()
|
|
if not stripped:
|
|
raise ValueError(f"{field_name} must be present")
|
|
try:
|
|
return to_decimal(stripped)
|
|
except InvalidOperation as exc:
|
|
raise ValueError(f"{field_name} must be numeric, got {value!r}") from exc
|
|
raise TypeError(f"{field_name} must be numeric, got {type(value)!r}")
|