Steuerkram/docs/datenbankstruktur.md
2026-04-12 19:55:51 +02:00

11 KiB
Raw Blame History

Datenbankstruktur

MariaDB 11, Engine InnoDB, Zeichensatz utf8mb4_unicode_ci. Das Schema wird durch nummerierte Migrations-Dateien in migrations/ verwaltet und beim Container-Start automatisch eingespielt.


Übersicht

Tabelle Zweck
fiscal_years Geschäftsjahre
accounts Kontenrahmen SKR03
company_settings Firmendaten und Einstellungen (Singleton)
customers Kundenstammdaten
belege Belegdokumente
bookings Buchungszeilen (EÜR-Journal)
invoices Ausgangsrechnungen
invoice_lines Rechnungspositionen
users Benutzerkonten
ustva_submissions UStVA-Einreichungen
audit_log GoBD-Audit-Log
schema_migrations Protokoll angewendeter Migrationen

Tabellen im Detail

fiscal_years – Geschäftsjahre

Spalte Typ Beschreibung
id INT UNSIGNED PK
year SMALLINT UNSIGNED UNIQUE Jahreszahl (z.B. 2026)
start_date DATE Beginn des Geschäftsjahres
end_date DATE Ende des Geschäftsjahres
locked TINYINT(1) 1 = Jahr abgeschlossen, keine neuen Buchungen möglich
created_at DATETIME

accounts – Kontenrahmen SKR03

Spalte Typ Beschreibung
id INT UNSIGNED PK
kontonummer VARCHAR(10) UNIQUE DATEV-Kontonummer
bezeichnung VARCHAR(255) Kontobezeichnung
kontenart ENUM Betriebseinnahme, Betriebsausgabe, Anlagevermögen, Zahlungskonto, Verbindlichkeit, Privat
beschreibung TEXT Erläuterungstext
steuercode VARCHAR(20) USt19, USt7, VSt19, VSt7 oder leer
ustva_kz VARCHAR(10) ELSTER-Kennzahl (z.B. 81, 35)
euer_zeile VARCHAR(5) Zeilennummer Anlage EÜR (z.B. 14, 51)
is_system TINYINT(1) 1 = SKR03-Standardkonto
aktiv TINYINT(1) 0 = deaktiviert
created_at / updated_at DATETIME

company_settings – Firmendaten (Singleton, id=1)

Spalte Typ Beschreibung
id INT UNSIGNED PK Immer 1
firma VARCHAR(255) Firmenname
inhaber VARCHAR(255) Inhabername
strasse, plz, ort VARCHAR Adresse
telefon, email, website VARCHAR Kontaktdaten
ust_id VARCHAR(20) Umsatzsteuer-ID (DE...)
steuernummer VARCHAR(30) Steuernummer beim Finanzamt
finanzamt VARCHAR(255) Zuständiges Finanzamt
iban, bic, bank_name VARCHAR Bankverbindung
logo_path VARCHAR(500) Pfad zum Logo-PNG
ustva_steuernummer VARCHAR(20) ELSTER-Format: FFFBBBBBBUUUUP
ustva_bundesland VARCHAR(2) Bundesland-Kürzel (z.B. BY)
invoice_nr_prefix VARCHAR(10) Präfix Rechnungsnummer (Standard: AR)
invoice_nr_next INT UNSIGNED Nächste Rechnungsnummer
invoice_nr_year SMALLINT UNSIGNED Jahresstand des Rechnungszählers
beleg_nr_prefix VARCHAR(10) Präfix Belegnummer (Standard: BLG)
beleg_nr_next INT UNSIGNED Nächste Belegnummer
anlage_nr_prefix VARCHAR(10) Präfix Anlagen-Nummer (Standard: ANL)
anlage_nr_next INT UNSIGNED Nächste Anlagen-Nummer
payment_days_default INT UNSIGNED Standard-Zahlungsziel in Tagen
ki_vorschlag_aktiv TINYINT(1) KI-Kontierungsvorschlag aktiviert
nextcloud_url VARCHAR(500) WebDAV-URL der Nextcloud-Instanz
nextcloud_user VARCHAR(255) Nextcloud-Benutzername
nextcloud_pass VARCHAR(500) Nextcloud-Passwort / App-Passwort
nextcloud_folder VARCHAR(500) Import-Quellordner (Standard: /Belege/Import)
nextcloud_done VARCHAR(500) Zielordner nach erfolgreichem Import
updated_at DATETIME

customers – Kundenstammdaten

Spalte Typ Beschreibung
id INT UNSIGNED PK
kundennummer VARCHAR(20) UNIQUE
firma VARCHAR(255) Firmenname (optional)
anrede, vorname, nachname VARCHAR Ansprechpartner
strasse, plz, ort, land VARCHAR Adresse
email, telefon VARCHAR Kontakt
ust_id VARCHAR(20) USt-ID des Kunden (B2B)
steuernummer VARCHAR(30)
payment_days INT UNSIGNED Zahlungsziel in Tagen
notes TEXT Interne Notizen
archived TINYINT(1) 1 = archiviert
created_at / updated_at DATETIME

belege – Belegdokumente

Spalte Typ Beschreibung
id INT UNSIGNED PK
beleg_nr VARCHAR(30) UNIQUE Automatisch vergeben (z.B. BLG-2026-0001)
filename VARCHAR(500) Originaldateiname
storage_path VARCHAR(500) Pfad unter public/static/uploads/
mime_type VARCHAR(100) MIME-Typ der Datei
file_hash VARCHAR(64) SHA-256 für GoBD-Integritätsprüfung
beleg_datum DATE Datum auf dem Dokument
rechnungs_nr VARCHAR(100) Rechnungsnummer des Lieferanten
betrag_brutto DECIMAL(12,2) Bruttobetrag laut Dokument
belegtyp ENUM Eingangsrechnung, Ausgangsrechnung, Quittung, Kontoauszug, Sonstiges
notes TEXT Interne Notizen
bewirtungsgrund TEXT Anlass der Bewirtung (§ 4 Abs. 5 Nr. 2 EStG)
teilnehmerliste TEXT Teilnehmer der Bewirtung
eigenanteil_30 TINYINT(1) 1 = 30%-Eigenanteil beim Buchen markiert
ki_vorschlag JSON KI-Kontierungsvorschlag
ki_vorschlag_at TIMESTAMP Zeitpunkt der KI-Analyse
beleg_text MEDIUMTEXT Extrahierter OCR-Text
locked TINYINT(1) GoBD: mit Geschäftsjahr gesperrt
fiscal_year_id INT UNSIGNED FK → fiscal_years.id
created_at / updated_at DATETIME

bookings – Buchungszeilen (EÜR-Journal)

GoBD-gesichert: MariaDB-Trigger verhindern Änderungen und Löschungen gesperrter Buchungen.

Spalte Typ Beschreibung
id INT UNSIGNED PK
buchungs_nr VARCHAR(30) UNIQUE Automatisch vergeben
beleg_id INT UNSIGNED FK → belege.id
asset_id INT UNSIGNED FK → assets.id (nur bei Anlagevermögen-Buchungen)
buchungs_datum DATE
buchungstyp ENUM Einnahme, Ausgabe
kategorie_konto_id INT UNSIGNED FK → accounts.id (Was?)
zahlungskonto_id INT UNSIGNED FK → accounts.id (Wie bezahlt?)
betrag_netto DECIMAL(12,2)
ust_satz DECIMAL(5,2) Steuersatz in % (0, 7, 19)
steuerart ENUM normal, ig_lieferung, export, ig_erwerb_19, ig_erwerb_7
betrag_ust DECIMAL(12,2)
betrag_brutto DECIMAL(12,2)
buchungstext VARCHAR(500)
is_reversal TINYINT(1) 1 = Stornobuchung
reversed_by INT UNSIGNED ID der zugehörigen Stornobuchung
locked TINYINT(1) GoBD: unveränderlich
fiscal_year_id INT UNSIGNED FK → fiscal_years.id
created_at DATETIME

Hinweis: Die Spalte asset_id existiert nur nach Migration 030 (Feature-Branch Betriebsvermögen).


assets – Anlagegüter (Wirtschaftsgüter)

Diese Tabelle existiert nur nach Migration 028 (Feature-Branch Betriebsvermögen).

Spalte Typ Beschreibung
id INT UNSIGNED PK
lfd_nr INT UNSIGNED Laufende Nummer
anlage_nr VARCHAR(30) Anlagen-Nummer (z.B. ANL-2026-0001)
bezeichnung VARCHAR(255) Bezeichnung des Wirtschaftsguts
account_id INT UNSIGNED FK → accounts.id (Anlageart)
anschaffungsdatum DATE
anschaffungskosten DECIMAL(12,2) Netto-Anschaffungskosten
zugaenge DECIMAL(12,2) Nachträgliche Anschaffungskosten
abgaenge DECIMAL(12,2) Wertminderungen
abschreibung_jahr DECIMAL(12,2) AfA laufendes Wirtschaftsjahr
nutzungsdauer INT UNSIGNED Nutzungsdauer in Jahren
notizen TEXT
fiscal_year_id INT UNSIGNED FK → fiscal_years.id
created_at / updated_at DATETIME

invoices – Ausgangsrechnungen

Spalte Typ Beschreibung
id INT UNSIGNED PK
rechnungs_nr VARCHAR(30) UNIQUE NULL solange Entwurf
customer_id INT UNSIGNED FK → customers.id
betreff VARCHAR(500)
leistungszeitraum_von / _bis DATE
rechnungs_datum DATE
faellig_datum DATE
status ENUM Entwurf, Gesendet, Bezahlt, Storniert
betrag_netto / _ust / _brutto DECIMAL(12,2) Summenspalten
beleg_id INT UNSIGNED FK → belege.id
notes TEXT
fiscal_year_id INT UNSIGNED FK → fiscal_years.id
created_at / updated_at DATETIME

invoice_lines – Rechnungspositionen

Spalte Typ Beschreibung
id INT UNSIGNED PK
invoice_id INT UNSIGNED FK → invoices.id (CASCADE DELETE)
position SMALLINT UNSIGNED Positionsnummer
bezeichnung VARCHAR(500)
menge DECIMAL(10,3)
einheit VARCHAR(20) z.B. Stk., h
einzelpreis DECIMAL(12,2) Netto-Einzelpreis
ust_satz DECIMAL(5,2)
betrag_netto / _ust / _brutto DECIMAL(12,2)

users – Benutzerkonten

Spalte Typ Beschreibung
id INT UNSIGNED PK
username VARCHAR(64) UNIQUE
password_hash VARCHAR(255) bcrypt
active TINYINT(1) 0 = deaktiviert
created_at DATETIME

ustva_submissions – UStVA-Einreichungen

Spalte Typ Beschreibung
id INT UNSIGNED PK
year SMALLINT UNSIGNED Meldejahr
month TINYINT UNSIGNED Meldemonat (1–12)
xml_content MEDIUMTEXT Generiertes ELSTER-XML
field_values JSON Kennzahlen als JSON
submitted_at DATETIME NULL = noch nicht eingereicht
status ENUM Erstellt, Eingereicht
created_at DATETIME

UNIQUE KEY auf (year, month).


audit_log – GoBD-Audit-Log

Spalte Typ Beschreibung
id BIGINT UNSIGNED PK
timestamp DATETIME
table_name VARCHAR(50) Betroffene Tabelle
record_id INT UNSIGNED Betroffener Datensatz
action ENUM INSERT, UPDATE, DELETE, LOCK
old_values JSON Werte vor der Änderung
new_values JSON Werte nach der Änderung
ip_address VARCHAR(45)
user_agent VARCHAR(500)

GoBD-Mechanismen

  • Trigger bookings_before_update / bookings_before_delete: Jeder Versuch, eine gesperrte Buchung (locked = 1) zu ändern oder zu löschen, wird mit einem SQL-Fehler abgewiesen.
  • file_hash in belege: SHA-256-Prüfsumme jedes Belegdokuments; erlaubt nachträgliche Integritätsprüfung.
  • audit_log: Protokolliert alle Datenbankänderungen mit alten und neuen Werten.
  • Stornobuchungen statt Löschungen: Korrekturen erzeugen eine Gegenbuchung, die ursprüngliche Buchung bleibt erhalten.

Migrationen

Schemaänderungen kommen ausschließlich als nummerierte SQL-Dateien in migrations/ und werden vom Script scripts/migrate.php beim Container-Start automatisch eingespielt. Die Tabelle schema_migrations protokolliert, welche Dateien bereits angewendet wurden.