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:
@@ -10,7 +10,15 @@ from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from config.database import Base
|
||||
from config.settings import AdminBootstrapSettings
|
||||
from services.bootstrap import AdminBootstrapResult, RoleBootstrapResult, bootstrap_admin
|
||||
from models import MiningOperationType, Project
|
||||
from services.bootstrap import (
|
||||
AdminBootstrapResult,
|
||||
PricingBootstrapResult,
|
||||
RoleBootstrapResult,
|
||||
bootstrap_admin,
|
||||
bootstrap_pricing_settings,
|
||||
)
|
||||
from services.pricing import PricingMetadata
|
||||
from services.unit_of_work import UnitOfWork
|
||||
|
||||
|
||||
@@ -114,3 +122,86 @@ def test_bootstrap_respects_force_reset(unit_of_work_factory: Callable[[], UnitO
|
||||
user = users_repo.get_by_email(rotated_settings.email)
|
||||
assert user is not None
|
||||
assert user.verify_password("rotated")
|
||||
|
||||
|
||||
def test_bootstrap_pricing_creates_defaults(unit_of_work_factory: Callable[[], UnitOfWork]) -> None:
|
||||
metadata = PricingMetadata(
|
||||
default_payable_pct=95.0,
|
||||
default_currency="CAD",
|
||||
moisture_threshold_pct=3.0,
|
||||
moisture_penalty_per_pct=1.25,
|
||||
)
|
||||
|
||||
result = bootstrap_pricing_settings(
|
||||
metadata=metadata,
|
||||
unit_of_work_factory=unit_of_work_factory,
|
||||
)
|
||||
|
||||
assert isinstance(result, PricingBootstrapResult)
|
||||
assert result.seed.created is True
|
||||
assert result.projects_assigned == 0
|
||||
|
||||
with unit_of_work_factory() as uow:
|
||||
settings_repo = uow.pricing_settings
|
||||
assert settings_repo is not None
|
||||
stored = settings_repo.get_by_slug("default")
|
||||
assert stored.default_currency == "CAD"
|
||||
assert float(stored.default_payable_pct) == pytest.approx(95.0)
|
||||
assert float(stored.moisture_threshold_pct) == pytest.approx(3.0)
|
||||
assert float(stored.moisture_penalty_per_pct) == pytest.approx(1.25)
|
||||
|
||||
|
||||
def test_bootstrap_pricing_assigns_projects(unit_of_work_factory: Callable[[], UnitOfWork]) -> None:
|
||||
metadata = PricingMetadata(
|
||||
default_payable_pct=90.0,
|
||||
default_currency="USD",
|
||||
moisture_threshold_pct=5.0,
|
||||
moisture_penalty_per_pct=0.5,
|
||||
)
|
||||
|
||||
with unit_of_work_factory() as uow:
|
||||
projects_repo = uow.projects
|
||||
assert projects_repo is not None
|
||||
project = Project(
|
||||
name="Project Alpha",
|
||||
operation_type=MiningOperationType.OPEN_PIT,
|
||||
)
|
||||
created = projects_repo.create(project)
|
||||
project_id = created.id
|
||||
|
||||
result = bootstrap_pricing_settings(
|
||||
metadata=metadata,
|
||||
unit_of_work_factory=unit_of_work_factory,
|
||||
)
|
||||
|
||||
assert result.projects_assigned == 1
|
||||
assert result.seed.created is True
|
||||
|
||||
with unit_of_work_factory() as uow:
|
||||
projects_repo = uow.projects
|
||||
assert projects_repo is not None
|
||||
stored = projects_repo.get(project_id, with_pricing=True)
|
||||
assert stored.pricing_settings is not None
|
||||
assert stored.pricing_settings.default_currency == "USD"
|
||||
|
||||
|
||||
def test_bootstrap_pricing_is_idempotent(unit_of_work_factory: Callable[[], UnitOfWork]) -> None:
|
||||
metadata = PricingMetadata(
|
||||
default_payable_pct=92.5,
|
||||
default_currency="EUR",
|
||||
moisture_threshold_pct=4.5,
|
||||
moisture_penalty_per_pct=0.75,
|
||||
)
|
||||
|
||||
first = bootstrap_pricing_settings(
|
||||
metadata=metadata,
|
||||
unit_of_work_factory=unit_of_work_factory,
|
||||
)
|
||||
second = bootstrap_pricing_settings(
|
||||
metadata=metadata,
|
||||
unit_of_work_factory=unit_of_work_factory,
|
||||
)
|
||||
|
||||
assert first.seed.created is True
|
||||
assert second.seed.created is False
|
||||
assert second.projects_assigned == 0
|
||||
|
||||
Reference in New Issue
Block a user