1
##############################################################################
3
# Copyright (c) 2004-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
5
# WARNING: This program as such is intended to be used by professional
6
# programmers who take the whole responsability of assessing all potential
7
# consequences resulting from its eventual inadequacies and bugs
8
# End users who are looking for a ready-to-use solution with commercial
9
# garantees and support are strongly adviced to contract a Free Software
12
# This program is Free Software; you can redistribute it and/or
13
# modify it under the terms of the GNU General Public License
14
# as published by the Free Software Foundation; either version 2
15
# of the License, or (at your option) any later version.
17
# This program is distributed in the hope that it will be useful,
18
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
# GNU General Public License for more details.
22
# You should have received a copy of the GNU General Public License
23
# along with this program; if not, write to the Free Software
24
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
##############################################################################
28
from osv import fields,osv
29
from osv.orm import browse_null
33
class report_custom(osv.osv):
34
_name = 'ir.report.custom'
36
'name': fields.char('Report Name', size=64, required=True, translate=True),
37
'model_id': fields.many2one('ir.model','Model', required=True, change_default=True),
38
'type': fields.selection([('table','Tabular'),('pie','Pie Chart'),('bar','Bar Chart'),('line','Line Plot')], "Report Type", size=64, required='True'),
39
'title': fields.char("Report title", size=64, required='True', translate=True),
40
'print_format': fields.selection((('A4','a4'),('A5','a5')), 'Print format', required=True),
41
'print_orientation': fields.selection((('landscape','Landscape'),('portrait','Portrait')), 'Print orientation', required=True, size=16),
42
'repeat_header': fields.boolean('Repeat Header'),
43
'footer': fields.char('Report Footer', size=64, required=True),
44
'sortby': fields.char('Sorted By', size=64),
45
'fields_child0': fields.one2many('ir.report.custom.fields', 'report_id','Fields', required=True),
46
'field_parent': fields.many2one('ir.model.fields','Child Field'),
47
'state': fields.selection([('unsubscribed','Unsubscribed'),('subscribed','Subscribed')], 'State', size=64),
48
'frequency': fields.selection([('Y','Yearly'),('M','Monthly'),('D','Daily')], 'Frequency', size=64),
49
'limitt': fields.char('Limit', size=9),
50
'menu_id': fields.many2one('ir.ui.menu', 'Menu')
53
'print_format': lambda *a: 'A4',
54
'print_orientation': lambda *a: 'portrait',
55
'state': lambda *a: 'unsubscribed',
56
'type': lambda *a: 'table',
57
'footer': lambda *a: 'Generated by Tiny ERP'
60
def onchange_model_id(self, cr, uid, ids, model_id):
63
return {'domain': {'field_parent': [('model_id','=',model_id)]}}
65
def unsubscribe(self, cr, uid, ids, context={}):
66
#TODO: should delete the ir.actions.report.custom for these reports and do an ir_del
67
self.write(cr, uid, ids, {'state':'unsubscribed'})
70
def subscribe(self, cr, uid, ids, context={}):
71
for report in self.browse(cr, uid, ids):
72
report.fields_child0.sort(lambda x,y : x.sequence - y.sequence)
74
# required on field0 does not seem to work( cause we use o2m_l ?)
75
if not report.fields_child0:
76
raise osv.except_osv('Invalid operation :', 'Enter at least one field !')
78
if report.type in ['pie', 'bar', 'line'] and report.field_parent:
79
raise osv.except_osv('Invalid operation :', 'Tree can only be used in tabular reports')
81
# Otherwise it won't build a good tree. See level.pop in custom.py.
82
if report.type == 'table' and report.field_parent and report.fields_child0 and not report.fields_child0[0].groupby:
83
raise osv.except_osv('Invalid operation :', 'When creating tree (field child) report, data must be group by the first field')
85
if report.type == 'pie':
86
if len(report.fields_child0) != 2:
87
raise osv.except_osv('Invalid operation :', 'Pie charts need exactly two fields')
92
tmp = report.fields_child0[i]
94
c_f[i].append((not isinstance(eval('tmp.field_child'+str(j)), browse_null) and eval('tmp.field_child'+str(j)+'.ttype')) or None)
95
if not reduce(lambda x,y : x or y, map(lambda x: x in ['integer', 'float'], c_f[1])):
96
raise osv.except_osv('Invalid operation : ','Second field should be figures')
98
if report.type == 'bar':
99
if len(report.fields_child0) < 2:
100
raise osv.except_osv('Invalid operation : ','Bar charts need at least two fields')
103
for i in range(len(report.fields_child0)):
105
tmp = report.fields_child0[i]
107
c_f[i].append((not isinstance(eval('tmp.field_child'+str(j)), browse_null) and eval('tmp.field_child'+str(j)+'.ttype')) or None)
112
if not reduce(lambda x,y : x or y, map(lambda x: x in ['integer', 'float'], c_f[i])):
113
raise osv.except_osv('Invalid operation : ','Field %d should be a figure' %(i,))
115
if report.state=='subscribed':
119
model = report.model_id.model
121
action_def = {'report_id':report.id, 'type':'ir.actions.report.custom', 'model':model, 'name':name}
122
id = self.pool.get('ir.actions.report.custom').create(cr, uid, action_def)
123
m_id = report.menu_id.id
124
action = "ir.actions.report.custom,%d" % (id,)
125
if not report.menu_id:
126
ir.ir_set(cr, uid, 'action', 'client_print_multi', name, [(model, False)], action, False, True)
128
ir.ir_set(cr, uid, 'action', 'tree_but_open', 'Menuitem', [('ir.ui.menu', int(m_id))], action, False, True)
130
self.write(cr, uid, [report.id], {'state':'subscribed'}, context)
135
class report_custom_fields(osv.osv):
136
_name = 'ir.report.custom.fields'
138
'name': fields.char('Name', size=64, required=True),
139
'report_id': fields.many2one('ir.report.custom', 'Report Ref', select=True),
140
'field_child0': fields.many2one('ir.model.fields', 'field child0', required=True),
141
'fc0_operande': fields.many2one('ir.model.fields', 'Constraint'),
142
'fc0_condition': fields.char('Condition', size=64),
143
'fc0_op': fields.selection((('>','>'),('<','<'),('==','='),('in','in'),('gety,==','(year)=')), 'Relation'),
144
'field_child1': fields.many2one('ir.model.fields', 'field child1'),
145
'fc1_operande': fields.many2one('ir.model.fields', 'Constraint'),
146
'fc1_condition': fields.char('condition', size=64),
147
'fc1_op': fields.selection((('>','>'),('<','<'),('==','='),('in','in'),('gety,==','(year)=')), 'Relation'),
148
'field_child2': fields.many2one('ir.model.fields', 'field child2'),
149
'fc2_operande': fields.many2one('ir.model.fields', 'Constraint'),
150
'fc2_condition': fields.char('condition', size=64),
151
'fc2_op': fields.selection((('>','>'),('<','<'),('==','='),('in','in'),('gety,==','(year)=')), 'Relation'),
152
'field_child3': fields.many2one('ir.model.fields', 'field child3'),
153
'fc3_operande': fields.many2one('ir.model.fields', 'Constraint'),
154
'fc3_condition': fields.char('condition', size=64),
155
'fc3_op': fields.selection((('>','>'),('<','<'),('==','='),('in','in'),('gety,==','(year)=')), 'Relation'),
156
'alignment': fields.selection((('left','left'),('right','right'),('center','center')), 'Alignment', required=True),
157
'sequence': fields.integer('Sequence', required=True),
158
'width': fields.integer('Fixed Width'),
159
'operation': fields.selection((('none', 'None'),('calc_sum','Calculate Sum'),('calc_avg','Calculate Average'),('calc_count','Calculate Count'),('calc_max', 'Get Max'))),
160
'groupby' : fields.boolean('Group by'),
161
'bgcolor': fields.char('Background Color', size=64),
162
'fontcolor': fields.char('Font color', size=64),
163
'cumulate': fields.boolean('Cumulate')
166
'alignment': lambda *a: 'left',
167
'bgcolor': lambda *a: 'white',
168
'fontcolor': lambda *a: 'black',
169
'operation': lambda *a: 'none',
173
def onchange_any_field_child(self, cr, uid, ids, field_id, level):
176
next_level_field_name = 'field_child%d' % (level+1)
177
next_level_operande = 'fc%d_operande' % (level+1)
178
field = self.pool.get('ir.model.fields').browse(cr, uid, [field_id])[0]
179
res = self.pool.get(field.model).fields_get(cr, uid, field.name)
180
if res[field.name].has_key('relation'):
181
cr.execute('select id from ir_model where model=%s', (res[field.name]['relation'],))
182
(id,) = cr.fetchone() or (False,)
186
next_level_field_name: [('model_id', '=', id)],
187
next_level_operande: [('model_id', '=', id)]
190
next_level_field_name: True
194
print "Warning: using a relation field which uses an unknown object"
195
return {'required': {next_level_field_name: True}}
197
return {'domain': {next_level_field_name: []}}
199
def get_field_child_onchange_method(level):
200
return lambda self, cr, uid, ids, field_id: self.onchange_any_field_child(cr, uid, ids, field_id, level)
202
onchange_field_child0 = get_field_child_onchange_method(0)
203
onchange_field_child1 = get_field_child_onchange_method(1)
204
onchange_field_child2 = get_field_child_onchange_method(2)
205
report_custom_fields()