Implement session state management in PreviewService
epic-bufdir-report-preview-core-logic-task-009 — Extend BufdirPreviewService with session state: store the most recently assembled BufdirPreviewModel (selected period, aggregation results) in memory so that navigating from the preview screen to the export screen does not require re-fetching or re-aggregating data. Expose a getCachedPreview() method and an invalidate() method. Use Riverpod StateNotifier or Bloc to hold service state. Document the cache lifetime — it must be cleared on period change or org switch.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Implement a BufdirPreviewSessionState sealed class with variants: Initial, Loading, Loaded(BufdirPreviewModel model, String periodId, String orgId), and Error(Object error). Use a Riverpod StateNotifier
Expose getCachedPreview() as a synchronous selector on the current state. Invalidate() simply emits Initial(). Document explicitly that this cache is a performance optimisation for the preview→export navigation flow and must not be used as a source of truth for any write operations.
Testing Requirements
Unit tests using flutter_test: (1) getCachedPreview returns null before first assembly, (2) getCachedPreview returns model after successful assembly, (3) invalidate clears cache and subsequent getCachedPreview returns null, (4) second assemblePreview with same args does not invoke repository, (5) period change invalidates cache before new assembly, (6) org switch invalidates cache. Use fakeAsync and mocktail. Test StateNotifier/Cubit state stream emissions for each lifecycle transition (loading → loaded → invalidated). Aim for 100% statement coverage on the session state class.
The exact minimum threshold values required by Bufdir guidelines (e.g., minimum participant counts per section) may not be formally documented in machine-readable form. If thresholds must be researched or negotiated during implementation, the validation service will be delayed and may launch with incomplete rules, reducing its effectiveness.
Mitigation & Contingency
Mitigation: Compile threshold rules from the Bufdir reporting guidelines PDF before sprint start. Store rules in a separate configuration file (not hardcoded in the service class) so they can be updated without a service rewrite. Treat unknown thresholds as 'no minimum' to avoid false errors.
Contingency: Launch with completeness and anomaly validation only, shipping threshold compliance rules as a follow-on config update once rules are confirmed with Bufdir. Flag this as a known limitation in the coordinator help text.
BufdirPreviewService coordinates three async operations (fetch aggregated data, map structure, run validation). Race conditions or partial failures in this chain could produce an inconsistent preview model — e.g., a model with field values but no validation results — which would silently mislead coordinators into thinking the report is clean.
Mitigation & Contingency
Mitigation: Model the orchestration as a single BLoC/Cubit state machine with explicit states (Loading, Loaded, Error) and ensure validation is always run atomically after mapping, never in parallel. Write integration tests that simulate network failure at each step of the chain.
Contingency: If a partial failure state reaches production, detect it via the missing validation summary field in the preview model and show a full-screen error state rather than an incomplete preview, prompting the coordinator to retry.