Pedro M. Baeza
8 years ago
committed by
GitHub
12 changed files with 170 additions and 152 deletions
-
2.travis.yml
-
28account_bank_statement_import_ofx/README.rst
-
5account_bank_statement_import_ofx/__init__.py
-
21account_bank_statement_import_ofx/__manifest__.py
-
78account_bank_statement_import_ofx/account_bank_statement_import_ofx.py
-
27account_bank_statement_import_ofx/demo/demo_data.xml
-
4account_bank_statement_import_ofx/tests/__init__.py
-
41account_bank_statement_import_ofx/tests/test_import_bank_statement.py
-
0account_bank_statement_import_ofx/tests/test_ofx_file/test_ofx.ofx
-
12account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml
-
2account_bank_statement_import_ofx/wizard/__init__.py
-
94account_bank_statement_import_ofx/wizard/account_bank_statement_import.py
@ -1,3 +1,2 @@ |
|||||
# -*- encoding: utf-8 -*- |
|
||||
|
|
||||
from . import account_bank_statement_import_ofx |
|
||||
|
# -*- coding: utf-8 -*- |
||||
|
from . import wizard |
@ -1,20 +1,23 @@ |
|||||
# -*- encoding: utf-8 -*- |
|
||||
|
# -*- coding: utf-8 -*- |
||||
{ |
{ |
||||
'name': 'Import OFX Bank Statement', |
'name': 'Import OFX Bank Statement', |
||||
'category': 'Banking addons', |
'category': 'Banking addons', |
||||
'version': '8.0.1.0.0', |
|
||||
'author': 'OpenERP SA,' |
|
||||
|
'version': '10.0.1.0.0', |
||||
|
'license': 'AGPL-3', |
||||
|
'author': 'Odoo SA,' |
||||
|
'Akretion,' |
||||
|
'La Louve,' |
||||
|
'GRAP,' |
||||
'Odoo Community Association (OCA)', |
'Odoo Community Association (OCA)', |
||||
'website': 'https://github.com/OCA/bank-statement-import', |
|
||||
|
'website': 'https://odoo-community.org/', |
||||
'depends': [ |
'depends': [ |
||||
'account_bank_statement_import' |
|
||||
|
'account_bank_statement_import', |
||||
], |
], |
||||
'demo': [ |
|
||||
'demo/demo_data.xml', |
|
||||
|
'data': [ |
||||
|
'views/view_account_bank_statement_import.xml', |
||||
], |
], |
||||
'external_dependencies': { |
'external_dependencies': { |
||||
'python': ['ofxparse'], |
'python': ['ofxparse'], |
||||
}, |
}, |
||||
'auto_install': False, |
|
||||
'installable': False, |
|
||||
|
'installable': True, |
||||
} |
} |
@ -1,78 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
|
|
||||
import logging |
|
||||
import StringIO |
|
||||
|
|
||||
from openerp import api, models |
|
||||
from openerp.tools.translate import _ |
|
||||
from openerp.exceptions import Warning |
|
||||
|
|
||||
_logger = logging.getLogger(__name__) |
|
||||
|
|
||||
try: |
|
||||
from ofxparse import OfxParser as ofxparser |
|
||||
except ImportError: |
|
||||
_logger.warn("ofxparse not found, OFX parsing disabled.") |
|
||||
ofxparser = None |
|
||||
|
|
||||
|
|
||||
class AccountBankStatementImport(models.TransientModel): |
|
||||
_inherit = 'account.bank.statement.import' |
|
||||
|
|
||||
@api.model |
|
||||
def _check_ofx(self, data_file): |
|
||||
if ofxparser is None: |
|
||||
return False |
|
||||
try: |
|
||||
ofx = ofxparser.parse(StringIO.StringIO(data_file)) |
|
||||
except: |
|
||||
return False |
|
||||
return ofx |
|
||||
|
|
||||
@api.model |
|
||||
def _parse_file(self, data_file): |
|
||||
ofx = self._check_ofx(data_file) |
|
||||
if not ofx: |
|
||||
return super(AccountBankStatementImport, self)._parse_file( |
|
||||
data_file) |
|
||||
|
|
||||
transactions = [] |
|
||||
total_amt = 0.00 |
|
||||
try: |
|
||||
for transaction in ofx.account.statement.transactions: |
|
||||
# Since ofxparse doesn't provide account numbers, we'll have |
|
||||
# to find res.partner and res.partner.bank here |
|
||||
# (normal behavious is to provide 'account_number', which the |
|
||||
# generic module uses to find partner/bank) |
|
||||
bank_account_id = partner_id = False |
|
||||
banks = self.env['res.partner.bank'].search( |
|
||||
[('owner_name', '=', transaction.payee)], limit=1) |
|
||||
if banks: |
|
||||
bank_account = banks[0] |
|
||||
bank_account_id = bank_account.id |
|
||||
partner_id = bank_account.partner_id.id |
|
||||
vals_line = { |
|
||||
'date': transaction.date, |
|
||||
'name': transaction.payee + ( |
|
||||
transaction.memo and ': ' + transaction.memo or ''), |
|
||||
'ref': transaction.id, |
|
||||
'amount': transaction.amount, |
|
||||
'unique_import_id': transaction.id, |
|
||||
'bank_account_id': bank_account_id, |
|
||||
'partner_id': partner_id, |
|
||||
} |
|
||||
total_amt += float(transaction.amount) |
|
||||
transactions.append(vals_line) |
|
||||
except Exception, e: |
|
||||
raise Warning(_("The following problem occurred during import. " |
|
||||
"The file might not be valid.\n\n %s" % e.message)) |
|
||||
|
|
||||
vals_bank_statement = { |
|
||||
'name': ofx.account.routing_number, |
|
||||
'transactions': transactions, |
|
||||
'balance_start': ofx.account.statement.balance, |
|
||||
'balance_end_real': |
|
||||
float(ofx.account.statement.balance) + total_amt, |
|
||||
} |
|
||||
return ofx.account.statement.currency, ofx.account.number, [ |
|
||||
vals_bank_statement] |
|
@ -1,27 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<openerp> |
|
||||
<data> |
|
||||
|
|
||||
<record id="ofx_bank_journal" model="account.journal"> |
|
||||
<field name="name">Bank Journal - (test ofx)</field> |
|
||||
<field name="code">TBNKOFX</field> |
|
||||
<field name="type">bank</field> |
|
||||
<field name="sequence_id" ref="account.sequence_bank_journal"/> |
|
||||
<field name="default_debit_account_id" ref="account.usd_bnk"/> |
|
||||
<field name="default_credit_account_id" ref="account.usd_bnk"/> |
|
||||
<field name="user_id" ref="base.user_root"/> |
|
||||
<field name="currency" ref="base.USD"/> |
|
||||
</record> |
|
||||
|
|
||||
<record id="ofx_company_bank" model="res.partner.bank"> |
|
||||
<field name="owner_name">Your Company</field> |
|
||||
<field name="acc_number">123456</field> |
|
||||
<field name="partner_id" ref="base.partner_root"></field> |
|
||||
<field name="company_id" ref="base.main_company"></field> |
|
||||
<field name="journal_id" ref="ofx_bank_journal"></field> |
|
||||
<field name="state">bank</field> |
|
||||
<field name="bank" ref="base.res_bank_1"/> |
|
||||
</record> |
|
||||
</data> |
|
||||
|
|
||||
</openerp> |
|
@ -1,4 +1,2 @@ |
|||||
# -*- encoding: utf-8 -*- |
|
||||
# noqa: This is a backport from Odoo. OCA has no control over style here. |
|
||||
# flake8: noqa |
|
||||
|
# -*- coding: utf-8 -*- |
||||
from . import test_import_bank_statement |
from . import test_import_bank_statement |
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<record id="view_account_bank_statement_import_form" model="ir.ui.view"> |
||||
|
<field name="model">account.bank.statement.import</field> |
||||
|
<field name="inherit_id" ref="account_bank_statement_import.account_bank_statement_import_view"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//ul[@id='statement_format']" position="inside"> |
||||
|
<li>Open Financial Exchange (.OFX Money)</li> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,2 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from . import account_bank_statement_import |
@ -0,0 +1,94 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
import logging |
||||
|
import StringIO |
||||
|
|
||||
|
from odoo import api, models, fields, _ |
||||
|
from odoo.exceptions import UserError |
||||
|
from odoo.tools import float_is_zero |
||||
|
|
||||
|
_logger = logging.getLogger(__name__) |
||||
|
|
||||
|
try: |
||||
|
from ofxparse import OfxParser |
||||
|
except ImportError: |
||||
|
_logger.debug("ofxparse not found.") |
||||
|
OfxParser = None |
||||
|
|
||||
|
|
||||
|
class AccountBankStatementImport(models.TransientModel): |
||||
|
_inherit = 'account.bank.statement.import' |
||||
|
|
||||
|
@api.model |
||||
|
def _check_ofx(self, data_file): |
||||
|
if not OfxParser: |
||||
|
return False |
||||
|
try: |
||||
|
ofx = OfxParser.parse(StringIO.StringIO(data_file)) |
||||
|
except Exception as e: |
||||
|
_logger.debug(e) |
||||
|
return False |
||||
|
return ofx |
||||
|
|
||||
|
@api.model |
||||
|
def _prepare_ofx_transaction_line(self, transaction): |
||||
|
# since odoo 9, the account module defines a constraint |
||||
|
# on account.bank.statement.line: 'amount' must be != 0 |
||||
|
# But some banks have some transactions with amount=0 |
||||
|
# for bank charges that are offered, which blocks the import |
||||
|
precision = self.env['decimal.precision'].precision_get('Account') |
||||
|
if float_is_zero( |
||||
|
float(transaction.amount), precision_digits=precision): |
||||
|
return False |
||||
|
# Since ofxparse doesn't provide account numbers, |
||||
|
# we cannot provide the key 'bank_account_id', |
||||
|
# nor the key 'account_number' |
||||
|
# If you read odoo10/addons/account_bank_statement_import/ |
||||
|
# account_bank_statement_import.py, it's the only 2 keys |
||||
|
# we can provide to match a partner. |
||||
|
vals = { |
||||
|
'date': transaction.date, |
||||
|
'name': transaction.payee + ( |
||||
|
transaction.memo and ': ' + transaction.memo or ''), |
||||
|
'ref': transaction.id, |
||||
|
'amount': float(transaction.amount), |
||||
|
'unique_import_id': transaction.id, |
||||
|
} |
||||
|
return vals |
||||
|
|
||||
|
@api.model |
||||
|
def _parse_file(self, data_file): |
||||
|
ofx = self._check_ofx(data_file) |
||||
|
if not ofx: |
||||
|
return super(AccountBankStatementImport, self)._parse_file( |
||||
|
data_file) |
||||
|
|
||||
|
transactions = [] |
||||
|
total_amt = 0.00 |
||||
|
start_date = end_date = False |
||||
|
try: |
||||
|
for transaction in ofx.account.statement.transactions: |
||||
|
vals = self._prepare_ofx_transaction_line(transaction) |
||||
|
if vals: |
||||
|
transactions.append(vals) |
||||
|
total_amt += vals['amount'] |
||||
|
tdate = fields.Date.to_string(vals['date']) |
||||
|
if not start_date or tdate < start_date: |
||||
|
start_date = tdate |
||||
|
if not end_date or tdate > end_date: |
||||
|
end_date = tdate |
||||
|
except Exception, e: |
||||
|
raise UserError(_( |
||||
|
"The following problem occurred during import. " |
||||
|
"The file might not be valid.\n\n %s") % e.message) |
||||
|
|
||||
|
vals_bank_statement = { |
||||
|
'name': _('Account %s %s > %s') % ( |
||||
|
ofx.account.number, start_date, end_date), |
||||
|
'transactions': transactions, |
||||
|
'balance_start': ofx.account.statement.balance, |
||||
|
'balance_end_real': |
||||
|
float(ofx.account.statement.balance) + total_amt, |
||||
|
} |
||||
|
return ofx.account.statement.currency, ofx.account.number, [ |
||||
|
vals_bank_statement] |
Write
Preview
Loading…
Cancel
Save
Reference in new issue