Wir alle kennen das Bild von einem Engelchen mit einer Harfe und Teufelchen mit einem Dreizack, die auf unseren Schultern sitzen und uns bei Entscheidungen in bestimmte Richtungen zu lenken versuchen. Auf den Schultern von uns Wirtschaftsinformatikern liegt oft doppelte Last, denn da machen sich zwei weitere Akteure breit.

Während auf der einen Schulter lässig ein Kapuzenpulli tragender Nerd mit einem 23-Tage Bart und einer dampfenden Tasse Kaffee hockt, nimmt auf der anderen Schulter ein adrett gekleideter Erbsenzähler mit Seitenscheitel und einem Aktenkoffer Platz. Wie man sich gut vorstellen kann, sehen die beiden die Welt mit absolut unterschiedlichen Augen. Die eine Seite würde am liebsten alles selbst programmieren und eine Anwendung, die nicht aus seiner Feder stammt, nicht mal mit einer Kneifzange anfassen. Die andere Seite brabbelt unentwegt von Projektplänen, Break-Even-Analysen und Kostenreduzierungen.

Bei einem Kundenauftrag sind beide Seiten wichtig – es geht ja darum, eine vernünftige Qualität zu liefern und dabei die Kosten nicht ausufern zu lassen. Bei einem privaten Projekt, wie dem, um den es in diesem Beitrag geht, ist es anders. Der Termindruck ist nicht da und der Kostengesichtspunkt ist eher zweitrangig völlig egal, sodass ich mich darauf freuen kann, dem OverEngineering zu frönen und die Anwendung hier und da mit sprichwörtlichen goldenen Wasserhähnen und Marmorböden auszustatten. Doch die Rechnung habe ich ohne den Erbsenzähler auf der Schulter gemacht, der seine Nase immer wieder in die IT-Angelegenheiten steckt und sowohl die Entwicklung der Anwendung als auch den Lesefluss dieses Beitrags unterbricht. Doch genug der Vorrede – legen wir mit der Implementierung der Anwendung zur Wohnungsverwaltung und Nebenkostenabrechnung los und versuchen dabei, das Gezanke von der Schulter auszublenden.

Die kaufmännische Verwaltung meiner beider Wohnungen, wozu unter anderem auch die Erstellung von Betriebskostenabrechnungen gehört, habe ich bislang mit Hilfe von einzelnen Exceltabellen erledigt, die ich kurz nach dem Erwerb der ersten Wohnung erstellt habe. Es sollte damals nur eine vorübergehende Lösung sein (wir alle wissen aber, wie langlebig solche Lösungen sein können), weswegen ich in deren Weiterentwicklung kaum Zeit investiert habe. So blieben die Exceltabellen aus dem Gesichtspunkt der Automatisierung auf dem Steinzeitniveau.

Jeden Herbst, wenn ich die Post von meiner Hausverwaltung in den Händen hielt, dämmerte’s bei mir wieder, dass ich eigentlich eine vernünftige Anwendung für die Wohnungsverwaltung implementieren wollte. Tja, wieder den Termin verpasst, also musste ich für ein weiteres Jahr die Nebenkostenabrechnungen mit einem Excelweitwurf, Word und viel Copy-and-Paste erstellen.

Letztes Jahr war es endlich soweit, dass ich mit der Umsetzung der neuen Anwendung begonnen habe, die meine prähistorische Exceltabellenlandschaft ablösen sollte. Als Technologie habe ich mich, wie bei meinem letzten eigenen Projekt „Rechnungsprogramm„, wieder für Microsoft Access entschieden. Selbst so ein einfaches Datenbankmanagementsystem (auch wenn böse Zunge behaupten, es sei kein richtiges DBMS) bringt schon von Haus aus Funktionalitäten mit, die Excel nicht hat (denn dafür wurde es auch nicht entwickelt) und die man für eine vernünftige Datenhaltung benötigt:

  • Möglichkeit, Daten normalisiert und redundanzarm abzulegen
  • Referenzielle Integrität für eine bessere Datenqualität
  • transaktionsbasierte Datenverarbeitung
  • einfache, aber dennoch mächtige Abfragen mit SQL

Die neue Anwendung soll erstmal meine wichtigsten (nicht alle) Prozesse rund um die Wohneinheitenverwaltung auf eine einheitliche technische Basis stellen und vor allem den Prozess der Erstellung von Nebenkostenabrechnungen soweit es geht automatisieren.

In den Kapiteln, die nun folgen, greife ich einige Aspekte der Anwendung auf und beschreibe deren technischen und fachlichen Besonderheiten.

Wohnungskauf

Während in der realen Welt ein Wohnungskauf, sowohl emotional als auch vom Betrag her, für mich ein Highlight darstellt, ist die datentechnische Abbildung eines Wohnungskaufs in der Anwendung ziemlich unspektakulär und erstreckt sich über lediglich 3 Tabellen:

In der Tabelle tblWEG werden grundlegende Daten zu Wohnungseigentümergemeinschaften (WEG) abgelegt:

  • WEG-Bezeichnung (dient nur der Anzeige in der Anwendung)
  • Anzahl Wohneinheiten (wird für Nebenkostenaufteilung benötigt)
  • Anzahl Miteigentumsanteile (wird für Nebenkostenaufteilung benötigt)
  • Fremdschlüssel auf die Tabelle tblAnschriften

Ganz korrekt ist die direkte Referenz von der WEG auf die Tabelle mit den Anschriften nicht. Denn es kann durchaus größere WEG’s geben, die aus mehreren Häusern bestehen und demzufolge auch mehrere Hausnummern haben. Sollte ich mal eine Wohnung in so einer großen WEG erwerben, muss das Datenmodell angepasst und eine zusätzliche Ebene für Häuser integriert werden.

Zur nächsten Tabelle namens tblAnschriften gibt’s nicht wirklich was zu sagen – da dürfte klar sein, welche Daten dort abgelegt sind.

