diff --git a/backend/src/main/java/org/raddatz/familienarchiv/document/DocumentService.java b/backend/src/main/java/org/raddatz/familienarchiv/document/DocumentService.java index 4f69922c..624a2a37 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/document/DocumentService.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/document/DocumentService.java @@ -1006,6 +1006,16 @@ public class DocumentService { return doc; } + /** + * Lean document lookup for embedding in JourneyItemView. Skips + * {@code tagService.resolveEffectiveColors} — ×N items per journey GET is wasted + * work that summary consumers never read. Called within a caller-provided transaction. + */ + public Document getSummaryById(UUID id) { + return documentRepository.findById(id) + .orElseThrow(() -> DomainException.notFound(ErrorCode.DOCUMENT_NOT_FOUND, "Document not found: " + id)); + } + /** * Loads a document for the detail view, additionally flagging whether it has any * transcription to read. Kept separate from {@link #getDocumentById} so the cheap diff --git a/backend/src/main/java/org/raddatz/familienarchiv/geschichte/DocumentSummary.java b/backend/src/main/java/org/raddatz/familienarchiv/geschichte/DocumentSummary.java new file mode 100644 index 00000000..151017f7 --- /dev/null +++ b/backend/src/main/java/org/raddatz/familienarchiv/geschichte/DocumentSummary.java @@ -0,0 +1,23 @@ +package org.raddatz.familienarchiv.geschichte; + +import io.swagger.v3.oas.annotations.media.Schema; +import org.raddatz.familienarchiv.document.DatePrecision; + +import java.time.LocalDate; +import java.util.UUID; + +/** + * Lean read-model view of a Document for embedding in JourneyItemView. + * Built by JourneyItemService.toSummary(Document) — never serialised from + * a JPA entity to avoid LazyInitializationException and tag-color overhead. + */ +public record DocumentSummary( + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID id, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) String title, + LocalDate documentDate, + LocalDate documentDateEnd, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) DatePrecision datePrecision, + String senderName, + String receiverName, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) Integer receiverCount +) {} diff --git a/backend/src/main/java/org/raddatz/familienarchiv/geschichte/GeschichteView.java b/backend/src/main/java/org/raddatz/familienarchiv/geschichte/GeschichteView.java new file mode 100644 index 00000000..2fa5a920 --- /dev/null +++ b/backend/src/main/java/org/raddatz/familienarchiv/geschichte/GeschichteView.java @@ -0,0 +1,36 @@ +package org.raddatz.familienarchiv.geschichte; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; +import org.raddatz.familienarchiv.geschichte.journeyitem.JourneyItemView; +import org.raddatz.familienarchiv.person.Person; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +/** + * Detail-view response for GET /api/geschichten/{id}. Assembled by + * GeschichteService — never the raw entity (author AppUser graph must not leak). + * items is always present (both STORY and JOURNEY); empty list for stories with no items. + */ +public record GeschichteView( + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID id, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) String title, + String body, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) GeschichteStatus status, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) GeschichteType type, + AuthorView author, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) Set persons, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) List items, + LocalDateTime publishedAt, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) LocalDateTime createdAt, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) LocalDateTime updatedAt +) { + /** Summarised author — exposes only id and displayName, never email or group memberships. */ + public record AuthorView( + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID id, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) String displayName + ) {} +} diff --git a/backend/src/main/java/org/raddatz/familienarchiv/geschichte/journeyitem/JourneyItemView.java b/backend/src/main/java/org/raddatz/familienarchiv/geschichte/journeyitem/JourneyItemView.java new file mode 100644 index 00000000..b15dc6b1 --- /dev/null +++ b/backend/src/main/java/org/raddatz/familienarchiv/geschichte/journeyitem/JourneyItemView.java @@ -0,0 +1,17 @@ +package org.raddatz.familienarchiv.geschichte.journeyitem; + +import io.swagger.v3.oas.annotations.media.Schema; +import org.raddatz.familienarchiv.geschichte.DocumentSummary; + +import java.util.UUID; + +/** + * Read-model response for a JourneyItem. Never the JPA entity (which has a + * Geschichte back-reference that would leak / hit LazyInitializationException). + */ +public record JourneyItemView( + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID id, + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) int position, + DocumentSummary document, + String note +) {}