fix(import): address PR review concerns
- remove duplicate List import in AdminControllerTest - derive skipped() from skippedFiles.size() — drop redundant int field - use machine codes for SkippedFile.reason (INVALID_PDF_SIGNATURE, FILE_READ_ERROR) - map reason codes to i18n strings in ImportStatusCard (de/en/es) - replace raw amber Tailwind classes with warning semantic token - fix <summary> accessibility: replace list-none with rotating chevron SVG - replace <p> with <span> inside <summary> (phrasing content rule) - extract setupOneValidOneFakeImport() helper — remove 3x copy-paste - add lenient mock to short-file test for defensive coverage - add IOException path test for isPdfMagicBytes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package org.raddatz.familienarchiv.importing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
@@ -56,11 +57,14 @@ public class MassImportService {
|
||||
|
||||
public record SkippedFile(String filename, String reason) {}
|
||||
|
||||
public record ImportStatus(State state, String statusCode, @JsonIgnore String message, int processed, int skipped, List<SkippedFile> skippedFiles, LocalDateTime startedAt) {}
|
||||
public record ImportStatus(State state, String statusCode, @JsonIgnore String message, int processed, List<SkippedFile> skippedFiles, LocalDateTime startedAt) {
|
||||
@JsonProperty("skipped")
|
||||
public int skipped() { return skippedFiles.size(); }
|
||||
}
|
||||
|
||||
record ProcessResult(int processed, int skipped, List<SkippedFile> skippedFiles) {}
|
||||
record ProcessResult(int processed, List<SkippedFile> skippedFiles) {}
|
||||
|
||||
private volatile ImportStatus currentStatus = new ImportStatus(State.IDLE, "IMPORT_IDLE", "Kein Import gestartet.", 0, 0, List.of(), null);
|
||||
private volatile ImportStatus currentStatus = new ImportStatus(State.IDLE, "IMPORT_IDLE", "Kein Import gestartet.", 0, List.of(), null);
|
||||
|
||||
public ImportStatus getStatus() {
|
||||
return currentStatus;
|
||||
@@ -122,22 +126,22 @@ public class MassImportService {
|
||||
if (currentStatus.state() == State.RUNNING) {
|
||||
throw DomainException.conflict(ErrorCode.IMPORT_ALREADY_RUNNING, "A mass import is already in progress");
|
||||
}
|
||||
currentStatus = new ImportStatus(State.RUNNING, "IMPORT_RUNNING", "Import läuft...", 0, 0, List.of(), LocalDateTime.now());
|
||||
currentStatus = new ImportStatus(State.RUNNING, "IMPORT_RUNNING", "Import läuft...", 0, List.of(), LocalDateTime.now());
|
||||
try {
|
||||
File spreadsheet = findSpreadsheetFile();
|
||||
log.info("Starte Massenimport aus: {}", spreadsheet.getAbsolutePath());
|
||||
ProcessResult result = processRows(readSpreadsheet(spreadsheet));
|
||||
currentStatus = new ImportStatus(State.DONE, "IMPORT_DONE",
|
||||
"Import abgeschlossen. " + result.processed() + " Dokumente verarbeitet.",
|
||||
result.processed(), result.skipped(), result.skippedFiles(), currentStatus.startedAt());
|
||||
result.processed(), result.skippedFiles(), currentStatus.startedAt());
|
||||
} catch (NoSpreadsheetException e) {
|
||||
log.error("Massenimport fehlgeschlagen: keine Tabellendatei", e);
|
||||
currentStatus = new ImportStatus(State.FAILED, "IMPORT_FAILED_NO_SPREADSHEET",
|
||||
"Fehler: " + e.getMessage(), 0, 0, List.of(), currentStatus.startedAt());
|
||||
"Fehler: " + e.getMessage(), 0, List.of(), currentStatus.startedAt());
|
||||
} catch (Exception e) {
|
||||
log.error("Massenimport fehlgeschlagen", e);
|
||||
currentStatus = new ImportStatus(State.FAILED, "IMPORT_FAILED_INTERNAL",
|
||||
"Fehler: " + e.getMessage(), 0, 0, List.of(), currentStatus.startedAt());
|
||||
"Fehler: " + e.getMessage(), 0, List.of(), currentStatus.startedAt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,12 +282,12 @@ public class MassImportService {
|
||||
try {
|
||||
if (!isPdfMagicBytes(fileOnDisk.get())) {
|
||||
log.warn("Überspringe {}: Datei beginnt nicht mit %PDF-Signatur", filename);
|
||||
skippedFiles.add(new SkippedFile(filename, "Keine gültige PDF-Signatur"));
|
||||
skippedFiles.add(new SkippedFile(filename, "INVALID_PDF_SIGNATURE"));
|
||||
continue;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Fehler beim Prüfen der Magic-Bytes für {}", filename, e);
|
||||
skippedFiles.add(new SkippedFile(filename, "Fehler beim Lesen der Datei"));
|
||||
skippedFiles.add(new SkippedFile(filename, "FILE_READ_ERROR"));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -293,7 +297,7 @@ public class MassImportService {
|
||||
processed++;
|
||||
}
|
||||
}
|
||||
return new ProcessResult(processed, skippedFiles.size(), skippedFiles);
|
||||
return new ProcessResult(processed, skippedFiles);
|
||||
}
|
||||
|
||||
private boolean isPdfMagicBytes(File file) throws IOException {
|
||||
|
||||
Reference in New Issue
Block a user