Hagemeister Conception
← Zurück zum Blog

Eine FileMaker-Datenbank für E-Rechnungen sinnvoll strukturieren – für Factur-X, ZUGFeRD und XRechnung

Die Rechnung ist längst verschickt. Wochen später ändert jemand die Anschrift im Kundenstamm – und plötzlich zeigt auch der alte Beleg die neue Adresse. Was bei einer nur auf Layout und PDF ausgerichteten FileMaker-Lösung lange unbemerkt bleiben kann, wird bei einer E-Rechnung zum grundlegenden Konstruktionsfehler.

Denn eine E-Rechnung ist kein Rechnungsformular mit angehängter XML-Datei, sondern ein strukturiertes Geschäftsdokument. Rechnungssteller, Rechnungsempfänger, Positionen, Nachlässe, Zuschläge, Steueraufschlüsselung, Summen und Zahlungsdaten müssen fachlich zusammenpassen, historisch reproduzierbar bleiben und sich eindeutig in Factur-X, ZUGFeRD oder XRechnung übertragen lassen.

Wer eine bestehende FileMaker-Rechnungslösung erweitert oder ein neues Datenmodell aufbaut, sollte deshalb nicht beim Layout und auch nicht bei XML-Knoten beginnen. Zuerst muss die Datenbank den Geschäftsvorgang richtig abbilden. Erst danach werden die gespeicherten Informationen auf die semantischen Elemente der E-Rechnung und schließlich auf UBL, CII oder ein hybrides Rechnungsformat abgebildet.

Das hier beschriebene Festschreibekonzept unterstützt zugleich die in Deutschland wichtige Unveränderbarkeit und Nachvollziehbarkeit im Sinne der GoBD. Ein gutes Datenmodell allein stellt jedoch noch keine GoBD-Konformität her. Dazu gehören ebenso ein Berechtigungskonzept, eine Verfahrensdokumentation, protokollierte Kontrollen, eine geeignete Aufbewahrung, Datensicherung und ein tatsächlich entsprechend organisierter Betrieb.

Das wichtigste Prinzip: Geschäftsmodell vor Exportformat

Eine Rechnungslösung verarbeitet drei unterschiedliche Arten von Daten:

  1. Stammdaten wie Kunden, Rechnungssteller, Artikel, Adressen und Steuerschlüssel.
  2. Belegdaten wie Rechnungskopf, Rechnungspositionen, Nachlässe, Zuschläge, Steueraufschlüsselungen und Zahlungsbedingungen.
  3. Technische Verarbeitungsdaten wie Exportprofil, erzeugte Dateien, Validierungsstatus und Prüfprotokolle.

Diese Ebenen sollten getrennt bleiben. Stammdaten unterstützen die Erfassung. Die Belegdaten dokumentieren den tatsächlich ausgestellten Geschäftsvorgang. Die technische Ebene erzeugt und prüft daraus die E-Rechnung.

Ein häufiger Strukturfehler besteht darin, diese Ebenen zu vermischen. Dann greifen alte Rechnungen auf inzwischen geänderte Kundenstammdaten zu, Berechnungen hängen vom aktuellen Layoutkontext ab oder die erzeugte XML-Datei wird zur eigentlichen Datenhaltung. Eine belastbare Lösung vermeidet genau das.

Einheitliche Feldnamen und technische Schlüssel

Jede Basistabelle sollte einen internen Primärschlüssel erhalten, vorzugsweise eine UUID in einem Textfeld. Dieser Schlüssel dient ausschließlich der technischen Verknüpfung von Datensätzen.

Zusätzlich gibt es sichtbare Geschäftskennungen, beispielsweise:

  • Rechnungsnummer
  • Kundennummer
  • Angebotsnummer
  • Auftragsnummer
  • Artikelnummer

Diese Nummern sind keine geeigneten Beziehungsschlüssel. Sie können Präfixe, führende Nullen, Jahresangaben oder unterschiedliche Nummernkreise enthalten. Deshalb sollten sie als Text gespeichert und nicht für interne Beziehungen verwendet werden.

Für die folgenden Beispiele gilt eine einheitliche Benennung:

  • Basistabellen stehen im Plural, beispielsweise Rechnungen und Kunden.
  • Der Primärschlüssel heißt in jeder Tabelle ID.
  • Fremdschlüssel verwenden den Namen des einzelnen übergeordneten Objekts: RechnungID, KundeID, RechnungsstellerID und RechnungspositionID.

Ein sinnvolles Grundmuster für operative Tabellen lautet:

Feld Zweck
IDUUID als Primärschlüssel
ErstelltAmErstellungszeitstempel
ErstelltVonErstellendes Konto
GeaendertAmÄnderungszeitstempel
GeaendertVonÄnderndes Konto

Fremdschlüssel erhalten ebenfalls den Typ Text und speichern die UUID des übergeordneten Datensatzes.

Die empfohlenen Kerntabellen

Für eine allgemeine E-Rechnungsstruktur sind folgende Basistabellen sinnvoll:

Tabelle Aufgabe
RechnungsstellerStammdaten der ausstellenden Organisation
KundenStammdaten des Käufers beziehungsweise Vertragspartners
AdressenWiederholbare Rechnungs-, Liefer- und sonstige Adressen
RechnungenKopf-, Referenz-, Zahlungs- und Abschlussdaten des Belegs
RechnungspositionenEinzelne abgerechnete Waren oder Leistungen
PositionsanpassungenWiederholbare Nachlässe und Zuschläge einer Position
BeleganpassungenWiederholbare Nachlässe und Zuschläge auf Belegebene
SteuerschluesselInterne Steuerlogik und Zuordnung zu normativen Steuerfällen
RechnungssteuernFestgeschriebene Steueraufschlüsselung je normativem Steuerfall
RechnungsnotizenInterne oder auszugebende Notizen mit Reihenfolge und Verwendungszweck
RechnungsdokumenteUnterstützende Dokumente, Anlagen und externe Referenzen
ExportlaeufeErzeugte Dateien, Exportparameter und Prüfprotokolle
NummernkreiseKonfiguration und nächster Wert eines Rechnungsnummernkreises
NummernvergabenNachvollziehbare Zuordnung einer Nummer zu einer Rechnung
DokumenttypenZulässige Rechnungs- und Korrekturbelegarten
WaehrungenZulässige Währungscodes
EinheitenZulässige Mengeneinheiten

Je nach Anwendung können weitere Stammtabellen hinzukommen, beispielsweise Artikel, Zahlungsarten, Bankkonten, Laender oder eine allgemeine Tabelle Geschaeftspartner. Entscheidend ist, dass wiederholbare Inhalte nicht als immer neue Felder in den Rechnungskopf eingebaut werden.

Das Beziehungsmodell im Überblick

erDiagram
    RECHNUNGSSTELLER ||--o{ RECHNUNGEN : stellt_aus
    KUNDEN ||--o{ RECHNUNGEN : ist_Kaeufer
    RECHNUNGEN ||--o{ RECHNUNGSPOSITIONEN : enthaelt
    ARTIKEL |o--o{ RECHNUNGSPOSITIONEN : dient_als_Vorlage
    STEUERSCHLUESSEL ||--o{ RECHNUNGSPOSITIONEN : klassifiziert
    RECHNUNGSPOSITIONEN ||--o{ POSITIONSANPASSUNGEN : besitzt
    RECHNUNGEN ||--o{ BELEGANPASSUNGEN : besitzt
    RECHNUNGEN ||--o{ RECHNUNGSSTEUERN : besitzt
    RECHNUNGEN ||--o{ RECHNUNGSNOTIZEN : besitzt
    RECHNUNGEN ||--o{ RECHNUNGSDOKUMENTE : besitzt
    RECHNUNGEN ||--o{ EXPORTLAEUFE : erzeugt
    NUMMERNKREISE ||--o{ NUMMERNVERGABEN : vergibt
    RECHNUNGEN ||--o| NUMMERNVERGABEN : erhaelt
    DOKUMENTTYPEN ||--o{ RECHNUNGEN : typisiert
    WAEHRUNGEN ||--o{ RECHNUNGEN : verwendet
    EINHEITEN ||--o{ RECHNUNGSPOSITIONEN : verwendet

Das Diagramm zeigt die fachlichen Beziehungen. In FileMaker werden sie über Tabellenauftreten im Beziehungsdiagramm hergestellt. Eine Basistabelle kann dort mehrfach vorkommen, wenn sie aus verschiedenen Beziehungskontexten benötigt wird.

Die Beziehungen im Detail

Rechnungssteller zu Rechnungen

Rechnungssteller::ID = Rechnungen::RechnungsstellerID

Kardinalität: Ein Rechnungssteller kann null bis viele Rechnungen besitzen. Jede Rechnung gehört genau zu einem Rechnungssteller.

Die Beziehung stellt während der Erfassung Name, Anschrift, Steuerkennungen, elektronische Adresse, Kontakt- und Zahlungsdaten bereit. Beim Festschreiben werden die tatsächlich verwendeten Werte in die Rechnung kopiert. Eine bereits ausgestellte Rechnung darf sich nicht ändern, wenn später der Rechnungsstellerstammsatz bearbeitet wird.

Kunde zu Rechnungen

Kunden::ID = Rechnungen::KundeID

Kardinalität: Ein Kunde kann null bis viele Rechnungen besitzen. Jede Rechnung gehört genau zu einem Käufer beziehungsweise Kunden.

Der Kunde ist der fachliche Vertragspartner. Auch diese Beziehung dient der Erfassung und Navigation. Die ausgegebenen Käuferdaten werden beim Festschreiben als Snapshot gespeichert.

Abweichender Rechnungsempfänger und Lieferadresse

Ein abweichender Rechnungsempfänger darf nicht in den Feldern des Käufers überschrieben werden. Ebenso ist die Lieferadresse nicht zwangsläufig mit der Rechnungsanschrift identisch.

In einer einfachen Lösung können dafür zusätzliche optionale Fremdschlüssel verwendet werden:

Kunden_Rechnungsempfaenger::ID = Rechnungen::RechnungsempfaengerID
Adressen_Lieferung::ID         = Rechnungen::LieferadresseID

Kunden_Rechnungsempfaenger und Adressen_Lieferung sind dabei eigene Tabellenauftreten der jeweiligen Basistabellen.

Kardinalität: Eine Rechnung besitzt null oder einen abweichenden Rechnungsempfänger und null oder eine abweichende Lieferadresse. Derselbe Stammdatensatz kann in beliebig vielen Rechnungen verwendet werden.

Bei komplexeren Lösungen ist eine allgemeine Tabelle Geschaeftspartner mit mehreren Rollen oft sinnvoller. Unabhängig von der Stammdatenstruktur müssen der tatsächlich verwendete Rechnungsempfänger, Lieferempfänger und die Lieferanschrift beim Festschreiben vollständig in den Rechnungs-Snapshot kopiert werden.

Rechnung zu Rechnungspositionen

Rechnungen::ID = Rechnungspositionen::RechnungID

Kardinalität: Eine Rechnung kann im Entwurf null bis viele Positionen enthalten. Jede Rechnungsposition gehört genau zu einer Rechnung. Eine normale festgeschriebene Rechnung benötigt regelmäßig mindestens eine Position.

Typische Felder einer Rechnungsposition sind:

  • ID
  • RechnungID
  • Positionsnummer
  • optionale ArtikelID
  • Verkäufer- und Käuferartikelkennung
  • Bezeichnung und Beschreibung
  • Menge
  • Einheit beziehungsweise festgeschriebener Einheitencode
  • Preisbasismenge
  • Einzelpreis
  • SteuerschluesselID
  • festgeschriebene Steuerkategorie und Steuersatz
  • Positionsnettobetrag

Nachlässe und Zuschläge gehören nicht als einzelnes Feld in die Position. Sie sind wiederholbar und werden deshalb in Positionsanpassungen gespeichert.

Positionen gehören in eine eigene Tabelle. Wiederholfelder, mehrere horizontal angelegte Positionsgruppen oder ausschließlich in JSON gespeicherte Positionen erschweren Berechnung, Prüfung, Auswertung und Nachvollziehbarkeit.

Artikel zu Rechnungspositionen

Artikel::ID = Rechnungspositionen::ArtikelID

Kardinalität: Ein Artikel kann in null bis vielen Rechnungspositionen vorkommen. Eine Rechnungsposition verweist auf null oder einen Artikel.

Die Artikelbeziehung ist optional, weil auch freie Leistungspositionen möglich sein können. Der Artikelstamm dient als Vorlage für Bezeichnung, Kennungen, Einheit, Preis und Steuerzuordnung. Beim Erstellen der Position werden die tatsächlich verwendeten Werte in die Rechnungsposition kopiert.

Eine historische Rechnungsposition darf nicht davon abhängen, ob der Artikel später umbenannt, gelöscht oder steuerlich neu klassifiziert wird.

Steuerschlüssel zu Rechnungspositionen

Steuerschluessel::ID = Rechnungspositionen::SteuerschluesselID

Kardinalität: Ein interner Steuerschlüssel kann in null bis vielen Rechnungspositionen verwendet werden. Jede Position verwendet genau einen Steuerschlüssel.

Ein Steuerschlüssel sollte mehr enthalten als nur einen Prozentsatz. Er beschreibt die interne Behandlung und ihre normative Zuordnung, beispielsweise:

  • interne Bezeichnung
  • normative Steuerkategorie
  • Steuersatz
  • gegebenenfalls Befreiungsgrundcode
  • gegebenenfalls Befreiungsgrundtext
  • Gültigkeitszeitraum

Zwei interne Steuerschlüssel können auf denselben normativen Steuerfall abbilden. Beispielsweise kann ein Unternehmen intern zwischen einer Ware und einer Leistung unterscheiden, obwohl beide dieselbe Steuerkategorie und denselben Steuersatz besitzen. Diese internen Schlüssel dürfen in der Steueraufschlüsselung nicht zwangsläufig zu zwei getrennten Gruppen führen.

Rechnungsposition zu Positionsanpassungen

Rechnungspositionen::ID = Positionsanpassungen::RechnungspositionID

Kardinalität: Eine Rechnungsposition kann null bis viele Nachlässe oder Zuschläge besitzen. Jede Positionsanpassung gehört genau zu einer Rechnungsposition.

Sinnvolle Felder sind:

Feld Zweck
ArtNachlass oder Zuschlag
ReihenfolgeEindeutige Berechnungs- und Ausgabereihenfolge
GrundLesbare Begründung
GrundcodeGegebenenfalls standardisierter Grundcode
BasisbetragBetrag, auf den die Anpassung berechnet wird
ProzentsatzOptionaler Prozentsatz
BetragVerbindlicher Anpassungsbetrag
Steuerkategorie_festFestgeschriebene normative Steuerkategorie
Steuersatz_festFestgeschriebener Steuersatz

Bei einer Positionsanpassung folgt die steuerliche Behandlung gewöhnlich der Position. Die Werte sollten dennoch festgeschrieben werden, damit die spätere Ausgabe nicht von einem geänderten Steuerschlüssel abhängt.

Der Positionsnettobetrag wird nach Anwendung aller Positionsnachlässe und Positionszuschläge ermittelt. Die Reihenfolge muss eindeutig definiert sein, insbesondere wenn mehrere prozentuale und absolute Anpassungen kombiniert werden.

Rechnung zu Beleganpassungen

Rechnungen::ID = Beleganpassungen::RechnungID

Kardinalität: Eine Rechnung kann null bis viele Nachlässe oder Zuschläge auf Belegebene besitzen. Jede Beleganpassung gehört genau zu einer Rechnung.

Auch auf Belegebene reicht ein einzelnes Feld wie Gesamtnachlass nicht aus. Jede Anpassung kann einen eigenen Grund, Grundcode, Betrag und Steuerfall besitzen.

Sinnvolle Felder sind:

Feld Zweck
ArtNachlass oder Zuschlag
ReihenfolgeBerechnungs- und Ausgabereihenfolge
GrundLesbare Begründung
GrundcodeGegebenenfalls standardisierter Grundcode
BasisbetragBerechnungsbasis
ProzentsatzOptionaler Prozentsatz
BetragVerbindlicher Anpassungsbetrag
Steuerkategorie_festNormative Steuerkategorie
Steuersatz_festNormativer Steuersatz
BefreiungsgrundCode_festGegebenenfalls Befreiungsgrundcode
BefreiungsgrundText_festGegebenenfalls Befreiungsgrundtext

Belegweite Nachlässe und Zuschläge wirken unmittelbar auf die Steueraufschlüsselung zurück. Sie müssen der zutreffenden Steuerkategorie und dem zutreffenden Steuersatz zugeordnet und bei der Ermittlung des steuerpflichtigen Betrags der jeweiligen Steuergruppe berücksichtigt werden.

Rechnung zu Rechnungssteuern

Rechnungen::ID = Rechnungssteuern::RechnungID

Kardinalität: Eine Rechnung kann null bis viele Steuerzeilen besitzen. Jede Steuerzeile gehört genau zu einer Rechnung. Für jeden normativen Steuerfall darf innerhalb der Rechnung nur eine Steuerzeile existieren.

Rechnungssteuern enthält nicht einfach eine Zeile je internem Steuerschlüssel. Gruppiert wird nach dem steuerlichen Sachverhalt, der in der E-Rechnung ausgegeben wird:

  • Steuerkategorie
  • normalisierter Steuersatz
  • bei steuerbefreiten oder vergleichbaren Fällen der maßgebliche Befreiungsgrund beziehungsweise Befreiungsgrundcode

Typische Felder sind:

  • ID
  • RechnungID
  • Steuerkategorie_fest
  • Steuersatz_fest
  • BefreiungsgrundCode_fest
  • BefreiungsgrundText_fest
  • SteuerpflichtigerBetrag_fest
  • Steuerbetrag_fest
  • SteuergruppenSchluessel
  • RechnungSteuergruppeKey

Eine direkte Pflichtbeziehung von Rechnungssteuern zu genau einem Steuerschluessel wäre irreführend. Mehrere interne Steuerschlüssel können in derselben normativen Steuergruppe zusammenlaufen. Soll die Herkunft im Detail nachvollziehbar bleiben, kann zusätzlich eine Zuordnungstabelle zwischen Steuerzeile und den beteiligten Positionen oder internen Steuerschlüsseln geführt werden.

Die Eindeutigkeit einer Steuergruppe in FileMaker

FileMaker besitzt keine zusammengesetzte Eindeutigkeitsprüfung über mehrere Felder. Deshalb reicht die fachliche Aussage „RechnungID plus Steuerkategorie plus Steuersatz muss eindeutig sein“ allein nicht aus.

Sinnvoll ist ein gespeichertes Textfeld, das per automatischer Eingabeberechnung oder durch das Aufbau-Skript gesetzt wird:

SteuergruppenSchluessel =
    Steuerkategorie_fest & Char ( 30 ) &
    NormalisierterSteuersatz & Char ( 30 ) &
    BefreiungsgrundSchluessel

Dabei steht BefreiungsgrundSchluessel vorzugsweise für einen normierten Code. Ist nur ein Text vorhanden, muss dieser vor der Schlüsselbildung vereinheitlicht werden. Der Steuersatz darf nicht aus einem formatierten Layouttext übernommen werden, sondern benötigt eine festgelegte, locale-unabhängige Darstellung.

Für die Eindeutigkeit innerhalb einer Rechnung wird ein zweites gespeichertes Feld gebildet:

RechnungSteuergruppeKey =
    RechnungID & Char ( 30 ) & SteuergruppenSchluessel

Für RechnungSteuergruppeKey werden in den Feldoptionen mindestens die Prüfungen nicht leer und eindeutiger Wert aktiviert. Das Trennzeichen sollte kein Absatzzeichen sein, weil return-separierte Werte in FileMaker-Beziehungen als Mehrfachschlüssel wirken können.

Die Eindeutigkeitsvalidierung ist eine zusätzliche Sicherung. Der eigentliche Aufbau der Steuerzeilen sollte trotzdem skriptgesteuert und transaktional erfolgen.

Rechnung zu Rechnungsnotizen

Rechnungen::ID = Rechnungsnotizen::RechnungID

Kardinalität im Datenmodell: Eine Rechnung kann null bis viele Notizen besitzen. Jede Notiz gehört genau zu einer Rechnung.

Eine Kindtabelle ist sinnvoll, weil Notizen unterschiedliche Aufgaben haben können:

  • interne Bearbeitungshinweise
  • auszugebende Rechnungsnotizen
  • rechtlich oder fachlich begründete Hinweise
  • Korrekturbegründungen
  • sprachabhängige Texte

Sinnvolle Felder sind Typ, Verwendung, Reihenfolge, Sprachcode und Text.

Die interne Wiederholbarkeit bedeutet nicht automatisch, dass jedes Exportprofil beliebig viele Notizen erlaubt. In verbreiteten E-Rechnungsprofilen ist die allgemeine Rechnungsnotiz häufig auf einen Eintrag begrenzt; in bestimmten nationalen Konstellationen kann eine Wiederholung erlaubt sein. Das Exportskript muss deshalb die Kardinalität des gewählten Profils prüfen. Sind nur eine Notiz oder ein Textfeld zulässig, müssen mehrere freigegebene Texte nach einer dokumentierten Regel zusammengeführt oder als Fehler zurückgewiesen werden.

Interne Notizen dürfen niemals ungeprüft in die E-Rechnung gelangen. Nur Datensätze mit einer ausdrücklichen Ausgabekennzeichnung werden in den Snapshot und den Export übernommen.

Rechnung zu unterstützenden Dokumenten

Rechnungen::ID = Rechnungsdokumente::RechnungID

Kardinalität: Eine Rechnung kann null bis viele unterstützende Dokumente besitzen. Jedes Dokument gehört genau zu einer Rechnung.

Mögliche Felder sind:

  • Dokumentreferenz
  • Beschreibung
  • externer Dokumentenort
  • Datei im Containerfeld
  • Dateiname
  • MIME-Typ
  • Dokumentenart
  • Reihenfolge

Ein einzelnes Feld im Rechnungskopf wäre nur dann ausreichend, wenn fachlich garantiert genau ein Dokument vorkommen kann. Eine allgemeine Lösung sollte von einer wiederholbaren Struktur ausgehen.

Rechnung zu Exportläufen

Rechnungen::ID = Exportlaeufe::RechnungID

Kardinalität: Eine Rechnung kann null bis viele Exportläufe besitzen. Jeder Exportlauf gehört genau zu einer Rechnung.

Ein Exportlauf dokumentiert einen konkreten Erzeugungs- und Prüfvorgang. Sinnvolle Felder sind:

  • Exportformat
  • verwendetes Profil und dessen Version
  • Erstellungszeitpunkt
  • zugrunde liegende Exportdaten
  • erzeugte XML-Datei
  • gegebenenfalls erzeugte PDF-Datei
  • Validierungsstatus
  • Prüfprotokoll
  • Prüfsumme der erzeugten Datei
  • Kennzeichnung des tatsächlich versendeten Exports

Die Eins-zu-viele-Beziehung ist wichtig. Ein fehlgeschlagener oder vorläufiger Export darf nicht einfach vom nächsten Versuch überschrieben werden. Die Historie zeigt, welche Datei wann, aus welchem Rechnungsstand und mit welchem Ergebnis erzeugt wurde.

Nummernkreis, Nummernvergabe und Rechnung

Nummernkreise::ID = Nummernvergaben::NummernkreisID
Rechnungen::ID    = Nummernvergaben::RechnungID

Kardinalität: Ein Nummernkreis kann null bis viele Nummernvergaben besitzen. Eine festgeschriebene Rechnung erhält genau eine Nummernvergabe; ein Entwurf besitzt noch keine.

Nummernkreise enthält beispielsweise:

  • ID
  • Bezeichnung des Nummernkreises
  • Rechnungsstellerzuordnung
  • Präfix und Suffix
  • Perioden- oder Jahreskennung
  • Anzahl der Stellen
  • NaechsterZaehler
  • Aktivstatus

Nummernvergaben dokumentiert die konkrete Vergabe:

  • ID
  • NummernkreisID
  • RechnungID
  • Zählerwert
  • fertig formatierte Rechnungsnummer
  • Vergabezeitpunkt
  • vergebendes Konto oder Script
  • Status der Vergabe
  • gegebenenfalls Fehler- oder Abbruchgrund

Die zusätzliche Vergabetabelle ist nicht zwingend, aber sehr hilfreich. Sie trennt die Nummernreservierung vom Rechnungsdatensatz und dokumentiert auch fehlgeschlagene oder abgebrochene Vergaben nachvollziehbar.

Codelisten zu Rechnungen und Positionen

Typische Beziehungen sind:

Dokumenttypen::ID = Rechnungen::DokumenttypID
Waehrungen::ID    = Rechnungen::WaehrungID
Einheiten::ID     = Rechnungspositionen::EinheitID

Kardinalität: Ein Codelisteneintrag kann von null bis vielen Belegen oder Positionen verwendet werden. Jeder Beleg beziehungsweise jede Position verwendet genau den jeweils erforderlichen Eintrag.

Codelisten trennen die interne Auswahl von der später auszugebenden normativen Kennung. Während der Erfassung kann über die Beziehung eine Werteliste bereitgestellt werden. Beim Festschreiben wird der tatsächlich verwendete Code in den Beleg kopiert.

Die Steueraufschlüsselung richtig erzeugen

Die Steueraufschlüsselung sollte nicht manuell nebenher gepflegt werden. Sie wird aus den festgeschriebenen Rechnungspositionen und den belegweiten Nachlässen oder Zuschlägen aufgebaut.

Der entscheidende Gruppierungsschlüssel ist nicht SteuerschluesselID, sondern die normative Kombination aus Steuerkategorie, Steuersatz und gegebenenfalls Befreiungsgrund.

Ein kontrollierter Berechnungslauf arbeitet beispielsweise so:

  1. Für jede Rechnungsposition den Positionsnettobetrag nach allen Positionsnachlässen und Positionszuschlägen ermitteln.
  2. Für jede Position aus den festgeschriebenen Steuerwerten den normativen Steuergruppenschlüssel bilden.
  3. Alle Beleganpassungen einlesen und ebenfalls ihrer normativen Steuergruppe zuordnen.
  4. Datensätze nach SteuergruppenSchluessel gruppieren, nicht nach dem internen SteuerschluesselID.
  5. Für jede Gruppe den steuerpflichtigen Betrag berechnen. Beispiel für die Steuergruppe mit 19 Prozent Umsatzsteuer:
100,00 € Nettosumme der Positionen mit 19 % USt.
- 10,00 € Rechnungsnachlass, der zu 19 % gehört
+  5,00 € Rechnungszuschlag, der zu 19 % gehört
= 95,00 € steuerpflichtiger Betrag für die Steuergruppe 19 %

Nachlässe und Zuschläge, die zu einer anderen Steuergruppe gehören, werden bei dieser Berechnung nicht berücksichtigt.

  1. Den Steuerbetrag nach der festgelegten Rundungsregel berechnen.
  2. Für jede normative Gruppe genau einen Datensatz in Rechnungssteuern anlegen oder aktualisieren.
  3. Nicht mehr verwendete Steuerzeilen entfernen, solange sich die Rechnung noch im Entwurfs- oder Vorbereitungstatus befindet.
  4. Die Summe aller Steuergruppen mit den Rechnungssummen vergleichen.
  5. Die Eindeutigkeit von RechnungSteuergruppeKey prüfen.

Dadurch werden beispielsweise zwei interne Schlüssel für unterschiedlich ausgewertete Umsätze mit derselben normativen Kategorie und demselben Satz korrekt in einer Steueraufschlüsselung zusammengeführt. Vor dem Export ist zusätzlich zu prüfen, ob das gewählte Profil für eine bestimmte Steuerkategorie nur eine einzige Steueraufschlüsselung zulässt. Unterschiedliche Befreiungsgründe dürfen in einem solchen Fall nicht unbesehen als mehrere Gruppen ausgegeben werden, sondern müssen vor der Festschreibung fachlich geklärt werden.

Summen und Rundung zentral beherrschen

Für Rechnungsbeträge darf es nur eine verbindliche Berechnungskette geben. Layout, Export und Archiv dürfen nicht unterschiedliche Formeln verwenden.

Eine typische Rechnungskette lautet:

Menge × Einzelpreis / Preisbasismenge
- Positionsnachlässe
+ Positionszuschläge
= Positionsnettobetrag

Summe der Positionsnettobeträge
- Nachlässe auf Belegebene
+ Zuschläge auf Belegebene
= Rechnungsnetto

Summe der Steuerzeilen
= Gesamtsteuer

Rechnungsnetto
+ Gesamtsteuer
= Rechnungsbrutto

Rechnungsbrutto
- bereits gezahlte Beträge
+/- definierte Rundungsdifferenz
= Zahlbetrag

Prozentwerte brauchen eine einheitliche Speicherkonvention. Ein Wert darf nicht in einem Feld als Prozentzahl und an anderer Stelle als Dezimalfaktor interpretiert werden.

Mengen, Preise und Prozentsätze können mehr Nachkommastellen benötigen als endgültige Geldsummen. Die Rundung muss deshalb an fachlich festgelegten Punkten erfolgen und darf nicht zufällig vom Anzeigeformat eines Feldes abhängen.

Für ausgestellte Belege werden die geprüften Endwerte gespeichert. Ungespeicherte Berechnungen, die weiterhin auf veränderliche Stammdaten oder wechselnde Beziehungskontexte zugreifen, sind keine geeignete alleinige Archivgrundlage.

Warum Stammdatenbeziehungen allein nicht genügen

Eine normalisierte Datenbank versucht, doppelte Informationen zu vermeiden. Bei ausgestellten Rechnungen ist kontrollierte Redundanz jedoch notwendig.

Angenommen, eine Rechnung zeigt den Kundennamen ausschließlich über die Beziehung zu Kunden. Ändert sich später die Anschrift im Kundenstamm, würde eine alte Rechnung beim erneuten Öffnen oder Exportieren plötzlich die neue Anschrift enthalten. Der historische Beleg wäre damit verändert.

Deshalb braucht eine Rechnung einen Snapshot aller ausgaberelevanten Informationen. Beim Festschreiben werden unter anderem kopiert:

  • Name, Anschrift, Land, Steuerkennungen und elektronische Adresse des Rechnungsstellers
  • Name, Anschrift, Land, Steuerkennungen und elektronische Adresse des Käufers
  • Daten eines abweichenden Rechnungsempfängers
  • Lieferempfänger und abweichende Lieferanschrift
  • gegebenenfalls ein abweichender Zahlungsempfänger
  • Rechnungsnummer, Dokumenttyp und Datumsangaben
  • Käufer-, Bestell-, Vertrags- und Auftragsreferenzen
  • Zahlungsbedingungen, Zahlungsart und Bankdaten
  • Währung
  • auszugebende Rechnungsnotizen in der festgelegten Reihenfolge
  • Positionsnummern, Kennungen, Beschreibungen, Mengen und Einheiten
  • Preisbasismengen und Einzelpreise
  • alle Positionsnachlässe und Positionszuschläge einschließlich Grund und Grundcode
  • alle Nachlässe und Zuschläge auf Belegebene einschließlich Steuerzuordnung
  • Steuerkategorie, Steuersatz und Befreiungsinformationen
  • geprüfte Netto-, Steuer-, Brutto- und Zahlbeträge
  • die tatsächlich erzeugte strukturierte Rechnungsdatei
  • gegebenenfalls die zugehörige PDF-Datei
  • verwendetes Exportprofil, Validierungsergebnis und Prüfprotokoll

Die Stammdaten-IDs bleiben für Navigation, Suche und Auswertung erhalten. Layout, erneuter Export und Archivdarstellung einer festgeschriebenen Rechnung greifen jedoch ausschließlich auf die Snapshot-Werte zu.

Das Suffix _fest kann dabei kenntlich machen, dass ein Feld zum unveränderlichen Belegstand gehört, beispielsweise Steuerkategorie_fest oder KaeuferName_fest. Entscheidend ist weniger der konkrete Feldname als die klare Trennung zwischen einer aktuellen Stammdatenanzeige und dem historischen Rechnungswert.

Die Rechnungsnummer erst kontrolliert vergeben

Eine Rechnungsnummer sollte nicht bereits beim Anlegen eines leeren Entwurfs vergeben werden. Sinnvoller ist eine möglichst späte Vergabe beim Festschreiben, nachdem die fachlichen Vorprüfungen erfolgreich waren.

Nach deutschem Umsatzsteuerrecht muss die Nummer innerhalb eines oder mehrerer Nummernkreise einmalig vergeben werden. Eine lückenlose Zahlenfolge ist dabei nicht zwingend. Technisch unverzichtbar sind jedoch Eindeutigkeit, nachvollziehbare Zuordnung zum Nummernkreis und ein kontrollierter Mehrbenutzerzugriff.

Kollisionen im Mehrbenutzerbetrieb verhindern

Ein sicherer Ablauf sieht so aus:

  1. Den passenden Nummernkreis bestimmen.
  2. Den Nummernkreisdatensatz zur Bearbeitung öffnen und damit sperren.
  3. Prüfen, ob ein anderer Benutzer den Datensatz bereits gesperrt hat.
  4. Den aktuellen Wert von NaechsterZaehler lesen.
  5. Daraus die endgültige Rechnungsnummer bilden.
  6. Eine Nummernvergabe anlegen und der Rechnung zuordnen.
  7. Den Zähler im Nummernkreis erhöhen.
  8. Die Eindeutigkeit der fertigen Rechnungsnummer zusätzlich über ein gespeichertes Schlüsselfeld validieren.
  9. Alle Änderungen gemeinsam bestätigen.

Für mehrere Rechnungssteller kann der eindeutige Schlüssel beispielsweise so aufgebaut werden:

RechnungsnummerKey =
    RechnungsstellerID & Char ( 30 ) & Rechnungsnummer

RechnungsnummerKey erhält eine Eindeutigkeitsvalidierung. Damit wird auch dann eine Doppelvergabe abgefangen, wenn ein Fehler im Vergabeskript auftreten sollte.

Warum automatische Seriennummern dafür ungeeignet sind

Eine automatische Seriennummer in Rechnungen ist für technische Datensatz-IDs brauchbar, aber als verbindliche Rechnungsnummer problematisch. FileMaker setzt den Zähler einer automatisch eingegebenen Seriennummer beim Zurücksetzen einer Transaktion nicht zurück. Außerdem lässt sich die Vergabe über mehrere Rechnungssteller, Perioden und Nummernkreise nur eingeschränkt kontrollieren.

Die Rechnungsnummer sollte deshalb aus einem ausdrücklich gesperrten Nummernkreisdatensatz vergeben und als Text gespeichert werden.

Lücken minimieren, aber nicht durch Wiederverwendung kaschieren

Eine Nummer muss vor der Erzeugung und abschließenden Validierung in der strukturierten Rechnung stehen. Scheitert danach ein externer Dienst oder eine technische Prüfung, kann bereits eine Nummer vergeben worden sein.

Dafür gibt es zwei sinnvolle Strategien:

  1. Kurzer, vollständig lokaler Festschreibeprozess: Nummernvergabe, Dateierzeugung, Validierung und Festschreibung erfolgen in einer Transaktion. Das ist nur sinnvoll, wenn alle Schritte schnell und zuverlässig innerhalb derselben Sitzung ausgeführt werden können.
  2. Zweistufiger Prozess mit externem Dienst: Zunächst werden alle fachlichen Prüfungen ohne endgültige Nummer durchgeführt. Danach wird die Nummer in einer kurzen Transaktion reserviert. Anschließend werden finale Datei und Validierung erzeugt. Scheitert dieser Schritt, bleibt die Nummer als fehlgeschlagene Vergabe dokumentiert und wird nicht wiederverwendet.

Die zweite Variante kann einzelne Lücken erzeugen, verhindert aber Doppelvergaben und verschleiert keine abgebrochenen Vorgänge. Eine einmal nach außen verwendete oder verbindlich reservierte Rechnungsnummer sollte nicht stillschweigend einer anderen Rechnung zugeteilt werden.

Festschreiben: vom Entwurf zum unveränderlichen Beleg

Während der Bearbeitung darf eine Rechnung dynamisch sein. Nach der Ausstellung muss ihr ursprünglicher Inhalt erhalten bleiben. Das Festschreiben ist deshalb kein einzelnes Statusfeld, sondern ein kontrollierter Prozess.

Ein sinnvoller Ablauf lautet:

  1. Prüfen, ob sich die Rechnung im zulässigen Ausgangsstatus befindet.
  2. Pflichtfelder, Beziehungen, Codelisten und Referenzen prüfen.
  3. Positionen sowie Positionsnachlässe und Positionszuschläge vollständig neu berechnen.
  4. Belegweite Nachlässe und Zuschläge prüfen und ihren Steuergruppen zuordnen.
  5. Steueraufschlüsselung nach Steuerkategorie, Steuersatz und gegebenenfalls Befreiungsgrund neu aufbauen.
  6. Netto-, Steuer-, Brutto- und Zahlbeträge gegeneinander prüfen.
  7. Alle Stammdaten, Adressrollen, Referenzen, Notizen und ausgaberelevanten Werte in Snapshot-Felder beziehungsweise Snapshot-Kinddatensätze kopieren.
  8. Nach erfolgreicher Vorprüfung die Rechnungsnummer kollisionssicher vergeben.
  9. Exportdaten ausschließlich aus dem Snapshot erzeugen.
  10. Die strukturierte Rechnung gegen das gewählte Profil validieren.
  11. XML, gegebenenfalls PDF, Exportparameter, Prüfsumme und Prüfprotokoll archivieren.
  12. Status, Festschreibungszeitpunkt und festschreibendes Konto setzen.
  13. Sämtliche Änderungen gemeinsam bestätigen oder bei einem Fehler vollständig zurücksetzen.

Eine Rechnung darf nicht als festgeschrieben gelten, wenn nur ein Teil der Snapshot-Daten gespeichert wurde, Steuerzeilen fehlen oder keine erfolgreich geprüfte Exportdatei archiviert ist.

Transaktionen in neueren und älteren FileMaker-Versionen

Neuere FileMaker-Versionen stellen dafür echte Transaktions-Scriptschritte bereit:

  • Transaktion öffnen
  • Transaktion bestätigen
  • Transaktion rückgängig
  • in neueren Versionen zusätzlich Transaktion bei Fehler zurücksetzen

Die Transaktionsschritte stehen seit FileMaker Pro 19.6.1 zur Verfügung. Änderungen an mehreren Datensätzen und Tabellen können damit gemeinsam bestätigt oder gemeinsam zurückgesetzt werden. Die Transaktion gehört zum aktuellen Fensterkontext; Vorgänge in anderen Fenstern oder unabhängigen Sitzungen sind nicht automatisch Teil derselben Transaktion.

Ein vereinfachtes Muster sieht so aus:

Fehleraufzeichnung setzen [ Ein ]
Transaktion öffnen
Transaktion bei Fehler zurücksetzen [ Ein ]

# Rechnung sperren und prüfen
# Snapshot schreiben
# Anpassungen und Steuergruppen aufbauen
# Nummernkreis sperren und Nummer vergeben
# Exportdatensätze anlegen

Wenn [ Fehlerbedingung ]
    Transaktion rückgängig
Ende (wenn)

Transaktion bestätigen

Behelfstechnik für ältere Bestandslösungen

Ältere FileMaker-Versionen besitzen keine echte Transaktion über mehrere Datensätze und Tabellen. Dort kann ein streng kontrollierter Ablauf verwendet werden:

  • Datensatz/Abfrage öffnen, um einen Datensatz ausdrücklich zur Bearbeitung zu sperren
  • nach jeder Sperre und jedem Schreibvorgang Hole ( LetzteFehlerNr ) prüfen
  • Änderungen erst nach vollständiger Prüfung mit Schreibe Änderung Datens./Abfrage bestätigen
  • unbestätigte Änderungen mit Verwerfe Änderung Datens./Abfrage zurücknehmen
  • neue Daten zunächst in Arbeits- oder Stagingtabellen aufbauen
  • erst nach erfolgreicher Prüfung in den endgültigen Belegstand übernehmen
  • bei Fehlern alle bereits erzeugten Arbeitsdatensätze kontrolliert entfernen oder als fehlgeschlagen kennzeichnen

Diese Behelfstechnik ist keine vollwertige Transaktion über mehrere Tabellen. Sie kann einen Prozess absichern, verlangt aber eine besonders sorgfältige Fehlerbehandlung und eine dokumentierte Wiederanlaufstrategie.

FileMaker-spezifisch: Tabellenauftreten sauber trennen

In FileMaker entsteht der Beziehungskontext nicht direkt durch die Basistabelle, sondern durch ihr Tabellenauftreten. Dieselbe Basistabelle darf und soll mehrfach im Beziehungsdiagramm vorkommen, wenn sie aus unterschiedlichen fachlichen Perspektiven benötigt wird.

Ein möglicher Rechnungskontext sieht so aus:

Rechnung
├── Rechnung_Rechnungssteller
├── Rechnung_Kaeufer
├── Rechnung_AbweichenderRechnungsempfaenger
├── Rechnung_Lieferadresse
├── Rechnung_Dokumenttyp
├── Rechnung_Waehrung
├── Rechnung_Rechnungspositionen
│   ├── Rechnungsposition_Artikelvorlage
│   ├── Rechnungsposition_Mengeneinheit
│   ├── Rechnungsposition_Steuerschluessel
│   └── Rechnungsposition_NachlaesseUndZuschlaege
├── Rechnung_NachlaesseUndZuschlaege
├── Rechnung_Steueraufschluesselungen
├── Rechnung_Notizen
├── Rechnung_UnterstuetzendeDokumente
├── Rechnung_Exportlaeufe
└── Rechnung_Nummernvergabe
    └── Nummernvergabe_Nummernkreis

Der Teil vor dem Unterstrich nennt jeweils den Ausgangskontext, der Teil danach die fachliche Rolle des verbundenen Datensatzes. Rechnung_Kaeufer ist dadurch eindeutiger als ein allgemeines Tabellenauftreten namens Kunde, und Rechnungsposition_Artikelvorlage macht sichtbar, dass der Artikelstamm nur als Vorlage für die festgeschriebenen Positionsdaten dient.

Für die Steuergruppen können zwei Kontexte sinnvoll sein:

  1. Alle Steuerzeilen einer Rechnung
Rechnung::ID = Rechnung_AlleSteueraufschluesselungen::RechnungID
  1. Eine bestimmte normative Steuergruppe
GesuchteSteueraufschluesselung::RechnungID = Rechnung_GesuchteSteueraufschluesselung::RechnungID
UND
GesuchteSteueraufschluesselung::SteuergruppenSchluessel = Rechnung_GesuchteSteueraufschluesselung::SteuergruppenSchluessel

Der zweite Kontext darf nicht über SteuerschluesselID aufgebaut werden, weil mehrere interne Steuerschlüssel in dieselbe normative Steuergruppe einfließen können.

Ein Tabellenauftreten sollte nicht gleichzeitig mehrere unabhängige Aufgaben erfüllen. Klare Namen und getrennte Kontexte verhindern schwer nachvollziehbare Berechnungen und unbeabsichtigte Abhängigkeiten.

Beziehungen nicht als unkontrollierte Löschautomatik verwenden

FileMaker kann beim Löschen eines übergeordneten Datensatzes automatisch alle abhängigen Datensätze löschen. Für Rechnungsdaten ist diese Option riskant.

Solange eine Rechnung Entwurf ist, kann ein kontrolliertes Skript Positionen, Anpassungen, Steuerzeilen, Dokumente, Notizen und Exportentwürfe gemeinsam entfernen. Nach der Festschreibung darf der Beleg grundsätzlich nicht mehr physisch gelöscht oder überschrieben werden.

Sicherer ist deshalb:

  • Löschvorgänge über Skripte zu steuern.
  • vor jedem Löschen den Status zu prüfen.
  • festgeschriebene Belege über Zugriffsrechte zu schützen.
  • Korrekturen und Stornierungen als neue Belege anzulegen.
  • automatische Löschoptionen nur dort einzusetzen, wo ihr Verhalten vollständig kontrolliert und dokumentiert ist.

Die Schreibsperre gehört in die Zugriffsrechte

Eine Layoutprüfung wie

Wenn Status = "Festgeschrieben", dann Feld nicht bearbeiten

reicht nicht aus. Datensätze können auch über andere Layouts, Importe, Schnittstellen, die Data API oder Skripte geändert werden.

Festgeschriebene Rechnungen und ihre Kinddatensätze sollten deshalb zusätzlich über die Zugriffsrechte auf Datensatzebene geschützt werden. Normale Benutzer erhalten nur noch Leserechte. Änderungen sind ausschließlich über einen neuen Korrektur- oder Stornobeleg möglich.

Auch Scripts mit erweiterten Zugriffsrechten müssen den Status ausdrücklich prüfen. Vollzugriff darf nicht dazu führen, dass ein allgemeines Bearbeitungsskript historische Rechnungen unbemerkt verändert.

Korrekturen als Selbstbeziehung modellieren

Eine Korrektur verändert nicht den ursprünglichen Rechnungsdatensatz. Sie ist ein neuer Beleg mit eigener Nummer, eigenem Datum und eigenen Positionen.

Dafür kann Rechnungen eine optionale Fremdschlüsselspalte besitzen:

Rechnungen::UrsprungsrechnungID = Ursprungsrechnung::ID

Kardinalität: Eine Korrektur bezieht sich auf null oder genau eine Ursprungsrechnung. Eine Ursprungsrechnung kann von null bis mehreren Folgebelegen referenziert werden.

Im Beziehungsdiagramm wird dafür ein zweites Tabellenauftreten derselben Basistabelle verwendet, beispielsweise Rechnung_Ursprungsrechnung.

So bleibt die Belegkette nachvollziehbar, ohne alte Daten zu überschreiben.

Optional: Angebote und Aufträge als vorgelagerte Belegkette

Eine E-Rechnungslösung kann unabhängig von Angeboten und Aufträgen funktionieren. Werden diese Belege jedoch in derselben Datenbank verwaltet, sollten sie jeweils einen eigenen Kopf und eigene Positionen erhalten.

erDiagram
    ANGEBOTE ||--o{ ANGEBOTSPOSITIONEN : enthaelt
    ANGEBOTE |o--o{ AUFTRAEGE : fuehrt_zu
    ANGEBOTSPOSITIONEN |o--o{ AUFTRAGSPOSITIONEN : wird_uebernommen
    AUFTRAEGE ||--o{ AUFTRAGSPOSITIONEN : enthaelt
    AUFTRAEGE |o--o{ RECHNUNGEN : wird_abgerechnet
    AUFTRAGSPOSITIONEN |o--o{ RECHNUNGSPOSITIONEN : wird_abgerechnet

Die Beziehungen bedeuten:

  • Ein Auftrag verweist auf null oder ein Angebot; ein Angebot kann zu null bis vielen Aufträgen führen.
  • Eine Auftragsposition verweist auf null oder eine Angebotsposition; eine Angebotsposition kann in null bis vielen Auftragspositionen übernommen werden.
  • Eine Rechnung verweist im einfachen Modell auf null oder einen Auftrag; ein Auftrag kann in null bis vielen Rechnungen abgerechnet werden.
  • Eine Rechnungsposition verweist auf null oder eine Auftragsposition; eine Auftragsposition kann bei Teilabrechnungen in null bis vielen Rechnungspositionen vorkommen.

Für ein einfaches Modell referenziert eine Rechnung höchstens einen Auftrag. Müssen Sammelrechnungen mehrere Aufträge zusammenfassen, sollte dafür eine eigene Zwischentabelle verwendet werden. Mehrere Auftrags-IDs gehören niemals als Liste in ein einzelnes Feld.

Auch zwischen Angebot, Auftrag und Rechnung werden Werte kopiert und nicht nur über Beziehungen angezeigt. Der jeweils bestätigte Beleg muss seinen damaligen Stand behalten.

Die Exportlogik vom Datenmodell trennen

Das relationale FileMaker-Modell sollte nicht versuchen, die Baumstruktur einer bestimmten XML-Syntax nachzubauen. Die Geschäftsdaten bleiben in fachlich verständlichen Tabellen und Feldern.

Der Export erfolgt anschließend in zwei Schritten:

  1. Die festgeschriebenen Rechnungsdaten werden auf die semantischen Inhalte einer E-Rechnung abgebildet.
  2. Diese Inhalte werden in die gewünschte technische Syntax serialisiert.

Dadurch kann dieselbe Rechnung in unterschiedlichen zulässigen Formaten ausgegeben werden, ohne das Datenmodell neu aufzubauen.

Mappingregeln, Profilangaben, Codelistenstände und technische Pfade gehören in eine eigene Konfiguration oder in den Exportcode. Sie sollten nicht die Bezeichnungen und Beziehungen der eigentlichen Geschäftstabellen bestimmen.

GoBD: Festschreibung ist ein Baustein, keine Gesamtlösung

Das beschriebene Snapshot- und Festschreibemodell setzt einen wesentlichen Grundgedanken der GoBD technisch um: Der ursprüngliche Inhalt eines Belegs bleibt feststellbar und spätere Änderungen dürfen ihn nicht unbemerkt ersetzen.

Dazu passen insbesondere:

  • Sperren festgeschriebener Datensätze
  • automatische oder kontrollierte Protokollierung
  • Historisierung und Versionierung
  • nachvollziehbare Korrekturbelege
  • Zugangs- und Zugriffsberechtigungen
  • Archivierung der strukturierten Originaldatei
  • Erhaltung der Bedeutung verwendeter Stammdaten und Schlüssel

Die Tabellenstruktur allein genügt trotzdem nicht. Eine belastbare Umsetzung benötigt unter anderem:

  • eine Verfahrensdokumentation
  • dokumentierte Rollen und Berechtigungen
  • ein internes Kontrollsystem
  • Sicherungs- und Wiederherstellungsverfahren
  • Schutz vor unprotokollierten Änderungen über Schnittstellen oder Scripts
  • Aufbewahrung der relevanten strukturierten Daten und Verarbeitungsinformationen
  • regelmäßige Prüfung, ob das tatsächlich eingesetzte System der dokumentierten Verfahrensweise entspricht

Checkliste vor der Inbetriebnahme

  • Jede Basistabelle besitzt eine technische UUID als Primärschlüssel.
  • Fremdschlüssel verwenden einheitliche Namen wie RechnungID, KundeID und RechnungsstellerID.
  • Rechnungsnummern und andere Geschäftskennungen werden nicht als Beziehungsschlüssel verwendet.
  • Die Rechnungsnummer wird über einen gesperrten Nummernkreis kollisionssicher vergeben.
  • Eine Eindeutigkeitsvalidierung verhindert doppelte Rechnungsnummern.
  • Positionen liegen als echte Kinddatensätze und nicht in Wiederholfeldern oder JSON vor.
  • Positionsnachlässe und Positionszuschläge liegen in einer eigenen Kindtabelle.
  • Belegweite Nachlässe und Zuschläge liegen in einer eigenen Kindtabelle und besitzen eine Steuerzuordnung.
  • Steuergruppen werden nach Steuerkategorie, Steuersatz und gegebenenfalls Befreiungsgrund gebildet, nicht nach dem internen Steuerschlüssel.
  • Ein gespeicherter zusammengesetzter Schlüssel erzwingt je Rechnung die Eindeutigkeit der Steuergruppe.
  • Belegweite Nachlässe und Zuschläge fließen in den steuerpflichtigen Betrag der jeweiligen Steuergruppe ein.
  • Abweichender Rechnungsempfänger und Lieferadresse werden als eigene Rollen beziehungsweise Snapshot-Daten behandelt.
  • Rechnungsnotizen sind strukturiert gespeichert und werden beim Export profilabhängig auf ihre zulässige Anzahl geprüft.
  • Alte Rechnungen werden ausschließlich aus Snapshot-Daten dargestellt und exportiert.
  • Stammdatenänderungen verändern keine festgeschriebenen Belege.
  • Die Festschreibung läuft transaktional oder in einem dokumentierten kontrollierten Ersatzverfahren.
  • Lang laufende externe Aufrufe halten keine Datensatzsperren unnötig offen.
  • Festgeschriebene Belege und Kinddatensätze sind über Zugriffsrechte geschützt.
  • Korrekturen erzeugen neue Belege und überschreiben niemals die Ursprungsrechnung.
  • Jeder Export- und Validierungsversuch bleibt als eigener Exportlauf nachvollziehbar.
  • Die strukturierte Rechnungsdatei, das verwendete Profil und das Prüfprotokoll werden archiviert.
  • Die technische Umsetzung ist in eine Verfahrensdokumentation und ein Berechtigungskonzept eingebettet.

Fazit

Eine belastbare FileMaker-Datenbank für E-Rechnungen braucht keine möglichst komplizierte Tabellenstruktur. Sie braucht klar getrennte Verantwortlichkeiten:

  • Stammdaten für Auswahl und Erfassung
  • Rechnungskopf und Positionen für den konkreten Beleg
  • eigene Kindtabellen für wiederholbare Nachlässe, Zuschläge, Notizen und Dokumente
  • eine Steueraufschlüsselung nach normativer Steuerkategorie, Steuersatz und gegebenenfalls Befreiungsgrund
  • eine kontrollierte und mehrbenutzersichere Rechnungsnummernvergabe
  • Snapshot-Felder und Snapshot-Kinddatensätze für den unveränderlichen Rechnungsstand
  • getrennte Tabellenauftreten für eindeutige FileMaker-Kontexte
  • eine zentrale Berechnungs-, Festschreibungs- und Validierungslogik

Der entscheidende Punkt ist nicht, wie die Rechnung auf einem Layout aussieht. Entscheidend ist, dass jede Beziehung fachlich eindeutig ist, wiederholbare Inhalte relational gespeichert werden und der einmal ausgestellte Beleg später exakt in seinem ursprünglichen Zustand reproduziert werden kann.

Quellen und weiterführende Dokumentation