fix(upload): structured error codes for quick-upload, fix duplicate filename crash
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled

- Switch errors from plain strings to { filename, code } objects so the
  frontend can show translated messages instead of raw exception text
- Add UNSUPPORTED_FILE_TYPE error code end-to-end (Java enum → errors.ts
  → de/en/es messages)
- Fix IncorrectResultSizeDataAccessException when a filename exists more
  than once in the DB: use findFirstByOriginalFilename instead of
  findByOriginalFilename in storeDocument()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-26 10:38:30 +01:00
parent 6a663cefe6
commit 963807ff05
11 changed files with 28 additions and 11 deletions

View File

@@ -7,6 +7,7 @@
"error_document_no_file": "Diesem Dokument ist noch keine Datei zugeordnet.",
"error_file_not_found": "Die Datei konnte im Speicher nicht gefunden werden.",
"error_file_upload_failed": "Die Datei konnte nicht hochgeladen werden.",
"error_unsupported_file_type": "Dieses Dateiformat wird nicht unterstützt.",
"error_user_not_found": "Der Benutzer wurde nicht gefunden.",
"error_import_already_running": "Ein Import läuft bereits. Bitte warten Sie, bis dieser abgeschlossen ist.",
"error_unauthorized": "Sie sind nicht angemeldet.",

View File

@@ -7,6 +7,7 @@
"error_document_no_file": "No file is associated with this document.",
"error_file_not_found": "The file could not be found in storage.",
"error_file_upload_failed": "The file could not be uploaded.",
"error_unsupported_file_type": "This file format is not supported.",
"error_user_not_found": "User not found.",
"error_import_already_running": "An import is already running. Please wait for it to finish.",
"error_unauthorized": "You are not logged in.",

View File

@@ -7,6 +7,7 @@
"error_document_no_file": "No hay ningún archivo asociado a este documento.",
"error_file_not_found": "El archivo no pudo encontrarse en el almacenamiento.",
"error_file_upload_failed": "No se pudo subir el archivo.",
"error_unsupported_file_type": "Este formato de archivo no está admitido.",
"error_user_not_found": "Usuario no encontrado.",
"error_import_already_running": "Ya hay una importación en curso. Por favor, espere a que finalice.",
"error_unauthorized": "No ha iniciado sesión.",

View File

@@ -9,6 +9,7 @@ export type ErrorCode =
| 'DOCUMENT_NO_FILE'
| 'FILE_NOT_FOUND'
| 'FILE_UPLOAD_FAILED'
| 'UNSUPPORTED_FILE_TYPE'
| 'USER_NOT_FOUND'
| 'EMAIL_ALREADY_IN_USE'
| 'WRONG_CURRENT_PASSWORD'
@@ -54,6 +55,8 @@ export function getErrorMessage(code: ErrorCode | string | undefined): string {
return m.error_file_not_found();
case 'FILE_UPLOAD_FAILED':
return m.error_file_upload_failed();
case 'UNSUPPORTED_FILE_TYPE':
return m.error_unsupported_file_type();
case 'USER_NOT_FOUND':
return m.error_user_not_found();
case 'EMAIL_ALREADY_IN_USE':

View File

@@ -7,6 +7,7 @@ import { untrack } from 'svelte';
import { SvelteURLSearchParams } from 'svelte/reactivity';
import { m } from '$lib/paraglide/messages.js';
import { formatDate } from '$lib/utils/date';
import { getErrorMessage } from '$lib/errors';
let { data } = $props();
@@ -101,7 +102,10 @@ async function uploadFiles(files: File[]) {
messages.push({ text: m.upload_success({ count: result.created.length }), isError: false });
}
for (const err of result.errors ?? []) {
messages.push({ text: err, isError: true });
messages.push({
text: `${err.filename}: ${getErrorMessage(err.code)}`,
isError: true
});
}
await invalidateAll();
} else {