Added watchdog to watch for changes and automatically convert

This commit is contained in:
2022-01-11 16:07:31 +10:00
parent 435a237049
commit 0b68363c6e
5 changed files with 99 additions and 221 deletions

8
Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM python:3
ADD converter.py /
RUN pip install OfxParser
RUN pip install watchdog
CMD [ "python", "./converter.py" ]

View File

@@ -1,87 +0,0 @@
OFXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE
<OFX>
<SIGNONMSGSRSV1>
<SONRS>
<STATUS>
<CODE>0
<SEVERITY>INFO
</STATUS>
<DTSERVER>20220110041351
<LANGUAGE>ENG
<FI>
<ORG>HSBC Bank Australia
<FID>10624
</FI>
<INTU.BID>10624
<INTU.USERID>XXXXXXXXXXXXXXXXXXXXXXXXXX
</SONRS>
</SIGNONMSGSRSV1>
<BANKMSGSRSV1>
<STMTTRNRS>
<TRNUID>0
<STATUS>
<CODE>0
<SEVERITY>INFO
</STATUS>
<STMTRS>
<CURDEF>AUD
<BANKACCTFROM>
<BANKID>001610020
<ACCTID>342101 576544258
<ACCTTYPE>CREDITLINE
</BANKACCTFROM>
<BANKTRANLIST>
<DTSTART>
<DTEND>
<STMTTRN>
<TRNTYPE>CREDIT
<DTPOSTED>20220106
<DTUSER>20220106
<TRNAMT>1173.71
<FITID>202200600001
<NAME> TRANSFER
<MEMO>FROM 099-271041-090 AUD IB1305543 INTERNET BANKING
</STMTTRN>
<STMTTRN>
<TRNTYPE>CREDIT
<DTPOSTED>20220106
<DTUSER>20220106
<TRNAMT>628.81
<FITID>202200600002
<NAME> TRANSFER
<MEMO>FROM 099-271041-090 AUD IB1004824 INTERNET BANKING
</STMTTRN>
<STMTTRN>
<TRNTYPE>DEBIT
<DTPOSTED>20220104
<DTUSER>20220104
<TRNAMT>-399440.42
<FITID>202200400001
<NAME> TRANSFER
<MEMO>PEXA217198219-B2895881 LOAN DD 1592204/099-271041 DBCU00064 BANKING TERMINAL (UBT
</STMTTRN>
</BANKTRANLIST>
<LEDGERBAL>
<BALAMT>-397637.90
<DTASOF>20220110041351
</LEDGERBAL>
<AVAILBAL>
<BALAMT>1802.52
<DTASOF>20220110041351
</AVAILBAL>
</STMTRS>
</STMTTRNRS>
</BANKMSGSRSV1>
</OFX>

View File

@@ -1,4 +0,0 @@
Date,Original Description,Category,Amount,Account Name
06/01/2022,FROM 099-271041-090 AUD IB1305543 INTERNET BANKING,Uncategorised,1173.71,HSBC Everyday Global
06/01/2022,FROM 099-271041-090 AUD IB1004824 INTERNET BANKING,Uncategorised,628.81,HSBC Everyday Global
04/01/2022,PEXA217198219-B2895881 LOAN DD 1592204/099-271041 DBCU00064 BANKING TERMINAL (UBT,Uncategorised,-399440.42,HSBC Everyday Global
1 Date Original Description Category Amount Account Name
2 06/01/2022 FROM 099-271041-090 AUD IB1305543 INTERNET BANKING Uncategorised 1173.71 HSBC Everyday Global
3 06/01/2022 FROM 099-271041-090 AUD IB1004824 INTERNET BANKING Uncategorised 628.81 HSBC Everyday Global
4 04/01/2022 PEXA217198219-B2895881 LOAN DD 1592204/099-271041 DBCU00064 BANKING TERMINAL (UBT Uncategorised -399440.42 HSBC Everyday Global

View File

@@ -1,92 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from ofxparse import OfxParser\n",
"import codecs"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"with codecs.open('qfx.qfx') as fileobj:\n",
" ofx = OfxParser.parse(fileobj)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'10624'"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"account = ofx.account\n",
"\n",
"account.institution.fid"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Decimal('9570.86')"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"statement = account.statement\n",
"statement.available_balance"
]
}
],
"metadata": {
"interpreter": {
"hash": "8f1f8a1d9576cf73e2f91f0cdc8e61e6f80707111d98c220b357b8bb1eb61bce"
},
"kernelspec": {
"display_name": "Python 3.8.12 64-bit ('hsbc': conda)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -4,47 +4,100 @@
from csv import DictWriter
from glob import glob
from ofxparse import OfxParser
from pathlib import Path
import os
import time
import watchdog.events
import watchdog.observers
DATE_FORMAT = "%d/%m/%Y"
WATCH_DIR = os.path.dirname(os.path.realpath(__file__))
PATTERN = '*.qfx'
BACKUP_DIR = 'Imported'
def write_csv(statement, out_file):
print("Writing: " + out_file)
fields = ['date', 'memo', 'category', 'amount', 'name']
with open(out_file, 'w') as f:
f.write("Date,Original Description,Category,Amount,Account Name")
f.write("\r\n")
writer = DictWriter(f, fieldnames=fields)
for line in statement:
writer.writerow(line)
def get_statement_from_qfx(qfx):
balance = qfx.account.statement.balance
statement = []
credit_transactions = ['credit', 'dep', 'int']
debit_transactions = ['debit', 'atm', 'pos', 'xfer', 'check']
for transaction in qfx.account.statement.transactions:
amount = ""
balance = balance + transaction.amount
if transaction.payee.startswith("PENDING:"):
continue
class Handler(watchdog.events.PatternMatchingEventHandler):
def __init__(self):
# Set the patterns for PatternMatchingEventHandler
watchdog.events.PatternMatchingEventHandler.__init__(self, patterns=['*.qfx'],
ignore_directories=True, case_sensitive=False)
@staticmethod
def write_csv(statement, out_file):
print("Writing: " + out_file)
fields = ['date', 'memo', 'category', 'amount', 'name']
with open(out_file, 'w') as f:
f.write("Date,Original Description,Category,Amount,Account Name")
f.write("\r\n")
writer = DictWriter(f, fieldnames=fields)
for line in statement:
writer.writerow(line)
line = {
'date': transaction.date.strftime(DATE_FORMAT),
'memo' : transaction.memo,
'category': 'Uncategorised',
'amount': transaction.amount,
'name': 'HSBC Everyday Global'
}
statement.append(line)
return statement
@staticmethod
def get_statement_from_qfx(qfx):
balance = qfx.account.statement.balance
files = glob("*.qfx")
for qfx_file in files:
qfx = OfxParser.parse(open(qfx_file, encoding="latin-1"), fail_fast=False)
statement = get_statement_from_qfx(qfx)
out_file = "converted_" + qfx_file.replace(".qfx",".csv")
write_csv(statement, out_file)
statement = []
credit_transactions = ['credit', 'dep', 'int']
debit_transactions = ['debit', 'atm', 'pos', 'xfer', 'check']
for transaction in qfx.account.statement.transactions:
amount = ""
balance = balance + transaction.amount
if transaction.payee.startswith("PENDING:"):
continue
line = {
'date': transaction.date.strftime(DATE_FORMAT),
'memo' : transaction.memo,
'category': 'Uncategorised',
'amount': transaction.amount,
'name': 'HSBC Everyday Global'
}
statement.append(line)
return statement
@staticmethod
def unique_path(directory, name_pattern):
counter = 0
while True:
counter += 1
path = directory / name_pattern.format(counter)
if not path.exists():
return path
def on_created(self, event):
qfx = OfxParser.parse(open(event.src_path, encoding="latin-1"), fail_fast=False)
statement = Handler.get_statement_from_qfx(qfx)
path = Path(event.src_path)
path.resolve()
out_file = str(path.parent / ('converted' + path.stem + '.csv'))
Handler.write_csv(statement, out_file)
#Now move the input file to backup
archive_file_dir = path.parent / BACKUP_DIR
archive_file = (path.stem + '{:04d}' + path.suffix)
destination = Handler.unique_path(archive_file_dir, archive_file)
if not archive_file_dir.exists():
archive_file_dir.mkdir()
if not destination.exists():
path.replace(destination)
if __name__ == "__main__":
event_handler = Handler()
observer = watchdog.observers.Observer()
observer.schedule(event_handler, path=WATCH_DIR, recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()