high priority low complexity backend pending backend specialist Tier 0

Acceptance Criteria

PeriodPreset is an immutable Dart class (final fields, const constructor) with fields: identifier (PeriodPresetIdentifier), label (String), dateRange (DateTimeRange)
PeriodPresetIdentifier enum contains at minimum: currentCalendarYear, lastCalendarYear, currentGrantCycle, lastGrantCycle, customRange
Abstract PeriodPresetService interface declares: Future<List<PeriodPreset>> resolvePresets(String orgId) and Future<DateTimeRange> resolveRange(PeriodPresetIdentifier identifier, String orgId)
DateTimeRange is a value object with start (DateTime) and end (DateTime), implementing == and hashCode based on both fields
DateTimeRange throws an ArgumentError if start is after end at construction time
All types are defined in a dedicated domain layer directory (e.g., lib/domain/period_selection/) with no Flutter or Supabase imports — pure Dart only
Dartdoc comments are present on all public classes, enums, and interface methods
A companion unit test file verifies DateTimeRange equality, hash consistency, and the ArgumentError for invalid ranges

Technical Requirements

frameworks
Dart (pure, no Flutter dependency)
flutter_test (for companion unit tests)
data models
annual_summary
activity
performance requirements
All domain model constructors are const-eligible where possible to enable compile-time constant instances
security requirements
orgId parameter must be typed as String (UUID) — do not accept dynamic or Object to prevent accidental type confusion

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Keep this layer entirely free of Flutter, Riverpod, and Supabase imports — it must be testable as plain Dart. Use Dart's built-in DateTimeRange if it satisfies requirements; if not, define a custom one and name it clearly (e.g., PeriodDateRange) to avoid import conflicts with Flutter's DateTimeRange. Define the abstract interface (abstract class PeriodPresetService) rather than a mixin or extension type so Riverpod providers can return concrete implementations without losing type safety. Place all domain models under lib/domain/period_selection/ to establish a clear domain boundary that implementation layers depend on, not the reverse.

This task produces the contract that tasks -002 and -003 implement — keep it stable after merging.

Testing Requirements

Unit tests for DateTimeRange value object: (1) two instances with identical start/end are equal (==) and share the same hashCode, (2) ArgumentError is thrown when start > end, (3) boundary case: start == end is valid (zero-duration range). Unit tests for PeriodPreset: (1) const constructor produces expected field values. No mocking required — pure domain logic only. 100% line coverage expected given the simplicity.

Component
Period Preset Service
service low
Epic Risks (2)
medium impact high prob dependency

Detecting overlap with previously submitted reports requires querying a report history table that may not yet exist or may not have a reliable submitted_at / period_end field, making the validator dependent on an incomplete upstream feature (Bufdir Report History & Audit Log).

Mitigation & Contingency

Mitigation: Define the minimum interface (a single repository method: getSubmittedPeriods(orgId) → List<DateTimeRange>) as an abstract class in this epic. Implement a stub that returns an empty list until the history feature is available, so the validator compiles and passes tests without a real data source.

Contingency: If the history feature is delayed beyond this feature's delivery window, ship the validator with the stub returning an empty list (overlap check disabled) and surface a feature-flag-controlled warning banner explaining that overlap detection will be enabled in a future update.

medium impact medium prob scope

Bufdir's structural requirements for reporting periods (complete calendar months, grant-year span restrictions) may be ambiguous or subject to change, causing the validator to enforce rules that are incorrect or overly restrictive for some organisations.

Mitigation & Contingency

Mitigation: Document the specific Bufdir rules being enforced in the validator's source code as named constants with references to the relevant Bufdir guidelines. Review the rules with at least one coordinator representative before implementation is finalised.

Contingency: Expose a per-org configuration flag (strict_bufdir_validation: bool) in the period configuration repository so that rule enforcement can be relaxed for specific organisations without a code deployment.