diff --git a/README.md b/README.md index f9165f0..98cf861 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,86 @@ # moneymoney -Erweiterungen für MoneyMoney in Lua + +Diese MoneyMoney Extension erlaubt es, die Umsätze auf ein oder mehreren in MoneyMoney geführte Konten direkt in eine Buchhaltungssoftware als vollständige Buchungssätze zu importieren. + +Die für die Buchungssätze erforderliche Zuordung von Umsätzen zu Finanz- und Gegenkonten, Steuersätzen und Kostenstellen wird durch die Zuweisung der Umsätze zu Kategorien vorgenommen. + +Dieses Exportskript wurde für eine Datenübergabe an die Buchhaltungssoftware MonKey Office entwickelt (und nur damit getestet) worden. Es sollte sich aber im Prinzip auch mit vergleichbaren Buchhaltungsprogrammen vertragen, die einen DATEV-ähnlichen Import und Export von Buchungen ermöglichen. + +## Konfiguration des Finanzkontos + +Für jedes in MoneyMoney geführte Bankkonto muss in der Buchhaltungssoftware ein entsprechendes Konto eingerichtet werden. Dieses **Finanzkonto** (z.B. 1800) muss in MoneyMoney in das Notizfeld der Einstellungen des Bankkontos eingetragen werden: + +``` +Finanzkonto=1800 +``` + +Das Finanzkonto wird in den exportierten Buchungen automatisch als *Soll-Konto* (bei Einnahmen) bzw. als *Haben-Konto* (bei Ausgaben) eingetragen. + +## Gegenkonto konfigurieren + +Zusätzlich zum Finanzkonto muss für jede Buchung ein entsprechendes **Gegenkonto** konfiguriert werden. Dieses ergibt sich aus der in MoneyMoney zugewiesenen Kategorie des Umsatzes. + +Das Gegenkonto wird direkt an den eigentlichen Namen der Kategorie am Ende des Titels in eckigen Klammern eingetragen: + +``` +Bürobedarf [6815] +``` + +Für die Buchungskonten, die über eine *Steuerautomatik* verfügen (wo sich also der Steuersatz automatisch aus dem Buchungskonto ableitet) ist in der Regel keine weitere Angabe erforderlich. + +## Steuersatz konfigurieren + +Für Buchungskonten ohne Steuerautomatik oder solche mit variablen Steuersätzen kann der Kategorie auch noch ein **Steuersatz** mit angegeben werden. Dazu muss der Steuersatz in geschweiften Klammern in den Titel geschrieben werden. + +``` +Reisekosten Mietwagen [6673] {VSt19} +Reisekosten Taxi [6673] {VSt7} +``` + +Die Bezeichnungen des Steuersatzes müssen dabei denen in der Buchhaltungssoftware verwendeten entsprechen, da sie vom Exportskript nur durchgereicht und nicht interpretiert werden. + +## Kostenstellen konfigurieren + +Zusätzlich zu Gegenkonto und Steuersatz können über Kategorien auch **Kostenstellen** spezifiziert werden. Das erlaubt es, bestimmte Buchungen automatisch einer oder zwei Kostenstellen zuzuweisen. + +Die Kostenstellen werden im Kategorie-Titel über das Rautezeichen eingeleitet: + +``` +Einnahmen Veranstaltungen Verkauf [4400] #1000 +Einnahmen Veranstaltungen Tickets [4300] #2000 +``` + +Werden einer Buchung mehr als zwei Kostenstellen zugewiesen führt das zum Abbruch des Exports. + +## Vererbung über Kategoriegruppen + +MoneyMoney erlaubt die Gruppierung von Kategorien durch Kategoriegruppen. Wenn man in MoneyMoney mehrere Kategorien für bestimmte Umsätze vergeben möchte, die aber alle die gleiche oder zumindest nur in Teilen abweichende Buchhaltungs-Konfiguration verfügen, können die gemeinsamen Werte der Kategoriegruppe zugewiesen werden. + +Diese Konfigurationswerte werden automatisch an die darunter liegenden Kategorien vererbt. Werden in den Unterkategorien das *Gegenkonto* oder der *Steuersatz* ein weiteres Mal spezifiziert, *überschreiben* diese Werte die Vorgabe der Gruppe. Werden in der Unterkategorie *Kostenstellen* spezifiziert, so *ergänzen* diese die vorher benannten Kostenstellen. + +Folgende Hierarchie: + +``` +Reisekosten [6673] {VSt19} #2000 +-- car2go #2010 +-- DriveNow #2020 +-- Flinkster #2030 +-- Taxi {VSt7} #2040 +``` + +ist äquivalent zu + +``` +car2go [6673] {VSt19} #2000 #2010 +DriveNow [6673] {VSt19} #2000 #2020 +Flinkster [6673] {VSt19} #2000 #2030 +Taxi [6673] {VSt7} #2000 #2040 +``` + +aber deutlich übersichtlicher und einfacher zu verwalten. + + +## Automatischer Abbruch + +Wurde ein zu exportierender Umsatz keiner Kategorie zugeordnet oder ist für eine Kategorie kein Gegenkonto ermittelbar, bricht der Export automatisch ab, damit alle Umsätze berücksichtigt werden und der Export nicht unvollständig ist. + diff --git a/buchungen.lua b/buchungen.lua index c4dacf8..be32319 100644 --- a/buchungen.lua +++ b/buchungen.lua @@ -8,17 +8,6 @@ -- Das Skript liest eine zweite Lua-Datei ein, in der sich die eigentliche Konfiguration -- befindet. Diese muss an die eigenen Bedürfnisse und Verhältnisse angepasst werden. -- --- Die Konfiguration sorgt im wesentlichen dafür, dass den verwendeten Bankkonten in --- MoneyMoney Finanzkonten und den Umsätzen selbst (z.B. auf Basis der in MoneyMoney zugewiesenen --- Kategorien) entsprechende Gegenkonten zugewiesen werden. Können für einen Umsatz --- ein Finanzkonto und ein Gegenkonto ermittelt werden, wird der Umsatz exportiert. --- --- TODO: --- --- * Abbuchungen (negative Beträge) sollten bereits im Export zum Vertauschen --- von Finanzkonto und Gegenkonto führen und den Betrag das Minuszeichen entziehen - --- -- CSV Dateieinstellungen @@ -32,34 +21,12 @@ local reverseOrder = false -- Exportformat bei MoneyMoney anmelden Exporter{version = 1.00, - format = MM.localizeText("GDPdU Buchungssätze"), + format = MM.localizeText("Buchungssätze"), fileExtension = "csv", reverseOrder = reverseOrder, description = MM.localizeText("Export von MoneyMoney Umsätzen zu direkt importierbaren Steuer-Buchungssätzen.")} --- Zugriffsklasse für Kostenstelle einrichten. --- Zugriff auf nicht definierte Kostenstellen führen zum Abbruch des Exports. - - -KS = setmetatable ({}, - { - __index = function(_, key) - local ks = Kostenstellen[key] - if ks then - return ks - end - - error("Kostenstelle " .. key .. " nicht definiert.") - end - } -) - --- Konfiguration einlesen - -require("conf/buchungen") - - -- Definition der Reihenfolge und Titel der zu exportierenden Buchungsfelder -- Format: Key (Internes Feld), Titel (in der ersten Zeile der CSV-Datei) @@ -102,8 +69,6 @@ local function concatenate (...) end - - -- -- WriteHeader: Erste Zeile der Exportdatei schreiben -- @@ -120,10 +85,85 @@ function WriteHeader (account, startDate, endDate, transactionCount) line = line .. csvField(Eintrag[2]) end assert(io.write(MM.toEncoding(encoding, line .. linebreak, utf_bom))) + print ("--------------- NEW EXPORT ----------------") + +end + + +function DruckeUmsatz(Grund, Umsatz) + print (string.format( "%s: %s / %s %s / %s / %s / %s\n", + Grund, Umsatz.Datum, Umsatz.Betrag, Umsatz.Waehrung, + Umsatz.Kategorie, Umsatz.Verwendungszweck, Umsatz.Notiz) ) end +-- Extrahiere Metadaten aus dem Kategorie-Titel +-- +-- Übergeben wird ein KategoriePfad, der die Kategorie-Hierarchie +-- in MoneyMoney wiedergibt. Jede Kategorie in diesem Pfad kann +-- ein Gegenkonto, einen Steuersatz oder eine Kostenstelle spezifizieren. +-- +-- Wird ein Gegenkonto oder Steuersatz mehrfach spezifiziert, überschreibt +-- jeweils das jeweils rechte Feld den Wert seines Vorgängers. Kostenstellen +-- ergänzen sich, es dürfen aber nur maximal zwei unterschiedliche Kostenstellen +-- angegeben werden. + +function KategorieMetadaten (KategoriePfad) + local KategorieNeuerPfad + local Gegenkonto, Steuersatz, KS1, KS2 + local AnzahlKostenstellen = 1 + local Kostenstellen = {} + + for Kategorie in string.gmatch(KategoriePfad, "([^\\]+)") do + + -- Ist dem Titel eine Konfiguration angehängt worden? + local i, _, Metadaten = string.find ( Kategorie, "([%[{#].*)$") + + -- Dann Metadaten extrahieren + if Metadaten then + -- Metadaten aus dem Kategorie-Titel entfernen + Kategorie = string.sub (Kategorie, 1, i - 1) + + -- Konto in eckigen Klammern ("[6851]") + _, _, Konto = string.find (Metadaten, "%[(%d+)%]") + if Konto then + Gegenkonto = Konto + end + + -- Steuersatz in geschweiften Klammern ("{VSt7}") + _, _, Text = string.find (Metadaten, "{(.+)}") + if Text then + Steuersatz = Text + end + + -- Kostenstelle 1 und 2 mit Hashzeichen ("#1000") + for Nummer in string.gmatch(Metadaten, "#(%d+)%s*") do + if AnzahlKostenstellen == 3 then + error("Zu viele Kostenstellen in der Kategorie angegeben") + end + Kostenstellen[AnzahlKostenstellen] = Nummer + AnzahlKostenstellen = AnzahlKostenstellen + 1 + end + end + + -- Leading/Trailing Whitespace aus dem verbliebenen Kategorie-Titel entfernen + _, _, Kategorie = string.find (Kategorie, "%s*(.-)%s*$") + + + -- Neuen Kategoriepfad aufbauen + if KategorieNeuerPfad then + KategorieNeuerPfad = KategorieNeuerPfad .. " - " .. Kategorie + else + KategorieNeuerPfad = Kategorie + end + + end + + -- Alle extrahierten Werte zurückliefern + return KategorieNeuerPfad, Gegenkonto, Steuersatz, Kostenstellen[1], Kostenstellen[2] +end + -- -- WriteTransactions: Jede Buchung in eine Zeile der Exportdatei schreiben @@ -133,16 +173,20 @@ end function WriteTransactions (account, transactions) for _,transaction in ipairs(transactions) do - -- Trage Umsatzdaten aus der Transaktion in der später zu expotierenden Form zusammen + -- Trage Umsatzdaten aus der Transaktion in der später zu exportierenden Form zusammen + + local Exportieren = true + + -- Zu übertragende Umsatzinformationen in eigener Struktur zwischenspeichern + -- und einfache Feldinhalte aus Transaktion übernehmen local Umsatz = { Typ = transaction.bookingText, Name = transaction.name or "", Kontonummer = transaction.accountNumber or "", Bankcode = transaction.bankcode or "", - Kategorie = string.gsub(transaction.category, [[\]], " - "), Datum = MM.localizeDate(transaction.bookingDate), - Betrag = MM.localizeNumber("0.00", transaction.amount), + Betrag = transaction.amount, Notiz = transaction.comment or "", Verwendungszweck = transaction.purpose or "", Waehrung = transaction.currency or "" @@ -152,105 +196,103 @@ function WriteTransactions (account, transactions) -- Daten für den zu schreibenden Buchungsdatensatz local Buchung = { Umsatzart = Umsatz.Typ, - Exportieren = true, Datum = Umsatz.Datum, Text = Umsatz.Name .. ": " .. Umsatz.Verwendungszweck .. ((Umsatz.Notiz ~= "") and ( " (" .. Umsatz.Notiz .. ")") or ""), Finanzkonto = nil, Gegenkonto = nil, - Betrag = Umsatz.Betrag, + Betrag = nil, Steuersatz = nil, Kostenstelle1 = nil, Kostenstelle2 = nil, BelegNr = "", Referenz = "", Waehrung = Umsatz.Waehrung, - Bemerkung = concatenate ("(", Umsatz.Kontonummer, ") [", Umsatz.Kategorie, "] {", Umsatz.Typ, "}" ) + Bemerkung = "" } - -- Finanzkonto für verwendetes Bankkonto ermitteln + -- Einlesen der Konto-spezifischen Konfiguration aus dem Kommentarfeld - if ( account.comment == "" ) then - -- Zuweisung des Finanzkontos aus der Konfiguration auf Basis des Kontonamens - Umsatz.Finanzkonto = Konfiguration.Bankkonten[account.name] - else - -- Zuweisung des Finanzkontos aus Notizfeld des MoneyMoney Kontos - Umsatz.Finanzkonto = account.comment + + local Bankkonto = {} + + for Kennzeichen, Wert in string.gmatch(account.comment, "(%g+)=(%g+)") do + Bankkonto[Kennzeichen] = Wert end - if ( Umsatz.Finanzkonto == "" ) then + -- Finanzkonto für verwendetes Bankkonto ermitteln + + if ( Bankkonto.Finanzkonto == "" ) then error ( "Kein Finanzkonto für " .. account.name .. " gesetzt" ) end + Buchung.Finanzkonto = Bankkonto.Finanzkonto - -- Buchungsfelder auf Basis der Zuordnung automatisch setzen - for Index, Eintrag in pairs(Konfiguration.Zuordnung) do - local ErsterEintrag = true - local Treffer = false - -- Alle Kriterien im müssen erfüllt sein, damit Buchungsfelder gesetzt werden können - for Feld, Wert in pairs(Eintrag[1]) do - if ErsterEintrag then - ErsterEintrag = false - Treffer = (Umsatz[Feld] == Wert) - else - Treffer = (Treffer and (Umsatz[Feld] == Wert) ) - end - end + -- Extrahiere Buchungsinformationen aus dem Kategorie-Text + Umsatz.Kategorie, Buchung.Gegenkonto, Buchung.Steuersatz, + Buchung.Kostenstelle1, Buchung.Kostenstelle2 = KategorieMetadaten (transaction.category) - -- Wenn alle Umsatz-Kriterien stimmen, setze alle eingestellten Buchungsfelder + Buchung.Bemerkung = concatenate ("(", Umsatz.Kontonummer, ") [", Umsatz.Kategorie, "] {", Umsatz.Typ, "}" ) - if (Treffer) then - for Feld, Wert in pairs(Eintrag[2]) do - Buchung[Feld] = Wert - end - break -- keine weiteren Vergleiche durchführen - end + -- Buchungen mit Betrag 0,00 nicht exportieren + + if ( transaction.amount == 0) then + Exportieren = false end + -- Buchungen mit Gegenkonto 0000 nicht exportieren + + if ( tonumber(Buchung.Gegenkonto) == 0) then + Exportieren = false + end - -- Suche nach Tags in den Umsatznotizen und setze die entsprechenden Buchungsfelder + -- Wenn für das Bankkonto eine Währung spezifiziert ist muss der Umsatz in dieser Währung vorliegen - for tag in string.gmatch(transaction.comment, "#%w+") do - local Match = Konfiguration.Tags[tag] - if (Match) then - for Feld, Wert in pairs(Match) do - Buchung[Feld] = Wert - end - end + if Bankkonto.Waehrung and (Bankkonto.Waehrung ~= Umsatz.Waehrung) then + Exportieren = false end + -- Export der Buchung vorbereiten - Buchung.Finanzkonto = Umsatz.Finanzkonto + if (transaction.amount > 0) then + Buchung.Betrag = MM.localizeNumber("0.00", transaction.amount) + else + Buchung.Betrag = MM.localizeNumber("0.00", - transaction.amount) + Buchung.Finanzkonto, Buchung.Gegenkonto = Buchung.Gegenkonto, Buchung.Finanzkonto + end + - if (Buchung.Finanzkonto and Buchung.Gegenkonto and Buchung.Exportieren) then + -- Buchung exportieren - local line = "" - for Position, Eintrag in ipairs(Exportdatei) do - if Position ~= 1 then - line = line .. separator + if Exportieren then + if Buchung.Finanzkonto and Buchung.Gegenkonto then + + local line = "" + for Position, Eintrag in ipairs(Exportdatei) do + if Position ~= 1 then + line = line .. separator + end + line = line .. csvField(Buchung[Eintrag[1]]) end - line = line .. csvField(Buchung[Eintrag[1]]) + assert(io.write(MM.toEncoding(encoding, line .. linebreak, utf_bom))) + else + DruckeUmsatz ("UNVOLLSTÄNDIG", Umsatz) + error("Abbruch des Exports, da Kontenzuordnung unvollständig ist.") end - assert(io.write(MM.toEncoding(encoding, line .. linebreak, utf_bom))) - - else - if (not Buchung.Exportieren) then - print ("Unvollständig: ", Umsatz.Datum, " ", Umsatz.Betrag, Umsatz.Waehrung, Umsatz.Kategorie, Umsatz.Verwendungszweck, Umsatz.Notiz) - end + DruckeUmsatz ("ÜBERSPRUNGEN", Umsatz) end end end - function WriteTail (account) -- Nothing to do. end diff --git a/conf/buchungen.lua b/conf/buchungen.lua deleted file mode 100644 index 109d181..0000000 --- a/conf/buchungen.lua +++ /dev/null @@ -1,232 +0,0 @@ --- Buchungen Export: Konfiguration - --- Kostenstellen --- Anlegen von Namen für Kostenstellen - - -Kostenstellen = { - PROJEKT1 = "1000", - PROJEKT2 = "2000", -} - -Konfiguration = { - - -- Konfiguration: Zuordnung von Bankkonto-Namen zu Finanzkonten - - Bankkonten = { - ["Girokonto"] = "1800", - ["PayPal"] = "1810" - }, - - - -- Konfiguration: Zuordnung von Gegenkonto, Steuersatz und Kostenstellen - -- Erster Eintrag: Suchkriterien (wenn keine vorhanden: Default) - -- Zweiter Eintrag: Zu setzende Felder (wenn keine vorhanden: Umsatz nicht exportieren) - - -- Die Beispiele gelten für einen Kontenrahmen SKR_04 - - Zuordnung = { - - -- Sonderfälle - { - { Kategorie = "PayPal Fremdwährung" }, -- PayPal Umbuchungen in anderen Währungen, die da eigentlich nichts verloren haben - { Exportieren = false } - }, - { - { Kategorie = "Einnahmen - Verkauf Anlagevermögen" }, -- Anlagevermögen muss manuell gebucht werden - { KontoHaben = "8300" } - }, - { - { Kategorie = "Ausgaben - Kauf Anlagevermögen" }, -- Anlagevermögen muss manuell gebucht werden - { KontoHaben = "8300" } - }, - { - { Betrag = "0,00" }, -- Nullbuchungen nicht exportieren - { Exportieren = false } - }, - - - --- Zuordnung über die Kategorie - - - -- Offene Posten und Kreditoren-/Debitorenzahlungen - - { - { Kategorie = "Einnahmen - Debitorenzahlungen" }, - { KontoHaben = "8100" } - }, - - -- Offene Posten und Kreditoren-/Debitorenzahlungen - - { - { Kategorie = "Ausgaben - Kreditorenzahlungen" }, - { KontoHaben = "8200" } - }, - - -- Einnahmen - - { - { Kategorie = "Einnahmen - Erlöse 19%" }, - { KontoHaben = "4400" } -- Erlöse 19% Ust - }, - { - { Kategorie = "Einnahmen - Projekt" }, - { KontoHaben = "4400", Kostenstelle1 = KS_PROJEKT1 } - }, - { - { Kategorie = "Einnahmen - Privateinlage" }, - { KontoHaben = "2180" } -- Privateinlage - }, - { - { Kategorie = "Einnahmen - Zinsen" }, - { KontoHaben = "7020" } -- Zinsen - }, - - - -- AUSGABEN - - { - { Kategorie = "Ausgaben - Privatentnahme" }, - { KontoHaben = "2100" } -- Privatentnahmen - }, - { - { Kategorie = "Ausgaben - Wareneinkauf" }, - { KontoHaben = "5400" } -- Wareneingang 19% - }, - { - { Kategorie = "Ausgaben - Kontogebühren" }, - { KontoHaben = "6855" } - }, - { - { Kategorie = "Ausgaben - Geschenke 0%" }, - { KontoHaben = "6610", Steuersatz="-" } -- Geschenke abzugsfähig ohne § 37b EStG - }, - { - { Kategorie = "Ausgaben - Geschenke 19%" }, - { KontoHaben = "6610", Steuersatz="VSt19" } -- Geschenke - }, - { - { Kategorie = "Ausgaben - Porto" }, - { KontoHaben = "6800" } - }, - { - { Kategorie = "Ausgaben - Betriebsausgaben 19%", }, - { KontoHaben = "6300" } -- Sonstige Betriebliche Aufwendungen - }, - { - { Kategorie = "Ausgaben - Betriebsausgaben 0%", }, - { KontoHaben = "6300", Steuersatz="-" } -- Sonstige Betriebliche Aufwendungen - }, - { - { Kategorie = "Ausgaben - Studio - Miete" }, - { KontoHaben = "6310", Steuersatz = "-" } -- Miete (keine Umsatzsteuer) - }, - { - { Kategorie = "Ausgaben - Gas" }, - { KontoHaben = "6325" } -- Gas / Strom - }, - { - { Kategorie = "Ausgaben - Strom" }, - { KontoHaben = "6325" } -- Gas / Strom - }, - { - { Kategorie = "Ausgaben - Telekommunikation" }, - { KontoHaben = "6805" } -- Telefon - }, - { - { Kategorie = "Ausgaben - Bürobedarf", }, - { KontoHaben = "6815" } -- Bürobedarf - }, - { - { Kategorie = "Ausgaben - Weiterbildung" }, - { KontoHaben = "6821" } -- Fortbildungskosten - }, - - -- Ausgaben: Reisekosten - - { - { Kategorie = "Ausgaben - Reisekosten - Flüge" }, - { KontoHaben = "6670" } -- Reisekosten - }, - { - { Kategorie = "Ausgaben - Reisekosten - Übernachtung" }, - { KontoHaben = "6680" } -- Übernachtung - }, - { - { Kategorie = "Ausgaben - Reisekosten - Taxi / Nahverkehr" }, - { KontoHaben = "6673", Steuersatz = "VSt7" } - }, - { - { Kategorie = "Ausgaben - Reisekosten - Mietwagen" }, - { KontoHaben = "6673", Steuersatz = "VSt19" } - }, - { - { Kategorie = "Ausgaben - Reisekosten - Bahn" }, - { KontoHaben = "6673", Steuersatz = "VSt19" } - }, - - -- Ausgaben: Versicherungen - - { - { Kategorie = "Privates - Rentenversicherung" }, - { KontoHaben = "2200" } -- Sonderausgaben beschränkt abzugsfähig - }, - { - { Kategorie = "Privates - Krankenversicherung" }, - { KontoHaben = "2200" } -- Sonderausgaben beschränkt abzugsfähig - }, - { - { Kategorie = "Privates - Private Versicherungen" }, - { KontoHaben = "2200" } -- Sonderausgaben beschränkt abzugsfähig - }, - - -- Ausgaben: Steuern - { - { Kategorie = "Privates - Steuern - Einkommensteuer" }, - { KontoHaben = "2150" } -- Privatsteuern VH - }, - { - { Kategorie = "Ausgaben - Steuern - Umsatzsteuer - Umsatzsteuer Vorauszahlung" }, - { KontoHaben = "3820" } -- UST VA - auch für Einnnahmen - }, - { - { Kategorie = "Ausgaben - Steuern - Umsatzsteuer - Umsatzsteuer Vorjahr" }, - { KontoHaben = "3841" } -- Umsatzsteuer Vorjahr - }, - { - { Kategorie = "Ausgaben - Steuern - Umsatzsteuer - Umsatzsteuer frühere Jahre" }, - { KontoHaben = "3845" } -- Umsatzsteuer frühere Jahre - }, - { - { Kategorie = "Ausgaben - Steuern - Umsatzsteuer - Einfuhrumsatzsteuer" }, - { KontoHaben = "1433" } -- Entstandene Einfuhrumsatzsteuer - }, - - - -- Ausgaben: Sonstiges - - { - { Kategorie = "Umbuchungen - Fehlbuchungen" }, - { KontoHaben = "7552" } - }, - { - { Kategorie = "Umbuchungen - Geldtransit" }, - { KontoHaben = "1460" } - }, - { - { }, -- Default - { KontoHaben = "8999" } -- Alle anderen Buchungen auf Habenkonto 8999 buchen (CATCHALL) - } - }, - - - -- Hashtags - - Tags = { - ["#PROJEKT1"] = { Kostenstelle2 = KS.PROJEKT1 }, - ["#VST0"] = { Steuersatz = "-" } - } - - -} -