The domain withdraw command carries the caller's bsn and owner-scopes the aggregate; unknown or not-owned is 404 (indistinguishable). The BFF forwards the DigiD token's bsn and relays 204/404. Regenerate the OpenAPI spec + Angular client for the new endpoint. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 lines
2.6 KiB
C#
56 lines
2.6 KiB
C#
using Big.Domain;
|
|
|
|
namespace Big.Application;
|
|
|
|
/// <summary>A zorgprofessional's request to withdraw their own registration ("trek aanvraag in").
|
|
/// <paramref name="Bsn"/> is the authenticated caller (from the DigiD token, forwarded by the BFF):
|
|
/// only the registration's own bsn may withdraw it.</summary>
|
|
public sealed record WithdrawRegistrationCommand(RegistrationId RegistrationId, string Bsn);
|
|
|
|
/// <summary>The outcome of a withdrawal request.</summary>
|
|
public enum WithdrawOutcome
|
|
{
|
|
/// <summary>The registration is now (or already was) INGETROKKEN.</summary>
|
|
Withdrawn,
|
|
|
|
/// <summary>No registration with that id belongs to the caller — unknown, or owned by someone
|
|
/// else (the two are deliberately indistinguishable, so the endpoint reveals neither).</summary>
|
|
NotFound,
|
|
}
|
|
|
|
/// <summary>
|
|
/// The withdrawal use case (S-11): a zorgprofessional pulls a still-open registration back. It
|
|
/// advances the aggregate to INGETROKKEN, persists it, then cancels the running registratie process
|
|
/// by correlating the withdrawal message to its instance (ADR-0014), so the case leaves the
|
|
/// behandelaar's werkbak. Idempotent — a repeated or redelivered withdrawal of an already-withdrawn
|
|
/// registration is a no-op (not persisted or cancelled again). Cancelling is best-effort: if the
|
|
/// registration never started a process the withdrawal still stands (the process cancel is skipped),
|
|
/// mirroring how <see cref="BeoordeelRegistratie"/> completes its task best-effort.
|
|
/// </summary>
|
|
public sealed class WithdrawRegistration(IRegistrationStore store, IWorkflowClient workflow)
|
|
{
|
|
public async Task<WithdrawOutcome> HandleAsync(WithdrawRegistrationCommand command, CancellationToken ct = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(command);
|
|
|
|
var registration = await store.GetAsync(command.RegistrationId, ct);
|
|
|
|
// Unknown, or not the caller's registration: report NotFound either way (don't reveal which).
|
|
if (registration is null || registration.Bsn != command.Bsn)
|
|
return WithdrawOutcome.NotFound;
|
|
|
|
// A repeated withdrawal is a no-op: don't persist or cancel the already-withdrawn one again.
|
|
if (registration.Status == RegistrationStatus.Ingetrokken)
|
|
return WithdrawOutcome.Withdrawn;
|
|
|
|
registration.Withdraw();
|
|
await store.SaveAsync(registration, ct);
|
|
|
|
// Cancel the running process (if one was started) so its Beoordelen task leaves the werkbak.
|
|
if (registration.ProcessInstanceId is not null)
|
|
await workflow.WithdrawProcessAsync(registration.ProcessInstanceId, ct);
|
|
|
|
return WithdrawOutcome.Withdrawn;
|
|
}
|
|
}
|