Einführung
MoneyMoney kann mit Extensions erweitert werden, um Umsätze aus anderen Anwendungen zu importieren. Diese Extensions sind kurze Lua-Skripte, die einfach zu erstellen, zu modifizieren und auszuwechseln sind. Bisher nicht unterstützte Dateiformate lassen sich durch neu geschriebene Skripte nachrüsten.
Die Lua-Skripte werden in einer virtuellen Maschine ausgeführt und kommunizieren über eine dokumentierte API mit MoneyMoney. Das vorliegende Dokument spezifiziert diese API. Die Wahl der Skriptsprache fiel auf Lua, da sie relativ leicht zu erlernen ist und sich gut mit C/C++/Objective-C kombinieren lässt. Für unsere Extensions reicht es vollkommen aus, die ersten fünf Kapitel von »Programming in Lua« gelesen zu haben. Die meisten innerhalb einer Extension aufgerufenen Funktionen sind nämlich gar nicht Bestandteil von Lua, sondern existieren ausschließlich in MoneyMoney.
Vom Skript zur Extension
Installation
Das Verzeichnis, in dem eigene Extensions abgelegt werden, kann über Menü Hilfe → Zeige Datenbank im Finder im Finder geöffnet werden:
~/Library/Containers/com.moneymoney-app.retail/Data/Library/Application Support/MoneyMoney/Extensions
Jede Änderung an Dateien in diesem Verzeichnis wirkt sich unmittelbar auf MoneyMoney aus, d.h. es ist nicht nötig, MoneyMoney neu zu starten.
Fehlermeldungen werden im Protokoll-Fenster von MoneyMoney angezeigt. Das Protokoll-Fenster lässt sich mit der Menüfunktion »Fenster« → »Protokollfenster« erreichen.
Die eigene Extension wird beim Aufruf der Menüfunktion »Konto« → »Umsätze importieren« in der Formatauswahl mit der im Parameter format festgelegten Bezeichnung (siehe nächster Abschnitt) angezeigt und kann dort ausgewählt werden.
Registrierung einer Extension
Ein Skript weist sich als Import-Extension aus, indem es am Beginn des Skripts einen Aufruf der Art
Importer{
version = 1.05,
format = "Comma-separated values",
fileExtension = "csv",
description = "Import transactions from CSV file"
}
enthält. Bei den benannten Parametern der Funktion Importer handelt es sich um:
| Parameter | Typ | Optional | Beschreibung |
|---|---|---|---|
version | Number | nein | Versionsnummer der Extension |
format | String | ja | Bezeichnung des Dateiformats, wie sie in der Formatauswahl des Datei-Öffnen-Dialogs angezeigt wird |
fileExtension | String | ja | Dateinamenserweiterung |
description | String | ja | Beschreibung der Extension |
Lua-Laufzeitumgebung
Die Parameter der Funktion Importer sind später im Skript als globale Variablen version, format, fileExtension und description zugänglich. Zusätzlich ist auch noch die globale Variable extensionName mit dem Namen der Extension definiert.
Die Variablen MM.productName und MM.productVersion enthalten Informationen zur Anwendung, also MoneyMoney.
Die Ausgabe der Standard-Funktion print wird im Protokoll-Fenster von MoneyMoney angezeigt.
Die Standard-Funktion error bricht die Ausführung des Skripts ab.
Das Skript selbst muss UTF-8-kodiert sein und es werden auch alle Strings als UTF-8-Strings zwischen dem Skript und MoneyMoney übergeben, außer es steht in der API-Beschreibung, dass es sich um Binärdaten handelt.
Ablauf
MoneyMoney treibt die Ausführung des Skripts, was bedeutet, dass jedes Skript eine bestimmte Funktion als Einsprungspunkt zur Verfügung stellen muss. MoneyMoney ruft zum Umsatzimport die Funktion ReadTransactions des Skripts auf.
Es wird das einfache I/O-Modell von Lua verwendet: Das Skript braucht die Daten bloß mit assert(io.read(...)) von der Standardeingabe (stdin) zu lesen. Das Öffnen und Schließen der Datei übernimmt MoneyMoney.
Vorlage
Folgende Vorlage kann als Ausgangspunkt für eigene Import-Extensions dienen.
Importer{
version=1.00,
format="Tab-separated values",
fileExtension="tsv"
}
local function strToDate (str)
-- Helper function for converting localized date strings to timestamps.
local d, m, y = string.match(str, "(%d%d).(%d%d).(%d%d%d%d)")
return os.time{year=y, month=m, day=d}
end
function ReadTransactions (account)
-- Read transactions from a file with the format "date<TAB>amount<TAB>purpose".
local transactions = {}
for line in assert(io.lines()) do
local values = {}
for value in string.gmatch(line, "[^\t]+") do
table.insert(values, value)
end
if #values >= 3 then
local transaction = {
bookingDate = strToDate(values[1]),
amount = tonumber(values[2]),
purpose = values[3]
}
table.insert(transactions, transaction)
end
end
return transactions
end
Einsprungspunkte
ReadTransactions
function ReadTransactions (account)
Liest die Umsätze aus der Datei. Die Daten werden mit assert(io.read(...)) bzw. assert(io.lines()) von der Standardeingabe gelesen; das Öffnen und Schließen der Datei übernimmt MoneyMoney.
| Parameter | Typ | Optional | Beschreibung |
|---|---|---|---|
account | Table | nein | Das Konto, in das die Umsätze importiert werden. Die Struktur ist im Abschnitt »Datenstruktur eines Kontos« beschrieben. |
| Rückgabe | Typ | Beschreibung |
|---|---|---|
| — | Array | Die Umsätze aus der Datei. Die Struktur der Array-Elemente ist im Abschnitt »Datenstruktur eines Umsatzes« beschrieben. |
| — | String | Eine Fehlermeldung. |
Datenstrukturen
Datenstruktur eines Kontos
Die Informationen eines Kontos werden in einer Lua-Tabelle gespeichert. Folgende Felder sind definiert:
| Feld | Typ | Beschreibung |
|---|---|---|
name | String | Bezeichnung des Kontos |
owner | String | Name des Kontoinhabers |
accountNumber | String | Kontonummer |
subAccount | String | Unterkontomerkmal |
bankCode | String | Bankleitzahl |
currency | String | Kontowährung |
iban | String | IBAN |
bic | String | BIC |
type | Konstante | Kontoart, siehe unten |
Mögliche Werte für die Kontoart type:
| Konstante | Bedeutung |
|---|---|
AccountTypeGiro | Girokonto |
AccountTypeSavings | Sparkonto |
AccountTypeFixedTermDeposit | Festgeldanlage |
AccountTypeLoan | Darlehenskonto |
AccountTypeCreditCard | Kreditkarte |
AccountTypeCash | Bargeld |
AccountTypeOther | Sonstige |
Datenstruktur eines Umsatzes
Die Daten eines Umsatzes werden in einer Lua-Tabelle gespeichert:
| Feld | Typ | Beschreibung |
|---|---|---|
name | String | Name des Auftraggebers/Zahlungsempfängers |
accountNumber | String | Kontonummer oder IBAN des Auftraggebers/Zahlungsempfängers |
bankCode | String | Bankleitzahl oder BIC des Auftraggebers/Zahlungsempfängers |
amount | Number | Betrag |
currency | String | Währung |
bookingDate | Number | Buchungstag; Die Angabe erfolgt in Form eines POSIX-Zeitstempels. |
valueDate | Number | Wertstellungsdatum; Die Angabe erfolgt in Form eines POSIX-Zeitstempels. |
purpose | String | Verwendungszweck; Mehrere Zeilen können durch Zeilenumbrüche (\n) getrennt werden. |
transactionCode | Number | Geschäftsvorfallcode |
textKeyExtension | Number | Textschlüsselergänzung |
purposeCode | String | SEPA-Verwendungsschlüssel |
bookingKey | String | SWIFT-Buchungsschlüssel |
bookingText | String | Umsatzart |
primanotaNumber | String | Primanota-Nummer |
batchReference | String | Sammlerreferenz |
endToEndReference | String | SEPA-Ende-zu-Ende-Referenz |
mandateReference | String | SEPA-Mandatsreferenz |
creditorId | String | SEPA-Gläubiger-ID |
returnReason | String | Rückgabegrund |
booked | Boolean | Gebuchter oder vorgemerkter Umsatz |
category | String | Kategorienname |
comment | String | Notiz |
MM-Funktionen
Lokalisierung
MM.localizeText
str = MM.localizeText(str)
Übersetzt einen Text. Diese Funktion ist primär für die mit MoneyMoney ausgelieferten Extensions gedacht. Sie ist ein Wrapper für die Cocoa-Funktion NSLocalizedString und liefert natürlich nur dann eine Übersetzung, wenn der Text in MoneyMoney hinterlegt worden ist.
| Parameter | Typ | Optional | Beschreibung |
|---|---|---|---|
str | String | nein | Englischer Text |
| Rückgabe | Typ | Beschreibung |
|---|---|---|
str | String | Übersetzter Text |
MM.localizeDate
str = MM.localizeDate([format, ]date)
Lokalisiert eine Zeitangabe. Da die von Lua unterstützten POSIX Locales innerhalb von macOS-Apps nicht zur Verfügung stehen, baut diese Funktion auf der Cocoa-Klasse NSDateFormatter auf.
| Parameter | Typ | Optional | Beschreibung |
|---|---|---|---|
format | String | ja | Ausgabeformat; Die Angabe erfolgt wie bei der Cocoa-Klasse NSDateFormatter nach dem Unicode Technical Standard #35. |
date | Number | nein | Datum; Die Angabe erfolgt in Form eines POSIX-Zeitstempels. |
| Rückgabe | Typ | Beschreibung |
|---|---|---|
str | String | Datum im lokalisierten Format |
MM.localizeNumber
str = MM.localizeNumber([format, ]num)
Lokalisiert eine Zahl. Da die von Lua unterstützten POSIX Locales innerhalb von macOS-Apps nicht zur Verfügung stehen, baut diese Funktion auf der Cocoa-Klasse NSNumberFormatter auf.
| Parameter | Typ | Optional | Beschreibung |
|---|---|---|---|
format | String | ja | Ausgabeformat; Die Angabe erfolgt wie bei der Cocoa-Klasse NSNumberFormatter nach dem Unicode Technical Standard #35. |
num | Number | nein | Zahl |
| Rückgabe | Typ | Beschreibung |
|---|---|---|
str | String | Zahl im lokalisierten Format |
MM.localizeAmount
str = MM.localizeAmount([format, ]amount[, currency])
Lokalisiert einen Währungsbetrag.
| Parameter | Typ | Optional | Beschreibung |
|---|---|---|---|
format | String | ja | Ausgabeformat; Die Angabe erfolgt wie bei der Cocoa-Klasse NSNumberFormatter nach dem Unicode Technical Standard #35. |
amount | Number | nein | Betrag |
currency | String | ja | Währung; Ohne diesen Parameter wird nur der Betrag ohne Währungsangabe zurückgegeben. |
| Rückgabe | Typ | Beschreibung |
|---|---|---|
str | String | Währungsbetrag im lokalisierten Format |
Zeichenketten und Kodierung
MM.toEncoding
data = MM.toEncoding(charset, str[, bom])
Konvertiert einen Text von UTF-8 zu einem anderen Zeichensatz.
| Parameter | Typ | Optional | Beschreibung |
|---|---|---|---|
charset | String | nein | Zeichensatz; Die Angabe erfolgt wie bei HTTP nach IANA. |
str | String | nein | Text in UTF-8 |
bom | Boolean | ja | Wenn dieser Parameter mit true belegt ist, wird der Rückgabewert um eine Byte Order Mark (BOM) ergänzt, sofern sie für den angegebenen Zeichensatz existiert. |
| Rückgabe | Typ | Beschreibung |
|---|---|---|
data | Binary | Text im angegebenen Zeichensatz |
Siehe auch: MM.fromEncoding
MM.fromEncoding
str = MM.fromEncoding(charset, data)
Konvertiert einen Text von einem anderen Zeichensatz zu UTF-8.
| Parameter | Typ | Optional | Beschreibung |
|---|---|---|---|
charset | String | nein | Zeichensatz; Die Angabe erfolgt wie bei HTTP nach IANA. |
data | Binary | nein | Text im angegebenen Zeichensatz |
| Rückgabe | Typ | Beschreibung |
|---|---|---|
str | String | Text in UTF-8 |
Siehe auch: MM.toEncoding