diff --git a/backend/src/main/java/org/raddatz/familienarchiv/service/AnnotationService.java b/backend/src/main/java/org/raddatz/familienarchiv/service/AnnotationService.java index f52c70b0..6735ef31 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/service/AnnotationService.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/service/AnnotationService.java @@ -48,6 +48,26 @@ public class AnnotationService { return annotationRepository.save(annotation); } + @Transactional + public DocumentAnnotation createOcrAnnotation(UUID documentId, CreateAnnotationDTO dto, + UUID userId, String fileHash, + List> polygon) { + DocumentAnnotation annotation = DocumentAnnotation.builder() + .documentId(documentId) + .pageNumber(dto.getPageNumber()) + .x(dto.getX()) + .y(dto.getY()) + .width(dto.getWidth()) + .height(dto.getHeight()) + .color(dto.getColor()) + .fileHash(fileHash) + .createdBy(userId) + .polygon(polygon) + .build(); + + return annotationRepository.save(annotation); + } + @Transactional public void deleteAnnotation(UUID documentId, UUID annotationId, UUID userId) { DocumentAnnotation annotation = annotationRepository diff --git a/backend/src/test/java/org/raddatz/familienarchiv/service/AnnotationServiceTest.java b/backend/src/test/java/org/raddatz/familienarchiv/service/AnnotationServiceTest.java index 2605cfb1..37652179 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/service/AnnotationServiceTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/service/AnnotationServiceTest.java @@ -260,6 +260,55 @@ class AnnotationServiceTest { verify(annotationRepository).save(any()); } + // ─── createOcrAnnotation ────────────────────────────────────────────────── + + @Test + void createOcrAnnotation_skipsOverlapCheck_andSavesWithPolygon() { + UUID docId = UUID.randomUUID(); + UUID userId = UUID.randomUUID(); + CreateAnnotationDTO dto = new CreateAnnotationDTO(1, 0.1, 0.1, 0.8, 0.04, "#00C7B1"); + List> polygon = List.of( + List.of(0.1, 0.1), List.of(0.9, 0.11), + List.of(0.89, 0.14), List.of(0.11, 0.13)); + when(annotationRepository.save(any())).thenAnswer(inv -> inv.getArgument(0)); + + DocumentAnnotation result = annotationService.createOcrAnnotation( + docId, dto, userId, "filehash", polygon); + + assertThat(result.getPolygon()).isEqualTo(polygon); + assertThat(result.getDocumentId()).isEqualTo(docId); + verify(annotationRepository).save(any()); + verify(annotationRepository, never()).findByDocumentIdAndPageNumber(any(), any(int.class)); + } + + @Test + void createOcrAnnotation_savesWithNullPolygon_whenPolygonNotProvided() { + UUID docId = UUID.randomUUID(); + UUID userId = UUID.randomUUID(); + CreateAnnotationDTO dto = new CreateAnnotationDTO(1, 0.1, 0.1, 0.8, 0.04, "#00C7B1"); + when(annotationRepository.save(any())).thenAnswer(inv -> inv.getArgument(0)); + + DocumentAnnotation result = annotationService.createOcrAnnotation( + docId, dto, userId, "filehash", null); + + assertThat(result.getPolygon()).isNull(); + verify(annotationRepository).save(any()); + } + + @Test + void createOcrAnnotation_doesNotCheckOverlap_evenWhenOverlappingAnnotationExists() { + UUID docId = UUID.randomUUID(); + UUID userId = UUID.randomUUID(); + CreateAnnotationDTO dto = new CreateAnnotationDTO(1, 0.1, 0.1, 0.3, 0.3, "#00C7B1"); + when(annotationRepository.save(any())).thenAnswer(inv -> inv.getArgument(0)); + + annotationService.createOcrAnnotation(docId, dto, userId, "hash", null); + + verify(annotationRepository, never()).findByDocumentIdAndPageNumber(any(), any(int.class)); + } + + // ─── overlaps — partial overlap cases ──────────────────────────────────── + @Test void createAnnotation_noConflict_whenAnnotationIsAbove() { // x ranges overlap, y ranges don't — existing is ABOVE the new annotation