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

@@ -13,6 +13,7 @@ from models import (
FinancialCategory,
FinancialInput,
MiningOperationType,
PricingSettings,
Project,
Scenario,
ScenarioStatus,
@@ -147,6 +148,30 @@ def test_unit_of_work_commit_and_rollback(engine) -> None:
projects = ProjectRepository(session).list()
assert len(projects) == 1
def test_unit_of_work_set_project_pricing_settings(engine) -> None:
TestingSession = sessionmaker(bind=engine, expire_on_commit=False, future=True)
with UnitOfWork(session_factory=TestingSession) as uow:
assert uow.projects is not None and uow.pricing_settings is not None
project = Project(name="Project Pricing", operation_type=MiningOperationType.OTHER)
uow.projects.create(project)
pricing_settings = PricingSettings(
name="Default Pricing",
slug="default",
default_currency="usd",
default_payable_pct=100.0,
moisture_threshold_pct=8.0,
moisture_penalty_per_pct=0.0,
)
uow.pricing_settings.create(pricing_settings)
uow.set_project_pricing_settings(project, pricing_settings)
with TestingSession() as session:
repo = ProjectRepository(session)
stored = repo.get(1, with_pricing=True)
assert stored.pricing_settings is not None
assert stored.pricing_settings.slug == "default"
# Rollback path
with pytest.raises(RuntimeError):
with UnitOfWork(session_factory=TestingSession) as uow:
@@ -302,6 +327,44 @@ def test_project_repository_filtered_for_export(session: Session) -> None:
assert results[0].scenarios[0].name == "Alpha Scenario"
def test_project_repository_with_pricing_settings(session: Session) -> None:
repo = ProjectRepository(session)
settings = PricingSettings(
name="Contract Core",
slug="contract-core",
default_currency="usd",
default_payable_pct=95.0,
moisture_threshold_pct=7.5,
moisture_penalty_per_pct=100.0,
)
project = Project(
name="Project Pricing",
operation_type=MiningOperationType.OPEN_PIT,
pricing_settings=settings,
)
session.add(project)
session.flush()
fetched = repo.get(project.id, with_pricing=True)
assert fetched.pricing_settings is not None
assert fetched.pricing_settings.slug == "contract-core"
assert fetched.pricing_settings.default_currency == "USD"
listed = repo.list(with_pricing=True)
assert listed[0].pricing_settings is not None
repo.set_pricing_settings(project, None)
session.refresh(project)
assert project.pricing_settings is None
repo.set_pricing_settings(project, settings)
session.refresh(project)
assert project.pricing_settings is settings
export_results = repo.filtered_for_export(None, include_pricing=True)
assert export_results[0].pricing_settings is not None
def test_scenario_repository_filtered_for_export(session: Session) -> None:
repo = ScenarioRepository(session)