204 lines
7.1 KiB
Nix
204 lines
7.1 KiB
Nix
{ common, core, helpers, ... }:
|
|
let
|
|
inherit(common) Transaction;
|
|
inherit(core) debug expression list path string;
|
|
inherit(helpers) parseAmountComma parseBritishDateTime trim;
|
|
|
|
convertTransaction
|
|
= { currency, lookUpAccount, self, ... }:
|
|
{ Adresse, Beschreibung, Betrag, Betreff, Datum, Kategorie, Land, PLZ, Stadt, ... } @ transaction:
|
|
let
|
|
address
|
|
= {
|
|
country = trim Land;
|
|
municipality = trim Stadt;
|
|
postalCode = trim PLZ;
|
|
text = trim Adresse;
|
|
};
|
|
amount = parseAmountComma Betrag currency;
|
|
category = trim Kategorie;
|
|
client
|
|
= lookUpAccount
|
|
{
|
|
inherit address category description details message subject uid;
|
|
};
|
|
dateTime = parseBritishDateTime Datum "00:00:00";
|
|
description = trim Beschreibung;
|
|
details = trim transaction."Weitere Details";
|
|
uid
|
|
= if description == "ZAHLUNG/ÜBERWEISUNG ERHALTEN BESTEN DANK"
|
|
then
|
|
"American Express"
|
|
else
|
|
trim (list.head (string.splitLines description));
|
|
message = trim transaction."Erscheint auf Ihrer Abrechnung als";
|
|
subject = trim Betreff;
|
|
in
|
|
Transaction
|
|
{
|
|
inherit dateTime description;
|
|
credit = { ${client.uid} = amount; };
|
|
debit = { ${self.uid} = amount; };
|
|
};
|
|
|
|
next
|
|
= { case, columns, index, quote, transaction, text, journal } @ state:
|
|
cell:
|
|
let
|
|
field = list.get columns index;
|
|
index' = index + 1;
|
|
|
|
isCell = string.isInstanceOf cell;
|
|
isColumnSep = sep == ",";
|
|
isFinalCell = index' == list.length columns;
|
|
isLineBreak = sep == "\n";
|
|
|
|
quoted = string.match "\"(.+)\"|'(.+)'" cell;
|
|
quoted0 = list.head quoted;
|
|
quoted1 = list.get quoted 1;
|
|
quoted' = if quoted0 != null then quoted0 else quoted1;
|
|
quotedStart = string.match "([\"'])(.+)" cell;
|
|
quotedStop = string.match "(.+)([\"'])" cell;
|
|
|
|
sep = list.get cell 1;
|
|
in
|
|
{
|
|
FinaliseCell
|
|
= if isFinalCell
|
|
then
|
|
if isLineBreak
|
|
then
|
|
{
|
|
case = "ParseCell";
|
|
index = 0;
|
|
journal = journal ++ [ transaction ];
|
|
transaction = {};
|
|
}
|
|
else
|
|
debug.panic [ "next" "FinaliseCell" ] "Line Break expected!"
|
|
else if isColumnSep
|
|
then
|
|
{
|
|
case = "ParseCell";
|
|
index = index';
|
|
quote = null;
|
|
}
|
|
else if isLineBreak && quote != null
|
|
then
|
|
{
|
|
case = "Quoted";
|
|
text = "${text}${quote}${string.concat cell}";
|
|
}
|
|
else
|
|
debug.panic [ "next" "FinaliseCell" ] "Column Seperator expected!";
|
|
|
|
ParseCell
|
|
= if !isCell
|
|
then
|
|
debug.panic [ "next" "ParseCell" ] "Cell expected!"
|
|
else if quoted != null
|
|
then
|
|
{
|
|
case = "FinaliseCell";
|
|
transaction
|
|
= transaction
|
|
// {
|
|
${field} = quoted';
|
|
};
|
|
}
|
|
else if quotedStart != null
|
|
then
|
|
{
|
|
case = "Quoted";
|
|
quote = list.head quotedStart;
|
|
text = list.get quotedStart 1;
|
|
}
|
|
else
|
|
{
|
|
case = "FinaliseCell";
|
|
transaction
|
|
= transaction
|
|
// {
|
|
${field} = cell;
|
|
};
|
|
};
|
|
|
|
ParseHeader
|
|
= if isCell
|
|
then
|
|
{
|
|
columns = columns ++ [ cell ];
|
|
}
|
|
else if isColumnSep
|
|
then
|
|
{}
|
|
else
|
|
{
|
|
case = "ParseCell";
|
|
};
|
|
|
|
Quoted
|
|
= if !isCell
|
|
then
|
|
{
|
|
text = "${text}${string.concat cell}";
|
|
}
|
|
else if quotedStop != null
|
|
&& quote == (list.get quotedStop 1)
|
|
then
|
|
{
|
|
case = "FinaliseCell";
|
|
transaction
|
|
= transaction
|
|
// {
|
|
${field} = "${text}${list.head quotedStop}";
|
|
};
|
|
text = "${text}${list.head quotedStop}";
|
|
}
|
|
else
|
|
{
|
|
text = "${text}${cell}";
|
|
};
|
|
}.${case};
|
|
|
|
next'
|
|
= { ... } @ state:
|
|
cell:
|
|
state // (next state cell);
|
|
|
|
parseCells
|
|
= list.fold next'
|
|
{
|
|
case = "ParseHeader";
|
|
columns = [];
|
|
index = 0;
|
|
journal = [];
|
|
quote = null;
|
|
text = "";
|
|
transaction = {};
|
|
};
|
|
|
|
parseFile
|
|
= fileName:
|
|
(
|
|
parseCells
|
|
(
|
|
string.split
|
|
"( *)([\n,])( *)"
|
|
(path.readFile fileName)
|
|
)
|
|
).journal;
|
|
in
|
|
{
|
|
journal
|
|
= files:
|
|
{ ... } @ env:
|
|
list.map
|
|
(convertTransaction env)
|
|
(
|
|
list.concatMap
|
|
parseFile
|
|
files
|
|
);
|
|
}
|