Summary
Phase 1 of the simulation/report V2 migration lays the foundation in the API for the new job-based simulation and analysis system. All changes are additive — no existing behavior is broken.
What was done
1. Fix Alembic migration branch conflict
Reconciled divergent migration branches (0002_user_policies and f419b5f4acba) with a merge migration so alembic upgrade head succeeds cleanly.
2. Add filter_field/filter_value to simulations table
Added nullable string columns to support regional filtering (e.g., state-level economy simulations that filter a national dataset).
3. Remove parent_report_id from Report model
Dropped unused parent_report_id column and its foreign key constraint. No code referenced it.
4. Create user_simulation_associations table + CRUD endpoints
New UserSimulationAssociation model and full CRUD router at /user-simulation-associations, following the existing UserPolicy pattern. 15 tests.
5. Create user_report_associations table + CRUD endpoints
New UserReportAssociation model (with last_run_at field) and full CRUD router at /user-report-associations. 16 tests.
6. Create standalone simulation endpoints
Added POST/GET /simulations/household and POST/GET /simulations/economy for creating individual simulation jobs. Non-blocking (returns pending status immediately). Deterministic UUID deduplication. 19 tests.
7. Create household_impact_uk and household_impact_us Modal functions
Report-based Modal functions that load a Report and its Simulations from the database, run household calculations, store results, and mark the report as completed. Called by _trigger_household_impact() when agent_use_modal=True.
8. Create _run_local_economy_comparison_us local fallback
US counterpart to the existing UK local economy comparison function. When agent_use_modal=False, US economy comparisons now run locally instead of falling back to Modal.
Files changed
alembic/versions/ — 5 new migration files
src/policyengine_api/models/ — new models for UserSimulationAssociation, UserReportAssociation; updated Simulation and Report models
src/policyengine_api/api/ — new routers for user associations and standalone simulations; updated analysis.py with US local fallback
src/policyengine_api/modal_app.py — new household_impact_uk and household_impact_us functions
tests/ — 50+ new tests covering all new endpoints
Test results
219 tests pass. 57 pre-existing failures (require policyengine library / Python 3.13 / DB seeding — not related to these changes).
Summary
Phase 1 of the simulation/report V2 migration lays the foundation in the API for the new job-based simulation and analysis system. All changes are additive — no existing behavior is broken.
What was done
1. Fix Alembic migration branch conflict
Reconciled divergent migration branches (
0002_user_policiesandf419b5f4acba) with a merge migration soalembic upgrade headsucceeds cleanly.2. Add
filter_field/filter_valueto simulations tableAdded nullable string columns to support regional filtering (e.g., state-level economy simulations that filter a national dataset).
3. Remove
parent_report_idfrom Report modelDropped unused
parent_report_idcolumn and its foreign key constraint. No code referenced it.4. Create
user_simulation_associationstable + CRUD endpointsNew
UserSimulationAssociationmodel and full CRUD router at/user-simulation-associations, following the existingUserPolicypattern. 15 tests.5. Create
user_report_associationstable + CRUD endpointsNew
UserReportAssociationmodel (withlast_run_atfield) and full CRUD router at/user-report-associations. 16 tests.6. Create standalone simulation endpoints
Added
POST/GET /simulations/householdandPOST/GET /simulations/economyfor creating individual simulation jobs. Non-blocking (returns pending status immediately). Deterministic UUID deduplication. 19 tests.7. Create
household_impact_ukandhousehold_impact_usModal functionsReport-based Modal functions that load a Report and its Simulations from the database, run household calculations, store results, and mark the report as completed. Called by
_trigger_household_impact()whenagent_use_modal=True.8. Create
_run_local_economy_comparison_uslocal fallbackUS counterpart to the existing UK local economy comparison function. When
agent_use_modal=False, US economy comparisons now run locally instead of falling back to Modal.Files changed
alembic/versions/— 5 new migration filessrc/policyengine_api/models/— new models for UserSimulationAssociation, UserReportAssociation; updated Simulation and Report modelssrc/policyengine_api/api/— new routers for user associations and standalone simulations; updated analysis.py with US local fallbacksrc/policyengine_api/modal_app.py— newhousehold_impact_ukandhousehold_impact_usfunctionstests/— 50+ new tests covering all new endpointsTest results
219 tests pass. 57 pre-existing failures (require
policyenginelibrary / Python 3.13 / DB seeding — not related to these changes).