diff --git a/tests/applications/modelling_e2e/test_handler.py b/tests/applications/modelling_e2e/test_handler.py index f2e33187b..32319bcd5 100644 --- a/tests/applications/modelling_e2e/test_handler.py +++ b/tests/applications/modelling_e2e/test_handler.py @@ -511,6 +511,70 @@ def test_attach_mode_partial_failure_persists_successes_then_records_failure() - ] +def test_first_plan_for_a_property_becomes_its_default() -> None: + """A property's first Plan is its default whatever the Scenario says (the + legacy p.is_new rule — readers select one default Plan per property); a + property that already has a default Plan keeps the Scenario's flag.""" + # Arrange — a non-default scenario; 111 has no default plan yet, 222 does + pid_first, pid_has_default = 111, 222 + mock_engine = _engine_mock( + [pid_first, pid_has_default], [1001, 1002], [POSTCODE, POSTCODE] + ) + scenario = MagicMock() + scenario.is_default = False + + with ExitStack() as stack: + stack.enter_context(patch("applications.modelling_e2e.handler.os.environ", _ENV)) + stack.enter_context( + patch("applications.modelling_e2e.handler._get_engine", return_value=mock_engine) + ) + stack.enter_context( + patch("applications.modelling_e2e.handler.EpcClientService") + ).return_value.get_by_uprn.return_value = MagicMock() + stack.enter_context(patch("applications.modelling_e2e.handler.GeospatialS3Repository")) + stack.enter_context(patch("applications.modelling_e2e.handler.GoogleSolarApiClient")) + stack.enter_context( + patch("applications.modelling_e2e.handler._spatial_for", return_value=None) + ) + stack.enter_context( + patch("applications.modelling_e2e.handler._solar_insights_for", return_value=None) + ) + stack.enter_context( + patch("applications.modelling_e2e.handler.overlays_from", return_value=[]) + ) + stack.enter_context( + patch("applications.modelling_e2e.handler.PropertyOverridesPostgresReader") + ).return_value.overrides_for_many.return_value = {} + stack.enter_context( + patch("applications.modelling_e2e.handler.ScenarioPostgresRepository") + ).return_value.get_many.return_value = [scenario] + stack.enter_context(patch("applications.modelling_e2e.handler.catalogue_snapshot_with_off_catalogue_overrides")) + stack.enter_context(patch("applications.modelling_e2e.handler.Session")) + stack.enter_context( + patch("applications.modelling_e2e.handler.run_modelling", return_value=_plan_mock()) + ) + MockUoW = stack.enter_context(patch("applications.modelling_e2e.handler.PostgresUnitOfWork")) + mock_uow = MagicMock() + mock_uow.plan.property_ids_with_default_plans.return_value = {pid_has_default} + MockUoW.return_value.__enter__.return_value = mock_uow + MockUoW.return_value.__exit__.return_value = False + + # Act + from applications.modelling_e2e.handler import handler + handler.__wrapped__( # type: ignore[attr-defined] + {"property_ids": [pid_first, pid_has_default], + "portfolio_id": PORTFOLIO_ID, "scenario_id": SCENARIO_ID, + "refetch_solar": False, "dry_run": False}, + None, _mock_orchestrator(), uuid4(), + ) + + # Assert — the first-timer's plan is promoted; the other keeps the flag + plan_requests = mock_uow.plan.save_batch.call_args.args[0] + by_pid = {r.property_id: r for r in plan_requests} + assert by_pid[pid_first].is_default is True + assert by_pid[pid_has_default].is_default is False + + # --------------------------------------------------------------------------- # Lodged EPC path # ---------------------------------------------------------------------------