- Updated form template to prefill currency input with default value and added help text for clarity. - Modified integration tests to assert more descriptive error messages for invalid currency codes. - Introduced new tests for currency normalization and validation in various scenarios, including imports and exports. - Added comprehensive tests for pricing calculations, ensuring defaults are respected and overrides function correctly. - Implemented unit tests for pricing settings repository, ensuring CRUD operations and default settings are handled properly. - Enhanced scenario pricing evaluation tests to validate currency handling and metadata defaults. - Added simulation tests to ensure Monte Carlo runs are accurate and handle various distribution scenarios.
44 lines
1.3 KiB
Python
44 lines
1.3 KiB
Python
from __future__ import annotations
|
|
|
|
"""Utilities for currency normalization within pricing and financial workflows."""
|
|
|
|
import re
|
|
from dataclasses import dataclass
|
|
|
|
VALID_CURRENCY_PATTERN = re.compile(r"^[A-Z]{3}$")
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class CurrencyValidationError(ValueError):
|
|
"""Raised when a currency code fails validation."""
|
|
|
|
code: str
|
|
|
|
def __str__(self) -> str: # pragma: no cover - dataclass repr not required in tests
|
|
return f"Invalid currency code: {self.code!r}"
|
|
|
|
|
|
def normalise_currency(code: str | None) -> str | None:
|
|
"""Normalise currency codes to uppercase ISO-4217 values."""
|
|
|
|
if code is None:
|
|
return None
|
|
candidate = code.strip().upper()
|
|
if not VALID_CURRENCY_PATTERN.match(candidate):
|
|
raise CurrencyValidationError(candidate)
|
|
return candidate
|
|
|
|
|
|
def require_currency(code: str | None, default: str | None = None) -> str:
|
|
"""Return normalised currency code, falling back to default when missing."""
|
|
|
|
normalised = normalise_currency(code)
|
|
if normalised is not None:
|
|
return normalised
|
|
if default is None:
|
|
raise CurrencyValidationError("<missing currency>")
|
|
fallback = normalise_currency(default)
|
|
if fallback is None:
|
|
raise CurrencyValidationError("<invalid default currency>")
|
|
return fallback
|