Wohnungen werden in der Tabelle tblWohnungen verwaltet. Jede Wohnung gehört zu einer bestimmten WEG und referenziert mit Hilfe eines Fremdschlüssels darauf. Darüber hinaus liegen in dieser Tabelle die ganzen kauftechnischen Grunddaten, beispielsweise:

  • Kaufpreis
  • Notarkosten
  • Grunderwerbsteuer
  • Maklergebühren
  • Kaufdatum

Wohnungstechnische Daten dürfen in der Tabelle natürlich auch nicht fehlen:

  • Wohnungsnummer
  • Wohnungsgröße
  • Anzahl der Zimmer
  • Stockwerk
  • Miteigentumsanteil

Vermietung

Die datentechnische Darstellung einer Vermietung ist um einiges komplexer als die des Wohnungskaufs. Der Dreh- und Angelpunkt ist dabei die Tabelle tblMietverhaeltnisse. Jedes Mietverhältnis wird durch einen Datensatz auf der oben genannten Tabelle abgebildet. Mit Hilfe eines Fremdschlüssels (Richtung Tabelle tblWohnungen) wird eine Beziehung zur Wohnung, in der sich das Mietverhältnis abspielt, hergestellt.

Die Dauer des Mietverhältnisses ergibt sich aus den Attributen MietverhaeltnisGueltigVon und MietverhaeltnisGueltigBis. Diese Datumsangaben sind besonders für die spätere Aufteilung von umlagefähigen Nebenkosten im Rahmen der Nebenkostenabrechnung von Bedeutung. Ebenso wird im Mietverhältnis-Datensatz gespeichert, ob und wenn ja, dann wann und von wem das Mietverhältnis gekündigt wurde.

Ein wesentlicher Punkt von jedem Mietverhältnis ist natürlich die Höhe der Kaltmiete und der Nebenkostenvorauszahlungen. Da sich beide Beträge im Laufe eines Mietverhältnisses ändern können, sind sie in separaten Tabellen tblMieten und tblNebenkostenvorauszahlungen ausgelagert und referenzieren mit Hilfe eines Fremdschlüssels auf das konkrete Mietverhältnis auf der Tabelle tblMietverhaeltnisse. Durch die beiden Attribute GueltigVon und GueltigBis wird die Historie der Beträge lückenlos abgebildet.

Für die Zuordnung von Mietern zu Mietverhältnissen ist die Tabelle tblMieterMietverhaeltnis zuständig, die eine M:N-Verknüpfung zwischen den Tabellen tblMietverhaeltnisse und tblPersonen schafft. Schließlich kann ein Mietverhältnis mehrere Mieter haben. Dies wäre natürlich problemlos mit einer 1:N-Beziehung abbildbar. Ein Problem hätte ich allerdings, wenn ein und der selbe Mieter im Laufe der Zeit mehrmals ein – und ausziehen, sprich mehrere Mietverhältnisse haben würde. Auch wenn diese Konstellation recht selten ist, habe ich sie durch die M:N-Variante im Datenmodell ermöglicht, zumal der Mehraufwand nur marginal ist.

Eine weitere M:N-Tabelle ist die tblMietverhaeltnisKonten, die Verknüpfungen zwischen Mietverhältnissen und Girokonten verwaltet. Ein Mietverhältnis kann im Laufe der Zeit mehrere Mieteingangskonten haben, die sich beispielsweise durch den Bankwechsel ergeben. Da ich für jede Wohnung jeweils ein separates Mieteingangskonto führe, hat ein Konto im Laufe der Zeit natürlich mehrere Mietverhältnisse.

Zahlungs- und Forderungsmanagement

Das Modul, das sich hinter dieser etwas hochtrabend anmutenden Kapitelüberschrift verbirgt, ist wieder etwas komplexer als das vorherige und erfüllt mehrere wichtige Zwecke in der Wohnungsverwaltung.

Verwaltung von Kontoumsätzen

Der Import von Kontoumsätzen stellt die elementare Datengrundlage für die Anwendung dar und erfolgte in den ersten Programmversionen mit Hilfe eines Dialogs, in dem ich die zu importierenden CAMT-Kontoauszugsdateien ausgewählt habe. Mittlerweile geschieht dies automatisch – die Anwendung „schaut“ beim Start in meinem Cloudverzeichnis für elektronische Kontoauszüge nach und importiert alle darin befindlichen und bislang nicht verarbeiteten XML-Dateien. Dabei wird der Inhalt der Dateien automatisch gegen die bereits importierten Kontoumsätze abgeglichen, um mehrfachen Import zu unterbinden. Hier musste ich leider feststellen, dass die Bank (die mit dem blauen D), bei der ich meine Miet- und Kautionskonten unterhalte, in CAMT-Kontoauszugsdateien ein so wichtiges Attribut wie AcctSvcrRef gar nicht befüllt. Es handelt sich dabei um eine Zahlungsreferenz, quasi ein „Fingerabdruck“, der jeden Kontoumsatz eindeutig identifiziert. Ich hab da so meinen Verdacht, dass es dem Rotstift eines Controllers zum Opfer gefallen sein könnte. Aus dem Grund waren ein paar zusätzliche programmiertechnische Klimmzüge nötig, um sicherzustellen, dass keine Zahlung mehrfach importiert wird. Kürzlich hab ich allerdings festgestellt, dass bei den Kontoumsätzen, die ab dem Dezember 2022 entstanden sind, dieses Attribut befüllt wird – wer weiß, vielleicht hat jemand die Bank darauf angesprochen – ich kann ja schließlich nicht wirklich der einzige gewesen sein, der an korrekter Befüllung dieses Attributes interessiert war.

Sind die Umsätze aus den ganzen Konten importiert, liegen sie ab da in der Tabelle tblKontobewegungen zentral vor, was dann die Recherche nach Umsätzen deutlich vereinfacht.

Kategorisierung und SOLL-IST-Abgleich

Doch so gut es auch ist, alle Kontoumsätze im Zugriff zu haben, lassen sie in ihrer Rohform keinen Rückschluss darauf zu, wie groß im jeweiligen Jahr beispielweise die Zinslast war, wie viel der Mieter an Nebenkostenvorauszahlungen bezahlt hat, wie hoch die Mieteinnahmen waren oder wie viel insgesamt an Handwerkerleistungen angefallen war. Ohne diese Kumulierungen sagen die Einzelumsätze für sich genommen auch nichts darüber aus, ob die Wohnungen einen Überschuss erzielt haben oder eher Verlustbringer waren. Ebenso wenig ist anhand der Einzelumsätze maschinell feststellbar, ob sie in der richtigen Höhe ein- oder abgegangen sind.

Für die Lösung dieser beiden Aufgaben habe ich mich für das Konzept der Forderungen entschieden. Eine Forderung ist in meiner Anwendung eine Zahlungsverpflichtung, die eine bestimmte Höhe und ein bestimmtes Fälligkeitsdatum hat. Ebenso hat jede Forderung eine Forderungsart (beispielsweise Kaltmiete, Nebenkostenvorauszahlung oder Hausgeld), die sie näher beschreibt und kategorisiert.

Der BWLer auf der Schulter wird beim Wort „Forderung“ plötzlich hellhörig und schaltet gleich den Klugscheißermodus an: „Der Begriff Forderung ist in diesem Kontext aber nicht ganz korrekt. Während Kaltmieten und Nebenkostenvorauszahlungen für den Wohnungseigentümer tatsächlich Forderungen darstellen, die er den Mietern gegenüber hat, handelt es sich beim Hausgeld oder bei Zinszahlungen um die Verbindlichkeiten, die man als Wohnungseigentümer an die Hausverwaltung bzw. die Bank zu begleichen hat. Diese wiederum fungieren aus der Sicht der Hausverwaltung und der Bank als Forderungen.

Der ITler auf der Schulter mit einem deutlich hörbar genervten Seufzen: „Alter… Wollen wir wirklich buchhalterische Haarspalterei betreiben? Es geht dabei doch nur darum, einen verständlichen Oberbegriff für das Ganze zu finden. Schau lieber, wie ich es umgesetzt habe.“

ITler: „Während ein Kontoumsatz den IST-Zustand repräsentiert (denn er ist tatsächlich ein- oder abgegangen oder eben gänzlich ausgeblieben), spiegelt eine Forderung den SOLL-Zustand wider. Durch den Abgleich und entsprechende Verknüpfung von Kontoumsätzen und Forderungen ist es möglich, sowohl den konkreten Umsatz zu kategorisieren als auch festzustellen, ob der Kontoumsatz in richtiger Höhe vorliegt.“

BWLer: „Und was passiert beim Mieteingang, der ja als Gesamtzahlung auf dem Konto eingeht, aber eigentlich aus der Kaltmiete und der Vorauszahlung besteht? Lässt sich die Konstellation auch abbilden?

ITler: „Freilich. Durch die M:N-Verknüpfung, ist es möglich, dass eine Zahlung mehrere Forderungen begleicht. Ebenso ist es möglich, dass eine Forderung durch mehrere Zahlungen beglichen wird.“

BWLer: „Prima, das klingt gut. Eins will ich noch wissen. Wer soll denn die Sollstellungen der ganzen Forderungen in der Anwendung vornehmen? Ich hoffe, die Aufgabe bleibt nicht bei mir hängen.

ITler: „Entspann dich. Das soll zum überwiegenden Teil automatisch geschehen. Das erkläre ich gleich.“

Ausschnitt aus dem Datenmodell für die Forderungsverwaltung und Zuordnung zu Kontopositionen

Generierung von Forderungen

Je nach Konstellation haben wir mit unterschiedlichen Forderungstypen zu tun, die auch auf unterschiedliche Art und Weise generiert werden.

regelmäßige Forderungen mit prognostizierbaren Beträgen

Die Forderungen von diesem Typ sind mir die liebsten, denn deren Anlage lässt sich komplett automatisieren. Dazu gehören Forderungen, die monatlich anfallen und deren Höhe entweder vertraglich (Kaltmieten), durch Vereinbarungen (Nebenkostenvorauszahlungen oder Hausgeldzahlungen) bzw. durch Blut (Finanzierungen) festgelegt ist. Die Beträge liegen lückenlos historisiert auf Tabellen in der Anwendung vor, sodass deren Höhe zu jedem Stichdatum ermittelbar ist.

  • tblMieten
  • tblNebenkostenvorauszahlungen
  • tblHausgelder
  • tblKreditvertraege

Die automatische Generierung dieses Forderungstyps wird bei jedem Start der Access-Anwendung durch eine Sub-Routine durchgeführt, die alle relevanten Mietverhältnisse durchläuft. Dabei wird ermittelt, ob für das jeweilige Mietverhältnis alle oben aufgeführten Forderungen für alle aktiven Monate angelegt sind. Ist es nicht der Fall, werden die noch fehlenden Forderungen entsprechend generiert.

situationsbedingte Forderungen mit prognostizierbaren Beträgen

Die Forderungen von diesem Typ haben auch einen maschinell ermittelbaren Betrag, fallen aber nicht monatlich, sondern nur situationsbedingt an. Aus diesem Grund werden die nicht durch eine Sub-Routine, die den Gesamtbestand durchsucht, sondern durch den jeweiligen fachlichen Prozess angelegt.

Kautionen sind ein gutes Beispiel für diesen Forderungstyp. Wenn ich in der Wohnungsverwaltung ein neues Mietverhältnis erfasse, hinterlege ich dabei, wie hoch die Kaution sein soll (1-3 Monatskaltmieten). Beim Speichern wird (als einer der Prozesse) eine Kautionsforderung zum Beginn des Mietverhältnisses mit dem entsprechenden, aus der Kaltmiete errechneten, Betrag automatisch generiert.

Genau verhält es sich mit Forderungen aus Nebenkostenabrechnungen. Wenn ich die Nebenkostenabrechnung eines Jahres freigebe, dann werden für alle Mietverhältnisse meiner Wohnungen aus der entsprechenden Wohnungseigentümergemeinschaft Nachzahlungs- bzw.. Erstattungsforderungen mit dem jeweiligen Betrag und der bestimmten Fälligkeit (Erstattungen werden zum Ende des aktuellen Monats, Nachzahlungen zum Ende des nächsten Monats fällig) generiert.

situationsbedingte Forderungen mit nicht prognostizierbaren Beträgen

Manche Forderungen lassen sich nicht vorab automatisch anlegen, weil nicht bekannt ist, ob, mit welchem Betrag und wann sie anfallen. Bestes Beispiel sind Handwerkerleistungen. Selbst, wenn es sich um eine geplante Maßnahme handelt, kann ich nur schätzen, was sie genau kosten wird. Eine geschätzte Forderung bringt mir da an der Stelle nicht viel. Wenn ich die Rechnung erhalten, sie beglichen und in die Anwendung mit der Kontoauszugsdatei importiert habe, „kennt“ die Anwendung zwar den genauen Betrag, „weiß“ aber nicht, welche Forderungsart hier zu generieren wäre. Da für die Verbuchung der Zahlung eine Forderung benötigt wird und diese vor der Verbuchung nicht vorliegt, wird in diesem Fall eine „künstliche“ Forderung unmittelbar im Verbuchungsprozess angelegt. Dazu gleich mehr im nächsten Kapitel.

Prozess der Verbuchung

regelmäßige Forderungen / situationsbedingte Forderungen mit prognostizierbaren Beträgen

Regelmäßig oder situationsbedingt anfallende Kontoumsätze, wie Mieteingang / Hausgeld oder Nebenkostenabrechnungsforderungen / Kautionen lassen sich in fast allen Fällen maschinell verbuchen. Dafür wird für jede noch offene Forderung geprüft, ob eine entsprechende Zahlung in der richtigen Höhe vorliegt und ob diese im zeitlichen Korridor befindet (3 Tage vor der Fälligkeit bis zu 7 Tagen nach der Fälligkeit).

Eine Ausnahme bildet hier der Kapitaldienst. Die Höhe der Annuität, die meine Bank und ich vereinbart haben, ist bekannt und jeden Monat gleich, sodass eine automatische Verbuchung eigentlich ein Kinderspiel wäre. Da mich jedoch die Aufteilung der Annuität in Zins- und Tilgungsanteil interessiert, ist die Sache etwas komplizierter.

Meine alte kreditgebende Bank (die mit dem roten S) bot da einen Superservice an, indem sie den Zins- und Tilgungsanteil in den Buchungstext jeder Abbuchung gepackt hat. Diese Informationen ließen sich ohne Probleme aus dem Buchungstext auslesen und so eine schöne und schlanke maschinelle Aufteilung realisieren. Doch bei der neuen kreditgebenden Bank (die mit dem weißen V) gibt’s sowas leider nicht. Schweren Herzens musste ich hier eine anderen Lösung realisieren. Die allgemeine Forderung vom Typ Kapitaldienst wird wie im Kapitel zuvor maschinell generiert. Für die Aufteilung in Zins und Tilgung markiere ich die Forderung und die dazugehörige Zahlung, woraufhin sich ein Aufteilungsformular öffnet (allerdings nur dann, wenn die Forderung vom Typ Kapitaldienst ist und der Forderungsbetrag mit dem Zahlungsbetrag übereinstimmt).

Dort trage ich entweder den Zins oder Tilgungsanteil ein (der jeweils andere Anteil wird aus der Gesamtforderung und dem eingetragenen Wert errechnet). Klicke ich auf speichern, passiert folgendes:

  • Zinsforderung mit dem Betrag aus dem Formular wird angelegt
  • Tilgungsforderung mit dem Betrag aus dem Formular wird angelegt
  • Verknüpfung der Zinsforderung zur Kontoabbuchung wird angelegt
  • Verknüpfung der Tilgungsforderung zur Kontoabbuchung wird angelegt
  • die allgemeine Gesamtforderung vom Typ Kapitaldienst wird gelöscht

situationsbedingte Forderungen mit nicht prognostizierbaren Beträgen

Wie im vorherigen Kapitel bereits erwähnt, kann für diesen Forderungstyp keine Forderung vor der Verbuchung angelegt werden, sondern wird während der Verbuchung generiert. Aus diesem Grund erfolgt die Verbuchung solcher Konstellationen immer manuell, was dann wie folgt abläuft:

Wenn ich im Verbuchungsformular eine Zahlung (beispielsweise von einem Handwerker) markiere, ohne dass dabei eine Forderung (denn es gibt ja keine) als Gegenposition markiert ist, geht ein spezielles Verbuchungsformular auf. Darin werden alle Forderungsarten angezeigt, die ich als direkt bebuchbar definiert habe.

Anschließend wähle ich dann die entsprechende Forderungsart, mit der ich die markierte Zahlung verbuchen möchte und klicke auf speichern. Erst zu diesem Zeitpunkt wird eine Forderung (mit dem gleichen Betrag und dem gleichen Datum wie die Zahlung) angelegt, die dann gleich mit der Zahlung über die Tabelle tblZuordnungenForderungUndKontoposition verknüpft wird.

Die Forderungen dieses Typs (neben Reparaturen gehören auch Modernisierungen, aber auch Grundsteuer und Niederschlagswasser dazu) haben noch die Besonderheit, dass sie nicht einem bestimmten Mietverhältnis, sondern immer einer konkreten Wohnung zuzuordnen sind. Dadurch dass ich für jede Wohnung ein separates Konto habe, auf das alle Einnahmen ein- und alle Ausgaben abfließen, erkennt der Verbuchungsprozess, von welchem Konto die Zahlung stammt und welcher Wohnung dieses Konto zugeordnet ist, sodass die Forderung gleich richtiger Wohnung automatisch zugewiesen wird.

Nebenkostenabrechnung

Diese Funktionalität ist das Herzstück der Datenbankanwendung und hat aufgrund seiner Komplexität mir den meisten Aufwand beschert.

