Pedro M. Baeza
10 years ago
19 changed files with 763 additions and 0 deletions
-
1.travis.yml
-
4account_bank_statement_import/__init__.py
-
27account_bank_statement_import/__openerp__.py
-
98account_bank_statement_import/account_bank_statement_import.py
-
51account_bank_statement_import/account_bank_statement_import_view.xml
-
119account_bank_statement_import/demo/fiscalyear_period.xml
-
38account_bank_statement_import/demo/partner_bank.xml
-
4account_bank_statement_import_ofx/__init__.py
-
32account_bank_statement_import_ofx/__openerp__.py
-
76account_bank_statement_import_ofx/account_bank_statement_import_ofx.py
-
100account_bank_statement_import_ofx/test_ofx_file/test_ofx.ofx
-
8account_bank_statement_import_ofx/tests/__init__.py
-
33account_bank_statement_import_ofx/tests/test_import_bank_statement.py
-
4account_bank_statement_import_qif/__init__.py
-
32account_bank_statement_import_qif/__openerp__.py
-
77account_bank_statement_import_qif/account_bank_statement_import_qif.py
-
21account_bank_statement_import_qif/test_qif_file/test_qif.qif
-
8account_bank_statement_import_qif/tests/__init__.py
-
30account_bank_statement_import_qif/tests/test_import_bank_statement.py
@ -0,0 +1,4 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
from . import account_bank_statement_import |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,27 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
{ |
||||
|
'name': 'Account Bank Statement Import', |
||||
|
'version': '1.0', |
||||
|
'author': 'OpenERP SA', |
||||
|
'depends': ['account'], |
||||
|
'demo': [], |
||||
|
'description' : """Generic Wizard to Import Bank Statements. |
||||
|
|
||||
|
Includes the import of files in .OFX format |
||||
|
|
||||
|
Backport from Odoo 9.0 |
||||
|
""", |
||||
|
'data' : [ |
||||
|
'account_bank_statement_import_view.xml', |
||||
|
], |
||||
|
'demo': [ |
||||
|
'demo/fiscalyear_period.xml', |
||||
|
'demo/partner_bank.xml', |
||||
|
], |
||||
|
'auto_install': False, |
||||
|
'installable': True, |
||||
|
} |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,98 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
|
||||
|
from openerp.osv import fields, osv |
||||
|
from openerp.tools.translate import _ |
||||
|
|
||||
|
import logging |
||||
|
_logger = logging.getLogger(__name__) |
||||
|
|
||||
|
_IMPORT_FILE_TYPE = [('none', _('No Import Format Available'))] |
||||
|
|
||||
|
def add_file_type(selection_value): |
||||
|
global _IMPORT_FILE_TYPE |
||||
|
if _IMPORT_FILE_TYPE[0][0] == 'none': |
||||
|
_IMPORT_FILE_TYPE = [selection_value] |
||||
|
else: |
||||
|
_IMPORT_FILE_TYPE.append(selection_value) |
||||
|
|
||||
|
class account_bank_statement_import(osv.TransientModel): |
||||
|
_name = 'account.bank.statement.import' |
||||
|
_description = 'Import Bank Statement' |
||||
|
|
||||
|
def _get_import_file_type(self, cr, uid, context=None): |
||||
|
return _IMPORT_FILE_TYPE |
||||
|
|
||||
|
_columns = { |
||||
|
'data_file': fields.binary('Bank Statement File', required=True, help='Get you bank statements in electronic format from your bank and select them here.'), |
||||
|
'file_type': fields.selection(_get_import_file_type, 'File Type', required=True), |
||||
|
'journal_id': fields.many2one('account.journal', 'Journal', required=True, help="The journal for which the bank statements will be created"), |
||||
|
} |
||||
|
|
||||
|
def _get_first_file_type(self, cr, uid, context=None): |
||||
|
return self._get_import_file_type(cr, uid, context=context)[0][0] |
||||
|
|
||||
|
def _get_default_journal(self, cr, uid, context=None): |
||||
|
company_id = self.pool.get('res.company')._company_default_get(cr, uid, 'account.bank.statement', context=context) |
||||
|
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'bank'), ('company_id', '=', company_id)], context=context) |
||||
|
return journal_ids and journal_ids[0] or False |
||||
|
|
||||
|
_defaults = { |
||||
|
'file_type': _get_first_file_type, |
||||
|
'journal_id': _get_default_journal, |
||||
|
} |
||||
|
|
||||
|
def _detect_partner(self, cr, uid, identifying_string, identifying_field='acc_number', context=None): |
||||
|
"""Try to find a bank account and its related partner for the given 'identifying_string', looking on the field 'identifying_field'. |
||||
|
|
||||
|
:param identifying_string: varchar |
||||
|
:param identifying_field: varchar corresponding to the name of a field of res.partner.bank |
||||
|
:returns: tuple(ID of the bank account found or False, ID of the partner for the bank account found or False) |
||||
|
""" |
||||
|
partner_id = False |
||||
|
bank_account_id = False |
||||
|
if identifying_string: |
||||
|
ids = self.pool.get('res.partner.bank').search(cr, uid, [(identifying_field, '=', identifying_string)], context=context) |
||||
|
if ids: |
||||
|
bank_account_id = ids[0] |
||||
|
partner_id = self.pool.get('res.partner.bank').browse(cr, uid, bank_account_id, context=context).partner_id.id |
||||
|
else: |
||||
|
#create the bank account, not linked to any partner. The reconciliation will link the partner manually |
||||
|
#chosen at the bank statement final confirmation time. |
||||
|
try: |
||||
|
type_model, type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'bank_normal') |
||||
|
type_id = self.pool.get('res.partner.bank.type').browse(cr, uid, type_id, context=context) |
||||
|
bank_code = type_id.code |
||||
|
except ValueError: |
||||
|
bank_code = 'bank' |
||||
|
acc_number = identifying_field == 'acc_number' and identifying_string or _('Undefined') |
||||
|
bank_account_vals = { |
||||
|
'acc_number': acc_number, |
||||
|
'state': bank_code, |
||||
|
} |
||||
|
bank_account_vals[identifying_field] = identifying_string |
||||
|
bank_account_id = self.pool.get('res.partner.bank').create(cr, uid, bank_account_vals, context=context) |
||||
|
return bank_account_id, partner_id |
||||
|
|
||||
|
def import_bank_statement(self, cr, uid, bank_statement_vals=False, context=None): |
||||
|
""" Get a list of values to pass to the create() of account.bank.statement object, and returns a list of ID created using those values""" |
||||
|
statement_ids = [] |
||||
|
for vals in bank_statement_vals: |
||||
|
statement_ids.append(self.pool.get('account.bank.statement').create(cr, uid, vals, context=context)) |
||||
|
return statement_ids |
||||
|
|
||||
|
def process_none(self, cr, uid, data_file, journal_id=False, context=None): |
||||
|
raise osv.except_osv(_('Error'), _('No available format for importing bank statement. You can install one of the file format available through the module installation.')) |
||||
|
|
||||
|
def parse_file(self, cr, uid, ids, context=None): |
||||
|
""" Process the file chosen in the wizard and returns a list view of the imported bank statements""" |
||||
|
data = self.browse(cr, uid, ids[0], context=context) |
||||
|
vals = getattr(self, "process_%s" % data.file_type)(cr, uid, data.data_file, data.journal_id.id, context=context) |
||||
|
statement_ids = self.import_bank_statement(cr, uid, vals, context=context) |
||||
|
model, action_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'action_bank_statement_tree') |
||||
|
action = self.pool[model].read(cr, uid, action_id, context=context) |
||||
|
action['domain'] = "[('id', 'in', [" + ', '.join(map(str, statement_ids)) + "])]" |
||||
|
return action |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,51 @@ |
|||||
|
<?xml version="1.0" ?> |
||||
|
<openerp> |
||||
|
<data> |
||||
|
|
||||
|
<record id="account_bank_statement_import_view" model="ir.ui.view"> |
||||
|
<field name="name">Import Bank Statements</field> |
||||
|
<field name="model">account.bank.statement.import</field> |
||||
|
<field name="priority">1</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form string="Import Bank Statements" version="7.0"> |
||||
|
<group> |
||||
|
<group> |
||||
|
<field name="data_file"/> |
||||
|
<field name="file_type"/> |
||||
|
<field name="journal_id" domain="[('type', '=', 'bank')]" context="{'default_type':'bank'}"/> |
||||
|
</group> |
||||
|
<group> |
||||
|
<b colspan="2"> How to import your bank statement in OpenERP.</b> |
||||
|
<label string= "1. Go to your bank account website." colspan="2"/> |
||||
|
<label string= "2. Download your bank statements in the right format. (.OFX, .QIF or CODA are accepted)" colspan="2"/> |
||||
|
<label string= "3. Upload right here the bank statements file into OpenERP. Click Import." colspan="2"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button name="parse_file" string="_Import" type="object" class="oe_highlight"/> |
||||
|
or |
||||
|
<button string="Cancel" class="oe_link" special="cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_account_bank_statement_import" model="ir.actions.act_window"> |
||||
|
<field name="name">Import Bank Statement</field> |
||||
|
<field name="type">ir.actions.act_window</field> |
||||
|
<field name="res_model">account.bank.statement.import</field> |
||||
|
<field name="view_type">form</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="target">new</field> |
||||
|
<field name="view_id" ref="account_bank_statement_import_view"/> |
||||
|
</record> |
||||
|
|
||||
|
<menuitem |
||||
|
parent="account.menu_finance_bank_and_cash" |
||||
|
id="menu_account_bank_statement_import" |
||||
|
action="action_account_bank_statement_import" |
||||
|
sequence="11" |
||||
|
/> |
||||
|
|
||||
|
</data> |
||||
|
</openerp> |
@ -0,0 +1,119 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<openerp> |
||||
|
<data> |
||||
|
|
||||
|
<!-- |
||||
|
Fiscal year |
||||
|
--> |
||||
|
|
||||
|
<record id="data_fiscalyear_2013" model="account.fiscalyear"> |
||||
|
<field eval="'Fiscal Year X 2013'" name="name"/> |
||||
|
<field eval="'FY2013'" name="code"/> |
||||
|
<field eval="'2013-01-01'" name="date_start"/> |
||||
|
<field eval="'2013-12-31'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
|
||||
|
<!-- |
||||
|
Fiscal Periods 2013 |
||||
|
--> |
||||
|
|
||||
|
<record id="period_1_2013" model="account.period"> |
||||
|
<field eval="'01/2013'" name="code"/> |
||||
|
<field eval="'X 01/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-01-01'" name="date_start"/> |
||||
|
<field eval="'2013-01-31'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="period_2_2013" model="account.period"> |
||||
|
<field eval="'02/2013'" name="code"/> |
||||
|
<field eval="'X 02/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-02-01'" name="date_start"/> |
||||
|
<field eval="'2013-02-28'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_3_2013" model="account.period"> |
||||
|
<field eval="'03/2013'" name="code"/> |
||||
|
<field eval="'X 03/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-03-01'" name="date_start"/> |
||||
|
<field eval="'2013-03-31'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_4_2013" model="account.period"> |
||||
|
<field eval="'04/2013'" name="code"/> |
||||
|
<field eval="'X 04/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-04-01'" name="date_start"/> |
||||
|
<field eval="'2013-04-30'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_5_2013" model="account.period"> |
||||
|
<field eval="'05/2013'" name="code"/> |
||||
|
<field eval="'X 05/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-05-01'" name="date_start"/> |
||||
|
<field eval="'2013-05-31'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_6_2013" model="account.period"> |
||||
|
<field eval="'06/2013'" name="code"/> |
||||
|
<field eval="'X 06/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-06-01'" name="date_start"/> |
||||
|
<field eval="'2013-06-30'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_7_2013" model="account.period"> |
||||
|
<field eval="'07/2013'" name="code"/> |
||||
|
<field eval="'X 07/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-07-01'" name="date_start"/> |
||||
|
<field eval="'2013-07-31'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_8_2013" model="account.period"> |
||||
|
<field eval="'08/2013'" name="code"/> |
||||
|
<field eval="'X 08/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-08-01'" name="date_start"/> |
||||
|
<field eval="'2013-08-31'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_9_2013" model="account.period"> |
||||
|
<field eval="'09/2013'" name="code"/> |
||||
|
<field eval="'X 09/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-09-01'" name="date_start"/> |
||||
|
<field eval="'2013-09-30'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_10_2013" model="account.period"> |
||||
|
<field eval="'10/2013'" name="code"/> |
||||
|
<field eval="'X 10/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-10-01'" name="date_start"/> |
||||
|
<field eval="'2013-10-31'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_11_2013" model="account.period"> |
||||
|
<field eval="'11/2013'" name="code"/> |
||||
|
<field eval="'X 11/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-11-01'" name="date_start"/> |
||||
|
<field eval="'2013-11-30'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
<record id="period_12_2013" model="account.period"> |
||||
|
<field eval="'12/2013'" name="code"/> |
||||
|
<field eval="'X 12/2013'" name="name"/> |
||||
|
<field name="fiscalyear_id" ref="data_fiscalyear_2013"/> |
||||
|
<field eval="'2013-12-01'" name="date_start"/> |
||||
|
<field eval="'2013-12-31'" name="date_stop"/> |
||||
|
<field name="company_id" ref="base.main_company"/> |
||||
|
</record> |
||||
|
</data> |
||||
|
</openerp> |
@ -0,0 +1,38 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<openerp> |
||||
|
<data> |
||||
|
|
||||
|
<record id="ofx_partner_bank_1" model="res.partner.bank"> |
||||
|
<field name="owner_name">Agrolait</field> |
||||
|
<field name="acc_number">00987654321</field> |
||||
|
<field name="partner_id" ref="base.res_partner_2"></field> |
||||
|
<field name="state">bank</field> |
||||
|
<field name="bank" ref="base.res_bank_1"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="ofx_partner_bank_2" model="res.partner.bank"> |
||||
|
<field name="owner_name">China Export</field> |
||||
|
<field name="acc_number">00987654322</field> |
||||
|
<field name="partner_id" ref="base.res_partner_3"></field> |
||||
|
<field name="state">bank</field> |
||||
|
<field name="bank" ref="base.res_bank_1"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="qif_partner_bank_1" model="res.partner.bank"> |
||||
|
<field name="owner_name">Delta PC</field> |
||||
|
<field name="acc_number">10987654320</field> |
||||
|
<field name="partner_id" ref="base.res_partner_4"></field> |
||||
|
<field name="state">bank</field> |
||||
|
<field name="bank" ref="base.res_bank_1"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="qif_partner_bank_2" model="res.partner.bank"> |
||||
|
<field name="owner_name">Epic Technologies</field> |
||||
|
<field name="acc_number">10987654322</field> |
||||
|
<field name="partner_id" ref="base.res_partner_5"></field> |
||||
|
<field name="state">bank</field> |
||||
|
<field name="bank" ref="base.res_bank_1"/> |
||||
|
</record> |
||||
|
|
||||
|
</data> |
||||
|
</openerp> |
@ -0,0 +1,4 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
from . import account_bank_statement_import_ofx |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,32 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
{ |
||||
|
'name': 'Import OFX Bank Statement', |
||||
|
'version': '1.0', |
||||
|
'author': 'OpenERP SA', |
||||
|
'depends': ['account_bank_statement_import'], |
||||
|
'demo': [], |
||||
|
'description' : """ |
||||
|
Module to import OFX bank statements. |
||||
|
====================================== |
||||
|
|
||||
|
This module allows you to import the machine readable OFX Files in Odoo: they are parsed and stored in human readable format in |
||||
|
Accounting \ Bank and Cash \ Bank Statements. |
||||
|
|
||||
|
Bank Statements may be generated containing a subset of the OFX information (only those transaction lines that are required for the |
||||
|
creation of the Financial Accounting records). |
||||
|
|
||||
|
Backported from Odoo 9.0 |
||||
|
|
||||
|
When testing with the provided test file, make sure the demo data from the |
||||
|
base account_bank_statement_import module has been imported, or manually |
||||
|
create periods for the year 2013. |
||||
|
""", |
||||
|
'data' : [], |
||||
|
'demo': [], |
||||
|
'auto_install': False, |
||||
|
'installable': True, |
||||
|
} |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,76 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
|
||||
|
import logging |
||||
|
import base64 |
||||
|
import os |
||||
|
|
||||
|
from openerp.osv import osv |
||||
|
from openerp.tools.translate import _ |
||||
|
|
||||
|
_logger = logging.getLogger(__name__) |
||||
|
|
||||
|
from openerp.addons.account_bank_statement_import import account_bank_statement_import as ibs |
||||
|
ibs.add_file_type(('ofx', 'OFX')) |
||||
|
|
||||
|
try: |
||||
|
from ofxparse import OfxParser as ofxparser |
||||
|
except ImportError: |
||||
|
_logger.warning("OFX parser unavailable because the `ofxparse` Python library cannot be found." |
||||
|
"It can be downloaded and installed from `https://pypi.python.org/pypi/ofxparse`.") |
||||
|
ofxparser = None |
||||
|
|
||||
|
class account_bank_statement_import(osv.TransientModel): |
||||
|
_inherit = 'account.bank.statement.import' |
||||
|
|
||||
|
def process_ofx(self, cr, uid, data_file, journal_id=False, context=None): |
||||
|
""" Import a file in the .OFX format""" |
||||
|
if ofxparser is None: |
||||
|
raise osv.except_osv(_("Error"), _("OFX parser unavailable because the `ofxparse` Python library cannot be found." |
||||
|
"It can be downloaded and installed from `https://pypi.python.org/pypi/ofxparse`.")) |
||||
|
try: |
||||
|
tempfile = open("temp.ofx", "w+") |
||||
|
tempfile.write(base64.decodestring(data_file)) |
||||
|
tempfile.read() |
||||
|
pathname = os.path.dirname('temp.ofx') |
||||
|
path = os.path.join(os.path.abspath(pathname), 'temp.ofx') |
||||
|
ofx = ofxparser.parse(file(path)) |
||||
|
except: |
||||
|
raise osv.except_osv(_('Import Error!'), _('Please check OFX file format is proper or not.')) |
||||
|
line_ids = [] |
||||
|
total_amt = 0.00 |
||||
|
try: |
||||
|
for transaction in ofx.account.statement.transactions: |
||||
|
bank_account_id, partner_id = self._detect_partner(cr, uid, transaction.payee, identifying_field='owner_name', context=context) |
||||
|
vals_line = { |
||||
|
'date': transaction.date, |
||||
|
'name': transaction.payee + ': ' + transaction.memo, |
||||
|
'ref': transaction.id, |
||||
|
'amount': transaction.amount, |
||||
|
'partner_id': partner_id, |
||||
|
'bank_account_id': bank_account_id, |
||||
|
} |
||||
|
total_amt += float(transaction.amount) |
||||
|
line_ids.append((0, 0, vals_line)) |
||||
|
except Exception, e: |
||||
|
raise osv.except_osv(_('Error!'), _("Following problem has been occurred while importing your file, Please verify the file is proper or not.\n\n %s" % e.message)) |
||||
|
st_start_date = ofx.account.statement.start_date or False |
||||
|
st_end_date = ofx.account.statement.end_date or False |
||||
|
period_obj = self.pool.get('account.period') |
||||
|
if st_end_date: |
||||
|
period_ids = period_obj.find(cr, uid, st_end_date, context=context) |
||||
|
else: |
||||
|
period_ids = period_obj.find(cr, uid, st_start_date, context=context) |
||||
|
vals_bank_statement = { |
||||
|
'name': ofx.account.routing_number, |
||||
|
'balance_start': ofx.account.statement.balance, |
||||
|
'balance_end_real': float(ofx.account.statement.balance) + total_amt, |
||||
|
'period_id': period_ids and period_ids[0] or False, |
||||
|
'journal_id': journal_id |
||||
|
} |
||||
|
vals_bank_statement.update({'line_ids': line_ids}) |
||||
|
os.remove(path) |
||||
|
return [vals_bank_statement] |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,100 @@ |
|||||
|
<?xml version="1.0" encoding="ASCII"?> |
||||
|
<?OFX OFXHEADER="200" VERSION="211" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?> |
||||
|
<OFX> |
||||
|
<SIGNONMSGSRSV1> |
||||
|
<SONRS> |
||||
|
<STATUS> |
||||
|
<CODE>0</CODE> |
||||
|
<SEVERITY>INFO</SEVERITY> |
||||
|
</STATUS> |
||||
|
<DTSERVER>20130831165153.000[-8:PST]</DTSERVER> |
||||
|
<LANGUAGE>ENG</LANGUAGE> |
||||
|
</SONRS> |
||||
|
</SIGNONMSGSRSV1> |
||||
|
<BANKMSGSRSV1> |
||||
|
<STMTTRNRS> |
||||
|
<TRNUID>0</TRNUID> |
||||
|
<STATUS> |
||||
|
<CODE>0</CODE> |
||||
|
<SEVERITY>INFO</SEVERITY> |
||||
|
</STATUS> |
||||
|
<STMTRS> |
||||
|
<CURDEF>USD</CURDEF> |
||||
|
<BANKACCTFROM> |
||||
|
<BANKID>000000123</BANKID> |
||||
|
<ACCTID>123456</ACCTID> |
||||
|
<ACCTTYPE>CHECKING</ACCTTYPE> |
||||
|
</BANKACCTFROM> |
||||
|
<BANKTRANLIST> |
||||
|
<DTSTART>20130801</DTSTART> |
||||
|
<DTEND>20130831165153.000[-8:PST]</DTEND> |
||||
|
<STMTTRN> |
||||
|
<TRNTYPE>POS</TRNTYPE> |
||||
|
<DTPOSTED>20130824080000</DTPOSTED> |
||||
|
<TRNAMT>-80</TRNAMT> |
||||
|
<FITID>219378</FITID> |
||||
|
<NAME>Agrolait</NAME> |
||||
|
</STMTTRN> |
||||
|
</BANKTRANLIST> |
||||
|
<BANKTRANLIST> |
||||
|
<DTSTART>20130801</DTSTART> |
||||
|
<DTEND>20130831165153.000[-8:PST]</DTEND> |
||||
|
<STMTTRN> |
||||
|
<TRNTYPE>POS</TRNTYPE> |
||||
|
<DTPOSTED>20130824080000</DTPOSTED> |
||||
|
<TRNAMT>-90</TRNAMT> |
||||
|
<FITID>219379</FITID> |
||||
|
<NAME>China Export</NAME> |
||||
|
</STMTTRN> |
||||
|
</BANKTRANLIST> |
||||
|
<BANKTRANLIST> |
||||
|
<DTSTART>20130801</DTSTART> |
||||
|
<DTEND>20130831165153.000[-8:PST]</DTEND> |
||||
|
<STMTTRN> |
||||
|
<TRNTYPE>POS</TRNTYPE> |
||||
|
<DTPOSTED>20130824080000</DTPOSTED> |
||||
|
<TRNAMT>-100</TRNAMT> |
||||
|
<FITID>219380</FITID> |
||||
|
<NAME>Axelor Scuba</NAME> |
||||
|
</STMTTRN> |
||||
|
</BANKTRANLIST> |
||||
|
<BANKTRANLIST> |
||||
|
<DTSTART>20130801</DTSTART> |
||||
|
<DTEND>20130831165153.000[-8:PST]</DTEND> |
||||
|
<STMTTRN> |
||||
|
<TRNTYPE>POS</TRNTYPE> |
||||
|
<DTPOSTED>20130824080000</DTPOSTED> |
||||
|
<TRNAMT>-90</TRNAMT> |
||||
|
<FITID>219381</FITID> |
||||
|
<NAME>China Scuba</NAME> |
||||
|
</STMTTRN> |
||||
|
</BANKTRANLIST> |
||||
|
<LEDGERBAL> |
||||
|
<BALAMT>2156.56</BALAMT> |
||||
|
<DTASOF>20130831165153</DTASOF> |
||||
|
</LEDGERBAL> |
||||
|
</STMTRS> |
||||
|
</STMTTRNRS> |
||||
|
</BANKMSGSRSV1> |
||||
|
<CREDITCARDMSGSRSV1> |
||||
|
<CCSTMTTRNRS> |
||||
|
<TRNUID>0</TRNUID> |
||||
|
<STATUS> |
||||
|
<CODE>0</CODE> |
||||
|
<SEVERITY>INFO</SEVERITY> |
||||
|
</STATUS> |
||||
|
<CCSTMTRS> |
||||
|
<CURDEF>USD</CURDEF> |
||||
|
<CCACCTFROM> |
||||
|
<ACCTID>123412341234</ACCTID> |
||||
|
</CCACCTFROM> |
||||
|
<BANKTRANLIST> |
||||
|
</BANKTRANLIST> |
||||
|
<LEDGERBAL> |
||||
|
<BALAMT>-562.00</BALAMT> |
||||
|
<DTASOF>20130831165153</DTASOF> |
||||
|
</LEDGERBAL> |
||||
|
</CCSTMTRS> |
||||
|
</CCSTMTTRNRS> |
||||
|
</CREDITCARDMSGSRSV1> |
||||
|
</OFX> |
@ -0,0 +1,8 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
from . import test_import_bank_statement |
||||
|
|
||||
|
checks = [ |
||||
|
test_import_bank_statement |
||||
|
] |
@ -0,0 +1,33 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
from openerp.tests.common import TransactionCase |
||||
|
from openerp.modules.module import get_module_resource |
||||
|
|
||||
|
class TestOfxFile(TransactionCase): |
||||
|
"""Tests for import bank statement ofx file format (account.bank.statement.import) |
||||
|
""" |
||||
|
|
||||
|
def setUp(self): |
||||
|
super(TestOfxFile, self).setUp() |
||||
|
self.statement_import_model = self.registry('account.bank.statement.import') |
||||
|
self.bank_statement_model = self.registry('account.bank.statement') |
||||
|
|
||||
|
def test_ofx_file_import(self): |
||||
|
try: |
||||
|
from ofxparse import OfxParser as ofxparser |
||||
|
except ImportError: |
||||
|
#the Python library isn't installed on the server, the OFX import is unavailable and the test cannot be run |
||||
|
return True |
||||
|
cr, uid = self.cr, self.uid |
||||
|
ofx_file_path = get_module_resource('account_bank_statement_import_ofx', 'test_ofx_file', 'test_ofx.ofx') |
||||
|
ofx_file = open(ofx_file_path, 'rb').read().encode('base64') |
||||
|
bank_statement_id = self.statement_import_model.create(cr, uid, dict( |
||||
|
file_type='ofx', |
||||
|
data_file=ofx_file, |
||||
|
)) |
||||
|
self.statement_import_model.parse_file(cr, uid, [bank_statement_id]) |
||||
|
statement_id = self.bank_statement_model.search(cr, uid, [('name', '=', '000000123')])[0] |
||||
|
bank_st_record = self.bank_statement_model.browse(cr, uid, statement_id) |
||||
|
self.assertEquals(bank_st_record.balance_start, 2156.56) |
||||
|
self.assertEquals(bank_st_record.balance_end_real, 1796.56) |
@ -0,0 +1,4 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from . import account_bank_statement_import_qif |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,32 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
{ |
||||
|
'name': 'Import QIF Bank Statement', |
||||
|
'version': '1.0', |
||||
|
'author': 'OpenERP SA', |
||||
|
'description': ''' |
||||
|
Module to import QIF bank statements. |
||||
|
====================================== |
||||
|
|
||||
|
This module allows you to import the machine readable QIF Files in Odoo: they are parsed and stored in human readable format in |
||||
|
Accounting \ Bank and Cash \ Bank Statements. |
||||
|
|
||||
|
Bank Statements may be generated containing a subset of the QIF information (only those transaction lines that are required for the |
||||
|
creation of the Financial Accounting records). |
||||
|
|
||||
|
Backported from Odoo 9.0 |
||||
|
|
||||
|
When testing with the provided test file, make sure the demo data from the |
||||
|
base account_bank_statement_import module has been imported, or manually |
||||
|
create periods for the year 2013. |
||||
|
''', |
||||
|
'images' : [], |
||||
|
'depends': ['account_bank_statement_import'], |
||||
|
'demo': [], |
||||
|
'data': [], |
||||
|
'auto_install': False, |
||||
|
'installable': True, |
||||
|
} |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,77 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
|
||||
|
import dateutil.parser |
||||
|
import base64 |
||||
|
from tempfile import TemporaryFile |
||||
|
|
||||
|
from openerp.tools.translate import _ |
||||
|
from openerp.osv import osv |
||||
|
|
||||
|
from openerp.addons.account_bank_statement_import import account_bank_statement_import as ibs |
||||
|
|
||||
|
ibs.add_file_type(('qif', 'QIF')) |
||||
|
|
||||
|
class account_bank_statement_import(osv.TransientModel): |
||||
|
_inherit = "account.bank.statement.import" |
||||
|
|
||||
|
def process_qif(self, cr, uid, data_file, journal_id=False, context=None): |
||||
|
""" Import a file in the .QIF format""" |
||||
|
try: |
||||
|
fileobj = TemporaryFile('wb+') |
||||
|
fileobj.write(base64.b64decode(data_file)) |
||||
|
fileobj.seek(0) |
||||
|
file_data = "" |
||||
|
for line in fileobj.readlines(): |
||||
|
file_data += line |
||||
|
fileobj.close() |
||||
|
if '\r' in file_data: |
||||
|
data_list = file_data.split('\r') |
||||
|
else: |
||||
|
data_list = file_data.split('\n') |
||||
|
header = data_list[0].strip() |
||||
|
header = header.split(":")[1] |
||||
|
except: |
||||
|
raise osv.except_osv(_('Import Error!'), _('Please check QIF file format is proper or not.')) |
||||
|
line_ids = [] |
||||
|
vals_line = {} |
||||
|
total = 0 |
||||
|
if header == "Bank": |
||||
|
vals_bank_statement = {} |
||||
|
for line in data_list: |
||||
|
line = line.strip() |
||||
|
if not line: |
||||
|
continue |
||||
|
if line[0] == 'D': # date of transaction |
||||
|
vals_line['date'] = dateutil.parser.parse(line[1:], fuzzy=True).date() |
||||
|
if vals_line.get('date') and not vals_bank_statement.get('period_id'): |
||||
|
period_ids = self.pool.get('account.period').find(cr, uid, vals_line['date'], context=context) |
||||
|
vals_bank_statement.update({'period_id': period_ids and period_ids[0] or False}) |
||||
|
elif line[0] == 'T': # Total amount |
||||
|
total += float(line[1:].replace(',', '')) |
||||
|
vals_line['amount'] = float(line[1:].replace(',', '')) |
||||
|
elif line[0] == 'N': # Check number |
||||
|
vals_line['ref'] = line[1:] |
||||
|
elif line[0] == 'P': # Payee |
||||
|
bank_account_id, partner_id = self._detect_partner(cr, uid, line[1:], identifying_field='owner_name', context=context) |
||||
|
vals_line['partner_id'] = partner_id |
||||
|
vals_line['bank_account_id'] = bank_account_id |
||||
|
vals_line['name'] = 'name' in vals_line and line[1:] + ': ' + vals_line['name'] or line[1:] |
||||
|
elif line[0] == 'M': # Memo |
||||
|
vals_line['name'] = 'name' in vals_line and vals_line['name'] + ': ' + line[1:] or line[1:] |
||||
|
elif line[0] == '^': # end of item |
||||
|
line_ids.append((0, 0, vals_line)) |
||||
|
vals_line = {} |
||||
|
elif line[0] == '\n': |
||||
|
line_ids = [] |
||||
|
else: |
||||
|
pass |
||||
|
else: |
||||
|
raise osv.except_osv(_('Error!'), _('Cannot support this Format !Type:%s.') % (header,)) |
||||
|
vals_bank_statement.update({'balance_end_real': total, |
||||
|
'line_ids': line_ids, |
||||
|
'journal_id': journal_id}) |
||||
|
return [vals_bank_statement] |
||||
|
|
||||
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,21 @@ |
|||||
|
!Type:Bank |
||||
|
D8/12/13 |
||||
|
T-1,000.00 |
||||
|
PDelta PC |
||||
|
^ |
||||
|
D8/15/13 |
||||
|
T-75.46 |
||||
|
PWalts Drugs |
||||
|
^ |
||||
|
D3/3/13 |
||||
|
T-379.00 |
||||
|
PEpic Technologies |
||||
|
^ |
||||
|
D3/4/13 |
||||
|
T-20.28 |
||||
|
PYOUR LOCAL SUPERMARKET |
||||
|
^ |
||||
|
D3/3/13 |
||||
|
T-421.35 |
||||
|
PSPRINGFIELD WATER UTILITY |
||||
|
^ |
@ -0,0 +1,8 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
from . import test_import_bank_statement |
||||
|
checks = [ |
||||
|
test_import_bank_statement |
||||
|
] |
||||
|
|
@ -0,0 +1,30 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# noqa: This is a backport from Odoo. OCA has no control over style here. |
||||
|
# flake8: noqa |
||||
|
from openerp.tests.common import TransactionCase |
||||
|
from openerp.modules.module import get_module_resource |
||||
|
|
||||
|
class TestQifFile(TransactionCase): |
||||
|
"""Tests for import bank statement qif file format (account.bank.statement.import) |
||||
|
""" |
||||
|
|
||||
|
def setUp(self): |
||||
|
super(TestQifFile, self).setUp() |
||||
|
self.statement_import_model = self.registry('account.bank.statement.import') |
||||
|
self.bank_statement_model = self.registry('account.bank.statement') |
||||
|
self.bank_statement_line_model = self.registry('account.bank.statement.line') |
||||
|
|
||||
|
def test_qif_file_import(self): |
||||
|
from openerp.tools import float_compare |
||||
|
cr, uid = self.cr, self.uid |
||||
|
qif_file_path = get_module_resource('account_bank_statement_import_qif', 'test_qif_file', 'test_qif.qif') |
||||
|
qif_file = open(qif_file_path, 'rb').read().encode('base64') |
||||
|
bank_statement_id = self.statement_import_model.create(cr, uid, dict( |
||||
|
file_type='qif', |
||||
|
data_file=qif_file, |
||||
|
)) |
||||
|
self.statement_import_model.parse_file(cr, uid, [bank_statement_id]) |
||||
|
line_id = self.bank_statement_line_model.search(cr, uid, [('name', '=', 'YOUR LOCAL SUPERMARKET')])[0] |
||||
|
statement_id = self.bank_statement_line_model.browse(cr, uid, line_id).statement_id.id |
||||
|
bank_st_record = self.bank_statement_model.browse(cr, uid, statement_id) |
||||
|
assert float_compare(bank_st_record.balance_end_real, -1896.09, 2) == 0 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue