Browse Source

[RFR] Move backported bank import modules from bank-payment

to bank-statement-import repository.
pull/2/head
Ronald Portier (Therp BV) 10 years ago
parent
commit
731330555a
  1. 5
      account_bank_statement_import/__init__.py
  2. 25
      account_bank_statement_import/__openerp__.py
  3. 96
      account_bank_statement_import/account_bank_statement_import.py
  4. 46
      account_bank_statement_import/account_bank_statement_import_view.xml
  5. 119
      account_bank_statement_import/demo/fiscalyear_period.xml
  6. 38
      account_bank_statement_import/demo/partner_bank.xml
  7. 5
      account_bank_statement_import_ofx/__init__.py
  8. 26
      account_bank_statement_import_ofx/__openerp__.py
  9. 74
      account_bank_statement_import_ofx/account_bank_statement_import_ofx.py
  10. 100
      account_bank_statement_import_ofx/test_ofx_file/test_ofx.ofx
  11. 5
      account_bank_statement_import_ofx/tests/__init__.py
  12. 30
      account_bank_statement_import_ofx/tests/test_import_bank_statement.py
  13. 5
      account_bank_statement_import_qif/__init__.py
  14. 27
      account_bank_statement_import_qif/__openerp__.py
  15. 75
      account_bank_statement_import_qif/account_bank_statement_import_qif.py
  16. 21
      account_bank_statement_import_qif/test_qif_file/test_qif.qif
  17. 5
      account_bank_statement_import_qif/tests/__init__.py
  18. 27
      account_bank_statement_import_qif/tests/test_import_bank_statement.py

5
account_bank_statement_import/__init__.py

@ -0,0 +1,5 @@
# -*- encoding: utf-8 -*-
import account_bank_statement_import
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

25
account_bank_statement_import/__openerp__.py

@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
{
'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:

96
account_bank_statement_import/account_bank_statement_import.py

@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
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:

46
account_bank_statement_import/account_bank_statement_import_view.xml

@ -0,0 +1,46 @@
<?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</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.periodical_processing_bank_statements" id="menu_account_bank_statement_import" action="action_account_bank_statement_import" sequence="11"/>
</data>
</openerp>

119
account_bank_statement_import/demo/fiscalyear_period.xml

@ -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>

38
account_bank_statement_import/demo/partner_bank.xml

@ -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>

5
account_bank_statement_import_ofx/__init__.py

@ -0,0 +1,5 @@
# -*- encoding: utf-8 -*-
import account_bank_statement_import_ofx
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

26
account_bank_statement_import_ofx/__openerp__.py

@ -0,0 +1,26 @@
# -*- encoding: utf-8 -*-
{
'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
""",
'data' : [],
'demo': [],
'auto_install': False,
'installable': True,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

74
account_bank_statement_import_ofx/account_bank_statement_import_ofx.py

@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
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:

100
account_bank_statement_import_ofx/test_ofx_file/test_ofx.ofx

@ -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>

5
account_bank_statement_import_ofx/tests/__init__.py

@ -0,0 +1,5 @@
from . import test_import_bank_statement
checks = [
test_import_bank_statement
]

30
account_bank_statement_import_ofx/tests/test_import_bank_statement.py

@ -0,0 +1,30 @@
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)

5
account_bank_statement_import_qif/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
import account_bank_statement_import_qif
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

27
account_bank_statement_import_qif/__openerp__.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
{
'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
''',
'images' : [],
'depends': ['account_bank_statement_import'],
'demo': [],
'data': [],
'auto_install': False,
'installable': True,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

75
account_bank_statement_import_qif/account_bank_statement_import_qif.py

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
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:

21
account_bank_statement_import_qif/test_qif_file/test_qif.qif

@ -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
^

5
account_bank_statement_import_qif/tests/__init__.py

@ -0,0 +1,5 @@
from . import test_import_bank_statement
checks = [
test_import_bank_statement
]

27
account_bank_statement_import_qif/tests/test_import_bank_statement.py

@ -0,0 +1,27 @@
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
Loading…
Cancel
Save