# Story 2.4: Prior-Cycle Defaults Application Status: ready-for-dev ## Story As a client services staff member, I want to copy configurable planning defaults from a municipality's prior election-cycle job into a new cycle, so that I can apply proven configurations without re-entering all details from scratch. ## Acceptance Criteria 1. **Given** an election-cycle job exists and the municipality has at least one prior completed cycle **When** a client services user selects "Apply Prior-Cycle Defaults" **Then** the prior cycle's service configurations and key date offsets are pre-populated into the new job's fields 2. **Given** prior-cycle defaults are applied **When** pre-populated fields are displayed **Then** each inherited field is visibly marked as "Inherited from [cycle name/year]" to distinguish it from manually entered data 3. **Given** a user applies defaults and then manually edits an inherited field **When** the edit is saved **Then** the "Inherited" marker is removed from that field and it is treated as a manually entered value going forward 4. **Given** a municipality has multiple prior cycles **When** applying defaults **Then** the user can select which prior cycle to use as the source from a list ordered most-recent first 5. **Given** a municipality has no prior cycles **When** the defaults action is viewed **Then** the option is disabled with a clear "No prior cycle available" message — no error state is triggered ## Tasks / Subtasks - [ ] Backend: apply-defaults endpoint (AC: #1, #4, #5) - [ ] Add an endpoint that, given a target cycle job and a chosen source prior-cycle id, copies service configuration values and key date offsets into the target job - [ ] Compute key dates by applying the source cycle's offsets relative to the target cycle's anchor date(s) — do not copy absolute dates verbatim - [ ] Reuse the read model from Story 1.13 (prior-cycle defaults view) for the source list, ordered most-recent first - [ ] Return a clear, non-error empty state when the municipality has no completed prior cycles - [ ] Backend: inheritance tracking (AC: #2, #3) - [ ] Persist an inheritance marker per field indicating source cycle id/name/year - [ ] On any subsequent save that changes the field value, clear the inheritance marker for that field atomically with the value update - [ ] Audit the apply-defaults action and subsequent inheritance clears via the shared audit logger - [ ] Frontend: apply-defaults UX (AC: #1–#5) - [ ] Add an "Apply Prior-Cycle Defaults" action on the cycle job detail with a source cycle selector ordered most-recent first - [ ] Disable the action with the empty-state message when no prior cycles exist (no error styling) - [ ] Render the "Inherited from [cycle name/year]" marker on each inherited field; remove it visually as soon as the field is edited and saved - [ ] Tests & evidence (AC: #1–#5) - [ ] Backend tests cover offset-based date application, inheritance marker lifecycle, empty-state behavior, audit emission - [ ] Frontend tests cover marker display, marker removal on edit, source cycle ordering, disabled empty state - [ ] Document changed files and any config notes ## Dev Notes - This story consumes the read-only prior-cycle defaults data delivered by Story 1.13 — extend that source rather than building a parallel one. - Key dates are applied as **offsets** relative to the target cycle's anchor, not as absolute dates. Coordinate the offset model with the key dates work from Story 2.3 (the offset basis must reference fields already persisted there). - "Inherited" is a per-field marker, not a job-level flag. A single manual edit clears only that field's marker and never the others. - The empty state ("No prior cycle available") is informational, not an error. Do not page on it or surface it as a failed validation. - All persistence remains in extension tables — no writes to legacy Access. ### Project Structure Notes - Backend: `Campaign_Tracker.Server/` — extend the election-cycle feature folder; reuse `MunicipalityPriorCycleDefaultsRepository` and related contracts from Story 1.13 - Frontend: `campaign-tracker-client/` — extend the cycle job detail view added in Stories 2.2/2.3; reuse the prior-cycle defaults modal patterns established in 1.13 - Story artifacts: `_bmad-output/implementation-artifacts/` ### References - Story source: `_bmad-output/planning-artifacts/epics.md` (Epic 2 / Story 2.4) - Architecture constraints: `_bmad-output/planning-artifacts/architecture.md` - UX patterns: `_bmad-output/planning-artifacts/ux-design-specification.md` - Prior stories: Story 1.13 — prior-cycle defaults read model; Story 2.2 — cycle job entity; Story 2.3 — key dates fields and persistence ## Dev Agent Record ### Agent Model Used {{agent_model_name_version}} ### Debug Log References - Story generated from epic source and architecture/UX planning artifacts. ### Completion Notes List - Story context created and marked ready-for-dev. ### File List ### Change Log