From bc3a268f66cf03ba3cd6cc9a10e8bc6085b01df8 Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 20 Apr 2026 21:01:54 +0200 Subject: [PATCH] feat(documents): re-add GET /api/documents/incomplete Restores the list endpoint removed in ddd811c6 and caps size at 200. The dashboard enrichment block (issue #296) and /enrich page both consume it; /enrich was silently 404ing since the deletion. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../controller/DocumentController.java | 8 +++++++ .../controller/DocumentControllerTest.java | 23 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/org/raddatz/familienarchiv/controller/DocumentController.java b/backend/src/main/java/org/raddatz/familienarchiv/controller/DocumentController.java index bbef336d..7d591c3f 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/controller/DocumentController.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/controller/DocumentController.java @@ -17,6 +17,7 @@ import org.raddatz.familienarchiv.dto.DocumentSearchResult; import org.raddatz.familienarchiv.dto.DocumentUpdateDTO; import org.raddatz.familienarchiv.dto.TagOperator; import org.raddatz.familienarchiv.dto.DocumentVersionSummary; +import org.raddatz.familienarchiv.dto.IncompleteDocumentDTO; import org.raddatz.familienarchiv.exception.DomainException; import org.raddatz.familienarchiv.exception.ErrorCode; import org.raddatz.familienarchiv.model.Document; @@ -197,6 +198,13 @@ public class DocumentController { return Map.of("count", documentService.getIncompleteCount()); } + @GetMapping("/incomplete") + public List getIncomplete( + @Parameter(description = "Maximum number of results (server caps at 200)") + @RequestParam(defaultValue = "50") int size) { + return documentService.findIncompleteDocuments(Math.min(size, 200)); + } + @GetMapping("/incomplete/next") public ResponseEntity getNextIncomplete(@RequestParam UUID excludeId) { return documentService.findNextIncompleteDocument(excludeId) diff --git a/backend/src/test/java/org/raddatz/familienarchiv/controller/DocumentControllerTest.java b/backend/src/test/java/org/raddatz/familienarchiv/controller/DocumentControllerTest.java index 6b8b5fbc..842fe43b 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/controller/DocumentControllerTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/controller/DocumentControllerTest.java @@ -391,14 +391,27 @@ class DocumentControllerTest { .andExpect(jsonPath("$.count").value(3)); } - // ─── GET /api/documents/incomplete (removed — superseded by dashboard) ──── + // ─── GET /api/documents/incomplete ─────────────────────────────────────── @Test - @WithMockUser - void getIncomplete_endpointRemoved() throws Exception { - // The path hits /{id} and fails UUID conversion — not a 200 anymore + void getIncomplete_returns401_whenUnauthenticated() throws Exception { mockMvc.perform(get("/api/documents/incomplete")) - .andExpect(status().is4xxClientError()); + .andExpect(status().isUnauthorized()); + } + + @Test + @WithMockUser(authorities = {"WRITE_ALL"}) + void getIncomplete_returns200_forWriter_withDTOList() throws Exception { + UUID id = UUID.randomUUID(); + java.time.LocalDateTime uploadedAt = java.time.LocalDateTime.of(2026, 4, 20, 12, 0); + var dto = new org.raddatz.familienarchiv.dto.IncompleteDocumentDTO(id, "Unvollständig", uploadedAt); + when(documentService.findIncompleteDocuments(anyInt())).thenReturn(List.of(dto)); + + mockMvc.perform(get("/api/documents/incomplete")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(id.toString())) + .andExpect(jsonPath("$[0].title").value("Unvollständig")) + .andExpect(jsonPath("$[0].uploadedAt").exists()); } // ─── GET /api/documents/incomplete/next ──────────────────────────────────