feat: Enhance currency handling and validation across scenarios

- 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.
This commit is contained in:
2025-11-11 18:29:59 +01:00
parent 032e6d2681
commit 795a9f99f4
50 changed files with 5110 additions and 81 deletions

View File

@@ -0,0 +1,54 @@
from __future__ import annotations
"""Scenario evaluation services including pricing integration."""
from dataclasses import dataclass
from typing import Iterable, Mapping
from models.scenario import Scenario
from services.pricing import (
PricingInput,
PricingMetadata,
PricingResult,
calculate_pricing,
)
@dataclass(slots=True)
class ScenarioPricingConfig:
"""Configuration for pricing evaluation within a scenario."""
metadata: PricingMetadata | None = None
@dataclass(slots=True)
class ScenarioPricingSnapshot:
"""Captured pricing results for a scenario."""
scenario_id: int
results: list[PricingResult]
class ScenarioPricingEvaluator:
"""Evaluate scenario profitability inputs using pricing services."""
def __init__(self, config: ScenarioPricingConfig | None = None) -> None:
self._config = config or ScenarioPricingConfig()
def evaluate(
self,
scenario: Scenario,
*,
inputs: Iterable[PricingInput],
metadata_override: PricingMetadata | None = None,
) -> ScenarioPricingSnapshot:
metadata = metadata_override or self._config.metadata
results: list[PricingResult] = []
for pricing_input in inputs:
result = calculate_pricing(
pricing_input,
metadata=metadata,
currency=scenario.currency,
)
results.append(result)
return ScenarioPricingSnapshot(scenario_id=scenario.id, results=results)