2009-10-13 05:58:37 +00:00
# -*- coding: utf-8 -*-
2007-01-04 09:45:50 +00:00
##############################################################################
2009-11-25 09:31:44 +00:00
#
2009-10-14 11:15:34 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2007-01-04 09:45:50 +00:00
#
2008-11-03 19:18:56 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 11:15:34 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2007-01-04 09:45:50 +00:00
#
2008-11-03 19:18:56 +00:00
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2009-10-14 11:15:34 +00:00
# GNU Affero General Public License for more details.
2007-01-04 09:45:50 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2009-11-25 09:31:44 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2007-01-04 09:45:50 +00:00
#
##############################################################################
2009-10-14 11:15:34 +00:00
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
2015-05-05 16:12:46 +00:00
from openerp . tools import float_is_zero
2012-12-06 14:56:32 +00:00
from openerp . tools . translate import _
2012-12-17 15:23:03 +00:00
import openerp . addons . decimal_precision as dp
2014-05-30 16:47:50 +00:00
from openerp . report import report_sxw
2014-11-27 13:57:11 +00:00
from openerp . tools import float_compare , float_round
2007-01-04 09:45:50 +00:00
2014-08-21 08:54:38 +00:00
import time
2007-01-04 09:45:50 +00:00
class account_bank_statement ( osv . osv ) :
2010-09-14 17:53:07 +00:00
def create ( self , cr , uid , vals , context = None ) :
2014-06-17 15:29:40 +00:00
if vals . get ( ' name ' , ' / ' ) == ' / ' :
journal_id = vals . get ( ' journal_id ' , self . _default_journal_id ( cr , uid , context = context ) )
vals [ ' name ' ] = self . _compute_default_statement_name ( cr , uid , journal_id , context = context )
2010-09-14 18:13:52 +00:00
if ' line_ids ' in vals :
2012-04-17 14:53:22 +00:00
for idx , line in enumerate ( vals [ ' line_ids ' ] ) :
line [ 2 ] [ ' sequence ' ] = idx + 1
2010-09-14 17:53:07 +00:00
return super ( account_bank_statement , self ) . create ( cr , uid , vals , context = context )
def write ( self , cr , uid , ids , vals , context = None ) :
res = super ( account_bank_statement , self ) . write ( cr , uid , ids , vals , context = context )
2010-10-20 10:12:02 +00:00
account_bank_statement_line_obj = self . pool . get ( ' account.bank.statement.line ' )
2010-09-14 17:53:07 +00:00
for statement in self . browse ( cr , uid , ids , context ) :
2012-04-17 14:53:22 +00:00
for idx , line in enumerate ( statement . line_ids ) :
account_bank_statement_line_obj . write ( cr , uid , [ line . id ] , { ' sequence ' : idx + 1 } , context = context )
2010-09-14 17:53:07 +00:00
return res
2010-11-19 13:48:01 +00:00
def _default_journal_id ( self , cr , uid , context = None ) :
2010-11-23 11:31:52 +00:00
if context is None :
context = { }
2010-07-30 11:12:06 +00:00
journal_pool = self . pool . get ( ' account.journal ' )
journal_type = context . get ( ' journal_type ' , False )
2012-01-24 15:27:47 +00:00
company_id = self . pool . get ( ' res.company ' ) . _company_default_get ( cr , uid , ' account.bank.statement ' , context = context )
2010-07-30 11:12:06 +00:00
if journal_type :
2012-01-24 15:27:47 +00:00
ids = journal_pool . search ( cr , uid , [ ( ' type ' , ' = ' , journal_type ) , ( ' company_id ' , ' = ' , company_id ) ] )
2010-07-30 11:12:06 +00:00
if ids :
2012-04-17 14:53:22 +00:00
return ids [ 0 ]
return False
2008-07-22 15:11:28 +00:00
def _end_balance ( self , cursor , user , ids , name , attr , context = None ) :
res = { }
2012-05-12 22:37:43 +00:00
for statement in self . browse ( cursor , user , ids , context = context ) :
2008-07-22 15:11:28 +00:00
res [ statement . id ] = statement . balance_start
2012-05-12 22:37:43 +00:00
for line in statement . line_ids :
res [ statement . id ] + = line . amount
2008-07-22 15:11:28 +00:00
return res
2010-11-19 13:48:01 +00:00
def _get_period ( self , cr , uid , context = None ) :
2013-04-18 10:39:07 +00:00
periods = self . pool . get ( ' account.period ' ) . find ( cr , uid , context = context )
2008-07-22 15:11:28 +00:00
if periods :
return periods [ 0 ]
2010-08-30 06:28:31 +00:00
return False
2008-07-22 15:11:28 +00:00
2014-06-17 15:29:40 +00:00
def _compute_default_statement_name ( self , cr , uid , journal_id , context = None ) :
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2014-05-30 16:47:50 +00:00
obj_seq = self . pool . get ( ' ir.sequence ' )
2014-06-17 15:29:40 +00:00
period = self . pool . get ( ' account.period ' ) . browse ( cr , uid , self . _get_period ( cr , uid , context = context ) , context = context )
context [ ' fiscalyear_id ' ] = period . fiscalyear_id . id
journal = self . pool . get ( ' account.journal ' ) . browse ( cr , uid , journal_id , None )
return obj_seq . next_by_id ( cr , uid , journal . sequence_id . id , context = context )
2014-05-30 16:47:50 +00:00
2008-07-22 15:11:28 +00:00
def _currency ( self , cursor , user , ids , name , args , context = None ) :
res = { }
res_currency_obj = self . pool . get ( ' res.currency ' )
res_users_obj = self . pool . get ( ' res.users ' )
default_currency = res_users_obj . browse ( cursor , user ,
user , context = context ) . company_id . currency_id
for statement in self . browse ( cursor , user , ids , context = context ) :
currency = statement . journal_id . currency
if not currency :
currency = default_currency
res [ statement . id ] = currency . id
currency_names = { }
for currency_id , currency_name in res_currency_obj . name_get ( cursor ,
user , [ x for x in res . values ( ) ] , context = context ) :
currency_names [ currency_id ] = currency_name
for statement_id in res . keys ( ) :
currency_id = res [ statement_id ]
res [ statement_id ] = ( currency_id , currency_names [ currency_id ] )
return res
2010-08-14 05:37:43 +00:00
2011-09-25 21:00:20 +00:00
def _get_statement ( self , cr , uid , ids , context = None ) :
result = { }
for line in self . pool . get ( ' account.bank.statement.line ' ) . browse ( cr , uid , ids , context = context ) :
result [ line . statement_id . id ] = True
return result . keys ( )
2014-05-30 16:47:50 +00:00
def _all_lines_reconciled ( self , cr , uid , ids , name , args , context = None ) :
res = { }
for statement in self . browse ( cr , uid , ids , context = context ) :
2015-01-15 15:42:30 +00:00
res [ statement . id ] = all ( [ line . journal_entry_id . id or line . account_id . id for line in statement . line_ids ] )
2014-05-30 16:47:50 +00:00
return res
2010-11-04 04:54:38 +00:00
_order = " date desc, id desc "
2008-07-22 15:11:28 +00:00
_name = " account.bank.statement "
_description = " Bank Statement "
2012-05-07 12:07:07 +00:00
_inherit = [ ' mail.thread ' ]
2008-07-22 15:11:28 +00:00
_columns = {
2014-07-06 14:44:26 +00:00
' name ' : fields . char (
' Reference ' , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ,
readonly = True , # readonly for account_cash_statement
copy = False ,
help = ' if you give the Name other then /, its created Accounting Entries Move '
' will be with same name as statement name. '
' This allows the statement entries to have the same references than the '
' statement itself ' ) ,
' date ' : fields . date ( ' Date ' , required = True , states = { ' confirm ' : [ ( ' readonly ' , True ) ] } ,
select = True , copy = False ) ,
2008-07-22 15:11:28 +00:00
' journal_id ' : fields . many2one ( ' account.journal ' , ' Journal ' , required = True ,
2010-09-27 06:15:38 +00:00
readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2008-07-22 15:11:28 +00:00
' period_id ' : fields . many2one ( ' account.period ' , ' Period ' , required = True ,
states = { ' confirm ' : [ ( ' readonly ' , True ) ] } ) ,
2010-07-15 13:07:11 +00:00
' balance_start ' : fields . float ( ' Starting Balance ' , digits_compute = dp . get_precision ( ' Account ' ) ,
2008-07-22 15:11:28 +00:00
states = { ' confirm ' : [ ( ' readonly ' , True ) ] } ) ,
2010-07-15 13:07:11 +00:00
' balance_end_real ' : fields . float ( ' Ending Balance ' , digits_compute = dp . get_precision ( ' Account ' ) ,
2013-03-15 10:08:04 +00:00
states = { ' confirm ' : [ ( ' readonly ' , True ) ] } , help = " Computed using the cash control lines " ) ,
2011-10-12 11:36:55 +00:00
' balance_end ' : fields . function ( _end_balance ,
2011-09-25 21:00:20 +00:00
store = {
2012-05-12 22:37:43 +00:00
' account.bank.statement ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' line_ids ' , ' move_line_ids ' , ' balance_start ' ] , 10 ) ,
2011-09-25 21:00:20 +00:00
' account.bank.statement.line ' : ( _get_statement , [ ' amount ' ] , 10 ) ,
} ,
2013-03-14 05:37:27 +00:00
string = " Computed Balance " , help = ' Balance as calculated based on Opening Balance and transaction lines ' ) ,
2010-09-14 17:53:07 +00:00
' company_id ' : fields . related ( ' journal_id ' , ' company_id ' , type = ' many2one ' , relation = ' res.company ' , string = ' Company ' , store = True , readonly = True ) ,
2008-07-22 15:11:28 +00:00
' line_ids ' : fields . one2many ( ' account.bank.statement.line ' ,
2014-07-06 14:44:26 +00:00
' statement_id ' , ' Statement lines ' ,
states = { ' confirm ' : [ ( ' readonly ' , True ) ] } , copy = True ) ,
2008-07-22 15:11:28 +00:00
' move_line_ids ' : fields . one2many ( ' account.move.line ' , ' statement_id ' ,
2014-07-06 14:44:26 +00:00
' Entry lines ' , states = { ' confirm ' : [ ( ' readonly ' , True ) ] } ) ,
2011-09-22 06:14:19 +00:00
' state ' : fields . selection ( [ ( ' draft ' , ' New ' ) ,
2011-09-17 00:50:07 +00:00
( ' open ' , ' Open ' ) , # used by cash statements
( ' confirm ' , ' Closed ' ) ] ,
2012-05-04 11:57:48 +00:00
' Status ' , required = True , readonly = " 1 " ,
2014-07-06 14:44:26 +00:00
copy = False ,
2012-10-12 12:45:13 +00:00
help = ' When new statement is created the status will be \' Draft \' . \n '
' And after getting confirmation from the bank it will be in \' Confirmed \' status. ' ) ,
2011-07-01 23:41:24 +00:00
' currency ' : fields . function ( _currency , string = ' Currency ' ,
2008-07-22 15:11:28 +00:00
type = ' many2one ' , relation = ' res.currency ' ) ,
2010-11-26 15:14:46 +00:00
' account_id ' : fields . related ( ' journal_id ' , ' default_debit_account_id ' , type = ' many2one ' , relation = ' account.account ' , string = ' Account used in this journal ' , readonly = True , help = ' used in statement reconciliation domain, but shouldn \' t be used elswhere. ' ) ,
2013-09-18 10:47:20 +00:00
' cash_control ' : fields . related ( ' journal_id ' , ' cash_control ' , type = ' boolean ' , relation = ' account.journal ' , string = ' Cash control ' ) ,
2014-05-30 16:47:50 +00:00
' all_lines_reconciled ' : fields . function ( _all_lines_reconciled , string = ' All lines reconciled ' , type = ' boolean ' ) ,
2008-07-22 15:11:28 +00:00
}
2008-08-22 11:53:40 +00:00
2008-07-22 15:11:28 +00:00
_defaults = {
2015-02-16 18:23:36 +00:00
' name ' : ' / ' ,
2012-02-13 18:07:41 +00:00
' date ' : fields . date . context_today ,
2010-09-23 06:38:30 +00:00
' state ' : ' draft ' ,
2008-07-22 15:11:28 +00:00
' journal_id ' : _default_journal_id ,
' period_id ' : _get_period ,
2011-04-07 15:06:57 +00:00
' company_id ' : lambda self , cr , uid , c : self . pool . get ( ' res.company ' ) . _company_default_get ( cr , uid , ' account.bank.statement ' , context = c ) ,
2008-07-22 15:11:28 +00:00
}
2012-01-25 09:29:32 +00:00
def _check_company_id ( self , cr , uid , ids , context = None ) :
for statement in self . browse ( cr , uid , ids , context = context ) :
if statement . company_id . id != statement . period_id . company_id . id :
return False
return True
_constraints = [
( _check_company_id , ' The journal and period chosen have to belong to the same company. ' , [ ' journal_id ' , ' period_id ' ] ) ,
]
2012-01-24 15:27:47 +00:00
def onchange_date ( self , cr , uid , ids , date , company_id , context = None ) :
2010-07-26 14:41:32 +00:00
"""
2012-01-24 15:27:47 +00:00
Find the correct period to use for the given date and company_id , return it and set it in the context
2010-07-26 14:41:32 +00:00
"""
res = { }
period_pool = self . pool . get ( ' account.period ' )
2010-09-23 06:38:30 +00:00
if context is None :
context = { }
2012-01-24 15:27:47 +00:00
ctx = context . copy ( )
ctx . update ( { ' company_id ' : company_id } )
pids = period_pool . find ( cr , uid , dt = date , context = ctx )
2010-07-26 14:41:32 +00:00
if pids :
2012-01-24 15:27:47 +00:00
res . update ( { ' period_id ' : pids [ 0 ] } )
2014-07-06 14:44:26 +00:00
context = dict ( context , period_id = pids [ 0 ] )
2010-08-14 05:37:43 +00:00
2010-07-26 14:41:32 +00:00
return {
' value ' : res ,
' context ' : context ,
}
2010-08-11 14:09:35 +00:00
2010-09-23 06:38:30 +00:00
def button_dummy ( self , cr , uid , ids , context = None ) :
return self . write ( cr , uid , ids , { } , context = context )
2010-09-17 14:30:45 +00:00
2012-06-21 10:40:18 +00:00
def _prepare_move ( self , cr , uid , st_line , st_line_number , context = None ) :
""" Prepare the dict of values to create the move from a
statement line . This method may be overridden to implement custom
move generation ( making sure to call super ( ) to establish
a clean extension chain ) .
: param browse_record st_line : account . bank . statement . line record to
create the move from .
: param char st_line_number : will be used as the name of the generated account move
: return : dict of value to create ( ) the account . move
"""
2012-07-25 08:25:39 +00:00
return {
2012-06-21 10:40:18 +00:00
' journal_id ' : st_line . statement_id . journal_id . id ,
' period_id ' : st_line . statement_id . period_id . id ,
' date ' : st_line . date ,
' name ' : st_line_number ,
' ref ' : st_line . ref ,
}
2012-07-25 08:25:39 +00:00
2014-10-06 15:10:50 +00:00
def _get_counter_part_account ( self , cr , uid , st_line , context = None ) :
2012-08-07 11:06:16 +00:00
""" Retrieve the account to use in the counterpart move.
2012-06-21 10:40:18 +00:00
2014-06-16 08:38:01 +00:00
: param browse_record st_line : account . bank . statement . line record to create the move from .
2012-06-21 10:40:18 +00:00
: return : int / long of the account . account to use as counterpart
"""
if st_line . amount > = 0 :
2012-07-25 08:25:39 +00:00
return st_line . statement_id . journal_id . default_credit_account_id . id
return st_line . statement_id . journal_id . default_debit_account_id . id
2012-06-21 10:40:18 +00:00
2014-10-06 15:10:50 +00:00
def _get_counter_part_partner ( self , cr , uid , st_line , context = None ) :
2012-08-07 11:06:16 +00:00
""" Retrieve the partner to use in the counterpart move.
2012-06-21 10:40:18 +00:00
2014-06-16 08:38:01 +00:00
: param browse_record st_line : account . bank . statement . line record to create the move from .
2012-06-21 10:40:18 +00:00
: return : int / long of the res . partner to use as counterpart
"""
2012-07-25 08:25:39 +00:00
return st_line . partner_id and st_line . partner_id . id or False
2012-06-21 10:40:18 +00:00
2014-05-30 16:47:50 +00:00
def _prepare_bank_move_line ( self , cr , uid , st_line , move_id , amount , company_currency_id , context = None ) :
2012-06-21 10:40:18 +00:00
""" Compute the args to build the dict of values to create the counter part move line from a
2015-02-16 18:23:36 +00:00
statement line by calling the _prepare_move_line_vals .
2012-06-21 10:40:18 +00:00
2014-06-16 08:38:01 +00:00
: param browse_record st_line : account . bank . statement . line record to create the move from .
2012-06-21 10:40:18 +00:00
: param int / long move_id : ID of the account . move to link the move line
: param float amount : amount of the move line
: param int / long company_currency_id : ID of currency of the concerned company
: return : dict of value to create ( ) the bank account . move . line
"""
account_id = self . _get_counter_part_account ( cr , uid , st_line , context = context )
partner_id = self . _get_counter_part_partner ( cr , uid , st_line , context = context )
debit = ( ( amount > 0 ) and amount ) or 0.0
2014-05-30 16:47:50 +00:00
credit = ( ( amount < 0 ) and - amount ) or 0.0
2012-06-21 10:40:18 +00:00
cur_id = False
amt_cur = False
2014-05-30 16:47:50 +00:00
if st_line . statement_id . currency . id != company_currency_id :
2012-06-21 10:40:18 +00:00
amt_cur = st_line . amount
2014-08-28 09:09:48 +00:00
cur_id = st_line . statement_id . currency . id
elif st_line . currency_id and st_line . amount_currency :
2014-05-30 16:47:50 +00:00
amt_cur = st_line . amount_currency
cur_id = st_line . currency_id . id
2012-08-07 11:06:16 +00:00
return self . _prepare_move_line_vals ( cr , uid , st_line , move_id , debit , credit ,
2014-05-30 16:47:50 +00:00
amount_currency = amt_cur , currency_id = cur_id , account_id = account_id ,
partner_id = partner_id , context = context )
2012-07-25 08:25:39 +00:00
2014-05-30 16:47:50 +00:00
def _prepare_move_line_vals ( self , cr , uid , st_line , move_id , debit , credit , currency_id = False ,
amount_currency = False , account_id = False , partner_id = False , context = None ) :
2012-06-21 10:40:18 +00:00
""" Prepare the dict of values to create the move line from a
2014-06-16 08:38:01 +00:00
statement line .
2012-06-21 10:40:18 +00:00
: param browse_record st_line : account . bank . statement . line record to
create the move from .
: param int / long move_id : ID of the account . move to link the move line
: param float debit : debit amount of the move line
: param float credit : credit amount of the move line
: param int / long currency_id : ID of currency of the move line to create
: param float amount_currency : amount of the debit / credit expressed in the currency_id
: param int / long account_id : ID of the account to use in the move line if different
from the statement line account ID
: param int / long partner_id : ID of the partner to put on the move line
: return : dict of value to create ( ) the account . move . line
"""
2012-07-25 08:25:39 +00:00
acc_id = account_id or st_line . account_id . id
cur_id = currency_id or st_line . statement_id . currency . id
par_id = partner_id or ( ( ( st_line . partner_id ) and st_line . partner_id . id ) or False )
return {
2012-06-21 10:40:18 +00:00
' name ' : st_line . name ,
' date ' : st_line . date ,
' ref ' : st_line . ref ,
' move_id ' : move_id ,
2012-09-17 15:05:48 +00:00
' partner_id ' : par_id ,
2012-06-21 10:40:18 +00:00
' account_id ' : acc_id ,
' credit ' : credit ,
' debit ' : debit ,
' statement_id ' : st_line . statement_id . id ,
' journal_id ' : st_line . statement_id . journal_id . id ,
' period_id ' : st_line . statement_id . period_id . id ,
2012-10-26 11:35:02 +00:00
' currency_id ' : amount_currency and cur_id ,
2012-07-25 08:25:39 +00:00
' amount_currency ' : amount_currency ,
2012-06-21 10:40:18 +00:00
}
2010-09-22 15:41:58 +00:00
def balance_check ( self , cr , uid , st_id , journal_type = ' bank ' , context = None ) :
2010-11-19 13:48:01 +00:00
st = self . browse ( cr , uid , st_id , context = context )
2012-05-12 22:37:43 +00:00
if not ( ( abs ( ( st . balance_end or 0.0 ) - st . balance_end_real ) < 0.0001 ) or ( abs ( ( st . balance_end or 0.0 ) - st . balance_end_real ) < 0.0001 ) ) :
2012-08-07 11:31:37 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) ,
2011-03-09 04:58:22 +00:00
_ ( ' The statement balance is incorrect ! \n The expected balance ( %.2f ) is different than the computed one. ( %.2f ) ' ) % ( st . balance_end_real , st . balance_end ) )
2010-09-22 15:41:58 +00:00
return True
def statement_close ( self , cr , uid , ids , journal_type = ' bank ' , context = None ) :
return self . write ( cr , uid , ids , { ' state ' : ' confirm ' } , context = context )
def check_status_condition ( self , cr , uid , state , journal_type = ' bank ' ) :
2011-09-25 21:00:20 +00:00
return state in ( ' draft ' , ' open ' )
2010-09-22 15:41:58 +00:00
2010-09-17 14:30:45 +00:00
def button_confirm_bank ( self , cr , uid , ids , context = None ) :
2010-08-16 07:03:58 +00:00
if context is None :
context = { }
2008-07-22 15:11:28 +00:00
2010-11-19 13:48:01 +00:00
for st in self . browse ( cr , uid , ids , context = context ) :
2010-09-22 15:41:58 +00:00
j_type = st . journal_id . type
if not self . check_status_condition ( cr , uid , st . state , journal_type = j_type ) :
2008-07-22 15:11:28 +00:00
continue
2010-09-23 06:38:30 +00:00
2010-09-22 15:41:58 +00:00
self . balance_check ( cr , uid , st . id , journal_type = j_type , context = context )
2008-07-22 15:11:28 +00:00
if ( not st . journal_id . default_credit_account_id ) \
or ( not st . journal_id . default_debit_account_id ) :
2014-05-30 16:47:50 +00:00
raise osv . except_osv ( _ ( ' Configuration Error! ' ) , _ ( ' Please verify that an account is defined in the journal. ' ) )
2008-07-22 15:11:28 +00:00
for line in st . move_line_ids :
2014-07-18 13:43:00 +00:00
if line . state != ' valid ' :
2014-05-30 16:47:50 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' The account entries lines are not in valid state. ' ) )
move_ids = [ ]
2010-09-17 14:30:45 +00:00
for st_line in st . line_ids :
if not st_line . amount :
2008-07-22 15:11:28 +00:00
continue
2014-07-18 13:43:00 +00:00
if st_line . account_id and not st_line . journal_entry_id . id :
#make an account move as before
vals = {
' debit ' : st_line . amount < 0 and - st_line . amount or 0.0 ,
' credit ' : st_line . amount > 0 and st_line . amount or 0.0 ,
' account_id ' : st_line . account_id . id ,
' name ' : st_line . name
}
self . pool . get ( ' account.bank.statement.line ' ) . process_reconciliation ( cr , uid , st_line . id , [ vals ] , context = context )
elif not st_line . journal_entry_id . id :
2014-05-30 16:47:50 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' All the account entries lines must be processed in order to close the statement. ' ) )
move_ids . append ( st_line . journal_entry_id . id )
2014-07-18 13:43:00 +00:00
if move_ids :
self . pool . get ( ' account.move ' ) . post ( cr , uid , move_ids , context = context )
2014-05-30 16:47:50 +00:00
self . message_post ( cr , uid , [ st . id ] , body = _ ( ' Statement %s confirmed, journal items were created. ' ) % ( st . name , ) , context = context )
2014-06-17 10:13:54 +00:00
self . link_bank_to_partner ( cr , uid , ids , context = context )
2014-08-21 08:54:38 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' confirm ' , ' closing_date ' : time . strftime ( " % Y- % m- %d % H: % M: % S " ) } , context = context )
2008-07-22 15:11:28 +00:00
2010-09-23 06:38:30 +00:00
def button_cancel ( self , cr , uid , ids , context = None ) :
2014-07-04 09:07:23 +00:00
bnk_st_line_ids = [ ]
2010-11-19 13:48:01 +00:00
for st in self . browse ( cr , uid , ids , context = context ) :
2014-07-04 09:07:23 +00:00
bnk_st_line_ids + = [ line . id for line in st . line_ids ]
self . pool . get ( ' account.bank.statement.line ' ) . cancel ( cr , uid , bnk_st_line_ids , context = context )
2014-06-17 11:48:52 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' draft ' } , context = context )
2012-08-07 11:06:16 +00:00
2012-04-26 12:30:17 +00:00
def _compute_balance_end_real ( self , cr , uid , journal_id , context = None ) :
2012-09-25 07:10:40 +00:00
res = False
if journal_id :
2014-01-02 11:30:09 +00:00
journal = self . pool . get ( ' account.journal ' ) . browse ( cr , uid , journal_id , context = context )
2013-12-30 07:24:52 +00:00
if journal . with_last_closing_balance :
cr . execute ( ' SELECT balance_end_real \
FROM account_bank_statement \
WHERE journal_id = % s AND NOT state = % s \
ORDER BY date DESC , id DESC LIMIT 1 ' , (journal_id, ' draft ' ))
res = cr . fetchone ( )
2012-04-26 12:30:17 +00:00
return res and res [ 0 ] or 0.0
def onchange_journal_id ( self , cr , uid , statement_id , journal_id , context = None ) :
2012-09-05 10:31:36 +00:00
if not journal_id :
return { }
2012-04-26 12:30:17 +00:00
balance_start = self . _compute_balance_end_real ( cr , uid , journal_id , context = context )
2013-09-18 09:10:41 +00:00
journal = self . pool . get ( ' account.journal ' ) . browse ( cr , uid , journal_id , context = context )
currency = journal . currency or journal . company_id . currency_id
2014-01-02 11:30:09 +00:00
res = { ' balance_start ' : balance_start , ' company_id ' : journal . company_id . id , ' currency ' : currency . id }
2013-09-18 10:47:20 +00:00
if journal . type == ' cash ' :
res [ ' cash_control ' ] = journal . cash_control
return { ' value ' : res }
2007-09-05 14:02:52 +00:00
2010-02-04 11:47:04 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
2014-10-25 13:19:20 +00:00
statement_line_obj = self . pool [ ' account.bank.statement.line ' ]
2014-07-06 14:44:26 +00:00
for item in self . browse ( cr , uid , ids , context = context ) :
if item . state != ' draft ' :
raise osv . except_osv (
2015-02-16 18:23:36 +00:00
_ ( ' Invalid Action! ' ) ,
2014-07-06 14:44:26 +00:00
_ ( ' In order to delete a bank statement, you must first cancel it to delete related journal items. ' )
)
2014-10-25 13:19:20 +00:00
# Explicitly unlink bank statement lines
# so it will check that the related journal entries have
# been deleted first
statement_line_obj . unlink ( cr , uid , [ line . id for line in item . line_ids ] , context = context )
2014-07-06 14:44:26 +00:00
return super ( account_bank_statement , self ) . unlink ( cr , uid , ids , context = context )
2010-04-16 14:37:24 +00:00
2012-11-08 11:48:54 +00:00
def button_journal_entries ( self , cr , uid , ids , context = None ) :
2014-05-30 16:47:50 +00:00
ctx = ( context or { } ) . copy ( )
ctx [ ' journal_id ' ] = self . browse ( cr , uid , ids [ 0 ] , context = context ) . journal_id . id
return {
' name ' : _ ( ' Journal Items ' ) ,
' view_type ' : ' form ' ,
' view_mode ' : ' tree ' ,
' res_model ' : ' account.move.line ' ,
' view_id ' : False ,
' type ' : ' ir.actions.act_window ' ,
' domain ' : [ ( ' statement_id ' , ' in ' , ids ) ] ,
' context ' : ctx ,
}
2014-06-18 12:37:29 +00:00
2014-09-04 09:32:16 +00:00
def number_of_lines_reconciled ( self , cr , uid , ids , context = None ) :
2014-06-18 12:37:29 +00:00
bsl_obj = self . pool . get ( ' account.bank.statement.line ' )
2014-09-04 09:32:16 +00:00
return bsl_obj . search_count ( cr , uid , [ ( ' statement_id ' , ' in ' , ids ) , ( ' journal_entry_id ' , ' != ' , False ) ] , context = context )
2014-06-02 00:28:15 +00:00
2014-06-17 10:13:54 +00:00
def link_bank_to_partner ( self , cr , uid , ids , context = None ) :
for statement in self . browse ( cr , uid , ids , context = context ) :
for st_line in statement . line_ids :
if st_line . bank_account_id and st_line . partner_id and st_line . bank_account_id . partner_id . id != st_line . partner_id . id :
2015-02-16 10:22:05 +00:00
# Update the partner informations of the bank account, possibly overriding existing ones
bank_obj = self . pool . get ( ' res.partner.bank ' )
bank_vals = bank_obj . onchange_partner_id ( cr , uid , [ st_line . bank_account_id . id ] , st_line . partner_id . id , context = context ) [ ' value ' ]
bank_vals . update ( { ' partner_id ' : st_line . partner_id . id } )
bank_obj . write ( cr , uid , [ st_line . bank_account_id . id ] , bank_vals , context = context )
2014-06-17 10:13:54 +00:00
2007-01-04 09:45:50 +00:00
class account_bank_statement_line ( osv . osv ) :
2007-09-05 14:02:52 +00:00
2014-09-16 10:23:13 +00:00
def create ( self , cr , uid , vals , context = None ) :
2014-09-17 09:18:16 +00:00
if vals . get ( ' amount_currency ' , 0 ) and not vals . get ( ' amount ' , 0 ) :
2014-09-16 10:23:13 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' If " Amount Currency " is specified, then " Amount " must be as well. ' ) )
return super ( account_bank_statement_line , self ) . create ( cr , uid , vals , context = context )
2014-08-29 17:13:41 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
for item in self . browse ( cr , uid , ids , context = context ) :
if item . journal_entry_id :
raise osv . except_osv (
2015-02-16 18:23:36 +00:00
_ ( ' Invalid Action! ' ) ,
2014-08-29 17:13:41 +00:00
_ ( ' In order to delete a bank statement line, you must first cancel it to delete related journal items. ' )
)
return super ( account_bank_statement_line , self ) . unlink ( cr , uid , ids , context = context )
2014-07-04 09:07:23 +00:00
def cancel ( self , cr , uid , ids , context = None ) :
account_move_obj = self . pool . get ( ' account.move ' )
move_ids = [ ]
for line in self . browse ( cr , uid , ids , context = context ) :
if line . journal_entry_id :
move_ids . append ( line . journal_entry_id . id )
for aml in line . journal_entry_id . line_id :
if aml . reconcile_id :
move_lines = [ l . id for l in aml . reconcile_id . line_id ]
move_lines . remove ( aml . id )
self . pool . get ( ' account.move.reconcile ' ) . unlink ( cr , uid , [ aml . reconcile_id . id ] , context = context )
if len ( move_lines ) > = 2 :
self . pool . get ( ' account.move.line ' ) . reconcile_partial ( cr , uid , move_lines , ' auto ' , context = context )
if move_ids :
account_move_obj . button_cancel ( cr , uid , move_ids , context = context )
account_move_obj . unlink ( cr , uid , move_ids , context )
2014-09-04 09:32:16 +00:00
def get_data_for_reconciliations ( self , cr , uid , ids , excluded_ids = None , search_reconciliation_proposition = True , context = None ) :
""" Returns the data required to display a reconciliation, for each statement line id in ids """
2014-05-30 16:47:50 +00:00
ret = [ ]
2014-09-04 09:32:16 +00:00
if excluded_ids is None :
excluded_ids = [ ]
2014-06-20 14:56:27 +00:00
for st_line in self . browse ( cr , uid , ids , context = context ) :
2014-09-04 09:32:16 +00:00
reconciliation_data = { }
if search_reconciliation_proposition :
reconciliation_proposition = self . get_reconciliation_proposition ( cr , uid , st_line , excluded_ids = excluded_ids , context = context )
for mv_line in reconciliation_proposition :
excluded_ids . append ( mv_line [ ' id ' ] )
reconciliation_data [ ' reconciliation_proposition ' ] = reconciliation_proposition
2014-06-20 14:56:27 +00:00
else :
2014-09-04 09:32:16 +00:00
reconciliation_data [ ' reconciliation_proposition ' ] = [ ]
st_line = self . get_statement_line_for_reconciliation ( cr , uid , st_line , context = context )
reconciliation_data [ ' st_line ' ] = st_line
ret . append ( reconciliation_data )
2014-05-30 16:47:50 +00:00
return ret
2014-09-04 09:32:16 +00:00
def get_statement_line_for_reconciliation ( self , cr , uid , st_line , context = None ) :
""" Returns the data required by the bank statement reconciliation widget to display a statement line """
if context is None :
context = { }
statement_currency = st_line . journal_id . currency or st_line . journal_id . company_id . currency_id
rml_parser = report_sxw . rml_parse ( cr , uid , ' reconciliation_widget_asl ' , context = context )
if st_line . amount_currency and st_line . currency_id :
amount = st_line . amount_currency
amount_currency = st_line . amount
amount_currency_str = amount_currency > 0 and amount_currency or - amount_currency
amount_currency_str = rml_parser . formatLang ( amount_currency_str , currency_obj = statement_currency )
else :
amount = st_line . amount
amount_currency_str = " "
amount_str = amount > 0 and amount or - amount
amount_str = rml_parser . formatLang ( amount_str , currency_obj = st_line . currency_id or statement_currency )
2014-05-30 16:47:50 +00:00
2014-06-16 08:38:01 +00:00
data = {
2014-09-04 09:32:16 +00:00
' id ' : st_line . id ,
' ref ' : st_line . ref ,
' note ' : st_line . note or " " ,
' name ' : st_line . name ,
' date ' : st_line . date ,
2014-06-02 00:28:15 +00:00
' amount ' : amount ,
2014-09-04 09:32:16 +00:00
' amount_str ' : amount_str , # Amount in the statement line currency
' currency_id ' : st_line . currency_id . id or statement_currency . id ,
' partner_id ' : st_line . partner_id . id ,
' statement_id ' : st_line . statement_id . id ,
' account_code ' : st_line . journal_id . default_debit_account_id . code ,
' account_name ' : st_line . journal_id . default_debit_account_id . name ,
' partner_name ' : st_line . partner_id . name ,
2014-09-16 09:01:06 +00:00
' communication_partner_name ' : st_line . partner_name ,
2014-09-04 09:32:16 +00:00
' amount_currency_str ' : amount_currency_str , # Amount in the statement currency
' has_no_partner ' : not st_line . partner_id . id ,
2014-05-30 16:47:50 +00:00
}
2014-09-04 09:32:16 +00:00
if st_line . partner_id . id :
2014-06-02 00:28:15 +00:00
if amount > 0 :
2014-09-04 09:32:16 +00:00
data [ ' open_balance_account_id ' ] = st_line . partner_id . property_account_receivable . id
else :
data [ ' open_balance_account_id ' ] = st_line . partner_id . property_account_payable . id
2014-06-16 08:38:01 +00:00
2014-09-04 09:32:16 +00:00
return data
2014-05-30 16:47:50 +00:00
[REF] Extract the domain generation for get_move_lines_for_reconciliation and get_reconciliation_proposition in new methods
This way, the query method can be used with a custom domain. Such a domain
could match on a 'transaction_ref' field as well as on 'ref' and 'name'.
Example of implementation:
class account_bank_statement_line(orm.Model):
_inherit = 'account.bank.statement.line'
def _domain_reconciliation_proposition(self, cr, uid, st_line,
excluded_ids=None, context=None):
_super = super(account_bank_statement_line, self)
_get_domain = _super._domain_reconciliation_proposition
domain = _get_domain(cr, uid, st_line, excluded_ids=excluded_ids,
context=context)
new_domain = []
for criterium in domain:
if len(criterium) == 3:
field, op, value = criterium
if (field, op) == ('ref', '='):
new_domain += [
'|',
('transaction_ref', '=', value),
]
new_domain.append(criterium)
return new_domain
def _domain_move_lines_for_reconciliation(self, cr, uid, st_line,
excluded_ids=None, str=False,
additional_domain=None,
context=None):
_super = super(account_bank_statement_line, self)
_domain_meth = _super._domain_move_lines_for_reconciliation
domain = _domain_meth(cr, uid, st_line, excluded_ids=excluded_ids,
str=str, additional_domain=additional_domain,
context=context)
if not str and str != '/':
return domain
domain = domain[:]
domain.insert(-1, '|')
domain.append(('transaction_ref', 'ilike', str))
return domain
2014-10-10 12:16:12 +00:00
def _domain_reconciliation_proposition ( self , cr , uid , st_line , excluded_ids = None , context = None ) :
2014-09-04 09:32:16 +00:00
if excluded_ids is None :
excluded_ids = [ ]
[REF] Extract the domain generation for get_move_lines_for_reconciliation and get_reconciliation_proposition in new methods
This way, the query method can be used with a custom domain. Such a domain
could match on a 'transaction_ref' field as well as on 'ref' and 'name'.
Example of implementation:
class account_bank_statement_line(orm.Model):
_inherit = 'account.bank.statement.line'
def _domain_reconciliation_proposition(self, cr, uid, st_line,
excluded_ids=None, context=None):
_super = super(account_bank_statement_line, self)
_get_domain = _super._domain_reconciliation_proposition
domain = _get_domain(cr, uid, st_line, excluded_ids=excluded_ids,
context=context)
new_domain = []
for criterium in domain:
if len(criterium) == 3:
field, op, value = criterium
if (field, op) == ('ref', '='):
new_domain += [
'|',
('transaction_ref', '=', value),
]
new_domain.append(criterium)
return new_domain
def _domain_move_lines_for_reconciliation(self, cr, uid, st_line,
excluded_ids=None, str=False,
additional_domain=None,
context=None):
_super = super(account_bank_statement_line, self)
_domain_meth = _super._domain_move_lines_for_reconciliation
domain = _domain_meth(cr, uid, st_line, excluded_ids=excluded_ids,
str=str, additional_domain=additional_domain,
context=context)
if not str and str != '/':
return domain
domain = domain[:]
domain.insert(-1, '|')
domain.append(('transaction_ref', 'ilike', str))
return domain
2014-10-10 12:16:12 +00:00
domain = [ ( ' ref ' , ' = ' , st_line . name ) ,
( ' reconcile_id ' , ' = ' , False ) ,
( ' state ' , ' = ' , ' valid ' ) ,
( ' account_id.reconcile ' , ' = ' , True ) ,
2015-11-24 09:22:16 +00:00
( ' id ' , ' not in ' , excluded_ids ) , ]
if st_line . partner_id :
domain . append ( ( ' partner_id ' , ' = ' , st_line . partner_id . id ) )
[REF] Extract the domain generation for get_move_lines_for_reconciliation and get_reconciliation_proposition in new methods
This way, the query method can be used with a custom domain. Such a domain
could match on a 'transaction_ref' field as well as on 'ref' and 'name'.
Example of implementation:
class account_bank_statement_line(orm.Model):
_inherit = 'account.bank.statement.line'
def _domain_reconciliation_proposition(self, cr, uid, st_line,
excluded_ids=None, context=None):
_super = super(account_bank_statement_line, self)
_get_domain = _super._domain_reconciliation_proposition
domain = _get_domain(cr, uid, st_line, excluded_ids=excluded_ids,
context=context)
new_domain = []
for criterium in domain:
if len(criterium) == 3:
field, op, value = criterium
if (field, op) == ('ref', '='):
new_domain += [
'|',
('transaction_ref', '=', value),
]
new_domain.append(criterium)
return new_domain
def _domain_move_lines_for_reconciliation(self, cr, uid, st_line,
excluded_ids=None, str=False,
additional_domain=None,
context=None):
_super = super(account_bank_statement_line, self)
_domain_meth = _super._domain_move_lines_for_reconciliation
domain = _domain_meth(cr, uid, st_line, excluded_ids=excluded_ids,
str=str, additional_domain=additional_domain,
context=context)
if not str and str != '/':
return domain
domain = domain[:]
domain.insert(-1, '|')
domain.append(('transaction_ref', 'ilike', str))
return domain
2014-10-10 12:16:12 +00:00
return domain
def get_reconciliation_proposition ( self , cr , uid , st_line , excluded_ids = None , context = None ) :
""" Returns move lines that constitute the best guess to reconcile a statement line. """
2014-09-04 09:32:16 +00:00
mv_line_pool = self . pool . get ( ' account.move.line ' )
# Look for structured communication
if st_line . name :
[REF] Extract the domain generation for get_move_lines_for_reconciliation and get_reconciliation_proposition in new methods
This way, the query method can be used with a custom domain. Such a domain
could match on a 'transaction_ref' field as well as on 'ref' and 'name'.
Example of implementation:
class account_bank_statement_line(orm.Model):
_inherit = 'account.bank.statement.line'
def _domain_reconciliation_proposition(self, cr, uid, st_line,
excluded_ids=None, context=None):
_super = super(account_bank_statement_line, self)
_get_domain = _super._domain_reconciliation_proposition
domain = _get_domain(cr, uid, st_line, excluded_ids=excluded_ids,
context=context)
new_domain = []
for criterium in domain:
if len(criterium) == 3:
field, op, value = criterium
if (field, op) == ('ref', '='):
new_domain += [
'|',
('transaction_ref', '=', value),
]
new_domain.append(criterium)
return new_domain
def _domain_move_lines_for_reconciliation(self, cr, uid, st_line,
excluded_ids=None, str=False,
additional_domain=None,
context=None):
_super = super(account_bank_statement_line, self)
_domain_meth = _super._domain_move_lines_for_reconciliation
domain = _domain_meth(cr, uid, st_line, excluded_ids=excluded_ids,
str=str, additional_domain=additional_domain,
context=context)
if not str and str != '/':
return domain
domain = domain[:]
domain.insert(-1, '|')
domain.append(('transaction_ref', 'ilike', str))
return domain
2014-10-10 12:16:12 +00:00
domain = self . _domain_reconciliation_proposition ( cr , uid , st_line , excluded_ids = excluded_ids , context = context )
2015-05-05 07:49:53 +00:00
match_id = mv_line_pool . search ( cr , uid , domain , offset = 0 , limit = 2 , context = context )
if match_id and len ( match_id ) == 1 :
2014-09-04 09:32:16 +00:00
mv_line_br = mv_line_pool . browse ( cr , uid , match_id , context = context )
target_currency = st_line . currency_id or st_line . journal_id . currency or st_line . journal_id . company_id . currency_id
mv_line = mv_line_pool . prepare_move_lines_for_reconciliation_widget ( cr , uid , mv_line_br , target_currency = target_currency , target_date = st_line . date , context = context ) [ 0 ]
mv_line [ ' has_no_partner ' ] = not bool ( st_line . partner_id . id )
# If the structured communication matches a move line that is associated with a partner, we can safely associate the statement line with the partner
if ( mv_line [ ' partner_id ' ] ) :
self . write ( cr , uid , st_line . id , { ' partner_id ' : mv_line [ ' partner_id ' ] } , context = context )
mv_line [ ' has_no_partner ' ] = False
return [ mv_line ]
2014-11-25 15:46:30 +00:00
# How to compare statement line amount and move lines amount
2014-11-27 13:57:11 +00:00
precision_digits = self . pool . get ( ' decimal.precision ' ) . precision_get ( cr , uid , ' Account ' )
2014-11-25 15:46:30 +00:00
currency_id = st_line . currency_id . id or st_line . journal_id . currency . id
2014-11-27 13:57:11 +00:00
# NB : amount can't be == 0 ; so float precision is not an issue for amount > 0 or amount < 0
2014-11-25 15:46:30 +00:00
amount = st_line . amount_currency or st_line . amount
domain = [ ( ' reconcile_partial_id ' , ' = ' , False ) ]
if currency_id :
domain + = [ ( ' currency_id ' , ' = ' , currency_id ) ]
sign = 1 # correct the fact that st_line.amount is signed and debit/credit is not
amount_field = ' debit '
if currency_id == False :
if amount < 0 :
amount_field = ' credit '
2014-09-16 10:55:02 +00:00
sign = - 1
2011-01-04 12:40:45 +00:00
else :
2014-05-30 16:47:50 +00:00
amount_field = ' amount_currency '
2014-11-27 13:57:11 +00:00
# Look for a matching amount
domain_exact_amount = domain + [ ( amount_field , ' = ' , float_round ( sign * amount , precision_digits = precision_digits ) ) ]
2015-07-02 15:01:05 +00:00
domain_exact_amount_ref = domain_exact_amount + [ ( ' ref ' , ' = ' , st_line . ref ) ]
match_id = self . get_move_lines_for_reconciliation ( cr , uid , st_line , excluded_ids = excluded_ids , offset = 0 , limit = 2 , additional_domain = domain_exact_amount_ref )
if not match_id :
match_id = self . get_move_lines_for_reconciliation ( cr , uid , st_line , excluded_ids = excluded_ids , offset = 0 , limit = 2 , additional_domain = domain_exact_amount )
2015-05-05 07:49:53 +00:00
if match_id and len ( match_id ) == 1 :
2014-11-25 15:46:30 +00:00
return match_id
2014-09-04 09:32:16 +00:00
2014-11-25 15:46:30 +00:00
if not st_line . partner_id . id :
return [ ]
# Look for a set of move line whose amount is <= to the line's amount
if amount > 0 : # Make sure we can't mix receivable and payable
domain + = [ ( ' account_id.type ' , ' = ' , ' receivable ' ) ]
else :
domain + = [ ( ' account_id.type ' , ' = ' , ' payable ' ) ]
if amount_field == ' amount_currency ' and amount < 0 :
2015-08-18 07:34:54 +00:00
domain + = [ ( amount_field , ' < ' , 0 ) , ( amount_field , ' >= ' , ( sign * amount ) ) ]
2014-11-25 15:46:30 +00:00
else :
2015-08-18 07:34:54 +00:00
domain + = [ ( amount_field , ' > ' , 0 ) , ( amount_field , ' <= ' , ( sign * amount ) ) ]
2015-05-10 08:25:05 +00:00
mv_lines = self . get_move_lines_for_reconciliation ( cr , uid , st_line , excluded_ids = excluded_ids , limit = 5 , additional_domain = domain , context = context )
2014-11-25 15:46:30 +00:00
ret = [ ]
total = 0
for line in mv_lines :
2014-11-27 13:57:11 +00:00
total + = abs ( line [ ' debit ' ] - line [ ' credit ' ] )
if float_compare ( total , abs ( amount ) , precision_digits = precision_digits ) != 1 :
2014-11-25 15:46:30 +00:00
ret . append ( line )
2014-11-27 13:57:11 +00:00
else :
2014-11-25 15:46:30 +00:00
break
return ret
2014-05-30 16:47:50 +00:00
2014-09-04 09:32:16 +00:00
def get_move_lines_for_reconciliation_by_statement_line_id ( self , cr , uid , st_line_id , excluded_ids = None , str = False , offset = 0 , limit = None , count = False , additional_domain = None , context = None ) :
""" Bridge between the web client reconciliation widget and get_move_lines_for_reconciliation (which expects a browse record) """
if excluded_ids is None :
excluded_ids = [ ]
if additional_domain is None :
additional_domain = [ ]
2014-06-16 08:38:01 +00:00
st_line = self . browse ( cr , uid , st_line_id , context = context )
2014-09-04 09:32:16 +00:00
return self . get_move_lines_for_reconciliation ( cr , uid , st_line , excluded_ids , str , offset , limit , count , additional_domain , context = context )
2014-06-16 08:38:01 +00:00
[REF] Extract the domain generation for get_move_lines_for_reconciliation and get_reconciliation_proposition in new methods
This way, the query method can be used with a custom domain. Such a domain
could match on a 'transaction_ref' field as well as on 'ref' and 'name'.
Example of implementation:
class account_bank_statement_line(orm.Model):
_inherit = 'account.bank.statement.line'
def _domain_reconciliation_proposition(self, cr, uid, st_line,
excluded_ids=None, context=None):
_super = super(account_bank_statement_line, self)
_get_domain = _super._domain_reconciliation_proposition
domain = _get_domain(cr, uid, st_line, excluded_ids=excluded_ids,
context=context)
new_domain = []
for criterium in domain:
if len(criterium) == 3:
field, op, value = criterium
if (field, op) == ('ref', '='):
new_domain += [
'|',
('transaction_ref', '=', value),
]
new_domain.append(criterium)
return new_domain
def _domain_move_lines_for_reconciliation(self, cr, uid, st_line,
excluded_ids=None, str=False,
additional_domain=None,
context=None):
_super = super(account_bank_statement_line, self)
_domain_meth = _super._domain_move_lines_for_reconciliation
domain = _domain_meth(cr, uid, st_line, excluded_ids=excluded_ids,
str=str, additional_domain=additional_domain,
context=context)
if not str and str != '/':
return domain
domain = domain[:]
domain.insert(-1, '|')
domain.append(('transaction_ref', 'ilike', str))
return domain
2014-10-10 12:16:12 +00:00
def _domain_move_lines_for_reconciliation ( self , cr , uid , st_line , excluded_ids = None , str = False , additional_domain = None , context = None ) :
2014-09-04 09:32:16 +00:00
if excluded_ids is None :
excluded_ids = [ ]
if additional_domain is None :
additional_domain = [ ]
# Make domain
2014-11-26 10:38:24 +00:00
domain = additional_domain + [
( ' reconcile_id ' , ' = ' , False ) ,
( ' state ' , ' = ' , ' valid ' ) ,
( ' account_id.reconcile ' , ' = ' , True )
]
2014-06-16 08:38:01 +00:00
if st_line . partner_id . id :
2014-09-16 13:01:03 +00:00
domain + = [ ( ' partner_id ' , ' = ' , st_line . partner_id . id ) ]
2014-05-30 16:47:50 +00:00
if excluded_ids :
domain . append ( ( ' id ' , ' not in ' , excluded_ids ) )
2014-09-04 09:32:16 +00:00
if str :
2014-11-26 10:38:24 +00:00
domain + = [
' | ' , ( ' move_id.name ' , ' ilike ' , str ) ,
' | ' , ( ' move_id.ref ' , ' ilike ' , str ) ,
( ' date_maturity ' , ' like ' , str ) ,
]
2014-09-17 11:00:21 +00:00
if not st_line . partner_id . id :
domain . insert ( - 1 , ' | ' , )
domain . append ( ( ' partner_id.name ' , ' ilike ' , str ) )
2014-09-17 13:02:02 +00:00
if str != ' / ' :
domain . insert ( - 1 , ' | ' , )
domain . append ( ( ' name ' , ' ilike ' , str ) )
[REF] Extract the domain generation for get_move_lines_for_reconciliation and get_reconciliation_proposition in new methods
This way, the query method can be used with a custom domain. Such a domain
could match on a 'transaction_ref' field as well as on 'ref' and 'name'.
Example of implementation:
class account_bank_statement_line(orm.Model):
_inherit = 'account.bank.statement.line'
def _domain_reconciliation_proposition(self, cr, uid, st_line,
excluded_ids=None, context=None):
_super = super(account_bank_statement_line, self)
_get_domain = _super._domain_reconciliation_proposition
domain = _get_domain(cr, uid, st_line, excluded_ids=excluded_ids,
context=context)
new_domain = []
for criterium in domain:
if len(criterium) == 3:
field, op, value = criterium
if (field, op) == ('ref', '='):
new_domain += [
'|',
('transaction_ref', '=', value),
]
new_domain.append(criterium)
return new_domain
def _domain_move_lines_for_reconciliation(self, cr, uid, st_line,
excluded_ids=None, str=False,
additional_domain=None,
context=None):
_super = super(account_bank_statement_line, self)
_domain_meth = _super._domain_move_lines_for_reconciliation
domain = _domain_meth(cr, uid, st_line, excluded_ids=excluded_ids,
str=str, additional_domain=additional_domain,
context=context)
if not str and str != '/':
return domain
domain = domain[:]
domain.insert(-1, '|')
domain.append(('transaction_ref', 'ilike', str))
return domain
2014-10-10 12:16:12 +00:00
return domain
def get_move_lines_for_reconciliation ( self , cr , uid , st_line , excluded_ids = None , str = False , offset = 0 , limit = None , count = False , additional_domain = None , context = None ) :
""" Find the move lines that could be used to reconcile a statement line. If count is true, only returns the count.
2014-09-17 11:00:21 +00:00
[REF] Extract the domain generation for get_move_lines_for_reconciliation and get_reconciliation_proposition in new methods
This way, the query method can be used with a custom domain. Such a domain
could match on a 'transaction_ref' field as well as on 'ref' and 'name'.
Example of implementation:
class account_bank_statement_line(orm.Model):
_inherit = 'account.bank.statement.line'
def _domain_reconciliation_proposition(self, cr, uid, st_line,
excluded_ids=None, context=None):
_super = super(account_bank_statement_line, self)
_get_domain = _super._domain_reconciliation_proposition
domain = _get_domain(cr, uid, st_line, excluded_ids=excluded_ids,
context=context)
new_domain = []
for criterium in domain:
if len(criterium) == 3:
field, op, value = criterium
if (field, op) == ('ref', '='):
new_domain += [
'|',
('transaction_ref', '=', value),
]
new_domain.append(criterium)
return new_domain
def _domain_move_lines_for_reconciliation(self, cr, uid, st_line,
excluded_ids=None, str=False,
additional_domain=None,
context=None):
_super = super(account_bank_statement_line, self)
_domain_meth = _super._domain_move_lines_for_reconciliation
domain = _domain_meth(cr, uid, st_line, excluded_ids=excluded_ids,
str=str, additional_domain=additional_domain,
context=context)
if not str and str != '/':
return domain
domain = domain[:]
domain.insert(-1, '|')
domain.append(('transaction_ref', 'ilike', str))
return domain
2014-10-10 12:16:12 +00:00
: param st_line : the browse record of the statement line
: param integers list excluded_ids : ids of move lines that should not be fetched
: param boolean count : just return the number of records
: param tuples list additional_domain : additional domain restrictions
"""
mv_line_pool = self . pool . get ( ' account.move.line ' )
domain = self . _domain_move_lines_for_reconciliation ( cr , uid , st_line , excluded_ids = excluded_ids , str = str , additional_domain = additional_domain , context = context )
2015-02-16 18:23:36 +00:00
2015-02-17 10:07:14 +00:00
# Get move lines ; in case of a partial reconciliation, only keep one line (the first whose amount is greater than
# the residual amount because it is presumably the invoice, which is the relevant item in this situation)
2014-09-17 11:49:39 +00:00
filtered_lines = [ ]
reconcile_partial_ids = [ ]
2014-09-17 12:18:52 +00:00
actual_offset = offset
2014-09-17 11:49:39 +00:00
while True :
2014-09-17 12:18:52 +00:00
line_ids = mv_line_pool . search ( cr , uid , domain , offset = actual_offset , limit = limit , order = " date_maturity asc, id asc " , context = context )
2014-09-17 11:49:39 +00:00
lines = mv_line_pool . browse ( cr , uid , line_ids , context = context )
2014-09-17 12:18:52 +00:00
make_one_more_loop = False
2014-09-04 09:32:16 +00:00
for line in lines :
2015-02-17 10:07:14 +00:00
if line . reconcile_partial_id and \
( line . reconcile_partial_id . id in reconcile_partial_ids or \
abs ( line . debit - line . credit ) < abs ( line . amount_residual ) ) :
2014-09-17 12:18:52 +00:00
#if we filtered a line because it is partially reconciled with an already selected line, we must do one more loop
#in order to get the right number of items in the pager
make_one_more_loop = True
2014-05-30 16:47:50 +00:00
continue
2014-09-17 11:49:39 +00:00
filtered_lines . append ( line )
2014-05-30 16:47:50 +00:00
if line . reconcile_partial_id :
reconcile_partial_ids . append ( line . reconcile_partial_id . id )
2014-09-17 12:18:52 +00:00
if not limit or not make_one_more_loop or len ( filtered_lines ) > = limit :
2014-09-17 11:49:39 +00:00
break
2014-09-17 12:18:52 +00:00
actual_offset = actual_offset + limit
2014-09-17 11:49:39 +00:00
lines = limit and filtered_lines [ : limit ] or filtered_lines
# Either return number of lines
if count :
return len ( lines )
2014-09-17 12:18:52 +00:00
2014-09-04 09:32:16 +00:00
# Or return list of dicts representing the formatted move lines
2014-05-30 16:47:50 +00:00
else :
2014-09-04 09:32:16 +00:00
target_currency = st_line . currency_id or st_line . journal_id . currency or st_line . journal_id . company_id . currency_id
mv_lines = mv_line_pool . prepare_move_lines_for_reconciliation_widget ( cr , uid , lines , target_currency = target_currency , target_date = st_line . date , context = context )
has_no_partner = not bool ( st_line . partner_id . id )
for line in mv_lines :
line [ ' has_no_partner ' ] = has_no_partner
return mv_lines
2014-05-30 16:47:50 +00:00
2014-06-02 09:54:18 +00:00
def get_currency_rate_line ( self , cr , uid , st_line , currency_diff , move_id , context = None ) :
if currency_diff < 0 :
account_id = st_line . company_id . expense_currency_exchange_account_id . id
if not account_id :
raise osv . except_osv ( _ ( ' Insufficient Configuration! ' ) , _ ( " You should configure the ' Loss Exchange Rate Account ' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates. " ) )
else :
account_id = st_line . company_id . income_currency_exchange_account_id . id
if not account_id :
raise osv . except_osv ( _ ( ' Insufficient Configuration! ' ) , _ ( " You should configure the ' Gain Exchange Rate Account ' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates. " ) )
return {
' move_id ' : move_id ,
' name ' : _ ( ' change ' ) + ' : ' + ( st_line . name or ' / ' ) ,
' period_id ' : st_line . statement_id . period_id . id ,
' journal_id ' : st_line . journal_id . id ,
' partner_id ' : st_line . partner_id . id ,
' company_id ' : st_line . company_id . id ,
' statement_id ' : st_line . statement_id . id ,
' debit ' : currency_diff < 0 and - currency_diff or 0 ,
' credit ' : currency_diff > 0 and currency_diff or 0 ,
2014-09-02 08:42:28 +00:00
' amount_currency ' : 0.0 ,
2014-06-02 09:54:18 +00:00
' date ' : st_line . date ,
' account_id ' : account_id
}
2015-05-26 16:18:11 +00:00
def _get_exchange_lines ( self , cr , uid , st_line , mv_line , currency_diff , currency_id , move_id , context = None ) :
'''
Prepare the two lines in company currency due to currency rate difference .
: param line : browse record of the voucher . line for which we want to create currency rate difference accounting
entries
: param move_id : Account move wher the move lines will be .
: param currency_diff : Amount to be posted .
: param company_currency : id of currency of the company to which the voucher belong
: param current_currency : id of currency of the voucher
: return : the account move line and its counterpart to create , depicted as mapping between fieldname and value
: rtype : tuple of dict
'''
if currency_diff > 0 :
exchange_account_id = st_line . company_id . expense_currency_exchange_account_id . id
else :
exchange_account_id = st_line . company_id . income_currency_exchange_account_id . id
# Even if the amount_currency is never filled, we need to pass the foreign currency because otherwise
# the receivable/payable account may have a secondary currency, which render this field mandatory
if mv_line . account_id . currency_id :
account_currency_id = mv_line . account_id . currency_id . id
else :
account_currency_id = st_line . company_id . currency_id . id != currency_id and currency_id or False
move_line = {
' journal_id ' : st_line . journal_id . id ,
' period_id ' : st_line . statement_id . period_id . id ,
' name ' : _ ( ' change ' ) + ' : ' + ( st_line . name or ' / ' ) ,
' account_id ' : mv_line . account_id . id ,
' move_id ' : move_id ,
' partner_id ' : st_line . partner_id . id ,
' currency_id ' : account_currency_id ,
' amount_currency ' : 0.0 ,
' quantity ' : 1 ,
' credit ' : currency_diff > 0 and currency_diff or 0.0 ,
' debit ' : currency_diff < 0 and - currency_diff or 0.0 ,
' date ' : st_line . date ,
' counterpart_move_line_id ' : mv_line . id ,
}
move_line_counterpart = {
' journal_id ' : st_line . journal_id . id ,
' period_id ' : st_line . statement_id . period_id . id ,
' name ' : _ ( ' change ' ) + ' : ' + ( st_line . name or ' / ' ) ,
' account_id ' : exchange_account_id ,
' move_id ' : move_id ,
' amount_currency ' : 0.0 ,
' partner_id ' : st_line . partner_id . id ,
' currency_id ' : account_currency_id ,
' quantity ' : 1 ,
' debit ' : currency_diff > 0 and currency_diff or 0.0 ,
' credit ' : currency_diff < 0 and - currency_diff or 0.0 ,
' date ' : st_line . date ,
}
return ( move_line , move_line_counterpart )
2014-09-16 15:15:54 +00:00
def process_reconciliations ( self , cr , uid , data , context = None ) :
for datum in data :
self . process_reconciliation ( cr , uid , datum [ 0 ] , datum [ 1 ] , context = context )
2014-05-30 16:47:50 +00:00
def process_reconciliation ( self , cr , uid , id , mv_line_dicts , context = None ) :
""" Creates a move line for each item of mv_line_dicts and for the statement line. Reconcile a new move line with its counterpart_move_line_id if specified. Finally, mark the statement line as reconciled by putting the newly created move id in the column journal_entry_id.
: param int id : id of the bank statement line
: param list of dicts mv_line_dicts : move lines to create . If counterpart_move_line_id is specified , reconcile with it
"""
2014-06-02 09:54:18 +00:00
if context is None :
context = { }
2014-05-30 16:47:50 +00:00
st_line = self . browse ( cr , uid , id , context = context )
company_currency = st_line . journal_id . company_id . currency_id
statement_currency = st_line . journal_id . currency or company_currency
bs_obj = self . pool . get ( ' account.bank.statement ' )
am_obj = self . pool . get ( ' account.move ' )
aml_obj = self . pool . get ( ' account.move.line ' )
currency_obj = self . pool . get ( ' res.currency ' )
# Checks
2014-06-02 09:54:18 +00:00
if st_line . journal_entry_id . id :
2014-05-30 16:47:50 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' The bank statement line was already reconciled. ' ) )
for mv_line_dict in mv_line_dicts :
for field in [ ' debit ' , ' credit ' , ' amount_currency ' ] :
if field not in mv_line_dict :
mv_line_dict [ field ] = 0.0
if mv_line_dict . get ( ' counterpart_move_line_id ' ) :
mv_line = aml_obj . browse ( cr , uid , mv_line_dict . get ( ' counterpart_move_line_id ' ) , context = context )
if mv_line . reconcile_id :
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' A selected move line was already reconciled. ' ) )
# Create the move
2014-08-26 12:45:00 +00:00
move_name = ( st_line . statement_id . name or st_line . name ) + " / " + str ( st_line . sequence )
2014-05-30 16:47:50 +00:00
move_vals = bs_obj . _prepare_move ( cr , uid , st_line , move_name , context = context )
move_id = am_obj . create ( cr , uid , move_vals , context = context )
# Create the move line for the statement line
2014-07-22 20:17:46 +00:00
if st_line . statement_id . currency . id != company_currency . id :
2014-08-28 09:09:48 +00:00
if st_line . currency_id == company_currency :
amount = st_line . amount_currency
else :
ctx = context . copy ( )
ctx [ ' date ' ] = st_line . date
amount = currency_obj . compute ( cr , uid , st_line . statement_id . currency . id , company_currency . id , st_line . amount , context = ctx )
2014-07-22 20:17:46 +00:00
else :
amount = st_line . amount
2014-05-30 16:47:50 +00:00
bank_st_move_vals = bs_obj . _prepare_bank_move_line ( cr , uid , st_line , move_id , amount , company_currency . id , context = context )
aml_obj . create ( cr , uid , bank_st_move_vals , context = context )
# Complete the dicts
2014-06-02 00:28:15 +00:00
st_line_currency = st_line . currency_id or statement_currency
2014-09-02 09:37:57 +00:00
st_line_currency_rate = st_line . currency_id and ( st_line . amount_currency / st_line . amount ) or False
2014-06-02 09:54:18 +00:00
to_create = [ ]
2014-05-30 16:47:50 +00:00
for mv_line_dict in mv_line_dicts :
2014-07-11 15:15:34 +00:00
if mv_line_dict . get ( ' is_tax_line ' ) :
continue
2014-05-30 16:47:50 +00:00
mv_line_dict [ ' ref ' ] = move_name
mv_line_dict [ ' move_id ' ] = move_id
2014-06-02 09:54:18 +00:00
mv_line_dict [ ' period_id ' ] = st_line . statement_id . period_id . id
mv_line_dict [ ' journal_id ' ] = st_line . journal_id . id
mv_line_dict [ ' company_id ' ] = st_line . company_id . id
mv_line_dict [ ' statement_id ' ] = st_line . statement_id . id
2014-05-30 16:47:50 +00:00
if mv_line_dict . get ( ' counterpart_move_line_id ' ) :
mv_line = aml_obj . browse ( cr , uid , mv_line_dict [ ' counterpart_move_line_id ' ] , context = context )
2014-09-17 15:12:50 +00:00
mv_line_dict [ ' partner_id ' ] = mv_line . partner_id . id or st_line . partner_id . id
2014-05-30 16:47:50 +00:00
mv_line_dict [ ' account_id ' ] = mv_line . account_id . id
2014-06-02 00:28:15 +00:00
if st_line_currency . id != company_currency . id :
2014-09-04 09:32:16 +00:00
ctx = context . copy ( )
ctx [ ' date ' ] = st_line . date
2014-05-30 16:47:50 +00:00
mv_line_dict [ ' amount_currency ' ] = mv_line_dict [ ' debit ' ] - mv_line_dict [ ' credit ' ]
2014-06-02 00:28:15 +00:00
mv_line_dict [ ' currency_id ' ] = st_line_currency . id
if st_line . currency_id and statement_currency . id == company_currency . id and st_line_currency_rate :
2014-06-02 09:54:18 +00:00
debit_at_current_rate = self . pool . get ( ' res.currency ' ) . round ( cr , uid , company_currency , mv_line_dict [ ' debit ' ] / st_line_currency_rate )
credit_at_current_rate = self . pool . get ( ' res.currency ' ) . round ( cr , uid , company_currency , mv_line_dict [ ' credit ' ] / st_line_currency_rate )
2014-09-02 09:37:57 +00:00
elif st_line . currency_id and st_line_currency_rate :
2014-09-04 09:32:16 +00:00
debit_at_current_rate = currency_obj . compute ( cr , uid , statement_currency . id , company_currency . id , mv_line_dict [ ' debit ' ] / st_line_currency_rate , context = ctx )
credit_at_current_rate = currency_obj . compute ( cr , uid , statement_currency . id , company_currency . id , mv_line_dict [ ' credit ' ] / st_line_currency_rate , context = ctx )
2014-06-02 00:28:15 +00:00
else :
2014-09-04 09:32:16 +00:00
debit_at_current_rate = currency_obj . compute ( cr , uid , st_line_currency . id , company_currency . id , mv_line_dict [ ' debit ' ] , context = ctx )
credit_at_current_rate = currency_obj . compute ( cr , uid , st_line_currency . id , company_currency . id , mv_line_dict [ ' credit ' ] , context = ctx )
2014-06-02 09:54:18 +00:00
if mv_line_dict . get ( ' counterpart_move_line_id ' ) :
#post an account line that use the same currency rate than the counterpart (to balance the account) and post the difference in another line
ctx [ ' date ' ] = mv_line . date
2015-05-05 16:12:46 +00:00
if mv_line . currency_id . id == mv_line_dict [ ' currency_id ' ] \
2015-05-08 14:12:37 +00:00
and float_is_zero ( abs ( mv_line . amount_currency ) - abs ( mv_line_dict [ ' amount_currency ' ] ) , precision_rounding = mv_line . currency_id . rounding ) :
2015-05-05 16:12:46 +00:00
debit_at_old_rate = mv_line . credit
credit_at_old_rate = mv_line . debit
else :
debit_at_old_rate = currency_obj . compute ( cr , uid , st_line_currency . id , company_currency . id , mv_line_dict [ ' debit ' ] , context = ctx )
credit_at_old_rate = currency_obj . compute ( cr , uid , st_line_currency . id , company_currency . id , mv_line_dict [ ' credit ' ] , context = ctx )
2014-06-02 09:54:18 +00:00
mv_line_dict [ ' credit ' ] = credit_at_old_rate
mv_line_dict [ ' debit ' ] = debit_at_old_rate
if debit_at_old_rate - debit_at_current_rate :
currency_diff = debit_at_current_rate - debit_at_old_rate
2014-09-04 09:32:16 +00:00
to_create . append ( self . get_currency_rate_line ( cr , uid , st_line , - currency_diff , move_id , context = context ) )
2014-06-02 09:54:18 +00:00
if credit_at_old_rate - credit_at_current_rate :
currency_diff = credit_at_current_rate - credit_at_old_rate
to_create . append ( self . get_currency_rate_line ( cr , uid , st_line , currency_diff , move_id , context = context ) )
2015-05-26 16:18:11 +00:00
if mv_line . currency_id and mv_line_dict [ ' currency_id ' ] == mv_line . currency_id . id :
amount_unreconciled = mv_line . amount_residual_currency
else :
amount_unreconciled = currency_obj . compute ( cr , uid , company_currency . id , mv_line_dict [ ' currency_id ' ] , mv_line . amount_residual , context = ctx )
if float_is_zero ( mv_line_dict [ ' amount_currency ' ] + amount_unreconciled , precision_rounding = mv_line . currency_id . rounding ) :
amount = mv_line_dict [ ' debit ' ] or mv_line_dict [ ' credit ' ]
sign = - 1 if mv_line_dict [ ' debit ' ] else 1
currency_rate_difference = sign * ( mv_line . amount_residual - amount )
if not company_currency . is_zero ( currency_rate_difference ) :
exchange_lines = self . _get_exchange_lines ( cr , uid , st_line , mv_line , currency_rate_difference , mv_line_dict [ ' currency_id ' ] , move_id , context = context )
for exchange_line in exchange_lines :
to_create . append ( exchange_line )
2014-06-02 09:54:18 +00:00
else :
mv_line_dict [ ' debit ' ] = debit_at_current_rate
mv_line_dict [ ' credit ' ] = credit_at_current_rate
2014-08-28 09:09:48 +00:00
elif statement_currency . id != company_currency . id :
#statement is in foreign currency but the transaction is in company currency
prorata_factor = ( mv_line_dict [ ' debit ' ] - mv_line_dict [ ' credit ' ] ) / st_line . amount_currency
mv_line_dict [ ' amount_currency ' ] = prorata_factor * st_line . amount
2014-06-02 09:54:18 +00:00
to_create . append ( mv_line_dict )
2015-02-16 18:23:36 +00:00
# If the reconciliation is performed in another currency than the company currency, the amounts are converted to get the right debit/credit.
# If there is more than 1 debit and 1 credit, this can induce a rounding error, which we put in the foreign exchane gain/loss account.
if st_line_currency . id != company_currency . id :
diff_amount = bank_st_move_vals [ ' debit ' ] - bank_st_move_vals [ ' credit ' ] \
+ sum ( aml [ ' debit ' ] for aml in to_create ) - sum ( aml [ ' credit ' ] for aml in to_create )
if not company_currency . is_zero ( diff_amount ) :
diff_aml = self . get_currency_rate_line ( cr , uid , st_line , diff_amount , move_id , context = context )
diff_aml [ ' name ' ] = _ ( ' Rounding error from currency conversion ' )
to_create . append ( diff_aml )
2014-05-30 16:47:50 +00:00
# Create move lines
move_line_pairs_to_reconcile = [ ]
2014-06-02 09:54:18 +00:00
for mv_line_dict in to_create :
2014-05-30 16:47:50 +00:00
counterpart_move_line_id = None # NB : this attribute is irrelevant for aml_obj.create() and needs to be removed from the dict
if mv_line_dict . get ( ' counterpart_move_line_id ' ) :
counterpart_move_line_id = mv_line_dict [ ' counterpart_move_line_id ' ]
del mv_line_dict [ ' counterpart_move_line_id ' ]
new_aml_id = aml_obj . create ( cr , uid , mv_line_dict , context = context )
if counterpart_move_line_id != None :
move_line_pairs_to_reconcile . append ( [ new_aml_id , counterpart_move_line_id ] )
# Reconcile
for pair in move_line_pairs_to_reconcile :
aml_obj . reconcile_partial ( cr , uid , pair , context = context )
# Mark the statement line as reconciled
self . write ( cr , uid , id , { ' journal_entry_id ' : move_id } , context = context )
# FIXME : if it wasn't for the multicompany security settings in account_security.xml, the method would just
# return [('journal_entry_id', '=', False)]
# Unfortunately, that spawns a "no access rights" error ; it shouldn't.
def _needaction_domain_get ( self , cr , uid , context = None ) :
user = self . pool . get ( " res.users " ) . browse ( cr , uid , uid )
2015-01-15 15:49:42 +00:00
return [ ' | ' , ( ' company_id ' , ' = ' , False ) , ( ' company_id ' , ' child_of ' , [ user . company_id . id ] ) , ( ' journal_entry_id ' , ' = ' , False ) , ( ' account_id ' , ' = ' , False ) ]
2008-07-22 15:11:28 +00:00
2010-08-16 05:23:06 +00:00
_order = " statement_id desc, sequence "
2008-07-22 15:11:28 +00:00
_name = " account.bank.statement.line "
_description = " Bank Statement Line "
2014-05-30 16:47:50 +00:00
_inherit = [ ' ir.needaction_mixin ' ]
2008-07-22 15:11:28 +00:00
_columns = {
2014-08-29 17:13:41 +00:00
' name ' : fields . char ( ' Communication ' , required = True ) ,
2014-07-23 08:15:29 +00:00
' date ' : fields . date ( ' Date ' , required = True ) ,
2010-12-09 09:34:48 +00:00
' amount ' : fields . float ( ' Amount ' , digits_compute = dp . get_precision ( ' Account ' ) ) ,
2008-07-22 15:11:28 +00:00
' partner_id ' : fields . many2one ( ' res.partner ' , ' Partner ' ) ,
2014-05-30 16:47:50 +00:00
' bank_account_id ' : fields . many2one ( ' res.partner.bank ' , ' Bank Account ' ) ,
2014-07-18 13:43:00 +00:00
' account_id ' : fields . many2one ( ' account.account ' , ' Account ' , help = " This technical field can be used at the statement line creation/import time in order to avoid the reconciliation process on it later on. The statement line will simply create a counterpart on this account " ) ,
2014-10-25 13:19:20 +00:00
' statement_id ' : fields . many2one ( ' account.bank.statement ' , ' Statement ' , select = True , required = True , ondelete = ' restrict ' ) ,
2012-01-02 09:08:33 +00:00
' journal_id ' : fields . related ( ' statement_id ' , ' journal_id ' , type = ' many2one ' , relation = ' account.journal ' , string = ' Journal ' , store = True , readonly = True ) ,
2014-08-29 17:13:41 +00:00
' partner_name ' : fields . char ( ' Partner Name ' , help = " This field is used to record the third party name when importing bank statement in electronic format, when the partner doesn ' t exist yet in the database (or cannot be found). " ) ,
' ref ' : fields . char ( ' Reference ' ) ,
2008-07-22 15:11:28 +00:00
' note ' : fields . text ( ' Notes ' ) ,
2011-12-09 06:03:08 +00:00
' sequence ' : fields . integer ( ' Sequence ' , select = True , help = " Gives the sequence order when displaying a list of bank statement lines. " ) ,
2010-09-16 13:26:14 +00:00
' company_id ' : fields . related ( ' statement_id ' , ' company_id ' , type = ' many2one ' , relation = ' res.company ' , string = ' Company ' , store = True , readonly = True ) ,
2014-07-23 08:15:29 +00:00
' journal_entry_id ' : fields . many2one ( ' account.move ' , ' Journal Entry ' , copy = False ) ,
2014-05-30 16:47:50 +00:00
' amount_currency ' : fields . float ( ' Amount Currency ' , help = " The amount expressed in an optional other currency if it is a multi-currency entry. " , digits_compute = dp . get_precision ( ' Account ' ) ) ,
' currency_id ' : fields . many2one ( ' res.currency ' , ' Currency ' , help = " The optional other currency if it is a multi-currency entry. " ) ,
2008-07-22 15:11:28 +00:00
}
_defaults = {
2015-09-03 09:57:58 +00:00
' name ' : lambda self , cr , uid , context = { } : self . pool . get ( ' ir.sequence ' ) . get ( cr , uid , ' account.bank.statement.line ' , context = context ) ,
2012-02-14 12:25:20 +00:00
' date ' : lambda self , cr , uid , context = { } : context . get ( ' date ' , fields . date . context_today ( self , cr , uid , context = context ) ) ,
2008-07-22 15:11:28 +00:00
}
2007-09-05 14:02:52 +00:00
2014-05-30 16:47:50 +00:00
class account_statement_operation_template ( osv . osv ) :
_name = " account.statement.operation.template "
_description = " Preset for the lines that can be created in a bank statement reconciliation "
_columns = {
' name ' : fields . char ( ' Button Label ' , required = True ) ,
2014-11-27 11:18:21 +00:00
' account_id ' : fields . many2one ( ' account.account ' , ' Account ' , ondelete = ' cascade ' , domain = [ ( ' type ' , ' not in ' , ( ' view ' , ' closed ' , ' consolidation ' ) ) ] ) ,
2014-05-30 16:47:50 +00:00
' label ' : fields . char ( ' Label ' ) ,
' amount_type ' : fields . selection ( [ ( ' fixed ' , ' Fixed ' ) , ( ' percentage_of_total ' , ' Percentage of total amount ' ) , ( ' percentage_of_balance ' , ' Percentage of open balance ' ) ] ,
' Amount type ' , required = True ) ,
2014-09-04 09:32:16 +00:00
' amount ' : fields . float ( ' Amount ' , digits_compute = dp . get_precision ( ' Account ' ) , help = " The amount will count as a debit if it is negative, as a credit if it is positive (except if amount type is ' Percentage of open balance ' ). " , required = True ) ,
2014-11-27 11:18:21 +00:00
' tax_id ' : fields . many2one ( ' account.tax ' , ' Tax ' , ondelete = ' restrict ' , domain = [ ( ' type_tax_use ' , ' in ' , [ ' purchase ' , ' all ' ] ) , ( ' parent_id ' , ' = ' , False ) ] ) ,
' analytic_account_id ' : fields . many2one ( ' account.analytic.account ' , ' Analytic Account ' , ondelete = ' set null ' , domain = [ ( ' type ' , ' != ' , ' view ' ) , ( ' state ' , ' not in ' , ( ' close ' , ' cancelled ' ) ) ] ) ,
2014-05-30 16:47:50 +00:00
}
_defaults = {
2014-09-04 09:32:16 +00:00
' amount_type ' : ' percentage_of_balance ' ,
' amount ' : 100.0
2014-05-30 16:47:50 +00:00
}
2007-01-04 09:45:50 +00:00
2010-11-26 15:14:46 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: