fix(CORE-001D3A): accept decimal boundary inputs

This commit is contained in:
Bu5hm4nn
2026-03-26 13:19:18 +01:00
parent bb557009c7
commit 753e9d3146
6 changed files with 105 additions and 69 deletions

View File

@@ -4,8 +4,8 @@ from dataclasses import dataclass
from decimal import Decimal
from typing import Protocol
from app.domain.units import decimal_from_float
from app.models.portfolio import PortfolioConfig
from app.services.boundary_values import boundary_decimal
class _SaveStatusConfig(Protocol):
@@ -27,38 +27,16 @@ class SaveStatusSnapshot:
margin_call_price: Decimal
def _decimal_from_boundary_value(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, int):
parsed = float(value)
elif isinstance(value, float):
parsed = value
elif isinstance(value, str):
stripped = value.strip()
if not stripped:
raise ValueError(f"{field_name} must be present")
try:
parsed = float(stripped)
except ValueError as exc:
raise ValueError(f"{field_name} must be numeric, got {value!r}") from exc
else:
raise TypeError(f"{field_name} must be numeric, got {type(value)!r}")
return decimal_from_float(float(parsed))
def _normalize_save_status_snapshot(config: PortfolioConfig | _SaveStatusConfig) -> SaveStatusSnapshot:
margin_call_price = config.margin_call_price
resolved_margin_call_price = margin_call_price() if callable(margin_call_price) else margin_call_price
return SaveStatusSnapshot(
entry_basis_mode=config.entry_basis_mode,
gold_value=_decimal_from_boundary_value(config.gold_value, field_name="config.gold_value"),
entry_price=_decimal_from_boundary_value(config.entry_price, field_name="config.entry_price"),
gold_ounces=_decimal_from_boundary_value(config.gold_ounces, field_name="config.gold_ounces"),
current_ltv=_decimal_from_boundary_value(config.current_ltv, field_name="config.current_ltv"),
margin_call_price=_decimal_from_boundary_value(
gold_value=boundary_decimal(config.gold_value, field_name="config.gold_value"),
entry_price=boundary_decimal(config.entry_price, field_name="config.entry_price"),
gold_ounces=boundary_decimal(config.gold_ounces, field_name="config.gold_ounces"),
current_ltv=boundary_decimal(config.current_ltv, field_name="config.current_ltv"),
margin_call_price=boundary_decimal(
resolved_margin_call_price,
field_name="config.margin_call_price",
),