Ausschmitt aus dem Datenmodell zur Definition von Umlageinformationen im Rahmen einer Nebenkostenabrechnung

Definition von Umlageinformationen

Schauen wir uns mal den entsprechenden Ausschnitt des Datenmodells an. Die zentrale Tabelle namens tblUmlageinformationen ist für die Speicherung aller Umlagedaten zuständig und besteht nahezu komplett aus Fremdschlüsselattributen. Sie beschreibt für eine konkrete Wohneigentümergemeinschaft (WEG), welcher Nebenkostenabrechnungsposten mit welchem Umlageschlüssel auf einzelne Mietverhältnisse aufgeteilt wird und für welchen Zeitraum diese Aufteilungsregel gilt. Die Referenz auf die WEG ist dabei wichtig, denn in unterschiedlichen WEG’s werden gleiche Nebenkostenabrechnungsposten oft auf unterschiedliche Art und Weise aufgeteilt. Ebenso ist der Gültigkeitszeitraum der Aufteilungsregel von Bedeutung, um Veränderungen im Umlageverfahren zeitlich voneinander abgrenzen zu können, was allerdings in den letzten 10 Jahren nur ein einziges Mal nötig war.

Frontend zur Definition von Umlageinformationen

Das Umlageverhältnis von jedem Umlageschlüssel wird im Datenmodell nicht direkt in Form eines dezimalen Wertes, sondern durch zwei Fremdschlüssel definiert. Beide referenzieren den jeweiligen Faktor auf der Tabelle tbUmlageverhaeltnisfaktor und repräsentieren so zum einen den Zähler, zum anderen den Nenner des Umlageverhältnisses. In meiner Anwendung gibt es zwei Arten von Faktoren:

  • einfache Faktoren: Sie zeichnen sich durch einen konkreten, nicht veränderbaren Wert aus. In der Regel sind es Werte, die nicht groß errechnet werden können oder müssen. Aktuell gibt es nur einen einzigen einfachen Faktor – er repräsentiert den Wert 1.
  • referenzierte Faktoren: Diese Faktoren zeichnen sich durch ihre Veränderlichkeit aus und treten als Platzhalter auf, die je nach Wohnung / WEG / Mietverhältnis unterschiedliche Werte annehmen können. Das mag auf den ersten Blick kompliziert erscheinen, hat aber den großen Vorteil, dass dadurch Faktoren allgemein definiert und von den konkreten Ausprägungen der einzelnen Wohnungen und Wohneigentumsgemeinschaften entkoppelt werden. So wird die Verwaltung von Umlageinformationen deutlich vereinfacht. Beispiele für solche Faktoren sind:
    • Wohnungsanzahl in der WEG
    • Miteigentumsanteil (MEA) der Wohnung
    • Miteigentumsanteil (MEA) der WEG
    • Mieteranzahl im Mietverhältnis
    • Anzahl der gemeldeten Personen in der WEG

Vielleicht wird der Vorteil der referenzierten Faktoren anhand eines konkreten Beispiels aus dem oberen Screenshot klarer. Die Nebenkostenposition „Gebäudeversicherung“ wird anhand der Miteigentumsanteile der jeweiligen Wohnung aufgeteilt. Nun es ist ja so, dass eine WEG in der Regel aus Wohnungen unterschiedlicher Größe besteht. Während in meiner WEG eine 37 qm Wohnung ein MEA-Verhältnis 37/1.000 hat, wartet eine 50 qm Wohnung mit dem Verhältnis von 50/1.000 auf. Um die Umlageinformationen für die Gebäudeversicherung (alle anderen Posten sind natürlich auch gemeint) nicht für jede Wohnung individuell hinterlegen zu müssen, wird stattdessen die Umlageinformation über die beiden referenzierten Faktoren (Platzhalter) definiert. Erst bei der tatsächlichen Aufteilung des WEG-Gesamtbetrages auf Wohnungen und Mietverhältnisse, werden die konkreten Faktoren für die jeweilige Wohnung und die jeweilige WEG ermittelt. Dazu gleich mehr im nächsten Kapitel.

Aufteilung von Nebenkosten

Da Hausverwaltungen die jährlichen Kostenaufstellungen nicht pro Mietverhältnis, sondern pro Wohnung ausweisen, ist es die Aufgabe des Eigentümers, die Kosten auf einzelne Mietverhältnisse korrekt aufzuteilen. Natürlich gibt’s bei den Kosten einige Ausnahmen, die uns Softwareentwicklern das Leben schwer machen Herausforderungen bescheren, an denen wir wachsen können. Bei der Entwicklung dieser Wohnungsverwaltung war es mir wichtig, dass vor allem die Aufteilung möglichst automatisch erfolgt.

Doch wie funktioniert es genau? Nun – zuerst müssen alle umlagefähigen Nebenkostenpositionen erfasst werden. Dafür navigiere ich in der Anwendung zur jeweiligen WEG und klicke dort auf das Jahr, welches ich abrechnen möchte und lande so im Erfassungsformular. Durch diese Vorauswahl werden ans Erfassungsformular die ID’s der WEG und des Abrechnungsjahres übertragen. Diese werden zum einen für die korrekte Zuordnung der Nebenkosten gebraucht. Zum anderen sind die beiden Schlüssel auch für die Ermittlung der korrekten Umlageinformationen erforderlich.

Im Formular wähle ich nacheinander alle Nebenkostenpositionen (zum Beispiel Gebäudeversicherung) aus und erfasse deren Gesamtkosten (zum Beispiel 1.684,18 €) auf WEG-Ebene. Hier stellt sich vielleicht die Frage, warum ich die Kosten auf WEG-Ebene eingebe und nicht gleich auf Wohnungsebene, wie sie mir von der Hausverwaltung geliefert werden. Nun – ich versuche einfach, unnötige und redundante Dateneingaben zu vermeiden. Aktuell habe ich zwei Wohnungen. Würde ich die Kosten auf Wohnungsebene übernehmen, müsste ich die händische Datenübernahme für beide Wohnungen separat machen. Würden zwei weitere Wohnungen dazukommen, würde ich insgesamt vier Datenübernahmen machen müssen, und zwar mit fast identischen Werten. Stattdessen habe ich mich entschieden, die Werte einmalig auf WEG-Ebene einzugeben und diese von der Anwendung gleich automatisch auf alle Wohnungen und Mietverhältnisse aufteilen zu lassen.

