feat(ownership): add take-ownership preflight endpoint

Enables dry-run checking before committing to case adoption. The preflight
shares the same side-effect-free checks (steps 1–3) as the real take-ownership
handler, so it cannot drift from what will actually succeed. Returns the same
status codes and error shapes as the real endpoint (200 with wouldSucceed:true,
or 409/404/422 if it would fail).

Portal renders a "Vooraf controleren" button for legacy cases, surfaced through
the existing actions block pattern. Confirmed in smoke.sh with two cases: one
where preflight predicts success (and writes nothing), one where it predicts
a named invariant failure (matching what the real call reproduces).

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-08-01 09:15:18 +02:00
co-authored by Claude Haiku 4.5
parent 19c010653a
commit 5f22156e6d
20 changed files with 519 additions and 156 deletions
@@ -1,5 +1,5 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, inject, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ErrorsResponse, InvariantViolationResponse, MessageResponse } from '../../shared/api-error.types';
@@ -32,6 +32,7 @@ export class EditApplicantDetails implements OnInit {
fieldErrors: Record<string, string> = {};
banner: string | null = null;
readonly saving = signal(false);
get isWriteThrough(): boolean {
return this.actionLink.mode === 'writeThrough';
@@ -52,6 +53,7 @@ export class EditApplicantDetails implements OnInit {
submit(): void {
this.fieldErrors = {};
this.banner = null;
this.saving.set(true);
const body: ApplicantDetailsRequest = {
surname: this.surname,
@@ -63,8 +65,14 @@ export class EditApplicantDetails implements OnInit {
};
this.caseDetailService.updateDetails(this.actionLink.href, body).subscribe({
next: () => this.saved.emit(),
error: (error: HttpErrorResponse) => this.handleError(error),
next: () => {
this.saving.set(false);
this.saved.emit();
},
error: (error: HttpErrorResponse) => {
this.saving.set(false);
this.handleError(error);
},
});
}