mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
[FIX] pep8, pylint, eyeballing
This commit is contained in:
@@ -117,4 +117,3 @@ class easy_reconcile_advanced_ref(TransientModel):
|
|||||||
yield ('partner_id', move_line['partner_id'])
|
yield ('partner_id', move_line['partner_id'])
|
||||||
yield ('ref', (move_line['ref'].lower().strip(),
|
yield ('ref', (move_line['ref'].lower().strip(),
|
||||||
move_line['name'].lower().strip()))
|
move_line['name'].lower().strip()))
|
||||||
|
|
||||||
|
|||||||
@@ -271,4 +271,3 @@ class easy_reconcile_advanced(AbstractModel):
|
|||||||
partial_reconciled_ids += reconcile_group_ids
|
partial_reconciled_ids += reconcile_group_ids
|
||||||
|
|
||||||
return reconciled_ids, partial_reconciled_ids
|
return reconciled_ids, partial_reconciled_ids
|
||||||
|
|
||||||
|
|||||||
@@ -34,4 +34,3 @@ class account_easy_reconcile_method(Model):
|
|||||||
'Advanced. Partner and Ref.'),
|
'Advanced. Partner and Ref.'),
|
||||||
]
|
]
|
||||||
return methods
|
return methods
|
||||||
|
|
||||||
|
|||||||
@@ -20,4 +20,4 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import statement
|
import statement
|
||||||
import partner
|
import partner
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
'author': 'Camptocamp',
|
'author': 'Camptocamp',
|
||||||
'maintainer': 'Camptocamp',
|
'maintainer': 'Camptocamp',
|
||||||
'category': 'Finance',
|
'category': 'Finance',
|
||||||
'complexity': 'normal', #easy, normal, expert
|
'complexity': 'normal',
|
||||||
'depends': ['account_statement_ext'],
|
'depends': ['account_statement_ext'],
|
||||||
'description': """
|
'description': """
|
||||||
The goal of this module is to improve the basic bank statement, help dealing with huge volume of
|
The goal of this module is to improve the basic bank statement, help dealing with huge volume of
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#################################################################################
|
#################################################################################
|
||||||
# #
|
# #
|
||||||
# Copyright (C) 2011 Akretion & Camptocamp
|
# Copyright (C) 2011 Akretion & Camptocamp
|
||||||
@@ -31,10 +31,8 @@ class res_partner(Model):
|
|||||||
_inherit = 'res.partner'
|
_inherit = 'res.partner'
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'bank_statement_label':fields.char('Bank Statement Label', size=100,
|
'bank_statement_label': fields.char('Bank Statement Label', size=100,
|
||||||
help="Enter the various label found on your bank statement separated by a ; If \
|
help="Enter the various label found on your bank statement separated by a ; If \
|
||||||
one of this label is include in the bank statement line, the partner will be automatically \
|
one of this label is include in the bank statement line, the partner will be automatically \
|
||||||
filled (as long as you use this method/rules in your statement profile)."),
|
filled (as long as you use this method/rules in your statement profile)."),
|
||||||
}
|
}
|
||||||
|
|
||||||
res_partner()
|
|
||||||
|
|||||||
@@ -20,10 +20,11 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
from tools.translate import _
|
from tools.translate import _
|
||||||
from openerp.osv.orm import Model, fields
|
from openerp.osv.orm import Model, fields
|
||||||
from openerp.osv import fields, osv, osv
|
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||||
from operator import itemgetter, attrgetter
|
from operator import attrgetter
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
class ErrorTooManyPartner(Exception):
|
class ErrorTooManyPartner(Exception):
|
||||||
"""
|
"""
|
||||||
New Exception definition that is raised when more than one partner is matched by
|
New Exception definition that is raised when more than one partner is matched by
|
||||||
@@ -31,6 +32,7 @@ class ErrorTooManyPartner(Exception):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return repr(self.value)
|
return repr(self.value)
|
||||||
|
|
||||||
@@ -40,38 +42,38 @@ class AccountStatementProfil(Model):
|
|||||||
Extend the class to add rules per profile that will match at least the partner,
|
Extend the class to add rules per profile that will match at least the partner,
|
||||||
but it could also be used to match other values as well.
|
but it could also be used to match other values as well.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_inherit = "account.statement.profile"
|
_inherit = "account.statement.profile"
|
||||||
|
|
||||||
_columns={
|
_columns = {
|
||||||
# @Akretion : For now, we don't implement this features, but this would probably be there:
|
# @Akretion : For now, we don't implement this features, but this would probably be there:
|
||||||
# 'auto_completion': fields.text('Auto Completion'),
|
# 'auto_completion': fields.text('Auto Completion'),
|
||||||
# 'transferts_account_id':fields.many2one('account.account', 'Transferts Account'),
|
# 'transferts_account_id':fields.many2one('account.account', 'Transferts Account'),
|
||||||
# => You can implement it in a module easily, we design it with your needs in mind
|
# => You can implement it in a module easily, we design it with your needs in mind
|
||||||
# as well !
|
# as well !
|
||||||
|
|
||||||
'rule_ids':fields.many2many('account.statement.completion.rule',
|
'rule_ids': fields.many2many(
|
||||||
|
'account.statement.completion.rule',
|
||||||
string='Related statement profiles',
|
string='Related statement profiles',
|
||||||
rel='as_rul_st_prof_rel',
|
rel='as_rul_st_prof_rel'),
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def find_values_from_rules(self, cr, uid, id, line_id, context=None):
|
def find_values_from_rules(self, cr, uid, id, line_id, context=None):
|
||||||
"""
|
"""
|
||||||
This method will execute all related rules, in their sequence order,
|
This method will execute all related rules, in their sequence order,
|
||||||
to retrieve all the values returned by the first rules that will match.
|
to retrieve all the values returned by the first rules that will match.
|
||||||
|
|
||||||
:param int/long line_id: id of the concerned account.bank.statement.line
|
:param int/long line_id: id of the concerned account.bank.statement.line
|
||||||
:return:
|
:return:
|
||||||
A dict of value that can be passed directly to the write method of
|
A dict of value that can be passed directly to the write method of
|
||||||
the statement line or {}
|
the statement line or {}
|
||||||
{'partner_id': value,
|
{'partner_id': value,
|
||||||
'account_id' : value,
|
'account_id' : value,
|
||||||
|
|
||||||
...}
|
...}
|
||||||
"""
|
"""
|
||||||
if not context:
|
if context is None:
|
||||||
context={}
|
context = {}
|
||||||
res = {}
|
res = {}
|
||||||
rule_obj = self.pool.get('account.statement.completion.rule')
|
rule_obj = self.pool.get('account.statement.completion.rule')
|
||||||
profile = self.browse(cr, uid, id, context=context)
|
profile = self.browse(cr, uid, id, context=context)
|
||||||
@@ -79,11 +81,11 @@ class AccountStatementProfil(Model):
|
|||||||
sorted_array = sorted(profile.rule_ids, key=attrgetter('sequence'))
|
sorted_array = sorted(profile.rule_ids, key=attrgetter('sequence'))
|
||||||
for rule in sorted_array:
|
for rule in sorted_array:
|
||||||
method_to_call = getattr(rule_obj, rule.function_to_call)
|
method_to_call = getattr(rule_obj, rule.function_to_call)
|
||||||
result = method_to_call(cr,uid,line_id,context)
|
result = method_to_call(cr, uid, line_id, context)
|
||||||
if result:
|
if result:
|
||||||
return result
|
return result
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
class AccountStatementCompletionRule(Model):
|
class AccountStatementCompletionRule(Model):
|
||||||
"""
|
"""
|
||||||
@@ -91,14 +93,14 @@ class AccountStatementCompletionRule(Model):
|
|||||||
fullfill the bank statement lines. You'll be able to extend them in you own module
|
fullfill the bank statement lines. You'll be able to extend them in you own module
|
||||||
and choose those to apply for every statement profile.
|
and choose those to apply for every statement profile.
|
||||||
The goal of a rule is to fullfill at least the partner of the line, but
|
The goal of a rule is to fullfill at least the partner of the line, but
|
||||||
if possible also the reference because we'll use it in the reconciliation
|
if possible also the reference because we'll use it in the reconciliation
|
||||||
process. The reference should contain the invoice number or the SO number
|
process. The reference should contain the invoice number or the SO number
|
||||||
or any reference that will be matched by the invoice accounting move.
|
or any reference that will be matched by the invoice accounting move.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_name = "account.statement.completion.rule"
|
_name = "account.statement.completion.rule"
|
||||||
_order = "sequence asc"
|
_order = "sequence asc"
|
||||||
|
|
||||||
def _get_functions(self, cr, uid, context=None):
|
def _get_functions(self, cr, uid, context=None):
|
||||||
"""
|
"""
|
||||||
List of available methods for rules. Override this to add you own.
|
List of available methods for rules. Override this to add you own.
|
||||||
@@ -109,19 +111,20 @@ class AccountStatementCompletionRule(Model):
|
|||||||
('get_from_label_and_partner_field', 'From line label (based on partner field)'),
|
('get_from_label_and_partner_field', 'From line label (based on partner field)'),
|
||||||
('get_from_label_and_partner_name', 'From line label (based on partner name)'),
|
('get_from_label_and_partner_name', 'From line label (based on partner name)'),
|
||||||
]
|
]
|
||||||
|
|
||||||
_columns={
|
_columns = {
|
||||||
'sequence': fields.integer('Sequence', help="Lower means parsed first."),
|
'sequence': fields.integer('Sequence', help="Lower means parsed first."),
|
||||||
'name': fields.char('Name', size=128),
|
'name': fields.char('Name', size=128),
|
||||||
'profile_ids': fields.many2many('account.statement.profile',
|
'profile_ids': fields.many2many(
|
||||||
rel='as_rul_st_prof_rel',
|
'account.statement.profile',
|
||||||
|
rel='as_rul_st_prof_rel',
|
||||||
string='Related statement profiles'),
|
string='Related statement profiles'),
|
||||||
'function_to_call': fields.selection(_get_functions, 'Method'),
|
'function_to_call': fields.selection(_get_functions, 'Method'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_from_ref_and_invoice(self, cursor, uid, line_id, context=None):
|
def get_from_ref_and_invoice(self, cursor, uid, line_id, context=None):
|
||||||
"""
|
"""
|
||||||
Match the partner based on the invoice number and the reference of the statement
|
Match the partner based on the invoice number and the reference of the statement
|
||||||
line. Then, call the generic get_values_for_line method to complete other values.
|
line. Then, call the generic get_values_for_line method to complete other values.
|
||||||
If more than one partner matched, raise the ErrorTooManyPartner error.
|
If more than one partner matched, raise the ErrorTooManyPartner error.
|
||||||
|
|
||||||
@@ -131,30 +134,42 @@ class AccountStatementCompletionRule(Model):
|
|||||||
the statement line or {}
|
the statement line or {}
|
||||||
{'partner_id': value,
|
{'partner_id': value,
|
||||||
'account_id' : value,
|
'account_id' : value,
|
||||||
|
|
||||||
...}
|
...}
|
||||||
"""
|
"""
|
||||||
st_obj = self.pool.get('account.bank.statement.line')
|
st_obj = self.pool.get('account.bank.statement.line')
|
||||||
st_line = st_obj.browse(cursor,uid,line_id)
|
st_line = st_obj.browse(cursor, uid, line_id, context=context)
|
||||||
res = {}
|
res = {}
|
||||||
if st_line:
|
if st_line:
|
||||||
inv_obj = self.pool.get('account.invoice')
|
inv_obj = self.pool.get('account.invoice')
|
||||||
inv_id = inv_obj.search(cursor, uid, [('number', '=', st_line.ref)])
|
inv_id = inv_obj.search(
|
||||||
|
cursor,
|
||||||
|
uid,
|
||||||
|
[('number', '=', st_line.ref)],
|
||||||
|
context=context)
|
||||||
if inv_id:
|
if inv_id:
|
||||||
if inv_id and len(inv_id) == 1:
|
if inv_id and len(inv_id) == 1:
|
||||||
inv = inv_obj.browse(cursor, uid, inv_id[0])
|
inv = inv_obj.browse(cursor, uid, inv_id[0], context=context)
|
||||||
res['partner_id'] = inv.partner_id.id
|
res['partner_id'] = inv.partner_id.id
|
||||||
elif inv_id and len(inv_id) > 1:
|
elif inv_id and len(inv_id) > 1:
|
||||||
raise ErrorTooManyPartner(_('Line named "%s" (Ref:%s) was matched by more than one partner.')%(st_line.name,st_line.ref))
|
raise ErrorTooManyPartner(
|
||||||
st_vals = st_obj.get_values_for_line(cursor, uid, profile_id = st_line.statement_id.profile_id.id,
|
_('Line named "%s" (Ref:%s) was matched by more '
|
||||||
partner_id = res.get('partner_id',False), line_type = st_line.type, amount = st_line.amount, context = context)
|
'than one partner.') % (st_line.name, st_line.ref))
|
||||||
|
st_vals = st_obj.get_values_for_line(
|
||||||
|
cursor,
|
||||||
|
uid,
|
||||||
|
profile_id=st_line.statement_id.profile_id.id,
|
||||||
|
partner_id=res.get('partner_id', False),
|
||||||
|
line_type=st_line.type,
|
||||||
|
amount=st_line.amount,
|
||||||
|
context=context)
|
||||||
res.update(st_vals)
|
res.update(st_vals)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def get_from_ref_and_so(self, cursor, uid, line_id, context=None):
|
def get_from_ref_and_so(self, cursor, uid, line_id, context=None):
|
||||||
"""
|
"""
|
||||||
Match the partner based on the SO number and the reference of the statement
|
Match the partner based on the SO number and the reference of the statement
|
||||||
line. Then, call the generic get_values_for_line method to complete other values.
|
line. Then, call the generic get_values_for_line method to complete other values.
|
||||||
If more than one partner matched, raise the ErrorTooManyPartner error.
|
If more than one partner matched, raise the ErrorTooManyPartner error.
|
||||||
|
|
||||||
:param int/long line_id: id of the concerned account.bank.statement.line
|
:param int/long line_id: id of the concerned account.bank.statement.line
|
||||||
@@ -163,32 +178,44 @@ class AccountStatementCompletionRule(Model):
|
|||||||
the statement line or {}
|
the statement line or {}
|
||||||
{'partner_id': value,
|
{'partner_id': value,
|
||||||
'account_id' : value,
|
'account_id' : value,
|
||||||
|
|
||||||
...}
|
...}
|
||||||
"""
|
"""
|
||||||
st_obj = self.pool.get('account.bank.statement.line')
|
st_obj = self.pool.get('account.bank.statement.line')
|
||||||
st_line = st_obj.browse(cursor,uid,line_id)
|
st_line = st_obj.browse(cursor, uid, line_id, context=context)
|
||||||
res = {}
|
res = {}
|
||||||
if st_line:
|
if st_line:
|
||||||
so_obj = self.pool.get('sale.order')
|
so_obj = self.pool.get('sale.order')
|
||||||
so_id = so_obj.search(cursor, uid, [('name', '=', st_line.ref)])
|
so_id = so_obj.search(
|
||||||
|
cursor,
|
||||||
|
uid,
|
||||||
|
[('name', '=', st_line.ref)],
|
||||||
|
context=context)
|
||||||
if so_id:
|
if so_id:
|
||||||
if so_id and len(so_id) == 1:
|
if so_id and len(so_id) == 1:
|
||||||
so = so_obj.browse(cursor, uid, so_id[0])
|
so = so_obj.browse(cursor, uid, so_id[0], context=context)
|
||||||
res['partner_id'] = so.partner_id.id
|
res['partner_id'] = so.partner_id.id
|
||||||
elif so_id and len(so_id) > 1:
|
elif so_id and len(so_id) > 1:
|
||||||
raise ErrorTooManyPartner(_('Line named "%s" (Ref:%s) was matched by more than one partner.')%(st_line.name,st_line.ref))
|
raise ErrorTooManyPartner(
|
||||||
st_vals = st_obj.get_values_for_line(cursor, uid, profile_id = st_line.statement_id.profile_id.id,
|
_('Line named "%s" (Ref:%s) was matched by more '
|
||||||
partner_id = res.get('partner_id',False), line_type = st_line.type, amount = st_line.amount, context = context)
|
'than one partner.') %
|
||||||
|
(st_line.name, st_line.ref))
|
||||||
|
st_vals = st_obj.get_values_for_line(
|
||||||
|
cursor,
|
||||||
|
uid,
|
||||||
|
profile_id=st_line.statement_id.profile_id.id,
|
||||||
|
partner_id=res.get('partner_id', False),
|
||||||
|
line_type=st_line.type,
|
||||||
|
amount=st_line.amount,
|
||||||
|
context=context)
|
||||||
res.update(st_vals)
|
res.update(st_vals)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def get_from_label_and_partner_field(self, cursor, uid, line_id, context=None):
|
def get_from_label_and_partner_field(self, cursor, uid, line_id, context=None):
|
||||||
"""
|
"""
|
||||||
Match the partner based on the label field of the statement line
|
Match the partner based on the label field of the statement line
|
||||||
and the text defined in the 'bank_statement_label' field of the partner.
|
and the text defined in the 'bank_statement_label' field of the partner.
|
||||||
Remember that we can have values separated with ; Then, call the generic
|
Remember that we can have values separated with ; Then, call the generic
|
||||||
get_values_for_line method to complete other values.
|
get_values_for_line method to complete other values.
|
||||||
If more than one partner matched, raise the ErrorTooManyPartner error.
|
If more than one partner matched, raise the ErrorTooManyPartner error.
|
||||||
|
|
||||||
@@ -198,26 +225,39 @@ class AccountStatementCompletionRule(Model):
|
|||||||
the statement line or {}
|
the statement line or {}
|
||||||
{'partner_id': value,
|
{'partner_id': value,
|
||||||
'account_id' : value,
|
'account_id' : value,
|
||||||
|
|
||||||
...}
|
...}
|
||||||
"""
|
"""
|
||||||
partner_obj = self.pool.get('res.partner')
|
partner_obj = self.pool.get('res.partner')
|
||||||
st_obj = self.pool.get('account.bank.statement.line')
|
st_obj = self.pool.get('account.bank.statement.line')
|
||||||
st_line = st_obj.browse(cursor,uid,line_id)
|
st_line = st_obj.browse(cursor, uid, line_id, context=context)
|
||||||
res = {}
|
res = {}
|
||||||
compt = 0
|
compt = 0
|
||||||
if st_line:
|
if st_line:
|
||||||
ids = partner_obj.search(cursor, uid, [['bank_statement_label', '!=', False]], context=context)
|
ids = partner_obj.search(
|
||||||
|
cursor,
|
||||||
|
uid,
|
||||||
|
[('bank_statement_label', '!=', False)],
|
||||||
|
context=context)
|
||||||
for partner in partner_obj.browse(cursor, uid, ids, context=context):
|
for partner in partner_obj.browse(cursor, uid, ids, context=context):
|
||||||
for partner_label in partner.bank_statement_label.split(';'):
|
for partner_label in partner.bank_statement_label.split(';'):
|
||||||
if partner_label in st_line.label:
|
if partner_label in st_line.label:
|
||||||
compt += 1
|
compt += 1
|
||||||
res['partner_id'] = partner.id
|
res['partner_id'] = partner.id
|
||||||
if compt > 1:
|
if compt > 1:
|
||||||
raise ErrorTooManyPartner(_('Line named "%s" (Ref:%s) was matched by more than one partner.')%(st_line.name,st_line.ref))
|
raise ErrorTooManyPartner(
|
||||||
|
_('Line named "%s" (Ref:%s) was matched by '
|
||||||
|
'more than one partner.') %
|
||||||
|
(st_line.name, st_line.ref))
|
||||||
if res:
|
if res:
|
||||||
st_vals = st_obj.get_values_for_line(cursor, uid, profile_id = st_line.statement_id.profile_id.id,
|
st_vals = st_obj.get_values_for_line(
|
||||||
partner_id = res.get('partner_id',False), line_type = st_line.type, amount = st_line.amount, context = context)
|
cursor,
|
||||||
|
uid,
|
||||||
|
profile_id=st_line.statement_id.profile_id.id,
|
||||||
|
partner_id=res.get('partner_id', False),
|
||||||
|
line_type=st_line.type,
|
||||||
|
amount=st_line.amount,
|
||||||
|
context=context)
|
||||||
res.update(st_vals)
|
res.update(st_vals)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@@ -234,29 +274,38 @@ class AccountStatementCompletionRule(Model):
|
|||||||
the statement line or {}
|
the statement line or {}
|
||||||
{'partner_id': value,
|
{'partner_id': value,
|
||||||
'account_id' : value,
|
'account_id' : value,
|
||||||
|
|
||||||
...}
|
...}
|
||||||
"""
|
"""
|
||||||
# This Method has not been tested yet !
|
# This Method has not been tested yet !
|
||||||
res = {}
|
res = {}
|
||||||
st_obj = self.pool.get('account.bank.statement.line')
|
st_obj = self.pool.get('account.bank.statement.line')
|
||||||
st_line = st_obj.browse(cursor,uid,line_id)
|
st_line = st_obj.browse(cursor, uid, line_id, context=context)
|
||||||
if st_line:
|
if st_line:
|
||||||
sql = "SELECT id FROM res_partner WHERE name ~* %s"
|
sql = "SELECT id FROM res_partner WHERE name ~* %s"
|
||||||
pattern = ".*%s.*" % st_line.label
|
pattern = ".*%s.*" % st_line.label
|
||||||
cursor.execute(sql, (pattern,))
|
cursor.execute(sql, (pattern,))
|
||||||
result = cursor.fetchall()
|
result = cursor.fetchall()
|
||||||
if len(result) > 1:
|
if len(result) > 1:
|
||||||
raise ErrorTooManyPartner(_('Line named "%s" (Ref:%s) was matched by more than one partner.')%(st_line.name,st_line.ref))
|
raise ErrorTooManyPartner(
|
||||||
|
_('Line named "%s" (Ref:%s) was matched by more '
|
||||||
|
'than one partner.') %
|
||||||
|
(st_line.name, st_line.ref))
|
||||||
for id in result[0]:
|
for id in result[0]:
|
||||||
res['partner_id'] = id
|
res['partner_id'] = id
|
||||||
if res:
|
if res:
|
||||||
st_vals = st_obj.get_values_for_line(cursor, uid, profile_id = st_line.statement_id.profile_id.id,
|
st_vals = st_obj.get_values_for_line(
|
||||||
partner_id = res.get('partner_id',False), line_type = st_line.type, amount = st_line.amount, context = context)
|
cursor,
|
||||||
|
uid,
|
||||||
|
profile_id=st_line.statement_id.profile_id.id,
|
||||||
|
partner_id=res.get('partner_id', False),
|
||||||
|
line_type=st_line.type,
|
||||||
|
amount=st_line.amount,
|
||||||
|
context=context)
|
||||||
res.update(st_vals)
|
res.update(st_vals)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
class AccountStatementLine(Model):
|
class AccountStatementLine(Model):
|
||||||
"""
|
"""
|
||||||
Add sparse field on the statement line to allow to store all the
|
Add sparse field on the statement line to allow to store all the
|
||||||
@@ -268,22 +317,28 @@ class AccountStatementLine(Model):
|
|||||||
"""
|
"""
|
||||||
_inherit = "account.bank.statement.line"
|
_inherit = "account.bank.statement.line"
|
||||||
|
|
||||||
_columns={
|
_columns = {
|
||||||
'additionnal_bank_fields' : fields.serialized('Additionnal infos from bank',
|
'additionnal_bank_fields': fields.serialized(
|
||||||
help="Used by completion and import system. Adds every field that is present in your bank/office \
|
'Additionnal infos from bank',
|
||||||
statement file"),
|
help="Used by completion and import system. Adds every field that "
|
||||||
'label': fields.sparse(type='char', string='Label',
|
"is present in your bank/office statement file"),
|
||||||
serialization_field='additionnal_bank_fields',
|
'label': fields.sparse(
|
||||||
help="Generiy field to store a label given from the bank/office on which we can \
|
type='char',
|
||||||
base the default/standard providen rule."),
|
string='Label',
|
||||||
'already_completed': fields.boolean("Auto-Completed",
|
serialization_field='additionnal_bank_fields',
|
||||||
help="When this checkbox is ticked, the auto-completion process/button will ignore this line."),
|
help="Generic field to store a label given from the "
|
||||||
|
"bank/office on which we can base the default/standard "
|
||||||
|
"providen rule."),
|
||||||
|
'already_completed': fields.boolean(
|
||||||
|
"Auto-Completed",
|
||||||
|
help="When this checkbox is ticked, the auto-completion "
|
||||||
|
"process/button will ignore this line."),
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'already_completed': False,
|
'already_completed': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_line_values_from_rules(self, cr, uid, ids, context=None):
|
def get_line_values_from_rules(self, cr, uid, ids, context=None):
|
||||||
"""
|
"""
|
||||||
We'll try to find out the values related to the line based on rules setted on
|
We'll try to find out the values related to the line based on rules setted on
|
||||||
@@ -292,30 +347,38 @@ class AccountStatementLine(Model):
|
|||||||
:return:
|
:return:
|
||||||
A dict of dict value that can be passed directly to the write method of
|
A dict of dict value that can be passed directly to the write method of
|
||||||
the statement line or {}. The first dict has statement line ID as a key:
|
the statement line or {}. The first dict has statement line ID as a key:
|
||||||
{117009: {'partner_id': 100997, 'account_id': 489L}}
|
{117009: {'partner_id': 100997, 'account_id': 489L}}
|
||||||
"""
|
"""
|
||||||
profile_obj = self.pool.get('account.statement.profile')
|
profile_obj = self.pool.get('account.statement.profile')
|
||||||
st_obj = self.pool.get('account.bank.statement.line')
|
st_obj = self.pool.get('account.bank.statement.line')
|
||||||
res={}
|
res = {}
|
||||||
errors_stack = []
|
errors_stack = []
|
||||||
for line in self.browse(cr,uid, ids, context):
|
for line in self.browse(cr, uid, ids, context=context):
|
||||||
if not line.already_completed:
|
if line.already_completed:
|
||||||
try:
|
continue
|
||||||
# Take the default values
|
try:
|
||||||
res[line.id] = st_obj.get_values_for_line(cr, uid, profile_id = line.statement_id.profile_id.id,
|
# Take the default values
|
||||||
line_type = line.type, amount = line.amount, context = context)
|
res[line.id] = st_obj.get_values_for_line(
|
||||||
# Ask the rule
|
cr,
|
||||||
vals = profile_obj.find_values_from_rules(cr, uid, line.statement_id.profile_id.id, line.id, context)
|
uid,
|
||||||
# Merge the result
|
profile_id=line.statement_id.profile_id.id,
|
||||||
res[line.id].update(vals)
|
line_type=line.type,
|
||||||
except ErrorTooManyPartner, exc:
|
amount=line.amount,
|
||||||
msg = "Line ID %s had following error: %s" % (line.id, exc.value)
|
context=context)
|
||||||
errors_stack.append(msg)
|
# Ask the rule
|
||||||
|
vals = profile_obj.find_values_from_rules(
|
||||||
|
cr, uid, line.statement_id.profile_id.id, line.id, context)
|
||||||
|
# Merge the result
|
||||||
|
res[line.id].update(vals)
|
||||||
|
except ErrorTooManyPartner, exc:
|
||||||
|
msg = "Line ID %s had following error: %s" % (line.id, exc.value)
|
||||||
|
errors_stack.append(msg)
|
||||||
if errors_stack:
|
if errors_stack:
|
||||||
msg = u"\n".join(errors_stack)
|
msg = u"\n".join(errors_stack)
|
||||||
raise ErrorTooManyPartner(msg)
|
raise ErrorTooManyPartner(msg)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
class AccountBankSatement(Model):
|
class AccountBankSatement(Model):
|
||||||
"""
|
"""
|
||||||
We add a basic button and stuff to support the auto-completion
|
We add a basic button and stuff to support the auto-completion
|
||||||
@@ -326,41 +389,46 @@ class AccountBankSatement(Model):
|
|||||||
_columns = {
|
_columns = {
|
||||||
'completion_logs': fields.text('Completion Log', readonly=True),
|
'completion_logs': fields.text('Completion Log', readonly=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
def write_completion_log(self, cr, uid, stat_id, error_msg, number_imported, context=None):
|
def write_completion_log(self, cr, uid, stat_id, error_msg, number_imported, context=None):
|
||||||
"""
|
"""
|
||||||
Write the log in the completion_logs field of the bank statement to let the user
|
Write the log in the completion_logs field of the bank statement to let the user
|
||||||
know what have been done. This is an append mode, so we don't overwrite what
|
know what have been done. This is an append mode, so we don't overwrite what
|
||||||
already recoded.
|
already recoded.
|
||||||
|
|
||||||
:param int/long stat_id: ID of the account.bank.statement
|
:param int/long stat_id: ID of the account.bank.statement
|
||||||
:param char error_msg: Message to add
|
:param char error_msg: Message to add
|
||||||
:number_imported int/long: Number of lines that have been completed
|
:number_imported int/long: Number of lines that have been completed
|
||||||
:return : True
|
:return : True
|
||||||
|
|
||||||
"""
|
"""
|
||||||
error_log = ""
|
error_log = ""
|
||||||
user_name = self.pool.get('res.users').read(cr, uid, uid, ['name'])['name']
|
user_name = self.pool.get('res.users').read(
|
||||||
log = self.read(cr, uid, stat_id, ['completion_logs'], context=context)['completion_logs']
|
cr, uid, uid, ['name'], context=context)['name']
|
||||||
|
log = self.read(
|
||||||
|
cr, uid, stat_id, ['completion_logs'], context=context)['completion_logs']
|
||||||
log_line = log and log.split("\n") or []
|
log_line = log and log.split("\n") or []
|
||||||
completion_date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
completion_date = datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||||
if error_msg:
|
if error_msg:
|
||||||
error_log = error_msg
|
error_log = error_msg
|
||||||
log_line[0:0] = [completion_date + ' : '
|
log_line[0:0] = [completion_date + ' : '
|
||||||
+ _("Bank Statement ID %s has %s lines completed by %s") %(stat_id, number_imported, user_name)
|
+ _("Bank Statement ID %s has %s lines completed by %s") % (stat_id, number_imported, user_name)
|
||||||
+ "\n" + error_log + "-------------" + "\n"]
|
+ "\n" + error_log + "-------------" + "\n"]
|
||||||
log = "\n".join(log_line)
|
log = "\n".join(log_line)
|
||||||
self.write(cr, uid, [stat_id], {'completion_logs' : log}, context=context)
|
self.write(cr, uid, [stat_id], {'completion_logs': log}, context=context)
|
||||||
self.message_post(cr, uid, [stat_id], body=_('Statement ID %s auto-completed for %s lines completed') % (stat_id,number_imported), context=context)
|
self.message_post(
|
||||||
|
cr, uid,
|
||||||
|
[stat_id],
|
||||||
|
body=_('Statement ID %s auto-completed for %s lines completed') % (stat_id, number_imported),
|
||||||
|
context=context)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def button_auto_completion(self, cr, uid, ids, context=None):
|
def button_auto_completion(self, cr, uid, ids, context=None):
|
||||||
"""
|
"""
|
||||||
Complete line with values given by rules and tic the already_completed
|
Complete line with values given by rules and tic the already_completed
|
||||||
checkbox so we won't compute them again unless the user untick them !
|
checkbox so we won't compute them again unless the user untick them !
|
||||||
"""
|
"""
|
||||||
if not context:
|
if context is None:
|
||||||
context={}
|
context = {}
|
||||||
stat_line_obj = self.pool.get('account.bank.statement.line')
|
stat_line_obj = self.pool.get('account.bank.statement.line')
|
||||||
msg = ""
|
msg = ""
|
||||||
compl_lines = 0
|
compl_lines = 0
|
||||||
@@ -369,7 +437,8 @@ class AccountBankSatement(Model):
|
|||||||
for line in stat.line_ids:
|
for line in stat.line_ids:
|
||||||
res = {}
|
res = {}
|
||||||
try:
|
try:
|
||||||
res = stat_line_obj.get_line_values_from_rules(cr, uid, [line.id], context=ctx)
|
res = stat_line_obj.get_line_values_from_rules(
|
||||||
|
cr, uid, [line.id], context=ctx)
|
||||||
if res:
|
if res:
|
||||||
compl_lines += 1
|
compl_lines += 1
|
||||||
except ErrorTooManyPartner, exc:
|
except ErrorTooManyPartner, exc:
|
||||||
@@ -381,5 +450,6 @@ class AccountBankSatement(Model):
|
|||||||
vals = res[line.id]
|
vals = res[line.id]
|
||||||
vals['already_completed'] = True
|
vals['already_completed'] = True
|
||||||
stat_line_obj.write(cr, uid, [line.id], vals, context=ctx)
|
stat_line_obj.write(cr, uid, [line.id], vals, context=ctx)
|
||||||
self.write_completion_log(cr, uid, stat.id, msg, compl_lines, context=context)
|
self.write_completion_log(
|
||||||
|
cr, uid, stat.id, msg, compl_lines, context=context)
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -20,4 +20,4 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
import parser
|
import parser
|
||||||
import wizard
|
import wizard
|
||||||
import statement
|
import statement
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
'author': 'Camptocamp',
|
'author': 'Camptocamp',
|
||||||
'maintainer': 'Camptocamp',
|
'maintainer': 'Camptocamp',
|
||||||
'category': 'Finance',
|
'category': 'Finance',
|
||||||
'complexity': 'normal', #easy, normal, expert
|
'complexity': 'normal',
|
||||||
'depends': ['account_statement_ext','account_statement_base_completion'],
|
'depends': [
|
||||||
|
'account_statement_ext',
|
||||||
|
'account_statement_base_completion'
|
||||||
|
],
|
||||||
'description': """
|
'description': """
|
||||||
This module brings basic methods and fields on bank statement to deal with
|
This module brings basic methods and fields on bank statement to deal with
|
||||||
the importation of different bank and offices. A generic abstract method is defined and an
|
the importation of different bank and offices. A generic abstract method is defined and an
|
||||||
|
|||||||
@@ -22,4 +22,4 @@
|
|||||||
from parser import new_bank_statement_parser
|
from parser import new_bank_statement_parser
|
||||||
from parser import BankStatementImportParser
|
from parser import BankStatementImportParser
|
||||||
import file_parser
|
import file_parser
|
||||||
import generic_file_parser
|
import generic_file_parser
|
||||||
|
|||||||
@@ -28,17 +28,18 @@ try:
|
|||||||
except:
|
except:
|
||||||
raise Exception(_('Please install python lib xlrd'))
|
raise Exception(_('Please install python lib xlrd'))
|
||||||
|
|
||||||
|
|
||||||
class FileParser(BankStatementImportParser):
|
class FileParser(BankStatementImportParser):
|
||||||
"""
|
"""
|
||||||
Generic abstract class for defining parser for .csv or .xls file format.
|
Generic abstract class for defining parser for .csv or .xls file format.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parse_name, keys_to_validate=[], ftype='csv', convertion_dict=None, header=None, *args, **kwargs):
|
def __init__(self, parse_name, keys_to_validate=[], ftype='csv', convertion_dict=None, header=None, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
:param char: parse_name : The name of the parser
|
:param char: parse_name : The name of the parser
|
||||||
:param list: keys_to_validate : contain the key that need to be present in the file
|
:param list: keys_to_validate : contain the key that need to be present in the file
|
||||||
:param char ftype: extension of the file (could be csv or xls)
|
:param char ftype: extension of the file (could be csv or xls)
|
||||||
:param: convertion_dict : keys and type to convert of every column in the file like
|
:param: convertion_dict : keys and type to convert of every column in the file like
|
||||||
{
|
{
|
||||||
'ref': unicode,
|
'ref': unicode,
|
||||||
'label': unicode,
|
'label': unicode,
|
||||||
@@ -48,7 +49,7 @@ class FileParser(BankStatementImportParser):
|
|||||||
}
|
}
|
||||||
:param list: header : specify header fields if the csv file has no header
|
:param list: header : specify header fields if the csv file has no header
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super(FileParser, self).__init__(parse_name, *args, **kwargs)
|
super(FileParser, self).__init__(parse_name, *args, **kwargs)
|
||||||
if ftype in ('csv', 'xls'):
|
if ftype in ('csv', 'xls'):
|
||||||
self.ftype = ftype
|
self.ftype = ftype
|
||||||
@@ -57,9 +58,9 @@ class FileParser(BankStatementImportParser):
|
|||||||
self.keys_to_validate = keys_to_validate
|
self.keys_to_validate = keys_to_validate
|
||||||
self.convertion_dict = convertion_dict
|
self.convertion_dict = convertion_dict
|
||||||
self.fieldnames = header
|
self.fieldnames = header
|
||||||
self._datemode = 0 # used only for xls documents,
|
self._datemode = 0 # used only for xls documents,
|
||||||
# 0 means Windows mode (1900 based dates).
|
# 0 means Windows mode (1900 based dates).
|
||||||
# Set in _parse_xls, from the contents of the file
|
# Set in _parse_xls, from the contents of the file
|
||||||
|
|
||||||
def _custom_format(self, *args, **kwargs):
|
def _custom_format(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -78,7 +79,7 @@ class FileParser(BankStatementImportParser):
|
|||||||
Launch the parsing through .csv or .xls depending on the
|
Launch the parsing through .csv or .xls depending on the
|
||||||
given ftype
|
given ftype
|
||||||
"""
|
"""
|
||||||
|
|
||||||
res = None
|
res = None
|
||||||
if self.ftype == 'csv':
|
if self.ftype == 'csv':
|
||||||
res = self._parse_csv()
|
res = self._parse_csv()
|
||||||
@@ -108,7 +109,6 @@ class FileParser(BankStatementImportParser):
|
|||||||
self.result_row_list = self._cast_rows(*args, **kwargs)
|
self.result_row_list = self._cast_rows(*args, **kwargs)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _parse_csv(self):
|
def _parse_csv(self):
|
||||||
"""
|
"""
|
||||||
:return: list of dict from csv file (line/rows)
|
:return: list of dict from csv file (line/rows)
|
||||||
@@ -116,7 +116,7 @@ class FileParser(BankStatementImportParser):
|
|||||||
csv_file = tempfile.NamedTemporaryFile()
|
csv_file = tempfile.NamedTemporaryFile()
|
||||||
csv_file.write(self.filebuffer)
|
csv_file.write(self.filebuffer)
|
||||||
csv_file.flush()
|
csv_file.flush()
|
||||||
with open(csv_file.name, 'rU') as fobj:
|
with open(csv_file.name, 'rU') as fobj:
|
||||||
reader = UnicodeDictReader(fobj, fieldnames=self.fieldnames)
|
reader = UnicodeDictReader(fobj, fieldnames=self.fieldnames)
|
||||||
return list(reader)
|
return list(reader)
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ class FileParser(BankStatementImportParser):
|
|||||||
try:
|
try:
|
||||||
wb_file.close()
|
wb_file.close()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
pass #file is allready closed
|
pass # file is already closed
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _from_csv(self, result_set, conversion_rules):
|
def _from_csv(self, result_set, conversion_rules):
|
||||||
@@ -175,6 +175,6 @@ class FileParser(BankStatementImportParser):
|
|||||||
Convert the self.result_row_list using the self.convertion_dict providen.
|
Convert the self.result_row_list using the self.convertion_dict providen.
|
||||||
We call here _from_xls or _from_csv depending on the self.ftype variable.
|
We call here _from_xls or _from_csv depending on the self.ftype variable.
|
||||||
"""
|
"""
|
||||||
func = getattr(self, '_from_%s'%(self.ftype))
|
func = getattr(self, '_from_%s' % self.ftype)
|
||||||
res = func(self.result_row_list, self.convertion_dict)
|
res = func(self.result_row_list, self.convertion_dict)
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -23,20 +23,20 @@ import base64
|
|||||||
import csv
|
import csv
|
||||||
import tempfile
|
import tempfile
|
||||||
import datetime
|
import datetime
|
||||||
# from . import file_parser
|
|
||||||
from file_parser import FileParser
|
from file_parser import FileParser
|
||||||
try:
|
try:
|
||||||
import xlrd
|
import xlrd
|
||||||
except:
|
except:
|
||||||
raise Exception(_('Please install python lib xlrd'))
|
raise Exception(_('Please install python lib xlrd'))
|
||||||
|
|
||||||
|
|
||||||
class GenericFileParser(FileParser):
|
class GenericFileParser(FileParser):
|
||||||
"""
|
"""
|
||||||
Standard parser that use a define format in csv or xls to import into a
|
Standard parser that use a define format in csv or xls to import into a
|
||||||
bank statement. This is mostely an example of how to proceed to create a new
|
bank statement. This is mostely an example of how to proceed to create a new
|
||||||
parser, but will also be useful as it allow to import a basic flat file.
|
parser, but will also be useful as it allow to import a basic flat file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parse_name, ftype='csv'):
|
def __init__(self, parse_name, ftype='csv'):
|
||||||
convertion_dict = {
|
convertion_dict = {
|
||||||
'ref': unicode,
|
'ref': unicode,
|
||||||
@@ -47,7 +47,7 @@ class GenericFileParser(FileParser):
|
|||||||
}
|
}
|
||||||
# Order of cols does not matter but first row of the file has to be header
|
# Order of cols does not matter but first row of the file has to be header
|
||||||
keys_to_validate = ['ref', 'label', 'date', 'amount', 'commission_amount']
|
keys_to_validate = ['ref', 'label', 'date', 'amount', 'commission_amount']
|
||||||
super(GenericFileParser,self).__init__(parse_name, keys_to_validate=keys_to_validate, ftype=ftype, convertion_dict=convertion_dict)
|
super(GenericFileParser, self).__init__(parse_name, keys_to_validate=keys_to_validate, ftype=ftype, convertion_dict=convertion_dict)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parser_for(cls, parser_name):
|
def parser_for(cls, parser_name):
|
||||||
@@ -60,7 +60,7 @@ class GenericFileParser(FileParser):
|
|||||||
def get_st_line_vals(self, line, *args, **kwargs):
|
def get_st_line_vals(self, line, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
This method must return a dict of vals that can be passed to create
|
This method must return a dict of vals that can be passed to create
|
||||||
method of statement line in order to record it. It is the responsibility
|
method of statement line in order to record it. It is the responsibility
|
||||||
of every parser to give this dict of vals, so each one can implement his
|
of every parser to give this dict of vals, so each one can implement his
|
||||||
own way of recording the lines.
|
own way of recording the lines.
|
||||||
:param: line: a dict of vals that represent a line of result_row_list
|
:param: line: a dict of vals that represent a line of result_row_list
|
||||||
@@ -78,11 +78,11 @@ class GenericFileParser(FileParser):
|
|||||||
for each one.
|
for each one.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
'name': line.get('label', line.get('ref','/')),
|
'name': line.get('label', line.get('ref', '/')),
|
||||||
'date': line.get('date', datetime.datetime.now().date()),
|
'date': line.get('date', datetime.datetime.now().date()),
|
||||||
'amount': line.get('amount', 0.0),
|
'amount': line.get('amount', 0.0),
|
||||||
'ref': line.get('ref','/'),
|
'ref': line.get('ref', '/'),
|
||||||
'label': line.get('label',''),
|
'label': line.get('label', ''),
|
||||||
'commission_amount': line.get('commission_amount', 0.0),
|
'commission_amount': line.get('commission_amount', 0.0),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,10 +93,6 @@ class GenericFileParser(FileParser):
|
|||||||
res = super(GenericFileParser, self)._post(*args, **kwargs)
|
res = super(GenericFileParser, self)._post(*args, **kwargs)
|
||||||
val = 0.0
|
val = 0.0
|
||||||
for row in self.result_row_list:
|
for row in self.result_row_list:
|
||||||
val += row.get('commission_amount',0.0)
|
val += row.get('commission_amount', 0.0)
|
||||||
self.commission_global_amount = val
|
self.commission_global_amount = val
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
import base64
|
import base64
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
|
|
||||||
def UnicodeDictReader(utf8_data, **kwargs):
|
def UnicodeDictReader(utf8_data, **kwargs):
|
||||||
sniffer = csv.Sniffer()
|
sniffer = csv.Sniffer()
|
||||||
pos = utf8_data.tell()
|
pos = utf8_data.tell()
|
||||||
@@ -31,6 +32,7 @@ def UnicodeDictReader(utf8_data, **kwargs):
|
|||||||
for row in csv_reader:
|
for row in csv_reader:
|
||||||
yield dict([(key, unicode(value, 'utf-8')) for key, value in row.iteritems()])
|
yield dict([(key, unicode(value, 'utf-8')) for key, value in row.iteritems()])
|
||||||
|
|
||||||
|
|
||||||
class BankStatementImportParser(object):
|
class BankStatementImportParser(object):
|
||||||
"""
|
"""
|
||||||
Generic abstract class for defining parser for different files and
|
Generic abstract class for defining parser for different files and
|
||||||
@@ -38,7 +40,7 @@ class BankStatementImportParser(object):
|
|||||||
own. If your file is a .csv or .xls format, you should consider inheirt
|
own. If your file is a .csv or .xls format, you should consider inheirt
|
||||||
from the FileParser instead.
|
from the FileParser instead.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parser_name, *args, **kwargs):
|
def __init__(self, parser_name, *args, **kwargs):
|
||||||
# The name of the parser as it will be called
|
# The name of the parser as it will be called
|
||||||
self.parser_name = parser_name
|
self.parser_name = parser_name
|
||||||
@@ -50,7 +52,7 @@ class BankStatementImportParser(object):
|
|||||||
# Concatenate here the global commission taken by the bank/office
|
# Concatenate here the global commission taken by the bank/office
|
||||||
# for this statement.
|
# for this statement.
|
||||||
self.commission_global_amount = None
|
self.commission_global_amount = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parser_for(cls, parser_name):
|
def parser_for(cls, parser_name):
|
||||||
"""
|
"""
|
||||||
@@ -58,17 +60,17 @@ class BankStatementImportParser(object):
|
|||||||
return the good class from his name.
|
return the good class from his name.
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _decode_64b_stream(self):
|
def _decode_64b_stream(self):
|
||||||
"""
|
"""
|
||||||
Decode self.filebuffer in base 64 and override it
|
Decode self.filebuffer in base 64 and override it
|
||||||
"""
|
"""
|
||||||
self.filebuffer = base64.b64decode(self.filebuffer)
|
self.filebuffer = base64.b64decode(self.filebuffer)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _format(self, decode_base_64=True, **kwargs):
|
def _format(self, decode_base_64=True, **kwargs):
|
||||||
"""
|
"""
|
||||||
Decode into base 64 if asked and Format the given filebuffer by calling
|
Decode into base 64 if asked and Format the given filebuffer by calling
|
||||||
_custom_format method.
|
_custom_format method.
|
||||||
"""
|
"""
|
||||||
if decode_base_64:
|
if decode_base_64:
|
||||||
@@ -83,43 +85,40 @@ class BankStatementImportParser(object):
|
|||||||
"""
|
"""
|
||||||
return NotImplementedError
|
return NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
def _pre(self, *args, **kwargs):
|
def _pre(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Implement a method in your parser to make a pre-treatment on datas before parsing
|
Implement a method in your parser to make a pre-treatment on datas before parsing
|
||||||
them, like concatenate stuff, and so... Work on self.filebuffer
|
them, like concatenate stuff, and so... Work on self.filebuffer
|
||||||
"""
|
"""
|
||||||
return NotImplementedError
|
return NotImplementedError
|
||||||
|
|
||||||
def _parse(self, *args, **kwargs):
|
def _parse(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Implement a method in your parser to save the result of parsing self.filebuffer
|
Implement a method in your parser to save the result of parsing self.filebuffer
|
||||||
in self.result_row_list instance property.
|
in self.result_row_list instance property.
|
||||||
"""
|
"""
|
||||||
return NotImplementedError
|
return NotImplementedError
|
||||||
|
|
||||||
def _validate(self, *args, **kwargs):
|
def _validate(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Implement a method in your parser to validate the self.result_row_list instance
|
Implement a method in your parser to validate the self.result_row_list instance
|
||||||
property and raise an error if not valid.
|
property and raise an error if not valid.
|
||||||
"""
|
"""
|
||||||
return NotImplementedError
|
return NotImplementedError
|
||||||
|
|
||||||
def _post(self, *args, **kwargs):
|
def _post(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Implement a method in your parser to make some last changes on the result of parsing
|
Implement a method in your parser to make some last changes on the result of parsing
|
||||||
the datas, like converting dates, computing commission, ...
|
the datas, like converting dates, computing commission, ...
|
||||||
Work on self.result_row_list and put the commission global amount if any
|
Work on self.result_row_list and put the commission global amount if any
|
||||||
in the self.commission_global_amount one.
|
in the self.commission_global_amount one.
|
||||||
"""
|
"""
|
||||||
return NotImplementedError
|
return NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_st_line_vals(self, line, *args, **kwargs):
|
def get_st_line_vals(self, line, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Implement a method in your parser that must return a dict of vals that can be
|
Implement a method in your parser that must return a dict of vals that can be
|
||||||
passed to create method of statement line in order to record it. It is the responsibility
|
passed to create method of statement line in order to record it. It is the responsibility
|
||||||
of every parser to give this dict of vals, so each one can implement his
|
of every parser to give this dict of vals, so each one can implement his
|
||||||
own way of recording the lines.
|
own way of recording the lines.
|
||||||
:param: line: a dict of vals that represent a line of result_row_list
|
:param: line: a dict of vals that represent a line of result_row_list
|
||||||
@@ -133,17 +132,17 @@ class BankStatementImportParser(object):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
return NotImplementedError
|
return NotImplementedError
|
||||||
|
|
||||||
def get_st_line_commision(self, *args, **kwargs):
|
def get_st_line_commision(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
This is called by the importation method to create the commission line in
|
This is called by the importation method to create the commission line in
|
||||||
the bank statement. We will always create one line for the commission in the
|
the bank statement. We will always create one line for the commission in the
|
||||||
bank statement, but it could be computated from a value of each line, or given
|
bank statement, but it could be computated from a value of each line, or given
|
||||||
in a single line for the whole file.
|
in a single line for the whole file.
|
||||||
return: float of the whole commission (self.commission_global_amount)
|
return: float of the whole commission (self.commission_global_amount)
|
||||||
"""
|
"""
|
||||||
return self.commission_global_amount
|
return self.commission_global_amount
|
||||||
|
|
||||||
def parse(self, filebuffer, *args, **kwargs):
|
def parse(self, filebuffer, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
This will be the method that will be called by wizard, button and so
|
This will be the method that will be called by wizard, button and so
|
||||||
@@ -151,7 +150,7 @@ class BankStatementImportParser(object):
|
|||||||
that need to be define for each parser.
|
that need to be define for each parser.
|
||||||
Return:
|
Return:
|
||||||
[] of rows as {'key':value}
|
[] of rows as {'key':value}
|
||||||
|
|
||||||
Note: The row_list must contain only value that are present in the account.
|
Note: The row_list must contain only value that are present in the account.
|
||||||
bank.statement.line object !!!
|
bank.statement.line object !!!
|
||||||
"""
|
"""
|
||||||
@@ -165,7 +164,8 @@ class BankStatementImportParser(object):
|
|||||||
self._validate(*args, **kwargs)
|
self._validate(*args, **kwargs)
|
||||||
self._post(*args, **kwargs)
|
self._post(*args, **kwargs)
|
||||||
return self.result_row_list
|
return self.result_row_list
|
||||||
|
|
||||||
|
|
||||||
def itersubclasses(cls, _seen=None):
|
def itersubclasses(cls, _seen=None):
|
||||||
"""
|
"""
|
||||||
itersubclasses(cls)
|
itersubclasses(cls)
|
||||||
@@ -179,7 +179,7 @@ def itersubclasses(cls, _seen=None):
|
|||||||
>>> class C(A): pass
|
>>> class C(A): pass
|
||||||
>>> class D(B,C): pass
|
>>> class D(B,C): pass
|
||||||
>>> class E(D): pass
|
>>> class E(D): pass
|
||||||
>>>
|
>>>
|
||||||
>>> for cls in itersubclasses(A):
|
>>> for cls in itersubclasses(A):
|
||||||
... print(cls.__name__)
|
... print(cls.__name__)
|
||||||
B
|
B
|
||||||
@@ -193,10 +193,11 @@ def itersubclasses(cls, _seen=None):
|
|||||||
if not isinstance(cls, type):
|
if not isinstance(cls, type):
|
||||||
raise TypeError('itersubclasses must be called with '
|
raise TypeError('itersubclasses must be called with '
|
||||||
'new-style classes, not %.100r' % cls)
|
'new-style classes, not %.100r' % cls)
|
||||||
if _seen is None: _seen = set()
|
if _seen is None:
|
||||||
|
_seen = set()
|
||||||
try:
|
try:
|
||||||
subs = cls.__subclasses__()
|
subs = cls.__subclasses__()
|
||||||
except TypeError: # fails only when cls is type
|
except TypeError: # fails only when cls is type
|
||||||
subs = cls.__subclasses__(cls)
|
subs = cls.__subclasses__(cls)
|
||||||
for sub in subs:
|
for sub in subs:
|
||||||
if sub not in _seen:
|
if sub not in _seen:
|
||||||
@@ -204,7 +205,8 @@ def itersubclasses(cls, _seen=None):
|
|||||||
yield sub
|
yield sub
|
||||||
for sub in itersubclasses(sub, _seen):
|
for sub in itersubclasses(sub, _seen):
|
||||||
yield sub
|
yield sub
|
||||||
|
|
||||||
|
|
||||||
def new_bank_statement_parser(parser_name, *args, **kwargs):
|
def new_bank_statement_parser(parser_name, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Return an instance of the good parser class base on the providen name
|
Return an instance of the good parser class base on the providen name
|
||||||
@@ -215,4 +217,3 @@ def new_bank_statement_parser(parser_name, *args, **kwargs):
|
|||||||
if cls.parser_for(parser_name):
|
if cls.parser_for(parser_name):
|
||||||
return cls(parser_name, *args, **kwargs)
|
return cls(parser_name, *args, **kwargs)
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
|||||||
@@ -21,61 +21,67 @@
|
|||||||
|
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
import datetime
|
import datetime
|
||||||
import netsvc
|
|
||||||
logger = netsvc.Logger()
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields, osv
|
||||||
from parser import new_bank_statement_parser
|
from parser import new_bank_statement_parser
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
class AccountStatementProfil(Model):
|
class AccountStatementProfil(Model):
|
||||||
_inherit = "account.statement.profile"
|
_inherit = "account.statement.profile"
|
||||||
|
|
||||||
|
|
||||||
def get_import_type_selection(self, cr, uid, context=None):
|
def get_import_type_selection(self, cr, uid, context=None):
|
||||||
"""
|
"""
|
||||||
Has to be inherited to add parser
|
Has to be inherited to add parser
|
||||||
"""
|
"""
|
||||||
return [('generic_csvxls_so', 'Generic .csv/.xls based on SO Name')]
|
return [('generic_csvxls_so', 'Generic .csv/.xls based on SO Name')]
|
||||||
|
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'launch_import_completion': fields.boolean("Launch completion after import",
|
'launch_import_completion': fields.boolean(
|
||||||
help="Tic that box to automatically launch the completion on each imported\
|
"Launch completion after import",
|
||||||
file using this profile."),
|
help="Tic that box to automatically launch the completion "
|
||||||
|
"on each imported file using this profile."),
|
||||||
'last_import_date': fields.datetime("Last Import Date"),
|
'last_import_date': fields.datetime("Last Import Date"),
|
||||||
'rec_log': fields.text('log', readonly=True),
|
'rec_log': fields.text('log', readonly=True),
|
||||||
'import_type': fields.selection(get_import_type_selection, 'Type of import', required=True,
|
'import_type': fields.selection(
|
||||||
help = "Choose here the method by which you want to import bank statement for this profile."),
|
get_import_type_selection,
|
||||||
|
'Type of import',
|
||||||
|
required=True,
|
||||||
|
help="Choose here the method by which you want to import bank"
|
||||||
|
"statement for this profile."),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def write_logs_after_import(self, cr, uid, ids, statement_id, num_lines, context):
|
def write_logs_after_import(self, cr, uid, ids, statement_id, num_lines, context):
|
||||||
"""
|
"""
|
||||||
Write the log in the logger + in the log field of the profile to report the user about
|
Write the log in the logger + in the log field of the profile to report the user about
|
||||||
what has been done.
|
what has been done.
|
||||||
|
|
||||||
:param int/long statement_id: ID of the concerned account.bank.statement
|
:param int/long statement_id: ID of the concerned account.bank.statement
|
||||||
:param int/long num_lines: Number of line that have been parsed
|
:param int/long num_lines: Number of line that have been parsed
|
||||||
:return: True
|
:return: True
|
||||||
"""
|
"""
|
||||||
if type(ids) is int:
|
if isinstance(ids, (int, long)):
|
||||||
ids = [ids]
|
ids = [ids]
|
||||||
for id in ids:
|
for id in ids:
|
||||||
log = self.read(cr, uid, id, ['rec_log'], context=context)['rec_log']
|
log = self.read(cr, uid, id, ['rec_log'], context=context)['rec_log']
|
||||||
log_line = log and log.split("\n") or []
|
log_line = log and log.split("\n") or []
|
||||||
import_date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
import_date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
log_line[0:0] = [import_date + ' : '
|
log_line[0:0] = [import_date + ' : '
|
||||||
+ _("Bank Statement ID %s have been imported with %s lines ") %(statement_id, num_lines)]
|
+ _("Bank Statement ID %s have been imported with %s lines ") % (statement_id, num_lines)]
|
||||||
log = "\n".join(log_line)
|
log = "\n".join(log_line)
|
||||||
self.write(cr, uid, id, {'rec_log' : log, 'last_import_date':import_date}, context=context)
|
self.write(cr, uid, id, {'rec_log': log, 'last_import_date': import_date}, context=context)
|
||||||
self.message_post(cr, uid, [statement_id], body=_('Statement ID %s have been imported with %s lines.')
|
self.message_post(
|
||||||
% (statement_id,num_lines), context=context)
|
cr,
|
||||||
|
uid,
|
||||||
|
[statement_id],
|
||||||
|
body=_('Statement ID %s have been imported with %s lines.') % (statement_id, num_lines),
|
||||||
|
context=context)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def prepare_global_commission_line_vals(self, cr, uid, parser,
|
def prepare_global_commission_line_vals(
|
||||||
result_row_list, profile, statement_id, context):
|
self, cr, uid, parser, result_row_list, profile, statement_id, context):
|
||||||
"""
|
"""
|
||||||
Prepare the global commission line if there is one. The global
|
Prepare the global commission line if there is one. The global
|
||||||
commission is computed by by calling the get_st_line_commision
|
commission is computed by by calling the get_st_line_commision
|
||||||
@@ -94,9 +100,8 @@ class AccountStatementProfil(Model):
|
|||||||
partner_id = profile.partner_id and profile.partner_id.id or False
|
partner_id = profile.partner_id and profile.partner_id.id or False
|
||||||
commission_account_id = profile.commission_account_id and profile.commission_account_id.id or False
|
commission_account_id = profile.commission_account_id and profile.commission_account_id.id or False
|
||||||
commission_analytic_id = profile.commission_analytic_id and profile.commission_analytic_id.id or False
|
commission_analytic_id = profile.commission_analytic_id and profile.commission_analytic_id.id or False
|
||||||
statement_line_obj = self.pool.get('account.bank.statement.line')
|
|
||||||
comm_values = {
|
comm_values = {
|
||||||
'name': 'IN '+ _('Commission line'),
|
'name': 'IN ' + _('Commission line'),
|
||||||
'date': datetime.datetime.now().date(),
|
'date': datetime.datetime.now().date(),
|
||||||
'amount': parser.get_st_line_commision(),
|
'amount': parser.get_st_line_commision(),
|
||||||
'partner_id': partner_id,
|
'partner_id': partner_id,
|
||||||
@@ -109,15 +114,16 @@ class AccountStatementProfil(Model):
|
|||||||
'already_completed': True,
|
'already_completed': True,
|
||||||
}
|
}
|
||||||
return comm_values
|
return comm_values
|
||||||
|
|
||||||
def prepare_statetement_lines_vals(self, cursor, uid, parser_vals,
|
def prepare_statetement_lines_vals(
|
||||||
account_payable, account_receivable, statement_id, context):
|
self, cursor, uid, parser_vals, account_payable, account_receivable,
|
||||||
|
statement_id, context):
|
||||||
"""
|
"""
|
||||||
Hook to build the values of a line from the parser returned values. At
|
Hook to build the values of a line from the parser returned values. At
|
||||||
least it fullfill the statement_id and account_id. Overide it to add your
|
least it fullfill the statement_id and account_id. Overide it to add your
|
||||||
own completion if needed.
|
own completion if needed.
|
||||||
|
|
||||||
:param dict of vals from parser for account.bank.statement.line (called by
|
:param dict of vals from parser for account.bank.statement.line (called by
|
||||||
parser.get_st_line_vals)
|
parser.get_st_line_vals)
|
||||||
:param int/long account_payable: ID of the receivable account to use
|
:param int/long account_payable: ID of the receivable account to use
|
||||||
:param int/long account_receivable: ID of the payable account to use
|
:param int/long account_receivable: ID of the payable account to use
|
||||||
@@ -126,7 +132,7 @@ class AccountStatementProfil(Model):
|
|||||||
"""
|
"""
|
||||||
statement_obj = self.pool.get('account.bank.statement')
|
statement_obj = self.pool.get('account.bank.statement')
|
||||||
values = parser_vals
|
values = parser_vals
|
||||||
values['statement_id']= statement_id
|
values['statement_id'] = statement_id
|
||||||
values['account_id'] = statement_obj.get_account_for_counterpart(
|
values['account_id'] = statement_obj.get_account_for_counterpart(
|
||||||
cursor,
|
cursor,
|
||||||
uid,
|
uid,
|
||||||
@@ -135,7 +141,7 @@ class AccountStatementProfil(Model):
|
|||||||
account_payable
|
account_payable
|
||||||
)
|
)
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def statement_import(self, cursor, uid, ids, profile_id, file_stream, ftype="csv", context=None):
|
def statement_import(self, cursor, uid, ids, profile_id, file_stream, ftype="csv", context=None):
|
||||||
"""
|
"""
|
||||||
Create a bank statement with the given profile and parser. It will fullfill the bank statement
|
Create a bank statement with the given profile and parser. It will fullfill the bank statement
|
||||||
@@ -143,13 +149,12 @@ class AccountStatementProfil(Model):
|
|||||||
the right account). This will be done in a second step with the completion rules.
|
the right account). This will be done in a second step with the completion rules.
|
||||||
It will also create the commission line if it apply and record the providen file as
|
It will also create the commission line if it apply and record the providen file as
|
||||||
an attachement of the bank statement.
|
an attachement of the bank statement.
|
||||||
|
|
||||||
:param int/long profile_id: ID of the profile used to import the file
|
:param int/long profile_id: ID of the profile used to import the file
|
||||||
:param filebuffer file_stream: binary of the providen file
|
:param filebuffer file_stream: binary of the providen file
|
||||||
:param char: ftype represent the file exstension (csv by default)
|
:param char: ftype represent the file exstension (csv by default)
|
||||||
:return: ID of the created account.bank.statemênt
|
:return: ID of the created account.bank.statemênt
|
||||||
"""
|
"""
|
||||||
context = context or {}
|
|
||||||
statement_obj = self.pool.get('account.bank.statement')
|
statement_obj = self.pool.get('account.bank.statement')
|
||||||
statement_line_obj = self.pool.get('account.bank.statement.line')
|
statement_line_obj = self.pool.get('account.bank.statement.line')
|
||||||
attachment_obj = self.pool.get('ir.attachment')
|
attachment_obj = self.pool.get('ir.attachment')
|
||||||
@@ -158,8 +163,8 @@ class AccountStatementProfil(Model):
|
|||||||
raise osv.except_osv(
|
raise osv.except_osv(
|
||||||
_("No Profile !"),
|
_("No Profile !"),
|
||||||
_("You must provide a valid profile to import a bank statement !"))
|
_("You must provide a valid profile to import a bank statement !"))
|
||||||
prof = prof_obj.browse(cursor,uid,profile_id,context)
|
prof = prof_obj.browse(cursor, uid, profile_id, context=context)
|
||||||
|
|
||||||
parser = new_bank_statement_parser(prof.import_type, ftype=ftype)
|
parser = new_bank_statement_parser(prof.import_type, ftype=ftype)
|
||||||
result_row_list = parser.parse(file_stream)
|
result_row_list = parser.parse(file_stream)
|
||||||
# Check all key are present in account.bank.statement.line !!
|
# Check all key are present in account.bank.statement.line !!
|
||||||
@@ -168,55 +173,60 @@ class AccountStatementProfil(Model):
|
|||||||
if col not in statement_line_obj._columns:
|
if col not in statement_line_obj._columns:
|
||||||
raise osv.except_osv(
|
raise osv.except_osv(
|
||||||
_("Missing column !"),
|
_("Missing column !"),
|
||||||
_("Column %s you try to import is not present in the bank statement line !") %(col))
|
_("Column %s you try to import is not "
|
||||||
|
"present in the bank statement line !") % col)
|
||||||
statement_id = statement_obj.create(cursor,uid,{'profile_id':prof.id,},context)
|
|
||||||
account_receivable, account_payable = statement_obj.get_default_pay_receiv_accounts(cursor, uid, context)
|
statement_id = statement_obj.create(
|
||||||
|
cursor, uid, {'profile_id': prof.id}, context=context)
|
||||||
|
account_receivable, account_payable = statement_obj.get_default_pay_receiv_accounts(
|
||||||
|
cursor, uid, context)
|
||||||
try:
|
try:
|
||||||
# Record every line in the bank statement and compute the global commission
|
# Record every line in the bank statement and compute the global commission
|
||||||
# based on the commission_amount column
|
# based on the commission_amount column
|
||||||
for line in result_row_list:
|
for line in result_row_list:
|
||||||
parser_vals = parser.get_st_line_vals(line)
|
parser_vals = parser.get_st_line_vals(line)
|
||||||
values = self.prepare_statetement_lines_vals(cursor, uid, parser_vals, account_payable,
|
values = self.prepare_statetement_lines_vals(
|
||||||
account_receivable, statement_id, context)
|
cursor, uid, parser_vals, account_payable,
|
||||||
|
account_receivable, statement_id, context)
|
||||||
# we finally create the line in system
|
# we finally create the line in system
|
||||||
statement_line_obj.create(cursor, uid, values, context=context)
|
statement_line_obj.create(cursor, uid, values, context=context)
|
||||||
# Build and create the global commission line for the whole statement
|
# Build and create the global commission line for the whole statement
|
||||||
comm_vals = self.prepare_global_commission_line_vals(cursor, uid, parser, result_row_list, prof, statement_id, context)
|
comm_vals = self.prepare_global_commission_line_vals(
|
||||||
|
cursor, uid, parser, result_row_list, prof, statement_id, context)
|
||||||
if comm_vals:
|
if comm_vals:
|
||||||
res = statement_line_obj.create(cursor, uid, comm_vals,context=context)
|
statement_line_obj.create(cursor, uid, comm_vals, context=context)
|
||||||
|
|
||||||
attachment_obj.create(
|
attachment_obj.create(
|
||||||
cursor,
|
cursor,
|
||||||
uid,
|
uid,
|
||||||
{
|
{
|
||||||
'name': 'statement file',
|
'name': 'statement file',
|
||||||
'datas': file_stream,
|
'datas': file_stream,
|
||||||
'datas_fname': "%s.%s"%(datetime.datetime.now().date(),
|
'datas_fname': "%s.%s" % (
|
||||||
ftype),
|
datetime.datetime.now().date(),
|
||||||
|
ftype),
|
||||||
'res_model': 'account.bank.statement',
|
'res_model': 'account.bank.statement',
|
||||||
'res_id': statement_id,
|
'res_id': statement_id,
|
||||||
},
|
},
|
||||||
context=context
|
context=context
|
||||||
)
|
)
|
||||||
# If user ask to launch completion at end of import, do it !
|
# If user ask to launch completion at end of import, do it !
|
||||||
if prof.launch_import_completion:
|
if prof.launch_import_completion:
|
||||||
statement_obj.button_auto_completion(cursor, uid, [statement_id], context)
|
statement_obj.button_auto_completion(cursor, uid, [statement_id], context)
|
||||||
|
|
||||||
# Write the needed log infos on profile
|
# Write the needed log infos on profile
|
||||||
self.write_logs_after_import(cursor, uid, prof.id, statement_id,
|
self.write_logs_after_import(
|
||||||
len(result_row_list), context)
|
cursor, uid, prof.id, statement_id, len(result_row_list), context)
|
||||||
|
|
||||||
except Exception, exc:
|
except Exception:
|
||||||
statement_obj.unlink(cursor, uid, [statement_id])
|
statement_obj.unlink(cursor, uid, [statement_id], context=context)
|
||||||
error_type, error_value, trbk = sys.exc_info()
|
error_type, error_value, trbk = sys.exc_info()
|
||||||
st = "Error: %s\nDescription: %s\nTraceback:" % (error_type.__name__, error_value)
|
st = "Error: %s\nDescription: %s\nTraceback:" % (error_type.__name__, error_value)
|
||||||
st += ''.join(traceback.format_tb(trbk, 30))
|
st += ''.join(traceback.format_tb(trbk, 30))
|
||||||
raise osv.except_osv(
|
raise osv.except_osv(
|
||||||
_("Statement import error"),
|
_("Statement import error"),
|
||||||
_("The statement cannot be created : %s") %(st))
|
_("The statement cannot be created : %s") % st)
|
||||||
return statement_id
|
return statement_id
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AccountStatementLine(Model):
|
class AccountStatementLine(Model):
|
||||||
@@ -227,8 +237,9 @@ class AccountStatementLine(Model):
|
|||||||
"""
|
"""
|
||||||
_inherit = "account.bank.statement.line"
|
_inherit = "account.bank.statement.line"
|
||||||
|
|
||||||
_columns={
|
_columns = {
|
||||||
'commission_amount': fields.sparse(type='float', string='Line Commission Amount',
|
'commission_amount': fields.sparse(
|
||||||
|
type='float',
|
||||||
|
string='Line Commission Amount',
|
||||||
serialization_field='additionnal_bank_fields'),
|
serialization_field='additionnal_bank_fields'),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,17 +23,18 @@
|
|||||||
Wizard to import financial institute date in bank statement
|
Wizard to import financial institute date in bank statement
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from openerp.osv import osv, orm
|
from openerp.osv import orm, fields
|
||||||
from openerp.osv import fields, osv
|
|
||||||
|
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
class CreditPartnerStatementImporter(orm.TransientModel):
|
class CreditPartnerStatementImporter(orm.TransientModel):
|
||||||
_name = "credit.statement.import"
|
_name = "credit.statement.import"
|
||||||
|
|
||||||
def default_get(self, cr, uid, fields, context=None):
|
def default_get(self, cr, uid, fields, context=None):
|
||||||
if context is None: context = {}
|
if context is None:
|
||||||
|
context = {}
|
||||||
res = {}
|
res = {}
|
||||||
if (context.get('active_model', False) == 'account.statement.profile' and
|
if (context.get('active_model', False) == 'account.statement.profile' and
|
||||||
context.get('active_ids', False)):
|
context.get('active_ids', False)):
|
||||||
@@ -41,55 +42,56 @@ class CreditPartnerStatementImporter(orm.TransientModel):
|
|||||||
assert len(ids) == 1, 'You cannot use this on more than one profile !'
|
assert len(ids) == 1, 'You cannot use this on more than one profile !'
|
||||||
res['profile_id'] = ids[0]
|
res['profile_id'] = ids[0]
|
||||||
other_vals = self.onchange_profile_id(cr, uid, [], res['profile_id'], context=context)
|
other_vals = self.onchange_profile_id(cr, uid, [], res['profile_id'], context=context)
|
||||||
res.update(other_vals.get('value',{}))
|
res.update(other_vals.get('value', {}))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'profile_id': fields.many2one('account.statement.profile',
|
'profile_id': fields.many2one('account.statement.profile',
|
||||||
'Import configuration parameter',
|
'Import configuration parameter',
|
||||||
required=True),
|
required=True),
|
||||||
'input_statement': fields.binary('Statement file', required=True),
|
'input_statement': fields.binary('Statement file', required=True),
|
||||||
'partner_id': fields.many2one('res.partner',
|
'partner_id': fields.many2one('res.partner',
|
||||||
'Credit insitute partner',
|
'Credit insitute partner'),
|
||||||
),
|
|
||||||
'journal_id': fields.many2one('account.journal',
|
'journal_id': fields.many2one('account.journal',
|
||||||
'Financial journal to use transaction',
|
'Financial journal to use transaction'),
|
||||||
),
|
|
||||||
'input_statement': fields.binary('Statement file', required=True),
|
|
||||||
'file_name': fields.char('File Name', size=128),
|
'file_name': fields.char('File Name', size=128),
|
||||||
'commission_account_id': fields.many2one('account.account',
|
'commission_account_id': fields.many2one('account.account',
|
||||||
'Commission account',
|
'Commission account'),
|
||||||
),
|
|
||||||
'commission_analytic_id': fields.many2one('account.analytic.account',
|
'commission_analytic_id': fields.many2one('account.analytic.account',
|
||||||
'Commission analytic account',
|
'Commission analytic account'),
|
||||||
),
|
|
||||||
'receivable_account_id': fields.many2one('account.account',
|
'receivable_account_id': fields.many2one('account.account',
|
||||||
'Force Receivable/Payable Account'),
|
'Force Receivable/Payable Account'),
|
||||||
'force_partner_on_bank': fields.boolean('Force partner on bank move',
|
'force_partner_on_bank': fields.boolean(
|
||||||
help="Tic that box if you want to use the credit insitute partner\
|
'Force partner on bank move',
|
||||||
in the counterpart of the treasury/banking move."
|
help="Tic that box if you want to use the credit insitute partner "
|
||||||
),
|
"in the counterpart of the treasury/banking move."),
|
||||||
'balance_check': fields.boolean('Balance check',
|
'balance_check': fields.boolean(
|
||||||
help="Tic that box if you want OpenERP to control the start/end balance\
|
'Balance check',
|
||||||
before confirming a bank statement. If don't ticked, no balance control will be done."
|
help="Tic that box if you want OpenERP to control the "
|
||||||
),
|
"start/end balance before confirming a bank statement. "
|
||||||
}
|
"If don't ticked, no balance control will be done."),
|
||||||
|
}
|
||||||
|
|
||||||
def onchange_profile_id(self, cr, uid, ids, profile_id, context=None):
|
def onchange_profile_id(self, cr, uid, ids, profile_id, context=None):
|
||||||
res={}
|
res = {}
|
||||||
if profile_id:
|
if profile_id:
|
||||||
c = self.pool.get("account.statement.profile").browse(cr,uid,profile_id)
|
c = self.pool.get("account.statement.profile").browse(
|
||||||
res = {'value': {'partner_id': c.partner_id and c.partner_id.id or False,
|
cr, uid, profile_id, context=context)
|
||||||
'journal_id': c.journal_id and c.journal_id.id or False, 'commission_account_id': \
|
res = {'value':
|
||||||
c.commission_account_id and c.commission_account_id.id or False,
|
{'partner_id': c.partner_id and c.partner_id.id or False,
|
||||||
'receivable_account_id': c.receivable_account_id and c.receivable_account_id.id or False,
|
'journal_id': c.journal_id and c.journal_id.id or False,
|
||||||
'commission_a':c.commission_analytic_id and c.commission_analytic_id.id or False,
|
'commission_account_id':
|
||||||
'force_partner_on_bank':c.force_partner_on_bank,
|
c.commission_account_id and c.commission_account_id.id or False,
|
||||||
'balance_check':c.balance_check,}}
|
'receivable_account_id': c.receivable_account_id and c.receivable_account_id.id or False,
|
||||||
|
'commission_a': c.commission_analytic_id and c.commission_analytic_id.id or False,
|
||||||
|
'force_partner_on_bank': c.force_partner_on_bank,
|
||||||
|
'balance_check': c.balance_check,
|
||||||
|
}
|
||||||
|
}
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _check_extension(self, filename):
|
def _check_extension(self, filename):
|
||||||
(shortname, ftype) = os.path.splitext(filename)
|
(__, ftype) = os.path.splitext(filename)
|
||||||
if not ftype:
|
if not ftype:
|
||||||
#We do not use osv exception we do not want to have it logged
|
#We do not use osv exception we do not want to have it logged
|
||||||
raise Exception(_('Please use a file with an extention'))
|
raise Exception(_('Please use a file with an extention'))
|
||||||
@@ -109,7 +111,7 @@ class CreditPartnerStatementImporter(orm.TransientModel):
|
|||||||
False,
|
False,
|
||||||
importer.profile_id.id,
|
importer.profile_id.id,
|
||||||
importer.input_statement,
|
importer.input_statement,
|
||||||
ftype.replace('.',''),
|
ftype.replace('.', ''),
|
||||||
context=context
|
context=context
|
||||||
)
|
)
|
||||||
model_obj = self.pool.get('ir.model.data')
|
model_obj = self.pool.get('ir.model.data')
|
||||||
|
|||||||
@@ -18,4 +18,3 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
'author': 'Camptocamp',
|
'author': 'Camptocamp',
|
||||||
'maintainer': 'Camptocamp',
|
'maintainer': 'Camptocamp',
|
||||||
'category': 'Finance',
|
'category': 'Finance',
|
||||||
'complexity': 'normal', #easy, normal, expert
|
'complexity': 'normal',
|
||||||
'depends': ['account_statement_base_completion','account_voucher'],
|
'depends': [
|
||||||
|
'account_statement_base_completion',
|
||||||
|
'account_voucher'
|
||||||
|
],
|
||||||
'description': """
|
'description': """
|
||||||
This module is only needed when using account_statement_base_completion with voucher in order adapt the view correctly.
|
This module is only needed when using account_statement_base_completion with voucher in order adapt the view correctly.
|
||||||
""",
|
""",
|
||||||
|
|||||||
@@ -21,4 +21,4 @@
|
|||||||
|
|
||||||
import statement
|
import statement
|
||||||
import report
|
import report
|
||||||
import account
|
import account
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
'author': 'Camptocamp',
|
'author': 'Camptocamp',
|
||||||
'maintainer': 'Camptocamp',
|
'maintainer': 'Camptocamp',
|
||||||
'category': 'Finance',
|
'category': 'Finance',
|
||||||
'complexity': 'normal', #easy, normal, expert
|
'complexity': 'normal',
|
||||||
'depends': ['account','report_webkit'],
|
'depends': [
|
||||||
|
'account',
|
||||||
|
'report_webkit'
|
||||||
|
],
|
||||||
'description': """
|
'description': """
|
||||||
Improve the basic bank statement, by adding various new features,
|
Improve the basic bank statement, by adding various new features,
|
||||||
and help dealing with huge volume of reconciliation through payment offices such as Paypal, Lazer,
|
and help dealing with huge volume of reconciliation through payment offices such as Paypal, Lazer,
|
||||||
|
|||||||
@@ -20,12 +20,12 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields
|
||||||
|
|
||||||
|
|
||||||
class account_move(Model):
|
class account_move(Model):
|
||||||
_inherit='account.move'
|
_inherit = 'account.move'
|
||||||
|
|
||||||
def unlink(self, cr, uid, ids, context=None):
|
def unlink(self, cr, uid, ids, context=None):
|
||||||
"""
|
"""
|
||||||
Delete the reconciliation when we delete the moves. This
|
Delete the reconciliation when we delete the moves. This
|
||||||
@@ -36,6 +36,3 @@ class account_move(Model):
|
|||||||
if move_line.reconcile_id:
|
if move_line.reconcile_id:
|
||||||
move_line.reconcile_id.unlink(context=context)
|
move_line.reconcile_id.unlink(context=context)
|
||||||
return super(account_move, self).unlink(cr, uid, ids, context=context)
|
return super(account_move, self).unlink(cr, uid, ids, context=context)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
|
||||||
# __init__.py
|
|
||||||
#
|
|
||||||
# Copyright (c) 2009 CamptoCamp. All rights reserved.
|
|
||||||
##############################################################################
|
|
||||||
#
|
#
|
||||||
# WARNING: This program as such is intended to be used by professional
|
# WARNING: This program as such is intended to be used by professional
|
||||||
# programmers who take the whole responsability of assessing all potential
|
# programmers who take the whole responsability of assessing all potential
|
||||||
@@ -28,4 +23,4 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import bank_statement_report
|
import bank_statement_report
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- coding utf-8 -*-
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
# Author: Nicolas Bessi. Copyright Camptocamp SA
|
# Author: Nicolas Bessi. Copyright Camptocamp SA
|
||||||
@@ -18,16 +18,13 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import time
|
from openerp.report import report_sxw
|
||||||
|
|
||||||
from report import report_sxw
|
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
import pooler
|
from openerp import pooler
|
||||||
from operator import add, itemgetter
|
|
||||||
from itertools import groupby
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from report_webkit import webkit_report
|
from report_webkit import webkit_report
|
||||||
|
|
||||||
|
|
||||||
class BankStatementWebkit(report_sxw.rml_parse):
|
class BankStatementWebkit(report_sxw.rml_parse):
|
||||||
|
|
||||||
def __init__(self, cursor, uid, name, context):
|
def __init__(self, cursor, uid, name, context):
|
||||||
@@ -35,15 +32,15 @@ class BankStatementWebkit(report_sxw.rml_parse):
|
|||||||
self.pool = pooler.get_pool(self.cr.dbname)
|
self.pool = pooler.get_pool(self.cr.dbname)
|
||||||
self.cursor = self.cr
|
self.cursor = self.cr
|
||||||
|
|
||||||
company = self.pool.get('res.users').browse(self.cr, uid, uid, context=context).company_id
|
company = self.pool.get('res.users').browse(
|
||||||
|
self.cr, uid, uid, context=context).company_id
|
||||||
header_report_name = ' - '.join((_('BORDEREAU DE REMISE DE CHEQUES'),
|
header_report_name = ' - '.join((_('BORDEREAU DE REMISE DE CHEQUES'),
|
||||||
company.name, company.currency_id.name))
|
company.name, company.currency_id.name))
|
||||||
statement = self.pool.get('account.bank.statement').browse(cursor,uid,context['active_id']);
|
|
||||||
footer_date_time = self.formatLang(str(datetime.today())[:19], date_time=True)
|
footer_date_time = self.formatLang(str(datetime.today())[:19], date_time=True)
|
||||||
self.localcontext.update({
|
self.localcontext.update({
|
||||||
'cr': cursor,
|
'cr': cursor,
|
||||||
'uid': uid,
|
'uid': uid,
|
||||||
'get_bank_statement' : self._get_bank_statement_data,
|
'get_bank_statement': self._get_bank_statement_data,
|
||||||
'report_name': _('BORDEREAU DE REMISE DE CHEQUES'),
|
'report_name': _('BORDEREAU DE REMISE DE CHEQUES'),
|
||||||
'additional_args': [
|
'additional_args': [
|
||||||
('--header-font-name', 'Helvetica'),
|
('--header-font-name', 'Helvetica'),
|
||||||
@@ -57,10 +54,15 @@ class BankStatementWebkit(report_sxw.rml_parse):
|
|||||||
('--footer-line',),
|
('--footer-line',),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
def _get_bank_statement_data(self,statement):
|
|
||||||
|
def _get_bank_statement_data(self, statement):
|
||||||
statement_obj = self.pool.get('account.bank.statement.line')
|
statement_obj = self.pool.get('account.bank.statement.line')
|
||||||
statement_line_ids = statement_obj.search(self.cr,self.uid,[['statement_id','=',statement.id]])
|
statement_line_ids = statement_obj.search(
|
||||||
statement_lines = statement_obj.browse(self.cr,self.uid,statement_line_ids)
|
self.cr,
|
||||||
|
self.uid,
|
||||||
|
[('statement_id', '=', statement.id)])
|
||||||
|
statement_lines = statement_obj.browse(
|
||||||
|
self.cr, self.uid, statement_line_ids)
|
||||||
return statement_lines
|
return statement_lines
|
||||||
|
|
||||||
webkit_report.WebKitParser('report.bank_statement_webkit',
|
webkit_report.WebKitParser('report.bank_statement_webkit',
|
||||||
|
|||||||
@@ -19,11 +19,10 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import time
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv, osv
|
from openerp.osv import fields, osv
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
import openerp.addons.decimal_precision as dp
|
|
||||||
|
|
||||||
class AccountStatementProfil(Model):
|
class AccountStatementProfil(Model):
|
||||||
"""
|
"""
|
||||||
@@ -33,45 +32,53 @@ class AccountStatementProfil(Model):
|
|||||||
"""
|
"""
|
||||||
_name = "account.statement.profile"
|
_name = "account.statement.profile"
|
||||||
_description = "Statement Profil"
|
_description = "Statement Profil"
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Name', size=128, required=True),
|
'name': fields.char('Name', required=True),
|
||||||
'partner_id': fields.many2one('res.partner',
|
'partner_id': fields.many2one(
|
||||||
'Bank/Payment Office partner',
|
'res.partner',
|
||||||
help="Put a partner if you want to have it on the commission move \
|
'Bank/Payment Office partner',
|
||||||
(and optionaly on the counterpart of the intermediate/banking move \
|
help="Put a partner if you want to have it on the "
|
||||||
if you tic the corresponding checkbox)."),
|
"commission move (and optionaly on the counterpart "
|
||||||
'journal_id': fields.many2one('account.journal',
|
"of the intermediate/banking move if you tick the "
|
||||||
'Financial journal to use for transaction',
|
"corresponding checkbox)."),
|
||||||
required=True),
|
'journal_id': fields.many2one(
|
||||||
'commission_account_id': fields.many2one('account.account',
|
'account.journal',
|
||||||
'Commission account',
|
'Financial journal to use for transaction',
|
||||||
required=True),
|
required=True),
|
||||||
'commission_analytic_id': fields.many2one('account.analytic.account',
|
'commission_account_id': fields.many2one(
|
||||||
'Commission analytic account'),
|
'account.account',
|
||||||
'receivable_account_id': fields.many2one('account.account',
|
'Commission account',
|
||||||
'Force Receivable/Payable Account',
|
required=True),
|
||||||
help="Choose a receivable account to force the default\
|
'commission_analytic_id': fields.many2one(
|
||||||
debit/credit account (eg. an intermediat bank account instead of\
|
'account.analytic.account',
|
||||||
default debitors)."),
|
'Commission analytic account'),
|
||||||
'force_partner_on_bank': fields.boolean('Force partner on bank move',
|
'receivable_account_id': fields.many2one(
|
||||||
help="Tic that box if you want to use the credit insitute partner\
|
'account.account',
|
||||||
in the counterpart of the intermediat/banking move."
|
'Force Receivable/Payable Account',
|
||||||
),
|
help="Choose a receivable account to force the default "
|
||||||
'balance_check': fields.boolean('Balance check',
|
"debit/credit account (eg. an intermediat bank account "
|
||||||
help="Tic that box if you want OpenERP to control the start/end \
|
"instead of default debitors)."),
|
||||||
balance before confirming a bank statement. If don't ticked, no \
|
'force_partner_on_bank': fields.boolean(
|
||||||
balance control will be done."
|
'Force partner on bank move',
|
||||||
),
|
help="Tick that box if you want to use the credit "
|
||||||
'bank_statement_prefix': fields.char('Bank Statement Prefix', size=32),
|
"institute partner in the counterpart of the "
|
||||||
'bank_statement_ids': fields.one2many('account.bank.statement', 'profile_id', 'Bank Statement Imported'),
|
"intermediate/banking move."),
|
||||||
|
'balance_check': fields.boolean(
|
||||||
|
'Balance check',
|
||||||
|
help="Tick that box if you want OpenERP to control "
|
||||||
|
"the start/end balance before confirming a bank statement. "
|
||||||
|
"If don't ticked, no balance control will be done."
|
||||||
|
),
|
||||||
|
'bank_statement_prefix': fields.char(
|
||||||
|
'Bank Statement Prefix', size=32),
|
||||||
|
'bank_statement_ids': fields.one2many(
|
||||||
|
'account.bank.statement', 'profile_id', 'Bank Statement Imported'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def _check_partner(self, cr, uid, ids, context=None):
|
def _check_partner(self, cr, uid, ids, context=None):
|
||||||
obj = self.browse(cr, uid, ids[0], context=context)
|
obj = self.browse(cr, uid, ids[0], context=context)
|
||||||
if obj.partner_id == False and obj.force_partner_on_bank:
|
if obj.partner_id is False and obj.force_partner_on_bank:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -82,57 +89,65 @@ class AccountStatementProfil(Model):
|
|||||||
|
|
||||||
class AccountBankSatement(Model):
|
class AccountBankSatement(Model):
|
||||||
"""
|
"""
|
||||||
We improve the bank statement class mostly for :
|
We improve the bank statement class mostly for :
|
||||||
- Removing the period and compute it from the date of each line.
|
- Removing the period and compute it from the date of each line.
|
||||||
- Allow to remove the balance check depending on the chosen profile
|
- Allow to remove the balance check depending on the chosen profile
|
||||||
- Report errors on confirmation all at once instead of crashing onr by one
|
- Report errors on confirmation all at once instead of crashing onr by one
|
||||||
- Add a profile notion that can change the generated entries on statement
|
- Add a profile notion that can change the generated entries on statement
|
||||||
confirmation.
|
confirmation.
|
||||||
For this, we had to override quite some long method and we'll need to maintain
|
For this, we had to override quite some long method and we'll need to maintain
|
||||||
them up to date. Changes are point up by '#Chg' comment.
|
them up to date. Changes are point up by '#Chg' comment.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_inherit = "account.bank.statement"
|
_inherit = "account.bank.statement"
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'profile_id': fields.many2one('account.statement.profile',
|
'profile_id': fields.many2one(
|
||||||
'Profil', required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
'account.statement.profile',
|
||||||
|
'Profil',
|
||||||
|
required=True,
|
||||||
|
readonly=True,
|
||||||
|
states={'draft': [('readonly', False)]}),
|
||||||
'credit_partner_id': fields.related(
|
'credit_partner_id': fields.related(
|
||||||
'profile_id',
|
'profile_id',
|
||||||
'partner_id',
|
'partner_id',
|
||||||
type='many2one',
|
|
||||||
relation='res.partner',
|
|
||||||
string='Financial Partner',
|
|
||||||
store=True, readonly=True),
|
|
||||||
'balance_check': fields.related(
|
|
||||||
'profile_id',
|
|
||||||
'balance_check',
|
|
||||||
type='boolean',
|
|
||||||
string='Balance check',
|
|
||||||
store=True, readonly=True),
|
|
||||||
'journal_id': fields.related(
|
|
||||||
'profile_id',
|
|
||||||
'journal_id',
|
|
||||||
type='many2one',
|
type='many2one',
|
||||||
relation='account.journal',
|
relation='res.partner',
|
||||||
string='Journal',
|
string='Financial Partner',
|
||||||
store=True, readonly=True),
|
store=True,
|
||||||
'period_id': fields.many2one('account.period', 'Period', required=False, readonly=True),
|
readonly=True),
|
||||||
|
'balance_check': fields.related(
|
||||||
|
'profile_id',
|
||||||
|
'balance_check',
|
||||||
|
type='boolean',
|
||||||
|
string='Balance check',
|
||||||
|
store=True,
|
||||||
|
readonly=True),
|
||||||
|
'journal_id': fields.related(
|
||||||
|
'profile_id',
|
||||||
|
'journal_id',
|
||||||
|
type='many2one',
|
||||||
|
relation='account.journal',
|
||||||
|
string='Journal',
|
||||||
|
store=True,
|
||||||
|
readonly=True),
|
||||||
|
'period_id': fields.many2one(
|
||||||
|
'account.period', 'Period', required=False, readonly=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'period_id': lambda *a: False,
|
'period_id': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
def create(self, cr, uid, vals, context=None):
|
def create(self, cr, uid, vals, context=None):
|
||||||
"""Need to pass the journal_id in vals anytime because of account.cash.statement
|
"""Need to pass the journal_id in vals anytime because of account.cash.statement
|
||||||
need it."""
|
need it."""
|
||||||
if 'profile_id' in vals:
|
if 'profile_id' in vals:
|
||||||
profile_obj = self.pool.get('account.statement.profile')
|
profile_obj = self.pool.get('account.statement.profile')
|
||||||
profile = profile_obj.browse(cr,uid,vals['profile_id'],context)
|
profile = profile_obj.browse(cr, uid, vals['profile_id'], context=context)
|
||||||
vals['journal_id'] = profile.journal_id.id
|
vals['journal_id'] = profile.journal_id.id
|
||||||
return super(AccountBankSatement, self).create(cr, uid, vals, context=context)
|
return super(AccountBankSatement, self).create(cr, uid, vals, context=context)
|
||||||
|
|
||||||
def _get_period(self, cursor, uid, date, context=None):
|
def _get_period(self, cursor, uid, date, context=None):
|
||||||
"""
|
"""
|
||||||
Find matching period for date, used in the statement line creation.
|
Find matching period for date, used in the statement line creation.
|
||||||
@@ -140,7 +155,7 @@ class AccountBankSatement(Model):
|
|||||||
period_obj = self.pool.get('account.period')
|
period_obj = self.pool.get('account.period')
|
||||||
periods = period_obj.find(cursor, uid, dt=date, context=context)
|
periods = period_obj.find(cursor, uid, dt=date, context=context)
|
||||||
return periods and periods[0] or False
|
return periods and periods[0] or False
|
||||||
|
|
||||||
def _check_company_id(self, cr, uid, ids, context=None):
|
def _check_company_id(self, cr, uid, ids, context=None):
|
||||||
"""
|
"""
|
||||||
Adapt this constraint method from the account module to reflect the
|
Adapt this constraint method from the account module to reflect the
|
||||||
@@ -157,25 +172,27 @@ class AccountBankSatement(Model):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
_constraints = [
|
_constraints = [
|
||||||
(_check_company_id, 'The journal and period chosen have to belong to the same company.', ['journal_id','period_id']),
|
(_check_company_id,
|
||||||
|
'The journal and period chosen have to belong to the same company.',
|
||||||
|
['journal_id', 'period_id']),
|
||||||
]
|
]
|
||||||
|
|
||||||
def button_cancel(self, cr, uid, ids, context={}):
|
def button_cancel(self, cr, uid, ids, context=None):
|
||||||
"""
|
"""
|
||||||
We cancel the related move, delete them and finally put the
|
We cancel the related move, delete them and finally put the
|
||||||
statement in draft state. So no need to unreconcile all entries,
|
statement in draft state. So no need to unreconcile all entries,
|
||||||
then unpost them, then finaly cancel the bank statement.
|
then unpost them, then finaly cancel the bank statement.
|
||||||
"""
|
"""
|
||||||
done = []
|
|
||||||
for st in self.browse(cr, uid, ids, context=context):
|
for st in self.browse(cr, uid, ids, context=context):
|
||||||
if st.state=='draft':
|
if st.state == 'draft':
|
||||||
continue
|
continue
|
||||||
ids = []
|
ids = []
|
||||||
for line in st.line_ids:
|
for line in st.line_ids:
|
||||||
for move in line.move_ids:
|
for move in line.move_ids:
|
||||||
if move.state <> 'draft':
|
if move.state != 'draft':
|
||||||
move.button_cancel(context=context)
|
move.button_cancel(context=context)
|
||||||
return super(AccountBankSatement, self).button_cancel(cr, uid, vals, context=context)
|
return super(AccountBankSatement, self).button_cancel(
|
||||||
|
cr, uid, ids, context=context)
|
||||||
|
|
||||||
def _prepare_move(self, cr, uid, st_line, st_line_number, context=None):
|
def _prepare_move(self, cr, uid, st_line, st_line_number, context=None):
|
||||||
"""Add the period_id from the statement line date to the move preparation.
|
"""Add the period_id from the statement line date to the move preparation.
|
||||||
@@ -187,19 +204,21 @@ class AccountBankSatement(Model):
|
|||||||
"""
|
"""
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
res = super(AccountBankSatement, self)._prepare_move(cr, uid, st_line, st_line_number, context=context)
|
res = super(AccountBankSatement, self)._prepare_move(
|
||||||
|
cr, uid, st_line, st_line_number, context=context)
|
||||||
ctx = context.copy()
|
ctx = context.copy()
|
||||||
ctx['company_id'] = st_line.company_id.id
|
ctx['company_id'] = st_line.company_id.id
|
||||||
period_id = self._get_period(cr, uid, st_line.date, context=ctx)
|
period_id = self._get_period(cr, uid, st_line.date, context=ctx)
|
||||||
res.update({'period_id': period_id})
|
res.update({'period_id': period_id})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _prepare_move_line_vals(self, cr, uid, st_line, move_id, debit, credit, currency_id = False,
|
def _prepare_move_line_vals(
|
||||||
amount_currency= False, account_id = False, analytic_id = False,
|
self, cr, uid, st_line, move_id, debit, credit, currency_id=False,
|
||||||
partner_id = False, context=None):
|
amount_currency=False, account_id=False, analytic_id=False,
|
||||||
|
partner_id=False, context=None):
|
||||||
"""Add the period_id from the statement line date to the move preparation.
|
"""Add the period_id from the statement line date to the move preparation.
|
||||||
Originaly, it was taken from the statement period_id
|
Originaly, it was taken from the statement period_id
|
||||||
|
|
||||||
:param browse_record st_line: account.bank.statement.line record to
|
:param browse_record st_line: account.bank.statement.line record to
|
||||||
create the move from.
|
create the move from.
|
||||||
:param int/long move_id: ID of the account.move to link the move line
|
:param int/long move_id: ID of the account.move to link the move line
|
||||||
@@ -215,9 +234,13 @@ class AccountBankSatement(Model):
|
|||||||
"""
|
"""
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
res = super(AccountBankSatement, self)._prepare_move_line_vals(cr, uid, st_line, move_id, debit,
|
res = super(AccountBankSatement, self)._prepare_move_line_vals(
|
||||||
credit, currency_id = currency_id, amount_currency = amount_currency, account_id = account_id,
|
cr, uid, st_line, move_id, debit, credit,
|
||||||
analytic_id = analytic_id, partner_id = partner_id, context = context)
|
currency_id=currency_id,
|
||||||
|
amount_currency=amount_currency,
|
||||||
|
account_id=account_id,
|
||||||
|
analytic_id=analytic_id,
|
||||||
|
partner_id=partner_id, context=context)
|
||||||
ctx = context.copy()
|
ctx = context.copy()
|
||||||
ctx['company_id'] = st_line.company_id.id
|
ctx['company_id'] = st_line.company_id.id
|
||||||
period_id = self._get_period(cr, uid, st_line.date, context=ctx)
|
period_id = self._get_period(cr, uid, st_line.date, context=ctx)
|
||||||
@@ -235,28 +258,31 @@ class AccountBankSatement(Model):
|
|||||||
create the move from.
|
create the move from.
|
||||||
:return: int/long of the res.partner to use as counterpart
|
:return: int/long of the res.partner to use as counterpart
|
||||||
"""
|
"""
|
||||||
bank_partner_id = super(AccountBankSatement, self)._get_counter_part_partner(cr, uid, st_line, context=context)
|
bank_partner_id = super(AccountBankSatement, self).\
|
||||||
# GET THE RIGHT PARTNER ACCORDING TO THE CHOSEN PROFIL
|
_get_counter_part_partner(cr, uid, st_line, context=context)
|
||||||
|
# get the right partner according to the chosen profil
|
||||||
if st_line.statement_id.profile_id.force_partner_on_bank:
|
if st_line.statement_id.profile_id.force_partner_on_bank:
|
||||||
bank_partner_id = st_line.statement_id.profile_id.partner_id.id
|
bank_partner_id = st_line.statement_id.profile_id.partner_id.id
|
||||||
return bank_partner_id
|
return bank_partner_id
|
||||||
|
|
||||||
def _get_st_number_period_profile(self, cr, uid, date, profile_id):
|
def _get_st_number_period_profile(self, cr, uid, date, profile_id):
|
||||||
"""
|
"""
|
||||||
Retrieve the name of bank statement from sequence, according to the period
|
Retrieve the name of bank statement from sequence, according to the period
|
||||||
corresponding to the date passed in args. Add a prefix if set in the profile.
|
corresponding to the date passed in args. Add a prefix if set in the profile.
|
||||||
|
|
||||||
:param: date: date of the statement used to compute the right period
|
:param: date: date of the statement used to compute the right period
|
||||||
:param: int/long: profile_id: the account.statement.profile ID from which to take the
|
:param: int/long: profile_id: the account.statement.profile ID from which to take the
|
||||||
bank_statement_prefix for the name
|
bank_statement_prefix for the name
|
||||||
:return: char: name of the bank statement (st_number)
|
:return: char: name of the bank statement (st_number)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
year = self.pool.get('account.period').browse(cr, uid, self._get_period(cr, uid, date)).fiscalyear_id.id
|
year = self.pool.get('account.period').browse(
|
||||||
profile = self.pool.get('account.statement.profile').browse(cr,uid, profile_id)
|
cr, uid, self._get_period(cr, uid, date)).fiscalyear_id.id
|
||||||
|
profile = self.pool.get('account.statement.profile').browse(cr, uid, profile_id)
|
||||||
c = {'fiscalyear_id': year}
|
c = {'fiscalyear_id': year}
|
||||||
obj_seq = self.pool.get('ir.sequence')
|
obj_seq = self.pool.get('ir.sequence')
|
||||||
journal_sequence_id = profile.journal_id.sequence_id and profile.journal_id.sequence_id.id or False
|
journal_sequence_id = (profile.journal_id.sequence_id and
|
||||||
|
profile.journal_id.sequence_id.id or False)
|
||||||
if journal_sequence_id:
|
if journal_sequence_id:
|
||||||
st_number = obj_seq.next_by_id(cr, uid, journal_sequence_id, context=c)
|
st_number = obj_seq.next_by_id(cr, uid, journal_sequence_id, context=c)
|
||||||
else:
|
else:
|
||||||
@@ -272,19 +298,16 @@ class AccountBankSatement(Model):
|
|||||||
instead of having them pop one by one.
|
instead of having them pop one by one.
|
||||||
We have to copy paste a big block of code, changing the error
|
We have to copy paste a big block of code, changing the error
|
||||||
stack + managing period from date.
|
stack + managing period from date.
|
||||||
|
|
||||||
TODO: Log the error in a bank statement field instead of using a popup !
|
TODO: Log the error in a bank statement field instead of using a popup !
|
||||||
"""
|
"""
|
||||||
# obj_seq = self.pool.get('irerrors_stack.sequence')
|
|
||||||
if context is None:
|
|
||||||
context = {}
|
|
||||||
for st in self.browse(cr, uid, ids, context=context):
|
for st in self.browse(cr, uid, ids, context=context):
|
||||||
|
|
||||||
j_type = st.journal_id.type
|
j_type = st.journal_id.type
|
||||||
company_currency_id = st.journal_id.company_id.currency_id.id
|
company_currency_id = st.journal_id.company_id.currency_id.id
|
||||||
if not self.check_status_condition(cr, uid, st.state, journal_type=j_type):
|
if not self.check_status_condition(cr, uid, st.state, journal_type=j_type):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.balance_check(cr, uid, st.id, journal_type=j_type, context=context)
|
self.balance_check(cr, uid, st.id, journal_type=j_type, context=context)
|
||||||
if (not st.journal_id.default_credit_account_id) \
|
if (not st.journal_id.default_credit_account_id) \
|
||||||
or (not st.journal_id.default_debit_account_id):
|
or (not st.journal_id.default_debit_account_id):
|
||||||
@@ -294,11 +317,11 @@ class AccountBankSatement(Model):
|
|||||||
if not st.name == '/':
|
if not st.name == '/':
|
||||||
st_number = st.name
|
st_number = st.name
|
||||||
else:
|
else:
|
||||||
# Begin Changes
|
# Begin Changes
|
||||||
st_number = self._get_st_number_period_profile(cr, uid, st.date, st.profile_id.id)
|
st_number = self._get_st_number_period_profile(cr, uid, st.date, st.profile_id.id)
|
||||||
# End Changes
|
# End Changes
|
||||||
for line in st.move_line_ids:
|
for line in st.move_line_ids:
|
||||||
if line.state <> 'valid':
|
if line.state != 'valid':
|
||||||
raise osv.except_osv(_('Error !'),
|
raise osv.except_osv(_('Error !'),
|
||||||
_('The account entries lines are not in valid state.'))
|
_('The account entries lines are not in valid state.'))
|
||||||
# begin changes
|
# begin changes
|
||||||
@@ -328,18 +351,18 @@ class AccountBankSatement(Model):
|
|||||||
'balance_end_real': st.balance_end
|
'balance_end_real': st.balance_end
|
||||||
}, context=context)
|
}, context=context)
|
||||||
self.message_post(cr, uid, [st.id], body=_('Statement %s confirmed, journal items were created.') % (st_number,), context=context)
|
self.message_post(cr, uid, [st.id], body=_('Statement %s confirmed, journal items were created.') % (st_number,), context=context)
|
||||||
return self.write(cr, uid, ids, {'state':'confirm'}, context=context)
|
return self.write(cr, uid, ids, {'state': 'confirm'}, context=context)
|
||||||
|
|
||||||
def get_account_for_counterpart(self, cursor, uid,
|
def get_account_for_counterpart(
|
||||||
amount, account_receivable, account_payable):
|
self, cursor, uid, amount, account_receivable, account_payable):
|
||||||
"""
|
"""
|
||||||
Give the amount, payable and receivable account (that can be found using
|
Give the amount, payable and receivable account (that can be found using
|
||||||
get_default_pay_receiv_accounts method) and receive the one to use. This method
|
get_default_pay_receiv_accounts method) and receive the one to use. This method
|
||||||
should be use when there is no other way to know which one to take.
|
should be use when there is no other way to know which one to take.
|
||||||
|
|
||||||
:param float: amount of the line
|
:param float: amount of the line
|
||||||
:param int/long: account_receivable the receivable account
|
:param int/long: account_receivable the receivable account
|
||||||
:param int/long: account_payable the payable account
|
:param int/long: account_payable the payable account
|
||||||
:return: int/long :the default account to be used by statement line as the counterpart
|
:return: int/long :the default account to be used by statement line as the counterpart
|
||||||
of the journal account depending on the amount.
|
of the journal account depending on the amount.
|
||||||
"""
|
"""
|
||||||
@@ -358,16 +381,15 @@ class AccountBankSatement(Model):
|
|||||||
def get_default_pay_receiv_accounts(self, cursor, uid, context=None):
|
def get_default_pay_receiv_accounts(self, cursor, uid, context=None):
|
||||||
"""
|
"""
|
||||||
We try to determine default payable/receivable accounts to be used as counterpart
|
We try to determine default payable/receivable accounts to be used as counterpart
|
||||||
from the company default propoerty. This is to be used if there is no otherway to
|
from the company default propoerty. This is to be used if there is no otherway to
|
||||||
find the good one, or to find a default value that will be overriden by a completion
|
find the good one, or to find a default value that will be overriden by a completion
|
||||||
method (rules of account_statement_base_completion) afterwards.
|
method (rules of account_statement_base_completion) afterwards.
|
||||||
|
|
||||||
:return: tuple of int/long ID that give account_receivable, account_payable based on
|
:return: tuple of int/long ID that give account_receivable, account_payable based on
|
||||||
company default.
|
company default.
|
||||||
"""
|
"""
|
||||||
account_receivable = False
|
account_receivable = False
|
||||||
account_payable = False
|
account_payable = False
|
||||||
context = context or {}
|
|
||||||
property_obj = self.pool.get('ir.property')
|
property_obj = self.pool.get('ir.property')
|
||||||
model_fields_obj = self.pool.get('ir.model.fields')
|
model_fields_obj = self.pool.get('ir.model.fields')
|
||||||
model_fields_ids = model_fields_obj.search(
|
model_fields_ids = model_fields_obj.search(
|
||||||
@@ -375,20 +397,20 @@ class AccountBankSatement(Model):
|
|||||||
uid,
|
uid,
|
||||||
[('name', 'in', ['property_account_receivable',
|
[('name', 'in', ['property_account_receivable',
|
||||||
'property_account_payable']),
|
'property_account_payable']),
|
||||||
('model', '=', 'res.partner'),],
|
('model', '=', 'res.partner')],
|
||||||
context=context
|
context=context
|
||||||
)
|
)
|
||||||
property_ids = property_obj.search(
|
property_ids = property_obj.search(
|
||||||
cursor,
|
cursor,
|
||||||
uid, [
|
uid,
|
||||||
('fields_id', 'in', model_fields_ids),
|
[('fields_id', 'in', model_fields_ids),
|
||||||
('res_id', '=', False),
|
('res_id', '=', False),
|
||||||
],
|
],
|
||||||
context=context
|
context=context
|
||||||
)
|
)
|
||||||
|
|
||||||
for erp_property in property_obj.browse(cursor, uid,
|
for erp_property in property_obj.browse(
|
||||||
property_ids, context=context):
|
cursor, uid, property_ids, context=context):
|
||||||
if erp_property.fields_id.name == 'property_account_receivable':
|
if erp_property.fields_id.name == 'property_account_receivable':
|
||||||
account_receivable = erp_property.value_reference.id
|
account_receivable = erp_property.value_reference.id
|
||||||
elif erp_property.fields_id.name == 'property_account_payable':
|
elif erp_property.fields_id.name == 'property_account_payable':
|
||||||
@@ -399,41 +421,46 @@ class AccountBankSatement(Model):
|
|||||||
"""
|
"""
|
||||||
Balance check depends on the profile. If no check for this profile is required,
|
Balance check depends on the profile. If no check for this profile is required,
|
||||||
return True and do nothing, otherwise call super.
|
return True and do nothing, otherwise call super.
|
||||||
|
|
||||||
:param int/long st_id: ID of the concerned account.bank.statement
|
:param int/long st_id: ID of the concerned account.bank.statement
|
||||||
:param char: journal_type that concern the bank statement
|
:param char: journal_type that concern the bank statement
|
||||||
:return: True
|
:return: True
|
||||||
"""
|
"""
|
||||||
st = self.browse(cr, uid, st_id, context=context)
|
st = self.browse(cr, uid, st_id, context=context)
|
||||||
if st.balance_check:
|
if st.balance_check:
|
||||||
return super(AccountBankSatement,self).balance_check(cr, uid, st_id, journal_type, context)
|
return super(AccountBankSatement, self).balance_check(
|
||||||
|
cr, uid, st_id, journal_type, context=context)
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def onchange_imp_config_id(self, cr, uid, ids, profile_id, context=None):
|
def onchange_imp_config_id(self, cr, uid, ids, profile_id, context=None):
|
||||||
"""
|
"""
|
||||||
Compute values on the change of the profile.
|
Compute values on the change of the profile.
|
||||||
|
|
||||||
:param: int/long: profile_id that changed
|
:param: int/long: profile_id that changed
|
||||||
:return dict of dict with key = name of the field
|
:return dict of dict with key = name of the field
|
||||||
"""
|
"""
|
||||||
if not profile_id:
|
if not profile_id:
|
||||||
return {}
|
return {}
|
||||||
import_config = self.pool.get("account.statement.profile").browse(cr,uid,profile_id)
|
import_config = self.pool.get("account.statement.profile").browse(
|
||||||
|
cr, uid, profile_id, context=context)
|
||||||
journal_id = import_config.journal_id.id
|
journal_id = import_config.journal_id.id
|
||||||
account_id = import_config.journal_id.default_debit_account_id.id
|
account_id = import_config.journal_id.default_debit_account_id.id
|
||||||
credit_partner_id = import_config.partner_id and import_config.partner_id.id or False
|
credit_partner_id = import_config.partner_id and import_config.partner_id.id or False
|
||||||
return {'value': {'journal_id':journal_id, 'account_id': account_id,
|
return {'value':
|
||||||
'balance_check':import_config.balance_check,
|
{'journal_id': journal_id,
|
||||||
'credit_partner_id':credit_partner_id,
|
'account_id': account_id,
|
||||||
}}
|
'balance_check': import_config.balance_check,
|
||||||
|
'credit_partner_id': credit_partner_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class AccountBankSatementLine(Model):
|
class AccountBankSatementLine(Model):
|
||||||
"""
|
"""
|
||||||
Override to compute the period from the date of the line, add a method to retrieve
|
Override to compute the period from the date of the line, add a method to retrieve
|
||||||
the values for a line from the profile. Override the on_change method to take care of
|
the values for a line from the profile. Override the on_change method to take care of
|
||||||
the profile when fullfilling the bank statement manually. Set the reference to 64
|
the profile when fullfilling the bank statement manually. Set the reference to 64
|
||||||
Char long instead 32.
|
Char long instead 32.
|
||||||
"""
|
"""
|
||||||
_inherit = "account.bank.statement.line"
|
_inherit = "account.bank.statement.line"
|
||||||
@@ -447,8 +474,8 @@ class AccountBankSatementLine(Model):
|
|||||||
return periods and periods[0] or False
|
return periods and periods[0] or False
|
||||||
|
|
||||||
def _get_default_account(self, cursor, user, context=None):
|
def _get_default_account(self, cursor, user, context=None):
|
||||||
return self.get_values_for_line(cursor, user, context = context)['account_id']
|
return self.get_values_for_line(cursor, user, context=context)['account_id']
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
# Set them as required + 64 char instead of 32
|
# Set them as required + 64 char instead of 32
|
||||||
'ref': fields.char('Reference', size=64, required=True),
|
'ref': fields.char('Reference', size=64, required=True),
|
||||||
@@ -458,8 +485,8 @@ class AccountBankSatementLine(Model):
|
|||||||
'period_id': _get_period,
|
'period_id': _get_period,
|
||||||
'account_id': _get_default_account,
|
'account_id': _get_default_account,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_values_for_line(self, cr, uid, profile_id = False, partner_id = False, line_type = False, amount = False, context = None):
|
def get_values_for_line(self, cr, uid, profile_id=False, partner_id=False, line_type=False, amount=False, context=None):
|
||||||
"""
|
"""
|
||||||
Return the account_id to be used in the line of a bank statement. It'll base the result as follow:
|
Return the account_id to be used in the line of a bank statement. It'll base the result as follow:
|
||||||
- If a receivable_account_id is set in the profile, return this value and type = general
|
- If a receivable_account_id is set in the profile, return this value and type = general
|
||||||
@@ -470,7 +497,7 @@ class AccountBankSatementLine(Model):
|
|||||||
so it is easier for the accountant to know why the receivable/payable has been chosen
|
so it is easier for the accountant to know why the receivable/payable has been chosen
|
||||||
- Then, if no partner are given we look and take the property from the company so we always give a value
|
- Then, if no partner are given we look and take the property from the company so we always give a value
|
||||||
for account_id. Note that in that case, we return the receivable one.
|
for account_id. Note that in that case, we return the receivable one.
|
||||||
|
|
||||||
:param int/long profile_id of the related bank statement
|
:param int/long profile_id of the related bank statement
|
||||||
:param int/long partner_id of the line
|
:param int/long partner_id of the line
|
||||||
:param char line_type: a value from: 'general', 'supplier', 'customer'
|
:param char line_type: a value from: 'general', 'supplier', 'customer'
|
||||||
@@ -483,17 +510,16 @@ class AccountBankSatementLine(Model):
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
if context is None:
|
|
||||||
context = {}
|
|
||||||
res = {}
|
res = {}
|
||||||
obj_partner = self.pool.get('res.partner')
|
obj_partner = self.pool.get('res.partner')
|
||||||
obj_stat = self.pool.get('account.bank.statement')
|
obj_stat = self.pool.get('account.bank.statement')
|
||||||
receiv_account = pay_account = account_id = False
|
receiv_account = pay_account = account_id = False
|
||||||
# If profile has a receivable_account_id, we return it in any case
|
# If profile has a receivable_account_id, we return it in any case
|
||||||
if profile_id:
|
if profile_id:
|
||||||
profile = self.pool.get("account.statement.profile").browse(cr,uid,profile_id)
|
profile = self.pool.get("account.statement.profile").browse(
|
||||||
|
cr, uid, profile_id, context=context)
|
||||||
if profile.receivable_account_id:
|
if profile.receivable_account_id:
|
||||||
res['account_id'] = profile.receivable_account_id.id
|
res['account_id'] = profile.receivable_account_id.id
|
||||||
res['type'] = 'general'
|
res['type'] = 'general'
|
||||||
return res
|
return res
|
||||||
# If partner -> take from him
|
# If partner -> take from him
|
||||||
@@ -503,7 +529,8 @@ class AccountBankSatementLine(Model):
|
|||||||
receiv_account = part.property_account_receivable.id
|
receiv_account = part.property_account_receivable.id
|
||||||
# If no value, look on the default company property
|
# If no value, look on the default company property
|
||||||
if not pay_account or not receiv_account:
|
if not pay_account or not receiv_account:
|
||||||
receiv_account, pay_account = obj_stat.get_default_pay_receiv_accounts(cr, uid, context=None)
|
receiv_account, pay_account = obj_stat.get_default_pay_receiv_accounts(
|
||||||
|
cr, uid, context=None)
|
||||||
# Now we have both pay and receive account, choose the one to use
|
# Now we have both pay and receive account, choose the one to use
|
||||||
# based on line_type first, then amount, otherwise take receivable one.
|
# based on line_type first, then amount, otherwise take receivable one.
|
||||||
if line_type is not False:
|
if line_type is not False:
|
||||||
@@ -519,18 +546,15 @@ class AccountBankSatementLine(Model):
|
|||||||
res['account_id'] = pay_account
|
res['account_id'] = pay_account
|
||||||
res['type'] = 'supplier'
|
res['type'] = 'supplier'
|
||||||
if not account_id:
|
if not account_id:
|
||||||
res['account_id'] = receiv_account
|
res['account_id'] = receiv_account
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def onchange_partner_id(self, cr, uid, ids, partner_id, profile_id, context=None):
|
def onchange_partner_id(self, cr, uid, ids, partner_id, profile_id, context=None):
|
||||||
"""
|
"""
|
||||||
Override of the basic method as we need to pass the profile_id in the on_change_type
|
Override of the basic method as we need to pass the profile_id in the on_change_type
|
||||||
call.
|
call.
|
||||||
"""
|
"""
|
||||||
obj_partner = self.pool.get('res.partner')
|
obj_partner = self.pool.get('res.partner')
|
||||||
if context is None:
|
|
||||||
context = {}
|
|
||||||
if not partner_id:
|
if not partner_id:
|
||||||
return {}
|
return {}
|
||||||
part = obj_partner.browse(cr, uid, partner_id, context=context)
|
part = obj_partner.browse(cr, uid, partner_id, context=context)
|
||||||
@@ -543,23 +567,25 @@ class AccountBankSatementLine(Model):
|
|||||||
type = 'supplier'
|
type = 'supplier'
|
||||||
if part.customer == True:
|
if part.customer == True:
|
||||||
type = 'customer'
|
type = 'customer'
|
||||||
res_type = self.onchange_type(cr, uid, ids, partner_id, type, profile_id, context=context) # Chg
|
res_type = self.onchange_type(cr, uid, ids, partner_id, type, profile_id, context=context) # Chg
|
||||||
if res_type['value'] and res_type['value'].get('account_id', False):
|
if res_type['value'] and res_type['value'].get('account_id', False):
|
||||||
return {'value': {'type': type, 'account_id': res_type['value']['account_id']}}
|
return {'value': {'type': type, 'account_id': res_type['value']['account_id']}}
|
||||||
return {'value': {'type': type}}
|
return {'value': {'type': type}}
|
||||||
|
|
||||||
def onchange_type(self, cr, uid, line_id, partner_id, type, profile_id, context=None):
|
def onchange_type(self, cr, uid, line_id, partner_id, type, profile_id, context=None):
|
||||||
"""
|
"""
|
||||||
Keep the same features as in standard and call super. If an account is returned,
|
Keep the same features as in standard and call super. If an account is returned,
|
||||||
call the method to compute line values.
|
call the method to compute line values.
|
||||||
"""
|
"""
|
||||||
if context is None:
|
res = super(AccountBankSatementLine, self).onchange_type(
|
||||||
context = {}
|
cr, uid, line_id, partner_id, type, context=context)
|
||||||
res = super(AccountBankSatementLine,self).onchange_type(cr, uid, line_id, partner_id, type, context)
|
|
||||||
if 'account_id' in res['value']:
|
if 'account_id' in res['value']:
|
||||||
result = self.get_values_for_line(cr, uid, profile_id = profile_id,
|
result = self.get_values_for_line(
|
||||||
partner_id = partner_id, line_type = type, context = context)
|
cr, uid,
|
||||||
|
profile_id=profile_id,
|
||||||
|
partner_id=partner_id,
|
||||||
|
line_type=type,
|
||||||
|
context=context)
|
||||||
if result:
|
if result:
|
||||||
res['value'].update({'account_id':result['account_id']})
|
res['value'].update({'account_id': result['account_id']})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
'author': 'Camptocamp',
|
'author': 'Camptocamp',
|
||||||
'maintainer': 'Camptocamp',
|
'maintainer': 'Camptocamp',
|
||||||
'category': 'Finance',
|
'category': 'Finance',
|
||||||
'complexity': 'normal', #easy, normal, expert
|
'complexity': 'normal',
|
||||||
'depends': ['account_statement_ext','account_voucher'],
|
'depends': [
|
||||||
|
'account_statement_ext',
|
||||||
|
'account_voucher'
|
||||||
|
],
|
||||||
'description': """
|
'description': """
|
||||||
This module is only needed when using account_bank_statement_ext with voucher in order to compute the period
|
This module is only needed when using account_bank_statement_ext with voucher in order to compute the period
|
||||||
correctly. This is mainly because with account_bank_statement_ext, the period is computed for each line.
|
correctly. This is mainly because with account_bank_statement_ext, the period is computed for each line.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv
|
|
||||||
|
|
||||||
class AccountVoucher(Model):
|
class AccountVoucher(Model):
|
||||||
|
|
||||||
@@ -31,7 +31,8 @@ class AccountVoucher(Model):
|
|||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
if not context.get('period_id') and context.get('move_line_ids'):
|
if not context.get('period_id') and context.get('move_line_ids'):
|
||||||
res = self.pool.get('account.move.line').browse(cr, uid , context.get('move_line_ids'))[0].period_id.id
|
res = self.pool.get('account.move.line').browse(
|
||||||
|
cr, uid, context.get('move_line_ids'), context=context)[0].period_id.id
|
||||||
context['period_id'] = res
|
context['period_id'] = res
|
||||||
elif context.get('date'):
|
elif context.get('date'):
|
||||||
periods = self.pool.get('account.period').find(
|
periods = self.pool.get('account.period').find(
|
||||||
@@ -48,4 +49,3 @@ class AccountVoucher(Model):
|
|||||||
ctx = dict(context, date=values.get('date'))
|
ctx = dict(context, date=values.get('date'))
|
||||||
values['period_id'] = self._get_period(cr, uid, ctx)
|
values['period_id'] = self._get_period(cr, uid, ctx)
|
||||||
return super(AccountVoucher, self).create(cr, uid, values, context)
|
return super(AccountVoucher, self).create(cr, uid, values, context)
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
'author': 'Camptocamp',
|
'author': 'Camptocamp',
|
||||||
'maintainer': 'Camptocamp',
|
'maintainer': 'Camptocamp',
|
||||||
'category': 'Finance',
|
'category': 'Finance',
|
||||||
'complexity': 'normal', #easy, normal, expert
|
'complexity': 'normal',
|
||||||
'depends': ['account_statement_base_completion', 'base_transaction_id'],
|
'depends': [
|
||||||
|
'account_statement_base_completion',
|
||||||
|
'base_transaction_id'
|
||||||
|
],
|
||||||
'description': """
|
'description': """
|
||||||
Add a completion method based on transaction ID providen by the bank/office.
|
Add a completion method based on transaction ID providen by the bank/office.
|
||||||
|
|
||||||
|
|||||||
@@ -20,27 +20,27 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
import datetime
|
|
||||||
import netsvc
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields
|
||||||
from openerp.addons.account_statement_base_completion.statement import ErrorTooManyPartner
|
from openerp.addons.account_statement_base_completion.statement import ErrorTooManyPartner
|
||||||
|
|
||||||
|
|
||||||
class AccountStatementCompletionRule(Model):
|
class AccountStatementCompletionRule(Model):
|
||||||
"""Add a rule based on transaction ID"""
|
"""Add a rule based on transaction ID"""
|
||||||
|
|
||||||
_inherit = "account.statement.completion.rule"
|
_inherit = "account.statement.completion.rule"
|
||||||
|
|
||||||
def _get_functions(self, cr, uid, context=None):
|
def _get_functions(self, cr, uid, context=None):
|
||||||
res = super (AccountStatementCompletionRule, self)._get_functions(
|
res = super(AccountStatementCompletionRule, self)._get_functions(
|
||||||
cr, uid, context=context)
|
cr, uid, context=context)
|
||||||
res.append(('get_from_transaction_id_and_so', 'From line reference (based on SO transaction ID)'))
|
res.append(('get_from_transaction_id_and_so',
|
||||||
|
'From line reference (based on SO transaction ID)'))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
_columns={
|
_columns = {
|
||||||
'function_to_call': fields.selection(_get_functions, 'Method'),
|
'function_to_call': fields.selection(_get_functions, 'Method'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_from_transaction_id_and_so(self, cr, uid, line_id, context=None):
|
def get_from_transaction_id_and_so(self, cr, uid, line_id, context=None):
|
||||||
"""
|
"""
|
||||||
Match the partner based on the transaction ID field of the SO.
|
Match the partner based on the transaction ID field of the SO.
|
||||||
@@ -55,36 +55,45 @@ class AccountStatementCompletionRule(Model):
|
|||||||
...}
|
...}
|
||||||
"""
|
"""
|
||||||
st_obj = self.pool.get('account.bank.statement.line')
|
st_obj = self.pool.get('account.bank.statement.line')
|
||||||
st_line = st_obj.browse(cr,uid,line_id)
|
st_line = st_obj.browse(cr, uid, line_id, context=context)
|
||||||
res = {}
|
res = {}
|
||||||
if st_line:
|
if st_line:
|
||||||
so_obj = self.pool.get('sale.order')
|
so_obj = self.pool.get('sale.order')
|
||||||
so_id = so_obj.search(cr, uid, [('transaction_id', '=', st_line.transaction_id)])
|
so_id = so_obj.search(
|
||||||
|
cr,
|
||||||
|
uid,
|
||||||
|
[('transaction_id', '=', st_line.transaction_id)],
|
||||||
|
context=context)
|
||||||
if so_id and len(so_id) == 1:
|
if so_id and len(so_id) == 1:
|
||||||
so = so_obj.browse(cr, uid, so_id[0])
|
so = so_obj.browse(cr, uid, so_id[0], context=context)
|
||||||
res['partner_id'] = so.partner_id.id
|
res['partner_id'] = so.partner_id.id
|
||||||
res['ref'] = so.name
|
res['ref'] = so.name
|
||||||
elif so_id and len(so_id) > 1:
|
elif so_id and len(so_id) > 1:
|
||||||
raise ErrorTooManyPartner(_('Line named "%s" (Ref:%s) was matched by more than one partner.')%(st_line.name,st_line.ref))
|
raise ErrorTooManyPartner(
|
||||||
|
_('Line named "%s" (Ref:%s) was matched by more than '
|
||||||
|
'one partner.') % (st_line.name, st_line.ref))
|
||||||
if so_id:
|
if so_id:
|
||||||
st_vals = st_obj.get_values_for_line(cr, uid, profile_id = st_line.statement_id.profile_id.id,
|
st_vals = st_obj.get_values_for_line(
|
||||||
partner_id = res.get('partner_id',False), line_type = st_line.type, amount = st_line.amount, context=context)
|
cr,
|
||||||
|
uid,
|
||||||
|
profile_id=st_line.statement_id.profile_id.id,
|
||||||
|
partner_id=res.get('partner_id', False),
|
||||||
|
line_type=st_line.type,
|
||||||
|
amount=st_line.amount,
|
||||||
|
context=context)
|
||||||
res.update(st_vals)
|
res.update(st_vals)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
class AccountStatementLine(Model):
|
class AccountStatementLine(Model):
|
||||||
_inherit = "account.bank.statement.line"
|
_inherit = "account.bank.statement.line"
|
||||||
|
|
||||||
_columns={
|
_columns = {
|
||||||
# 'additionnal_bank_fields' : fields.serialized('Additionnal infos from bank', help="Used by completion and import system."),
|
# 'additionnal_bank_fields' : fields.serialized('Additionnal infos from bank', help="Used by completion and import system."),
|
||||||
'transaction_id': fields.sparse(type='char', string='Transaction ID',
|
'transaction_id': fields.sparse(
|
||||||
|
type='char',
|
||||||
|
string='Transaction ID',
|
||||||
size=128,
|
size=128,
|
||||||
serialization_field='additionnal_bank_fields',
|
serialization_field='additionnal_bank_fields',
|
||||||
help="Transction id from the financial institute"),
|
help="Transction id from the financial institute"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,4 +19,4 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
import parser
|
import parser
|
||||||
import statement
|
import statement
|
||||||
|
|||||||
@@ -24,8 +24,11 @@
|
|||||||
'author': 'Camptocamp',
|
'author': 'Camptocamp',
|
||||||
'maintainer': 'Camptocamp',
|
'maintainer': 'Camptocamp',
|
||||||
'category': 'Finance',
|
'category': 'Finance',
|
||||||
'complexity': 'normal', #easy, normal, expert
|
'complexity': 'normal',
|
||||||
'depends': ['account_statement_base_import','account_statement_transactionid_completion'],
|
'depends': [
|
||||||
|
'account_statement_base_import',
|
||||||
|
'account_statement_transactionid_completion'
|
||||||
|
],
|
||||||
'description': """
|
'description': """
|
||||||
This module brings generic methods and fields on bank statement to deal with
|
This module brings generic methods and fields on bank statement to deal with
|
||||||
the importation of different bank and offices that uses transactionID.
|
the importation of different bank and offices that uses transactionID.
|
||||||
@@ -36,12 +39,12 @@
|
|||||||
|
|
||||||
This module can handle a commission taken by the payment office and has the following format:
|
This module can handle a commission taken by the payment office and has the following format:
|
||||||
|
|
||||||
* transaction_id : the transaction ID given by the bank/office. It is used as reference
|
* transaction_id: the transaction ID given by the bank/office. It is used as reference
|
||||||
in the generated entries and is useful for reconciliation process
|
in the generated entries and is useful for reconciliation process
|
||||||
* date : date of the payment
|
* date: date of the payment
|
||||||
* amount : amount paid in the currency of the journal used in the importation profile
|
* amount: amount paid in the currency of the journal used in the importation profile
|
||||||
* commission_amount : amount of the comission for each line
|
* commission_amount: amount of the comission for each line
|
||||||
* label : the comunication given by the payment office, used as communication in the
|
* label: the comunication given by the payment office, used as communication in the
|
||||||
generated entries.
|
generated entries.
|
||||||
""",
|
""",
|
||||||
'website': 'http://www.camptocamp.com',
|
'website': 'http://www.camptocamp.com',
|
||||||
|
|||||||
@@ -19,6 +19,4 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# from parser import new_bank_statement_parser
|
import transactionid_file_parser
|
||||||
# from parser import BankStatementImportParser
|
|
||||||
import transactionid_file_parser
|
|
||||||
|
|||||||
@@ -19,23 +19,16 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
import base64
|
|
||||||
import csv
|
|
||||||
import tempfile
|
|
||||||
import datetime
|
import datetime
|
||||||
from account_statement_base_import.parser.file_parser import FileParser
|
from account_statement_base_import.parser.file_parser import FileParser
|
||||||
|
|
||||||
try:
|
|
||||||
import xlrd
|
|
||||||
except:
|
|
||||||
raise Exception(_('Please install python lib xlrd'))
|
|
||||||
|
|
||||||
class TransactionIDFileParser(FileParser):
|
class TransactionIDFileParser(FileParser):
|
||||||
"""
|
"""
|
||||||
TransactionID parser that use a define format in csv or xls to import
|
TransactionID parser that use a define format in csv or xls to import
|
||||||
bank statement.
|
bank statement.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parse_name, ftype='csv'):
|
def __init__(self, parse_name, ftype='csv'):
|
||||||
convertion_dict = {
|
convertion_dict = {
|
||||||
'transaction_id': unicode,
|
'transaction_id': unicode,
|
||||||
@@ -46,7 +39,7 @@ class TransactionIDFileParser(FileParser):
|
|||||||
}
|
}
|
||||||
# Order of cols does not matter but first row of the file has to be header
|
# Order of cols does not matter but first row of the file has to be header
|
||||||
keys_to_validate = ['transaction_id', 'label', 'date', 'amount', 'commission_amount']
|
keys_to_validate = ['transaction_id', 'label', 'date', 'amount', 'commission_amount']
|
||||||
super(TransactionIDFileParser,self).__init__(parse_name, keys_to_validate=keys_to_validate, ftype=ftype, convertion_dict=convertion_dict)
|
super(TransactionIDFileParser, self).__init__(parse_name, keys_to_validate=keys_to_validate, ftype=ftype, convertion_dict=convertion_dict)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parser_for(cls, parser_name):
|
def parser_for(cls, parser_name):
|
||||||
@@ -59,7 +52,7 @@ class TransactionIDFileParser(FileParser):
|
|||||||
def get_st_line_vals(self, line, *args, **kwargs):
|
def get_st_line_vals(self, line, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
This method must return a dict of vals that can be passed to create
|
This method must return a dict of vals that can be passed to create
|
||||||
method of statement line in order to record it. It is the responsibility
|
method of statement line in order to record it. It is the responsibility
|
||||||
of every parser to give this dict of vals, so each one can implement his
|
of every parser to give this dict of vals, so each one can implement his
|
||||||
own way of recording the lines.
|
own way of recording the lines.
|
||||||
:param: line: a dict of vals that represent a line of result_row_list
|
:param: line: a dict of vals that represent a line of result_row_list
|
||||||
@@ -77,12 +70,12 @@ class TransactionIDFileParser(FileParser):
|
|||||||
for each one.
|
for each one.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
'name': line.get('label', line.get('ref','/')),
|
'name': line.get('label', line.get('ref', '/')),
|
||||||
'date': line.get('date', datetime.datetime.now().date()),
|
'date': line.get('date', datetime.datetime.now().date()),
|
||||||
'amount': line.get('amount', 0.0),
|
'amount': line.get('amount', 0.0),
|
||||||
'ref': line.get('transaction_id','/'),
|
'ref': line.get('transaction_id', '/'),
|
||||||
'label': line.get('label',''),
|
'label': line.get('label', ''),
|
||||||
'transaction_id': line.get('transaction_id','/'),
|
'transaction_id': line.get('transaction_id', '/'),
|
||||||
'commission_amount': line.get('commission_amount', 0.0),
|
'commission_amount': line.get('commission_amount', 0.0),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +86,6 @@ class TransactionIDFileParser(FileParser):
|
|||||||
res = super(TransactionIDFileParser, self)._post(*args, **kwargs)
|
res = super(TransactionIDFileParser, self)._post(*args, **kwargs)
|
||||||
val = 0.0
|
val = 0.0
|
||||||
for row in self.result_row_list:
|
for row in self.result_row_list:
|
||||||
val += row.get('commission_amount',0.0)
|
val += row.get('commission_amount', 0.0)
|
||||||
self.commission_global_amount = val
|
self.commission_global_amount = val
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|||||||
@@ -20,24 +20,28 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields
|
||||||
|
|
||||||
|
|
||||||
class AccountStatementProfil(Model):
|
class AccountStatementProfil(Model):
|
||||||
_inherit = "account.statement.profile"
|
_inherit = "account.statement.profile"
|
||||||
|
|
||||||
|
|
||||||
def get_import_type_selection(self, cr, uid, context=None):
|
def get_import_type_selection(self, cr, uid, context=None):
|
||||||
"""
|
"""
|
||||||
Has to be inherited to add parser
|
Has to be inherited to add parser
|
||||||
"""
|
"""
|
||||||
res = super(AccountStatementProfil, self).get_import_type_selection(cr, uid, context=context)
|
res = super(AccountStatementProfil, self).get_import_type_selection(
|
||||||
res.append(('generic_csvxls_transaction','Generic .csv/.xls based on SO transaction ID'))
|
cr, uid, context=context)
|
||||||
|
res.append(('generic_csvxls_transaction',
|
||||||
|
'Generic .csv/.xls based on SO transaction ID'))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'import_type': fields.selection(get_import_type_selection, 'Type of import', required=True,
|
'import_type': fields.selection(
|
||||||
help = "Choose here the method by which you want to import bank statement for this profile."),
|
get_import_type_selection,
|
||||||
|
'Type of import',
|
||||||
|
required=True,
|
||||||
|
help="Choose here the method by which you want to import "
|
||||||
|
"bank statement for this profile."),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,18 +24,30 @@
|
|||||||
'author': 'Camptocamp',
|
'author': 'Camptocamp',
|
||||||
'maintainer': 'Camptocamp',
|
'maintainer': 'Camptocamp',
|
||||||
'category': 'Hidden/Dependency',
|
'category': 'Hidden/Dependency',
|
||||||
'complexity': 'easy', #easy, normal, expert
|
'complexity': 'easy',
|
||||||
'depends': ['account', 'sale','stock'],
|
'depends': [
|
||||||
|
'account',
|
||||||
|
'sale',
|
||||||
|
'stock'
|
||||||
|
],
|
||||||
'description': """
|
'description': """
|
||||||
Adds transaction id to invoice and sale models and views. On Sales order, you can specify the transaction ID
|
Adds transaction id to invoice and sale models and views.
|
||||||
used for the payment and it will be propagated to the invoice (even if made from packing).
|
On Sales order, you can specify the transaction ID used
|
||||||
This is mostly used for e-commerce handling. You can then add a mapping on that SO field to save the e-commerce
|
for the payment and it will be propagated to the invoice
|
||||||
financial Transaction ID into the OpenERP SO field. The main purpose is to ease the reconciliation process and
|
(even if made from packing).
|
||||||
|
This is mostly used for e-commerce handling.
|
||||||
|
You can then add a mapping on that SO field to save
|
||||||
|
the e-commerce financial Transaction ID into the
|
||||||
|
OpenERP sale order field.
|
||||||
|
The main purpose is to ease the reconciliation process and
|
||||||
be able to find the partner when importing the bank statement.
|
be able to find the partner when importing the bank statement.
|
||||||
""",
|
""",
|
||||||
'website': 'http://www.openerp.com',
|
'website': 'http://www.openerp.com',
|
||||||
'init_xml': [],
|
'init_xml': [],
|
||||||
'update_xml': ['invoice_view.xml', 'sale_view.xml'],
|
'update_xml': [
|
||||||
|
'invoice_view.xml',
|
||||||
|
'sale_view.xml'
|
||||||
|
],
|
||||||
'demo_xml': [],
|
'demo_xml': [],
|
||||||
'test': [],
|
'test': [],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
|
|||||||
@@ -20,17 +20,17 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields
|
||||||
from openerp.tools.translate import _
|
|
||||||
|
|
||||||
class AccountInvoice(Model):
|
class AccountInvoice(Model):
|
||||||
_inherit = 'account.invoice'
|
_inherit = 'account.invoice'
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'transaction_id':fields.char(
|
'transaction_id': fields.char(
|
||||||
'Transaction id',
|
'Transaction id',
|
||||||
size=128,
|
size=128,
|
||||||
required=False,
|
required=False,
|
||||||
select=1,
|
select=1,
|
||||||
help="Transction id from the financial institute"
|
help="Transction id from the financial institute"),
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,21 +20,24 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields
|
||||||
|
|
||||||
|
|
||||||
class SaleOrder(Model):
|
class SaleOrder(Model):
|
||||||
_inherit = 'sale.order'
|
_inherit = 'sale.order'
|
||||||
_columns = {
|
|
||||||
'transaction_id':fields.char('Transaction id', size=128,required=False,
|
|
||||||
help="Transction id from the financial institute"),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
_columns = {
|
||||||
|
'transaction_id': fields.char(
|
||||||
|
'Transaction id',
|
||||||
|
size=128,
|
||||||
|
required=False,
|
||||||
|
help="Transaction id from the financial institute"),
|
||||||
|
}
|
||||||
|
|
||||||
def _prepare_invoice(self, cursor, uid, order, lines, context=None):
|
def _prepare_invoice(self, cursor, uid, order, lines, context=None):
|
||||||
#we put the transaction id in the generated invoices
|
#we put the transaction id in the generated invoices
|
||||||
if context is None:
|
invoice_vals = super(SaleOrder, self)._prepare_invoice(
|
||||||
context = {}
|
cursor, uid, order, lines, context=context)
|
||||||
invoice_vals = super(SaleOrder, self)._prepare_invoice(cursor, uid, order, lines, context)
|
|
||||||
invoice_vals.update({
|
invoice_vals.update({
|
||||||
'transaction_id': order.transaction_id})
|
'transaction_id': order.transaction_id})
|
||||||
return invoice_vals
|
return invoice_vals
|
||||||
|
|||||||
@@ -20,20 +20,23 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from openerp.osv.orm import Model
|
from openerp.osv.orm import Model
|
||||||
from openerp.osv import fields, osv
|
|
||||||
|
|
||||||
class StockPicking(Model):
|
class StockPicking(Model):
|
||||||
_inherit = "stock.picking"
|
_inherit = "stock.picking"
|
||||||
|
|
||||||
def action_invoice_create(self, cursor, uid, ids, journal_id=False,
|
def action_invoice_create(
|
||||||
group=False, type='out_invoice', context=None):
|
self, cursor, uid, ids, journal_id=False, group=False,
|
||||||
res = super(StockPicking, self).action_invoice_create(cursor, uid, ids,
|
type='out_invoice', context=None):
|
||||||
journal_id,group, type, context)
|
res = super(StockPicking, self).action_invoice_create(
|
||||||
|
cursor, uid, ids, journal_id, group, type, context)
|
||||||
for pick_id in res:
|
for pick_id in res:
|
||||||
pick = self.browse(cursor, uid, pick_id)
|
pick = self.browse(cursor, uid, pick_id, context=context)
|
||||||
if pick.sale_id and pick.sale_id.transaction_id:
|
if pick.sale_id and pick.sale_id.transaction_id:
|
||||||
self.pool.get('account.invoice').write(cursor,
|
self.pool.get('account.invoice').write(
|
||||||
uid,
|
cursor,
|
||||||
res[pick_id],
|
uid,
|
||||||
{'transaction_id': pick.sale_id.transaction_id})
|
res[pick_id],
|
||||||
|
{'transaction_id': pick.sale_id.transaction_id},
|
||||||
|
context=context)
|
||||||
return res
|
return res
|
||||||
|
|||||||
Reference in New Issue
Block a user