feat(CORE-001D3A): normalize alerts and settings service boundaries

This commit is contained in:
Bu5hm4nn
2026-03-26 13:10:30 +01:00
parent 91f67cd414
commit bb557009c7
7 changed files with 231 additions and 27 deletions

View File

@@ -1,11 +1,12 @@
from __future__ import annotations
from decimal import Decimal
from pathlib import Path
import pytest
from app.models.portfolio import PortfolioConfig
from app.services.alerts import AlertService, build_portfolio_alert_context
from app.services.alerts import AlertService, _normalize_alert_evaluation_input, build_portfolio_alert_context
@pytest.fixture
@@ -13,6 +14,39 @@ def alert_service(tmp_path: Path) -> AlertService:
return AlertService(history_path=tmp_path / "alert_history.json")
def test_normalize_alert_evaluation_input_coerces_numeric_boundary_values() -> None:
config = PortfolioConfig(gold_value=215_000.0, entry_price=215.0, loan_amount=151_000.0)
normalized = _normalize_alert_evaluation_input(
config,
{
"ltv_ratio": "0.7023",
"spot_price": "215.0",
"quote_updated_at": 123,
},
)
assert normalized.ltv_ratio == Decimal("0.7023")
assert normalized.spot_price == Decimal("215.0")
assert normalized.updated_at == "123"
assert normalized.warning_threshold == Decimal("0.7")
assert normalized.critical_threshold == Decimal("0.75")
def test_normalize_alert_evaluation_input_rejects_bool_values() -> None:
config = PortfolioConfig(gold_value=215_000.0, entry_price=215.0, loan_amount=151_000.0)
with pytest.raises(TypeError, match="portfolio.ltv_ratio must be numeric, got bool"):
_normalize_alert_evaluation_input(
config,
{
"ltv_ratio": True,
"spot_price": 215.0,
"quote_updated_at": "2026-03-24T12:00:00Z",
},
)
def test_alert_service_reports_ok_when_ltv_is_below_warning(alert_service: AlertService) -> None:
config = PortfolioConfig(gold_value=215_000.0, entry_price=215.0, loan_amount=120_000.0)
portfolio = build_portfolio_alert_context(

View File

@@ -1,7 +1,11 @@
from __future__ import annotations
from decimal import Decimal
import pytest
from app.models.portfolio import PortfolioConfig
from app.services.settings_status import save_status_text
from app.services.settings_status import _normalize_save_status_snapshot, save_status_text
class CallableMarginCallPriceConfig:
@@ -17,6 +21,34 @@ class CallableMarginCallPriceConfig:
return self._margin_call_price
class StringBoundaryConfig:
entry_basis_mode = "weight"
gold_value = "215000"
entry_price = "215.0"
gold_ounces = "1000"
current_ltv = "0.6744186046511628"
margin_call_price = "193.33333333333334"
def test_normalize_save_status_snapshot_coerces_numeric_boundary_values() -> None:
snapshot = _normalize_save_status_snapshot(StringBoundaryConfig())
assert snapshot.entry_basis_mode == "weight"
assert snapshot.gold_value == Decimal("215000")
assert snapshot.entry_price == Decimal("215.0")
assert snapshot.gold_ounces == Decimal("1000")
assert snapshot.current_ltv == Decimal("0.6744186046511628")
assert snapshot.margin_call_price == Decimal("193.33333333333334")
def test_normalize_save_status_snapshot_rejects_bool_values() -> None:
class InvalidBoundaryConfig(StringBoundaryConfig):
current_ltv = True
with pytest.raises(TypeError, match="config.current_ltv must be numeric, got bool"):
_normalize_save_status_snapshot(InvalidBoundaryConfig())
def test_save_status_text_uses_margin_call_price_api() -> None:
config = PortfolioConfig(gold_value=215_000.0, entry_price=215.0, loan_amount=145_000.0)