fix: Berechtigungen der Tagesübersicht, WebDAV-Ausbau, Tests instand gesetzt
Build and Push Multi-Platform Images / build-and-push (push) Successful in 55s

Die tägliche E-Mail-Zusammenfassung zeigte Nutzern Bereiche, für die sie
keine Berechtigung haben. Zwei unabhängige Ursachen:

- Das Backend prüfte weiterhin die Altgruppe PM_Belege. Die Umbenennung
  zu PM_Buchhaltung (ca1d371) war nur im Frontend angekommen, weshalb
  der Digest "Manuell bearbeiten" und "In Agrarmonitor" anbot, während
  die Oberfläche beide Bereiche sperrte.
- Der Cron-Versand wertet die Gruppen aus user_settings aus. Diese Spalte
  wurde nur beim Aufruf der Benutzereinstellungen gefüllt; entzogene
  Berechtigungen erreichten den Digest daher unter Umständen nie.

Behoben durch Angleichen des Gruppen-Mappings und den neuen
UserIdentitySyncService, der E-Mail, Benutzername und Gruppen bei jedem
authentifizierten Request aus dem Token spiegelt – ohne den Request zu
blockieren und ohne DB-Zugriff, solange sich das Token nicht ändert. Die
doppelte Identitätspflege im UserSettingsService entfällt.

WebDAV wird nicht eingesetzt und ist entfernt; Export-Ziele bieten nur
noch FTP. Damit verschwindet das ESM-Paket webdav, an dem zwei
Jest-Suites bereits beim Parsen scheiterten.

Veraltete Tests instand gesetzt: email.controller und settings.controller
mockten weniger Abhängigkeiten, als die Klassen inzwischen haben;
postprocessing.service.spec beschrieb noch das alte Regelmodell mit
Einzelfeldern statt FilterJson und ist gegen die heutige Filter-Engine
neu geschrieben (AND/OR, verschachtelte Gruppen, Fehlerprotokollierung).

Enthält außerdem den Arbeitsstand der E-Rechnungs-Mandantenzuordnung, da
sich beide Änderungen dieselben Dateien teilen (SettingsPage, package.json).

98 Tests in 12 Suites grün, Backend- und Frontend-Build sauber.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
bjoernpoettkerandClaude Opus 5 committed 2026-09-01 00:06:50 +02:00
1 parent 32ba772e4e
commit b7b65c64ae
41 files changed
+2462 -443

No files matched your search

+20
View File
@@ -25,6 +25,23 @@ export interface DocumentRequirement {
fieldOptions?: { id: string | number; label: string }[];
}
export interface ERechnungVorschlag {
/** Ob das Dokument überhaupt eine auswertbare E-Rechnung enthält. */
erechnung: boolean;
mandantId: number | null;
belegartId: number | null;
/** Kurztext, wenn kein Vorschlag möglich war. */
hinweis: string | null;
rechnung: {
rechnungsnummer: string | null;
rechnungsdatum: string | null;
gesamtbetrag: number | null;
waehrung: string | null;
verkaeufer: string | null;
typeCode: string | null;
} | null;
}
export interface Kontonummer {
KontonummerId?: number;
CorrespondentId: number;
@@ -54,4 +71,7 @@ export const posteingangApi = {
createKontonummer: (data: { correspondentId: number; nummer: string }) =>
api.post<Kontonummer>('/api/kontonummern', data).then(r => r.data),
getErechnung: (id: number) =>
api.get<ERechnungVorschlag>(`/api/paperless/inbox/${id}/erechnung`).then(r => r.data),
};
+28 -2
View File
@@ -7,6 +7,8 @@ export interface SettingDocType {
TagNotReady: number | null;
TagReady: number | null;
FreigabeErforderlich?: boolean | null;
/** Rechnungstyp-Codes (BT-3) einer E-Rechnung, kommagetrennt (z. B. "380,384") */
ERechnungTypeCodes?: string | null;
}
export interface SettingDocField {
@@ -53,7 +55,7 @@ export interface SettingPostprocessingAction {
export interface SettingExportTarget {
Id: number;
Name: string;
Protocol: string; // 'ftp' | 'webdav'
Protocol: string; // 'ftp'
Host: string;
Port: number | null;
Username: string | null;
@@ -86,6 +88,22 @@ export interface SettingClient {
AgrarmonitorBetriebId: number | null;
}
/** Kennungsarten, über die ein Mandant in einer E-Rechnung erkannt wird. */
export type ClientIdentifierTyp = 'ustid' | 'leitwegid' | 'kaeuferkennung';
export interface SettingClientIdentifier {
Id: number;
ClientId: number;
Typ: ClientIdentifierTyp;
Wert: string;
}
export const CLIENT_IDENTIFIER_LABELS: Record<ClientIdentifierTyp, string> = {
ustid: 'USt-IdNr.',
leitwegid: 'Leitweg-ID',
kaeuferkennung: 'Käufer-Kennung',
};
export const settingsApi = {
// Dokumenttypen
getDocTypes: () => api.get<SettingDocType[]>('/api/settings/document-types').then(r => r.data),
@@ -162,6 +180,14 @@ export const settingsApi = {
updateClient: (id: number, AgrarmonitorBetriebId: number | null) =>
api.put<SettingClient>(`/api/settings/clients/${id}`, { AgrarmonitorBetriebId }).then(r => r.data),
// E-Rechnungs-Kennungen der Mandanten
getClientIdentifiers: () =>
api.get<SettingClientIdentifier[]>('/api/settings/client-identifiers').then(r => r.data),
createClientIdentifier: (data: { ClientId: number; Typ: ClientIdentifierTyp; Wert: string }) =>
api.post<SettingClientIdentifier>('/api/settings/client-identifiers', data).then(r => r.data),
deleteClientIdentifier: (id: number) =>
api.delete(`/api/settings/client-identifiers/${id}`).then(r => r.data),
// Inbox-Postprozessor (global, deprecated)
listInboxActions: () =>
api.get<InboxAction[]>('/api/settings/inbox-actions').then((r) => r.data),
@@ -191,7 +217,7 @@ export interface InboxAction {
export const INBOX_ACTION_LABELS: Record<InboxActionType, string> = {
MAIL: 'Per E-Mail senden',
EXPORT: 'Export (FTP/WebDAV)',
EXPORT: 'Export (FTP)',
PAPERLESS: 'In Paperless importieren',
};