Von einem Übersetzer : Während meiner Arbeit bei der nigerianischen Fintech musste ich ein Zahlungssystem von Grund auf neu erstellen. Zu dieser Zeit verstand ich eigentlich nichts von Buchhaltung, wie es besser ist, Zahlungen und Salden zu speichern. Es bestand jedoch der Verdacht, dass die primitive Option mit einer Saldoziffer im Benutzerkonto zu einfach ist, um richtig zu sein.
Dieser Artikel hat mir geholfen, eine Reihe von Rechen in dieser Angelegenheit zu verstehen und zu vermeiden. Gleichzeitig sind die Informationen zum Thema "Wie Sie Ihr eigenes Zahlungssystem erstellen" recht klein und es ist für einen Programmierer nicht so einfach, Bücher über Buchhaltung zu verstehen (und sehr mühsam). Ich hoffe, dass dieses Material für diejenigen nützlich ist, die so etwas tun werden.
Ich entschuldige mich sofort für mögliche Ungenauigkeiten in Bezug auf die russischsprachige Finanzabteilung. Ich bin immer noch ein Programmierer, kein Buchhalter und mit der russischen Terminologie in diesem Bereich nicht vertraut.
Einleitung
Viele Computersysteme, die relationale Datenbanken verwenden, speichern irgendeine Art von Finanzinformation über Guthaben und Transaktionen. Darüber hinaus wirft der Entwurf und die Entwicklung einer solchen Datenbank häufig die Frage auf, wie diese Informationen gespeichert werden sollen. In der Regel besteht die Wahl zwischen einer billigen „einfachen Aufnahme“ und einer komplexeren „doppelten Aufnahme“.

Luca Pacioli, Autor des ältesten (15. Jahrhundert) überlieferten Buches, in dem die Prinzipien der doppelten Einreise beschrieben werden
In einem einfachen Aufzeichnungssystem werden numerische Werte nur einmal aufgezeichnet. In einem System mit doppelter Erfassung wird jeder Wert zweimal als Gutschrift (positiver Wert) und als Lastschrift (negativer Wert) erfasst. Es gibt eine Reihe von Regeln, die die Beziehung zwischen diesen Werten bestimmen. Diese Regeln werden Ihnen von jedem erfahrenen Buchhalter leicht beschrieben, obwohl er sich nicht einmal vorstellen kann, wie sie in einer relationalen Datenbank dargestellt werden können.
Die Grundregeln lauten wie folgt:
- Jeder Eintrag im System muss ausgeglichen sein, d.h. Die Summe aller Werte in einer Operation sollte Null ergeben.
- Die Summe aller Werte im gesamten System zu einem bestimmten Zeitpunkt sollte Null ergeben (die Regel der sogenannten "Probebilanz").
- Bereits in die Datenbank eingegebene Werte können nicht bearbeitet oder gelöscht werden. Wenn Korrekturen erforderlich sind, muss der Vorgang zuerst durch einen anderen Vorgang mit dem entgegengesetzten Vorzeichen abgebrochen und dann mit dem korrekten Wert wiederholt werden. Auf diese Weise können Sie einen zuverlässigen Audit-Trail implementieren (ein vollständiges Protokoll aller Transaktionen, die häufig bei Inspektionen erforderlich sind).
Anwendbarkeit der doppelten Buchhaltung
Zu Beginn eines Projekts ist der niedrige Preis einer einfachen Aufnahme immer verlockend, und die Kosten für die Implementierung und die Komplexität einer vollwertigen Doppelaufnahme scheinen unnötig. In der Realität ist die Verwendung einer einfachen Aufzeichnung jedoch häufig eine falsche Einsparung.
Wenn die Buchhaltungsinformationen im IT-System nur die vorhandenen Papieraufzeichnungen kopieren, die außerhalb der zu entwickelnden Datenbank gespeichert sind, hat eine einfache Aufzeichnung immer noch das Recht auf Leben. Wenn jedoch mindestens eine der unten aufgeführten Tatsachen über das System zutrifft, sollte von Anfang an die doppelte Eingabe verwendet werden:
- Falls jemals eine Rechnungsprüfung von Informationen erforderlich ist
- Wenn die Informationen im System die einzige Informationsquelle über die Eigenschaft sind
- Wenn die Informationen Objekte von hohem Wert betreffen
- Wenn das System in Zukunft ernsthaft weiterentwickelt werden soll
Beispiel mit doppelter Eingabe
Die Schlüsselidee der doppelten Eingabe ist das Vorhandensein eines speziellen "Kassenbuch" -Kontos ( ungefähr übersetzt: Ich habe nicht gefunden, wie ich es angemessen auf Russisch nennen kann, kann mir jemand sagen? ). Dieses Konto enthält Aufzeichnungen, die erstellt wurden, als Wertgegenstände (z. B. Geld) in unserem Buchhaltungssystem ein- oder ausgezahlt wurden. Der aktuelle Saldo dieses Kontos spiegelt somit die Gesamtzahl der Werte im System wider.
Das folgende ist ein einfaches Beispiel mit zwei Konten, "Kassenbuch" und "Smith".
(a) 300 £ werden in das System eingegeben und auf das Konto von Smith eingezahlt. Auf Smiths Konto wird ein Darlehen von 300 Pfund Sterling angelegt (Gutschrift rechts, Abbuchung links). Um diesen Betrag auszugleichen, wird auf dem Kassenbuchkonto eine Abbuchung von 300 GBP vorgenommen.

