feat(#68): fall back to filename as title when createDocument gets no title

When a document is created without an explicit title (null or blank),
the service now derives the title from the uploaded filename using the
same titleFromFilename() logic already used by storeDocument — stripping
the extension for plain names and formatting structured names as
"Firstname Lastname (DD.MM.YYYY)".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-26 22:51:24 +01:00
parent 065dd8fabd
commit d6f4ea05d9
2 changed files with 61 additions and 1 deletions

View File

@@ -108,9 +108,13 @@ public class DocumentService {
|| (dto.getReceiverIds() != null && !dto.getReceiverIds().isEmpty());
}
String titleToUse = (dto.getTitle() != null && !dto.getTitle().isBlank())
? dto.getTitle()
: titleFromFilename(filename);
Document doc = Document.builder()
.originalFilename(filename)
.title(dto.getTitle())
.title(titleToUse)
.documentDate(dto.getDocumentDate())
.location(dto.getLocation())
.documentLocation(dto.getDocumentLocation())

View File

@@ -467,6 +467,62 @@ class DocumentServiceTest {
assertThat(captor.getValue().getSender()).isNull();
}
// ─── createDocument title fallback ────────────────────────────────────────
@Test
void createDocument_usesTitleFromFilename_whenDtoTitleIsNull() throws Exception {
DocumentUpdateDTO dto = new DocumentUpdateDTO();
// dto.title is null
MockMultipartFile file = new MockMultipartFile("file", "Brief_1965.pdf", "application/pdf", new byte[]{1});
Document saved = Document.builder().id(UUID.randomUUID()).title("Brief_1965")
.originalFilename("Brief_1965.pdf").status(DocumentStatus.PLACEHOLDER).build();
when(documentRepository.save(any())).thenReturn(saved);
when(documentRepository.findById(any())).thenReturn(Optional.of(saved));
when(fileService.uploadFile(any(), any())).thenReturn(new FileService.UploadResult("path", "hash"));
ArgumentCaptor<Document> captor = ArgumentCaptor.forClass(Document.class);
documentService.createDocument(dto, file);
verify(documentRepository, atLeastOnce()).save(captor.capture());
assertThat(captor.getAllValues().get(0).getTitle()).isEqualTo("Brief_1965");
}
@Test
void createDocument_usesTitleFromFilename_whenDtoTitleIsBlank() throws Exception {
DocumentUpdateDTO dto = new DocumentUpdateDTO();
dto.setTitle(" ");
MockMultipartFile file = new MockMultipartFile("file", "Rechnung_1980.pdf", "application/pdf", new byte[]{1});
Document saved = Document.builder().id(UUID.randomUUID()).title("Rechnung_1980")
.originalFilename("Rechnung_1980.pdf").status(DocumentStatus.PLACEHOLDER).build();
when(documentRepository.save(any())).thenReturn(saved);
when(documentRepository.findById(any())).thenReturn(Optional.of(saved));
when(fileService.uploadFile(any(), any())).thenReturn(new FileService.UploadResult("path", "hash"));
ArgumentCaptor<Document> captor = ArgumentCaptor.forClass(Document.class);
documentService.createDocument(dto, file);
verify(documentRepository, atLeastOnce()).save(captor.capture());
assertThat(captor.getAllValues().get(0).getTitle()).isEqualTo("Rechnung_1980");
}
@Test
void createDocument_keepsDtoTitle_whenProvided() throws Exception {
DocumentUpdateDTO dto = new DocumentUpdateDTO();
dto.setTitle("Mein Titel");
MockMultipartFile file = new MockMultipartFile("file", "scan.pdf", "application/pdf", new byte[]{1});
Document saved = Document.builder().id(UUID.randomUUID()).title("Mein Titel")
.originalFilename("scan.pdf").status(DocumentStatus.PLACEHOLDER).build();
when(documentRepository.save(any())).thenReturn(saved);
when(documentRepository.findById(any())).thenReturn(Optional.of(saved));
when(fileService.uploadFile(any(), any())).thenReturn(new FileService.UploadResult("path", "hash"));
ArgumentCaptor<Document> captor = ArgumentCaptor.forClass(Document.class);
documentService.createDocument(dto, file);
verify(documentRepository, atLeastOnce()).save(captor.capture());
assertThat(captor.getAllValues().get(0).getTitle()).isEqualTo("Mein Titel");
}
// ─── createDocument metadataComplete ─────────────────────────────────────
@Test