Kontostand Dashboard

Wäre es nicht interessant den eigenen Kontostand zu beobachten? Somit zu erfahren, ob wirklich Geld im Monat übrig bleibt oder zu viel ausgegeben wurde? Diese Idee kam mir vor einiger Zeit. In der Banking-App sehe ich nur den Verlauf meiner Ausgaben und Einnahmen. Allerdings nicht, ob am Ende eines Monats Geld übrig geblieben ist. Erschwerend kommt noch hinzu, dass ich viel mit dem Geld jongliere und auf mehrere Konten verteile. Das führt dazu, dass die grafischen Anzeigen der Bank wirres Zeug anzeigen. Um diesen Problem Herr zu werden, habe ich es mir zur Aufgabe gemacht, jeden Monat zum 1. meine Salden abzufragen. Die Ergebnisse tragen ich dann in eine Datenbank-Tabelle ein.

Da das eigene Einkommen auch mit dazu beiträgt, habe ich es ebenfalls mit ins Projekt reingenommen.

Datenbank Design

In der Datenbank, ich nenne sie Balance, gibt es insgesamt 6 Tabellen, mehrere Unique Key, Primary Key, Foreign Keys und Triggers. In BAL_BANKACCOUNT, BAL_COMPANY, BAL_LOCATION, BAL_INSTITUTION werden Stammdaten eingetragen und dienen als Fremdschlüssel für andere Tabellen. BAL_INCOME und BAL_BALANCE enthalten die gewünschten Informationen, die später ausgelesen werden.

Eigentlich wollte ich z.B. in BAL_INCOME einen Primärschlüssel aus COMPANY_ID, MONTH und YEAR, um so Doppeleinträge zu verhindern. Leider sorgt Django zu einer Limitierung und ich habe ID als primären Schlüssel definieren müssen. Von Django möchte ich das Admin-Interface benutzen, wie ich es auch schon zuvor getan habe. Django erfordert genau einen Primärschlüssel und ein Verbund aus Primärschlüsseln sorgt für Fehler, daher ist ID der alleinige Primärschlüssel und MONTH, YEAR und BNR sind als unique deklariert worden.

BAL_BANKACCOUNTAlle Bank Konten werden hier eingetragen
BAL_COMPANYAlle Firmen werden hier eingetragen
BAL_LOCATIONAlle Orte werden hier eingetragen
BAL_INSTITUTIONAlle Bank Institutionen werden hier eingetragen
BAL_INCOMEDas Einkommen wird hier eingetragen
BAL_BALANCEDie Salden werden hier eingetragen

Eine Sache muss hier aber noch erwähnt werden und das ist die Prozedur. Würde ich jetzt eine Result von BAL_BALANCE zurückbekommen, so wären die Bankkonten im Result aufzufinden.

IDMONTHYEARBNRBALANCEA.._BALANCEU.._BALANCE
112021Konto1300030000
212021Konto220000150005000
312021Konto310000100000
412021Konto450000500000
522021Konto1350035000

Zur Weiterverarbeitung mit Pandas wollte ich diese allerdings als Spaltennamen einsetzen. Zusätzlich wollte ich es vermeiden, immer und immer wieder neue Bankkonten als neue Spalte hinzufügen zu müssen.

CREATE DEFINER=`username`@`%` PROCEDURE `P_BAL_BALANCE`(IN START int, IN END int)
BEGIN
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'ifnull(SUM(case when BNR = ''',
      BNR,
      ''' then BALANCE end),0) AS `',
      BNR, '`'
    )
  ) INTO @sql
FROM
  Balance.BAL_BALANCE ;
SET @sql = CONCAT('SELECT YEAR,MONTH, ', @sql, ' 
                  FROM Balance.BAL_BALANCE where YEAR >= ', START ,' and YEAR <= ', END ,'
GROUP BY YEAR,MONTH');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END

Die Prozedur nimmt sich die BNRs und verwendet diese als Spaltennamen und erwartet zusätzlich noch ein Start- sowie Endjahr, von dem es die Results bereitstellen soll. Der Aufruf ist dahingehend einfach:

call Balance.P_BAL_BALANCE(2019, 2021);
MONTHYEARKONTO1KONTO2KONTO3KONTO4
120213000200001000050000
220213500

Noch zu erwähnen wäre der Trigger in BAL_INCOME, denn der berechnet die gesetzlichen Abgaben anhand der Daten, die eingegeben worden sind.

CREATE DEFINER=`username`@`%` TRIGGER `Balance`.`BAL_INCOME_BEFORE_INSERT` BEFORE INSERT ON `BAL_INCOME` FOR EACH ROW
BEGIN
set NEW.STATUTORY_LEVIES = NEW.INCOME - NEW.NET_INCOME;
END

Kontostand in Python Dash

Die Erstellung des Backends ist somit erledigt. Den Kontostand und somit die Visualisierung stelle ich mit Plotly/Dash grafisch her. Es würde den Rahmen sprengen den kompletten Code hier zu veröffentlichen, daher habe ich ihn auf github hochgeladen. Wer daran interessiert ist, findet ihn hier: https://github.com/stevieWoW/balance.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert