from __future__ import annotations from decimal import Decimal import pytest from app.models.portfolio import PortfolioConfig from app.services.settings_status import _normalize_save_status_snapshot, save_status_text class CallableMarginCallPriceConfig: def __init__(self, config: PortfolioConfig) -> None: self.entry_basis_mode = config.entry_basis_mode self.gold_value = config.gold_value self.entry_price = config.entry_price self.gold_ounces = config.gold_ounces self.current_ltv = config.current_ltv self._margin_call_price = config.margin_call_price def margin_call_price(self) -> float: 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) status = save_status_text(CallableMarginCallPriceConfig(config)) assert "Saved: basis=value_price" in status assert "start=$215,000" in status assert "entry=$215.00/oz" in status assert "weight=1,000.00 oz" in status assert "LTV=67.4%" in status assert "trigger=$193.33/oz" in status