~oscarolar/addons-vauxoo/addons-vauxoo

« back to all changes in this revision

Viewing changes to ifrs_report/model/ifrs.py

  • Committer: Humberto Arocha
  • Date: 2013-05-24 15:31:51 UTC
  • Revision ID: humbertoarocha@gmail.com-20130524153151-hh4fbw172drp6poq
[MERGE] Backport from Trunk revno 802..803

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
# -*- encoding: utf-8 -*-
 
3
###########################################################################
 
4
#    Module Writen to OpenERP, Open Source Management Solution
 
5
#    Copyright (C) OpenERP Venezuela (<http://openerp.com.ve>).
 
6
#    All Rights Reserved
 
7
###############Credits######################################################
 
8
#    Coded by: Katherine Zaoral <katherine.zaoral@vauxoo.com>
 
9
#    Coded by: Yanina Aular <yanina.aular@vauxoo.com>
 
10
#    Planified by: Humberto Arocha <hbto@vauxoo.com>
 
11
#    Audited by: Nhomar Hernandez <nhomar@vauxoo.com>
 
12
#############################################################################
 
13
#    This program is free software: you can redistribute it and/or modify
 
14
#    it under the terms of the GNU Affero General Public License as published by
 
15
#    the Free Software Foundation, either version 3 of the License, or
 
16
#    (at your option) any later version.
 
17
#
 
18
#    This program is distributed in the hope that it will be useful,
 
19
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
#    GNU Affero General Public License for more details.
 
22
#
 
23
#    You should have received a copy of the GNU Affero General Public License
 
24
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
25
################################################################################
 
26
 
 
27
from osv import osv
 
28
from osv import fields
 
29
 
 
30
from tools.translate import _
 
31
 
 
32
class ifrs_ifrs(osv.osv):
 
33
 
 
34
    _name = 'ifrs.ifrs'
 
35
    _rec_name = 'code'
 
36
    _columns = {
 
37
        'name' : fields.char('Name', 128, required = True ),
 
38
        'company_id' : fields.many2one('res.company', string='Company', ondelete='cascade' ),
 
39
        'title' : fields.char('Title', 128, required = True, translate = True ),
 
40
        'code' : fields.char('Code', 128, required = True ),
 
41
        'description' : fields.text('Description'),
 
42
 
 
43
        'ifrs_lines_ids' : fields.one2many('ifrs.lines', 'ifrs_id', 'IFRS lines' ),
 
44
 
 
45
        'state': fields.selection( [
 
46
            ('draft','Draft'),
 
47
            ('ready', 'Ready'),
 
48
            ('done','Done'),
 
49
            ('cancel','Cancel') ],
 
50
            'State', required=True ),
 
51
 
 
52
        'fiscalyear_id' : fields.many2one('account.fiscalyear', 'Fiscal Year' ),
 
53
        'do_compute' : fields.boolean('Compute'),
 
54
        'ifrs_ids':fields.many2many('ifrs.ifrs', 'ifrs_m2m_rel', 'parent_id', 'child_id', string='Other Reportes',)
 
55
    }
 
56
 
 
57
    _defaults = {
 
58
        'state' : 'draft',
 
59
    }
 
60
 
 
61
    def compute(self, cr, uid, ids, context=None):
 
62
        if context is None: context = {}
 
63
        fy = self.browse(cr, uid, ids, context=context)[0]
 
64
        context.update({'whole_fy':True, 'fiscalyear':fy.fiscalyear_id.id})
 
65
        
 
66
        return self.write(cr,uid,ids,{'do_compute':True},context=context)
 
67
    
 
68
    def copy(self, cr, uid, id, default=None, context=None):
 
69
        if default is None:
 
70
            default = {}
 
71
        default.update({
 
72
            'do_compute' : False,
 
73
        })
 
74
        res = super(ifrs_ifrs, self).copy(cr, uid, id, default, context)
 
75
        return res
 
76
 
 
77
ifrs_ifrs()
 
78
 
 
79
class ifrs_lines(osv.osv):
 
