fix: Berechtigungen der Tagesübersicht, WebDAV-Ausbau, Tests instand gesetzt
Build and Push Multi-Platform Images / build-and-push (push) Successful in 55s
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:
1 parent
32ba772e4e
commit
b7b65c64ae
41 files changed
+2462
-443
No files matched your search
@@ -15,6 +15,7 @@ import {
|
||||
Kontonummer,
|
||||
Document,
|
||||
UserClient,
|
||||
ClientIdentifier,
|
||||
Email,
|
||||
Attachment,
|
||||
Content,
|
||||
@@ -47,6 +48,7 @@ export const entities = [
|
||||
Kontonummer,
|
||||
Document,
|
||||
UserClient,
|
||||
ClientIdentifier,
|
||||
Email,
|
||||
Attachment,
|
||||
Content,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Entity, PrimaryGeneratedColumn, Column, Index } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Kennungsarten, über die ein Mandant in einer E-Rechnung erkannt werden kann.
|
||||
* Bewusst nur "starke" Kennungen – Name und E-Mail sind zu unscharf, um sie
|
||||
* dauerhaft festzuschreiben.
|
||||
*/
|
||||
export type ClientIdentifierTyp = 'ustid' | 'leitwegid' | 'kaeuferkennung';
|
||||
|
||||
export const CLIENT_IDENTIFIER_TYPEN: ClientIdentifierTyp[] = [
|
||||
'ustid',
|
||||
'leitwegid',
|
||||
'kaeuferkennung',
|
||||
];
|
||||
|
||||
/** Zuordnung einer Käufer-Kennung aus dem E-Rechnungs-XML zu einem Mandanten. */
|
||||
@Entity('ClientIdentifiers')
|
||||
@Index('IX_ClientIdentifiers_TypWert', ['Typ', 'Wert'], { unique: true })
|
||||
export class ClientIdentifier {
|
||||
@PrimaryGeneratedColumn()
|
||||
Id!: number;
|
||||
|
||||
@Index('IX_ClientIdentifiers_ClientId')
|
||||
@Column({ type: 'int' })
|
||||
ClientId!: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 20 })
|
||||
Typ!: ClientIdentifierTyp;
|
||||
|
||||
/** Normalisiert gespeichert: Großschreibung, ohne Leer- und Trennzeichen. */
|
||||
@Column({ type: 'varchar', length: 100 })
|
||||
Wert!: string;
|
||||
}
|
||||
@@ -19,4 +19,12 @@ export class DocumentType {
|
||||
|
||||
@Column({ type: 'tinyint', width: 1, nullable: true, default: null })
|
||||
FreigabeErforderlich!: boolean | null;
|
||||
|
||||
/**
|
||||
* Rechnungstyp-Codes (BT-3) einer E-Rechnung, die auf diese Belegart
|
||||
* abgebildet werden – kommagetrennt, z. B. "380,384" für Rechnung, "381"
|
||||
* für Gutschrift. Leer = diese Belegart wird nie vorgeschlagen.
|
||||
*/
|
||||
@Column({ type: 'varchar', length: 100, nullable: true, default: null })
|
||||
ERechnungTypeCodes!: string | null;
|
||||
}
|
||||
@@ -9,7 +9,7 @@ export class ExportTarget {
|
||||
Name!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20 })
|
||||
Protocol!: string; // 'ftp' | 'webdav'
|
||||
Protocol!: string; // 'ftp'
|
||||
|
||||
@Column({ type: 'varchar', length: 255 })
|
||||
Host!: string;
|
||||
|
||||
@@ -10,6 +10,7 @@ export { Setting } from './setting.entity';
|
||||
export { Kontonummer } from './kontonummer.entity';
|
||||
export { Document } from './document.entity';
|
||||
export { UserClient } from './user-client.entity';
|
||||
export { ClientIdentifier } from './client-identifier.entity';
|
||||
export { Email } from './email.entity';
|
||||
export { Attachment } from './attachment.entity';
|
||||
export { Content } from './content.entity';
|
||||
|
||||
@@ -10,7 +10,7 @@ export class PostprocessingAction {
|
||||
|
||||
@Column({ type: 'int' })
|
||||
ActionType!: number;
|
||||
// 1 = Export (FTP/WebDAV)
|
||||
// 1 = Export (FTP)
|
||||
// 2 = Mail
|
||||
// 3 = Tag setzen/entfernen
|
||||
// 4 = Custom Field setzen
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Grundlage für den Mandanten-Vorschlag aus E-Rechnungen:
|
||||
*
|
||||
* - `ClientIdentifiers` ordnet Käufer-Kennungen aus dem Rechnungs-XML
|
||||
* (USt-IdNr., Leitweg-ID, Käufer-Kennung) einem Mandanten zu. Der eindeutige
|
||||
* Index über (Typ, Wert) verhindert, dass eine Kennung auf mehrere Mandanten
|
||||
* zeigt.
|
||||
* - `DocumentTypes.ERechnungTypeCodes` bildet den Rechnungstyp (BT-3) auf eine
|
||||
* Belegart ab, z. B. "380,384" für Rechnung und "381" für Gutschrift.
|
||||
*/
|
||||
export class ERechnungMandantenzuordnung1787000000000 implements MigrationInterface {
|
||||
name = 'ERechnungMandantenzuordnung1787000000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`ClientIdentifiers\` (
|
||||
\`Id\` int NOT NULL AUTO_INCREMENT,
|
||||
\`ClientId\` int NOT NULL,
|
||||
\`Typ\` varchar(20) NOT NULL,
|
||||
\`Wert\` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (\`Id\`),
|
||||
UNIQUE INDEX \`IX_ClientIdentifiers_TypWert\` (\`Typ\`, \`Wert\`),
|
||||
INDEX \`IX_ClientIdentifiers_ClientId\` (\`ClientId\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE \`DocumentTypes\`
|
||||
ADD \`ERechnungTypeCodes\` varchar(100) NULL DEFAULT NULL
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE \`DocumentTypes\` DROP COLUMN \`ERechnungTypeCodes\``,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE \`ClientIdentifiers\``);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user