fix: return 409 on duplicate kontonummer, show server error in snackbar, block save when sub-account suffix is empty

This commit is contained in:
Matthias Hochmeister
2026-03-30 11:03:53 +02:00
parent 2e736f7995
commit b7015ace84
3 changed files with 9 additions and 5 deletions

View File

@@ -167,9 +167,10 @@ class BuchhaltungController {
try { try {
const data = await buchhaltungService.createKonto(req.body, req.user!.id); const data = await buchhaltungService.createKonto(req.body, req.user!.id);
res.status(201).json({ success: true, data }); res.status(201).json({ success: true, data });
} catch (error) { } catch (error: any) {
logger.error('BuchhaltungController.createKonto', { error }); logger.error('BuchhaltungController.createKonto', { error });
res.status(500).json({ success: false, message: 'Konto konnte nicht erstellt werden' }); const status = error.statusCode || 500;
res.status(status).json({ success: false, message: error.message || 'Konto konnte nicht erstellt werden' });
} }
} }

View File

@@ -375,8 +375,11 @@ async function createKonto(
[data.haushaltsjahr_id, data.konto_typ_id || null, data.kontonummer, data.bezeichnung, data.parent_id || null, data.budget_gwg || 0, data.budget_anlagen || 0, data.budget_instandhaltung || 0, data.notizen || null, userId] [data.haushaltsjahr_id, data.konto_typ_id || null, data.kontonummer, data.bezeichnung, data.parent_id || null, data.budget_gwg || 0, data.budget_anlagen || 0, data.budget_instandhaltung || 0, data.notizen || null, userId]
); );
return result.rows[0]; return result.rows[0];
} catch (error) { } catch (error: any) {
logger.error('BuchhaltungService.createKonto failed', { error }); logger.error('BuchhaltungService.createKonto failed', { error });
if (error.code === '23505' && error.constraint === 'buchhaltung_konten_haushaltsjahr_id_kontonummer_key') {
throw Object.assign(new Error(`Kontonummer "${data.kontonummer}" existiert bereits in diesem Haushaltsjahr`), { statusCode: 409 });
}
throw new Error('Konto konnte nicht erstellt werden'); throw new Error('Konto konnte nicht erstellt werden');
} }
} }

View File

@@ -268,7 +268,7 @@ function KontoDialog({
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={onClose}>Abbrechen</Button> <Button onClick={onClose}>Abbrechen</Button>
<Button variant="contained" onClick={() => onSave(form)}>Speichern</Button> <Button variant="contained" onClick={() => onSave(form)} disabled={!form.bezeichnung || !form.kontonummer || (!!parentPrefix && kontonummerSuffix === '')}>Speichern</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
); );
@@ -992,7 +992,7 @@ function KontenTab({ haushaltsjahre, selectedJahrId, onJahrChange }: {
const createKontoMut = useMutation({ const createKontoMut = useMutation({
mutationFn: buchhaltungApi.createKonto, mutationFn: buchhaltungApi.createKonto,
onSuccess: () => { qc.invalidateQueries({ queryKey: ['buchhaltung-konten'] }); qc.invalidateQueries({ queryKey: ['kontenTree'] }); setKontoDialog({ open: false }); showSuccess('Konto erstellt'); }, onSuccess: () => { qc.invalidateQueries({ queryKey: ['buchhaltung-konten'] }); qc.invalidateQueries({ queryKey: ['kontenTree'] }); setKontoDialog({ open: false }); showSuccess('Konto erstellt'); },
onError: () => showError('Konto konnte nicht erstellt werden'), onError: (err: any) => showError(err?.response?.data?.message || 'Konto konnte nicht erstellt werden'),
}); });
const updateKontoMut = useMutation({ const updateKontoMut = useMutation({
mutationFn: ({ id, data }: { id: number; data: Partial<KontoFormData> }) => buchhaltungApi.updateKonto(id, data), mutationFn: ({ id, data }: { id: number; data: Partial<KontoFormData> }) => buchhaltungApi.updateKonto(id, data),