80
 
 
81
    _name = 'ifrs.lines'
 
82
    _parent_store = True
 
83
#    _parent_name = "parent_id"
 
84
    _order = 'sequence, type'
 
85
 
 
86
    def _get_sum_total(self, cr, uid, brw, context = None):
 
87
        if context is None: context = {}
 
88
        c = context.copy()
 
89
        res = 0
 
90
        for t in brw.total_ids:
 
91
            res += self._get_sum( cr, uid, t.id, context = c )
 
92
        if brw.operator <> 'without':
 
93
            res2=0
 
94
            for o in brw.operand_ids:
 
95
                res2 += self._get_sum( cr, uid, o.id, context = c )
 
96
            if brw.operator == 'subtract':
 
97
                res -= res2
 
98
            elif brw.operator == 'percent':
 
99
                res =  res2 != 0 and (100 * res / res2) or 0.0
 
100
            elif brw.operator == 'ratio':
 
101
                res =  res2 != 0 and (res / res2) or 0.0
 
102
            elif brw.operator == 'product':
 
103
                res =  res * res2
 
104
        return res
 
105
 
 
106
    def _get_sum( self, cr, uid, id, context = None ):
 
107
        fy_obj = self.pool.get('account.fiscalyear')
 
108
        period_obj = self.pool.get('account.period')
 
109
        if context is None: context = {}
 
110
        res = 0
 
111
        c = context.copy()
 
112
        brw = self.browse( cr, uid, id, context = c )
 
113
        
 
114
        #~ Assembling context
 
115
        
 
116
        #~ Generic context applicable to the different types
 
117
        
 
118
        if not c.get('fiscalyear'):
 
119
            c['fiscalyear']=fy_obj.find(cr,uid,dt=None,context=c)
 
120
        
 
121
        if not c.get('period_from',False) and not c.get('period_to',False):
 
122
            if context.get('whole_fy',False):
 
123
                c['period_from'] = period_obj.search(cr,uid,[('fiscalyear_id','=',c['fiscalyear']),('special','=',True)])
 
124
                if not c['period_from']:
 
125
                    raise osv.except_osv(_('Error !'), _('There are no special period in %s')%(fy_obj.browse(cr,uid,c['fiscalyear'],context=c).name))
 
126
                c['period_from']=c['period_from'][0]
 
127
            c['period_to'] =period_obj.search(cr,uid,[('fiscalyear_id','=',c['fiscalyear'])])[-1]
 
128
        
 
129
        c.get('periods') and c.pop('periods')
 
130
        c.get('initial_bal') and c.pop('initial_bal')
 
131
        
 
132
        if brw.type == 'detail':
 
133
            if brw.acc_val=='init':
 
134
                print c['period_from'],'impirmo period_from'
 
135
                period_ids = period_obj.build_ctx_periods_initial(cr, uid, c['period_from'])
 
136
                c['periods'] = period_ids
 
137
                print c['periods'],'impprimo period'
 
138
                period_company_id = period_obj.browse(cr, uid, c['period_from'], context=context).company_id.id
 
139
##                c['period_to']= period_obj.previous(cr, uid, c['period_from'],context= c) or c['period_from']
 
140
#                period_to = period_obj.previous(cr, uid, c['period_from'],context= c) or c['period_from']
 
141
 #               c['period_from'] = period_obj.search(cr, uid, [('company_id', '=', period_company_id),('special', '=', True), ('fiscalyear_id','=',context.get('fiscalyear'))], order='date_start', limit=1)[0]
 
142
  #              period_from_to = period_obj.browse(cr, uid, [c['period_to'], c['period_from']], context=context)
 
143
   #             if period_from_to[0].date_start <> period_from_to[1].date_start:
 
144
    #                c['period_to'] = period_to
 
145
     #           else:
 
146
      #              c['period_to'] = c['period_from']
 
147
##                c['period_from'] = period_obj.previous(cr, uid, c['period_from'],context= c) or c['period_from']
 
148
            if not c['period_from']:
 
