mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
PEP8 on account_banking
This commit is contained in:
@@ -11,8 +11,8 @@
|
||||
# garantees and support are strongly adviced to contract EduSense BV
|
||||
#
|
||||
# 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
|
||||
# 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,
|
||||
@@ -24,6 +24,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import sepa
|
||||
import record
|
||||
import banking_import_transaction
|
||||
@@ -33,5 +34,3 @@ import wizard
|
||||
import res_partner
|
||||
import res_bank
|
||||
import res_partner_bank
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -70,7 +70,8 @@
|
||||
+ IBAN accounts are the standard in the SEPA countries
|
||||
+ local accounts are derived from SEPA (excluding Turkey) but are
|
||||
considered to be identical to the corresponding SEPA account.
|
||||
+ Banks are identified with either Country + Bank code + Branch code or BIC
|
||||
+ Banks are identified with either Country + Bank code + Branch code or
|
||||
BIC
|
||||
+ Each bank can have its own pace in introducing SEPA into their
|
||||
communication with their customers.
|
||||
+ National online databases can be used to convert BBAN's to IBAN's.
|
||||
|
||||
@@ -86,11 +86,11 @@ class account_banking_account_settings(orm.Model):
|
||||
string='Partner'),
|
||||
'default_credit_account_id': fields.many2one(
|
||||
'account.account', 'Default credit account', select=True,
|
||||
help=('The account to use when an unexpected payment was signaled. '
|
||||
'This can happen when a direct debit payment is cancelled '
|
||||
help=('The account to use when an unexpected payment was signaled.'
|
||||
' This can happen when a direct debit payment is cancelled '
|
||||
'by a customer, or when no matching payment can be found. '
|
||||
' Mind that you can correct movements before confirming them.'
|
||||
),
|
||||
'Mind that you can correct movements before confirming them.'
|
||||
),
|
||||
required=True
|
||||
),
|
||||
'default_debit_account_id': fields.many2one(
|
||||
@@ -98,27 +98,27 @@ class account_banking_account_settings(orm.Model):
|
||||
select=True, required=True,
|
||||
help=('The account to use when an unexpected payment is received. '
|
||||
'This can be needed when a customer pays in advance or when '
|
||||
'no matching invoice can be found. Mind that you can correct '
|
||||
'movements before confirming them.'
|
||||
),
|
||||
'no matching invoice can be found. Mind that you can '
|
||||
'correct movements before confirming them.'
|
||||
),
|
||||
),
|
||||
'costs_account_id': fields.many2one(
|
||||
'account.account', 'Bank Costs Account', select=True,
|
||||
help=('The account to use when the bank invoices its own costs. '
|
||||
'Leave it blank to disable automatic invoice generation '
|
||||
'on bank costs.'
|
||||
),
|
||||
),
|
||||
),
|
||||
'invoice_journal_id': fields.many2one(
|
||||
'account.journal', 'Costs Journal',
|
||||
help=('This is the journal used to create invoices for bank costs.'
|
||||
),
|
||||
),
|
||||
),
|
||||
'bank_partner_id': fields.many2one(
|
||||
'res.partner', 'Bank Partner',
|
||||
help=('The partner to use for bank costs. Banks are not partners '
|
||||
'by default. You will most likely have to create one.'
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
}
|
||||
@@ -196,7 +196,7 @@ class account_banking_account_settings(orm.Model):
|
||||
values['journal_id'] = bank['journal_id'][0]
|
||||
return {'value': values}
|
||||
|
||||
def onchange_company_id (
|
||||
def onchange_company_id(
|
||||
self, cr, uid, ids, company_id=False, context=None):
|
||||
if not company_id:
|
||||
return {}
|
||||
@@ -229,37 +229,59 @@ class account_banking_imported_file(orm.Model):
|
||||
_description = __doc__
|
||||
_rec_name = 'date'
|
||||
_columns = {
|
||||
'company_id': fields.many2one('res.company', 'Company',
|
||||
select=True, readonly=True
|
||||
),
|
||||
'date': fields.datetime('Import Date', readonly=True, select=True,
|
||||
states={'draft': [('readonly', False)]}
|
||||
),
|
||||
'format': fields.char('File Format', size=20, readonly=True,
|
||||
states={'draft': [('readonly', False)]}
|
||||
),
|
||||
'file': fields.binary('Raw Data', readonly=True,
|
||||
states={'draft': [('readonly', False)]}
|
||||
),
|
||||
'file_name': fields.char('File name', size=256),
|
||||
'log': fields.text('Import Log', readonly=True,
|
||||
states={'draft': [('readonly', False)]}
|
||||
),
|
||||
'user_id': fields.many2one('res.users', 'Responsible User',
|
||||
readonly=True, select=True,
|
||||
states={'draft': [('readonly', False)]}
|
||||
),
|
||||
'state': fields.selection(
|
||||
[('unfinished', 'Unfinished'),
|
||||
('error', 'Error'),
|
||||
('review', 'Review'),
|
||||
('ready', 'Finished'),
|
||||
], 'State', select=True, readonly=True
|
||||
'company_id': fields.many2one(
|
||||
'res.company',
|
||||
'Company',
|
||||
select=True,
|
||||
readonly=True,
|
||||
),
|
||||
'date': fields.datetime(
|
||||
'Import Date',
|
||||
readonly=True,
|
||||
select=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'format': fields.char(
|
||||
'File Format',
|
||||
size=20,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'file': fields.binary(
|
||||
'Raw Data',
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'file_name': fields.char('File name', size=256),
|
||||
'log': fields.text(
|
||||
'Import Log',
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'user_id': fields.many2one(
|
||||
'res.users',
|
||||
'Responsible User',
|
||||
readonly=True,
|
||||
select=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'state': fields.selection(
|
||||
[
|
||||
('unfinished', 'Unfinished'),
|
||||
('error', 'Error'),
|
||||
('review', 'Review'),
|
||||
('ready', 'Finished'),
|
||||
],
|
||||
'State',
|
||||
select=True,
|
||||
readonly=True,
|
||||
),
|
||||
'statement_ids': fields.one2many(
|
||||
'account.bank.statement',
|
||||
'banking_id',
|
||||
'Statements',
|
||||
readonly=False,
|
||||
),
|
||||
'statement_ids': fields.one2many('account.bank.statement',
|
||||
'banking_id', 'Statements',
|
||||
readonly=False,
|
||||
),
|
||||
}
|
||||
_defaults = {
|
||||
'date': fields.date.context_today,
|
||||
@@ -284,11 +306,17 @@ class account_bank_statement(orm.Model):
|
||||
_inherit = 'account.bank.statement'
|
||||
|
||||
_columns = {
|
||||
'period_id': fields.many2one('account.period', 'Period',
|
||||
required=False, readonly=True),
|
||||
'banking_id': fields.many2one('account.banking.imported.file',
|
||||
'Imported File', readonly=True,
|
||||
),
|
||||
'period_id': fields.many2one(
|
||||
'account.period',
|
||||
'Period',
|
||||
required=False,
|
||||
readonly=True,
|
||||
),
|
||||
'banking_id': fields.many2one(
|
||||
'account.banking.imported.file',
|
||||
'Imported File',
|
||||
readonly=True,
|
||||
),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
@@ -321,7 +349,7 @@ class account_bank_statement(orm.Model):
|
||||
_constraints = [
|
||||
(_check_company_id,
|
||||
'The journal and period chosen have to belong to the same company.',
|
||||
['journal_id','period_id']),
|
||||
['journal_id', 'period_id']),
|
||||
]
|
||||
|
||||
def _get_period(self, cr, uid, date=False, context=None):
|
||||
@@ -419,11 +447,12 @@ class account_bank_statement(orm.Model):
|
||||
('account_id', '=', st_line.account_id.id)],
|
||||
context=context)
|
||||
account_move_line_obj.write(cr, uid, torec, {
|
||||
(st_line.reconcile_id.line_partial_ids and
|
||||
'reconcile_partial_id' or 'reconcile_id'):
|
||||
st_line.reconcile_id.id }, context=context)
|
||||
(st_line.reconcile_id.line_partial_ids
|
||||
and 'reconcile_partial_id'
|
||||
or 'reconcile_id'): st_line.reconcile_id.id
|
||||
}, context=context)
|
||||
for move_line in (st_line.reconcile_id.line_id or []) + (
|
||||
st_line.reconcile_id.line_partial_ids or []):
|
||||
st_line.reconcile_id.line_partial_ids or []):
|
||||
netsvc.LocalService("workflow").trg_trigger(
|
||||
uid, 'account.move.line', move_line.id, cr)
|
||||
return res
|
||||
@@ -438,7 +467,7 @@ class account_bank_statement(orm.Model):
|
||||
if ids and isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
noname_ids = self.search(
|
||||
cr, uid, [('id', 'in', ids),('name', '=', '/')],
|
||||
cr, uid, [('id', 'in', ids), ('name', '=', '/')],
|
||||
context=context)
|
||||
for st in self.browse(cr, uid, noname_ids, context=context):
|
||||
if st.journal_id.sequence_id:
|
||||
@@ -464,7 +493,7 @@ class account_voucher(orm.Model):
|
||||
context = {}
|
||||
if not context.get('period_id') and context.get('move_line_ids'):
|
||||
move_line = self.pool.get('account.move.line').browse(
|
||||
cr, uid , context.get('move_line_ids')[0], context=context)
|
||||
cr, uid, context.get('move_line_ids')[0], context=context)
|
||||
return move_line.period_id.id
|
||||
return super(account_voucher, self)._get_period(cr, uid, context)
|
||||
|
||||
@@ -498,8 +527,8 @@ class account_bank_statement_line(orm.Model):
|
||||
which is inaccessible from within this method.
|
||||
'''
|
||||
res_users_obj = self.pool.get('res.users')
|
||||
return res_users_obj.browse(cr, uid, uid,
|
||||
context=context).company_id.currency_id.id
|
||||
return res_users_obj.browse(
|
||||
cr, uid, uid, context=context).company_id.currency_id.id
|
||||
|
||||
def _get_invoice_id(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
@@ -519,36 +548,70 @@ class account_bank_statement_line(orm.Model):
|
||||
|
||||
_columns = {
|
||||
# Redefines. Todo: refactor away to view attrs
|
||||
'amount': fields.float('Amount', readonly=True,
|
||||
digits_compute=dp.get_precision('Account'),
|
||||
states={'draft': [('readonly', False)]}),
|
||||
'ref': fields.char('Ref.', size=32, readonly=True,
|
||||
states={'draft': [('readonly', False)]}),
|
||||
'name': fields.char('Name', size=64, required=False, readonly=True,
|
||||
states={'draft': [('readonly', False)]}),
|
||||
'date': fields.date('Date', required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)]}),
|
||||
|
||||
'amount': fields.float(
|
||||
'Amount',
|
||||
readonly=True,
|
||||
digits_compute=dp.get_precision('Account'),
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'ref': fields.char(
|
||||
'Ref.',
|
||||
size=32,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'name': fields.char(
|
||||
'Name',
|
||||
size=64,
|
||||
required=False,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'date': fields.date(
|
||||
'Date',
|
||||
required=True,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
# New columns
|
||||
'trans': fields.char('Bank Transaction ID', size=15, required=False,
|
||||
readonly=True,
|
||||
states={'draft':[('readonly', False)]},
|
||||
),
|
||||
'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account',
|
||||
required=False, readonly=True,
|
||||
states={'draft':[('readonly', False)]},
|
||||
),
|
||||
'period_id': fields.many2one('account.period', 'Period', required=True,
|
||||
states={'confirmed': [('readonly', True)]}),
|
||||
'currency': fields.many2one('res.currency', 'Currency', required=True,
|
||||
states={'confirmed': [('readonly', True)]}),
|
||||
'trans': fields.char(
|
||||
'Bank Transaction ID',
|
||||
size=15,
|
||||
required=False,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'partner_bank_id': fields.many2one(
|
||||
'res.partner.bank',
|
||||
'Bank Account',
|
||||
required=False,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
),
|
||||
'period_id': fields.many2one(
|
||||
'account.period',
|
||||
'Period',
|
||||
required=True,
|
||||
states={'confirmed': [('readonly', True)]},
|
||||
),
|
||||
'currency': fields.many2one(
|
||||
'res.currency',
|
||||
'Currency',
|
||||
required=True,
|
||||
states={'confirmed': [('readonly', True)]},
|
||||
),
|
||||
'reconcile_id': fields.many2one(
|
||||
'account.move.reconcile', 'Reconciliation', readonly=True
|
||||
),
|
||||
'account.move.reconcile',
|
||||
'Reconciliation',
|
||||
readonly=True,
|
||||
),
|
||||
'invoice_id': fields.function(
|
||||
_get_invoice_id, method=True, string='Linked Invoice',
|
||||
type='many2one', relation='account.invoice'
|
||||
),
|
||||
_get_invoice_id,
|
||||
method=True,
|
||||
string='Linked Invoice',
|
||||
type='many2one',
|
||||
relation='account.invoice',
|
||||
),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
@@ -592,16 +655,14 @@ class invoice(orm.Model):
|
||||
'''
|
||||
return [('none', _('Free Reference')),
|
||||
('structured', _('Structured Reference')),
|
||||
]
|
||||
]
|
||||
|
||||
_columns = {
|
||||
'reference_type': fields.selection(_get_reference_type,
|
||||
'Reference Type', required=True
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
invoice()
|
||||
|
||||
|
||||
class account_move_line(orm.Model):
|
||||
_inherit = "account.move.line"
|
||||
@@ -617,9 +678,6 @@ class account_move_line(orm.Model):
|
||||
if not ids:
|
||||
return total
|
||||
for line in self.read(
|
||||
cr, uid, ids, ['debit', 'credit'], context=context):
|
||||
cr, uid, ids, ['debit', 'credit'], context=context):
|
||||
total += (line['debit'] or 0.0) - (line['credit'] or 0.0)
|
||||
return total
|
||||
account_move_line()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,8 @@
|
||||
# Copyright (C) 2011 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
|
||||
# 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,
|
||||
@@ -24,10 +24,11 @@ __name__ = ("account.bank.statement.line:: set new field 'state' to "
|
||||
"confirmed for all statement lines belonging to confirmed "
|
||||
"statements")
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
cr.execute ("UPDATE account_bank_statement_line as sl "
|
||||
" SET state = 'confirmed'"
|
||||
" FROM account_bank_statement as s "
|
||||
" WHERE sl.statement_id = s.id "
|
||||
" AND s.state = 'confirm' "
|
||||
)
|
||||
cr.execute("UPDATE account_bank_statement_line as sl "
|
||||
" SET state = 'confirmed'"
|
||||
" FROM account_bank_statement as s "
|
||||
" WHERE sl.statement_id = s.id "
|
||||
" AND s.state = 'confirm' "
|
||||
)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
if not version:
|
||||
return
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
if not version:
|
||||
return
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
def table_exists(cr, table):
|
||||
""" Check whether a certain table or view exists """
|
||||
cr.execute(
|
||||
@@ -26,6 +27,7 @@ def table_exists(cr, table):
|
||||
(table,))
|
||||
return cr.fetchone()[0] == 1
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
"""
|
||||
Migration script for semantic changes in account_banking_payment_export.
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -19,6 +19,6 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import models
|
||||
from . import models
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -29,14 +29,17 @@ try:
|
||||
except AttributeError:
|
||||
from mx import DateTime as datetime
|
||||
|
||||
|
||||
def str2date(datestr, format='%d/%m/%y'):
|
||||
'''Convert a string to a datatime object'''
|
||||
return datetime.strptime(datestr, format)
|
||||
|
||||
|
||||
def date2str(date, format='%Y-%m-%d'):
|
||||
'''Convert a datetime object to a string'''
|
||||
return date.strftime(format)
|
||||
|
||||
|
||||
def date2date(datestr, fromfmt='%d/%m/%y', tofmt='%Y-%m-%d'):
|
||||
'''
|
||||
Convert a date in a string to another string, in a different
|
||||
@@ -44,7 +47,9 @@ def date2date(datestr, fromfmt='%d/%m/%y', tofmt='%Y-%m-%d'):
|
||||
'''
|
||||
return date2str(str2date(datestr, fromfmt), tofmt)
|
||||
|
||||
_SWIFT = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-?:().,'+ "
|
||||
_SWIFT = ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
"/-?:().,'+ ")
|
||||
|
||||
|
||||
def to_swift(astr, schemes=['utf-8', 'latin-1', 'ascii']):
|
||||
'''
|
||||
@@ -62,7 +67,7 @@ def to_swift(astr, schemes=['utf-8', 'latin-1', 'ascii']):
|
||||
|
||||
s = [x in _SWIFT and x or ' '
|
||||
for x in unicodedata.normalize('NFKD', astr).encode('ascii', 'ignore')
|
||||
]
|
||||
]
|
||||
return ''.join(s)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
import re
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class mem_bank_statement(object):
|
||||
'''
|
||||
A mem_bank_statement is a real life projection of a bank statement paper
|
||||
@@ -34,9 +35,15 @@ class mem_bank_statement(object):
|
||||
'''
|
||||
# Lock attributes to enable parsers to trigger non-conformity faults
|
||||
__slots__ = [
|
||||
'start_balance','end_balance', 'date', 'local_account',
|
||||
'local_currency', 'id', 'transactions'
|
||||
'start_balance',
|
||||
'end_balance',
|
||||
'date',
|
||||
'local_account',
|
||||
'local_currency',
|
||||
'id',
|
||||
'transactions'
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(mem_bank_statement, self).__init__(*args, **kwargs)
|
||||
self.id = ''
|
||||
@@ -59,6 +66,7 @@ class mem_bank_statement(object):
|
||||
check += float(transaction.transferred_amount)
|
||||
return abs(check - float(self.end_balance)) < 0.0001
|
||||
|
||||
|
||||
class mem_bank_transaction(object):
|
||||
'''
|
||||
A mem_bank_transaction is a real life copy of a bank transfer. Mapping to
|
||||
@@ -126,7 +134,8 @@ class mem_bank_transaction(object):
|
||||
# The other parties postal code belonging to the address
|
||||
|
||||
'remote_owner_country_code',
|
||||
# The other parties two letter ISO country code belonging to the previous
|
||||
# The other parties two letter ISO country code belonging to the
|
||||
# previous
|
||||
|
||||
'remote_owner_custno',
|
||||
# The other parties customer number
|
||||
@@ -270,7 +279,7 @@ class mem_bank_transaction(object):
|
||||
if value in self.types:
|
||||
self.transfer_type = value
|
||||
else:
|
||||
raise ValueError, _('Invalid value for transfer_type')
|
||||
raise ValueError(_('Invalid value for transfer_type'))
|
||||
|
||||
type = property(_get_type, _set_type)
|
||||
|
||||
@@ -282,6 +291,7 @@ class mem_bank_transaction(object):
|
||||
return (self.execution_date and self.remote_account
|
||||
and self.transferred_amount and True) or False
|
||||
|
||||
|
||||
class parser_type(type):
|
||||
'''
|
||||
Meta annex factory class for house keeping and collecting parsers.
|
||||
@@ -314,11 +324,13 @@ class parser_type(type):
|
||||
keys.sort()
|
||||
return [(parsers[x].code, parsers[x].name) for x in keys]
|
||||
|
||||
|
||||
def create_parser(code):
|
||||
if code in parser_type.parser_by_code:
|
||||
return parser_type.parser_by_code[code]()
|
||||
return None
|
||||
|
||||
|
||||
class parser(object):
|
||||
'''
|
||||
A parser delivers the interface for any parser object. Inherit from
|
||||
@@ -408,5 +420,3 @@ class parser(object):
|
||||
raise NotImplementedError(
|
||||
_('This is a stub. Please implement your own.')
|
||||
)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -31,16 +31,19 @@ from datetime import datetime, date
|
||||
# Correct python2.4 issues
|
||||
try:
|
||||
datetime.strptime
|
||||
|
||||
def strpdate(str, format):
|
||||
return datetime.strptime(str, format).date()
|
||||
except AttributeError:
|
||||
import time
|
||||
|
||||
def strpdate(str, format):
|
||||
tm = time.strptime(str, format)
|
||||
return date(tm.tm_year, tm.tm_mon, tm.tm_mday)
|
||||
|
||||
import unicodedata
|
||||
|
||||
|
||||
class Field(object):
|
||||
'''Base Field class - fixed length left aligned string field in a record'''
|
||||
def __init__(self, name, length=1, fillchar=' ', cast=str):
|
||||
@@ -57,11 +60,14 @@ class Field(object):
|
||||
|
||||
def take(self, buffer):
|
||||
offset = hasattr(self, 'offset') and self.offset or 0
|
||||
return self.cast(buffer[offset:offset + self.length].rstrip(self.fillchar))
|
||||
return self.cast(buffer[offset:offset + self.length].rstrip(
|
||||
self.fillchar)
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s "%s"' % (self.__class__.__name__, self.name)
|
||||
|
||||
|
||||
class Filler(Field):
|
||||
'''Constant value field'''
|
||||
def __init__(self, name, length=1, value=' '):
|
||||
@@ -73,9 +79,10 @@ class Filler(Field):
|
||||
|
||||
def format(self, value):
|
||||
return super(Filler, self).format(
|
||||
self.value * (self.length / len(self.value) +1)
|
||||
self.value * (self.length / len(self.value) + 1)
|
||||
)
|
||||
|
||||
|
||||
class DateField(Field):
|
||||
'''Variable date field'''
|
||||
def __init__(self, name, format='%Y-%m-%d', auto=False, cast=str):
|
||||
@@ -98,6 +105,7 @@ class DateField(Field):
|
||||
return strpdate(value, self.dateformat)
|
||||
return self.auto and date.today() or None
|
||||
|
||||
|
||||
class RightAlignedField(Field):
|
||||
'''Deviation of Field: right aligned'''
|
||||
def format(self, value):
|
||||
@@ -107,7 +115,10 @@ class RightAlignedField(Field):
|
||||
|
||||
def take(self, buffer):
|
||||
offset = hasattr(self, 'offset') and self.offset or 0
|
||||
return self.cast(buffer[offset:offset + self.length].lstrip(self.fillchar))
|
||||
return self.cast(buffer[offset:offset + self.length].lstrip(
|
||||
self.fillchar)
|
||||
)
|
||||
|
||||
|
||||
class NumberField(RightAlignedField):
|
||||
'''Deviation of Field: left zero filled'''
|
||||
@@ -118,6 +129,7 @@ class NumberField(RightAlignedField):
|
||||
def format(self, value):
|
||||
return super(NumberField, self).format(self.cast(value or ''))
|
||||
|
||||
|
||||
class RecordType(object):
|
||||
fields = []
|
||||
|
||||
@@ -130,7 +142,7 @@ class RecordType(object):
|
||||
offset += field.length
|
||||
|
||||
def __len__(self):
|
||||
return reduce(lambda x,y: x+y.length, self.fields, 0)
|
||||
return reduce(lambda x, y: x + y.length, self.fields, 0)
|
||||
|
||||
def __contains__(self, key):
|
||||
return any(lambda x, y=key: x.name == y, self.fields)
|
||||
@@ -139,7 +151,7 @@ class RecordType(object):
|
||||
for field in self.fields:
|
||||
if field.name == key:
|
||||
return field
|
||||
raise KeyError, 'No such field: %s' % key
|
||||
raise KeyError('No such field: %s' % key)
|
||||
|
||||
def format(self, buffer):
|
||||
result = []
|
||||
@@ -150,7 +162,8 @@ class RecordType(object):
|
||||
def take(self, buffer):
|
||||
return dict(zip([x.name for x in self.fields],
|
||||
[x.take(buffer) for x in self.fields]
|
||||
))
|
||||
))
|
||||
|
||||
|
||||
class Record(object):
|
||||
_recordtype = None
|
||||
@@ -159,7 +172,7 @@ class Record(object):
|
||||
if hasattr(self, '_fields') and self._fields:
|
||||
self._recordtype = RecordType(self._fields)
|
||||
if not self._recordtype and not recordtype:
|
||||
raise ValueError, 'No recordtype specified'
|
||||
raise ValueError('No recordtype specified')
|
||||
if not self._recordtype:
|
||||
self._recordtype = recordtype()
|
||||
self._length = len(self._recordtype)
|
||||
@@ -173,9 +186,11 @@ class Record(object):
|
||||
super(Record, self).__setattr__(attr, value)
|
||||
else:
|
||||
field = self._recordtype[attr]
|
||||
self._value = self._value[:field.offset] + \
|
||||
field.format(value) + \
|
||||
self._value[field.offset + field.length:]
|
||||
self._value = (
|
||||
self._value[:field.offset] +
|
||||
field.format(value) +
|
||||
self._value[field.offset + field.length:]
|
||||
)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr.startswith('_'):
|
||||
@@ -189,7 +204,6 @@ class Record(object):
|
||||
def __unicode__(self):
|
||||
return unicode(self.cast(self))
|
||||
|
||||
|
||||
def asciify(str):
|
||||
return unicodedata.normalize('NFKD', str).encode('ascii', 'ignore')
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
__all__ = ['IBAN', 'BBAN']
|
||||
|
||||
|
||||
def modulo_97_base10(abuffer):
|
||||
'''
|
||||
Calculate the modulo 97 value of a string in base10
|
||||
@@ -55,6 +56,7 @@ def modulo_97_base10(abuffer):
|
||||
checksum %= 97
|
||||
return checksum
|
||||
|
||||
|
||||
def base36_to_base10str(abuffer):
|
||||
'''
|
||||
Convert a base36 string value to a string of base10 digits.
|
||||
@@ -67,6 +69,7 @@ def base36_to_base10str(abuffer):
|
||||
result += digit
|
||||
return result
|
||||
|
||||
|
||||
class BBANFormat(object):
|
||||
'''
|
||||
A BBANFormat is an auxilliary class for IBAN. It represents the composition
|
||||
@@ -178,6 +181,7 @@ class BBANFormat(object):
|
||||
i += 1
|
||||
return res
|
||||
|
||||
|
||||
class IBAN(str):
|
||||
'''
|
||||
A IBAN string represents a SEPA bank account number. This class provides
|
||||
@@ -272,7 +276,7 @@ class IBAN(str):
|
||||
if item.isalnum():
|
||||
init += item
|
||||
elif item not in ' \t.-':
|
||||
raise ValueError, 'Invalid chars found in IBAN number'
|
||||
raise ValueError('Invalid chars found in IBAN number')
|
||||
return str.__new__(cls, init)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -287,8 +291,7 @@ class IBAN(str):
|
||||
|
||||
@classmethod
|
||||
def create(cls, BIC=None, countrycode=None, BBAN=None, bankcode=None,
|
||||
branchcode=None, account=None
|
||||
):
|
||||
branchcode=None, account=None):
|
||||
'''
|
||||
Create a IBAN number from a BBAN and a country code. Optionaly create
|
||||
a BBAN from BBAN components before generation.
|
||||
@@ -304,20 +307,17 @@ class IBAN(str):
|
||||
if countrycode:
|
||||
countrycode = countrycode.upper()
|
||||
else:
|
||||
raise ValueError, \
|
||||
'Either BIC or countrycode is required'
|
||||
raise ValueError('Either BIC or countrycode is required')
|
||||
|
||||
if countrycode not in cls.countries:
|
||||
raise ValueError, \
|
||||
'%s is not a SEPA country' % countrycode
|
||||
raise ValueError('%s is not a SEPA country' % countrycode)
|
||||
format = cls.BBAN_formats[countrycode]
|
||||
|
||||
if BBAN:
|
||||
if len(BBAN) == len(format._iban):
|
||||
ibanno = cls(countrycode + '00' + BBAN)
|
||||
return cls(countrycode + ibanno.checksum + BBAN)
|
||||
raise ValueError, \
|
||||
'Insufficient data to generate IBAN'
|
||||
raise ValueError('Insufficient data to generate IBAN')
|
||||
|
||||
@property
|
||||
def valid(self):
|
||||
@@ -325,8 +325,10 @@ class IBAN(str):
|
||||
Check if the string + check digits deliver a valid checksum
|
||||
'''
|
||||
_buffer = self[4:] + self[:4]
|
||||
return self.countrycode in self.countries and \
|
||||
int(base36_to_base10str(_buffer)) % 97 == 1
|
||||
return (
|
||||
self.countrycode in self.countries
|
||||
and int(base36_to_base10str(_buffer)) % 97 == 1
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
'''
|
||||
@@ -421,6 +423,7 @@ class IBAN(str):
|
||||
'''
|
||||
return self[4:]
|
||||
|
||||
|
||||
class BBAN(object):
|
||||
'''
|
||||
Class to reformat a local BBAN account number to IBAN specs.
|
||||
@@ -433,10 +436,11 @@ class BBAN(object):
|
||||
Internal method to calculate the length of a parameter in a
|
||||
formatted string
|
||||
'''
|
||||
i = 0; max_i = len(fmt._iban)
|
||||
i = 0
|
||||
max_i = len(fmt._iban)
|
||||
while i < max_i:
|
||||
if fmt._iban[i] == element:
|
||||
next = i +1
|
||||
next = i + 1
|
||||
while next < max_i and fmt._iban[next] == element:
|
||||
next += 1
|
||||
return next - i
|
||||
@@ -453,7 +457,10 @@ class BBAN(object):
|
||||
if countrycode.upper() in IBAN.countries:
|
||||
self._fmt = IBAN.BBAN_formats[countrycode.upper()]
|
||||
res = ''
|
||||
i = 0; j = 0; max_i = len(self._fmt._bban); max_j = len(bban)
|
||||
i = 0
|
||||
j = 0
|
||||
max_i = len(self._fmt._bban)
|
||||
max_j = len(bban)
|
||||
while i < max_i and j < max_j:
|
||||
while bban[j] in ' \t' and j < max_j:
|
||||
j += 1
|
||||
@@ -512,15 +519,16 @@ class BBAN(object):
|
||||
'''Simple check if BBAN is in the right format'''
|
||||
return self._bban and True or False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
for arg in sys.argv[1:]:
|
||||
iban = IBAN(arg)
|
||||
print 'IBAN:', iban
|
||||
print 'country code:', iban.countrycode
|
||||
print 'bank code:', iban.bankcode
|
||||
print 'branch code:', iban.branchcode
|
||||
print 'BBAN:', iban.BBAN
|
||||
print 'localized BBAN:', iban.localized_BBAN
|
||||
print 'check digits:', iban.checkdigits
|
||||
print 'checksum:', iban.checksum
|
||||
print('IBAN:', iban)
|
||||
print('country code:', iban.countrycode)
|
||||
print('bank code:', iban.bankcode)
|
||||
print('branch code:', iban.branchcode)
|
||||
print('BBAN:', iban.BBAN)
|
||||
print('localized BBAN:', iban.localized_BBAN)
|
||||
print('check digits:', iban.checkdigits)
|
||||
print('checksum:', iban.checksum)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -27,6 +27,7 @@ import re
|
||||
|
||||
__all__ = ['split', 'get', 'PostalCode']
|
||||
|
||||
|
||||
class PostalCode(object):
|
||||
'''
|
||||
The PostalCode class is a wrapper around PostCodeFormat and an internal
|
||||
@@ -46,10 +47,10 @@ class PostalCode(object):
|
||||
'''
|
||||
# Sort formats on length, longest first
|
||||
formats = [(len(x), x) for x in format.split('|')]
|
||||
formats = [x[1] for x in sorted(formats, lambda x,y: -cmp(x,y))]
|
||||
self.res = [re.compile(x.replace('#', '\\d').replace('@','[A-Z]'))
|
||||
formats = [x[1] for x in sorted(formats, lambda x, y: -cmp(x, y))]
|
||||
self.res = [re.compile(x.replace('#', '\\d').replace('@', '[A-Z]'))
|
||||
for x in formats
|
||||
]
|
||||
]
|
||||
|
||||
def get(self, str_):
|
||||
'''
|
||||
@@ -99,7 +100,8 @@ class PostalCode(object):
|
||||
'IM': '@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA',
|
||||
'IL': '#####', 'IT': '####', 'JM': '', 'JP': '###-####',
|
||||
'JE': '@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA',
|
||||
'JO': '#####', 'KZ': '######', 'KE': '#####', 'KI': '', 'KP': '###-###',
|
||||
'JO': '#####', 'KZ': '######', 'KE': '#####', 'KI': '',
|
||||
'KP': '###-###',
|
||||
'KR': 'SEOUL ###-###', 'KW': '#####', 'KG': '######', 'LA': '#####',
|
||||
'LV': 'LV-####', 'LB': '#### ####|####', 'LS': '###', 'LR': '####',
|
||||
'LY': '', 'LI': '####', 'LT': 'LT-#####', 'LU': '####', 'MO': '',
|
||||
@@ -155,14 +157,12 @@ class PostalCode(object):
|
||||
|
||||
# Find optimum (= max length postalcode) when iso code is unknown
|
||||
all = {}
|
||||
opt_iso = ''
|
||||
max_l = 0
|
||||
for key in cls._formats.iterkeys():
|
||||
i, p, c = cls.split(str_, key)
|
||||
l = len(p)
|
||||
if l > max_l:
|
||||
max_l = l
|
||||
opt_iso = i
|
||||
if l in all:
|
||||
all[l].append((i, p, c))
|
||||
else:
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -18,6 +18,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
'''
|
||||
Define a struct class which behaves like a dict, but allows using
|
||||
object.attr alongside object['attr'].
|
||||
@@ -25,6 +26,7 @@ object.attr alongside object['attr'].
|
||||
|
||||
__all__ = ['struct']
|
||||
|
||||
|
||||
class struct(dict):
|
||||
'''
|
||||
Ease working with dicts. Allow dict.key alongside dict['key']
|
||||
@@ -52,4 +54,4 @@ class struct(dict):
|
||||
else:
|
||||
fmt = '%*.*s%%s: %%s' % (indent, indent, '')
|
||||
for item in self.iteritems():
|
||||
print fmt % item
|
||||
print(fmt % item)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -18,8 +18,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
import bank_import
|
||||
import banking_transaction_wizard
|
||||
import link_partner
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
from . import bank_import
|
||||
from . import banking_transaction_wizard
|
||||
from . import link_partner
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -23,11 +23,13 @@
|
||||
# Kaspars Vilkens (KNdati): lenghty discussions, bugreports and bugfixes
|
||||
# Stefan Rijnhart (Therp): bugreport and bugfix
|
||||
#
|
||||
|
||||
'''
|
||||
This module contains the business logic of the wizard account_banking_import.
|
||||
The parsing is done in the parser modules. Every parser module is required to
|
||||
use parser.models as a mean of communication with the business logic.
|
||||
'''
|
||||
|
||||
import base64
|
||||
import datetime
|
||||
from openerp.osv import orm, fields
|
||||
@@ -44,6 +46,7 @@ bt = models.mem_bank_transaction
|
||||
# the real payment date. This can occur with online transactions (web shops).
|
||||
payment_window = datetime.timedelta(days=10)
|
||||
|
||||
|
||||
def parser_types(*args, **kwargs):
|
||||
'''Delay evaluation of parser types until start of wizard, to allow
|
||||
depending modules to initialize and add their parsers to the list
|
||||
@@ -57,18 +60,26 @@ class banking_import_line(orm.TransientModel):
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64),
|
||||
'date': fields.date('Date', readonly=True),
|
||||
'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
|
||||
'amount': fields.float(
|
||||
'Amount',
|
||||
digits_compute=dp.get_precision('Account'),
|
||||
),
|
||||
'statement_line_id': fields.many2one(
|
||||
'account.bank.statement.line',
|
||||
'Resulting statement line', readonly=True),
|
||||
'type': fields.selection([
|
||||
('supplier','Supplier'),
|
||||
('customer','Customer'),
|
||||
('general','General')
|
||||
('supplier', 'Supplier'),
|
||||
('customer', 'Customer'),
|
||||
('general', 'General')
|
||||
], 'Type', required=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'statement_id': fields.many2one('account.bank.statement', 'Statement',
|
||||
select=True, required=True, ondelete='cascade'),
|
||||
'statement_id': fields.many2one(
|
||||
'account.bank.statement',
|
||||
'Statement',
|
||||
select=True,
|
||||
required=True,
|
||||
ondelete='cascade',
|
||||
),
|
||||
'ref': fields.char('Reference', size=32),
|
||||
'note': fields.text('Notes'),
|
||||
'period_id': fields.many2one('account.period', 'Period'),
|
||||
@@ -83,13 +94,16 @@ class banking_import_line(orm.TransientModel):
|
||||
'account.invoice', 'banking_import_line_invoice_rel',
|
||||
'line_id', 'invoice_id'),
|
||||
'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account'),
|
||||
'transaction_type': fields.selection([
|
||||
'transaction_type': fields.selection(
|
||||
[
|
||||
# TODO: payment terminal etc...
|
||||
('invoice', 'Invoice payment'),
|
||||
('storno', 'Canceled debit order'),
|
||||
('bank_costs', 'Bank costs'),
|
||||
('unknown', 'Unknown'),
|
||||
], 'Transaction type'),
|
||||
],
|
||||
'Transaction type',
|
||||
),
|
||||
'duplicate': fields.boolean('Duplicate'),
|
||||
}
|
||||
|
||||
@@ -119,7 +133,8 @@ class banking_import(orm.TransientModel):
|
||||
if not parser:
|
||||
raise orm.except_orm(
|
||||
_('ERROR!'),
|
||||
_('Unable to import parser %(parser)s. Parser class not found.') %
|
||||
_('Unable to import parser %(parser)s. Parser class not '
|
||||
'found.') %
|
||||
{'parser': parser_code}
|
||||
)
|
||||
|
||||
@@ -133,16 +148,17 @@ class banking_import(orm.TransientModel):
|
||||
if any([x for x in statements if not x.is_valid()]):
|
||||
raise orm.except_orm(
|
||||
_('ERROR!'),
|
||||
_('The imported statements appear to be invalid! Check your file.')
|
||||
_('The imported statements appear to be invalid! Check your '
|
||||
'file.')
|
||||
)
|
||||
|
||||
# Create the file now, as the statements need to be linked to it
|
||||
import_id = statement_file_obj.create(cr, uid, dict(
|
||||
company_id = company.id,
|
||||
file = statements_file,
|
||||
file_name = banking_import.file_name,
|
||||
state = 'unfinished',
|
||||
format = parser.name,
|
||||
company_id=company.id,
|
||||
file=statements_file,
|
||||
file_name=banking_import.file_name,
|
||||
state='unfinished',
|
||||
format=parser.name,
|
||||
))
|
||||
|
||||
bank_country_code = False
|
||||
@@ -151,14 +167,14 @@ class banking_import(orm.TransientModel):
|
||||
|
||||
# Results
|
||||
results = struct(
|
||||
stat_loaded_cnt = 0,
|
||||
trans_loaded_cnt = 0,
|
||||
stat_skipped_cnt = 0,
|
||||
trans_skipped_cnt = 0,
|
||||
trans_matched_cnt = 0,
|
||||
bank_costs_invoice_cnt = 0,
|
||||
error_cnt = 0,
|
||||
log = [],
|
||||
stat_loaded_cnt=0,
|
||||
trans_loaded_cnt=0,
|
||||
stat_skipped_cnt=0,
|
||||
trans_skipped_cnt=0,
|
||||
trans_matched_cnt=0,
|
||||
bank_costs_invoice_cnt=0,
|
||||
error_cnt=0,
|
||||
log=[],
|
||||
)
|
||||
|
||||
# Caching
|
||||
@@ -175,7 +191,9 @@ class banking_import(orm.TransientModel):
|
||||
continue
|
||||
|
||||
# Create fallback currency code
|
||||
currency_code = statement.local_currency or company.currency_id.name
|
||||
currency_code = (
|
||||
statement.local_currency or company.currency_id.name
|
||||
)
|
||||
|
||||
# Check cache for account info/currency
|
||||
if statement.local_account in info and \
|
||||
@@ -190,8 +208,10 @@ class banking_import(orm.TransientModel):
|
||||
)
|
||||
if not account_info:
|
||||
results.log.append(
|
||||
_('Statements found for unknown account %(bank_account)s') %
|
||||
{'bank_account': statement.local_account}
|
||||
_('Statements found for unknown account '
|
||||
'%(bank_account)s') % {
|
||||
'bank_account': statement.local_account
|
||||
}
|
||||
)
|
||||
error_accounts[statement.local_account] = True
|
||||
results.error_cnt += 1
|
||||
@@ -200,7 +220,7 @@ class banking_import(orm.TransientModel):
|
||||
results.log.append(
|
||||
_('Statements found for account %(bank_account)s, '
|
||||
'but no default journal was defined.'
|
||||
) % {'bank_account': statement.local_account}
|
||||
) % {'bank_account': statement.local_account}
|
||||
)
|
||||
error_accounts[statement.local_account] = True
|
||||
results.error_cnt += 1
|
||||
@@ -210,7 +230,7 @@ class banking_import(orm.TransientModel):
|
||||
currency_code = account_info.currency_id.name
|
||||
|
||||
# Cache results
|
||||
if not statement.local_account in info:
|
||||
if statement.local_account not in info:
|
||||
info[statement.local_account] = {
|
||||
currency_code: account_info
|
||||
}
|
||||
@@ -224,10 +244,10 @@ class banking_import(orm.TransientModel):
|
||||
results.log.append(
|
||||
_('Statement %(statement_id)s for account %(bank_account)s'
|
||||
' uses different currency than the defined bank journal.'
|
||||
) % {
|
||||
'bank_account': statement.local_account,
|
||||
'statement_id': statement.id
|
||||
}
|
||||
) % {
|
||||
'bank_account': statement.local_account,
|
||||
'statement_id': statement.id
|
||||
}
|
||||
)
|
||||
error_accounts[statement.local_account] = True
|
||||
results.error_cnt += 1
|
||||
@@ -251,7 +271,8 @@ class banking_import(orm.TransientModel):
|
||||
)
|
||||
continue
|
||||
|
||||
# Get the period for the statement (as bank statement object checks this)
|
||||
# Get the period for the statement (as bank statement object
|
||||
# checks this)
|
||||
period_ids = period_obj.search(
|
||||
cr, uid, [
|
||||
('company_id', '=', company.id),
|
||||
@@ -272,17 +293,17 @@ class banking_import(orm.TransientModel):
|
||||
|
||||
# Create the bank statement record
|
||||
statement_id = statement_obj.create(cr, uid, dict(
|
||||
name = statement.id,
|
||||
journal_id = account_info.journal_id.id,
|
||||
date = convert.date2str(statement.date),
|
||||
balance_start = statement.start_balance,
|
||||
balance_end_real = statement.end_balance,
|
||||
balance_end = statement.end_balance,
|
||||
state = 'draft',
|
||||
user_id = uid,
|
||||
banking_id = import_id,
|
||||
company_id = company.id,
|
||||
period_id = period_ids[0],
|
||||
name=statement.id,
|
||||
journal_id=account_info.journal_id.id,
|
||||
date=convert.date2str(statement.date),
|
||||
balance_start=statement.start_balance,
|
||||
balance_end_real=statement.end_balance,
|
||||
balance_end=statement.end_balance,
|
||||
state='draft',
|
||||
user_id=uid,
|
||||
banking_id=import_id,
|
||||
company_id=company.id,
|
||||
period_id=period_ids[0],
|
||||
))
|
||||
imported_statement_ids.append(statement_id)
|
||||
|
||||
@@ -294,7 +315,8 @@ class banking_import(orm.TransientModel):
|
||||
values = {}
|
||||
for attr in transaction.__slots__ + ['type']:
|
||||
if attr in import_transaction_obj.column_map:
|
||||
values[import_transaction_obj.column_map[attr]] = eval('transaction.%s' % attr)
|
||||
values[import_transaction_obj.column_map[attr]] = \
|
||||
eval('transaction.%s' % attr)
|
||||
elif attr in import_transaction_obj._columns:
|
||||
values[attr] = eval('transaction.%s' % attr)
|
||||
values['statement_id'] = statement_id
|
||||
@@ -308,32 +330,14 @@ class banking_import(orm.TransientModel):
|
||||
|
||||
results.stat_loaded_cnt += 1
|
||||
|
||||
import_transaction_obj.match(cr, uid, transaction_ids, results=results, context=context)
|
||||
import_transaction_obj.match(
|
||||
cr, uid, transaction_ids, results=results, context=context
|
||||
)
|
||||
|
||||
#recompute statement end_balance for validation
|
||||
# recompute statement end_balance for validation
|
||||
statement_obj.button_dummy(
|
||||
cr, uid, imported_statement_ids, context=context)
|
||||
|
||||
|
||||
# Original code. Didn't take workflow logistics into account...
|
||||
#
|
||||
#cr.execute(
|
||||
# "UPDATE payment_order o "
|
||||
# "SET state = 'done', "
|
||||
# "date_done = '%s' "
|
||||
# "FROM payment_line l "
|
||||
# "WHERE o.state = 'sent' "
|
||||
# "AND o.id = l.order_id "
|
||||
# "AND l.id NOT IN ("
|
||||
# "SELECT DISTINCT id FROM payment_line "
|
||||
# "WHERE date_done IS NULL "
|
||||
# "AND id IN (%s)"
|
||||
# ")" % (
|
||||
# time.strftime('%Y-%m-%d'),
|
||||
# ','.join([str(x) for x in payment_line_ids])
|
||||
# )
|
||||
#)
|
||||
|
||||
report = [
|
||||
'%s: %s' % (_('Total number of statements'),
|
||||
results.stat_skipped_cnt + results.stat_loaded_cnt),
|
||||
@@ -360,15 +364,18 @@ class banking_import(orm.TransientModel):
|
||||
text_log = '\n'.join(report + results.log)
|
||||
state = results.error_cnt and 'error' or 'ready'
|
||||
statement_file_obj.write(cr, uid, import_id, dict(
|
||||
state = state, log = text_log,
|
||||
), context)
|
||||
state=state,
|
||||
log=text_log,
|
||||
), context)
|
||||
if not imported_statement_ids or not results.trans_loaded_cnt:
|
||||
# file state can be 'ready' while import state is 'error'
|
||||
state = 'error'
|
||||
self.write(cr, uid, [ids[0]], dict(
|
||||
import_id = import_id, log = text_log, state = state,
|
||||
statement_ids = [(6, 0, imported_statement_ids)],
|
||||
), context)
|
||||
import_id=import_id,
|
||||
log=text_log,
|
||||
state=state,
|
||||
statement_ids=[(6, 0, imported_statement_ids)],
|
||||
), context)
|
||||
return {
|
||||
'name': (state == 'ready' and _('Review Bank Statements') or
|
||||
_('Error')),
|
||||
@@ -393,13 +400,15 @@ class banking_import(orm.TransientModel):
|
||||
),
|
||||
'file_name': fields.char('File name', size=256),
|
||||
'file': fields.binary(
|
||||
'Statements File', required=True,
|
||||
help = ('The Transactions File to import. Please note that while it is '
|
||||
'perfectly safe to reload the same file multiple times or to load in '
|
||||
'timeframe overlapping statements files, there are formats that may '
|
||||
'introduce different sequencing, which may create double entries.\n\n'
|
||||
'To stay on the safe side, always load bank statements files using the '
|
||||
'same format.'),
|
||||
'Statements File',
|
||||
required=True,
|
||||
help=('The Transactions File to import. Please note that while it '
|
||||
'is perfectly safe to reload the same file multiple times '
|
||||
'or to load in timeframe overlapping statements files, '
|
||||
'there are formats that may introduce different '
|
||||
'sequencing, which may create double entries.\n\n'
|
||||
'To stay on the safe side, always load bank statements '
|
||||
'files using the same format.'),
|
||||
states={
|
||||
'ready': [('readonly', True)],
|
||||
'error': [('readonly', True)],
|
||||
@@ -435,8 +444,8 @@ class banking_import(orm.TransientModel):
|
||||
|
||||
_defaults = {
|
||||
'state': 'init',
|
||||
'company': lambda s,cr,uid,c:
|
||||
'company': lambda s, cr, uid, c:
|
||||
s.pool.get('res.company')._company_default_get(
|
||||
cr, uid, 'bank.import.transaction', context=c),
|
||||
cr, uid, 'bank.import.transaction', context=c),
|
||||
'parser': _default_parser_type,
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -78,7 +78,7 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
import_transaction_obj = self.pool.get('banking.import.transaction')
|
||||
trans_id = self.read(
|
||||
cr, uid, ids[0], ['import_transaction_id'],
|
||||
context=context)['import_transaction_id'][0] # many2one tuple
|
||||
context=context)['import_transaction_id'][0] # many2one tuple
|
||||
import_transaction_obj.match(cr, uid, [trans_id], context=context)
|
||||
return self.create_act_window(cr, uid, ids, context=None)
|
||||
|
||||
@@ -128,12 +128,17 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
wiz.import_transaction_id.invoice_id):
|
||||
transaction_obj.write(
|
||||
cr, uid, wiz.import_transaction_id.id,
|
||||
{ 'move_line_id': move_line.id, }, context=context)
|
||||
{'move_line_id': move_line.id, },
|
||||
context=context
|
||||
)
|
||||
statement_line_obj.write(
|
||||
cr, uid, wiz.import_transaction_id.statement_line_id.id,
|
||||
{ 'partner_id': move_line.partner_id.id or False,
|
||||
'account_id': move_line.account_id.id,
|
||||
}, context=context)
|
||||
cr, uid,
|
||||
wiz.import_transaction_id.statement_line_id.id,
|
||||
{
|
||||
'partner_id': (
|
||||
move_line.partner_id.id or False),
|
||||
'account_id': move_line.account_id.id,
|
||||
}, context=context)
|
||||
found = True
|
||||
break
|
||||
# Cannot match the invoice
|
||||
@@ -150,15 +155,16 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
# Rewrite *2many directive notation
|
||||
if manual_invoice_ids:
|
||||
manual_invoice_ids = (
|
||||
[i[1] for i in manual_invoice_ids if i[0]==4] +
|
||||
[j for i in manual_invoice_ids if i[0]==6 for j in i[2]])
|
||||
[i[1] for i in manual_invoice_ids if i[0] == 4] +
|
||||
[j for i in manual_invoice_ids if i[0] == 6 for j in i[2]])
|
||||
if manual_move_line_ids:
|
||||
manual_move_line_ids = (
|
||||
[i[1] for i in manual_move_line_ids if i[0]==4] +
|
||||
[j for i in manual_move_line_ids if i[0]==6 for j in i[2]])
|
||||
[i[1] for i in manual_move_line_ids if i[0] == 4] +
|
||||
[j for i in manual_move_line_ids
|
||||
if i[0] == 6 for j in i[2]])
|
||||
for wiz in self.browse(cr, uid, ids, context=context):
|
||||
#write can be called multiple times for the same values
|
||||
#that doesn't hurt above, but it does here
|
||||
# write can be called multiple times for the same values
|
||||
# that doesn't hurt above, but it does here
|
||||
if wiz.match_type and (
|
||||
len(manual_move_line_ids) > 1 or
|
||||
len(manual_invoice_ids) > 1):
|
||||
@@ -171,7 +177,8 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
found_move_line = False
|
||||
if invoice.move_id:
|
||||
for line in invoice.move_id.line_id:
|
||||
if line.account_id.type in ('receivable', 'payable'):
|
||||
if line.account_id.type in ('receivable',
|
||||
'payable'):
|
||||
todo.append((invoice.id, line.id))
|
||||
found_move_line = True
|
||||
break
|
||||
@@ -181,12 +188,13 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
_("No entry found for the selected invoice. "))
|
||||
for move_line_id in manual_move_line_ids:
|
||||
todo_entry = [False, move_line_id]
|
||||
move_line=move_line_obj.read(
|
||||
cr,
|
||||
uid,
|
||||
move_line_id,
|
||||
['invoice'],
|
||||
context=context)
|
||||
move_line = move_line_obj.read(
|
||||
cr,
|
||||
uid,
|
||||
move_line_id,
|
||||
['invoice'],
|
||||
context=context
|
||||
)
|
||||
if move_line['invoice']:
|
||||
todo_entry[0] = move_line['invoice'][0]
|
||||
todo.append(todo_entry)
|
||||
@@ -194,25 +202,27 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
while todo:
|
||||
todo_entry = todo.pop()
|
||||
move_line = move_line_obj.browse(
|
||||
cr, uid, todo_entry[1], context)
|
||||
cr, uid, todo_entry[1], context)
|
||||
transaction_id = wiz.import_transaction_id.id
|
||||
statement_line_id = wiz.statement_line_id.id
|
||||
|
||||
if len(todo) > 0:
|
||||
statement_line_id = wiz.statement_line_id.split_off(
|
||||
move_line.debit or -move_line.credit)[0]
|
||||
move_line.debit or -move_line.credit)[0]
|
||||
transaction_id = statement_line_obj.browse(
|
||||
cr,
|
||||
uid,
|
||||
statement_line_id,
|
||||
context=context).import_transaction_id.id
|
||||
cr,
|
||||
uid,
|
||||
statement_line_id,
|
||||
context=context
|
||||
).import_transaction_id.id
|
||||
|
||||
vals = {
|
||||
'move_line_id': todo_entry[1],
|
||||
'move_line_ids': [(6, 0, [todo_entry[1]])],
|
||||
'invoice_id': todo_entry[0],
|
||||
'invoice_ids': [(6, 0,
|
||||
[todo_entry[0]] if todo_entry[0] else [])],
|
||||
'invoice_ids': [
|
||||
(6, 0, [todo_entry[0]] if todo_entry[0] else [])
|
||||
],
|
||||
'match_type': 'manual',
|
||||
}
|
||||
|
||||
@@ -255,22 +265,19 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
# Get the bank account setting record, to reset the account
|
||||
account_id = False
|
||||
journal_id = wiz.statement_line_id.statement_id.journal_id.id
|
||||
setting_ids = settings_pool.find(cr, uid, journal_id, context=context)
|
||||
setting_ids = settings_pool.find(
|
||||
cr, uid, journal_id, context=context
|
||||
)
|
||||
|
||||
# Restore partner id from the bank account or else reset
|
||||
partner_id = False
|
||||
if (wiz.statement_line_id.partner_bank_id and
|
||||
wiz.statement_line_id.partner_bank_id.partner_id):
|
||||
partner_id = wiz.statement_line_id.partner_bank_id.partner_id.id
|
||||
partner_id = (
|
||||
wiz.statement_line_id.partner_bank_id.partner_id.id
|
||||
)
|
||||
wiz.write({'partner_id': partner_id})
|
||||
|
||||
# Select account type by parter customer or supplier,
|
||||
# or default based on amount sign
|
||||
if wiz.amount < 0:
|
||||
account_type = 'payable'
|
||||
else:
|
||||
account_type = 'receivable'
|
||||
|
||||
bank_partner = False
|
||||
if partner_id:
|
||||
bank_partner = wiz.statement_line_id.partner_bank_id.partner_id
|
||||
@@ -295,13 +302,18 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
wiz.statement_line_id.write({'account_id': account_id})
|
||||
|
||||
if wiz.statement_line_id:
|
||||
#delete splits causing an unsplit if this is a split
|
||||
#transaction
|
||||
statement_pool.unlink(cr, uid,
|
||||
statement_pool.search(cr, uid,
|
||||
[('parent_id', '=', wiz.statement_line_id.id)],
|
||||
context=context),
|
||||
context=context)
|
||||
# delete splits causing an unsplit if this is a split
|
||||
# transaction
|
||||
statement_pool.unlink(
|
||||
cr,
|
||||
uid,
|
||||
statement_pool.search(
|
||||
cr, uid,
|
||||
[('parent_id', '=', wiz.statement_line_id.id)],
|
||||
context=context
|
||||
),
|
||||
context=context
|
||||
)
|
||||
|
||||
if wiz.import_transaction_id:
|
||||
wiz.import_transaction_id.clear_and_write()
|
||||
@@ -313,8 +325,8 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
ids = [ids]
|
||||
transaction_obj = self.pool.get('banking.import.transaction')
|
||||
for wiz in self.read(
|
||||
cr, uid, ids, ['duplicate', 'import_transaction_id'],
|
||||
context=context):
|
||||
cr, uid, ids, ['duplicate', 'import_transaction_id'],
|
||||
context=context):
|
||||
transaction_obj.write(
|
||||
cr, uid, wiz['import_transaction_id'][0],
|
||||
{'duplicate': not wiz['duplicate']}, context=context)
|
||||
@@ -363,8 +375,12 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
'import_transaction_id', 'invoice_ids', string="Matching invoices",
|
||||
type='many2many', relation='account.invoice'),
|
||||
'invoice_id': fields.related(
|
||||
'import_transaction_id', 'invoice_id', string="Invoice to reconcile",
|
||||
type='many2one', relation='account.invoice'),
|
||||
'import_transaction_id',
|
||||
'invoice_id',
|
||||
string="Invoice to reconcile",
|
||||
type='many2one',
|
||||
relation='account.invoice',
|
||||
),
|
||||
'move_line_ids': fields.related(
|
||||
'import_transaction_id', 'move_line_ids', string="Entry lines",
|
||||
type='many2many', relation='account.move.line'),
|
||||
@@ -372,15 +388,20 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
'import_transaction_id', 'move_line_id', string="Entry line",
|
||||
type='many2one', relation='account.move.line'),
|
||||
'duplicate': fields.related(
|
||||
'import_transaction_id', 'duplicate', string='Flagged as duplicate',
|
||||
type='boolean'),
|
||||
'import_transaction_id',
|
||||
'duplicate',
|
||||
string='Flagged as duplicate',
|
||||
type='boolean',
|
||||
),
|
||||
'match_multi': fields.related(
|
||||
'import_transaction_id', 'match_multi',
|
||||
type="boolean", string='Multiple matches'),
|
||||
'match_type': fields.related(
|
||||
'import_transaction_id', 'match_type', type='selection',
|
||||
'import_transaction_id',
|
||||
'match_type',
|
||||
type='selection',
|
||||
selection=[
|
||||
('move','Move'),
|
||||
('move', 'Move'),
|
||||
('invoice', 'Invoice'),
|
||||
('payment', 'Payment line'),
|
||||
('payment_order', 'Payment order'),
|
||||
@@ -388,8 +409,10 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
('manual', 'Manual'),
|
||||
('payment_manual', 'Payment line (manual)'),
|
||||
('payment_order_manual', 'Payment order (manual)'),
|
||||
],
|
||||
string='Match type', readonly=True),
|
||||
],
|
||||
string='Match type',
|
||||
readonly=True,
|
||||
),
|
||||
'manual_invoice_ids': fields.many2many(
|
||||
'account.invoice',
|
||||
'banking_transaction_wizard_account_invoice_rel',
|
||||
@@ -401,8 +424,17 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
'wizard_id', 'move_line_id', string='Or match one or more entries',
|
||||
domain=[('account_id.reconcile', '=', True),
|
||||
('reconcile_id', '=', False)]),
|
||||
'payment_option': fields.related('import_transaction_id','payment_option', string='Payment Difference', type='selection', required=True,
|
||||
selection=[('without_writeoff', 'Keep Open'),('with_writeoff', 'Reconcile Payment Balance')]),
|
||||
'payment_option': fields.related(
|
||||
'import_transaction_id',
|
||||
'payment_option',
|
||||
string='Payment Difference',
|
||||
type='selection',
|
||||
required=True,
|
||||
selection=[
|
||||
('without_writeoff', 'Keep Open'),
|
||||
('with_writeoff', 'Reconcile Payment Balance')
|
||||
],
|
||||
),
|
||||
'writeoff_analytic_id': fields.related(
|
||||
'import_transaction_id', 'writeoff_analytic_id',
|
||||
type='many2one', relation='account.analytic.account',
|
||||
@@ -411,9 +443,11 @@ class banking_transaction_wizard(orm.TransientModel):
|
||||
'statement_line_id', 'analytic_account_id',
|
||||
type='many2one', relation='account.analytic.account',
|
||||
string="Analytic Account"),
|
||||
'move_currency_amount': fields.related('import_transaction_id','move_currency_amount',
|
||||
type='float', string='Match Currency Amount', readonly=True),
|
||||
}
|
||||
|
||||
banking_transaction_wizard()
|
||||
|
||||
'move_currency_amount': fields.related(
|
||||
'import_transaction_id',
|
||||
'move_currency_amount',
|
||||
type='float',
|
||||
string='Match Currency Amount',
|
||||
readonly=True,
|
||||
),
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# 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
|
||||
# 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,
|
||||
@@ -32,6 +32,7 @@ __all__ = [
|
||||
'create_bank_account',
|
||||
]
|
||||
|
||||
|
||||
def get_period(pool, cr, uid, date, company, log=None):
|
||||
'''
|
||||
Wrapper over account_period.find() to log exceptions of
|
||||
@@ -43,7 +44,7 @@ def get_period(pool, cr, uid, date, company, log=None):
|
||||
try:
|
||||
period_ids = pool.get('account.period').find(
|
||||
cr, uid, dt=date, context=context)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
if log is None:
|
||||
raise
|
||||
else:
|
||||
@@ -51,6 +52,7 @@ def get_period(pool, cr, uid, date, company, log=None):
|
||||
return False
|
||||
return period_ids[0]
|
||||
|
||||
|
||||
def get_bank_accounts(pool, cr, uid, account_number, log, fail=False):
|
||||
'''
|
||||
Get the bank account with account number account_number
|
||||
@@ -72,6 +74,7 @@ def get_bank_accounts(pool, cr, uid, account_number, log, fail=False):
|
||||
return []
|
||||
return partner_bank_obj.browse(cr, uid, bank_account_ids)
|
||||
|
||||
|
||||
def _has_attr(obj, attr):
|
||||
# Needed for dangling addresses and a weird exception scheme in
|
||||
# OpenERP's orm.
|
||||
@@ -80,6 +83,7 @@ def _has_attr(obj, attr):
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
|
||||
def get_partner(pool, cr, uid, name, address, postal_code, city,
|
||||
country_id, log, context=None):
|
||||
'''
|
||||
@@ -115,7 +119,8 @@ def get_partner(pool, cr, uid, name, address, postal_code, city,
|
||||
key = name.lower()
|
||||
partners = []
|
||||
for partner in partner_obj.read(
|
||||
cr, uid, partner_search_ids, ['name', 'commercial_partner_id'], context=context):
|
||||
cr, uid, partner_search_ids, ['name', 'commercial_partner_id'],
|
||||
context=context):
|
||||
if (len(partner['name']) > 3 and partner['name'].lower() in key):
|
||||
partners.append(partner)
|
||||
partners.sort(key=lambda x: len(x['name']), reverse=True)
|
||||
@@ -126,6 +131,7 @@ def get_partner(pool, cr, uid, name, address, postal_code, city,
|
||||
'name %(name)s') % {'name': name})
|
||||
return partner_ids and partner_ids[0] or False
|
||||
|
||||
|
||||
def get_company_bank_account(pool, cr, uid, account_number, currency,
|
||||
company, log):
|
||||
'''
|
||||
@@ -139,16 +145,16 @@ def get_company_bank_account(pool, cr, uid, account_number, currency,
|
||||
return False
|
||||
elif len(bank_accounts) != 1:
|
||||
log.append(
|
||||
_('More than one bank account was found with the same number %(account_no)s')
|
||||
% dict(account_no = account_number)
|
||||
_('More than one bank account was found with the same number '
|
||||
'%(account_no)s') % dict(account_no=account_number)
|
||||
)
|
||||
return False
|
||||
if bank_accounts[0].partner_id.id != company.partner_id.id:
|
||||
log.append(
|
||||
_('Account %(account_no)s is not owned by %(partner)s')
|
||||
% dict(account_no = account_number,
|
||||
partner = company.partner_id.name,
|
||||
))
|
||||
% dict(account_no=account_number,
|
||||
partner=company.partner_id.name,
|
||||
))
|
||||
return False
|
||||
results.account = bank_accounts[0]
|
||||
bank_settings_obj = pool.get('account.banking.account.settings')
|
||||
@@ -189,8 +195,9 @@ def get_company_bank_account(pool, cr, uid, account_number, currency,
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def get_or_create_bank(pool, cr, uid, bic, online=False, code=None,
|
||||
name=None):
|
||||
name=None, context=None):
|
||||
'''
|
||||
Find or create the bank with the provided BIC code.
|
||||
When online, the SWIFT database will be consulted in order to
|
||||
@@ -231,30 +238,33 @@ def get_or_create_bank(pool, cr, uid, bic, online=False, code=None,
|
||||
bank_id = False
|
||||
|
||||
if online:
|
||||
info, address = bank_obj.online_bank_info(cr, uid, bic, context=context)
|
||||
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,
|
||||
name = info.name,
|
||||
street = address.street,
|
||||
street2 = address.street2,
|
||||
zip = address.zip,
|
||||
city = address.city,
|
||||
country = country_id,
|
||||
bic = info.bic[:8],
|
||||
code=info.code,
|
||||
name=info.name,
|
||||
street=address.street,
|
||||
street2=address.street2,
|
||||
zip=address.zip,
|
||||
city=address.city,
|
||||
country=country_id,
|
||||
bic=info.bic[:8],
|
||||
))
|
||||
else:
|
||||
info = struct(name=name, code=code)
|
||||
|
||||
if not online or not bank_id:
|
||||
bank_id = bank_obj.create(cr, uid, dict(
|
||||
code = info.code or 'UNKNOW',
|
||||
name = info.name or _('Unknown Bank'),
|
||||
country = country_id,
|
||||
bic = bic,
|
||||
code=info.code or 'UNKNOW', # FIXME: Typo?
|
||||
name=info.name or _('Unknown Bank'),
|
||||
country=country_id,
|
||||
bic=bic,
|
||||
))
|
||||
return bank_id, country_id
|
||||
|
||||
|
||||
def get_country_id(pool, cr, uid, transaction, context=None):
|
||||
"""
|
||||
Derive a country id from the info on the transaction.
|
||||
@@ -283,6 +293,7 @@ def get_country_id(pool, cr, uid, transaction, context=None):
|
||||
country_id = company.partner_id.country.id
|
||||
return country_id
|
||||
|
||||
|
||||
def create_bank_account(pool, cr, uid, partner_id,
|
||||
account_number, holder_name, address, city,
|
||||
country_id, bic=False,
|
||||
@@ -291,9 +302,9 @@ def create_bank_account(pool, cr, uid, partner_id,
|
||||
Create a matching bank account with this holder for this partner.
|
||||
'''
|
||||
values = struct(
|
||||
partner_id = partner_id,
|
||||
owner_name = holder_name,
|
||||
country_id = country_id,
|
||||
partner_id=partner_id,
|
||||
owner_name=holder_name,
|
||||
country_id=country_id,
|
||||
)
|
||||
|
||||
# Are we dealing with IBAN?
|
||||
@@ -325,5 +336,3 @@ def create_bank_account(pool, cr, uid, partner_id,
|
||||
# Create bank account and return
|
||||
return pool.get('res.partner.bank').create(
|
||||
cr, uid, values, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -24,6 +24,7 @@ from openerp.tools.translate import _
|
||||
from openerp.addons.account_banking.wizard import banktools
|
||||
import ast
|
||||
|
||||
|
||||
class link_partner(orm.TransientModel):
|
||||
_name = 'banking.link_partner'
|
||||
_description = 'Link partner'
|
||||
@@ -160,8 +161,8 @@ class link_partner(orm.TransientModel):
|
||||
wiz_read = self.read(
|
||||
cr, uid, ids[0], context=context, load='_classic_write')
|
||||
partner_vals = {
|
||||
'type': 'default',
|
||||
}
|
||||
'type': 'default',
|
||||
}
|
||||
self.update_partner_values(
|
||||
cr, uid, wiz_read, partner_vals, context=context)
|
||||
partner_id = self.pool.get('res.partner').create(
|
||||
@@ -205,5 +206,3 @@ class link_partner(orm.TransientModel):
|
||||
'res_id': ids[0],
|
||||
'nodestroy': nodestroy,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user