Skip to content

Commit

Permalink
Initial release.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheoMarescaux committed Feb 11, 2016
1 parent d1c12a9 commit c336958
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 116 deletions.
78 changes: 4 additions & 74 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sample plugin for ofxstatement
ING Belgium plugin for ofxstatement
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This project provides a boilerplate for custom plugins for ofxstatement.

`ofxstatement`_ is a tool to convert proprietary bank statement to OFX format,
suitable for importing to GnuCash. Plugin for ofxstatement parses a
particular proprietary bank statement format and produces common data
Expand All @@ -16,75 +14,7 @@ Users of ofxstatement have developed several plugins for their banks. They are
listed on main `ofxstatement`_ site. If your bank is missing, you can develop
your own plugin.

Setting up development environment
==================================

It is recommended to use ``virtualenv`` make a clean development environment.
Setting up dev environment for writing a plugin is easy::

$ git clone https://github.com/kedder/ofxstatement-sample ofxstatement-yourbank
$ cd ofxstatement-yourbank
$ virtualenv -p python3 --no-site-packages .venv
$ . .venv/bin/activate
(.venv)$ python setup.py develop

This will download all the dependencies and install them into your virtual
environment. After this, you should be able to do::

(.venv)$ ofxstatement list-plugins
The following plugins are available:

sample Sample plugin (for developers only)



Your own plugin
===============

To create your own plugin, follow these steps:

* Edit ``setup.py`` and provide relevant metadata for your plugin. Pay
close attention to ``entry_points`` parameter to ``setup`` function: it
lists plugins you are registering within ofxstatement. Give meaningful
name to the plugin and provide plugin class name
* Replace contents of ``README.rst`` with description of your plugin
* Rename ``ofxstatement/plugins/sample.py`` to match plugin package name
you have provided in ``entry_points`` parameter.
* Open renamed sample.py and rename ``SamplePlugin`` and ``SampleParser``
classes to match your plugin class name.
* Now, draw the rest of the owl (c).

.. _ofxstatement-sample: https://github.com/kedder/ofxstatement-sample

Your ``StatementParser`` is the main object that does all the hard work. It
has only one public method: ``parse()``, that should return
``ofxstatement.statement.Statement`` object, filled with data from given input.
The default implementation, however, splits this work into two parts:
``split_records()`` to split the whole file into logical parts, e.g.
transaction records, and ``parse_record()`` to extract information from
individual record. See ``src/ofxstatement/parser.py`` for details. If your
statement' format looks like CSV file, you might find ``CsvStatementParser``
class useful: it simplifies mapping bettween CSV columns and ``StatementLine``
attributes.

``Plugin`` interface consists only of ``get_parser()`` method, that returns
configured StatementParser object for given input filename. Docstrings on
Plugin class is also useful for describing the purpose of your plugin. First
line of it is visible in ``ofxstatement list-plugins`` output.

Testing
=======

Test your code as you would do with any other project. To make sure
ofxstatement is still able to load your plugin, run::

(.venv)$ ofxstatement list-plugins

You should be able to see your plugin listed.

After you are done
==================
Usage
=====

After your plugin is ready, feel free to open an issue on `ofxstatement`_
project to include your plugin in "known plugin list". That would hopefully
make life of other clients of your bank easier.
$ ofxstatement convert -t ingbe input.csv output.ofx
12 changes: 6 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
with open('README.rst') as f:
long_description = f.read()

setup(name='ofxstatement-sample',
setup(name='ofxstatement-be-ing',
version=version,
author="Andrey Lebedev",
author_email="[email protected]",
url="https://github.com/kedder/ofxstatement",
description=("Sample plugin for ofxstatement"),
author="Theodore Marescaux",
author_email="[email protected]",
url="https://github.com/TheoMarescaux/ofxstatement-be-ing",
description=("OFXStatement plugin for ING (Belgium)"),
long_description=long_description,
license="GPLv3",
keywords=["ofx", "banking", "statement"],
Expand All @@ -32,7 +32,7 @@
namespace_packages=["ofxstatement", "ofxstatement.plugins"],
entry_points={
'ofxstatement':
['sample = ofxstatement.plugins.sample:SamplePlugin']
['ingbe = ofxstatement.plugins.ingbe:IngBePlugin']
},
install_requires=['ofxstatement'],
include_package_data=True,
Expand Down
72 changes: 72 additions & 0 deletions src/ofxstatement/plugins/ingbe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import csv

from ofxstatement import statement
from ofxstatement.plugin import Plugin
from ofxstatement.parser import CsvStatementParser
from ofxstatement.parser import StatementParser
from ofxstatement.statement import StatementLine

class IngBePlugin(Plugin):
"""ING Belgium Plugin
"""

def get_parser(self, filename):
f = open(filename, 'r', encoding=self.settings.get("charset", "ISO-8859-1"))
parser = IngBeParser(f)
#parser.statement.bank_id = "ING Belgium"
#parser.statement.bank_id = self.settings.get('bank', 'ING Belgium')
return parser

class IngBeParser(CsvStatementParser):

date_format = "%d/%m/%Y"
mappings = {
'check_no': 3,
'date': 4,
'payee': 2,
'memo': 9,
'amount': 6
}

def parse(self):
"""Main entry point for parsers
super() implementation will call to split_records and parse_record to
process the file.
"""
stmt = super(IngBeParser, self).parse()
statement.recalculate_balance(stmt)
return stmt

def split_records(self):
"""Return iterable object consisting of a line per transaction
"""

reader = csv.reader(self.fin)
next(reader, None)
return reader

def parse_record(self, line):
"""Parse given transaction line and return StatementLine object
"""

# Remove non CSV cr*p and zero-value notifications
if(line[5] and not (line[6]=="0" and line[7]=="0")):
transaction_id = line[3]
date = line[4]
date_value = line[5]
account_to = line[2]
currency = line[8]

# fix amount - Well done ING, mixing the comma as decimal separator and as CSV delimiter. Way to go...
line[6] = line[6]+"."+line[7]
amount = line[6]

# Pack info in description
line[9] = line[9]+"-"+line[10]+"-"+line[11]
description = line[9]

stmtline = super(IngBeParser, self).parse_record(line)
stmtline.trntype = 'DEBIT' if stmtline.amount < 0 else 'CREDIT'

return stmtline
36 changes: 0 additions & 36 deletions src/ofxstatement/plugins/sample.py

This file was deleted.

0 comments on commit c336958

Please sign in to comment.