(b) Smith zieht dann £ 50 vom System ab. Wir erstellen eine Abbuchung für diesen Betrag auf Smiths Konto und eine Gutschrift im Kassenbuch.

(c) Fügen Sie ein weiteres Pattel-Konto hinzu und überweisen Sie ihm 100 £ von Smith. Dazu müssen wir bei Smith eine Abbuchung für diesen Betrag und bei Pattel einen Kredit erstellen.
(d) Lassen Sie als letzten Schliff Pattel nun £ 60 vom System abheben. Wir erstellen eine Lastschrift auf seinem Konto und eine Gutschrift im Kassenbuch.

Als Ergebnis all dieser Operationen können wir berechnen, dass der Gesamtsaldo von Smith 150 £, Pattela 40 £ und im Kassenbuch -190 £ die negative Summe der Salden aller anderen Konten beträgt. Basierend auf diesen einfachen Regeln und Operationen können Sie in Zukunft ein sehr umfassendes Wertkontrollsystem aufbauen.
Datenmodell
Die Struktur eines einfachen Datenmodells, mit dem alle diese Informationen dargestellt werden können:

Die POSTING-Tabelle enthält die doppelten Einträge selbst. Das Speichern aller Zahlen in einer Tabelle vereinfacht alle Berechnungen erheblich. Als Primärschlüssel sollte ein monoton ansteigender Zähler verwendet werden. Die Werte sollten in diesem Fall in einer Reihe stehen. Anhand der Zahl können Sie immer sicherstellen, dass kein Datensatz gelöscht wurde. Die Tabellen BATCH und JOURNAL dienen zur Steuerung und Eingabe von Daten in diese POSTING-Tabelle.
Jeder Eintrag in der Tabelle JOURNAL repräsentiert eine Transaktion (aus betriebswirtschaftlicher Sicht), die doppelte Einträge generiert. Eine solche Transaktion ist eine abgeschlossene Arbeitseinheit oder ein Geschäftsprozess. Entweder müssen alle POSTING-Datensätze, die dem JOURNAL-Datensatz zugeordnet sind, erfolgreich abgeschlossen werden, oder keiner von ihnen. Die Summe aller POSTING-Datensätze in einer einzelnen Transaktion sollte Null sein. Jede Übertragungsoperation aus dem obigen Beispiel wird durch ihren Eintrag in der Tabelle JOURNAL dargestellt
Der Eintrag in die BATCH-Tabelle dient der bequemen Dateneingabe. Es wird verwendet, um JOURNAL-Datensätze in bequemen Paketen zu gruppieren, z. B. eine Reihe von Überprüfungen für die Eingabe in das System, eine Art globaler Geschäftsprozess, wie das gleichzeitige Erheben von Zinsen für alle Benutzer usw.
In der Tabelle ACCOUNT werden Daten zu den Eigentümern von Werten im System gespeichert.
Die Tabelle ASSET TYPE enthält Informationen zu den im System verwendeten Wertetypen. Indem Sie dem Primärschlüssel der Tabelle POSTING einen Wertetyp hinzufügen, können Sie ein System erstellen, das mehrere Wertetypen gleichzeitig verarbeitet (z. B. die Verarbeitung mehrerer Währungen).
So könnte eine solche Datenbank für das obige Beispiel in der einfachsten Form aussehen:

Der Saldo der Spalte Betrag in der POSTING-Tabelle ist nach Abschluss einer Transaktion von JOURNAL immer Null (die Software sollte sicherstellen, dass keine Aufzeichnungen über unvollständige Transaktionen in der Datenbank vorhanden sind).
Die Summe der Operationen für das Kassenbuchkonto ergibt -190, was der Summe der Salden von Smith und Pattel mit dem entgegengesetzten Vorzeichen entspricht.
Um die Mehrwährungsoperation zu demonstrieren, wurde eine neue Art von Wert hinzugefügt. Wenn Smith 20 Pfund in Dollar zum Kurs von 1 gegen 1,5 tauschen möchte, wird die Transaktion wie folgt über das Kassenbuch abgewickelt:

Abrechnungszeiträume
Das Modell, das wir bekommen haben, sieht gut aus, aber in Wirklichkeit wird es unter hoher Last sehr schnell kaputt gehen, da wir nichts löschen können und gezwungen sind, die ständig steigende Anzahl von Datensätzen in POSTING zu wiederholen.
Die meisten Buchhaltungssysteme haben das Konzept eines Abrechnungszeitraums - normalerweise ein Monat, drei Monate oder ein Jahr. Ein derartiger Zeitraum legt geeignete Punkte für die Aufteilung des Datenstroms nahe. In der Regel ist das Jahresende, der Kalender oder die Finanzlage ein geeigneter Punkt.
Wir können der Tabelle POSTING und ihrem Primärschlüssel eine Spalte mit einem Punktkennzeichen hinzufügen, um die Daten in Gruppen zu unterteilen, die unabhängig voneinander verarbeitet werden können. Wenn im obigen Beispiel einige der Datensätze auf einen neuen Abrechnungszeitraum fallen, werden die Kontensalden wie folgt vorgetragen.
Zunächst würden die Salden der Vorperiode ausgeglichen.

Und dann würden sie in eine neue Zeit versetzt

Nach einer bestimmten Zeit können alle Datensätze des Zeitraums JAHR 1 an das Archiv gesendet und aus dem System gelöscht werden, ohne dass die Integrität verloren geht.
Transaktionsaggregation
Einige Vorgänge im Abrechnungssystem können viele oder sogar alle Benutzer gleichzeitig betreffen. Zum Beispiel Zinszahlungen an alle Benutzer in Form eines Teils ihres aktuellen Guthabens.
Solche Vorgänge können als Teil einer einzelnen Transaktion in der Tabelle JOURNAL verarbeitet werden, und Sie können alle Vorgänge aus dem Kassenbuch in einem gemeinsamen Datensatz in der Tabelle POSTING zusammenfassen (anstatt für jedes Konto einen eigenen Vorgang zu erstellen). Auf diese Weise können Sie alle oben genannten Abrechnungsregeln einhalten und gleichzeitig die Anzahl der Datensätze in der Datenbank halbieren. Mit diesem Ansatz sieht das Ende des Jahres in der Datenbank folgendermaßen aus:

Stapelverarbeitung
Die Stapelverarbeitung wird häufig verwendet, um die Dateneingabe in das Buchhaltungssystem zu vereinfachen.
In der Vergangenheit hat die Scheckverarbeitung so funktioniert. Der Buchhalter erhielt ein Paket mit zehn Schecks, die Nummer des Pakets und den Gesamtbetrag aller Schecks. In der ersten Phase werden Schecks in Form von "nicht autorisierten" Einträgen in das System eingegeben. In diesem Fall werden Menge und Gesamtmenge über die BATCH-Tabelle überprüft. Nur wenn sie mit dem korrekten Wert übereinstimmen, kann der Benutzer das Paket festschreiben. Danach wird das Paket an einen anderen Mitarbeiter gesendet, der es auf Gültigkeit überprüft und dann "autorisiert", wenn alles korrekt eingegeben wurde.
Dieser Vorgang wird als "Hersteller / Prüfer" bezeichnet und kann verwendet werden, um relevante Daten in das System einzugeben.
In diesem Fall sind "nicht autorisierte" Datensätze in einer von der Hauptmenge der doppelten Datensätze in der POSTING-Tabelle getrennten Tabelle korrekt. Sie können auch eine Reihe solcher Tabellen für verschiedene Geschäftsprozesse haben. Beispielsweise muss der Buchhalter bei Schecks, mit denen Geld in das System eingegeben oder aus dem System entnommen wird, nur ein Konto prüfen. Seit dem zweiten, Cash Book, sind solche Operationen immer implizit impliziert. In diesem Fall kann in der Tabelle CHECK nur eine Spalte mit dem Konto verwaltet werden, während in der hypothetischen Tabelle FUND TRANSFER zwei Spalten benötigt werden: "Absender" und "Empfänger".
Hier entsteht das grundsätzliche Missverständnis der Prinzipien der Doppelerfassung. Die meisten Menschen im normalen Leben stoßen nur auf einfache Geschäftsbücher aus Papier. Um beispielsweise in einem solchen Papierbuch die Finanzen eines bestimmten Interessenvereins zu erfassen, ist für jede Operation nur ein Eintrag erforderlich. Es gibt jedoch immer noch einen impliziten Doppeleintrag, da es immer ein implizites Kassenbuchkonto gibt (in diesem Fall ist dies der Club), da alle Kassenflüsse immer entweder eingegeben werden (Zahlung von Gebühren durch Teilnehmer) oder dem System Geld entnehmen (Ausgaben) Club).
Der zweite Grund für Missverständnisse ist, dass in persönlichen Kontoauszügen das auf dem Konto eingezahlte Geld als „Darlehen“ betrachtet wird, da eine Person im Wesentlichen Kredite an eine Bank vergibt, die ihr Geld erhält. Wenn diese Person sein Hauptbuch geführt hätte, wäre dieser Eintrag als "Lastschrift" verbucht worden - da die Bank dieses Geld ihrem Kunden schuldet. Dieses Geld wird dem "Zahlungssystem" des Nutzers entnommen und in das Bankensystem eingegeben.
Software-Architektur
Software, die ein solches Double-Entry-Accounting-System implementiert, wird am besten unter Verwendung von OOP und eines mehrstufigen Ansatzes entwickelt. Die Ebenen sind wie folgt:
- Externe Schnittstelle
- Geschäftslogik
- Arbeite mit einer DB
Natürlich hängt die Architektur des Systems davon ab, was genau dieses System tun soll. Wir können jedoch davon ausgehen, dass die folgenden Module enthalten sind:
PostEntry: Ein Modul, das die Erstellung von Doppeleinträgen in der POSTING-Tabelle steuert. Er ist verantwortlich für das Einfügen von Datensätzen, die Zuweisung von IDs und Zeitstempeln. Das Modul kann keine Datensätze löschen oder ändern, und kein anderes Modul sollte diese Datensätze löschen oder ändern, mit Ausnahme des möglichen Löschens alter archivierter Datensätze für bereits irrelevante Abrechnungszeiträume. Die POSTING-Tabelle sollte für alle anderen Module schreibgeschützt sein.
MakeDeposit, MakeWithdrawal, MakeTransfer: Diese Module implementieren die grundlegende Geschäftslogik für Überweisungsvorgänge. Sie verwenden das PostEntry-Modul, um ihre Ergebnisse in die Datenbank einzugeben.
ChequeEntry und ChequeAuthorisation, ReceiveBACS ( Hinweis: BACS ist ein Interbank-Zahlungssystem ): Diese Module verbinden das System mit der Außenwelt und bieten eine übergeordnete Schnittstelle. Sie werden die Business-Layer-Module verwenden, um ihre Funktionen auszuführen. In diesem Fall können Sie die korrekte Verarbeitung unabhängig von der Dateneingabemethode gewährleisten, da sowohl ChequeEntry als auch ReceiveBACS dasselbe MakeDeposit verarbeiten
Diese Methode zum Trennen von Schichten kann je nach Komplexität des Systems und der gewünschten Reinheit der Anwendung der Prinzipien des Objektdesigns mehr oder weniger angewendet werden. Gleichzeitig kann es beispielsweise sinnvoll sein, dem Berichterstellungsmodul (z. B. TestTrialBalance) den direkten Zugriff auf die Datenbank von der Schnittstellenebene aus zu ermöglichen, anstatt Zwischenmodule auf Geschäfts- und Datenbankebene zu erstellen.

