From 4963c3e7a77ae7a39ec4b7a281c4de93ed0a6609 Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Thu, 16 Jan 2020 19:02:17 +0100 Subject: [PATCH] Refactor and add revolut processing --- ofx_processor/__init__.py | 1 - ofx_processor/bpvf_processor/__init__.py | 1 + ofx_processor/{ => bpvf_processor}/main.py | 0 ofx_processor/revolut_processor/__init__.py | 1 + ofx_processor/revolut_processor/main.py | 54 +++++++++++++++++ poetry.lock | 66 ++++++++++++++++++++- pyproject.toml | 6 +- tests/test_ofx_processor.py | 2 +- 8 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 ofx_processor/bpvf_processor/__init__.py rename ofx_processor/{ => bpvf_processor}/main.py (100%) create mode 100644 ofx_processor/revolut_processor/__init__.py create mode 100644 ofx_processor/revolut_processor/main.py diff --git a/ofx_processor/__init__.py b/ofx_processor/__init__.py index bbab024..e69de29 100644 --- a/ofx_processor/__init__.py +++ b/ofx_processor/__init__.py @@ -1 +0,0 @@ -__version__ = "0.1.4" diff --git a/ofx_processor/bpvf_processor/__init__.py b/ofx_processor/bpvf_processor/__init__.py new file mode 100644 index 0000000..bbab024 --- /dev/null +++ b/ofx_processor/bpvf_processor/__init__.py @@ -0,0 +1 @@ +__version__ = "0.1.4" diff --git a/ofx_processor/main.py b/ofx_processor/bpvf_processor/main.py similarity index 100% rename from ofx_processor/main.py rename to ofx_processor/bpvf_processor/main.py diff --git a/ofx_processor/revolut_processor/__init__.py b/ofx_processor/revolut_processor/__init__.py new file mode 100644 index 0000000..bbab024 --- /dev/null +++ b/ofx_processor/revolut_processor/__init__.py @@ -0,0 +1 @@ +__version__ = "0.1.4" diff --git a/ofx_processor/revolut_processor/main.py b/ofx_processor/revolut_processor/main.py new file mode 100644 index 0000000..ea9c9b3 --- /dev/null +++ b/ofx_processor/revolut_processor/main.py @@ -0,0 +1,54 @@ +import csv +import os + +import click +import dateparser + + +def process_amount(amount): + if amount: + return float(amount.replace(",", ".")) + return "" + + +def process_memo(line): + return " - ".join( + filter(None, map(str.strip, [line["Category"], line["Exchange Rate"]])) + ) + + +@click.command() +@click.argument("csv_filename") +def cli(csv_filename): + formatted_data = [] + + with open(csv_filename) as f: + reader = csv.DictReader(f, delimiter=";") + for line in reader: + date = dateparser.parse(line["Completed Date"]) + formatted_data.append( + { + "Date": date.strftime("%Y-%m-%d"), + "Payee": line["Reference"], + "Memo": process_memo(line), + "Outflow": process_amount(line["Paid Out (EUR)"]), + "Inflow": process_amount(line["Paid In (EUR)"]), + } + ) + + if not formatted_data: + click.secho("Nothing to write.") + + processed_file = os.path.join(os.path.dirname(csv_filename), "processed.csv") + with open(processed_file, "w") as f: + writer = csv.DictWriter( + f, delimiter=",", quotechar='"', fieldnames=formatted_data[0].keys() + ) + writer.writeheader() + writer.writerows(formatted_data) + + click.secho("{} written".format(processed_file), fg="green") + + +if __name__ == "__main__": + cli() diff --git a/poetry.lock b/poetry.lock index 9b45dbb..8583f5f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -66,6 +66,20 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" version = "0.4.3" +[[package]] +category = "main" +description = "Date parsing library designed to parse dates from HTML pages" +name = "dateparser" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.7.2" + +[package.dependencies] +python-dateutil = "*" +pytz = "*" +regex = "*" +tzlocal = "*" + [[package]] category = "dev" description = "Read metadata from Python packages" @@ -176,7 +190,26 @@ version = ">=0.12" testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] -category = "dev" +category = "main" +description = "Extensions to the standard Python datetime module" +name = "python-dateutil" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +version = "2.8.1" + +[package.dependencies] +six = ">=1.5" + +[[package]] +category = "main" +description = "World timezone definitions, modern and historical" +name = "pytz" +optional = false +python-versions = "*" +version = "2019.3" + +[[package]] +category = "main" description = "Alternative regular expression module, to replace re." name = "regex" optional = false @@ -184,7 +217,7 @@ python-versions = "*" version = "2020.1.8" [[package]] -category = "dev" +category = "main" description = "Python 2 and 3 compatibility utilities" name = "six" optional = false @@ -207,6 +240,17 @@ optional = false python-versions = "*" version = "1.4.1" +[[package]] +category = "main" +description = "tzinfo object for the local timezone" +name = "tzlocal" +optional = false +python-versions = "*" +version = "2.0.0" + +[package.dependencies] +pytz = "*" + [[package]] category = "dev" description = "Measures number of Terminal column cells of wide-character codes" @@ -232,7 +276,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pathlib2", "contextlib2", "unittest2"] [metadata] -content-hash = "fdef0368fd2681fefb714829b8c3d65a68ebe48db2c885abb46f6f4e48fe452f" +content-hash = "be08d3690daf99f4cf8210564a85c7346366473c6bfc2f098dcdf3108883c20b" python-versions = ">=3.7" [metadata.files] @@ -260,6 +304,10 @@ colorama = [ {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, ] +dateparser = [ + {file = "dateparser-0.7.2-py2.py3-none-any.whl", hash = "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665"}, + {file = "dateparser-0.7.2.tar.gz", hash = "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b"}, +] importlib-metadata = [ {file = "importlib_metadata-1.4.0-py2.py3-none-any.whl", hash = "sha256:bdd9b7c397c273bcc9a11d6629a38487cd07154fa255a467bf704cd2c258e359"}, {file = "importlib_metadata-1.4.0.tar.gz", hash = "sha256:f17c015735e1a88296994c0697ecea7e11db24290941983b08c9feb30921e6d8"}, @@ -295,6 +343,14 @@ pytest = [ {file = "pytest-5.3.2-py3-none-any.whl", hash = "sha256:e41d489ff43948babd0fad7ad5e49b8735d5d55e26628a58673c39ff61d95de4"}, {file = "pytest-5.3.2.tar.gz", hash = "sha256:6b571215b5a790f9b41f19f3531c53a45cf6bb8ef2988bc1ff9afb38270b25fa"}, ] +python-dateutil = [ + {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, + {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, +] +pytz = [ + {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, + {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, +] regex = [ {file = "regex-2020.1.8-cp27-cp27m-win32.whl", hash = "sha256:4e8f02d3d72ca94efc8396f8036c0d3bcc812aefc28ec70f35bb888c74a25161"}, {file = "regex-2020.1.8-cp27-cp27m-win_amd64.whl", hash = "sha256:e6c02171d62ed6972ca8631f6f34fa3281d51db8b326ee397b9c83093a6b7242"}, @@ -350,6 +406,10 @@ typed-ast = [ {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, ] +tzlocal = [ + {file = "tzlocal-2.0.0-py2.py3-none-any.whl", hash = "sha256:11c9f16e0a633b4b60e1eede97d8a46340d042e67b670b290ca526576e039048"}, + {file = "tzlocal-2.0.0.tar.gz", hash = "sha256:949b9dd5ba4be17190a80c0268167d7e6c92c62b30026cf9764caf3e308e5590"}, +] wcwidth = [ {file = "wcwidth-0.1.8-py2.py3-none-any.whl", hash = "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603"}, {file = "wcwidth-0.1.8.tar.gz", hash = "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8"}, diff --git a/pyproject.toml b/pyproject.toml index 5e05ce1..919507d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "ofx-processor" -version = "0.1.4" +version = "0.2.0" description = "Personal ofx processor" readme = "README.md" license = "GPL-3.0-or-later" @@ -14,13 +14,15 @@ classifiers = [ python = ">=3.7" ofxtools = "^0.8.20" click = "^7.0" +dateparser = "^0.7.2" [tool.poetry.dev-dependencies] pytest = "^5.2" black = "^19.10b0" [tool.poetry.scripts] -ofxprocessor = 'ofx_processor.main:cli' +process-bpvf = 'ofx_processor.bpvf_processor.main:cli' +process-revolut = 'ofx_processor.revolut_processor.main:cli' [build-system] requires = ["poetry>=0.12"] diff --git a/tests/test_ofx_processor.py b/tests/test_ofx_processor.py index 67080c9..7ed4edd 100644 --- a/tests/test_ofx_processor.py +++ b/tests/test_ofx_processor.py @@ -1,4 +1,4 @@ -from ofx_processor import __version__ +from ofx_processor.bpvf_processor import __version__ def test_version():