using Microsoft.EntityFrameworkCore;
namespace Projection.ReadModel;
///
/// The read projection's persistence. This single store is the system's rebuildable read model
/// (PRD §8.4): the Event Subscriber writes to it (projector) and the projection-api reads it
/// (query). Both processes are the one "Read Projection" bounded context and share this schema —
/// not a cross-domain DB share (ADR-0008 reconciles this with CLAUDE.md §8.5).
///
public sealed class ProjectionDbContext(DbContextOptions options) : DbContext(options)
{
/// The public-facing register rows (public-safe filtering is tightened in S-09).
public DbSet RegisterEntries => Set();
/// The Event Subscriber's durable log of accepted notifications — idempotency guard and rebuild source.
public DbSet ProcessedNotifications => Set();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(e =>
{
e.ToTable("register_projection");
e.HasKey(r => r.Id);
e.Property(r => r.Id).HasColumnName("id");
e.Property(r => r.Status).HasColumnName("status").IsRequired();
e.Property(r => r.Reference).HasColumnName("reference");
e.Property(r => r.Bsn).HasColumnName("bsn");
e.Property(r => r.NaamPlaceholder).HasColumnName("naam_placeholder");
});
modelBuilder.Entity(e =>
{
e.ToTable("processed_notifications");
e.HasKey(r => r.Key);
e.Property(r => r.Key).HasColumnName("key");
e.Property(r => r.Actie).HasColumnName("actie").IsRequired();
e.Property(r => r.ZaakId).HasColumnName("zaak_id").IsRequired();
e.Property(r => r.Resource).HasColumnName("resource").IsRequired();
e.Property(r => r.Reference).HasColumnName("reference");
e.Property(r => r.ReceivedAt).HasColumnName("received_at");
});
}
}
/// A register projection row. Bsn/NaamPlaceholder are deferred (ADR-0008).
public sealed class RegisterEntryRow
{
public required string Id { get; set; }
public required string Status { get; set; }
/// The citizen-facing reference (the zaak's identificatie) — matches the submit confirmation (#78).
public string? Reference { get; set; }
public string? Bsn { get; set; }
public string? NaamPlaceholder { get; set; }
}
/// An accepted notification, retained so the projection can be rebuilt without OpenZaak (§8.1).
public sealed class ProcessedNotificationRow
{
public required string Key { get; set; }
public required string Actie { get; set; }
public required string ZaakId { get; set; }
/// The ZGW resource (e.g. zaak or status) — retained so a rebuild reprojects
/// the right status without reading OpenZaak (S-09b).
public required string Resource { get; set; }
/// The zaak reference (identificatie), retained so a rebuild reprojects it without the ACL (#78).
public string? Reference { get; set; }
public DateTimeOffset ReceivedAt { get; set; }
}