2010-04-09 11:09:59 +00:00
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
2010-10-15 13:35:22 +00:00
2010-04-09 11:09:59 +00:00
from osv import fields , osv
from tools . translate import _
class account_fiscalyear_close ( osv . osv_memory ) :
"""
Closes Account Fiscalyear and Generate Opening entries for New Fiscalyear
"""
_name = " account.fiscalyear.close "
_description = " Fiscalyear Close "
_columns = {
' fy_id ' : fields . many2one ( ' account.fiscalyear ' , \
2010-10-14 09:11:55 +00:00
' Fiscal Year to close ' , required = True , help = " Select a Fiscal year to close " ) ,
2010-04-09 11:09:59 +00:00
' fy2_id ' : fields . many2one ( ' account.fiscalyear ' , \
' New Fiscal Year ' , required = True ) ,
2010-11-16 12:16:58 +00:00
' journal_id ' : fields . many2one ( ' account.journal ' , ' Opening Entries Journal ' , domain = " [( ' type ' , ' = ' , ' situation ' )] " , required = True , help = ' The best practice here is to use a journal dedicated to contain the opening entries of all fiscal years. Note that you should define it with default debit/credit accounts, of type \' situation \' and with a centralized counterpart. ' ) ,
' period_id ' : fields . many2one ( ' account.period ' , ' Opening Entries Period ' , required = True ) ,
2010-10-14 09:11:55 +00:00
' report_name ' : fields . char ( ' Name of new entries ' , size = 64 , required = True , help = " Give name of the new entries " ) ,
2010-08-19 11:51:57 +00:00
}
2010-04-09 11:09:59 +00:00
_defaults = {
2010-11-16 12:16:58 +00:00
' report_name ' : _ ( ' End of Fiscal Year Entry ' ) ,
2010-08-19 11:51:57 +00:00
}
2010-04-09 11:09:59 +00:00
2010-04-09 11:48:13 +00:00
def data_save ( self , cr , uid , ids , context = None ) :
2010-04-09 11:09:59 +00:00
"""
This function close account fiscalyear and create entries in new fiscalyear
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of Account fiscalyear close state ’ s IDs
"""
obj_acc_period = self . pool . get ( ' account.period ' )
obj_acc_fiscalyear = self . pool . get ( ' account.fiscalyear ' )
obj_acc_journal = self . pool . get ( ' account.journal ' )
2011-09-23 13:48:27 +00:00
obj_acc_move = self . pool . get ( ' account.move ' )
2010-04-09 11:09:59 +00:00
obj_acc_move_line = self . pool . get ( ' account.move.line ' )
obj_acc_account = self . pool . get ( ' account.account ' )
obj_acc_journal_period = self . pool . get ( ' account.journal.period ' )
2011-09-23 13:48:27 +00:00
currency_obj = self . pool . get ( ' res.currency ' )
2010-04-09 11:09:59 +00:00
2011-02-15 09:20:57 +00:00
data = self . browse ( cr , uid , ids , context = context )
2010-04-09 11:09:59 +00:00
2010-04-09 11:48:13 +00:00
if context is None :
context = { }
2011-02-15 09:20:57 +00:00
fy_id = data [ 0 ] . fy_id . id
2010-04-09 11:09:59 +00:00
2011-02-15 09:20:57 +00:00
cr . execute ( " SELECT id FROM account_period WHERE date_stop < (SELECT date_start FROM account_fiscalyear WHERE id = %s ) " , ( str ( data [ 0 ] . fy2_id . id ) , ) )
2010-06-23 13:33:32 +00:00
fy_period_set = ' , ' . join ( map ( lambda id : str ( id [ 0 ] ) , cr . fetchall ( ) ) )
2010-10-11 05:51:53 +00:00
cr . execute ( " SELECT id FROM account_period WHERE date_start > (SELECT date_stop FROM account_fiscalyear WHERE id = %s ) " , ( str ( fy_id ) , ) )
2010-06-23 13:33:32 +00:00
fy2_period_set = ' , ' . join ( map ( lambda id : str ( id [ 0 ] ) , cr . fetchall ( ) ) )
2010-04-09 11:09:59 +00:00
2011-02-15 09:20:57 +00:00
period = obj_acc_period . browse ( cr , uid , data [ 0 ] . period_id . id , context = context )
new_fyear = obj_acc_fiscalyear . browse ( cr , uid , data [ 0 ] . fy2_id . id , context = context )
old_fyear = obj_acc_fiscalyear . browse ( cr , uid , fy_id , context = context )
2010-04-09 11:09:59 +00:00
2011-02-15 09:20:57 +00:00
new_journal = data [ 0 ] . journal_id . id
2010-04-09 11:09:59 +00:00
new_journal = obj_acc_journal . browse ( cr , uid , new_journal , context = context )
if not new_journal . default_credit_account_id or not new_journal . default_debit_account_id :
raise osv . except_osv ( _ ( ' UserError ' ) ,
_ ( ' The journal must have default credit and debit account ' ) )
2010-10-20 13:43:32 +00:00
if ( not new_journal . centralisation ) or new_journal . entry_posted :
2010-04-09 11:09:59 +00:00
raise osv . except_osv ( _ ( ' UserError ' ) ,
2010-10-20 13:43:32 +00:00
_ ( ' The journal must have centralised counterpart without the Skipping draft state option checked! ' ) )
2010-04-09 11:09:59 +00:00
2011-09-23 13:48:27 +00:00
#delete existing move and move lines if any
move_ids = obj_acc_move . search ( cr , uid , [
( ' journal_id ' , ' = ' , new_journal . id ) , ( ' period_id ' , ' = ' , period . id ) ] )
2010-04-09 11:09:59 +00:00
if move_ids :
2011-09-23 13:48:27 +00:00
move_line_ids = obj_acc_move_line . search ( cr , uid , [ ( ' move_id ' , ' in ' , move_ids ) ] )
obj_acc_move_line . _remove_move_reconcile ( cr , uid , move_line_ids , context = context )
obj_acc_move_line . unlink ( cr , uid , move_line_ids , context = context )
obj_acc_move . unlink ( cr , uid , move_ids , context = context )
2010-09-07 04:28:31 +00:00
2010-06-23 13:33:32 +00:00
cr . execute ( " SELECT id FROM account_fiscalyear WHERE date_stop < %s " , ( str ( new_fyear . date_start ) , ) )
2010-04-09 11:09:59 +00:00
result = cr . dictfetchall ( )
fy_ids = ' , ' . join ( [ str ( x [ ' id ' ] ) for x in result ] )
query_line = obj_acc_move_line . _query_get ( cr , uid ,
obj = ' account_move_line ' , context = { ' fiscalyear ' : fy_ids } )
2011-09-23 13:48:27 +00:00
#create the opening move
vals = {
' name ' : ' / ' ,
' ref ' : ' ' ,
' period_id ' : period . id ,
' journal_id ' : new_journal . id ,
}
move_id = obj_acc_move . create ( cr , uid , vals , context = context )
#1. report of the accounts with defferal method == 'unreconciled'
cr . execute ( '''
SELECT a . id
FROM account_account a
LEFT JOIN account_account_type t ON ( a . user_type = t . id )
WHERE a . active
AND a . type != ' view '
AND t . close_method = % s ''' , ( ' unreconciled ' , ))
account_ids = map ( lambda x : x [ 0 ] , cr . fetchall ( ) )
if account_ids :
cr . execute ( '''
INSERT INTO account_move_line (
name , create_uid , create_date , write_uid , write_date ,
statement_id , journal_id , currency_id , date_maturity ,
partner_id , blocked , credit , state , debit ,
ref , account_id , period_id , date , move_id , amount_currency ,
quantity , product_id , company_id )
( SELECT name , create_uid , create_date , write_uid , write_date ,
statement_id , % s , currency_id , date_maturity , partner_id ,
blocked , credit , ' draft ' , debit , ref , account_id ,
% s , date , % s , amount_currency , quantity , product_id , company_id
FROM account_move_line
WHERE account_id IN % s
AND ''' + query_line + '''
AND reconcile_id IS NULL ) ''' , (new_journal.id, period.id, move_id, tuple(account_ids),))
#We have also to consider all move_lines that were reconciled
#on another fiscal year, and report them too
cr . execute ( '''
INSERT INTO account_move_line (
name , create_uid , create_date , write_uid , write_date ,
statement_id , journal_id , currency_id , date_maturity ,
partner_id , blocked , credit , state , debit ,
ref , account_id , period_id , date , move_id , amount_currency ,
quantity , product_id , company_id )
( SELECT
b . name , b . create_uid , b . create_date , b . write_uid , b . write_date ,
b . statement_id , % s , b . currency_id , b . date_maturity ,
b . partner_id , b . blocked , b . credit , ' draft ' , b . debit ,
b . ref , b . account_id , % s , b . date , % s , b . amount_currency ,
b . quantity , b . product_id , b . company_id
FROM account_move_line b
WHERE b . account_id IN % s
AND b . reconcile_id IS NOT NULL
AND b . period_id IN ( ''' +fy_period_set+ ''' )
AND b . reconcile_id IN ( SELECT DISTINCT ( reconcile_id )
FROM account_move_line a
WHERE a . period_id IN ( ''' +fy2_period_set+ ''' ) ) ) ''' , (new_journal.id, period.id, move_id, tuple(account_ids),))
#2. report of the accounts with defferal method == 'detail'
cr . execute ( '''
SELECT a . id
FROM account_account a
LEFT JOIN account_account_type t ON ( a . user_type = t . id )
WHERE a . active
AND a . type != ' view '
AND t . close_method = % s ''' , ( ' detail ' , ))
account_ids = map ( lambda x : x [ 0 ] , cr . fetchall ( ) )
if account_ids :
cr . execute ( '''
INSERT INTO account_move_line (
name , create_uid , create_date , write_uid , write_date ,
statement_id , journal_id , currency_id , date_maturity ,
partner_id , blocked , credit , state , debit ,
ref , account_id , period_id , date , move_id , amount_currency ,
quantity , product_id , company_id )
( SELECT name , create_uid , create_date , write_uid , write_date ,
statement_id , % s , currency_id , date_maturity , partner_id ,
blocked , credit , ' draft ' , debit , ref , account_id ,
% s , date , % s , amount_currency , quantity , product_id , company_id
FROM account_move_line
WHERE account_id IN % s
AND ''' + query_line + ''' )
''' , (new_journal.id, period.id, move_id, tuple(account_ids),))
#3. report of the accounts with defferal method == 'balance'
cr . execute ( '''
SELECT a . id
FROM account_account a
LEFT JOIN account_account_type t ON ( a . user_type = t . id )
WHERE a . active
AND a . type != ' view '
AND t . close_method = % s ''' , ( ' balance ' , ))
account_ids = map ( lambda x : x [ 0 ] , cr . fetchall ( ) )
query_1st_part = """
INSERT INTO account_move_line (
debit , credit , name , date , move_id , journal_id , period_id ,
account_id , currency_id , amount_currency , company_id , state ) VALUES
"""
query_2nd_part = " "
query_2nd_part_args = [ ]
for account in obj_acc_account . browse ( cr , uid , account_ids , context = { ' fiscalyear ' : fy_id } ) :
balance_in_currency = 0.0
if account . currency_id :
cr . execute ( ' SELECT sum(amount_currency) as balance_in_currency FROM account_move_line ' \
' WHERE account_id = %s ' \
' AND ' + query_line + ' ' \
' AND currency_id = %s ' , ( account . id , account . currency_id . id ) )
balance_in_currency = cr . dictfetchone ( ) [ ' balance_in_currency ' ]
company_currency_id = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ) . company_id . currency_id
if not currency_obj . is_zero ( cr , uid , company_currency_id , abs ( account . balance ) ) :
if query_2nd_part :
query_2nd_part + = ' , '
query_2nd_part + = " ( %s , %s , %s , %s , %s , %s , %s , %s , %s , %s , %s , %s ) "
query_2nd_part_args + = ( account . balance > 0 and account . balance or 0.0 ,
account . balance < 0 and - account . balance or 0.0 ,
data [ 0 ] . report_name ,
period . date_start ,
move_id ,
new_journal . id ,
period . id ,
account . id ,
account . currency_id and account . currency_id . id or None ,
balance_in_currency ,
account . company_id . id ,
' draft ' )
if query_2nd_part :
cr . execute ( query_1st_part + query_2nd_part , tuple ( query_2nd_part_args ) )
#validate and centralize the opening move
obj_acc_move . validate ( cr , uid , [ move_id ] , context = context )
#reconcile all the move.line of the opening move
ids = obj_acc_move_line . search ( cr , uid , [ ( ' journal_id ' , ' = ' , new_journal . id ) ,
2010-04-09 11:09:59 +00:00
( ' period_id.fiscalyear_id ' , ' = ' , new_fyear . id ) ] )
context [ ' fy_closing ' ] = True
if ids :
2011-09-23 13:48:27 +00:00
reconcile_id = obj_acc_move_line . reconcile ( cr , uid , ids , context = context )
#set the creation date of the reconcilation at the first day of the new fiscalyear, in order to have good figures in the aged trial balance
self . pool . get ( ' account.move.reconcile ' ) . write ( cr , uid , [ reconcile_id ] , { ' create_date ' : new_fyear . date_start } , context = context )
#create the journal.period object and link it to the old fiscalyear
2011-02-15 09:20:57 +00:00
new_period = data [ 0 ] . period_id . id
2011-09-23 13:48:27 +00:00
ids = obj_acc_journal_period . search ( cr , uid , [ ( ' journal_id ' , ' = ' , new_journal . id ) , ( ' period_id ' , ' = ' , new_period ) ] )
2010-04-09 11:09:59 +00:00
if not ids :
ids = [ obj_acc_journal_period . create ( cr , uid , {
2011-09-23 13:48:27 +00:00
' name ' : ( new_journal . name or ' ' ) + ' : ' + ( period . code or ' ' ) ,
2010-04-09 11:09:59 +00:00
' journal_id ' : new_journal . id ,
' period_id ' : period . id
} ) ]
cr . execute ( ' UPDATE account_fiscalyear ' \
' SET end_journal_period_id = %s ' \
' WHERE id = %s ' , ( ids [ 0 ] , old_fyear . id ) )
2011-09-23 13:48:27 +00:00
2010-12-28 10:44:45 +00:00
return { ' type ' : ' ir.actions.act_window_close ' }
2010-04-09 11:09:59 +00:00
account_fiscalyear_close ( )
2010-11-16 12:16:58 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: