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