critical priority low complexity backend pending backend specialist Tier 1

Acceptance Criteria

BufdirPreviewModel is an immutable Dart class (all fields final, constructor const-compatible where possible)
The model contains a List<BufdirReportSectionModel> sections field in display order
The model contains a ValidationResult validationResult field
The model contains a BufdirPeriodMetadata selectedPeriod field describing the selected reporting period
The model contains a BufdirAggregationMetadata aggregationResult field describing aggregation outcomes
No field in BufdirPreviewModel requires a secondary service call to resolve — all data is embedded at construction time
The model exposes computed getters: bool hasErrors (true if validationResult contains any error-severity issue) and bool hasWarnings
The model has an equality implementation (== and hashCode) based on all fields to support BLoC state comparison
The model has a copyWith() method for state update patterns in BLoC
The class has no Flutter SDK imports — pure Dart, usable in unit tests without Flutter
BufdirPeriodMetadata and BufdirAggregationMetadata are also defined as immutable value objects in this task

Technical Requirements

frameworks
Dart
BLoC (consumed by BLoC layer — model itself has no BLoC dependency)
data models
BufdirPreviewModel
BufdirReportSectionModel
ValidationResult
BufdirPeriodMetadata
BufdirAggregationMetadata
performance requirements
Model construction is O(1) — no computation in constructor body beyond assignment
hasErrors and hasWarnings getters are O(n) on the issues list — acceptable for typical report sizes (<100 issues)
security requirements
The model must not expose raw database row data — all fields must be typed domain objects
Period metadata must not include internal database IDs in any field surfaced to the UI

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Keep the model definition in lib/features/bufdir/preview/models/bufdir_preview_model.dart. Do not use code generation (freezed, json_serializable) for this model — hand-write the immutable class to keep the dependency graph simple and avoid generated file churn. Pattern for copyWith: BufdirPreviewModel copyWith({ List? sections, ValidationResult?

validationResult, BufdirPeriodMetadata? selectedPeriod, BufdirAggregationMetadata? aggregationResult }) => BufdirPreviewModel(sections: sections ?? this.sections, ...).

For equality, override == using all four primary fields and implement hashCode with Object.hash(). BufdirPeriodMetadata should include: String periodLabel (human-readable, e.g. '2024 Q1'), DateTime startDate, DateTime endDate. BufdirAggregationMetadata should include: int totalActivities, int totalParticipants, String organizationId — these are the summary counts displayed at the top of the preview screen.

Testing Requirements

Unit tests using flutter_test. Test class: BufdirPreviewModelTest. Required scenarios: (1) model constructed with all required fields holds values correctly, (2) hasErrors returns true when ValidationResult contains an error, (3) hasErrors returns false when ValidationResult contains only warnings, (4) hasWarnings returns true when ValidationResult contains a warning, (5) hasWarnings returns false when ValidationResult is empty, (6) copyWith() returns a new instance with only the specified field changed, (7) two models with identical fields are equal (== returns true), (8) two models with differing validationResult are not equal. Tests should be in test/preview/bufdir_preview_model_test.dart.

No Flutter widget test setup required.

Component
Bufdir Preview Service
service high
Epic Risks (2)
medium impact medium prob scope

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.

high impact low prob technical

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.