├── .gitignore ├── LICENSE ├── MoneyMonkey.lua ├── README.md └── moneymonkey.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Lua sources 2 | luac.out 3 | 4 | # luarocks build files 5 | *.src.rock 6 | *.zip 7 | *.tar.gz 8 | 9 | # Object files 10 | *.o 11 | *.os 12 | *.ko 13 | *.obj 14 | *.elf 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | *.def 26 | *.exp 27 | 28 | # Shared objects (inc. Windows DLLs) 29 | *.dll 30 | *.so 31 | *.so.* 32 | *.dylib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.i*86 39 | *.x86_64 40 | *.hex 41 | 42 | 43 | .DS_Store 44 | 45 | .DS_Store 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Tim Pritlove 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MoneyMonkey.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- Export von MoneyMoney Umsätzen zu direkt importierbaren Steuer-Buchungssätzen. 3 | -- 4 | -- Dieses Skript ist getestet mit MonKey Office, sollte aber im Prinzip auch mit allen 5 | -- anderen Buchhaltungsprogrammen funktionieren, die Buchungssätze als CSV-Datei 6 | -- direkt importieren können (was vermutlich nahezu alle sind). 7 | -- 8 | -- Das Skript liest eine zweite Lua-Datei ein, in der sich die eigentliche Konfiguration 9 | -- befindet. Diese muss an die eigenen Bedürfnisse und Verhältnisse angepasst werden. 10 | -- 11 | -- Erforderliche MoneyMoney-Version: 2.3.26 12 | 13 | -- CSV Dateieinstellungen 14 | 15 | local encoding = "UTF-8" 16 | local utf_bom = false 17 | local linebreak = "\n" 18 | 19 | -- Exportformat bei MoneyMoney anmelden 20 | 21 | Exporter { version = 1.6, 22 | options = { 23 | { label = "Umsätze müssen als erledigt markiert sein", name = "checkedOnly", default = true }, 24 | { label = "Nur Umsätze mit gültigem Buchungskonto exportieren", name = "accountMandatory", default = true } 25 | }, 26 | format = MM.localizeText("MoneyMonkey"), 27 | fileExtension = "csv", 28 | reverseOrder = true, 29 | description = MM.localizeText("Export von MoneyMoney Umsätzen zu direkt importierbaren Steuer-Buchungssätzen.") } 30 | 31 | 32 | -- Definition der Reihenfolge und Titel der zu exportierenden Buchungsfelder 33 | -- Format: Key (Internes Feld), Titel (in der ersten Zeile der CSV-Datei) 34 | 35 | Exportdatei = { 36 | { "Datum", "Datum" }, 37 | { "BelegNr", "BelegNr" }, 38 | { "Referenz", "Referenz" }, 39 | { "Betrag", "Betrag" }, 40 | { "Waehrung", "Währung" }, 41 | { "Text", "Text" }, 42 | { "Finanzkonto", "KontoSoll" }, 43 | { "Gegenkonto", "KontoHaben" }, 44 | { "Steuersatz", "Steuersatz" }, 45 | { "Kostenstelle1", "Kostenstelle1" }, 46 | { "Kostenstelle2", "Kostenstelle2" }, 47 | { "Notiz", "Notiz" } 48 | } 49 | 50 | 51 | 52 | -- 53 | -- Hilfsfunktionen zur String-Behandlung 54 | -- 55 | 56 | local DELIM = "," -- Delimiter 57 | 58 | local function csvField(str) 59 | if str == nil or str == "" then 60 | return "" 61 | end 62 | return '"' .. string.gsub(str, '"', '""') .. '"' 63 | end 64 | 65 | 66 | local function concatenate(...) 67 | local catstring = "" 68 | for _, str in pairs({ ... }) do 69 | catstring = catstring .. (str or "") 70 | end 71 | return catstring 72 | end 73 | 74 | 75 | -- 76 | -- WriteHeader: Erste Zeile der Exportdatei schreiben 77 | -- 78 | 79 | 80 | function WriteHeader(account, startDate, endDate, transactionCount, options) 81 | -- Write CSV header. 82 | 83 | local line = "" 84 | for Position, Eintrag in ipairs(Exportdatei) do 85 | if Position ~= 1 then 86 | line = line .. DELIM 87 | end 88 | line = line .. csvField(Eintrag[2]) 89 | end 90 | assert(io.write(MM.toEncoding(encoding, line .. linebreak, utf_bom))) 91 | print("--------------- START EXPORT ----------------") 92 | end 93 | 94 | -- 95 | -- WriteHeader: Export abschließen 96 | -- 97 | 98 | function WriteTail(account, options) 99 | print("--------------- END EXPORT ----------------") 100 | end 101 | 102 | function DruckeUmsatz(Grund, Umsatz) 103 | print(string.format("%s: %s / %s %s / %s / %s / %s\n", 104 | Grund, Umsatz.Datum, Umsatz.Betrag, Umsatz.Waehrung, 105 | Umsatz.Kategorie, Umsatz.Verwendungszweck, Umsatz.Notiz)) 106 | end 107 | 108 | -- Extrahiere Metadaten aus dem Kategorie-Titel 109 | -- 110 | -- Übergeben wird ein KategoriePfad, der die Kategorie-Hierarchie 111 | -- in MoneyMoney wiedergibt. Jede Kategorie in diesem Pfad kann 112 | -- ein Gegenkonto, einen Steuersatz oder eine Kostenstelle spezifizieren. 113 | -- 114 | -- Wird ein Gegenkonto oder Steuersatz mehrfach spezifiziert, überschreibt 115 | -- jeweils das jeweils rechte Feld den Wert seines Vorgängers. Kostenstellen 116 | -- ergänzen sich, es dürfen aber nur maximal zwei unterschiedliche Kostenstellen 117 | -- angegeben werden. 118 | 119 | function UmsatzMetadaten(KategoriePfad, Kommentar) 120 | local KategoriePfadNeu 121 | local Gegenkonto, Steuersatz, KS1, KS2 122 | local AnzahlKostenstellen = 1 123 | local Kostenstellen = {} 124 | 125 | for Kategorie in string.gmatch(KategoriePfad, "([^\\]+)") do 126 | -- Ist dem Titel eine Konfiguration angehängt worden? 127 | local i, _, Metadaten = string.find(Kategorie, "([%[{#].*)$") 128 | 129 | -- Dann Metadaten extrahieren 130 | if Metadaten then 131 | -- Metadaten aus dem Kategorie-Titel entfernen 132 | Kategorie = string.sub(Kategorie, 1, i - 1) 133 | 134 | -- Konto in eckigen Klammern ("[6851]") 135 | _, _, Konto = string.find(Metadaten, "%[(%d+)%]") 136 | if Konto then 137 | Gegenkonto = Konto 138 | end 139 | 140 | -- Steuersatz in geschweiften Klammern ("{VSt7}") 141 | _, _, Text = string.find(Metadaten, "{(.+)}") 142 | if Text then 143 | Steuersatz = Text 144 | end 145 | 146 | -- Kostenstelle 1 und 2 mit Hashzeichen ("#1000") 147 | for Nummer in string.gmatch(Metadaten, "#(%w+)%s*") do 148 | if AnzahlKostenstellen > 2 then 149 | error( 150 | string.format( 151 | "Der Export wurde abgebrochen, da mehr als zwei Kostenstellen über die Kategorie angegeben wurde.\n\nKategorie: %s\n", 152 | Kategorie), 0) 153 | end 154 | Kostenstellen[AnzahlKostenstellen] = Nummer 155 | AnzahlKostenstellen = AnzahlKostenstellen + 1 156 | end 157 | end 158 | 159 | 160 | -- Leading/Trailing Whitespace aus dem verbliebenen Kategorie-Titel entfernen 161 | _, _, Kategorie = string.find(Kategorie, "%s*(.-)%s*$") 162 | 163 | 164 | -- Neuen Kategoriepfad aufbauen 165 | if KategoriePfadNeu then 166 | KategoriePfadNeu = KategoriePfadNeu .. " - " .. Kategorie 167 | else 168 | KategoriePfadNeu = Kategorie 169 | end 170 | end 171 | 172 | -- Umsatz-Kommentar nach Kostenstellen oder Steuersätzen durchsuchen 173 | 174 | KommentarNeu = Kommentar 175 | for KS in string.gmatch(Kommentar, "#(%w+)%s*") do 176 | if AnzahlKostenstellen > 2 then 177 | error( 178 | string.format( 179 | "Der Export wurde abgebrochen, da zu viele weitere Kostenstellen in den Notizen angegeben wurden.\n\nKategorie: %s\nNotiz: %s\nKostenstelle 1: %s\nKostenstelle 2: %s", 180 | Kategorie, Notiz, Kostenstellen[1], Kostenstellen[2]), 0) 181 | end 182 | Kostenstellen[AnzahlKostenstellen] = KS 183 | AnzahlKostenstellen = AnzahlKostenstellen + 1 184 | KommentarNeu = string.gsub(KommentarNeu, "#" .. KS .. "%s*", "") 185 | end 186 | 187 | Begin, End, Text = string.find(Kommentar, "{(.+)}") 188 | if Text then 189 | Steuersatz = Text 190 | KommentarNeu = string.sub(KommentarNeu, 1, Begin) .. string.sub(KommentarNeu, End) 191 | KommentarNeu = string.gsub(KommentarNeu, "{" .. Text .. "}%s*", "") 192 | end 193 | 194 | KommentarNeu = string.gsub(KommentarNeu, "%s*$", "") 195 | 196 | -- Alle extrahierten Werte zurückliefern 197 | return KategoriePfadNeu, KommentarNeu, Gegenkonto, Steuersatz, Kostenstellen[1], Kostenstellen[2] 198 | end 199 | 200 | -- 201 | -- WriteTransactions: Jede Buchung in eine Zeile der Exportdatei schreiben 202 | -- 203 | 204 | 205 | function WriteTransactions(account, transactions, options) 206 | for _, transaction in ipairs(transactions) do 207 | -- Trage Umsatzdaten aus der Transaktion in der später zu exportierenden Form zusammen 208 | 209 | local Exportieren = true 210 | 211 | -- Zu übertragende Umsatzinformationen in eigener Struktur zwischenspeichern 212 | -- und einfache Feldinhalte aus Transaktion übernehmen 213 | 214 | local Umsatz = { 215 | Typ = transaction.bookingText, 216 | Name = transaction.name or "", 217 | Kontonummer = transaction.accountNumber or "", 218 | Bankcode = transaction.bankcode or "", 219 | Datum = MM.localizeDate(transaction.bookingDate), 220 | Betrag = transaction.amount, 221 | Kommentar = transaction.comment or "", 222 | Verwendungszweck = transaction.purpose or "", 223 | Waehrung = transaction.currency or "" 224 | } 225 | 226 | 227 | -- Daten für den zu schreibenden Buchungsdatensatz 228 | local Buchung = { 229 | Umsatzart = Umsatz.Typ, 230 | Datum = Umsatz.Datum, 231 | Text = nil, 232 | Finanzkonto = nil, 233 | Gegenkonto = nil, 234 | Betrag = nil, 235 | Steuersatz = nil, 236 | Kostenstelle1 = nil, 237 | Kostenstelle2 = nil, 238 | BelegNr = string.gsub(io.filename, ".*/", ""), -- Dateiname des Exports ist die Belegnummer 239 | Referenz = Umsatz.Referenz, 240 | Waehrung = Umsatz.Waehrung, 241 | Notiz = "" 242 | } 243 | 244 | 245 | -- Einlesen der Konto-spezifischen Konfiguration aus den Konto-Attributen bzw. dem Kommentarfeld 246 | 247 | 248 | local Bankkonto = {} 249 | 250 | for Kennzeichen, Wert in pairs(account.attributes) do 251 | Bankkonto[Kennzeichen] = Wert 252 | end 253 | 254 | for Kennzeichen, Wert in string.gmatch(account.comment, "(%g+)=(%g+)") do 255 | Bankkonto[Kennzeichen] = Wert 256 | end 257 | 258 | -- Finanzkonto für verwendetes Bankkonto ermitteln 259 | 260 | if (Bankkonto.Finanzkonto == "") then 261 | error( 262 | string.format( 263 | "Kein Finanzkonto für Konto %s gesetzt.\n\n" .. 264 | "Bitte Feld 'Finanzkonto' in den benutzerdefinierten Feldern in den Einstellungen zum Konto setzen.", 265 | account.name), 0) 266 | end 267 | 268 | Buchung.Finanzkonto = Bankkonto.Finanzkonto 269 | 270 | 271 | 272 | -- Extrahiere Buchungsinformationen aus dem Kategorie-Text und Kommentar 273 | 274 | Umsatz.Kategorie, Umsatz.Kommentar, Buchung.Gegenkonto, Buchung.Steuersatz, 275 | Buchung.Kostenstelle1, Buchung.Kostenstelle2 = UmsatzMetadaten(transaction.category, Umsatz.Kommentar) 276 | 277 | 278 | Buchung.Text = Umsatz.Name .. 279 | ": " .. Umsatz.Verwendungszweck .. ((Umsatz.Kommentar ~= "") and (" (" .. Umsatz.Kommentar .. ")") or "") 280 | 281 | -- Metadaten für Notizfeld sammeln 282 | local metadata = {} 283 | local metadataFields = { 284 | { source = Umsatz.Typ, field = "Umsatzart" }, 285 | { source = Umsatz.Kontonummer, field = "Konto" }, 286 | { source = transaction.mandateReference, field = "Mandat" }, 287 | { source = transaction.creditorId, field = "Kreditor" }, 288 | { source = transaction.endToEndReference, field = "E2E" } 289 | } 290 | 291 | for _, item in ipairs(metadataFields) do 292 | if item.source and item.source ~= "" then 293 | table.insert(metadata, item.field .. "=" .. item.source) 294 | end 295 | end 296 | 297 | Buchung.Notiz = table.concat(metadata, ";") 298 | 299 | 300 | -- Vorgemerkte Buchungen nicht exportieren 301 | 302 | if (transaction.booked == false) then 303 | Exportieren = false 304 | end 305 | 306 | -- Buchungen mit Betrag 0,00 nicht exportieren 307 | 308 | if (transaction.amount == 0) then 309 | Exportieren = false 310 | end 311 | 312 | -- Buchungen mit Gegenkonto 0000 nicht exportieren 313 | 314 | if (tonumber(Buchung.Gegenkonto) == 0) then 315 | Exportieren = false 316 | end 317 | 318 | -- Buchungen ohne Kategorie (wenn Option gesetzt) nicht exportieren 319 | 320 | if not options.accountMandatory and (Umsatz.Kategorie == nil) then 321 | Exportieren = false 322 | end 323 | 324 | -- Wenn für das Bankkonto eine Währung spezifiziert ist muss der Umsatz in dieser Währung vorliegen 325 | 326 | if Bankkonto.Waehrung and (Bankkonto.Waehrung ~= Umsatz.Waehrung) then 327 | Exportieren = false 328 | end 329 | 330 | 331 | 332 | -- Export der Buchung vorbereiten 333 | 334 | if (transaction.amount > 0) then 335 | Buchung.Betrag = MM.localizeNumber("0.00", transaction.amount) 336 | else 337 | Buchung.Betrag = MM.localizeNumber("0.00", -transaction.amount) 338 | Buchung.Finanzkonto, Buchung.Gegenkonto = Buchung.Gegenkonto, Buchung.Finanzkonto 339 | end 340 | 341 | 342 | -- Buchung exportieren 343 | 344 | if Exportieren then 345 | if options ~= nil then 346 | if options.checkedOnly and transaction.checkmark == false then 347 | error( 348 | string.format( 349 | "Der Export wurde abgebrochen, da ein Umsatz nicht als erledigt markiert wurde.\n\n" .. 350 | "Betroffener Umsatz:\n" .. 351 | "Konto: %s\n" .. 352 | "Datum: %s\n" .. 353 | "Name: %s\n" .. 354 | "Betrag: %.2f %s\n" .. 355 | "Kategorie: %s\n" .. 356 | "Zweck: %s\n" .. 357 | "Notiz: %s", 358 | account.name, Umsatz.Datum, Umsatz.Name, Umsatz.Betrag, Umsatz.Waehrung, Umsatz.Kategorie, 359 | Umsatz.Verwendungszweck, Umsatz.Notiz), 0) 360 | end 361 | end 362 | 363 | if Buchung.Finanzkonto and Buchung.Gegenkonto then 364 | local line = "" 365 | for Position, Eintrag in ipairs(Exportdatei) do 366 | if Position ~= 1 then 367 | line = line .. DELIM 368 | end 369 | line = line .. csvField(Buchung[Eintrag[1]]) 370 | end 371 | assert(io.write(MM.toEncoding(encoding, line .. linebreak, utf_bom))) 372 | else 373 | DruckeUmsatz("UNVOLLSTÄNDIG", Umsatz) 374 | local error_msg = "" 375 | if (Umsatz.Kategorie == nil) then 376 | error_msg = string.format( 377 | "Der Export wurde abgebrochen, da einem Umsatz keine Kategorie zugewiesen wurde.\n") 378 | else 379 | error_msg = string.format( 380 | "Der Export wurde abgebrochen, da die Kontenzuordnung für die Buchhaltung unvollständig ist.\n") 381 | if Buchung.Finanzkonto == nil then 382 | error_msg = error_msg .. 383 | string.format( 384 | "\nFür das Konto \"%s\" muss in den Einstellungen (CMD-I) im Bereich 'Notizen' ein benutzerdefiniertes Feld mit dem Namen 'Finanzkonto' angelegt werden. Dessen Wert muss auf das dem Bankkonto zugeordnete Buchungskonto in der Buchhaltungs-Software gesetzt werden.\n\n", 385 | account.name) 386 | end 387 | if Buchung.Gegenkonto == nil then 388 | error_msg = error_msg .. 389 | string.format( 390 | "\nDem Umsatz muss eine Kategorie zugeordnet werden, die ein Buchungskonto spezifiziert werden (im Titel der Kategorie in eckigen Klammern).\n\n") 391 | end 392 | end 393 | error_msg = error_msg .. 394 | string.format( 395 | "\nBetroffener Umsatz:\n\n" .. 396 | "Konto: %s\n" .. 397 | "Datum: %s\n" .. 398 | "Name: %s\n" .. 399 | "Betrag: %.2f %s\n" .. 400 | "Kategorie: %s\n" .. 401 | "Zweck: %s\n" .. 402 | "Notiz: %s\n" .. 403 | "Finanzkonto: %s\n" .. 404 | "Gegenkonto: %s\n", 405 | account.name, Umsatz.Datum, Umsatz.Name, Umsatz.Betrag, Umsatz.Waehrung, Umsatz.Kategorie, 406 | Umsatz.Verwendungszweck, Umsatz.Notiz, Buchung.Finanzkonto, Buchung.Gegenkonto) 407 | 408 | error(error_msg, 0) 409 | end 410 | else 411 | DruckeUmsatz("ÜBERSPRUNGEN", Umsatz) 412 | end 413 | end 414 | end 415 | 416 | function WriteTail(account) 417 | -- Nothing to do. 418 | end 419 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MoneyMonkey v1.6 2 | 3 | **MoneyMonkey** ist eine Erweiterung (Plugin, Extension) für das Online-Banking-Programm _[MoneyMoney](https://moneymoney-app.com)_ (macOS). Mit **MoneyMonkey** können Umsätze von einem oder mehreren in _MoneyMoney_ geführten Konten direkt in eine Buchhaltungssoftware als vollständige Buchungssätze importiert werden und damit den Buchungsvorgang automatisieren. 4 | 5 | Die für die Buchungssätze erforderliche Zuordnung von Umsätzen zu Finanz- und Gegenkonten, Steuersätzen und Kostenstellen wird durch die Zuweisung der Umsätze in Kategorien bzw. durch Anmerkungen in den Kommentarfeldern der Umsätze vorgenommen. 6 | 7 | ## MonKey Office 8 | 9 | Dieses Exportskript wurde für eine automatisierte Datenübergabe an die Buchhaltungssoftware _[MonKey Office](http://www.monkey-office.de/products/monkeyoffice/index.html)_ entwickelt (und ist bisher nur damit getestet worden). Es sollte sich aber im Prinzip auch mit vergleichbaren Buchhaltungsprogrammen vertragen, die einen DATEV-ähnlichen Import von Buchungen ermöglichen. 10 | 11 | Mit **MoneyMonkey** ist es möglich, eine Online-Banking-gestützte Buchhaltung weitgehend automatisiert zu unterhalten, erfordert aber nach wie vor Kenntnisse in der Buchhaltungssoftware, um die Ergebnisse zu prüfen und ggf. noch weitere Umbuchungen vorzunehmen. 12 | 13 | **MoneyMonkey** ersetzt dafür die lästigen Wege über die nervige Bankauszug-Funktion von _MonKey Office_ und ist besonders effizient, wenn viele wiederkehrende Buchungstypen vorliegen, da diese dann in _MoneyMoney_ oft [automatisch bestimmten Buchungskategorien zugeordnet werden können]( https://moneymoney-app.com/categorization/ ). 14 | 15 | ## Installation 16 | 17 | Starte _MoneyMoney_ und wähle aus dem Menü `Hilfe` den Eintrag `Zeige Datenbank im Finder`. Im Finder öffnet sich dann der _MoneyMoney_-Ordner, der die Datenbank, die Kontoauszüge und die Erweiterungen anzeigen. 18 | 19 | Kopiere die Datei `MoneyMonkey.lua` in den Ordner `Extensions`. Das war's. 20 | 21 | ## Konfiguration 22 | 23 | Bevor der Export der Buchungen durchgeführt werden kann, müssen innerhalb von _MoneyMoney_ die Bankkonten mit Informationen angereichert und Kategorien eingerichtet werden. 24 | 25 | ### Konfiguration der Bankkonten 26 | 27 | Für jedes in _MoneyMoney_ geführte Bankkonto muss in der Buchhaltungssoftware ein entsprechendes Konto eingerichtet sein. 28 | 29 | Dieses **Finanzkonto** (z.B. _1800_ für ein Girokonto im Kontenrahmen SKR 04) muss in _MoneyMoney_ in die _benutzerdefinierten Felder_ jedes Bankkontos eingetragen werden, das später exportiert werden soll. 30 | 31 | 1. Konto in der Seitenleiste auswählen 32 | 2. Aus dem Kontextmenü den Eintrag `Einstellungen …` auswählen (oder `CMD-I` drücken) 33 | 3. In der Seitenleiste des Einstellungen-Fensters den Bereich `Notizen` auswählen 34 | 4. In der Tabelle _Benutzerdefinierte Felder_ in der Spalte _Attribut_ `Finanzkonto` und für _Wert_ das entsprechende Konto aus der Buchhaltung eintragen, das dieses Bankkonto repräsentiert (z.B. `1800`) 35 | 5. Dialog mit OK beenden 36 | 37 | _Anmerkung:_ Benutzerdefinierte Felder stehen in _MoneyMoney_ seit Version 2.3.0 bereit. In Vorgängerversionen mussten die Felder mit einer `Attribut=Wert` Notation direkt in das Notizfeld eingetragen werden. Das wird immer noch unterstützt, es sollte aber auf das neue Modell umgestiegen werden. 38 | 39 | Das Finanzkonto wird in den exportierten Buchungen automatisch als *Soll-Konto* (bei Einnahmen) bzw. als *Haben-Konto* (bei Ausgaben) eingetragen. 40 | 41 | #### Währung für Bankkonto spezifizieren 42 | 43 | Zusätzlich zum Finanzkonto kann für das Bankkonto optional auch noch die Währung gesetzt werden. Dazu muss entsprechend die Spalte _Attribut_ auf `Waehrung` und die Spalte _Wert_ auf das entsprechende Währungskennzeichen (z.B. auf `EUR`). 44 | 45 | Wenn **MoneyMonkey** die Währung des Kontos kennt, so werden Buchungen in einer anderen Währung automatisch übersprungen. Das ist z.B. bei PayPal-Konten hilfreich, da _MoneyMoney_ diese Buchungen selbst nicht trennt und gemeinsam exportiert. Würden diese Buchungen übernommen, würde der Saldo nicht stimmen. 46 | 47 | ### Kategorien einrichten 48 | 49 | 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. 50 | 51 | Das Gegenkonto wird direkt an den eigentlichen Namen der Kategorie am Ende des Titels in eckigen Klammern eingetragen (z.B. `Bürobedarf [6815]`). 52 | 53 | Um den Namen einer Kategorie zu ändern, wählt man die Kategorie in der Seitenleiste aus und wählt aus dem Kontextmenü den Eintrag `Einstellungen …` (oder CMD-I drücken). 54 | 55 | #### Umsätze überspringen 56 | 57 | Umsätze, deren Betrag 0,00 ist, werden generell **NICHT** exportiert. 58 | 59 | Wird für eine Kategorie das Gegenkonto `[0000]` bestimmt, werden die dieser Kategorie zugewiesenen Umsätze automatisch übersprungen, also **NICHT** exportiert. Diese Funktion sollte nur in Ausnahmefällen gewählt werden (z.B. für Buchungen in Fremdwährungen, wofür sich aber eher die Einstellung einer Währung für das Bankkonto (siehe oben) empfiehlt). 60 | 61 | _Hinweis_: Wenn Buchungen, deren Saldo nicht null ist, aus dem Export herausgenommen werden, werden in der Buchhaltung falsche Saldi erzeugt, die dann manuell korrigiert werden müssten. 62 | 63 | ### Steuersatz konfigurieren 64 | 65 | Für die Gegenkonten, die über eine *Steuerautomatik* verfügen (wo sich also der Steuersatz automatisch aus dem Buchungskonto ableitet) ist in der Regel keine Angabe eines Steuersatzes erforderlich. 66 | 67 | Für Gegenkonten ohne Steuerautomatik oder solche mit variablen Steuersätzen kann in der Kategorie auch noch ein **Steuersatz** mit angegeben werden. Dazu muss der Steuersatz in geschweiften Klammern in den Titel geschrieben werden. 68 | 69 | ``` 70 | Reisekosten Mietwagen [6673] {VSt19} 71 | Reisekosten Taxi [6673] {VSt7} 72 | Betriebsausgaben 0% [6300] {-} 73 | ``` 74 | 75 | Die Bezeichnungen des Steuersatzes müssen dabei den in der Buchhaltungssoftware verwendeten Konten entsprechen (z.B. Kontenrahmen SKR03 oder SKR04), da sie vom Exportskript nur durchgereicht und nicht interpretiert werden. 76 | 77 | #### Abweichenden Steuersatz pro Umsatz einstellen 78 | 79 | Wenn man nur für einen oder wenige Umsätze einen abweichenden Steuersatz angeben möchte, lohnt sich Anlegen einer Kategorie dafür oft nicht und die Liste der Kategorien würde nur unnötig aufgebläht und entsprechend unübersichtlich werden. Daher kann man für diese Ausnahmen den Steuersatz auch direkt im Notizfeld eines Umsatzes angeben. 80 | 81 | Dazu wählt man den Menüeintrag `Konto -> Notiz hinzufügen...` (bzw. aus dem Kontextmenü) aus und trägt einen entsprechenden Text ein, der den gewünschten Steuersatz wie oben beschrieben angibt. 82 | 83 | ### Kostenstellen konfigurieren 84 | 85 | 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. 86 | 87 | Die Kostenstellen werden im Kategorie-Titel über das Rautezeichen eingeleitet: 88 | 89 | ``` 90 | Einnahmen Veranstaltungen Verkauf [4400] #EVENT 91 | Einnahmen Veranstaltungen Tickets [4300] #EVENT 92 | ``` 93 | 94 | Werden einer Buchung mehr als zwei unterschiedliche Kostenstellen zugewiesen führt das zum Abbruch des Exports. 95 | 96 | _Hinweis:_ *MonKey Office* erlaubt es, Kostenstellen mit beliebigen Zeichen (einschließlich Leerzeichen) zu benennen. *MoneyMonkey* unterstützt aus Gründen der Übersichtlichkeit und als Analogie zu Hashtags nur alphanumerische Bezeichner (Groß- und Kleinbuchstaben und Ziffern) zzgl. des Unterstrichs ("_") aber keine Leerzeichen). 97 | 98 | 99 | 100 | #### Kostenstellen pro Umsatz einstellen 101 | 102 | Wie schon beim Steuersatz können auch die Kostenstellen pro Umsatz angegeben werden, in dem sie in das Notizfeld des Umsatzes eingetragen werden (`Konto -> Notiz hinzufügen...`). So können auch Einzelumsätze unabhängig von Ihrer Kategorie z.B. einzelnen Projekten zugewiesen und später in *MonKey Office* ausgewertet werden. 103 | 104 | 105 | ### Vererbung über Kategoriegruppen 106 | 107 | _MoneyMoney_ erlaubt die Gruppierung von Kategorien durch Kategoriegruppen. Wenn man mehrere Unterkategorien für bestimmte Umsätze unterscheiden möchte, die aber alle über die gleiche oder zumindest nur in Teilen abweichende Buchhaltungs-Konfiguration verfügen, können die gemeinsamen Werte der Kategoriegruppe zugewiesen werden. 108 | 109 | Diese Einstellungen werden automatisch an die darunter liegenden Kategorien nach folgenden Regeln vererbt: 110 | 111 | * Werden in den Unterkategorien das *Gegenkonto* oder der *Steuersatz* ein weiteres Mal spezifiziert, *überschreiben* diese Werte die Vorgabe der Gruppe. 112 | * Werden in der Unterkategorie *Kostenstellen* spezifiziert, so *ergänzen* diese die vorher benannten Kostenstellen. 113 | 114 | Folgende Kategorie-Hierarchie: 115 | 116 | * `Reisekosten [6673] {VSt19} #REISE` 117 | * `car2go #CAR2GO` 118 | * `DriveNow #DRIVENOW` 119 | * `Flinkster #FLINKSTER` 120 | * `Taxi {VSt7} #TAXI` 121 | 122 | ist äquivalent zu 123 | 124 | * `car2go [6673] {VSt19} #REISE #CAR2GO` 125 | * `DriveNow [6673] {VSt19} #REISE #DRIVENOW` 126 | * `Flinkster [6673] {VSt19} #REISE #FLINKSTER` 127 | * `Taxi [6673] {VSt7} #REISE #TAXI` 128 | 129 | ist aber deutlich übersichtlicher und einfacher zu verwalten. 130 | 131 | Wie schon bei einer einzelnen Buchung gilt: werden einer Buchung durch Vererbung mehr als zwei unterschiedliche Kostenstellen zugewiesen führt das zum Abbruch des Exports. 132 | 133 | 134 | ## MoneyMonkey starten 135 | 136 | Wenn nun in _MoneyMoney_ Umsätze ausgewählt werden, kann man im Menü `Konto` den Eintrag `Umsätze exportieren …` auswählen. In der Folge erscheint ein Dialog zur Bestimmung einer Exportdatei. In dem Auswahlmenü unten in diesem Dialog kann man nun den Punkt `MoneyMonkey (.csv)` auswählen. Damit wird das Plugin für den Export ausgewählt. 137 | 138 | Wurde das Plugin ausgewählt, erscheint darunter noch eine Option `Umsätze müssen als erledigt markiert sein`. Ist diese Option gesetzt, muss bei allen zu exportierenden Umsätzen in _MoneyMoney_ das Markierungsfeld hinter dem Umsatz ausgewählt sein. Fehlt dieses bei einem Umsatz bricht der Export mit einer entsprechenden Fehlermeldung ab. Mit dieser Option kann man sicherstellen, dass jeder Umsatz bevor er in die Buchhaltung übernommen wird eine explizite Prüfung erfahren hat (Plausibilität, korrekte Kategoriezuordnung, Beleg vorhanden etc.). Wenn man auf eine solche Prüfung verzichten möchte oder zu Testzwecken einen Export vornehmen will kann man diese Option auch ausschalten, sie ist aber empfohlen. 139 | 140 | Eine zweite Option heißt "Nur Umsätze mit gültigem Buchungskonto exportieren". Wenn diese Option gesetzt ist, werden nur Umsätze exportiert, die einem gültigen Buchungskonto zugeordnet sind. Diese Option ist empfohlen, da sonst auch Umsätze exportiert werden, die keinem gültigen Buchungskonto zugeordnet sind. 141 | 142 | Wenn keine Konfigurationsfehler gefunden werden startet **MoneyMonkey** anschließend den Export der ausgewählten Umsätze in die angegebene Datei. 143 | 144 | Ein Umsatz wird _nicht_ exportiert wenn eine der folgenden Bedingungen erfüllt ist 145 | 146 | * Der Umsatz wurde dem Gegenkonto [0000] zugeordnet 147 | * Im Bankkonto eines Umsatzes wurde eine Währung konfiguriert und der Umsatz hat eine andere Währung als die dort eingestellte 148 | 149 | Das Skript _beendet_ den Export vorzeitig wenn einer der folgenden Fehler detektiert wurde: 150 | 151 | * Ein Umsatz wurde keiner Kategorie zugeordnet 152 | * Für das Bankkonto eines Umsatzes wurde kein Finanzkonto konfiguriert 153 | * Für eine eingestellte Kategorie ist kein Gegenkonto ermittelbar 154 | * Der Umsatz wurde nicht bestätigt (Markierungsfeld gesetzt - nur wenn die Option gesetzt wurde, s.o.) 155 | * Es wurden einer Kategorie mehr als zwei Kostenstellen zugeordnet 156 | 157 | Der Fehler wird entsprechend in einem Dialog angezeigt. In jedem dieser Fälle wird keine Datei erzeugt. 158 | 159 | 160 | ## Format der Exportdatei 161 | 162 | Die Exportdatei ist eine klassische CSV-Datei mit den Spalten "Buchungskonto", "Gegenkonto", "Betrag", "Währung", "Steuersatz", "Kostenstellen", "Notiz". Die Felder sind durch Kommas getrennt, wenn Werte Leerzeichen oder Kommas enthalten, werden diese in Anführungszeichen gesetzt. Diese Datei sollte sich mit jeder CSV-kompatiblen Software öffnen lassen. 163 | 164 | Das Feld "Text" enthält den Buchungstext, der sich aus dem Verwendungszweck und der manuellen Notiz des Umsatzes zusammensetzt (die man in MoneyMoney in den Kommentar des Umsatzes via CMD-Shift-K eintragen kann). 165 | 166 | Das Feld "Notiz" enthält weitere Metadaten, die für die Buchhaltung relevant sein die der Banktransaktion entnommen werden können. Bei SEPA-Überweisungen werden z.B. von manchen Bankendie Felder "Umsatzart", "Mandatsreferenz", "Kreditor-ID" und "End-To-End-Reference" ausgefüllt. Sind diese Felder enthalten schreibt MoneyMoney diese in einem "Feld=Wert" Format und durch Semikolon getrennt in das Feld "Notiz", so dass man diese ggf. auch noch automatisiert übernehmen kann. 167 | 168 | ## Import in MonKey Office 169 | 170 | Wenn die Exportdatei geschrieben wurde kann sie anschließend über die Funktion "Import & Export -> Textdatei importieren" importiert werden. 171 | 172 | ###Import konfigurieren 173 | 174 | Um die Datei imporieren zu können muss zunächst eine Einstellung dafür angelegt werden. Diese muss mit den folgenden Einstellungen angelegt werden: 175 | 176 | * Bereich: `Buchungen` 177 | * Trennzeichen für Felder: `Komma` 178 | * Trennzeichen für Datensätze: `LF` 179 | * Text in Anführungszeichen: `Doppelt "` 180 | * Zeichensatz für: `UTF-8` 181 | * Importieren ab Zeile: `2` 182 | * Steuerautomatik: _abhängig von der Buchhaltungssystematik_ 183 | * Einzeilig: **AUS** 184 | 185 | Bevor es losgehen kann müssen noch die Felder aus der MoneyMonkey-Exportdatei den Feldern der Buchhaltung zugeordnet werden. Das kann halbautomatisch erfolgen, da die Spaltentitel der Exportdatei dabei 1:1 den Bezeichnungen in MonKey Office entsprechen. Dazu folgende Schritte vornehmen: 186 | 187 | 1. Über den Button _Datei_ eine MoneyMonkey-Exportdatei ausgewählen 188 | 2. Die Einstellung _Importieren ab Zeile_ vorübergehend auf den Wert `1` setzen 189 | 3. Den Button _Felder zuordnen_ klicken. Damit sollten alle Spalten in der Exportdatei den Feldern der Buchhaltung zugeordnet werden. Zur Sicherheit noch mal drüber schauen, ob alles geklappt hat, sonst manuell zuordnen. 190 | 4. Die Einstellung _Importieren ab Zeile_ wieder auf den Wert `2` setzen 191 | 192 | Damit kann die Import-Einstellung verwendet werden. Neben dem Button `Datei` wird nun noch der Name der zuvor ausgewählten Datei angezeigt und darunter unter `Ordner` der Ordner, in dem sich diese Datei befand. Wenn beide Felder so belassen werden, wird beim Aktivieren der Einstellung automatisch auf genau diese Datei zugegriffen. Wenn man den Eintrag bei `Datei` löscht, erscheint beim Aktivieren des Imports automatisch ein Dateiauswahlfenster (voreingestellt auf den eingestellten Ordner). Darüber kann man sich beim Import entweder Zeit sparen oder auch sicherstellen, dass man explizit eine bestimmte Datei (oder einen bestimmten Ordner) manuell auswählen muss. 193 | 194 | 195 | ### Import starten 196 | 197 | Wenn die Einstellungen für den Import vorgenommen wurden kann die Exportdatei importiert werden. Dabei sollte ggf. noch mal überprüft werden, ob die richtigen Spalten gewählt wurden und ob den Buchungen die richtigen Finanz- bzw. Gegenkonten, Steuersätze und Kostenstellen zugeordnet wurden. 198 | 199 | Nach dem Import sind die Buchungen sofort gültig und müssen nicht noch einmal bestätigt werden. Damit lassen sich auch große Zahlen an Umsätzen schnell in Buchungen überführen. 200 | 201 | Vorsicht: In der Importdatei angegebene Kostenstellen werden von **MonKey Office** automatisch angelegt (und sollten dann später in `Vorgaben -> Kostenstellen` noch entsprechend benannt werden). 202 | 203 | ### Empfohlener Workflow 204 | 205 | Wie oft und mit welcher Granularität importiert werden soll hängt stark vom Bedarf ab. Üblicherweise sollte man mindestens monatlich die Daten von **MoneyMoney** in **MonKey Office** überführen allein schon um sicherzustellen, dass man bei der Vergabe der Kategorien und/oder Kostenstellen keine Fehler gemacht hat. Typische Fehlbuchungen lassen sich zumeist mit `Buchhaltung -> Summen und Salden` bzw. dem `Buchhaltung -> Kontoauszug` gut erkennen und entsprechende Fehler aufspüren. 206 | 207 | Der Name der jeweils gewählten Exportdatei ist in den exportierten Umsätze jeweils im Feld "BelegNr" abgelegt. Damit lassen sich Umsätze aus einem bestimmten Exportvorgang problemlos über den Buchungsfilter wiederfinden und bei Bedarf auch löschen, so dass ein Import auch wiederholt werden kann, ohne die sonstigen Buchungen zu beeinflussen. 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /moneymonkey.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Usage: 4 | # 5 | # moneymonkey.sh command -o targetfile -f date -t date -l days -a account 6 | 7 | 8 | # Primäre Konfigurationsvariable 9 | # 10 | # ACCOUNT Name des MoneyMoney Bankkontos, dass exportiert werden soll (IBAN oder vergebener Name) 11 | # TARGETFILE Pfad der Exportdatei, die erstellt werden soll. Der Dateiname wird im Feld "Beleg" jeder Buchung mit abgelegt 12 | 13 | ACCOUNT="${MONEYMONKEY_ACCOUNT}" 14 | TARGETFILE="${MONEYMONKEY_TARGETFILE}" 15 | 16 | # Grundeinstellung: Exportiere die Buchungen von gestern 17 | 18 | YESTERDAY=$(date -v-1d +%Y-%m-%d) 19 | FROM_DATE=${YESTERDAY} 20 | TO_DATE=${YESTERDAY} 21 | 22 | 23 | # Einlesen der Optionen 24 | 25 | function usage { 26 | echo "./$(basename $0) export -o outfile -f from_date -t to_date -l days -a account" 27 | exit 1 28 | } 29 | 30 | 31 | function export_from_moneymoney { 32 | 33 | OPTSTRING="f:t:o:a:l:" 34 | 35 | while getopts ${OPTSTRING} arg; do 36 | case ${arg} in 37 | a) 38 | ACCOUNT="${OPTARG}" 39 | ;; 40 | o) 41 | TARGETFILE="${OPTARG}" 42 | ;; 43 | f) 44 | FROM_DATE="${OPTARG}" 45 | ;; 46 | t) 47 | TO_DATE="${OPTARG}" 48 | ;; 49 | l) 50 | TO_DATE="${YESTERDAY}" 51 | FROM_DATE=$(date -v-${OPTARG}d +%Y-%m-%d) 52 | ;; 53 | :) 54 | echo "$0: Diese Option benötigt einen Parameter -$OPTARG." >&2 55 | exit 1 56 | ;; 57 | ?) 58 | echo "Unbekannte Option: -${OPTARG}." 59 | usage 60 | exit 2 61 | ;; 62 | esac 63 | done 64 | 65 | 66 | # Überprüfen, ob eine Exportdatei angegeben wurde 67 | 68 | if [ -z "${TARGETFILE}" ] 69 | then 70 | echo "$0: Es wurde keine Exportdatei angegeben (verwende -o)" 71 | exit 1 72 | fi 73 | 74 | # Wurde kein Ende-Datum angegeben, exportiere nur einen Tag 75 | 76 | if [ -z "${TO_DATE}" ] 77 | then 78 | TO_DATE=${FROM_DATE} 79 | fi 80 | 81 | # Gesetzte Parameter anzeigen 82 | 83 | echo "Konto: ${ACCOUNT}" 84 | echo "Von Datum: ${FROM_DATE}" 85 | echo "Bis Datum: ${TO_DATE}" 86 | echo "Exportdatei: ${TARGETFILE}" 87 | 88 | # Export in MoneyMoney durchführen lassen 89 | 90 | APPLESCRIPT='tell application "MoneyMoney" to set result to export transactions from account "'${ACCOUNT}'" from date "'${FROM_DATE}'" to date "'${TO_DATE}'" as "MoneyMonkey"' 91 | TMPFILE=$(osascript -e "${APPLESCRIPT}") 92 | 93 | # Verwende den Namen der Exportdatei als Belegnamen 94 | 95 | TMPFILENAME=`basename "${TMPFILE}"` 96 | TARGETFILENAME=`basename "${TARGETFILE}"` 97 | sed "s;${TMPFILENAME};${TARGETFILENAME};" ${TMPFILE} >"${TARGETFILE}" 98 | rm "${TMPFILE}" 99 | 100 | # Anzeigen der Exportdatei 101 | 102 | ls -l "${TARGETFILE}" 103 | } 104 | 105 | case "${1}" in 106 | export) 107 | shift 108 | export_from_moneymoney "$@" 109 | ;; 110 | *) 111 | echo "Unbekanntes Kommando: ${1}" 112 | usage 113 | exit 2 114 | ;; 115 | esac 116 | 117 | --------------------------------------------------------------------------------