diff --git a/account_statement_ext/report/bank_statement_report.mako b/account_statement_ext/report/bank_statement_report.mako index 7d1875b7..4a21333b 100644 --- a/account_statement_ext/report/bank_statement_report.mako +++ b/account_statement_ext/report/bank_statement_report.mako @@ -1,3 +1,4 @@ +## -*- coding: utf-8 -*- diff --git a/account_statement_ext/statement.py b/account_statement_ext/statement.py index f8762054..4775362b 100644 --- a/account_statement_ext/statement.py +++ b/account_statement_ext/statement.py @@ -111,6 +111,11 @@ class AccountStatementProfile(Model): _constraints = [ (_check_partner, "You need to put a partner if you tic the 'Force partner on bank move'!", []), ] + + _sql_constraints = [ + ('name_uniq', 'unique (name, company_id)', 'The name of the bank statement must be unique !') + ] + class AccountBankSatement(Model): diff --git a/account_statement_ofx_import/__init__.py b/account_statement_ofx_import/__init__.py new file mode 100644 index 00000000..19462c05 --- /dev/null +++ b/account_statement_ofx_import/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Pedro Manuel Baeza Romero +# Copyright 2013 Servicios Tecnológicos Avanzados +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +import statement +import parser diff --git a/account_statement_ofx_import/__openerp__.py b/account_statement_ofx_import/__openerp__.py new file mode 100644 index 00000000..ae06cfbf --- /dev/null +++ b/account_statement_ofx_import/__openerp__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Pedro Manuel Baeza Romero +# Copyright 2013 Servicios Tecnológicos Avanzados +# Financed by AB Internet (http://www.abinternet.co.uk/) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{'name': "Bank statement OFX import", + 'version': '1.0', + 'author': 'Servicios Tecnológicos Avanzados - Pedro M. Baeza', + 'maintainer': 'Pedro M. Baeza', + 'category': 'Finance', + 'complexity': 'normal', + 'depends': [ + 'account_statement_base_import', + ], + 'external_dependencies': { + 'python': ['ofxparse'], + } + 'description': """ + Allows to import OFX (Open Financial Exchange) statement files, using + *account_statement_base_import* generic inheritance mechanism to import + statements. + + It requires ofxparse library to work. + """, + 'website': 'http://www.serviciosbaeza.com', + 'data': [], + 'test': [], + 'installable': True, + 'images': [], + 'auto_install': False, + 'license': 'AGPL-3', +} diff --git a/account_statement_ofx_import/parser/__init__.py b/account_statement_ofx_import/parser/__init__.py new file mode 100644 index 00000000..682e6db7 --- /dev/null +++ b/account_statement_ofx_import/parser/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Pedro Manuel Baeza Romero +# Copyright 2013 Servicios Tecnológicos Avanzados +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +from . import ofx_parser + diff --git a/account_statement_ofx_import/parser/ofx_parser.py b/account_statement_ofx_import/parser/ofx_parser.py new file mode 100644 index 00000000..65961241 --- /dev/null +++ b/account_statement_ofx_import/parser/ofx_parser.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Pedro Manuel Baeza Romero +# Copyright 2013 Servicios Tecnológicos Avanzados +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +from openerp.tools.translate import _ +from account_statement_base_import.parser import BankStatementImportParser +import tempfile +import datetime + +try: + import ofxparse +except: + raise Exception(_('Please install python lib ofxparse')) + +class OfxParser(BankStatementImportParser): + """ + Class for defining parser for OFX file format. + """ + + def __init__(self, parser_name, *args, **kwargs): + """ + """ + super(OfxParser, self).__init__(parser_name, *args, **kwargs) + + @classmethod + def parser_for(cls, parser_name): + """ + Used by the new_bank_statement_parser class factory. Return true if + the providen name is 'ofx_so'. + """ + return parser_name == 'ofx_so' + + def _custom_format(self, *args, **kwargs): + """ + No other work on data are needed in this parser. + """ + return True + + def _pre(self, *args, **kwargs): + """ + No pre-treatment needed for this parser. + """ + return True + + def _parse(self, *args, **kwargs): + """ + Launch the parsing itself. + """ + ofx_file = tempfile.NamedTemporaryFile() + ofx_file.seek(0) + ofx_file.write(self.filebuffer) + ofx_file.flush() + ofx = ofxparse.OfxParser.parse(file(ofx_file.name)) + ofx_file.close() + res = [] + for transaction in ofx.account.statement.transactions: + res.append({ + 'date': transaction.date, + 'amount': transaction.amount, + 'ref': transaction.type, + 'label': transaction.payee, + }) + self.result_row_list = res + return True + + def _validate(self, *args, **kwargs): + """ + Nothing to do here. ofxparse trigger possible format errors. + """ + return True + + def _post(self, *args, **kwargs): + """ + Nothing is needed to do after parsing. + """ + return True + + def _post(self, *args, **kwargs): + """ + Nothing to do. + """ + return True + + def get_st_line_vals(self, line, *args, **kwargs): + """ + This method must return a dict of vals that can be passed to create + method of statement line in order to record it. It is the + responsibility of every parser to give this dict of vals, so each one + can implement his own way of recording the lines. + :param: line: a dict of vals that represent a line of + result_row_list + :return: dict of values to give to the create method of statement + line + """ + return { + 'name': line.get('label', line.get('ref', '/')), + 'date': line.get('date', datetime.datetime.now().date()), + 'amount': line.get('amount', 0.0), + 'ref': line.get('ref', '/'), + 'label': line.get('label', ''), + } + diff --git a/account_statement_ofx_import/statement.py b/account_statement_ofx_import/statement.py new file mode 100644 index 00000000..c5b06fe8 --- /dev/null +++ b/account_statement_ofx_import/statement.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Pedro Manuel Baeza Romero +# Copyright 2013 Servicios Tecnológicos Avanzados +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +from openerp.tools.translate import _ +from openerp.osv import fields, orm + +class AccountStatementProfil(orm.Model): + _inherit = "account.statement.profile" + + def get_import_type_selection(self, cr, uid, context=None): + """ + Inherited from parent to add parser. + """ + selection = super(AccountStatementProfil, self + ).get_import_type_selection(cr, uid, + context=context) + selection.append(('ofx_so', _('OFX - Open Financial Exchange'))) + return selection + + _columns = { + 'import_type': fields.selection( + get_import_type_selection, + 'Type of import', + required=True, + help="Choose here the method by which you want to import bank" + "statement for this profile."), + + } + diff --git a/account_statement_transactionid_import/parser/transactionid_file_parser.py b/account_statement_transactionid_import/parser/transactionid_file_parser.py index ecc5d054..0a54b1e5 100644 --- a/account_statement_transactionid_import/parser/transactionid_file_parser.py +++ b/account_statement_transactionid_import/parser/transactionid_file_parser.py @@ -27,16 +27,21 @@ class TransactionIDFileParser(FileParser): bank statement. """ - def __init__(self, parse_name, ftype='csv'): - conversion_dict = {'transaction_id': unicode, - 'label': unicode, - 'date': datetime.datetime, - 'amount': float, - 'commission_amount': float} - # Order of cols does not matter but first row of the file has to be header - keys_to_validate = ['transaction_id', 'label', 'date', 'amount', 'commission_amount'] - super(TransactionIDFileParser, self).__init__(parse_name, keys_to_validate=keys_to_validate, - ftype=ftype, conversion_dict=conversion_dict) + def __init__(self, parse_name, ftype='csv', extra_fields=None, header=None, **kwargs): + """ + Add transaction_id in header keys + :param char: parse_name: The name of the parser + :param char: ftype: extension of the file (could be csv or xls) + :param dict: extra_fields: extra fields to add to the conversion dict. In the format + {fieldname: fieldtype} + :param list: header : specify header fields if the csv file has no header + """ + extra_fields = {'transaction_id': unicode} + super(TransactionIDFileParser, self).__init__(parse_name, extra_fields=extra_fields, + ftype=ftype, header=header, **kwargs) + # ref is replaced by transaction_id thus we delete it from check + self.keys_to_validate = [k for k in self.keys_to_validate if k != 'ref'] + del self.conversion_dict['ref'] @classmethod def parser_for(cls, parser_name): @@ -73,14 +78,3 @@ class TransactionIDFileParser(FileParser): 'label': line.get('label', ''), 'transaction_id': line.get('transaction_id', '/'), 'commission_amount': line.get('commission_amount', 0.0)} - - def _post(self, *args, **kwargs): - """ - Compute the commission from value of each line - """ - res = super(TransactionIDFileParser, self)._post(*args, **kwargs) - val = 0.0 - for row in self.result_row_list: - val += row.get('commission_amount', 0.0) - self.commission_global_amount = val - return res