Probebilanz
"Trial Balance" - die Hauptmethode zur Überprüfung der Integrität des Rechnungsführungssystems. Wenn alle Einträge nach den Doppeleintragsregeln in das System eingegeben wurden und keine Fehler aufgetreten sind, sollte die Summe aller Einträge Null sein. Die Wahrscheinlichkeit, dass sich mehrere separate Fehler addieren und auf einer ungültigen Basis eine Gesamtzahl von Null ergeben, ist normalerweise so gering, dass sie vernachlässigt werden.
Der beste Weg, dies zu überprüfen, ist eine gleichmäßige Bewegung von der oberen zur unteren Ebene. Schecks sind in dieser Reihenfolge sinnvoll:
- Die Summe aller Werte in der Spalte POSTING.Amount
Wenn ein Fehler gefunden wird (der Wert ist nicht Null), dann: - Die Summe aller POSTING.Amount-Werte, die jedoch für verschiedene Werttypen und Abrechnungszeiträume separat berechnet werden
Zu diesem Zeitpunkt sollte klarer werden, in welchem Teil des Systems ein Fehler aufgetreten ist. - Einzelne Operationen in der Tabelle JOURNAL prüfen. Da die Summe aller POSTING.Accounts in jeder Transaktion aus der JOURNAL-Tabelle ebenfalls Null ergeben sollte, können Sie die spezifische problematische Transaktion verfolgen.
JOURNAL Beitragstypen
Die Tabelle JOURNAL enthält eine einfache Darstellung von Entitäten, die sich jedoch häufig als komplexer und in verschiedene Beziehungen verwickelt erweisen.
Manchmal ist es sinnvoll, eine Tabelle in mehrere zu teilen. Beispielsweise können bei MATERIALIZED und DEMATERIALIZED, die möglicherweise einen anderen Satz von Spalten haben, für Materialentitäten Daten zu ihrem aktuellen Standort erforderlich sein.
In einer Tabelle können auch verschiedene Subtypen von Werten gespeichert werden, z. B. Währung oder Wertpapiere. Jeder Subtyp kann seine eigenen Eigenschaften und Attribute haben.
Entitäten, die sowohl Unter- als auch Supertypen enthalten, können auf vier Arten in der Datenbank organisiert werden (dies ist für jede Datenbank eine ziemlich übliche Situation):
- Eine gemeinsame große Tabelle mit vielen optionalen Spalten für Untertypattribute
- Separate Tabelle für jeden Untertyp mit Duplizierung aller gemeinsamen Spalten
- Trennen Sie Entitäten, damit der Supertyp in einer separaten Tabelle gespeichert und mit anderen Tabellen verknüpft wird, die nur untertypspezifische Spalten enthalten
- Wie in 3, jedoch mit Duplikation von Supertypspalten in Subtyp-Tabellen
Jede der vier Optionen hat ihre Vor- und Nachteile. Aus Sicht der doppelten Eingabe ist es nützlich, eine gemeinsame Tabelle für POSTING-Einträge zu haben. Option 1 eignet sich besser für ein einfaches Abrechnungssystem (wie in den Beispielen in diesem Artikel, in denen der einzige Unterschied in den Wertetypen durch die Spalte JOURNAL.Type bestimmt wird). Option 3 ist wahrscheinlich besser für komplexe Systeme geeignet, die mit einem breiten Bereich sehr unterschiedlicher Werte arbeiten.