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:
2026-09-01 00:06:50 +02:00
co-authored by Claude Opus 5
parent 32ba772e4e
commit b7b65c64ae
41 changed files with 2462 additions and 443 deletions
@@ -1,6 +1,8 @@
import {
Controller,
Get,
Inject,
forwardRef,
Param,
Post,
Put,
@@ -14,6 +16,7 @@ import {
HttpStatus,
Res,
Query,
Request,
} from '@nestjs/common';
import type { Response } from 'express';
import { RequirePermissions } from '../auth/permissions.decorator';
@@ -31,6 +34,7 @@ import { Document } from '../database/entities/document.entity';
import { DocumentField } from '../database/entities/document-field.entity';
import { DocumentType } from '../database/entities/document-type.entity';
import { Setting } from '../database/entities/setting.entity';
import { ErechnungService } from '../erechnung/erechnung.service';
/** Setting.Tag-Schlüssel für die manuell gepflegte Steuertag-Liste */
export const STEUERTAG_SETTING_KEY = 'steuertag_ids';
@@ -51,6 +55,8 @@ export class PaperlessController {
private readonly documentTypeRepo: Repository<DocumentType>,
@InjectRepository(Setting)
private readonly settingRepo: Repository<Setting>,
@Inject(forwardRef(() => ErechnungService))
private readonly erechnungService: ErechnungService,
) {}
/** Liest die als Steuertags markierten Tag-IDs aus den Einstellungen. */
@@ -318,6 +324,20 @@ export class PaperlessController {
return retVal;
}
/**
* Wertet eine im Original-PDF eingebettete E-Rechnung aus und schlägt
* Mandant und Belegart vor. Liefert `erechnung: false`, wenn das Dokument
* keine auswertbare E-Rechnung enthält.
*/
@Get('inbox/:id/erechnung')
@RequirePermissions(Permission.VIEW_INBOX)
async getInboxErechnung(@Param('id') id: string, @Request() req: any) {
return this.erechnungService.analysiereDokument(
parseInt(id, 10),
req.user?.userId,
);
}
@Put('inbox/:id')
@RequirePermissions(Permission.VIEW_INBOX)
async putInboxDocument(@Param('id') id: string, @Body() body: any) {
@@ -474,6 +494,17 @@ export class PaperlessController {
delete oldDocument.created_date;
await this.paperlessService.updateDocument(documentId, oldDocument);
// Kennungen der E-Rechnung auf den tatsächlich gespeicherten Mandanten
// fortschreiben, damit die nächste Rechnung desselben Käufers automatisch
// zugeordnet wird. Fehler hierbei bleiben ohne Folgen für das Speichern.
if (body.erechnung === true && oldDocument.owner) {
await this.erechnungService.lerneAusDokument(
documentId,
Number(oldDocument.owner),
);
}
return { success: true };
}
@@ -12,6 +12,7 @@ import { Attachment } from '../database/entities/attachment.entity';
import { Setting } from '../database/entities/setting.entity';
import { PostprocessingModule } from '../postprocessing/postprocessing.module';
import { AuthModule } from '../auth/auth.module';
import { ErechnungModule } from '../erechnung/erechnung.module';
@Module({
imports: [
@@ -24,6 +25,7 @@ import { AuthModule } from '../auth/auth.module';
Setting,
]),
forwardRef(() => PostprocessingModule),
forwardRef(() => ErechnungModule),
AuthModule,
],
controllers: [PaperlessController],