[FIX] base_module_quality: get_ids method problem
[odoo/odoo.git] / addons / base_module_quality / base_module_quality.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6 #    $Id$
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU General Public License as published by
10 #    the Free Software Foundation, either version 3 of the License, or
11 #    (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU General Public License for more details.
17 #
18 #    You should have received a copy of the GNU General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22 import os
23
24 import pooler
25 import osv
26 import tools
27 from tools import config
28 from tools.translate import _
29 from osv import osv, fields
30
31 class abstract_quality_check(object):
32     '''
33         This Class is abstract class for all test
34     '''
35
36     def __init__(self):
37         '''
38         this method should initialize the variables
39         '''
40         #This float have to store the rating of the module.
41         #Used to compute the final score (average of all scores).
42         #0 <= self.score <= 1
43         self.score = 0.0
44
45         #This char have to store the name of the test.
46         self.name = ""
47
48         #This char have to store the aim of the test and eventually a note.
49         self.note = ""
50
51         #This char have to store the result.
52         #Used to display the result of the test.
53         self.result = ""
54
55         #This char have to store the result with more details.
56         #Used to provide more details if necessary.
57         self.result_details = ""
58
59         # This boolean variable defines that if you do not want to calculate score and just only need detail
60         # or summary report for some test then you will make it False.
61         self.bool_count_score = True
62
63         #This bool defines if the test can be run only if the module
64         #is installed.
65         #True => the module have to be installed.
66         #False => the module can be uninstalled.
67         self.bool_installed_only = True
68
69         #This variable is used to give result of test more weight,
70         #because some tests are more critical than others.
71         self.ponderation = 1.0
72
73         #Specify test got an error on module
74         self.error = False
75
76         #Specify the minimal score for the test (in percentage(%))
77         self.min_score = 50
78
79         #Specify whether test should be consider for Quality checking of the module
80         self.active = True
81
82         #This variable used to give message if test result is good or not
83         self.message = ''
84
85         #The tests have to subscribe itselfs in this list, that contains
86         #all the test that have to be performed.
87         self.tests = []
88         self.list_folders = os.listdir(config['addons_path'] +
89             '/base_module_quality/')
90         for item in self.list_folders:
91             self.item = item
92             path = config['addons_path']+'/base_module_quality/'+item
93             if os.path.exists(path + '/' + item + '.py') and item not in ['report', 'wizard', 'security']:
94                 item2 = 'base_module_quality.' + item +'.' + item
95                 x_module = __import__(item2)
96                 x_file = getattr(x_module, item)
97                 x_obj = getattr(x_file, item)
98                 self.tests.append(x_obj)
99 #        raise 'Not Implemented'
100
101     def run_test(self, cr, uid, module_path=""):
102         '''
103         this method should do the test and fill the score, result and result_details var
104         '''
105         raise osv.except_osv(_('Programming Error'), _('Test Is Not Implemented'))
106
107     def get_objects(self, cr, uid, module):
108         # This function returns all object of the given module..
109         pool = pooler.get_pool(cr.dbname)
110         ids2 = pool.get('ir.model.data').search(cr, uid,
111             [('module', '=', module), ('model', '=', 'ir.model')])
112         model_list = []
113         model_data = pool.get('ir.model.data').browse(cr, uid, ids2)
114         for model in model_data:
115             model_list.append(model.res_id)
116         obj_list = []
117         for mod in pool.get('ir.model').browse(cr, uid, model_list):
118             obj_list.append(str(mod.model))
119         return obj_list
120
121     def get_model_ids(self, cr, uid, models=[]):
122         # This function returns all ids of the given objects..
123         if not models:
124             return []
125         pool = pooler.get_pool(cr.dbname)
126         return pool.get('ir.model').search(cr, uid, [('model', 'in', models)])
127
128     def get_ids(self, cr, uid, object_list):
129         #This method return dictionary with ids of records of object for module
130         pool = pooler.get_pool(cr.dbname)
131         result_ids = {}
132         for obj in object_list:
133             ids = pool.get(obj).search(cr, uid, [])
134             ids = filter(lambda id: id != None, ids or [])
135             result_ids[obj] = ids
136         return result_ids
137
138     def format_table(self, header=[], data_list={}): #This function can work forwidget="text_wiki"
139         detail = ""
140         detail += (header[0]) % tuple(header[1])
141         frow = '\n|-'
142         for i in header[1]:
143             frow += '\n| %s'
144         for key, value in data_list.items():
145             detail += (frow) % tuple(value)
146         detail = detail + '\n|}'
147         return detail
148
149     def format_html_table(self, header=[], data_list=[]): #This function can work for widget="html_tag"
150         # function create html table....
151         detail = ""
152         detail += (header[0]) % tuple(header[1])
153         frow = '<tr>'
154         for i in header[1]:
155             frow += '<td>%s</td>'
156         frow += '</tr>'
157         for key, value in data_list.items():
158             detail += (frow) % tuple(value)
159         return detail
160
161     def add_quatation(self, x_no, y_no):
162         return x_no/y_no
163
164     def get_style(self):
165         # This function return style tag with specified styles for html pages
166         style = '''
167             <style>
168                 .divstyle {
169                 border:1px solid #aaaaaa;
170                 background-color:#f9f9f9;
171                 padding:5px;
172                 }
173                 .tablestyle
174                 {
175                 border:1px dashed gray;
176                 }
177                 .tdatastyle
178                 {
179                 border:0.5px solid gray;
180                 }
181                 .head
182                 {
183                 color: black;
184                 background: none;
185                 font-weight: normal;
186                 margin: 0;
187                 padding-top: .5em;
188                 padding-bottom: .17em;
189                 border-bottom: 1px solid #aaa;
190                 }
191                 }
192           </style> '''
193         return style
194
195
196 class module_quality_check(osv.osv):
197     _name = 'module.quality.check'
198     _columns = {
199         'name': fields.char('Rated Module', size=64, ),
200         'final_score': fields.char('Final Score (%)', size=10,),
201         'check_detail_ids': fields.one2many('module.quality.detail', 'quality_check_id', 'Tests',)
202     }
203
204     def check_quality(self, cr, uid, module_name, module_state=None):
205         '''
206         This function will calculate score of openerp module
207         It will return data in below format:
208             Format: {'final_score':'80.50', 'name': 'sale',
209                     'check_detail_ids':
210                         [(0,0,{'name':'workflow_test', 'score':'100', 'ponderation':'0', 'summary': text_wiki format data, 'detail': html format data, 'state':'done', 'note':'XXXX'}),
211                         ((0,0,{'name':'terp_test', 'score':'60', 'ponderation':'1', 'summary': text_wiki format data, 'detail': html format data, 'state':'done', 'note':'terp desctioption'}),
212                          ..........]}
213         So here the detail result is in html format and summary will be in text_wiki format.
214         '''
215         #list_folders = os.listdir(config['addons_path']+'/base_module_quality/')
216         pool = pooler.get_pool(cr.dbname)
217         obj_module = pool.get('ir.module.module')
218         if not module_state:
219             module_id = obj_module.search(cr, uid, [('name', '=', module_name)])
220             if module_id:
221                 module_state = obj_module.browse(cr, uid, module_id[0]).state
222
223         abstract_obj = abstract_quality_check()
224         score_sum = 0.0
225         ponderation_sum = 0.0
226         create_ids = []
227         for test in abstract_obj.tests:
228             ad = tools.config['addons_path']
229             if module_name == 'base':
230                 ad = tools.config['root_path']+'/addons'
231             module_path = os.path.join(ad, module_name)
232             val = test.quality_test()
233             if val.active:
234                 if not val.bool_installed_only or module_state == "installed":
235                     val.run_test(cr, uid, str(module_path))
236                     if not val.error:
237                         data = {
238                             'name': val.name,
239                             'score': val.score * 100,
240                             'ponderation': val.ponderation,
241                             'summary': val.result,
242                             'detail': val.result_details,
243                             'state': 'done',
244                             'note': val.note,
245                             'message': val.message
246                         }
247                         if val.bool_count_score:
248                             score_sum += val.score * val.ponderation
249                             ponderation_sum += val.ponderation
250                     else:
251                         data = {
252                             'name': val.name,
253                             'score': 0,
254                             'summary': val.result,
255                             'state': 'skipped',
256                             'note': val.note,
257                         }
258                 else:
259                     data = {
260                         'name': val.name,
261                         'note': val.note,
262                         'score': 0,
263                         'state': 'skipped',
264                         'summary': _("The module has to be installed before running this test.")
265                     }
266                 create_ids.append((0, 0, data))
267         final_score = ponderation_sum and '%.2f' % (score_sum / ponderation_sum * 100) or 0
268         data = {
269             'name': module_name,
270             'final_score': final_score,
271             'check_detail_ids' : create_ids,
272         }
273         return data
274
275 module_quality_check()
276
277 class module_quality_detail(osv.osv):
278     _name = 'module.quality.detail'
279     _columns = {
280         'quality_check_id': fields.many2one('module.quality.check', 'Quality'),
281         'name': fields.char('Name',size=128),
282         'score': fields.float('Score (%)'),
283         'ponderation': fields.float('Ponderation', help='Some tests are more critical than others, so they have a bigger weight in the computation of final rating'),
284         'note': fields.text('Note'),
285         'summary': fields.text('Summary'),
286         'detail': fields.text('Details'),
287         'message': fields.char('Message', size=64),
288         'state': fields.selection([('done','Done'),('skipped','Skipped'),], 'State', size=6, help='The test will be completed only if the module is installed or if the test may be processed on uninstalled module.'),
289     }
290
291 module_quality_detail()
292
293 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: