From 8b177b94303a6d512ba1cd340b1980ef20f8f273 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 5 May 2026 07:23:25 +0200 Subject: [PATCH] refactor(transcription-queue): route through DocumentService projections TranscriptionQueueService injected DocumentRepository to fetch the four queue projections. Move the four read methods (findSegmentationQueue, findTranscriptionQueue, findReadyToReadQueue, findWeeklyStats) onto DocumentService as 1-line delegations and update the consumer. Refs #417 (C6.2 violation #5). Co-Authored-By: Claude Opus 4.7 --- .../service/DocumentService.java | 16 ++++++++++ .../service/TranscriptionQueueService.java | 11 ++++--- .../TranscriptionQueueServiceTest.java | 29 +++++++++---------- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/backend/src/main/java/org/raddatz/familienarchiv/service/DocumentService.java b/backend/src/main/java/org/raddatz/familienarchiv/service/DocumentService.java index 399395b4..d02c36aa 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/service/DocumentService.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/service/DocumentService.java @@ -94,6 +94,22 @@ public class DocumentService { return documentRepository.save(doc); } + public List findSegmentationQueue(int limit) { + return documentRepository.findSegmentationQueue(limit); + } + + public List findTranscriptionQueue(int limit) { + return documentRepository.findTranscriptionQueue(limit); + } + + public List findReadyToReadQueue(int limit) { + return documentRepository.findReadyToReadQueue(limit); + } + + public org.raddatz.familienarchiv.repository.TranscriptionWeeklyStatsProjection findWeeklyStats() { + return documentRepository.findWeeklyStats(); + } + public Map findTitlesByIds(Collection ids) { if (ids.isEmpty()) return Map.of(); Map titles = new HashMap<>(); diff --git a/backend/src/main/java/org/raddatz/familienarchiv/service/TranscriptionQueueService.java b/backend/src/main/java/org/raddatz/familienarchiv/service/TranscriptionQueueService.java index 6b82abb9..50ffbac6 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/service/TranscriptionQueueService.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/service/TranscriptionQueueService.java @@ -5,7 +5,6 @@ import org.raddatz.familienarchiv.audit.ActivityActorDTO; import org.raddatz.familienarchiv.audit.AuditLogQueryService; import org.raddatz.familienarchiv.dto.TranscriptionQueueItemDTO; import org.raddatz.familienarchiv.dto.TranscriptionWeeklyStatsDTO; -import org.raddatz.familienarchiv.repository.DocumentRepository; import org.raddatz.familienarchiv.repository.TranscriptionQueueProjection; import org.springframework.stereotype.Service; @@ -20,23 +19,23 @@ public class TranscriptionQueueService { private static final int DEFAULT_QUEUE_SIZE = 5; private static final int MAX_CONTRIBUTORS = 5; - private final DocumentRepository documentRepository; + private final DocumentService documentService; private final AuditLogQueryService auditLogQueryService; public List getSegmentationQueue() { - return enrichWithContributors(documentRepository.findSegmentationQueue(DEFAULT_QUEUE_SIZE)); + return enrichWithContributors(documentService.findSegmentationQueue(DEFAULT_QUEUE_SIZE)); } public List getTranscriptionQueue() { - return enrichWithContributors(documentRepository.findTranscriptionQueue(DEFAULT_QUEUE_SIZE)); + return enrichWithContributors(documentService.findTranscriptionQueue(DEFAULT_QUEUE_SIZE)); } public List getReadyToReadQueue() { - return enrichWithContributors(documentRepository.findReadyToReadQueue(DEFAULT_QUEUE_SIZE)); + return enrichWithContributors(documentService.findReadyToReadQueue(DEFAULT_QUEUE_SIZE)); } public TranscriptionWeeklyStatsDTO getWeeklyStats() { - var stats = documentRepository.findWeeklyStats(); + var stats = documentService.findWeeklyStats(); return new TranscriptionWeeklyStatsDTO( stats.getSegmentationCount(), stats.getTranscriptionCount() diff --git a/backend/src/test/java/org/raddatz/familienarchiv/service/TranscriptionQueueServiceTest.java b/backend/src/test/java/org/raddatz/familienarchiv/service/TranscriptionQueueServiceTest.java index 6c7a47ac..624a3f82 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/service/TranscriptionQueueServiceTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/service/TranscriptionQueueServiceTest.java @@ -10,7 +10,6 @@ import org.raddatz.familienarchiv.audit.ActivityActorDTO; import org.raddatz.familienarchiv.audit.AuditLogQueryService; import org.raddatz.familienarchiv.dto.TranscriptionQueueItemDTO; import org.raddatz.familienarchiv.dto.TranscriptionWeeklyStatsDTO; -import org.raddatz.familienarchiv.repository.DocumentRepository; import org.raddatz.familienarchiv.repository.TranscriptionQueueProjection; import org.raddatz.familienarchiv.repository.TranscriptionWeeklyStatsProjection; @@ -26,7 +25,7 @@ import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class TranscriptionQueueServiceTest { - @Mock DocumentRepository documentRepository; + @Mock DocumentService documentService; @Mock AuditLogQueryService auditLogQueryService; @InjectMocks TranscriptionQueueService service; @@ -41,11 +40,11 @@ class TranscriptionQueueServiceTest { void getSegmentationQueue_delegatesToRepositoryWithDefaultSize() { UUID id = UUID.randomUUID(); TranscriptionQueueProjection proj = mockQueueProjection(id, "Brief von 1920", null, 0, 0, 0); - when(documentRepository.findSegmentationQueue(5)).thenReturn(List.of(proj)); + when(documentService.findSegmentationQueue(5)).thenReturn(List.of(proj)); List result = service.getSegmentationQueue(); - verify(documentRepository).findSegmentationQueue(5); + verify(documentService).findSegmentationQueue(5); assertThat(result).hasSize(1); assertThat(result.get(0).id()).isEqualTo(id); assertThat(result.get(0).title()).isEqualTo("Brief von 1920"); @@ -55,7 +54,7 @@ class TranscriptionQueueServiceTest { @Test void getSegmentationQueue_returnsEmptyList_whenQueueIsEmpty() { - when(documentRepository.findSegmentationQueue(5)).thenReturn(List.of()); + when(documentService.findSegmentationQueue(5)).thenReturn(List.of()); List result = service.getSegmentationQueue(); @@ -67,7 +66,7 @@ class TranscriptionQueueServiceTest { void getSegmentationQueue_returnsAllFive_andHasMoreFalse_whenExactlyFiveContributors() { UUID docId = UUID.randomUUID(); TranscriptionQueueProjection proj = mockQueueProjection(docId, "Brief", null, 0, 0, 0); - when(documentRepository.findSegmentationQueue(5)).thenReturn(List.of(proj)); + when(documentService.findSegmentationQueue(5)).thenReturn(List.of(proj)); List fiveActors = List.of( new ActivityActorDTO("A1", "#111", "Alice One"), @@ -89,7 +88,7 @@ class TranscriptionQueueServiceTest { void getSegmentationQueue_mapsDocumentDateWhenPresent() { LocalDate date = LocalDate.of(1920, 6, 15); TranscriptionQueueProjection proj = mockQueueProjection(UUID.randomUUID(), "Brief", date, 0, 0, 0); - when(documentRepository.findSegmentationQueue(5)).thenReturn(List.of(proj)); + when(documentService.findSegmentationQueue(5)).thenReturn(List.of(proj)); List result = service.getSegmentationQueue(); @@ -102,11 +101,11 @@ class TranscriptionQueueServiceTest { void getTranscriptionQueue_delegatesToRepositoryWithDefaultSize() { UUID id = UUID.randomUUID(); TranscriptionQueueProjection proj = mockQueueProjection(id, "Tagebuch", LocalDate.of(1943, 1, 1), 3, 1, 0); - when(documentRepository.findTranscriptionQueue(5)).thenReturn(List.of(proj)); + when(documentService.findTranscriptionQueue(5)).thenReturn(List.of(proj)); List result = service.getTranscriptionQueue(); - verify(documentRepository).findTranscriptionQueue(5); + verify(documentService).findTranscriptionQueue(5); assertThat(result).hasSize(1); assertThat(result.get(0).annotationCount()).isEqualTo(3); assertThat(result.get(0).textedBlockCount()).isEqualTo(1); @@ -118,11 +117,11 @@ class TranscriptionQueueServiceTest { @Test void getReadyToReadQueue_delegatesToRepositoryWithDefaultSize() { TranscriptionQueueProjection proj = mockQueueProjection(UUID.randomUUID(), "Urkunde", null, 4, 4, 4); - when(documentRepository.findReadyToReadQueue(5)).thenReturn(List.of(proj)); + when(documentService.findReadyToReadQueue(5)).thenReturn(List.of(proj)); List result = service.getReadyToReadQueue(); - verify(documentRepository).findReadyToReadQueue(5); + verify(documentService).findReadyToReadQueue(5); assertThat(result).hasSize(1); assertThat(result.get(0).reviewedBlockCount()).isEqualTo(4); } @@ -132,7 +131,7 @@ class TranscriptionQueueServiceTest { @Test void getWeeklyStats_mapsProjectionToDTO() { TranscriptionWeeklyStatsProjection proj = mockStatsProjection(3L, 7L); - when(documentRepository.findWeeklyStats()).thenReturn(proj); + when(documentService.findWeeklyStats()).thenReturn(proj); TranscriptionWeeklyStatsDTO result = service.getWeeklyStats(); @@ -143,7 +142,7 @@ class TranscriptionQueueServiceTest { @Test void getWeeklyStats_returnsZeros_whenAllCountsAreZero() { TranscriptionWeeklyStatsProjection proj = mockStatsProjection(0L, 0L); - when(documentRepository.findWeeklyStats()).thenReturn(proj); + when(documentService.findWeeklyStats()).thenReturn(proj); TranscriptionWeeklyStatsDTO result = service.getWeeklyStats(); @@ -157,7 +156,7 @@ class TranscriptionQueueServiceTest { void getSegmentationQueue_includesContributors_whenAuditDataPresent() { UUID docId = UUID.randomUUID(); TranscriptionQueueProjection proj = mockQueueProjection(docId, "Brief", null, 0, 0, 0); - when(documentRepository.findSegmentationQueue(5)).thenReturn(List.of(proj)); + when(documentService.findSegmentationQueue(5)).thenReturn(List.of(proj)); ActivityActorDTO actor = new ActivityActorDTO("MR", "#a6dad8", "Max Raddatz"); when(auditLogQueryService.findContributorsPerDocument(List.of(docId))) @@ -173,7 +172,7 @@ class TranscriptionQueueServiceTest { void getSegmentationQueue_capsContributorsAtFive_andSetsHasMoreFlag() { UUID docId = UUID.randomUUID(); TranscriptionQueueProjection proj = mockQueueProjection(docId, "Brief", null, 0, 0, 0); - when(documentRepository.findSegmentationQueue(5)).thenReturn(List.of(proj)); + when(documentService.findSegmentationQueue(5)).thenReturn(List.of(proj)); List sixActors = List.of( new ActivityActorDTO("A1", "#111", "Alice One"),