diff --git a/backend/src/main/java/org/raddatz/familienarchiv/importing/DocumentImporter.java b/backend/src/main/java/org/raddatz/familienarchiv/importing/DocumentImporter.java index 6be566ab..085a4ff4 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/importing/DocumentImporter.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/importing/DocumentImporter.java @@ -159,7 +159,13 @@ public class DocumentImporter { Person sender = resolveSender(row.get("sender_person_id"), senderName); Set receivers = resolveReceivers(row.get("receiver_person_ids")); - doc.setTitle(index); + LocalDate date = parseIsoDate(row.get("date_iso")); + DatePrecision precision = parsePrecision(row.get("date_precision")); + LocalDate dateEnd = parseIsoDate(row.get("date_end")); + String dateRaw = blankToNull(row.get("date_raw")); + String location = blankToNull(row.get("location")); + + doc.setTitle(buildTitle(index, date, precision, dateEnd, dateRaw, location)); doc.setStatus(status); doc.setFilePath(s3Key); doc.setContentType(contentType); @@ -171,17 +177,31 @@ public class DocumentImporter { doc.getReceivers().clear(); doc.getReceivers().addAll(receivers); doc.setReceiverText(blankToNull(receiverNames)); - doc.setDocumentDate(parseIsoDate(row.get("date_iso"))); - doc.setMetaDatePrecision(parsePrecision(row.get("date_precision"))); - doc.setMetaDateEnd(parseIsoDate(row.get("date_end"))); - doc.setMetaDateRaw(blankToNull(row.get("date_raw"))); - doc.setLocation(blankToNull(row.get("location"))); + doc.setDocumentDate(date); + doc.setMetaDatePrecision(precision); + doc.setMetaDateEnd(dateEnd); + doc.setMetaDateRaw(dateRaw); + doc.setLocation(location); doc.setSummary(blankToNull(row.get("summary"))); attachTag(doc, row.get("tags")); doc.setMetadataComplete(doc.getDocumentDate() != null || sender != null || !receivers.isEmpty()); return doc; } + // The title carries the date at the HONEST precision (never a fabricated day) via the + // shared DocumentTitleFormatter, plus the location — kept under 20 lines by delegating. + private static String buildTitle(String index, LocalDate date, DatePrecision precision, + LocalDate end, String raw, String location) { + StringBuilder title = new StringBuilder(index); + if (date != null && precision != DatePrecision.UNKNOWN) { + title.append(" – ").append(DocumentTitleFormatter.formatTitleDate(date, precision, end, raw)); + } + if (location != null && !location.isBlank()) { + title.append(" – ").append(location); + } + return title.toString(); + } + // ─── attribution routing — register-first, always retain raw ───────────────────── private Person resolveSender(String slug, String rawName) { diff --git a/backend/src/test/java/org/raddatz/familienarchiv/importing/DocumentImporterTest.java b/backend/src/test/java/org/raddatz/familienarchiv/importing/DocumentImporterTest.java index f0b2263b..99d7bd5c 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/importing/DocumentImporterTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/importing/DocumentImporterTest.java @@ -404,6 +404,50 @@ class DocumentImporterTest { d.getReceivers().isEmpty() && d.getTags().isEmpty())); } + // ─── title carries the honest date label — never a precision the data lacks ─────── + + @Test + void load_buildsTitleWithMonthLabel_whenPrecisionIsMonth(@TempDir Path tempDir) throws Exception { + ReflectionTestUtils.setField(importer, "importDir", tempDir.toString()); + when(documentService.findByOriginalFilename("W-0100")).thenReturn(Optional.empty()); + when(documentService.save(any())).thenAnswer(inv -> inv.getArgument(0)); + Path xlsx = writeDocs(tempDir, docRow("W-0100", "", "", "", "", "", + "1916-06-01", "Juni 1916", "MONTH", "")); + + importer.load(xlsx.toFile()); + + verify(documentService).save(org.mockito.ArgumentMatchers.argThat(d -> + d.getTitle().contains("Juni 1916") && !d.getTitle().contains("1. Juni"))); + } + + @Test + void load_buildsTitleWithFullDate_whenPrecisionIsDay(@TempDir Path tempDir) throws Exception { + ReflectionTestUtils.setField(importer, "importDir", tempDir.toString()); + when(documentService.findByOriginalFilename("W-0101")).thenReturn(Optional.empty()); + when(documentService.save(any())).thenAnswer(inv -> inv.getArgument(0)); + Path xlsx = writeDocs(tempDir, docRow("W-0101", "", "", "", "", "", + "1943-12-24", "24.12.1943", "DAY", "")); + + importer.load(xlsx.toFile()); + + verify(documentService).save(org.mockito.ArgumentMatchers.argThat(d -> + d.getTitle().contains("24. Dezember 1943"))); + } + + @Test + void load_buildsTitleFromIndexOnly_whenDateUnknown(@TempDir Path tempDir) throws Exception { + ReflectionTestUtils.setField(importer, "importDir", tempDir.toString()); + when(documentService.findByOriginalFilename("W-0102")).thenReturn(Optional.empty()); + when(documentService.save(any())).thenAnswer(inv -> inv.getArgument(0)); + Path xlsx = writeDocs(tempDir, docRow("W-0102", "", "", "", "", "", + "", "?", "UNKNOWN", "")); + + importer.load(xlsx.toFile()); + + verify(documentService).save(org.mockito.ArgumentMatchers.argThat(d -> + d.getTitle().equals("W-0102"))); + } + // ─── helpers ───────────────────────────────────────────────────────────────────── private Map docRow(String index, String file, String senderId, String senderName,