@@ -48,6 +48,26 @@ public class AnnotationService {
|
|||||||
return annotationRepository.save(annotation);
|
return annotationRepository.save(annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public DocumentAnnotation createOcrAnnotation(UUID documentId, CreateAnnotationDTO dto,
|
||||||
|
UUID userId, String fileHash,
|
||||||
|
List<List<Double>> 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
|
@Transactional
|
||||||
public void deleteAnnotation(UUID documentId, UUID annotationId, UUID userId) {
|
public void deleteAnnotation(UUID documentId, UUID annotationId, UUID userId) {
|
||||||
DocumentAnnotation annotation = annotationRepository
|
DocumentAnnotation annotation = annotationRepository
|
||||||
|
|||||||
@@ -260,6 +260,55 @@ class AnnotationServiceTest {
|
|||||||
verify(annotationRepository).save(any());
|
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<List<Double>> 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
|
@Test
|
||||||
void createAnnotation_noConflict_whenAnnotationIsAbove() {
|
void createAnnotation_noConflict_whenAnnotationIsAbove() {
|
||||||
// x ranges overlap, y ranges don't — existing is ABOVE the new annotation
|
// x ranges overlap, y ranges don't — existing is ABOVE the new annotation
|
||||||
|
|||||||
Reference in New Issue
Block a user