Two backlog trees are complete: `docs/project/backlog/` (75 files, every WP done) and `docs/project/refactor-backlog-setup/` (the arc before it). Move both under `docs/project/archive/` with `git mv`, so history stays intact through `git log --follow`. `SHOWCASE-ROADMAP.md` moves with them, because it points at the now-archived backlog README. Add `docs/project/archive/README.md`. It states that these trees are historical and names the two directories that are still live. Repoint every inbound reference named in RD-30's Files table: CLAUDE.md, the root README, both backend READMEs, `LetterHtml.cs`, `a11y.mdx`, the `document-feature` and `new-ssp` skills, and the readable-codebase PLAN, README, and RD-19 ticket. Fix two upward-relative links inside the moved WP files (WP-68, WP-69) that gained a directory level and would otherwise break. Repoint `.prettierignore`'s two agent-prompt exclusions to their new path, so prettier keeps leaving those files' exact wording alone. Mark RD-30 done and check off its acceptance criteria; flip its README row to done. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
87 lines
4.2 KiB
Markdown
87 lines
4.2 KiB
Markdown
# WP-63 — Backend: aanvraag status lifecycle as a published DTO
|
|
|
|
Status: done
|
|
Phase: 11 — Behandelportal
|
|
|
|
## Why
|
|
|
|
The FE currently infers "in behandeling" from a single boolean, `pendingHerregistratie`
|
|
(`big-profile.store.ts:53`) — explicitly called out in ADR-0002 as "a temporary stand-in
|
|
for a real, backend-owned status." The full lifecycle (`Ingediend → In behandeling →
|
|
(Meer info gevraagd ⇄) → Goedgekeurd/Afgewezen`) needs to become a real backend-published
|
|
value before either frontend can render it meaningfully — the SSP needs it as a richer
|
|
read (this WP), the behandelportal needs it as the thing it advances (WP-65).
|
|
|
|
## Read first
|
|
|
|
- [ADR-0002](../reference/architecture/0002-user-groups-and-bounded-contexts.md) (status
|
|
lifecycle diagram)
|
|
- `src/app/registratie/application/big-profile.store.ts` (the current boolean)
|
|
- [ADR-0001 — BFF-lite decision DTOs](../reference/architecture/0001-bff-lite-decision-dtos.md)
|
|
|
|
## Decisions (pre-made, don't relitigate)
|
|
|
|
- Status lives on the existing `Aanvraag`/`ApplicationSummaryDto` aggregate (extend,
|
|
don't invent a parallel status resource).
|
|
- The DTO change is additive: the SSP's `pendingHerregistratie` boolean can be derived
|
|
from the new status field (or kept as a computed convenience) so this ships with zero
|
|
required FE behavior change — a pure backend + contract widening.
|
|
- Only the status _value_ is published here; any transition (advancing it) is a separate
|
|
write endpoint, not part of this slice (that's WP-65's mutation).
|
|
|
|
## Files
|
|
|
|
- `Data/ApplicationStore.cs` (status field/enum)
|
|
- `Contracts/Dtos.cs` (extend `ApplicationSummaryDto`/status DTO)
|
|
- The FE `infrastructure/*.adapter.ts` + `parse*` boundary consuming it
|
|
- `big-profile.store.ts` (derive the existing boolean from the new field)
|
|
|
|
## Steps
|
|
|
|
1. Model the full status enum backend-side (`Ingediend`, `InBehandeling`,
|
|
`MeerInfoGevraagd`, `Goedgekeurd`, `Afgewezen`) on `Aanvraag`.
|
|
2. Publish it on the existing DTO the SSP already consumes.
|
|
3. Regenerate the typed client (`npm run gen:api`); update the FE `parse*` boundary to
|
|
read the new field.
|
|
4. Point `pendingHerregistratie` (or its replacement) at the new field so the SSP's
|
|
existing behavior is unchanged, just backed by a real value.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [x] Backend publishes the full status lifecycle value on the existing aanvraag DTO.
|
|
- [x] `npm run gen:api` leaves no drift; SSP's existing "pending" display is unchanged in
|
|
behavior, now backed by the real status.
|
|
- [x] `dotnet test` + `npm run ci` green.
|
|
|
|
## Outcome
|
|
|
|
Implemented as a pure type-system widening, not a behavior change: `AanvraagStatusTag`
|
|
(`Ingediend | InBehandeling | MeerInfoGevraagd | Goedgekeurd | Afgewezen`) is a new C# enum
|
|
backing `Mappers.ToStatusDto`'s existing string literals — `AanvraagStatusDto.Tag` stays a
|
|
plain string, so the OpenAPI schema (and `npm run gen:api`) don't change at all, satisfying
|
|
"zero required FE behavior change" trivially. `Ingediend`/`MeerInfoGevraagd` aren't reachable
|
|
from any code path yet (no behandelaar action exists to produce them) — that's WP-65's
|
|
transition endpoint, exactly per this WP's own Risks note. The FE `AanvraagStatus` union,
|
|
`parseAanvraagStatus`, `statusLabel`/`submittedRow`/`detailRows`, `blockActions`, and the
|
|
dashboard's sort order were all widened to the two new tags so TypeScript's exhaustiveness
|
|
checking forces every switch to handle them once WP-65 starts emitting them.
|
|
`big-profile.store.ts`'s `pendingHerregistratie` was deliberately left untouched — it's a
|
|
pure client-side optimistic UI flag unrelated to any DTO field (not what the WP's "Why"
|
|
section implied), and the decision text's "or kept as a computed convenience" explicitly
|
|
allows this.
|
|
|
|
## Verification
|
|
|
|
`cd backend && dotnet test`; `npm run gen:api` (no drift); `npm run ci`; manual: SSP
|
|
dashboard still shows the same pending/approved states it does today.
|
|
|
|
## Out of scope
|
|
|
|
Any endpoint that _advances_ the status (WP-65); the behandelportal consuming it (WP-64).
|
|
|
|
## Risks
|
|
|
|
If the enum doesn't anticipate a state WP-65 needs (e.g. distinguishing who can transition
|
|
from what), it gets revised there — acceptable, this slice only needs to cover the states
|
|
already named in ADR-0002's diagram.
|