1
# -*- encoding: utf-8 -*-
2
###########################################################################
3
# Module Writen to OpenERP, Open Source Management Solution
4
# Copyright (C) OpenERP Venezuela (<http://openerp.com.ve>).
6
###############Credits######################################################
7
# Coded by: Humberto Arocha humberto@openerp.com.ve
8
# Angelica Barrios angelicaisabelb@gmail.com
9
# Jordi Esteve <jesteve@zikzakmedia.com>
10
# Javier Duran <javieredm@gmail.com>
11
# Planified by: Humberto Arocha
12
# Finance by: LUBCAN COL S.A.S http://www.lubcancol.com
13
# Audited by: Humberto Arocha humberto@openerp.com.ve
14
#############################################################################
15
# This program is free software: you can redistribute it and/or modify
16
# it under the terms of the GNU General Public License as published by
17
# the Free Software Foundation, either version 3 of the License, or
18
# (at your option) any later version.
20
# This program is distributed in the hope that it will be useful,
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
# GNU General Public License for more details.
25
# You should have received a copy of the GNU General Public License
26
# along with this program. If not, see <http://www.gnu.org/licenses/>.
27
##############################################################################
31
from operator import itemgetter
34
from report import report_sxw
35
from tools import config
36
from tools.translate import _
38
class account_balance(report_sxw.rml_parse):
40
def __init__(self, cr, uid, name, context):
41
super(account_balance, self).__init__(cr, uid, name, context)
43
self.sum_credit = 0.00
44
self.sum_balance = 0.00
45
self.sum_debit_fy = 0.00
46
self.sum_credit_fy = 0.00
47
self.sum_balance_fy = 0.00
49
self.date_lst_string = ''
50
self.localcontext.update({
53
'get_fiscalyear_text': self.get_fiscalyear_text,
54
'get_periods_and_date_text': self.get_periods_and_date_text,
55
'get_informe_text': self.get_informe_text,
56
'get_month':self.get_month,
57
'exchange_name':self.exchange_name,
59
self.context = context
62
def get_fiscalyear_text(self, form):
64
Returns the fiscal year text used on the report.
66
fiscalyear_obj = self.pool.get('account.fiscalyear')
68
if form.get('fiscalyear'):
69
fiscalyear = fiscalyear_obj.browse(self.cr, self.uid, form['fiscalyear'])
70
return fiscalyear.name or fiscalyear.code
72
fiscalyear = fiscalyear_obj.browse(self.cr, self.uid, fiscalyear_obj.find(self.cr, self.uid))
73
return "%s*" % (fiscalyear.name or fiscalyear.code)
75
def get_informe_text(self, form):
77
Returns the header text used on the report.
79
afr_id = form['afr_id'] and type(form['afr_id']) in (list,tuple) and form['afr_id'][0] or form['afr_id']
81
name = self.pool.get('afr').browse(self.cr, self.uid, afr_id).name
82
elif form['analytic_ledger'] and form['columns']=='four' and form['inf_type'] == 'BS':
83
name = _('Analytic Ledger')
84
elif form['inf_type'] == 'BS':
85
name = _('Balance Sheet')
86
elif form['inf_type'] == 'IS':
87
name = _('Income Statement')
91
def get_month(self, form):
93
return day, year and month
95
if form['filter'] in ['bydate', 'all']:
96
months=["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"]
97
mes = months[time.strptime(form['date_to'],"%Y-%m-%d")[1]-1]
98
ano = time.strptime(form['date_to'],"%Y-%m-%d")[0]
99
dia = time.strptime(form['date_to'],"%Y-%m-%d")[2]
100
return _('From ')+self.formatLang(form['date_from'], date=True)+ _(' to ')+self.formatLang(form['date_to'], date=True)
101
elif form['filter'] in ['byperiod', 'all']:
103
period_obj = self.pool.get('account.period')
105
for period in period_obj.browse(self.cr, self.uid, form['periods']):
106
aux.append(period.date_start)
107
aux.append(period.date_stop)
109
return _('From ')+self.formatLang(aux[0], date=True)+_(' to ')+self.formatLang(aux[-1], date=True)
111
def get_periods_and_date_text(self, form):
113
Returns the text with the periods/dates used on the report.
115
period_obj = self.pool.get('account.period')
117
fiscalyear_id = form['fiscalyear'] or fiscalyear_obj.find(self.cr, self.uid)
118
period_ids = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear_id),('special','=',False)])
119
if form['filter'] in ['byperiod', 'all']:
120
period_ids = form['periods']
121
periods_str = ', '.join([period.name or period.code for period in period_obj.browse(self.cr, self.uid, period_ids)])
124
if form['filter'] in ['bydate', 'all']:
125
dates_str = self.formatLang(form['date_from'], date=True) + ' - ' + self.formatLang(form['date_to'], date=True) + ' '
126
return {'periods':periods_str, 'date':dates_str}
129
def special_period(self, periods):
130
period_obj = self.pool.get('account.period')
131
period_brw = period_obj.browse(self.cr, self.uid, periods)
132
period_counter = [True for i in period_brw if not i.special]
133
if not period_counter:
137
def exchange_name(self, form):
138
self.from_currency_id = self.get_company_currency(form['company_id'] and type(form['company_id']) in (list,tuple) and form['company_id'][0] or form['company_id'])
139
if not form['currency_id']:
140
self.to_currency_id = self.from_currency_id
142
self.to_currency_id = form['currency_id'] and type(form['currency_id']) in (list, tuple) and form['currency_id'][0] or form['currency_id']
143
return self.pool.get('res.currency').browse(self.cr, self.uid, self.to_currency_id).name
145
def exchange(self, from_amount):
146
if self.from_currency_id == self.to_currency_id:
148
curr_obj = self.pool.get('res.currency')
149
return curr_obj.compute(self.cr, self.uid, self.from_currency_id, self.to_currency_id, from_amount)
151
def get_company_currency(self, company_id):
152
rc_obj = self.pool.get('res.company')
153
return rc_obj.browse(self.cr, self.uid, company_id).currency_id.id
155
def get_company_accounts(self, company_id, acc='credit'):
156
rc_obj = self.pool.get('res.company')
158
return [brw.id for brw in rc_obj.browse(self.cr, self.uid, company_id).credit_account_ids]
160
return [brw.id for brw in rc_obj.browse(self.cr, self.uid, company_id).debit_account_ids]
163
def _get_analytic_ledger(self, account, ctx={}):
166
if account['type'] in ('other','liquidity','receivable','payable'):
167
#~ TODO: CUANDO EL PERIODO ESTE VACIO LLENARLO CON LOS PERIODOS DEL EJERCICIO
168
#~ FISCAL, SIN LOS PERIODOS ESPECIALES
169
periods = ', '.join([str(i) for i in ctx['periods']])
170
#~ periods = str(tuple(ctx['periods']))
171
where = """where aml.period_id in (%s) and aa.id = %s and aml.state <> 'draft'"""%(periods,account['id'])
173
sql_detalle = """select aml.id as id, aj.name as diario, aa.name as descripcion,
174
(select name from res_partner where aml.partner_id = id) as partner,
175
aa.code as cuenta, aml.name as name,
177
case when aml.debit is null then 0.00 else aml.debit end as debit,
178
case when aml.credit is null then 0.00 else aml.credit end as credit,
179
(select code from account_analytic_account where aml.analytic_account_id = id) as analitica,
180
aml.date as date, ap.name as periodo,
182
from account_move_line aml
183
inner join account_journal aj on aj.id = aml.journal_id
184
inner join account_account aa on aa.id = aml.account_id
185
inner join account_period ap on ap.id = aml.period_id
186
inner join account_move am on am.id = aml.move_id """ + where +\
187
""" order by date, am.name"""
189
self.cr.execute(sql_detalle)
190
resultat = self.cr.dictfetchall()
191
balance = account['balanceinit']
193
balance += det['debit'] - det['credit']
197
'journal':det['diario'],
198
'partner':det['partner'],
200
'entry':det['asiento'],
202
'debit': det['debit'],
203
'credit': det['credit'],
204
'analytic': det['analitica'],
205
'period': det['periodo'],
210
def lines(self, form, level=0):
212
Returns all the data needed for the report lines
213
(account info plus debit/credit/balance in the selected period
217
account_obj = self.pool.get('account.account')
218
period_obj = self.pool.get('account.period')
219
fiscalyear_obj = self.pool.get('account.fiscalyear')
221
def _get_children_and_consol(cr, uid, ids, level, context={},change_sign=False):
222
aa_obj = self.pool.get('account.account')
224
for aa_brw in aa_obj.browse(cr, uid, ids, context):
225
if aa_brw.child_id and aa_brw.level < level and aa_brw.type !='consolidation':
227
ids2.append([aa_brw.id,True, False,aa_brw])
228
ids2 += _get_children_and_consol(cr, uid, [x.id for x in aa_brw.child_id], level, context,change_sign=change_sign)
230
ids2.append(aa_brw.id)
232
ids2.append([aa_brw.id,False,True,aa_brw])
235
ids2.append(aa_brw.id)
237
ids2.append([aa_brw.id,True,True,aa_brw])
240
#############################################################################
241
# CONTEXT FOR ENDIND BALANCE #
242
#############################################################################
246
ctx_end['filter'] = form.get('filter','all')
247
ctx_end['fiscalyear'] = fiscalyear.id
248
#~ ctx_end['periods'] = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear.id),('special','=',False)])
250
if ctx_end['filter'] not in ['bydate','none']:
251
special = self.special_period(form['periods'])
255
if form['filter'] in ['byperiod', 'all']:
257
ctx_end['periods'] = period_obj.search(self.cr, self.uid, [('id','in',form['periods'] or ctx_end.get('periods',False))])
259
ctx_end['periods'] = period_obj.search(self.cr, self.uid, [('id','in',form['periods'] or ctx_end.get('periods',False)),('special','=',False)])
261
if form['filter'] in ['bydate','all','none']:
262
ctx_end['date_from'] = form['date_from']
263
ctx_end['date_to'] = form['date_to']
265
return ctx_end.copy()
267
def missing_period(ctx_init):
269
ctx_init['fiscalyear'] = fiscalyear_obj.search(self.cr, self.uid, [('date_stop','<',fiscalyear.date_start)],order='date_stop') and \
270
fiscalyear_obj.search(self.cr, self.uid, [('date_stop','<',fiscalyear.date_start)],order='date_stop')[-1] or []
271
ctx_init['periods'] = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',ctx_init['fiscalyear']),('date_stop','<',fiscalyear.date_start)])
273
#############################################################################
274
# CONTEXT FOR INITIAL BALANCE #
275
#############################################################################
278
ctx_init = self.context.copy()
279
ctx_init['filter'] = form.get('filter','all')
280
ctx_init['fiscalyear'] = fiscalyear.id
282
if form['filter'] in ['byperiod', 'all']:
283
ctx_init['periods'] = form['periods']
284
if not ctx_init['periods']:
285
ctx_init = missing_period(ctx_init.copy())
286
date_start = min([period.date_start for period in period_obj.browse(self.cr, self.uid, ctx_init['periods'])])
287
ctx_init['periods'] = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear.id),('date_stop','<=',date_start)])
288
elif form['filter'] in ['bydate']:
289
ctx_init['date_from'] = fiscalyear.date_start
290
ctx_init['date_to'] = form['date_from']
291
ctx_init['periods'] = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear.id),('date_stop','<=',ctx_init['date_to'])])
292
elif form['filter'] == 'none':
293
ctx_init['periods'] = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear.id),('special','=',True)])
294
date_start = min([period.date_start for period in period_obj.browse(self.cr, self.uid, ctx_init['periods'])])
295
ctx_init['periods'] = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear.id),('date_start','<=',date_start),('special','=',True)])
297
return ctx_init.copy()
300
return abs(n) < 0.005 and 0.0 or n
303
self.from_currency_id = self.get_company_currency(form['company_id'] and type(form['company_id']) in (list,tuple) and form['company_id'][0] or form['company_id'])
304
if not form['currency_id']:
305
self.to_currency_id = self.from_currency_id
307
self.to_currency_id = form['currency_id'] and type(form['currency_id']) in (list, tuple) and form['currency_id'][0] or form['currency_id']
309
if form.has_key('account_list') and form['account_list']:
310
account_ids = form['account_list']
311
del form['account_list']
313
credit_account_ids = self.get_company_accounts(form['company_id'] and type(form['company_id']) in (list,tuple) and form['company_id'][0] or form['company_id'],'credit')
315
debit_account_ids = self.get_company_accounts(form['company_id'] and type(form['company_id']) in (list,tuple) and form['company_id'][0] or form['company_id'],'debit')
317
if form.get('fiscalyear'):
318
if type(form.get('fiscalyear')) in (list,tuple):
319
fiscalyear = form['fiscalyear'] and form['fiscalyear'][0]
320
elif type(form.get('fiscalyear')) in (int,):
321
fiscalyear = form['fiscalyear']
322
fiscalyear = fiscalyear_obj.browse(self.cr, self.uid, fiscalyear)
324
################################################################
326
################################################################
328
account_ids = _get_children_and_consol(self.cr, self.uid, account_ids, form['display_account_level'] and form['display_account_level'] or 100,self.context)
330
credit_account_ids = _get_children_and_consol(self.cr, self.uid, credit_account_ids, 100,self.context,change_sign=True)
332
debit_account_ids = _get_children_and_consol(self.cr, self.uid, debit_account_ids, 100,self.context,change_sign=True)
334
credit_account_ids = list(set(credit_account_ids) - set(debit_account_ids))
337
# Generate the report lines (checking each account)
342
if not form['periods']:
343
form['periods'] = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear.id),('special','=',False)],order='date_start asc')
344
if not form['periods']:
345
raise osv.except_osv(_('UserError'),_('The Selected Fiscal Year Does not have Regular Periods'))
347
if form['columns'] == 'qtr':
348
period_ids = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear.id),('special','=',False)],order='date_start asc')
364
elif form['columns'] == 'thirteen':
365
period_ids = period_obj.search(self.cr, self.uid, [('fiscalyear_id','=',fiscalyear.id),('special','=',False)],order='date_start asc')
367
if form['columns'] == 'qtr':
374
elif form['columns'] == 'thirteen':
391
ctx_init = _ctx_init(self.context.copy())
392
ctx_end = _ctx_end(self.context.copy())
405
for aa_id in account_ids:
409
# Check if we need to include this level
411
if not form['display_account_level'] or aa_id[3].level <= form['display_account_level']:
414
'type' : aa_id[3].type,
415
'code' : aa_id[3].code,
416
'name' : (aa_id[2] and not aa_id[1]) and 'TOTAL %s'%(aa_id[3].name.upper()) or aa_id[3].name,
417
'parent_id' : aa_id[3].parent_id and aa_id[3].parent_id.id,
418
'level' : aa_id[3].level,
421
'change_sign' : credit_account_ids and (id in credit_account_ids and -1 or 1) or 1
424
if form['columns'] == 'qtr':
427
form['periods'] = p_id
429
ctx_init = _ctx_init(self.context.copy())
430
aa_brw_init = account_obj.browse(self.cr, self.uid, id, ctx_init)
432
ctx_end = _ctx_end(self.context.copy())
433
aa_brw_end = account_obj.browse(self.cr, self.uid, id, ctx_end)
435
if form['inf_type'] == 'IS':
436
d,c,b = map(z,[aa_brw_end.debit,aa_brw_end.credit,aa_brw_end.balance])
438
'dbr%s'%pn: self.exchange(d),
439
'cdr%s'%pn: self.exchange(c),
440
'bal%s'%pn: self.exchange(b),
443
i,d,c = map(z,[aa_brw_init.balance,aa_brw_end.debit,aa_brw_end.credit])
446
'dbr%s'%pn: self.exchange(d),
447
'cdr%s'%pn: self.exchange(c),
448
'bal%s'%pn: self.exchange(b),
453
form['periods'] = period_ids
455
ctx_init = _ctx_init(self.context.copy())
456
aa_brw_init = account_obj.browse(self.cr, self.uid, id, ctx_init)
458
ctx_end = _ctx_end(self.context.copy())
459
aa_brw_end = account_obj.browse(self.cr, self.uid, id, ctx_end)
461
if form['inf_type'] == 'IS':
462
d,c,b = map(z,[aa_brw_end.debit,aa_brw_end.credit,aa_brw_end.balance])
464
'dbr5': self.exchange(d),
465
'cdr5': self.exchange(c),
466
'bal5': self.exchange(b),
469
i,d,c = map(z,[aa_brw_init.balance,aa_brw_end.debit,aa_brw_end.credit])
472
'dbr5': self.exchange(d),
473
'cdr5': self.exchange(c),
474
'bal5': self.exchange(b),
477
elif form['columns'] == 'thirteen':
479
for p_id in period_ids:
480
form['periods'] = [p_id]
482
ctx_init = _ctx_init(self.context.copy())
483
aa_brw_init = account_obj.browse(self.cr, self.uid, id, ctx_init)
485
ctx_end = _ctx_end(self.context.copy())
486
aa_brw_end = account_obj.browse(self.cr, self.uid, id, ctx_end)
488
if form['inf_type'] == 'IS':
489
d,c,b = map(z,[aa_brw_end.debit,aa_brw_end.credit,aa_brw_end.balance])
491
'dbr%s'%pn: self.exchange(d),
492
'cdr%s'%pn: self.exchange(c),
493
'bal%s'%pn: self.exchange(b),
496
i,d,c = map(z,[aa_brw_init.balance,aa_brw_end.debit,aa_brw_end.credit])
499
'dbr%s'%pn: self.exchange(d),
500
'cdr%s'%pn: self.exchange(c),
501
'bal%s'%pn: self.exchange(b),
506
form['periods'] = period_ids
508
ctx_init = _ctx_init(self.context.copy())
509
aa_brw_init = account_obj.browse(self.cr, self.uid, id, ctx_init)
511
ctx_end = _ctx_end(self.context.copy())
512
aa_brw_end = account_obj.browse(self.cr, self.uid, id, ctx_end)
514
if form['inf_type'] == 'IS':
515
d,c,b = map(z,[aa_brw_end.debit,aa_brw_end.credit,aa_brw_end.balance])
517
'dbr13': self.exchange(d),
518
'cdr13': self.exchange(c),
519
'bal13': self.exchange(b),
522
i,d,c = map(z,[aa_brw_init.balance,aa_brw_end.debit,aa_brw_end.credit])
525
'dbr13': self.exchange(d),
526
'cdr13': self.exchange(c),
527
'bal13': self.exchange(b),
532
aa_brw_init = account_obj.browse(self.cr, self.uid, id, ctx_init)
533
aa_brw_end = account_obj.browse(self.cr, self.uid, id, ctx_end)
535
i,d,c = map(z,[aa_brw_init.balance,aa_brw_end.debit,aa_brw_end.credit])
538
'balanceinit': self.exchange(i),
539
'debit': self.exchange(d),
540
'credit': self.exchange(c),
541
'ytd': self.exchange(d-c),
544
if form['inf_type'] == 'IS' and form['columns'] == 'one':
546
'balance': self.exchange(d-c),
550
'balance': self.exchange(b),
554
# Check whether we must include this line in the report or not
558
if form['columns'] in ('thirteen', 'qtr'):
560
if form['display_account'] == 'mov' and aa_id[3].parent_id:
561
# Include accounts with movements
562
for x in range(pn-1):
563
to_test.append(res.get('dbr%s'%x,0.0) >= 0.005 and True or False)
564
to_test.append(res.get('cdr%s'%x,0.0) >= 0.005 and True or False)
568
elif form['display_account'] == 'bal' and aa_id[3].parent_id:
569
# Include accounts with balance
570
for x in range(pn-1):
571
to_test.append(res.get('bal%s'%x,0.0) >= 0.005 and True or False)
575
elif form['display_account'] == 'bal_mov' and aa_id[3].parent_id:
576
# Include accounts with balance or movements
577
for x in range(pn-1):
578
to_test.append(res.get('bal%s'%x,0.0) >= 0.005 and True or False)
579
to_test.append(res.get('dbr%s'%x,0.0) >= 0.005 and True or False)
580
to_test.append(res.get('cdr%s'%x,0.0) >= 0.005 and True or False)
584
# Include all accounts
589
if form['display_account'] == 'mov' and aa_id[3].parent_id:
590
# Include accounts with movements
591
if abs(d) >= 0.005 or abs(c) >= 0.005:
593
elif form['display_account'] == 'bal' and aa_id[3].parent_id:
594
# Include accounts with balance
597
elif form['display_account'] == 'bal_mov' and aa_id[3].parent_id:
598
# Include accounts with balance or movements
599
if abs(b) >= 0.005 or abs(d) >= 0.005 or abs(c) >= 0.005:
602
# Include all accounts
606
if to_include and form['analytic_ledger'] and form['columns']=='four' and form['inf_type'] == 'BS' and res['type'] in ('other','liquidity','receivable','payable'):
607
res['mayor'] = self._get_analytic_ledger(res,ctx=ctx_end)
613
result_acc.append(res)
615
# Check whether we must sumarize this line in the report or not
617
if form['tot_check'] and res['type'] == 'view' and res['level'] == 1 and (res['id'] not in tot):
619
if form['columns'] == 'qtr':
621
tot[res['id']] = True
622
tot_bal1 += res.get('bal1',0.0)
623
tot_bal2 += res.get('bal2',0.0)
624
tot_bal3 += res.get('bal3',0.0)
625
tot_bal4 += res.get('bal4',0.0)
626
tot_bal5 += res.get('bal5',0.0)
628
elif form['columns'] == 'thirteen':
630
tot[res['id']] = True
631
tot_bal1 += res.get('bal1',0.0)
632
tot_bal2 += res.get('bal2',0.0)
633
tot_bal3 += res.get('bal3',0.0)
634
tot_bal4 += res.get('bal4',0.0)
635
tot_bal5 += res.get('bal5',0.0)
636
tot_bal6 += res.get('bal6',0.0)
637
tot_bal7 += res.get('bal7',0.0)
638
tot_bal8 += res.get('bal8',0.0)
639
tot_bal9 += res.get('bal9',0.0)
640
tot_bal10 += res.get('bal10',0.0)
641
tot_bal11 += res.get('bal11',0.0)
642
tot_bal12 += res.get('bal12',0.0)
643
tot_bal13 += res.get('bal13',0.0)
647
tot[res['id']] = True
648
tot_bin += res['balanceinit']
649
tot_deb += res['debit']
650
tot_crd += res['credit']
651
tot_ytd += res['ytd']
652
tot_eje += res['balance']
655
str_label = form['lab_str']
658
'name': 'TOTAL %s'%(str_label),
662
if form['columns'] == 'qtr':
669
elif form['columns'] == 'thirteen':
687
'balanceinit': tot_bin,
694
result_acc.append(res2)
697
report_sxw.report_sxw('report.afr.1cols',
699
'account_financial_report/report/balance_full.rml',
700
parser=account_balance,
703
report_sxw.report_sxw('report.afr.2cols',
705
'account_financial_report/report/balance_full_2_cols.rml',
706
parser=account_balance,
709
report_sxw.report_sxw('report.afr.4cols',
711
'account_financial_report/report/balance_full_4_cols.rml',
712
parser=account_balance,
715
report_sxw.report_sxw('report.afr.analytic.ledger',
717
'account_financial_report/report/balance_full_4_cols_analytic_ledger.rml',
718
parser=account_balance,
721
report_sxw.report_sxw('report.afr.5cols',
723
'account_financial_report/report/balance_full_5_cols.rml',
724
parser=account_balance,
727
report_sxw.report_sxw('report.afr.qtrcols',
729
'account_financial_report/report/balance_full_qtr_cols.rml',
730
parser=account_balance,
733
report_sxw.report_sxw('report.afr.13cols',
735
'account_financial_report/report/balance_full_13_cols.rml',
736
parser=account_balance,