from __future__ import annotations import pytest from models import MiningOperationType, Project, Scenario, ScenarioStatus from services.pricing import PricingInput, PricingMetadata from services.scenario_evaluation import ScenarioPricingConfig, ScenarioPricingEvaluator def build_scenario() -> Scenario: project = Project(name="Test Project", operation_type=MiningOperationType.OPEN_PIT) scenario = Scenario( project=project, project_id=1, name="Scenario A", status=ScenarioStatus.ACTIVE, currency="USD", ) scenario.id = 1 # simulate persisted entity return scenario def test_scenario_pricing_evaluator_uses_metadata_defaults() -> None: scenario = build_scenario() evaluator = ScenarioPricingEvaluator( ScenarioPricingConfig( metadata=PricingMetadata( default_currency="USD", default_payable_pct=95) ) ) inputs = [ PricingInput( metal="copper", ore_tonnage=50_000, head_grade_pct=1.0, recovery_pct=90, payable_pct=None, reference_price=9_000, treatment_charge=50_000, smelting_charge=10_000, moisture_pct=9, moisture_threshold_pct=None, moisture_penalty_per_pct=None, impurity_ppm={"As": 120}, premiums=10_000, fx_rate=1.0, currency_code=None, ) ] snapshot = evaluator.evaluate(scenario, inputs=inputs) assert snapshot.scenario_id == scenario.id assert len(snapshot.results) == 1 result = snapshot.results[0] assert result.currency == "USD" assert result.net_revenue > 0 def test_scenario_pricing_evaluator_override_metadata() -> None: scenario = build_scenario() evaluator = ScenarioPricingEvaluator(ScenarioPricingConfig()) metadata_override = PricingMetadata( default_currency="CAD", default_payable_pct=90, moisture_threshold_pct=5, moisture_penalty_per_pct=500, ) inputs = [ PricingInput( metal="copper", ore_tonnage=20_000, head_grade_pct=1.2, recovery_pct=88, payable_pct=None, reference_price=8_200, treatment_charge=15_000, smelting_charge=6_000, moisture_pct=6, moisture_threshold_pct=None, moisture_penalty_per_pct=None, premiums=5_000, fx_rate=1.0, currency_code="cad", ), PricingInput( metal="gold", ore_tonnage=5_000, head_grade_pct=2.0, recovery_pct=90, payable_pct=None, reference_price=60_000, treatment_charge=10_000, smelting_charge=5_000, moisture_pct=4, moisture_threshold_pct=None, moisture_penalty_per_pct=None, premiums=15_000, fx_rate=1.0, currency_code="cad", ), ] snapshot = evaluator.evaluate( scenario, inputs=inputs, metadata_override=metadata_override, ) assert len(snapshot.results) == 2 assert all(result.currency == scenario.currency for result in snapshot.results) copper_result = snapshot.results[0] expected_payable = 20_000 * 0.012 * 0.88 * 0.90 assert copper_result.payable_metal_tonnes == pytest.approx( expected_payable) assert sum(result.net_revenue for result in snapshot.results) > 0