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 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-05 07:23:25 +02:00
parent e2e7b79067
commit 8b177b9430
3 changed files with 35 additions and 21 deletions

View File

@@ -94,6 +94,22 @@ public class DocumentService {
return documentRepository.save(doc); return documentRepository.save(doc);
} }
public List<org.raddatz.familienarchiv.repository.TranscriptionQueueProjection> findSegmentationQueue(int limit) {
return documentRepository.findSegmentationQueue(limit);
}
public List<org.raddatz.familienarchiv.repository.TranscriptionQueueProjection> findTranscriptionQueue(int limit) {
return documentRepository.findTranscriptionQueue(limit);
}
public List<org.raddatz.familienarchiv.repository.TranscriptionQueueProjection> findReadyToReadQueue(int limit) {
return documentRepository.findReadyToReadQueue(limit);
}
public org.raddatz.familienarchiv.repository.TranscriptionWeeklyStatsProjection findWeeklyStats() {
return documentRepository.findWeeklyStats();
}
public Map<UUID, String> findTitlesByIds(Collection<UUID> ids) { public Map<UUID, String> findTitlesByIds(Collection<UUID> ids) {
if (ids.isEmpty()) return Map.of(); if (ids.isEmpty()) return Map.of();
Map<UUID, String> titles = new HashMap<>(); Map<UUID, String> titles = new HashMap<>();

View File

@@ -5,7 +5,6 @@ import org.raddatz.familienarchiv.audit.ActivityActorDTO;
import org.raddatz.familienarchiv.audit.AuditLogQueryService; import org.raddatz.familienarchiv.audit.AuditLogQueryService;
import org.raddatz.familienarchiv.dto.TranscriptionQueueItemDTO; import org.raddatz.familienarchiv.dto.TranscriptionQueueItemDTO;
import org.raddatz.familienarchiv.dto.TranscriptionWeeklyStatsDTO; import org.raddatz.familienarchiv.dto.TranscriptionWeeklyStatsDTO;
import org.raddatz.familienarchiv.repository.DocumentRepository;
import org.raddatz.familienarchiv.repository.TranscriptionQueueProjection; import org.raddatz.familienarchiv.repository.TranscriptionQueueProjection;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -20,23 +19,23 @@ public class TranscriptionQueueService {
private static final int DEFAULT_QUEUE_SIZE = 5; private static final int DEFAULT_QUEUE_SIZE = 5;
private static final int MAX_CONTRIBUTORS = 5; private static final int MAX_CONTRIBUTORS = 5;
private final DocumentRepository documentRepository; private final DocumentService documentService;
private final AuditLogQueryService auditLogQueryService; private final AuditLogQueryService auditLogQueryService;
public List<TranscriptionQueueItemDTO> getSegmentationQueue() { public List<TranscriptionQueueItemDTO> getSegmentationQueue() {
return enrichWithContributors(documentRepository.findSegmentationQueue(DEFAULT_QUEUE_SIZE)); return enrichWithContributors(documentService.findSegmentationQueue(DEFAULT_QUEUE_SIZE));
} }
public List<TranscriptionQueueItemDTO> getTranscriptionQueue() { public List<TranscriptionQueueItemDTO> getTranscriptionQueue() {
return enrichWithContributors(documentRepository.findTranscriptionQueue(DEFAULT_QUEUE_SIZE)); return enrichWithContributors(documentService.findTranscriptionQueue(DEFAULT_QUEUE_SIZE));
} }
public List<TranscriptionQueueItemDTO> getReadyToReadQueue() { public List<TranscriptionQueueItemDTO> getReadyToReadQueue() {
return enrichWithContributors(documentRepository.findReadyToReadQueue(DEFAULT_QUEUE_SIZE)); return enrichWithContributors(documentService.findReadyToReadQueue(DEFAULT_QUEUE_SIZE));
} }
public TranscriptionWeeklyStatsDTO getWeeklyStats() { public TranscriptionWeeklyStatsDTO getWeeklyStats() {
var stats = documentRepository.findWeeklyStats(); var stats = documentService.findWeeklyStats();
return new TranscriptionWeeklyStatsDTO( return new TranscriptionWeeklyStatsDTO(
stats.getSegmentationCount(), stats.getSegmentationCount(),
stats.getTranscriptionCount() stats.getTranscriptionCount()

View File

@@ -10,7 +10,6 @@ import org.raddatz.familienarchiv.audit.ActivityActorDTO;
import org.raddatz.familienarchiv.audit.AuditLogQueryService; import org.raddatz.familienarchiv.audit.AuditLogQueryService;
import org.raddatz.familienarchiv.dto.TranscriptionQueueItemDTO; import org.raddatz.familienarchiv.dto.TranscriptionQueueItemDTO;
import org.raddatz.familienarchiv.dto.TranscriptionWeeklyStatsDTO; import org.raddatz.familienarchiv.dto.TranscriptionWeeklyStatsDTO;
import org.raddatz.familienarchiv.repository.DocumentRepository;
import org.raddatz.familienarchiv.repository.TranscriptionQueueProjection; import org.raddatz.familienarchiv.repository.TranscriptionQueueProjection;
import org.raddatz.familienarchiv.repository.TranscriptionWeeklyStatsProjection; import org.raddatz.familienarchiv.repository.TranscriptionWeeklyStatsProjection;
@@ -26,7 +25,7 @@ import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class TranscriptionQueueServiceTest { class TranscriptionQueueServiceTest {
@Mock DocumentRepository documentRepository; @Mock DocumentService documentService;
@Mock AuditLogQueryService auditLogQueryService; @Mock AuditLogQueryService auditLogQueryService;
@InjectMocks TranscriptionQueueService service; @InjectMocks TranscriptionQueueService service;
@@ -41,11 +40,11 @@ class TranscriptionQueueServiceTest {
void getSegmentationQueue_delegatesToRepositoryWithDefaultSize() { void getSegmentationQueue_delegatesToRepositoryWithDefaultSize() {
UUID id = UUID.randomUUID(); UUID id = UUID.randomUUID();
TranscriptionQueueProjection proj = mockQueueProjection(id, "Brief von 1920", null, 0, 0, 0); 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<TranscriptionQueueItemDTO> result = service.getSegmentationQueue(); List<TranscriptionQueueItemDTO> result = service.getSegmentationQueue();
verify(documentRepository).findSegmentationQueue(5); verify(documentService).findSegmentationQueue(5);
assertThat(result).hasSize(1); assertThat(result).hasSize(1);
assertThat(result.get(0).id()).isEqualTo(id); assertThat(result.get(0).id()).isEqualTo(id);
assertThat(result.get(0).title()).isEqualTo("Brief von 1920"); assertThat(result.get(0).title()).isEqualTo("Brief von 1920");
@@ -55,7 +54,7 @@ class TranscriptionQueueServiceTest {
@Test @Test
void getSegmentationQueue_returnsEmptyList_whenQueueIsEmpty() { void getSegmentationQueue_returnsEmptyList_whenQueueIsEmpty() {
when(documentRepository.findSegmentationQueue(5)).thenReturn(List.of()); when(documentService.findSegmentationQueue(5)).thenReturn(List.of());
List<TranscriptionQueueItemDTO> result = service.getSegmentationQueue(); List<TranscriptionQueueItemDTO> result = service.getSegmentationQueue();
@@ -67,7 +66,7 @@ class TranscriptionQueueServiceTest {
void getSegmentationQueue_returnsAllFive_andHasMoreFalse_whenExactlyFiveContributors() { void getSegmentationQueue_returnsAllFive_andHasMoreFalse_whenExactlyFiveContributors() {
UUID docId = UUID.randomUUID(); UUID docId = UUID.randomUUID();
TranscriptionQueueProjection proj = mockQueueProjection(docId, "Brief", null, 0, 0, 0); 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<ActivityActorDTO> fiveActors = List.of( List<ActivityActorDTO> fiveActors = List.of(
new ActivityActorDTO("A1", "#111", "Alice One"), new ActivityActorDTO("A1", "#111", "Alice One"),
@@ -89,7 +88,7 @@ class TranscriptionQueueServiceTest {
void getSegmentationQueue_mapsDocumentDateWhenPresent() { void getSegmentationQueue_mapsDocumentDateWhenPresent() {
LocalDate date = LocalDate.of(1920, 6, 15); LocalDate date = LocalDate.of(1920, 6, 15);
TranscriptionQueueProjection proj = mockQueueProjection(UUID.randomUUID(), "Brief", date, 0, 0, 0); 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<TranscriptionQueueItemDTO> result = service.getSegmentationQueue(); List<TranscriptionQueueItemDTO> result = service.getSegmentationQueue();
@@ -102,11 +101,11 @@ class TranscriptionQueueServiceTest {
void getTranscriptionQueue_delegatesToRepositoryWithDefaultSize() { void getTranscriptionQueue_delegatesToRepositoryWithDefaultSize() {
UUID id = UUID.randomUUID(); UUID id = UUID.randomUUID();
TranscriptionQueueProjection proj = mockQueueProjection(id, "Tagebuch", LocalDate.of(1943, 1, 1), 3, 1, 0); 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<TranscriptionQueueItemDTO> result = service.getTranscriptionQueue(); List<TranscriptionQueueItemDTO> result = service.getTranscriptionQueue();
verify(documentRepository).findTranscriptionQueue(5); verify(documentService).findTranscriptionQueue(5);
assertThat(result).hasSize(1); assertThat(result).hasSize(1);
assertThat(result.get(0).annotationCount()).isEqualTo(3); assertThat(result.get(0).annotationCount()).isEqualTo(3);
assertThat(result.get(0).textedBlockCount()).isEqualTo(1); assertThat(result.get(0).textedBlockCount()).isEqualTo(1);
@@ -118,11 +117,11 @@ class TranscriptionQueueServiceTest {
@Test @Test
void getReadyToReadQueue_delegatesToRepositoryWithDefaultSize() { void getReadyToReadQueue_delegatesToRepositoryWithDefaultSize() {
TranscriptionQueueProjection proj = mockQueueProjection(UUID.randomUUID(), "Urkunde", null, 4, 4, 4); 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<TranscriptionQueueItemDTO> result = service.getReadyToReadQueue(); List<TranscriptionQueueItemDTO> result = service.getReadyToReadQueue();
verify(documentRepository).findReadyToReadQueue(5); verify(documentService).findReadyToReadQueue(5);
assertThat(result).hasSize(1); assertThat(result).hasSize(1);
assertThat(result.get(0).reviewedBlockCount()).isEqualTo(4); assertThat(result.get(0).reviewedBlockCount()).isEqualTo(4);
} }
@@ -132,7 +131,7 @@ class TranscriptionQueueServiceTest {
@Test @Test
void getWeeklyStats_mapsProjectionToDTO() { void getWeeklyStats_mapsProjectionToDTO() {
TranscriptionWeeklyStatsProjection proj = mockStatsProjection(3L, 7L); TranscriptionWeeklyStatsProjection proj = mockStatsProjection(3L, 7L);
when(documentRepository.findWeeklyStats()).thenReturn(proj); when(documentService.findWeeklyStats()).thenReturn(proj);
TranscriptionWeeklyStatsDTO result = service.getWeeklyStats(); TranscriptionWeeklyStatsDTO result = service.getWeeklyStats();
@@ -143,7 +142,7 @@ class TranscriptionQueueServiceTest {
@Test @Test
void getWeeklyStats_returnsZeros_whenAllCountsAreZero() { void getWeeklyStats_returnsZeros_whenAllCountsAreZero() {
TranscriptionWeeklyStatsProjection proj = mockStatsProjection(0L, 0L); TranscriptionWeeklyStatsProjection proj = mockStatsProjection(0L, 0L);
when(documentRepository.findWeeklyStats()).thenReturn(proj); when(documentService.findWeeklyStats()).thenReturn(proj);
TranscriptionWeeklyStatsDTO result = service.getWeeklyStats(); TranscriptionWeeklyStatsDTO result = service.getWeeklyStats();
@@ -157,7 +156,7 @@ class TranscriptionQueueServiceTest {
void getSegmentationQueue_includesContributors_whenAuditDataPresent() { void getSegmentationQueue_includesContributors_whenAuditDataPresent() {
UUID docId = UUID.randomUUID(); UUID docId = UUID.randomUUID();
TranscriptionQueueProjection proj = mockQueueProjection(docId, "Brief", null, 0, 0, 0); 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"); ActivityActorDTO actor = new ActivityActorDTO("MR", "#a6dad8", "Max Raddatz");
when(auditLogQueryService.findContributorsPerDocument(List.of(docId))) when(auditLogQueryService.findContributorsPerDocument(List.of(docId)))
@@ -173,7 +172,7 @@ class TranscriptionQueueServiceTest {
void getSegmentationQueue_capsContributorsAtFive_andSetsHasMoreFlag() { void getSegmentationQueue_capsContributorsAtFive_andSetsHasMoreFlag() {
UUID docId = UUID.randomUUID(); UUID docId = UUID.randomUUID();
TranscriptionQueueProjection proj = mockQueueProjection(docId, "Brief", null, 0, 0, 0); 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<ActivityActorDTO> sixActors = List.of( List<ActivityActorDTO> sixActors = List.of(
new ActivityActorDTO("A1", "#111", "Alice One"), new ActivityActorDTO("A1", "#111", "Alice One"),