[MERGE] merged HEAD into current feature branch

This commit is contained in:
Raphaël Valyi
2014-03-21 16:12:47 -03:00
81 changed files with 1173 additions and 589 deletions

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_bank_statement_tax
#: model:ir.model,name:account_bank_statement_tax.model_account_bank_statement_line

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_bank_statement_tax
#: model:ir.model,name:account_bank_statement_tax.model_account_bank_statement_line

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_bank_statement_tax
#: model:ir.model,name:account_bank_statement_tax.model_account_bank_statement_line

View File

@@ -31,5 +31,7 @@ import account_banking
import parsers
import wizard
import res_partner
import res_bank
import res_partner_bank
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -26,14 +26,13 @@
{
'name': 'Account Banking',
'version': '0.1.136',
'version': '0.2',
'license': 'AGPL-3',
'author': 'Banking addons community',
'website': 'https://launchpad.net/banking-addons',
'category': 'Banking addons',
'depends': [
'account_voucher',
'account_iban_preserve_domestic',
],
'data': [
'security/ir.model.access.csv',
@@ -47,14 +46,9 @@
'js': [
'static/src/js/account_banking.js',
],
'external_dependencies': {
'python' : ['BeautifulSoup'],
},
'description': '''
Module to do banking.
Note: This module is depending on BeautifulSoup.
This modules tries to combine all current banking import and export
schemes. Rationale for this is that it is quite common to have foreign
bank account numbers next to national bank account numbers. The current

View File

@@ -65,14 +65,8 @@ Modifications are extensive:
from openerp.osv import orm, fields
from openerp.osv.osv import except_osv
from openerp.tools.translate import _
from openerp import netsvc, SUPERUSER_ID
from openerp import netsvc
from openerp.addons.decimal_precision import decimal_precision as dp
from openerp.addons.account_banking import sepa
from openerp.addons.account_banking.wizard.banktools import get_or_create_bank
def warning(title, message):
'''Convenience routine'''
return {'warning': {'title': title, 'message': message}}
class account_banking_account_settings(orm.Model):
@@ -559,415 +553,6 @@ class account_bank_statement_line(orm.Model):
'currency': _get_currency,
}
account_bank_statement_line()
class res_partner_bank(orm.Model):
'''
This is a hack to circumvent the very limited but widely used base_iban
dependency. The usage of __mro__ requires inside information of
inheritence. This code is tested and works - it bypasses base_iban
altogether. Be sure to use 'super' for inherited classes from here though.
Extended functionality:
1. BBAN and IBAN are considered equal
2. Online databases are checked when available
3. Banks are created on the fly when using IBAN
4. Storage is uppercase, not lowercase
5. Presentation is formal IBAN
6. BBAN's are generated from IBAN when possible
7. In the absence of online databanks, BBAN's are checked on format
using IBAN specs.
'''
_inherit = 'res.partner.bank'
def __init__(self, *args, **kwargs):
'''
Locate founder (first non inherited class) in inheritance tree.
Defaults to super()
Algorithm should prevent moving unknown classes between
base.res_partner_bank and this module's res_partner_bank.
'''
self._founder = super(res_partner_bank, self)
self._founder.__init__(*args, **kwargs)
mro = self.__class__.__mro__
for i in range(len(mro)):
if mro[i].__module__.startswith('openerp.addons.base.'):
self._founder = mro[i]
break
def init(self, cr):
'''
Update existing iban accounts to comply to new regime
'''
partner_bank_obj = self.pool.get('res.partner.bank')
bank_ids = partner_bank_obj.search(
cr, SUPERUSER_ID, [('state', '=', 'iban')], limit=0)
for bank in partner_bank_obj.read(cr, SUPERUSER_ID, bank_ids):
write_vals = {}
if bank['state'] == 'iban':
iban_acc = sepa.IBAN(bank['acc_number'])
if iban_acc.valid:
write_vals['acc_number_domestic'] = iban_acc.localized_BBAN
write_vals['acc_number'] = str(iban_acc)
elif bank['acc_number'] != bank['acc_number'].upper():
write_vals['acc_number'] = bank['acc_number'].upper()
if write_vals:
partner_bank_obj.write(
cr, SUPERUSER_ID, bank['id'], write_vals)
@staticmethod
def _correct_IBAN(acc_number):
'''
Routine to correct IBAN values and deduce localized values when valid.
Note: No check on validity IBAN/Country
'''
iban = sepa.IBAN(acc_number)
return (str(iban), iban.localized_BBAN)
def create(self, cr, uid, vals, context=None):
'''
Create dual function IBAN account for SEPA countries
'''
if vals.get('state') == 'iban':
iban = (vals.get('acc_number')
or vals.get('acc_number_domestic', False))
vals['acc_number'], vals['acc_number_domestic'] = (
self._correct_IBAN(iban))
return self._founder.create(self, cr, uid, vals, context)
def write(self, cr, uid, ids, vals, context=None):
'''
Create dual function IBAN account for SEPA countries
Update the domestic account number when the IBAN is
written, or clear the domestic number on regular account numbers.
'''
if ids and isinstance(ids, (int, long)):
ids = [ids]
for account in self.read(
cr, uid, ids, ['state', 'acc_number']):
if 'state' in vals or 'acc_number' in vals:
account.update(vals)
if account['state'] == 'iban':
vals['acc_number'], vals['acc_number_domestic'] = (
self._correct_IBAN(account['acc_number']))
else:
vals['acc_number_domestic'] = False
self._founder.write(self, cr, uid, account['id'], vals, context)
return True
def search(self, cr, uid, args, *rest, **kwargs):
'''
Overwrite search, as both acc_number and iban now can be filled, so
the original base_iban 'search and search again fuzzy' tactic now can
result in doubled findings. Also there is now enough info to search
for local accounts when a valid IBAN was supplied.
Chosen strategy: create complex filter to find all results in just
one search
'''
def is_term(arg):
'''Flag an arg as term or otherwise'''
return isinstance(arg, (list, tuple)) and len(arg) == 3
def extended_filter_term(term):
'''
Extend the search criteria in term when appropriate.
'''
extra_term = None
if term[0].lower() == 'acc_number' and term[1] in ('=', '=='):
iban = sepa.IBAN(term[2])
if iban.valid:
# Some countries can't convert to BBAN
try:
bban = iban.localized_BBAN
# Prevent empty search filters
if bban:
extra_term = ('acc_number_domestic', term[1], bban)
except:
pass
if extra_term:
return ['|', term, extra_term]
return [term]
def extended_search_expression(args):
'''
Extend the search expression in args when appropriate.
The expression itself is in reverse polish notation, so recursion
is not needed.
'''
if not args:
return []
all = []
if is_term(args[0]) and len(args) > 1:
# Classic filter, implicit '&'
all += ['&']
for arg in args:
if is_term(arg):
all += extended_filter_term(arg)
else:
all += arg
return all
# Extend search filter
newargs = extended_search_expression(args)
# Original search
results = super(res_partner_bank, self).search(
cr, uid, newargs, *rest, **kwargs)
return results
def read(
self, cr, uid, ids, fields=None, context=None, load='_classic_read'):
'''
Convert IBAN electronic format to IBAN display format
SR 2012-02-19: do we really need this? Fields are converted upon write already.
'''
if fields and 'state' not in fields:
fields.append('state')
records = self._founder.read(self, cr, uid, ids, fields, context, load)
is_list = True
if not isinstance(records, list):
records = [records,]
is_list = False
for record in records:
if 'acc_number' in record and record['state'] == 'iban':
record['acc_number'] = unicode(sepa.IBAN(record['acc_number']))
if is_list:
return records
return records[0]
def check_iban(self, cr, uid, ids, context=None):
'''
Check IBAN number
'''
for bank_acc in self.browse(cr, uid, ids, context=context):
if bank_acc.state == 'iban' and bank_acc.acc_number:
iban = sepa.IBAN(bank_acc.acc_number)
if not iban.valid:
return False
return True
def get_bban_from_iban(self, cr, uid, ids, context=None):
'''
Return the local bank account number aka BBAN from the IBAN.
'''
res = {}
for record in self.browse(cr, uid, ids, context):
if not record.state == 'iban':
res[record.id] = False
else:
iban_acc = sepa.IBAN(record.acc_number)
try:
res[record.id] = iban_acc.localized_BBAN
except NotImplementedError:
res[record.id] = False
return res
def onchange_acc_number(
self, cr, uid, ids, acc_number, acc_number_domestic,
state, partner_id, country_id, context=None):
if state == 'iban':
return self.onchange_iban(
cr, uid, ids, acc_number, acc_number_domestic,
state, partner_id, country_id, context=None
)
else:
return self.onchange_domestic(
cr, uid, ids, acc_number,
partner_id, country_id, context=None
)
def onchange_domestic(
self, cr, uid, ids, acc_number,
partner_id, country_id, context=None):
'''
Trigger to find IBAN. When found:
1. Reformat BBAN
2. Autocomplete bank
TODO: prevent unnecessary assignment of country_ids and
browsing of the country
'''
if not acc_number:
return {}
values = {}
country_obj = self.pool.get('res.country')
country_ids = []
country = False
# Pre fill country based on available data. This is just a default
# which can be overridden by the user.
# 1. Use provided country_id (manually filled)
if country_id:
country = country_obj.browse(cr, uid, country_id, context=context)
country_ids = [country_id]
# 2. Use country_id of found bank accounts
# This can be usefull when there is no country set in the partners
# addresses, but there was a country set in the address for the bank
# account itself before this method was triggered.
elif ids and len(ids) == 1:
partner_bank_obj = self.pool.get('res.partner.bank')
partner_bank_id = partner_bank_obj.browse(cr, uid, ids[0], context=context)
if partner_bank_id.country_id:
country = partner_bank_id.country_id
country_ids = [country.id]
# 3. Use country_id of default address of partner
# The country_id of a bank account is a one time default on creation.
# It originates in the same address we are about to check, but
# modifications on that address afterwards are not transfered to the
# bank account, hence the additional check.
elif partner_id:
partner_obj = self.pool.get('res.partner')
country = partner_obj.browse(cr, uid, partner_id, context=context).country
country_ids = country and [country.id] or []
# 4. Without any of the above, take the country from the company of
# the handling user
if not country_ids:
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
# Try user companies partner (user no longer has address in 6.1)
if (user.company_id and
user.company_id.partner_id and
user.company_id.partner_id.country
):
country_ids = [user.company_id.partner_id.country.id]
else:
if (user.company_id and user.company_id.partner_id and
user.company_id.partner_id.country):
country_ids = [user.company_id.partner_id.country.id]
else:
# Ok, tried everything, give up and leave it to the user
return warning(_('Insufficient data'),
_('Insufficient data to select online '
'conversion database')
)
result = {'value': values}
# Complete data with online database when available
if country_ids:
country = country_obj.browse(
cr, uid, country_ids[0], context=context)
values['country_id'] = country_ids[0]
if country and country.code in sepa.IBAN.countries:
try:
info = sepa.online.account_info(country.code, acc_number)
if info:
iban_acc = sepa.IBAN(info.iban)
if iban_acc.valid:
values['acc_number_domestic'] = iban_acc.localized_BBAN
values['acc_number'] = unicode(iban_acc)
values['state'] = 'iban'
bank_id, country_id = get_or_create_bank(
self.pool, cr, uid,
info.bic or iban_acc.BIC_searchkey,
name = info.bank
)
if country_id:
values['country_id'] = country_id
values['bank'] = bank_id or False
if info.bic:
values['bank_bic'] = info.bic
else:
info = None
if info is None:
result.update(warning(
_('Invalid data'),
_('The account number appears to be invalid for %s')
% country.name
))
except NotImplementedError:
if country.code in sepa.IBAN.countries:
acc_number_fmt = sepa.BBAN(acc_number, country.code)
if acc_number_fmt.valid:
values['acc_number_domestic'] = str(acc_number_fmt)
else:
result.update(warning(
_('Invalid format'),
_('The account number has the wrong format for %s')
% country.name
))
return result
def onchange_iban(
self, cr, uid, ids, acc_number, acc_number_domestic,
state, partner_id, country_id, context=None):
'''
Trigger to verify IBAN. When valid:
1. Extract BBAN as local account
2. Auto complete bank
'''
if not acc_number:
return {}
iban_acc = sepa.IBAN(acc_number)
if iban_acc.valid:
bank_id, country_id = get_or_create_bank(
self.pool, cr, uid, iban_acc.BIC_searchkey,
code=iban_acc.BIC_searchkey
)
return {
'value': dict(
acc_number_domestic = iban_acc.localized_BBAN,
acc_number = unicode(iban_acc),
country = country_id or False,
bank = bank_id or False,
)
}
return warning(_('Invalid IBAN account number!'),
_("The IBAN number doesn't seem to be correct")
)
res_partner_bank()
class res_bank(orm.Model):
'''
Add a on_change trigger to automagically fill bank details from the
online SWIFT database. Allow hand filled names to overrule SWIFT names.
'''
_inherit = 'res.bank'
def onchange_bic(self, cr, uid, ids, bic, name, context=None):
'''
Trigger to auto complete other fields.
'''
if not bic:
return {}
info, address = sepa.online.bank_info(bic)
if not info:
return {}
if address and address.country_id:
country_id = self.pool.get('res.country').search(
cr, uid, [('code','=',address.country_id)]
)
country_id = country_id and country_id[0] or False
else:
country_id = False
return {
'value': dict(
# Only the first eight positions of BIC are used for bank
# transfers, so ditch the rest.
bic = info.bic[:8],
street = address.street,
street2 =
address.has_key('street2') and address.street2 or False,
zip = address.zip,
city = address.city,
country = country_id,
name = name and name or info.name,
)
}
res_bank()
class invoice(orm.Model):
'''

View File

@@ -95,7 +95,7 @@
action="action_account_banking_journals"
sequence="20"
/>
<!-- Create new view on imported statement files -->
<record model="ir.ui.view" id="view_account_banking_imported_file_form">
<field name="name">account.banking.imported.file.form</field>
@@ -221,7 +221,7 @@
</xpath>
<!-- Add invisible field for identification of import file
on bank statements
on bank statements
-->
<field name="balance_end_real" position="after">
<field name="banking_id" invisible="True"/>
@@ -248,7 +248,10 @@
position="after">
<field name="partner_bank_id"/>
</xpath>
<xpath expr="//field[@name='line_ids']/tree//field[@name='account_id']"
position="attributes">
<attribute name="attrs">{'readonly': ['|', ('state', '!=', 'draft'), ('match_type', '!=', '')]}</attribute>
</xpath>
<xpath expr="//field[@name='line_ids']/tree/field[@name='amount']"
position="after">
<field name="match_type"/>
@@ -286,42 +289,13 @@
</field>
</record>
<record id="view_partner_bank_account_banking_form_2" model="ir.ui.view">
<field name="name">res.partner.bank.form.banking-2</field>
<field name="model">res.partner.bank</field>
<field name="inherit_id" ref="base.view_partner_bank_form"/>
<field name="priority" eval="24"/>
<field name="arch" type="xml">
<data>
<field name="acc_number" position="attributes">
<attribute name="on_change">onchange_acc_number(acc_number, acc_number_domestic, state, partner_id, country_id)</attribute>
</field>
<field name="acc_number_domestic" position="attributes">
<attribute name="on_change">onchange_domestic(acc_number_domestic, partner_id, country_id)</attribute>
</field>
</data>
</field>
</record>
<!-- Set trigger on BIC in res_bank form -->
<record id="view_res_bank_account_banking_form_1" model="ir.ui.view">
<field name="name">res.bank.form.banking-1</field>
<field name="model">res.bank</field>
<field name="inherit_id" ref="base.view_res_bank_form"/>
<field name="arch" type="xml">
<field name="bic" position="replace">
<field name="bic" on_change="onchange_bic(bic, name)"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_bank_statement_line_tree">
<field name="name">Bank statement line tree view</field>
<field name="model">account.bank.statement.line</field>
<field name="arch" type="xml">
<tree string="Statement lines" colors="black:state == 'confirmed';darkmagenta:match_multi == True;crimson:duplicate == True;grey:state=='draft';">
<field name="sequence" readonly="1" invisible="1"/>
<field name="date" groups="base.group_extended"/>
<field name="date"/>
<field name="name"/>
<field name="ref"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
@@ -336,7 +310,8 @@
<field name="partner_bank_id"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
<!-- TODO note the references to parent from the statement form view -->
<field domain="[('journal_id','=',parent.journal_id)]" name="account_id"/>
<field domain="[('journal_id','=',parent.journal_id)]"
attrs="{'readonly': ['|', ('state', '!=', 'draft'), ('match_type', '!=', '')]}" name="account_id"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>
<field name="amount"/>
<field name="match_type"/>

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking
#: field:account.bank.statement.line,reconcile_id:0

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2011 - 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import orm
class ResBank(orm.Model):
_inherit = 'res.bank'
def online_bank_info(self, cr, uid, bic, context=None):
"""
API hook for legacy online lookup of BICs,
to be removed in OpenERP 8.0.
"""
return False, False

View File

@@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import orm
from openerp.addons.account_banking import sepa
class ResPartnerBank(orm.Model):
_inherit = 'res.partner.bank'
def online_account_info(
self, cr, uid, country_code, acc_number, context=None):
"""
API hook for legacy online lookup of account info,
to be removed in OpenERP 8.0.
"""
return False
def search(self, cr, uid, args, *rest, **kwargs):
"""
When a complete IBAN is searched, also search for its BBAN
if we have the domestic column. Disregard spaces
when comparing IBANs.
"""
def is_term(arg):
'''Flag an arg as term or otherwise'''
return isinstance(arg, (list, tuple)) and len(arg) == 3
def extended_filter_term(term):
'''
Extend the search criteria in term when appropriate.
'''
result = [term]
extra_terms = []
if term[0].lower() == 'acc_number' and term[1] in ('=', '=='):
iban = sepa.IBAN(term[2])
if iban.valid:
# Disregard spaces when comparing IBANs
cr.execute(
"""
SELECT id FROM res_partner_bank
WHERE replace(acc_number, ' ', '') = %s
""", (term[2].replace(' ', ''),))
ids = [row[0] for row in cr.fetchall()]
result = [('id', 'in', ids)]
if 'acc_number_domestic' in self._columns:
bban = iban.localized_BBAN
# Prevent empty search filters
if bban:
extra_terms.append(
('acc_number_domestic', term[1], bban))
for extra_term in extra_terms:
result = ['|'] + result + [extra_term]
return result
def extended_search_expression(args):
'''
Extend the search expression in args when appropriate.
The expression itself is in reverse polish notation, so recursion
is not needed.
'''
if not args:
return []
result = []
if is_term(args[0]) and len(args) > 1:
# Classic filter, implicit '&'
result += ['&']
for arg in args:
if is_term(arg):
result += extended_filter_term(arg)
else:
result += arg
return result
# Extend search filter
newargs = extended_search_expression(args)
# Original search
return super(ResPartnerBank, self).search(
cr, uid, newargs, *rest, **kwargs)

View File

@@ -19,6 +19,5 @@
#
##############################################################################
import iban
import online
IBAN = iban.IBAN
BBAN = iban.BBAN

View File

@@ -408,10 +408,9 @@ class IBAN(str):
Localized format of local or Basic Bank Account Number, aka BBAN
'''
if self.countrycode == 'TR':
raise NotImplementedError, (
'The Turkish BBAN requires information that is not in the '
'IBAN number.'
)
# The Turkish BBAN requires information that is not in the
# IBAN number.
return False
return self.BBAN_format.BBAN(self)
@property

View File

@@ -63,12 +63,6 @@ def get_bank_accounts(pool, cr, uid, account_number, log, fail=False):
bank_account_ids = partner_bank_obj.search(cr, uid, [
('acc_number', '=', account_number)
])
if not bank_account_ids:
# SR 2012-02-19 does the search() override in res_partner_bank
# provides this result on the previous query?
bank_account_ids = partner_bank_obj.search(cr, uid, [
('acc_number_domestic', '=', account_number)
])
if not bank_account_ids:
if not fail:
log.append(
@@ -237,7 +231,7 @@ def get_or_create_bank(pool, cr, uid, bic, online=False, code=None,
bank_id = False
if online:
info, address = sepa.online.bank_info(bic)
info, address = bank_obj.online_bank_info(cr, uid, bic, context=context)
if info:
bank_id = bank_obj.create(cr, uid, dict(
code = info.code,
@@ -301,7 +295,6 @@ def create_bank_account(pool, cr, uid, partner_id,
owner_name = holder_name,
country_id = country_id,
)
bankcode = None
# Are we dealing with IBAN?
iban = sepa.IBAN(account_number)
@@ -309,23 +302,20 @@ def create_bank_account(pool, cr, uid, partner_id,
# Take as much info as possible from IBAN
values.state = 'iban'
values.acc_number = str(iban)
values.acc_number_domestic = iban.BBAN
bankcode = iban.bankcode + iban.countrycode
else:
# No, try to convert to IBAN
values.state = 'bank'
values.acc_number = values.acc_number_domestic = account_number
values.acc_number = account_number
if country_id:
country_code = pool.get('res.country').read(
cr, uid, country_id, ['code'], context=context)['code']
if country_code in sepa.IBAN.countries:
account_info = sepa.online.account_info(
country_code, values.acc_number)
account_info = pool['res.partner.bank'].online_account_info(
cr, uid, country_code, values.acc_number, context=context)
if account_info:
values.acc_number = iban = account_info.iban
values.state = 'iban'
bankcode = account_info.code
bic = account_info.bic
if bic:

View File

@@ -21,8 +21,8 @@
from lxml import etree
from openerp.osv.orm import except_orm
from account_banking.parsers import models
from account_banking.parsers.convert import str2date
from openerp.addons.account_banking.parsers import models
from openerp.addons.account_banking.parsers.convert import str2date
bt = models.mem_bank_transaction

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_fi_patu
#: code:addons/account_banking_fi_patu/patu.py:115

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_fi_patu
#: code:addons/account_banking_fi_patu/patu.py:115

View File

@@ -0,0 +1,3 @@
from . import online
from . import urlagent
from . import model

View File

@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Banking Addons - Iban lookup (legacy)',
'version': '0.1',
'license': 'AGPL-3',
'author': 'Banking addons community',
'website': 'https://launchpad.net/banking-addons',
'category': 'Banking addons',
'depends': [
'account_banking',
'account_iban_preserve_domestic',
],
'data': [
'view/res_bank.xml',
'view/res_partner_bank.xml',
],
'external_dependencies': {
'python': ['BeautifulSoup'],
},
'description': '''
This addons contains the legacy infrastructure for autocompletion of IBANs
and BBANs.
The autocompletion was implemented for Dutch IBANs, but as it turns out
the online database that it consults does not get updated. As a result,
the autocompletion will come up with outdated IBANs and BICs.
This module is deprecated and will be dropped in OpenERP 8.0.
''',
'auto_install': False,
'installable': True,
}

View File

@@ -0,0 +1,2 @@
from . import res_bank
from . import res_partner_bank

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import orm
from openerp.addons.account_banking_iban_lookup import online
class ResBank(orm.Model):
_inherit = 'res.bank'
def online_bank_info(self, cr, uid, bic, context=None):
"""
Overwrite existing API hook from account_banking
"""
return online.bank_info(bic)
def onchange_bic(
self, cr, uid, ids, bic, name, context=None):
if not bic:
return {}
info, address = online.bank_info(bic)
if not info:
return {}
if address and address.country_id:
country_ids = self.pool.get('res.country').search(
cr, uid, [('code', '=', address.country_id)])
country_id = country_ids[0] if country_ids else False
else:
country_id = False
return {
'value': dict(
# Only the first eight positions of BIC are used for bank
# transfers, so ditch the rest.
bic=info.bic[:8],
street=address.street,
street2=address.get('street2', False),
zip=address.zip,
city=address.city,
country=country_id,
name=name or info.name,
)
}

View File

@@ -0,0 +1,271 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2014 Therp BV (<http://therp.nl>).
#
# All other contributions are (C) by their respective contributors
#
# All Rights Reserved
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import SUPERUSER_ID
from openerp.osv import orm
from openerp.tools.translate import _
from openerp.addons.account_banking_iban_lookup import online
from openerp.addons.account_banking import sepa
from openerp.addons.account_banking.wizard.banktools import get_or_create_bank
def warning(title, message):
'''Convenience routine'''
return {'warning': {'title': title, 'message': message}}
class res_partner_bank(orm.Model):
'''
Extended functionality:
1. BBAN and IBAN are considered equal
2. Online lookup when an API is available (providing NL in this module)
3. Banks are created on the fly when using IBAN + online
4. IBAN formatting
5. BBAN's are generated from IBAN when possible
'''
_inherit = 'res.partner.bank'
def init(self, cr):
'''
Update existing iban accounts to comply to new regime
'''
partner_bank_obj = self.pool.get('res.partner.bank')
bank_ids = partner_bank_obj.search(
cr, SUPERUSER_ID, [('state', '=', 'iban')], limit=0)
for bank in partner_bank_obj.read(cr, SUPERUSER_ID, bank_ids):
write_vals = {}
if bank['state'] == 'iban':
iban_acc = sepa.IBAN(bank['acc_number'])
if iban_acc.valid:
write_vals['acc_number_domestic'] = iban_acc.localized_BBAN
write_vals['acc_number'] = str(iban_acc)
elif bank['acc_number'] != bank['acc_number'].upper():
write_vals['acc_number'] = bank['acc_number'].upper()
if write_vals:
partner_bank_obj.write(
cr, SUPERUSER_ID, bank['id'], write_vals)
@staticmethod
def _correct_IBAN(acc_number):
'''
Routine to correct IBAN values and deduce localized values when valid.
Note: No check on validity IBAN/Country
'''
iban = sepa.IBAN(acc_number)
return (str(iban), iban.localized_BBAN)
def create(self, cr, uid, vals, context=None):
'''
Create dual function IBAN account for SEPA countries
'''
if vals.get('state') == 'iban':
iban = (vals.get('acc_number')
or vals.get('acc_number_domestic', False))
vals['acc_number'], vals['acc_number_domestic'] = (
self._correct_IBAN(iban))
return super(res_partner_bank, self).create(
cr, uid, vals, context)
def write(self, cr, uid, ids, vals, context=None):
'''
Create dual function IBAN account for SEPA countries
Update the domestic account number when the IBAN is
written, or clear the domestic number on regular account numbers.
'''
if ids and isinstance(ids, (int, long)):
ids = [ids]
for account in self.read(
cr, uid, ids, ['state', 'acc_number']):
if 'state' in vals or 'acc_number' in vals:
account.update(vals)
if account['state'] == 'iban':
vals['acc_number'], vals['acc_number_domestic'] = (
self._correct_IBAN(account['acc_number']))
else:
vals['acc_number_domestic'] = False
super(res_partner_bank, self).write(
cr, uid, account['id'], vals, context)
return True
def onchange_acc_number(
self, cr, uid, ids, acc_number, acc_number_domestic,
state, partner_id, country_id, context=None):
if state == 'iban':
return self.onchange_iban(
cr, uid, ids, acc_number, acc_number_domestic,
state, partner_id, country_id, context=None
)
else:
return self.onchange_domestic(
cr, uid, ids, acc_number,
partner_id, country_id, context=None
)
def onchange_domestic(
self, cr, uid, ids, acc_number,
partner_id, country_id, context=None):
'''
Trigger to find IBAN. When found:
1. Reformat BBAN
2. Autocomplete bank
TODO: prevent unnecessary assignment of country_ids and
browsing of the country
'''
if not acc_number:
return {}
values = {}
country_obj = self.pool.get('res.country')
country_ids = []
country = False
# Pre fill country based on available data. This is just a default
# which can be overridden by the user.
# 1. Use provided country_id (manually filled)
if country_id:
country = country_obj.browse(cr, uid, country_id, context=context)
country_ids = [country_id]
# 2. Use country_id of found bank accounts
# This can be usefull when there is no country set in the partners
# addresses, but there was a country set in the address for the bank
# account itself before this method was triggered.
elif ids and len(ids) == 1:
partner_bank_obj = self.pool.get('res.partner.bank')
partner_bank_id = partner_bank_obj.browse(
cr, uid, ids[0], context=context)
if partner_bank_id.country_id:
country = partner_bank_id.country_id
country_ids = [country.id]
# 3. Use country_id of default address of partner
# The country_id of a bank account is a one time default on creation.
# It originates in the same address we are about to check, but
# modifications on that address afterwards are not transfered to the
# bank account, hence the additional check.
elif partner_id:
partner_obj = self.pool.get('res.partner')
country = partner_obj.browse(
cr, uid, partner_id, context=context).country
country_ids = country and [country.id] or []
# 4. Without any of the above, take the country from the company of
# the handling user
if not country_ids:
user = self.pool.get('res.users').browse(
cr, uid, uid, context=context)
# Try user companies partner (user no longer has address in 6.1)
if (user.company_id and
user.company_id.partner_id and
user.company_id.partner_id.country):
country_ids = [user.company_id.partner_id.country.id]
else:
if (user.company_id and user.company_id.partner_id and
user.company_id.partner_id.country):
country_ids = [user.company_id.partner_id.country.id]
else:
# Ok, tried everything, give up and leave it to the user
return warning(_('Insufficient data'),
_('Insufficient data to select online '
'conversion database')
)
result = {'value': values}
# Complete data with online database when available
if country_ids:
country = country_obj.browse(
cr, uid, country_ids[0], context=context)
values['country_id'] = country_ids[0]
if country and country.code in sepa.IBAN.countries:
info = online.account_info(country.code, acc_number)
if info:
iban_acc = sepa.IBAN(info.iban)
if iban_acc.valid:
values['acc_number_domestic'] = iban_acc.localized_BBAN
values['acc_number'] = unicode(iban_acc)
values['state'] = 'iban'
bank_id, country_id = get_or_create_bank(
self.pool, cr, uid,
info.bic or iban_acc.BIC_searchkey,
name=info.bank)
if country_id:
values['country_id'] = country_id
values['bank'] = bank_id or False
if info.bic:
values['bank_bic'] = info.bic
else:
info = None
if info is None:
result.update(warning(
_('Invalid data'),
_('The account number appears to be invalid for %s')
% country.name
))
if info is False:
if country.code in sepa.IBAN.countries:
acc_number_fmt = sepa.BBAN(acc_number, country.code)
if acc_number_fmt.valid:
values['acc_number_domestic'] = str(acc_number_fmt)
else:
result.update(warning(
_('Invalid format'),
_('The account number has the wrong format for %s')
% country.name
))
return result
def onchange_iban(
self, cr, uid, ids, acc_number, acc_number_domestic,
state, partner_id, country_id, context=None):
'''
Trigger to verify IBAN. When valid:
1. Extract BBAN as local account
2. Auto complete bank
'''
if not acc_number:
return {}
iban_acc = sepa.IBAN(acc_number)
if iban_acc.valid:
bank_id, country_id = get_or_create_bank(
self.pool, cr, uid, iban_acc.BIC_searchkey,
code=iban_acc.BIC_searchkey
)
return {
'value': dict(
acc_number_domestic=iban_acc.localized_BBAN,
acc_number=unicode(iban_acc),
country=country_id or False,
bank=bank_id or False,
)
}
return warning(
_('Invalid IBAN account number!'),
_("The IBAN number doesn't seem to be correct"))
def online_account_info(
self, cr, uid, country_code, acc_number, context=None):
"""
Overwrite API hook from account_banking
"""
return online.account_info(country_code, acc_number)

View File

@@ -1,4 +1,4 @@
# -*- encoding: utf-8 -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
@@ -26,7 +26,7 @@ import re
import urllib, urllib2
from BeautifulSoup import BeautifulSoup
from openerp.addons.account_banking.sepa import postalcode
from openerp.addons.account_banking.sepa.urlagent import URLAgent, SoupForm
from openerp.addons.account_banking_iban_lookup.urlagent import URLAgent, SoupForm
from openerp.addons.account_banking.sepa.iban import IBAN
from openerp.addons.account_banking.struct import struct
@@ -157,13 +157,13 @@ def account_info(iso, bank_acc):
'''
Consult the online database for this country to obtain its
corresponding IBAN/BIC number and other info available.
Raise NotImplemented when no information service could be found.
Returns None when a service was found but something went wrong.
Returns a dictionary (struct) of information when found.
Returns a dictionary (struct) of information when found, or
False when not implemented.
'''
if iso in _account_info:
return _account_info[iso](bank_acc)
raise NotImplementedError()
return False
bic_re = re.compile("[^']+'([^']*)'.*")
SWIFTlink = 'http://www.swift.com/bsl/freequery.do'

View File

@@ -25,7 +25,6 @@ forms and to parse the results back in. It is heavily based on BeautifulSoup.
'''
import urllib
from BeautifulSoup import BeautifulSoup
__all__ = ['urlsplit', 'urljoin', 'pathbase', 'urlbase', 'SoupForm',
'URLAgent'

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_res_bank_account_banking_form_1" model="ir.ui.view">
<field name="name">Add BIC lookup to bank form</field>
<field name="model">res.bank</field>
<field name="inherit_id" ref="base.view_res_bank_form"/>
<field name="arch" type="xml">
<field name="bic" position="replace">
<field name="bic" on_change="onchange_bic(bic, name)"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_partner_bank_account_banking_form_2" model="ir.ui.view">
<field name="name">Add autocompletion methods to partner bank form</field>
<field name="model">res.partner.bank</field>
<field name="inherit_id" ref="base.view_partner_bank_form"/>
<field name="priority" eval="24"/>
<field name="arch" type="xml">
<data>
<field name="acc_number" position="attributes">
<attribute name="on_change">onchange_acc_number(acc_number, acc_number_domestic, state, partner_id, country_id)</attribute>
</field>
<field name="acc_number_domestic" position="attributes">
<attribute name="on_change">onchange_domestic(acc_number_domestic, partner_id, country_id)</attribute>
</field>
</data>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import mt940

View File

@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name" : "MT940",
"version" : "1.0",
"author" : "Therp BV",
"complexity": "expert",
"description": """
This addon provides a generic parser for MT940 files. Given that MT940 is a
non-open non-standard of pure evil in the way that every bank cooks up its own
interpretation of it, this addon alone won't help you much. It is rather
intended to be used by other addons to implement the dialect specific to a
certain bank.
See account_banking_nl_ing_mt940 for an example on how to use it.
""",
"category" : "Dependency",
"depends" : [
'account_banking',
],
"data" : [
],
"js": [
],
"css": [
],
"qweb": [
],
"auto_install": False,
"installable": True,
"application": False,
"external_dependencies" : {
'python' : [],
},
}

View File

@@ -0,0 +1,217 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
"""
Parser for MT940 format files
"""
import re
import datetime
import logging
try:
from openerp.addons.account_banking.parsers.models import\
mem_bank_statement, mem_bank_transaction
from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT
except ImportError:
#this allows us to run this file standalone, see __main__ at the end
class mem_bank_statement:
def __init__(self):
self.transactions = []
class mem_bank_transaction:
pass
DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
class MT940(object):
'''Inherit this class in your account_banking.parsers.models.parser,
define functions to handle the tags you need to handle and adjust static
variables as needed.
Note that order matters: You need to do your_parser(MT940, parser), not the
other way around!
At least, you should override handle_tag_61 and handle_tag_86. Don't forget
to call super.
handle_tag_* functions receive the remainder of the the line (that is,
without ':XX:') and are supposed to write into self.current_transaction'''
header_lines = 3
'''One file can contain multiple statements, each with its own poorly
documented header. For now, the best thing to do seems to skip that'''
footer_regex = '^-}$'
footer_regex = '^-XXX$'
'The line that denotes end of message, we need to create a new statement'
tag_regex = '^:[0-9]{2}[A-Z]*:'
'The beginning of a record, should be anchored to beginning of the line'
def __init__(self, *args, **kwargs):
super(MT940, self).__init__(*args, **kwargs)
'state variables'
self.current_statement = None
'type account_banking.parsers.models.mem_bank_statement'
self.current_transaction = None
'type account_banking.parsers.models.mem_bank_transaction'
self.statements = []
'parsed statements up to now'
def parse(self, cr, data):
'implements account_banking.parsers.models.parser.parse()'
iterator = data.split('\r\n').__iter__()
line = None
record_line = ''
try:
while True:
if not self.current_statement:
self.handle_header(cr, line, iterator)
line = iterator.next()
if not self.is_tag(cr, line) and not self.is_footer(cr, line):
record_line = self.append_continuation_line(
cr, record_line, line)
continue
if record_line:
self.handle_record(cr, record_line)
if self.is_footer(cr, line):
self.handle_footer(cr, line, iterator)
record_line = ''
continue
record_line = line
except StopIteration:
pass
return self.statements
def append_continuation_line(self, cr, line, continuation_line):
'''append a continuation line for a multiline record.
Override and do data cleanups as necessary.'''
return line + continuation_line
def create_statement(self, cr):
'''create a mem_bank_statement - override if you need a custom
implementation'''
return mem_bank_statement()
def create_transaction(self, cr):
'''create a mem_bank_transaction - override if you need a custom
implementation'''
return mem_bank_transaction()
def is_footer(self, cr, line):
'''determine if a line is the footer of a statement'''
return line and bool(re.match(self.footer_regex, line))
def is_tag(self, cr, line):
'''determine if a line has a tag'''
return line and bool(re.match(self.tag_regex, line))
def handle_header(self, cr, line, iterator):
'''skip header lines, create current statement'''
for i in range(self.header_lines):
iterator.next()
self.current_statement = self.create_statement(cr)
def handle_footer(self, cr, line, iterator):
'''add current statement to list, reset state'''
self.statements.append(self.current_statement)
self.current_statement = None
def handle_record(self, cr, line):
'''find a function to handle the record represented by line'''
tag_match = re.match(self.tag_regex, line)
tag = tag_match.group(0).strip(':')
if not hasattr(self, 'handle_tag_%s' % tag):
logging.error('Unknown tag %s', tag)
logging.error(line)
return
handler = getattr(self, 'handle_tag_%s' % tag)
handler(cr, line[tag_match.end():])
def handle_tag_20(self, cr, data):
'''ignore reference number'''
pass
def handle_tag_25(self, cr, data):
'''get account owner information'''
self.current_statement.local_account = data
def handle_tag_28C(self, cr, data):
'''get sequence number _within_this_batch_ - this alone
doesn't provide a unique id!'''
self.current_statement.id = data
def handle_tag_60F(self, cr, data):
'''get start balance and currency'''
self.current_statement.local_currency = data[7:10]
self.current_statement.date = str2date(data[1:7])
self.current_statement.start_balance = \
(1 if data[0] == 'C' else -1) * str2float(data[10:])
self.current_statement.id = '%s/%s' % (
self.current_statement.date.strftime('%Y'),
self.current_statement.id)
def handle_tag_62F(self, cr, data):
'''get ending balance'''
self.current_statement.end_balance = \
(1 if data[0] == 'C' else -1) * str2float(data[10:])
def handle_tag_64(self, cr, data):
'''get current balance in currency'''
pass
def handle_tag_65(self, cr, data):
'''get future balance in currency'''
pass
def handle_tag_61(self, cr, data):
'''get transaction values'''
transaction = self.create_transaction(cr)
self.current_statement.transactions.append(transaction)
self.current_transaction = transaction
transaction.execution_date = str2date(data[:6])
transaction.effective_date = str2date(data[:6])
'...and the rest already is highly bank dependent'
def handle_tag_86(self, cr, data):
'''details for previous transaction, here most differences between
banks occur'''
pass
'utility functions'
def str2date(string, fmt='%y%m%d'):
return datetime.datetime.strptime(string, fmt)
def str2float(string):
return float(string.replace(',', '.'))
'testing'
def main(filename):
parser = MT940()
parser.parse(None, open(filename, 'r').read())
for statement in parser.statements:
print '''statement found for %(local_account)s at %(date)s
with %(local_currency)s%(start_balance)s to %(end_balance)s
''' % statement.__dict__
for transaction in statement.transactions:
print '''
transaction on %(execution_date)s''' % transaction.__dict__
if __name__ == '__main__':
import sys
main(*sys.argv[1:])

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_abnamro
#: code:addons/account_banking_nl_abnamro/abnamro.py:122

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_abnamro
#: code:addons/account_banking_nl_abnamro/abnamro.py:122

View File

@@ -24,7 +24,10 @@
'author': 'EduSense BV',
'website': 'http://www.edusense.nl',
'category': 'Account Banking',
'depends': ['account_banking_payment'],
'depends': [
'account_banking_payment',
'account_iban_preserve_domestic',
],
'data': [
'account_banking_nl_clieop.xml',
'wizard/export_clieop_view.xml',

View File

@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"

View File

@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"

View File

@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"

View File

@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_girotel
#: code:addons/account_banking_nl_girotel/girotel.py:325

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_girotel
#: code:addons/account_banking_nl_girotel/girotel.py:325

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_girotel
#: code:addons/account_banking_nl_girotel/girotel.py:325

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_ing
#: code:addons/account_banking_nl_ing/ing.py:257

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_ing
#: code:addons/account_banking_nl_ing/ing.py:257

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import account_banking_nl_ing_mt940

View File

@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name" : "MT940 import for Dutch ING",
"version" : "1.0",
"author" : "Therp BV",
"complexity": "normal",
"description": """
This addon imports the structured MT940 format as offered by the Dutch ING
bank.
""",
"category" : "Account Banking",
"depends" : [
'account_banking_mt940',
],
"data" : [
],
"js": [
],
"css": [
],
"qweb": [
],
"auto_install": False,
"installable": True,
"application": False,
"external_dependencies" : {
'python' : [],
},
}

View File

@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import re
from openerp.tools.translate import _
from openerp.addons.account_banking.parsers.models import parser,\
mem_bank_transaction
from openerp.addons.account_banking_mt940.mt940 import MT940, str2float
class transaction(mem_bank_transaction):
def is_valid(self):
'''allow transactions without remote account'''
return bool(self.execution_date) and bool(self.transferred_amount)
class IngMT940Parser(MT940, parser):
name = _('ING MT940 (structured)')
country_code = 'NL'
code = 'INT_MT940_STRUC'
tag_61_regex = re.compile(
'^(?P<date>\d{6})(?P<sign>[CD])(?P<amount>\d+,\d{2})N(?P<type>\d{3})'
'(?P<reference>\w{1,16})')
def create_transaction(self, cr):
return transaction()
def handle_tag_60F(self, cr, data):
super(IngMT940Parser, self).handle_tag_60F(cr, data)
self.current_statement.id = '%s-%s' % (
self.get_unique_account_identifier(
cr, self.current_statement.local_account),
self.current_statement.id)
def handle_tag_61(self, cr, data):
super(IngMT940Parser, self).handle_tag_61(cr, data)
parsed_data = self.tag_61_regex.match(data).groupdict()
self.current_transaction.transferred_amount = \
(-1 if parsed_data['sign'] == 'D' else 1) * str2float(
parsed_data['amount'])
self.current_transaction.reference = parsed_data['reference']
def handle_tag_86(self, cr, data):
if not self.current_transaction:
return
super(IngMT940Parser, self).handle_tag_86(cr, data)
codewords = ['RTRN', 'BENM', 'ORDP', 'CSID', 'BUSP', 'MARF', 'EREF',
'PREF', 'REMI', 'ID', 'PURP', 'ULTB', 'ULTD']
subfields = {}
current_codeword = None
for word in data.split('/'):
if not word and not current_codeword:
continue
if word in codewords:
current_codeword = word
subfields[current_codeword] = []
continue
subfields[current_codeword].append(word)
if 'BENM' in subfields:
self.current_transaction.remote_account = subfields['BENM'][0]
self.current_transaction.remote_bank_bic = subfields['BENM'][1]
self.current_transaction.remote_owner = subfields['BENM'][2]
self.current_transaction.remote_owner_city = subfields['BENM'][3]
if 'ORDP' in subfields:
self.current_transaction.remote_account = subfields['ORDP'][0]
self.current_transaction.remote_bank_bic = subfields['ORDP'][1]
self.current_transaction.remote_owner = subfields['ORDP'][2]
self.current_transaction.remote_owner_city = subfields['ORDP'][3]
if 'REMI' in subfields:
self.current_transaction.message = '/'.join(
filter(lambda x: bool(x), subfields['REMI']))
if self.current_transaction.reference in subfields:
self.current_transaction.reference = ''.join(
subfields[self.current_transaction.reference])
if not subfields:
self.current_transaction.message = data
self.current_transaction = None

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -20,7 +20,7 @@
##############################################################################
{
'name': 'Account Banking',
'name': 'Account Banking - NL Multibank import',
'version': '0.62',
'license': 'AGPL-3',
'author': 'EduSense BV',

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_multibank
#: code:addons/account_banking_nl_multibank/multibank.py:292

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_multibank
#: code:addons/account_banking_nl_multibank/multibank.py:292

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_multibank
#: code:addons/account_banking_nl_multibank/multibank.py:292

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_triodos
#: code:addons/account_banking_nl_triodos/triodos.py:183

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_triodos
#: code:addons/account_banking_nl_triodos/triodos.py:183

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_nl_triodos
#: code:addons/account_banking_nl_triodos/triodos.py:183

View File

@@ -45,8 +45,12 @@ class res_company(orm.Model):
company = self.browse(cr, uid, company_id, context=context)
company_vat = company.vat
party_identifier = False
if company_vat and company_vat[0:2].upper() in ['BE']:
party_identifier = company_vat[2:].replace(' ', '')
if company_vat:
country_code = company_vat[0:2].upper()
if country_code == 'BE':
party_identifier = company_vat[2:].replace(' ', '')
elif country_code == 'ES':
party_identifier = company.sepa_creditor_identifier
return party_identifier
def _initiating_party_issuer_default(self, cr, uid, context=None):

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_pain_base
#: field:res.company,initiating_party_issuer:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-12 06:27+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_pain_base
#: field:res.company,initiating_party_issuer:0

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_partner_journal_account
#: model:ir.model,name:account_banking_partner_journal_account.model_res_partner

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_payment
#: model:ir.model,name:account_banking_payment.model_payment_order_create

View File

@@ -116,14 +116,26 @@ class banking_import_transaction(orm.Model):
'''
# TODO: Not sure what side effects are created when payments are done
# for credited customer invoices, which will be matched later on too.
def bank_match(account, partner_bank):
"""
Returns whether a given account number is equivalent to a
partner bank in the database. We simply call the search method,
which checks IBAN, domestic and disregards from spaces in IBANs.
:param account: string representation of a bank account number
:param partner_bank: browse record of model res.partner.bank
"""
return partner_bank.id in self.pool['res.partner.bank'].search(
cr, uid, [('acc_number', '=', account)])
digits = dp.get_precision('Account')(cr)[1]
candidates = [
x for x in payment_lines
if x.communication == trans.reference
and round(x.amount, digits) == -round(
trans.statement_line_id.amount, digits)
and trans.remote_account in (x.bank_id.acc_number,
x.bank_id.acc_number_domestic)
line for line in payment_lines
if (line.communication == trans.reference
and round(line.amount, digits) == -round(
trans.statement_line_id.amount, digits)
and bank_match(trans.remote_account, line.bank_id))
]
if len(candidates) == 1:
candidate = candidates[0]

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_payment_export
#: help:payment.mode.type,name:0

View File

@@ -187,6 +187,7 @@ class payment_order_create(orm.TransientModel):
or line.journal_id.currency.id
or line.journal_id.company_id.currency_id.id),
}, context=context)
# Force reload of payment order view as a workaround for lp:1155525
return {'name': _('Payment Orders'),
'context': context,
'view_type': 'form',

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_sepa_credit_transfer
#: selection:banking.export.sepa.wizard,state:0

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_sepa_credit_transfer
#: selection:banking.export.sepa.wizard,state:0

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_sepa_direct_debit
#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_valid

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-12 06:27+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_banking_sepa_direct_debit
#: model:mail.message.subtype,description:account_banking_sepa_direct_debit.mandate_valid

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_direct_debit
#: model:account.payment.term,note:account_direct_debit.payment_term_direct_debit

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_iban_preserve_domestic
#: field:res.partner.bank,acc_number_domestic:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: account_iban_preserve_domestic
#: field:res.partner.bank,acc_number_domestic:0

View File

@@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
import payment_order
from . import payment_order

View File

@@ -20,7 +20,7 @@
##############################################################################
{
'name': 'Account Payment Invoice Selection Shortcut',
'version': '6.1.1.134',
'version': '1.134',
'license': 'AGPL-3',
'author': 'Smile / Therp BV',
'website': 'https://launchpad.net/banking-addons',

View File

@@ -22,7 +22,7 @@
#
##############################################################################
from osv import orm
from openerp.osv import orm
class payment_order_create(orm.TransientModel):
_inherit = 'payment.order.create'

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: base_iban_bic_not_required
#: constraint:res.partner.bank:0

View File

@@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-11 06:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-21 06:57+0000\n"
"X-Generator: Launchpad (build 16967)\n"
#. module: base_iban_bic_not_required
#: constraint:res.partner.bank:0