Problem
The current legacy report flow in policyengine-api has no supported way to rerun a previously completed report.
That blocks the current app from offering a "rerun report" action, because the backend cannot reset the stored legacy state that makes the frontend think the work is already complete.
Today, rerunning a legacy report needs to do more than just clear the report row:
report_outputs.output and report_outputs.error_message must be cleared
- the report status must go back to
pending
- linked
simulations.output and simulations.error_message may also need to be cleared
- linked simulation statuses may need to go back to
pending
- economy report cache rows in
reform_impact may need to be deleted so the economy calculation actually recomputes
Why This Is Annoying
There are a few legacy constraints that make this non-trivial:
report_outputs rows are reused by simulation ids, year, and cache version
simulations rows are reused by country, population, and policy
- the economy cache lives in
reform_impact, which is keyed more broadly than the report row itself
- the existing update helpers only write
output / error_message when the incoming value is non-None, so they cannot express a true reset-to-pending operation
Required Behavior
We need a supported legacy rerun path that:
- loads the stored
report_outputs row
- loads the linked simulation row(s)
- resets the report row to
pending and clears persisted output/error state
- resets the linked simulation row(s) to
pending and clears persisted output/error state
- for economy-shaped reports, deletes the matching
reform_impact cache row(s)
- returns a small success payload for the current app to consume
For the current legacy app path, economy reruns can use these assumptions when targeting reform_impact:
dataset = "default"
options_hash = "[]"
time_period = report.year
baseline_policy_id = simulation_1.policy_id
reform_policy_id = simulation_2.policy_id when present, otherwise simulation_1.policy_id
region = simulation_1.population_id
api_version = current economy cache version
That assumption set is correct for the current app-generated legacy flow, but should not be mistaken for a universal provenance model for all historical legacy callers.
Acceptance Criteria
- legacy services expose explicit reset helpers for reports and simulations
- economy cache deletion can remove completed cache rows, not just
computing rows
POST /<country_id>/report/<report_id>/rerun exists
- household reruns clear report and simulation persisted output
- economy reruns also delete matching
reform_impact rows
- malformed linked-simulation state returns a controlled error without partially mutating stored rows
- tests cover household, economy, and malformed-linkage cases
Problem
The current legacy report flow in
policyengine-apihas no supported way to rerun a previously completed report.That blocks the current app from offering a "rerun report" action, because the backend cannot reset the stored legacy state that makes the frontend think the work is already complete.
Today, rerunning a legacy report needs to do more than just clear the report row:
report_outputs.outputandreport_outputs.error_messagemust be clearedpendingsimulations.outputandsimulations.error_messagemay also need to be clearedpendingreform_impactmay need to be deleted so the economy calculation actually recomputesWhy This Is Annoying
There are a few legacy constraints that make this non-trivial:
report_outputsrows are reused by simulation ids, year, and cache versionsimulationsrows are reused by country, population, and policyreform_impact, which is keyed more broadly than the report row itselfoutput/error_messagewhen the incoming value is non-None, so they cannot express a true reset-to-pending operationRequired Behavior
We need a supported legacy rerun path that:
report_outputsrowpendingand clears persisted output/error statependingand clears persisted output/error statereform_impactcache row(s)For the current legacy app path, economy reruns can use these assumptions when targeting
reform_impact:dataset = "default"options_hash = "[]"time_period = report.yearbaseline_policy_id = simulation_1.policy_idreform_policy_id = simulation_2.policy_idwhen present, otherwisesimulation_1.policy_idregion = simulation_1.population_idapi_version = current economy cache versionThat assumption set is correct for the current app-generated legacy flow, but should not be mistaken for a universal provenance model for all historical legacy callers.
Acceptance Criteria
computingrowsPOST /<country_id>/report/<report_id>/rerunexistsreform_impactrows