Source code for tariochbctools.importers.revolut.importer
import csv
import logging
import re
from datetime import timedelta
from typing import Any
import beangulp
from beancount.core import amount, data
from beancount.core.number import ZERO, D
from dateutil.parser import parse
[docs]
class Importer(beangulp.Importer):
"""An importer for Revolut CSV files."""
def __init__(
self, filepattern: str, account: data.Account, currency: str, fee: Any = None
):
self._filepattern = filepattern
self._account = account
self.currency = currency
self._fee = fee
[docs]
def identify(self, filepath: str) -> bool:
return re.search(self._filepattern, filepath) is not None
[docs]
def extract(self, filepath: str, existing: data.Entries) -> data.Entries:
entries = []
with open(filepath) as csvfile:
reader = csv.DictReader(
csvfile,
[
"Type",
"Product",
"Started Date",
"Completed Date",
"Description",
"Amount",
"Fee",
"Currency",
"State",
"Balance",
],
delimiter=",",
skipinitialspace=True,
)
next(reader)
is_fee_mode = self._fee is not None
for row in reader:
try:
bal = D(row["Balance"].replace("'", "").strip())
amount_raw = D(row["Amount"].replace("'", "").strip())
amt = amount.Amount(amount_raw, row["Currency"])
balance = amount.Amount(bal, self.currency)
book_date = parse(row["Completed Date"].strip()).date()
fee_amt_raw = D(row["Fee"].replace("'", "").strip())
fee = amount.Amount(-fee_amt_raw, row["Currency"])
except Exception as e:
logging.warning(e)
continue
if is_fee_mode and fee_amt_raw == ZERO:
continue
postings = [
data.Posting(self._account, amt, None, None, None, None),
]
description = row["Description"].strip()
if is_fee_mode:
postings = [
data.Posting(self._account, fee, None, None, None, None),
data.Posting(
self._fee["account"], -fee, None, None, None, None
),
]
description = f"Fees for {description}"
assert isinstance(description, str), (
"Actual type of description is " + str(type(description))
)
entry = data.Transaction(
data.new_metadata(filepath, 0, {}),
book_date,
"*",
"",
description,
data.EMPTY_SET,
data.EMPTY_SET,
postings,
)
entries.append(entry)
if not is_fee_mode:
# only add balance after the last (newest) transaction
try:
book_date = book_date + timedelta(days=1)
entry = data.Balance(
data.new_metadata(filepath, 0, {}),
book_date,
self._account,
balance,
None,
None,
)
entries.append(entry)
except NameError:
pass
return entries