diff --git a/backend/src/main/java/org/raddatz/familienarchiv/timeline/TimelineEventView.java b/backend/src/main/java/org/raddatz/familienarchiv/timeline/TimelineEventView.java new file mode 100644 index 00000000..ac67af11 --- /dev/null +++ b/backend/src/main/java/org/raddatz/familienarchiv/timeline/TimelineEventView.java @@ -0,0 +1,59 @@ +package org.raddatz.familienarchiv.timeline; + +import io.swagger.v3.oas.annotations.media.Schema; + +import org.raddatz.familienarchiv.document.DatePrecision; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +/** + * Response view for the timeline event endpoints — returned by GET, POST, and PUT alike. + * Assembled inside the service transaction (after {@code saveAndFlush} on the write paths, so + * {@code version} is non-null) from the managed entity's already-loaded collections. The raw + * {@link TimelineEvent} is never serialized: its LAZY {@code persons}/{@code documents} + * collections under {@code open-in-view: false} would otherwise 500 (ADR-036/ADR-040 §2), and + * splatting the entities would leak curator-internal fields ({@code Person.notes}, + * {@code provisional}, transcription data) to every READ_ALL reader. The explicit field + * allow-list below is that guarantee. + */ +public record TimelineEventView( + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID id, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) String title, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) EventType type, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) LocalDate eventDate, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) DatePrecision precision, + LocalDate eventDateEnd, + String description, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) Long version, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID createdBy, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) LocalDateTime createdAt, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID updatedBy, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) LocalDateTime updatedAt, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) List persons, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) List documents +) { + /** Summarised person — exposes only id, firstName, and lastName. Mirrors GeschichteView.PersonView. */ + public record PersonView( + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID id, + String firstName, + String lastName + ) {} + + /** + * Summarised linked document — id, title, and the eager {@code documentDate} only (no lazy + * sender/receiver hop, no person-name leak through the document side). + * + *

timeline-local by design; do not promote to {@code document/} — see #775 R7. Reusing + * {@code geschichte.journeyitem.DocumentSummary} would force a cross-domain import of a + * package-private mapper plus duplicated name-assembly logic; a 3-field local record is the + * lower-coupling choice. + */ + public record DocumentRef( + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID id, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) String title, + LocalDate documentDate + ) {} +}