149
                    raise osv.except_osv(_('Error !'), _('prueba001 %s')%(period_obj.browse(cr,uid,c['period_from'],context=c).name))
 
150
##                c['period_to']=c['period_from']
 
151
 
 
152
 
 
153
            elif brw.acc_val=='var':
 
154
                if context.get('whole_fy',False):
 
155
                    c['period_from'] =period_obj.search(cr,uid,[('fiscalyear_id','=',c['fiscalyear'],)])
 
156
                    if not c['period_from']:
 
157
                        raise osv.except_osv(_('Error !'), _('There are no periods in %s')%(fy_obj.browse(cr,uid,c['fiscalyear'],context=c).name))
 
158
                    
 
159
                if isinstance( c['period_from'], (int, long) ):
 
160
                    c['period_from']=c['period_from']
 
161
                else:
 
162
                    c['period_from']=c['period_from'][1]
 
163
                    
 
164
        elif brw.type == 'total':
 
165
            if brw.comparison <> 'without':
 
166
                c2 = c.copy()
 
167
 
 
168
                print "c2['period_from']",c2['period_from']
 
169
                print "c2['period_to']",c2['period_to']
 
170
 
 
171
                c2['period_from'] = period_obj.previous(cr, uid, c2['period_from'],context= c2)
 
172
                if not c2['period_from']:
 
173
                    raise osv.except_osv(_('Error !'), _('There are previous period to %s')%(period_obj.browse(cr,uid,c['period_from'],context=c).name))
 
174
                c2['period_to']=c2['period_from']
 
175
                
 
176
                print "c2['period_from']",c2['period_from']
 
177
                print "c2['period_to']",c2['period_to']
 
178
        
 
179
        
 
180
        #~ Stuffing the sum
 
181
        brw = self.browse( cr, uid, id, context = c )
 
182
        
 
183
        if brw.type == 'abstract':
 
184
            pass
 
185
        elif brw.type == 'constant':
 
186
            if brw.constant_type == 'period_days':
 
187
                res = period_obj._get_period_days(cr, uid, c['period_from'], c['period_to'])
 
188
            elif brw.constant_type == 'fy_periods':
 
189
                res = fy_obj._get_fy_periods(cr, uid, c['fiscalyear'])
 
190
            elif brw.constant_type == 'fy_month':
 
191
                res = fy_obj._get_fy_month(cr, uid, c['fiscalyear'],c['period_to'])
 
192
        elif brw.type == 'detail':
 
193
            analytic = [an.id for an in brw.analytic_ids]
 
194
            if analytic:
 
195
                c['analytic'] = analytic
 
196
            c['partner_detail'] = c.get('partner_detail')
 
197
            for a in brw.cons_ids:
 
198
                if brw.value == 'debit':
 
199
                    res += a.debit
 
200
                elif brw.value == 'credit':
 
201
                    res += a.credit
 
202
                else:
 
203
                    res += a.balance
 
204
                    
 
205
        elif brw.type == 'total':
 
206
            res = self._get_sum_total(cr, uid, brw, context = c)
 
207
            if brw.comparison <> 'without':
 
208
                res2=0
 
209
                #~ TODO: Write definition for previous periods
 
210
                #~ that will be the arguments for the new brw.
 
211
                
 
212
                brw = self.browse( cr, uid, id, context = c2 )
 
213
                res2 = self._get_sum_total(cr, uid, brw, context = c2)
 
214
 
 
215
                print 100*'*'
 
216
                print 'RES 1 DE COMPARACION ', res
 
217
                print 'RES 2 DE COMPARACION ', res2
 
218
 
 
219
 
 
220
                if brw.comparison == 'subtract':
 
221
                    res -= res2
 
222
                elif brw.comparison == 'percent':
 
223
                    res =  res2 != 0 and (100 * res / res2) or 0.0
 
224
                elif brw.comparison == 'ratio':
 
225
                    res =  res2 != 0 and (res / res2) or 0.0
 
226
            
 
227
                print 'RES DESPUES DE COMPARACION ', res
 
228
        return brw.inv_sign and (-1.0 * res) or res 
 
229
 
 
230
    def _consolidated_accounts_sum( self, cr, uid, ids, field_name, arg, context = None ):
 
231
        if context is None: context = {}
 
232
        res = {}
 
233
        for id in ids:
 
234
            res[id] = self._get_sum( cr, uid, id, context = context )
 
235
        return res
 
236
 
 
237
    def _get_level(self, cr, uid, ids, field_name, arg, context=None):
 
238
        res = {}
 
239
        for ifrs_line in self.browse(cr, uid, ids, context=context):
 
240
            level = 0
 
241
            parent = ifrs_line.parent_id
 
242
            while parent:
 
243
                level += 1
 
244
                parent = parent.parent_id
 
245
            res[ifrs_line.id] = level
 
246
        return res
 
247
 
 
248
    def _get_children_and_total(self, cr, uid, ids, context=None):
 
249
        #this function search for all the children and all consolidated children (recursively) of the given total ids
 
250
        ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)], context=context)
 
251
        ids3 = []
 
252
        for rec in self.browse(cr, uid, ids2, context=context):
 
253
            for child in rec.total_ids:
 
254
                ids3.append(child.id)
 
255
        if ids3:
 
256
            ids3 = self._get_children_and_total(cr, uid, ids3, context)
 
257
        return ids2 + ids3
 
258
    def _get_changes_on_ifrs(self, cr, uid, ids, context=None):
 
259
        if context is None: context = {}
 
260
        res = []
 
261
        ifrs_brws = self.pool.get('ifrs.ifrs').browse(cr, uid, ids, context = context)
 
262
        for brw in ifrs_brws:
 
263
            if brw.do_compute:
 
264
                for l in brw.ifrs_lines_ids:
 
265
                    res.append(l.id)
 
266
                #~ TODO: write back False to brw.do_compute with SQL
 
267
                #~ INCLUDE A LOGGER
 
268
        print 100*"*"
 
269
        print 'RECOMPUTING LINES ',res
 
270
        return res
 
271
        
 
272
    _columns = {
 
273
        'sequence' : fields.integer( 'Sequence', required = True ),
 
274
        'name' : fields.char( 'Name', 128, required = True, translate = True ),
 
275
        'type': fields.selection(
 
276
           [
 
277
                ('abstract','Abstract'),
 
278
                ('detail', 'Detail'),
 
279
                ('constant', 'Constant'),
 
280
                ('total','Total') ] ,
 
281
            string = 'Type',
 
282
            required = True ),
 
283
        'constant_type': fields.selection(
 
284
           [
 
285
                ('period_days','Days of Period'),
 
286
                ('fy_periods',"FY's Periods"),
 
287
                ('fy_month',"FY's Month"),
 
288
            ],
 
289
            string = 'Constant Type',
 
290
            required = False ),
 
291
        'ifrs_id' : fields.many2one('ifrs.ifrs', 'IFRS', required = True ),
 
292
        'amount' : fields.function( _consolidated_accounts_sum, method = True, type='float', string='Amount', 
 
293
            store={
 
294
                    'ifrs.ifrs':(_get_changes_on_ifrs,['do_compute'],15)
 
295
            },
 
296
            help="This field will update when you click the compute button in the IFRS doc form"
 
297
            ),
 
298
 
 
299
        'cons_ids' : fields.many2many('account.account', 'ifrs_account_rel', 'ifrs_lines_id', 'account_id', string='Consolidated Accounts' ),
 
300
        'analytic_ids' : fields.many2many('account.analytic.account', 'ifrs_analytic_rel', 'ifrs_lines_id', 'analytic_id', string='Consolidated Analytic Accounts' ),
 
301
 
 
302
        
 
303
        'parent_id' : fields.many2one('ifrs.lines','Parent', select=True, ondelete ='set null', domain="[('ifrs_id','=',parent.id), ('type','=','total'),('id','!=',id)]"),
 
304
 
 
305
        'parent_abstract_id' : fields.many2one('ifrs.lines','Parent Abstract', select=True, ondelete ='set null', domain="[('ifrs_id','=',parent.id),('type','=','abstract'),('id','!=',id)]"),
 
306
 
 
307
        'parent_right' : fields.integer('Parent Right', select=1 ),
 
308
        'parent_left' : fields.integer('Parent Left', select=1 ),
 
309
 
 
310
    'level': fields.function(_get_level, string='Level', method=True, type='integer',
 
311
         store={
 
312
            'ifrs.lines': (_get_children_and_total, ['parent_id'], 10),
 
313
         }),
 
314
 
 
315
        'operand_ids' : fields.many2many('ifrs.lines', 'ifrs_operand_rel', 'ifrs_parent_id', 'ifrs_child_id', string='Operands' ),
 
316
 
 
317
        'operator': fields.selection( [
 
318
            ('subtract', 'Subtraction'),
 
319
            ('percent', 'Percentage'),
 
320
            ('ratio','Ratio'),
 
321
            ('product','Product'),
 
322
            ('without','')
 
323
            ],
 
324
            'Operator', required=False ,
 
325
            help='Leaving blank will not take into account Operands'),
 
326
 
 
327
        'comparison': fields.selection( [
 
328
            ('subtract', 'Subtraction'),
 
329
            ('percent', 'Percentage'),
 
330
            ('ratio','Ratio'),
 
331
            ('without','')],
 
332
            'Make Comparison', required=False ,
 
333
            help='Make a Comparison against the previous period.\nThat is, period X(n) minus period X(n-1)\nLeaving blank will not make any effects'),
 
334
        
 
335
        'acc_val': fields.selection( [
 
336
            ('init', 'Initial Values'),
 
337
            ('var','Variation in Periods'),
 
338
            ('fy', ('FY All'))],
 
339
            'Accounting Spam', required=False,
 
340
            help='Leaving blank means YTD'),
 
341
 
 
342
        'value': fields.selection( [
 
343
            ('debit', 'Debit'),
 
344
            ('credit','Credit'),
 
345
            ('balance', 'Balance')],
 
346
            'Accounting Value', required=False,
 
347
            help='Leaving blank means Balance'),
 
348
 
 
349
        'total_ids' : fields.many2many('ifrs.lines','ifrs_lines_rel','parent_id','child_id',string='Total'),
 
350
        
 
351
        'inv_sign' : fields.boolean('Change Sign to Amount'),
 
352
        
 
353
        'invisible' : fields.boolean('Invisible'),
 
354
    }
 
355
 
 
356
    _defaults = {
 
357
        'type' : 'abstract',
 
358
        'invisible' : False,
 
359
        'acc_val' : 'fy',
 
360
        'value' : 'balance'
 
361
        #'sequence': lambda obj, cr, uid, context: uid,
 
362
    }
 
363
 
 
364
 
 
365
    def _check_description(self, cr, user, ids):
 
366
        for s in self.browse(cr,user,ids):
 
367
            #if s.type=='total' and s.parent_id.type!='abstract':
 
368
            #    return False
 
369
            pass
 
370
        return True
 
371
    
 
372
    _constraints = [
 
373
        (_check_description, ('Error: Los padres de las lineas ifrs de tipo total solo pueden tener padres de tipo abstract'), ['parent_id']),
 
374
    ]
 
375
 
 
376
    _sql_constraints = [('sequence_ifrs_id_unique','unique(sequence,ifrs_id)', 'The sequence already have been set in another IFRS line')]
 
377
    
 
378
ifrs_lines()
 
379
 
 
380
 
 
381
 
 
382
 
 
383
#~ pregunta. comprobacion de la linea... lo hace cuando le da a guardar--- no lo hace a la hora de ingresarlo, puede taer confuciones a la hora que el usuario agregue a mucha gente y luego no sepa a cual se refiere.
 
384
 
 
385
#~ buscar, como hacer para que ordene por secuencia, lo que ingreso!