feat(handelsware-datev): API, Kontenliste mit Zeilenschutz und DATEV-Export
- Prisma-Modelle HandelswareDatevConfig und HandelswareKonto mit Zeilenschutz (Migration 20261002130000) - XLSX lesen (B1 Kopf, A/B ab Zeile 2, Zahl oder deutscher Text), Konten zuordnen, TXT erzeugen - neue Konten werden nur beim Export in einer mandantengebundenen Transaktion gespeichert (409 bei geaenderter Liste) - Konten-CSV Import (alles ersetzen) und Export mit Schutz vor Formeleinschleusung - Einstellungen nur fuer Administratoren, statische Routen vor accounts/:id Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
-- 261002-fm5 — Finanzbuchhaltung: Modul "Handelsware" (handelsware-datev).
|
||||
--
|
||||
-- Zweck: zwei neue Tabellen. `HandelswareDatevConfig` traegt die Einstellungen
|
||||
-- des Mandanten (Standard-Erloeskonto fuer neue Konten, Startwert fuer die
|
||||
-- Gegenkonto-Vergabe bei leerer Kontenliste) — eine Zeile je Mandant
|
||||
-- (Singleton, Vorbild `DkvModuleConfig`/`KantineDatevConfig`). Beide Zahlen
|
||||
-- haben ABSICHTLICH keinen Standardwert: solange sie leer sind, sperrt das
|
||||
-- Modul die Verarbeitung. `HandelswareKonto` ist die Kontenliste (Produktname
|
||||
-- -> Gegenkonto, Erloeskonto) — mehrere Zeilen je Mandant, der Name ist je
|
||||
-- Mandant eindeutig, das Gegenkonto bewusst nicht (mehrere Produkte duerfen
|
||||
-- auf dasselbe Gegenkonto laufen).
|
||||
--
|
||||
-- Von Hand geschrieben (Vorbild 20260923140000_proxmox_server), von Hand
|
||||
-- gepflegter Kopfkommentar Pflicht bei jeder RLS-Migration in diesem Projekt.
|
||||
--
|
||||
-- Zeilenschutz (Pflicht — sonst schlaegt rls-coverage.spec.ts fehl): beide
|
||||
-- Tabellen tragen `tenantId` und `tenant_isolation_policy` OHNE
|
||||
-- Benutzerdimension (`USING ("tenantId" = current_tenant_id())`, Form aus
|
||||
-- `DkvModuleConfig`) — Verwaltungsdaten des Mandanten, nicht persoenliche Daten
|
||||
-- eines Benutzers. Keine `system_read_policy`: es gibt keinen Hintergrunddienst,
|
||||
-- der diese Tabellen ueber alle Mandanten liest.
|
||||
--
|
||||
-- Rechte fuer die Anwendungsrolle tessera_app kommen automatisch ueber
|
||||
-- ALTER DEFAULT PRIVILEGES aus 20260909130000_rls_app_role — hier nichts zu
|
||||
-- tun.
|
||||
--
|
||||
-- WICHTIG: wie alle bisherigen RLS-Migrationen wirken diese Regeln erst,
|
||||
-- wenn die Anwendung als Rolle ohne Umgehungsrecht verbindet (Schalter
|
||||
-- heute AUS, siehe docs/mandantentrennung-datenbankrolle.md).
|
||||
|
||||
-- 1) HandelswareDatevConfig
|
||||
CREATE TABLE "HandelswareDatevConfig" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"erloeskonto" INTEGER,
|
||||
"startGegenkonto" INTEGER,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "HandelswareDatevConfig_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "HandelswareDatevConfig_tenantId_key" ON "HandelswareDatevConfig"("tenantId");
|
||||
CREATE INDEX "HandelswareDatevConfig_tenantId_idx" ON "HandelswareDatevConfig"("tenantId");
|
||||
|
||||
ALTER TABLE "HandelswareDatevConfig" ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "HandelswareDatevConfig" FORCE ROW LEVEL SECURITY;
|
||||
CREATE POLICY tenant_isolation_policy ON "HandelswareDatevConfig"
|
||||
USING ("tenantId" = current_tenant_id());
|
||||
|
||||
-- 2) HandelswareKonto
|
||||
CREATE TABLE "HandelswareKonto" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"gegenkonto" INTEGER NOT NULL,
|
||||
"erloeskonto" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "HandelswareKonto_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "HandelswareKonto_tenantId_name_key" ON "HandelswareKonto"("tenantId", "name");
|
||||
CREATE INDEX "HandelswareKonto_tenantId_idx" ON "HandelswareKonto"("tenantId");
|
||||
|
||||
ALTER TABLE "HandelswareKonto" ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "HandelswareKonto" FORCE ROW LEVEL SECURITY;
|
||||
CREATE POLICY tenant_isolation_policy ON "HandelswareKonto"
|
||||
USING ("tenantId" = current_tenant_id());
|
||||
@@ -361,6 +361,39 @@ model KantineDatevConfig {
|
||||
@@index([tenantId])
|
||||
}
|
||||
|
||||
// quick-261002-fm5: Handelsware (Modul handelsware-datev). Einstellungen je
|
||||
// Mandant (Singleton wie KantineDatevConfig): Standard-Erloeskonto fuer neue
|
||||
// Konten und Startwert fuer die Gegenkonto-Vergabe bei leerer Kontenliste.
|
||||
// Beide Zahlen haben bewusst KEINEN Standardwert — der Administrator hinterlegt
|
||||
// sie einmalig, bis dahin ist die Verarbeitung gesperrt.
|
||||
model HandelswareDatevConfig {
|
||||
id String @id @default(uuid())
|
||||
tenantId String @unique
|
||||
erloeskonto Int?
|
||||
startGegenkonto Int?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([tenantId])
|
||||
}
|
||||
|
||||
// quick-261002-fm5: Kontenliste der Handelsware (Produktname -> Gegenkonto,
|
||||
// Erloeskonto). Der Name ist je Mandant eindeutig; das Gegenkonto bewusst
|
||||
// NICHT (mehrere Produkte duerfen auf dasselbe Gegenkonto laufen, wie in der
|
||||
// Desktop-Vorlage). Keine Relation zu Tenant, Zeilenschutz nach ProxmoxServer.
|
||||
model HandelswareKonto {
|
||||
id String @id @default(uuid())
|
||||
tenantId String
|
||||
name String
|
||||
gegenkonto Int
|
||||
erloeskonto Int
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([tenantId, name])
|
||||
@@index([tenantId])
|
||||
}
|
||||
|
||||
// Phase 14, Plan 03 (INGEST-05, CONFIG-02, D-06/D-07) — per-tenant portal-
|
||||
// alert mailbox config, mirroring DkvModuleConfig's shape/pattern exactly
|
||||
// (own tenantId @unique row, own encrypted creds — D-03: each module keeps
|
||||
|
||||
Reference in New Issue
Block a user