feat(importing): build honest precision-aware document import titles
Wires DocumentTitleFormatter into DocumentImporter.buildDocument: the title
now reads "{index} – {honest date label} – {location}", so a MONTH-precision
letter's title says "Juni 1916" instead of a fabricated "1. Juni 1916", and an
UNKNOWN-date row keeps a bare index title. buildTitle stays under 20 lines by
delegating to the shared formatter (single source of truth with the UI label).
Restores the date+location title behavior that the old MassImportService had
(it appended a full GERMAN_DATE day) but now at the honest precision.
Refs #666
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -159,7 +159,13 @@ public class DocumentImporter {
|
||||
Person sender = resolveSender(row.get("sender_person_id"), senderName);
|
||||
Set<Person> 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) {
|
||||
|
||||
@@ -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<String, String> docRow(String index, String file, String senderId, String senderName,
|
||||
|
||||
Reference in New Issue
Block a user