Die Auswahl einer Nebenkostenposition im Formular bewirkt, dass für diese Nebenkostenposition, für diese WEG und für dieses Abrechnungsjahr die jeweils geltende Umlageinformation automatisch ermittelt und ins Formular geladen wird. So sehe ich gleich, wie die konkrete Nebenkostenposition aufgeteilt wird. In diesem Fall ist der Umlageschlüssel die Miteigentumsanteile und das Umlageverhältnis lautet Miteigentumsanteile der Wohnung / Miteigentumsanteile der gesamten Miteigentümergemeinschaft.

Erfassung einer Nebenkostenposition im Frontend

Klicke ich auf „Speichern“, passiert folgendes:

1) Der erfasste Gesamtbetrag wird als solcher auf der Tabelle tblNebenkostenWEG abgelegt.

2) Anschließend wird im Hintergrund ermittelt, welche Wohnungen im abzurechnenden Jahr innerhalb der ausgewählten Wohneigentümergemeinschaft vermietet waren. All diese Wohnungen werden dabei nacheinander in einer Schleife durchlaufen. Als erstes werden aus dem Formular die für die Nebenkostenposition ermittelten FaktorenID’s für den Nenner und den Zähler des Umlageverhältnisses ausgelesen. Für die Abrechnung sind die FaktorenID’s natürlich nicht ausreichend – dafür sind die tatsächlichen Faktorausprägungen erforderlich. Wenn es sich dabei um einen einfachen Faktor handelt, dann wird in der Faktortabelle einfach sein Wert anhand der FaktorID nachgeschlagen und zurückgegeben. Wenn es allerdings um einen referenzierten Faktor handelt, dann ist die Ermittlung etwas aufwändiger. In unserem Beispiel ist der Zählerfaktor „MEA der Wohnung“ und der Nennerfaktor „MEA der WEG“. Diese werden anhand der MietverhältnisID ermittelt – denn jedes Mietverhältnis „weiß“, in welcher Wohnung es sich abspielt – so kann der Miteigentumsanteil der Wohnung (37 MEA) aus der Tabelle tblWohnungen ermittelt werden. Und jede Wohnung „weiß“, welcher WEG diese angehört, sodass auch die Anzahl der Wohneinheiten und in diesem Fall relevante Summe aller Miteigentumsanteile (1.000 MEA) aus der Tabelle tblWEG ausgelesen werden können.

Nach dem die genauen Faktoren bekannt sind, wird anhand des kompletten WEG-Betrages der Wohnungsanteil ermittelt, indem der Betrag mit dem Zählerfaktor multipliziert und durch den Nennerfaktor dividiert wird. 1.684,18 Euro x 37 / 1.000 = 62,31 €

Anhand dieses gerade errechneten Wohnungsbetrages kann der Mietverhältnisanteil ermittelt werden. Am einfachsten ist es natürlich, wenn die Wohnung im Abrechnungsjahr durchgängig im selben Mietverhältnis vermietet war. In diesem Fall wäre der Wohnungsanteil gleich dem Mietverhältnisanteil. Aus der Softwarentwicklungssicht ist es jedoch viel interessanter, wenn es innerhalb eines Jahres etwas mehr Bewegung in Form von Mieterwechsel und Leerstand gibt. Um korrekte Aufteilung in solchen Konstellationen sicherzustellen, wird für jedes Mietverhältnis seine Dauer in Tagen im abzurechenden Jahr ermittelt. Daraus ergeben sich dann entsprechende Aufteilungsfaktoren, um den eben ermittelten Wohnungsanteil exakt auf einzelne Mietverhältnisse aufzuteilen.

Springen wir mal in das Abrechnungsjahr 2022 rein. Es ist insofern ein gutes Beispieljahr, als dass ich in diesem Jahr einen unterjährigen Mieterwechsel und einen Leerstand hatte. Mein langjähriger Mieter hat die Wohnung berufsbedingt gekündigt. Um ihm entgegen zu kommen, habe ich seine Kündigungsfrist von drei auf einen Monat verkürzt, sodass wir zum 15.01.2022 die Wohnungsübergabe machen konnten. Im Jahr 2022 nutzte er die Wohnung also lediglich 15 Tage, sodass sein Anteil an den Nebenkosten 15/365 betrug. Mit Hilfe dieses Faktors ist sein Anteil an der Gebäudeversicherung wie folgt auszurechnen: 62,31 € * 15 / 365 = 2,56 €.

Anschließend stand die Wohnung im Zeitraum 16. 01.- 31.01. leer, da ich an der einen oder anderen Stelle Kleinigkeiten ausgebessert habe. Der Leerstand dauerte insgesamt 15 Tage an, sodass mein Anteil an den Nebenkosten 15/365 beträgt. In Euro ausgedrückt ist es: 62,31 € * 15 / 365 = 2,56 €.

Anschließend habe ich die Wohnung zum 01.02.2022 wieder vermietet. Dieser Mieter bewohnt die Wohnung nach wie vor, sodass für das Jahr 2022 insgesamt 334 Tage auf sein Mietverhältnis entfallen (01.02.- 31.12.). Somit liegt sein Anteil an den Nebenkosten 334 /365, was seinen Anteil wie folgt aussehen lässt: 62,31 € * 334 / 365 = 57,02 €.

Die so aufgeteilten Beträge werden dann in der Tabelle tblNebenkostenMietverhaeltnis mit Referenz auf das Mietverhältnis und den dazu gehörigen Abrechnungsposten abgelegt.

Sieht doch voll einfach aus, stimmts? Nicht ganz… Denn es gibt, wie oben bereits erwähnt, Ausnahmen, beispielsweise in Form von verbrauchsabhängigen Nebenkostenpositionen (Heiz- und Wasserkosten), für deren Aufteilung der WEG-weiten Kosten auf einzelne Wohnungen und auf einzelne Mietverhältnisse mir entsprechende Datengrundlage fehlt. Die Verbräuche werden daher vom Ablesedienstleister (Ista / Techem und so) ermittelt und gleich auf Mitverhältnisse aufgeteilt. Hierzu habe ich im Formular eine entsprechende Regel hineinkonfiguriert. Diese Regel besagt, dass wenn ein Abrechnungsposten den Umlageschlüssel „Verbrauch“ aufweist (selbstverständlich findet die Prüfung mit Hilfe eines Enums statt), die Aufteilung nicht automatisch erfolgt. Stattdessen geht in diesem Fall ein weiteres Formular auf, welches alle in dieser WEG in diesem Abrechnungsjahr stattgefundenen Mietverhältnisse auflistet, denen ich dann die gemeldeten und auf Mietverhältnisse aufgeteilten Beträge zuweise.

Jetzt müsste es doch genug mit Ausnahmen sein, oder? Leider nicht ganz… Es gibt noch eine weitere Besonderheit – nämlich die Grundsteuer und das Niederschlagswasser. Diese beiden umlagefähigen Posten werden weder über die Hausverwaltung noch über einen Abrechnungsdienstleister abgerechnet. Stattdessen erhalte ich pro Wohnung entsprechende Rechnungen von der Stadt (die WEG-Gesamtkosten sind mir da leider nicht bekannt – die kennt tatsächlich nur die Stadt selbst).

BWLer: „Nutzen wir doch einfach das Formular, das wir schon für die manuelle Pflege der Heizkosten realisiert haben und lassen anstatt von Mietverhältnissen dort Wohnungen ausgeben, denen wir dann die Beträge zuweisen.

ITler: „Gute Idee, das Formular wieder zu verwenden. Solche Nebenkosten kann ich am Umlageschlüssel „Bescheid der Stadt“ erkennen und so die Aufstellung aller Wohnungen anstoßen. Ich schaue, ob ich eine Lösung auf die Beine stellen kann, um die Gesamtkosten solcher Nebenkostenpositionen automatisch zu ermitteln und dort anzeigen zu lassen.

BWLer: „Lass mal, das lohnt sich nicht. Wir würden, wenn es hochkommt, 3 Minuten pro Jahr einsparen. Außerdem tragen wir ja die Heizkosten auch manuell ein.“

ITler: „Bei den Heizkosten gab es wirklich keine andere Möglichkeit, als die Werte pro Mietverhältnis manuell vorzugeben, weil nur der Ablesedienstleister die Rohdaten hat. Die können wir uns ja nicht aus den Fingern saugen. Bei den Nebenkostenpositionen, die vom Girokonto abgebucht werden, ist es ja was ganz anderes. Schließlich hat die Wohnungsverwaltungsanwendung alle Kontoumsätze bereits im Bauch. Ich trage doch händisch keine Werte ein, die sich automatisiert ermitteln lassen.

BWLer: „Klar, die Anwendung hat die Daten im Bauch, aber wie willst du denn solchen Nebenkostenpositionen beibringen, aus welchen einzelnen Kontoabbuchungen sie sich zusammensetzen? Die Umlageinformationen und Kontoumsätze sind separate Datentöpfe. Lass uns lieber aufs Wesentliche konzentrieren. Die Anwendung muss fertig sein, bevor die Post von der Hausverwaltung wieder eintrudelt. Außerdem – warum seid ihr ITler so versessen darauf, alles zu automatisieren?

ITler: „Ganz einfach – es geht um die Herausforderung. Darum, Lösungsansätze zu entwickeln, sie zu verproben, mit ein paar davon vielleicht auf die Nase zu fallen, aber am Ende eine schwierige Aufgabe zu meistern. Eben kreativ zu sein. Wenn du im Rechnungswesen zu viel Kreativität an den Tag legst, wird es vermutlich ungern gesehen, oder? In der IT ist es anders. Lass mal die Datenverknüpfung meine Sorge sein, ich hab schon eine Umsetzungsidee. Hol dir mal einen Kaffee – eher du zurück bist, habe ich die Lösung.

Der BWLer murmelt leise beim Rausgehen: „eingebildeter Nerd….“

Ich grinse den ITler an: „Gut geflunkert! Du weißt aber schon, dass er seinen Kaffee immer beim Starbacks um die Ecke holt und vermutlich in 5 Minuten wieder bei dir auf der Matte steht? Ich sehe zu, dass ich dir die Nervensäge für 2 Stunden vom Hals halte. Das dürfte für die Konzeption, Umsetzung und Tests reichen, oder?

ITler grinsend: „Ja, mit 2 Stunden komme ich gut zurecht, danke dir! Sag’s ihm aber nicht, sonst kriegt er gleich einen Herzinfarkt!

Für die Lösung des Problems habe ich im Datenmodell eine neue Tabelle namens tblUmlageinformationenMitForderungsarten angelegt, die mit der Tabelle tblUmlageinformationen und tblForderungsarten verknüpft ist. Nun kann ich jeder Umlage (in meinem Fall sind es, wie erwähnt, nur die mit dem Umlageschlüssel „Bescheid der Stadt“) zuweisen, mit welcher Forderungsart die dazugehörigen Kontoabbuchungen in meiner Anwendung verbucht werden.

Wenn ich also im Formular eine Nebenkostenabrechnungsposition mit dem Umlageschlüssel „Bescheid der Stadt“ aufrufe, dann passiert im Hintergrund folgendes. Jede Wohnung der ausgewählten WEG, die im abzurechnenden Jahr vermietet war, wird durchlaufen. Bei jedem Durchlauf wird eine SQL-Abfrage, die als Parameter die ID der Nebenkostenabrechnungsposition, die ID des Abrechnungsjahres und die WohnungID erhält, aufgerufen. Die SQL-Abfrage liefert dann den kumulierten Betrag, der für diese Wohnung, in diesem Jahr mit der ermittelten ForderungsartID verbucht worden ist.

Irgendwann sind dann alle Nebenkostenpositionen erfasst. Anschließend überfliege ich dann die erstellten Betriebskostenabrechnungen (die noch als Entwurf vorliegen) und klicke auf „Abrechnungsjahr abschließen“. Auch dabei wird eine Menge erledigt:

  • der Abrechnungsdatensatz (fungiert als Verbindung zwischen einer bestimmten WEG und einem bestimmten Abrechnungsjahr) wird als erledigt markiert, indem dort das heutige Datum gespeichert wird. Ab jetzt sind die Nebenkostenabrechnungen dieser WEG und des Abrechnungsjahres für die Bearbeitung gesperrt
  • die Anwendung prüft, ob ob im Rahmen der Nebenkostenabrechnung bei einzelnen Mietverhältnissen ein so hohes Abrechnungsergebnis (unabhängig davon, ob Nachzahlung oder Erstattung) entstanden ist, dass die Höhe der künftigen Vorauszahlungen angepasst werden sollte. In diesem Fall wird fürs betroffene Mietverhältnis ein neuer Vorauszahlungsdatensatz erstellt und eine Verbindung zum Abrechnungsdatensatz geschaffen. So lässt sich später nachvollziehen, anhand von welcher Abrechnung die Vorauszahlung angepasst wurde.
  • die Anwendung legt automatisiert Forderungen (entweder Nachzahlung oder Erstattung) an, damit deren Begleichung überwacht werden kann. Dabei fällt mir ein, dass ich noch den, zugegebenermaßen seltenen, Fall abdecken sollte, wenn die Nachzahlung 0,00 bzw. wenige Cents beträgt.
  • die einzelnen Betriebskostenabrechnungen werden als PDF-Dateien exportiert

Begleitschreiben zur Nebenkostenabrechnung

Begleitschreben der Nebenkostenabrechnung

Nebenkostenabrechnung

Nebenkostenabrechnung

Fertigstellung

BWLer: „WAS machst du eigentlich die letzten Tage? Du programmierst die ganze Zeit rum, aber ich sehe gar keinen Fortschritt. Es kommen keine neuen Formulare dazu. Die Auswertungsmöglichkeiten sind ebenfalls die gleichen wie letzte Woche.“

ITler: „Ich hinterlege gerade Plausibilitätsprüfungen und programmiere die Formularsteuerungen.

BWLer: „Das verschlingt zu viel Zeit! Lass uns auf die Plausibilitätsprüfungen verzichten – sie bieten ja keinerlei nützliche Funktionalität. Wir könnten stattdessen schon mal mit der Migration der Daten anfangen.

ITler: „Ich habe aber keine Lust, eine halbgare Software in Betrieb zu nehmen. Plausibilitätsprüfungen gehören zu einer guten Software einfach dazu. Sie muss stabil sein und weitestgehend Fehlbedienung durch Nutzer ausschließen.

BWL: „Von welcher Fehlbedienung redest du? Ich bin doch nicht blöd und kann eine Software bedienen!“

ITler leise murmelnd: „Da habe ich manchmal meine Zweifel…“

ITler nun lauter: „Ganz einfach. Du erfasst ein neues Mietverhältnis und hinterlegst dort aus Versehen ein Endedatum, das vor dem Beginndatum liegt. Oder du erfasst für eine Wohnung ein neues Mietverhältnis, das sich zeitlich mit dem alten überschneidet. Oder du erstellst eine Nebenkostenabrechnung, ohne zuvor alle Zahlungen des Mieters verbucht zu haben. Dass das zu Folgenfehlern führt, die sich dann im Bestand fortpflanzen, brauche ich nicht zu erwähnen. All das wird irgendwann passieren, wenn die Anwendung unerlaubte Konstellationen nicht von vornherein als solche erkennt und abweist. In der Justiz gilt der Prinzip der Unschuldsvermutung. In der Anwendungsentwicklung können wir uns diesen Luxus nicht erlauben und müssen davon ausgehen, dass Nutzer Falscheingaben machen.“

Der ITler redet sich in Rage: „Wenn ich auf Prüfungen und Formularsteuerungen verzichte, weil du mir mit deinen unrealistischen Terminvorgaben im Nacken sitzt, bist du anschließend der erste, der mir die Ohren vollheult, dass die Anwendung im produktiven Betrieb viel zu viele Fehler macht. Diese Fehler nachträglich zu bereinigen und deren Quelle zu finden und dichtzumachen, kostet viel mehr Zeit, als es gleich zu machen. Also nerv mich nicht und lass mich meine Arbeit machen.

Eine ganze Weile ist seitdem vergangen. Unglaublich, aber die Wohnungsverwaltung ist in ihrer Grundstruktur tatsächlich fertig geworden, sodass ich vor ein paar Monaten die Abrechnung des Geschäftsjahres 2022 durchführen und die Betriebskostenabrechnungen an meine Mieter verschicken konnte. Davor war die Datenmigration angesagt, die ich händisch vorgenommen habe und die eine sehr gute Testphase war, in der ich eine Menge Kinderkrankheiten der Anwendung eliminiert habe.

Wie es so häufig ist, ist eine Anwendung, selbst, wenn sie schon im produktiven Betrieb ist, eigentlich nie fertig. Als nächstes Ziel habe ich mir vorgenommen, die ganzen Unterlagen (Mietvertrag, Übergabeprotokoll beim Einzug / Auszug, Vermieterbescheinigung), die im Rahmen eines Mietverhältnisses zu erstellen sind, automatisiert durch die Wohnungsverwaltung selbst generieren zu lassen. Hört sich nach einem machbaren Ziel an.

Aber zuerst ist erstmal Urlaub angesagt. Schöne Weihnachtszeit!

Schreibe einen Kommentar

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