diff --git a/addons/account/invoice.py b/addons/account/invoice.py index 37a73adfea4..6ec083ac7cb 100644 --- a/addons/account/invoice.py +++ b/addons/account/invoice.py @@ -921,7 +921,7 @@ class account_invoice_line(osv.osv): if 'check_total' in context: t = context['check_total'] for l in context.get('invoice_line', {}): - if len(l) >= 3 and l[2]: + if isinstance(l, (list, tuple)) and len(l) >= 3 and l[2]: tax_obj = self.pool.get('account.tax') p = l[2].get('price_unit', 0) * (1-l[2].get('discount', 0)/100.0) t = t - (p * l[2].get('quantity')) diff --git a/addons/account/report/invoice.rml b/addons/account/report/invoice.rml index 10d50610720..cb6d549a7bd 100644 --- a/addons/account/report/invoice.rml +++ b/addons/account/report/invoice.rml @@ -404,13 +404,13 @@ - + Fiscal Position Remark : - [[ o.fiscal_position and format(o.fiscal_position.note) or removeParentNode('blockTable') ]] + [[ format(o.fiscal_position and o.fiscal_position.note or removeParentNode('blockTable')) ]] diff --git a/addons/account/report/tax_report.py b/addons/account/report/tax_report.py index 79e59959d12..1f0332d2906 100644 --- a/addons/account/report/tax_report.py +++ b/addons/account/report/tax_report.py @@ -43,20 +43,6 @@ class tax_report(rml_parse.rml_parse): }) - def comma_me(self,amount): - - if type(amount) is float : - amount = str('%.2f'%amount) - else : - amount = str(amount) - if (amount == '0'): - return ' ' - orig = amount - new = re.sub("^(-?\d+)(\d{3})", "\g<1>'\g<2>", amount) - if orig == new: - return new - else: - return self.comma_me(new) def _get_lines(self, based_on,period_list,company_id=False, parent=False, level=0): res = self._get_codes(based_on,company_id,parent,level,period_list) @@ -73,7 +59,6 @@ class tax_report(rml_parse.rml_parse): i = 0 top_result = [] - while i < len(res): res_dict = { 'code' : res[i][1].code, @@ -106,7 +91,6 @@ class tax_report(rml_parse.rml_parse): def _get_general(self, tax_code_id,period_list ,company_id, based_on): res=[] period_sql_list = ','.join(map(str, period_list[0][2])) - if based_on == 'payments': self.cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ SUM(line.debit) AS debit, \ @@ -125,6 +109,7 @@ class tax_report(rml_parse.rml_parse): AND line.account_id = account.id \ AND account.company_id = %s \ AND move.id = line.move_id \ + AND line.period_id IN ('+ period_sql_list +') \ AND ((invoice.state = %s) \ OR (invoice.id IS NULL)) \ GROUP BY account.id,account.name,account.code', ('draft',tax_code_id, @@ -144,6 +129,7 @@ class tax_report(rml_parse.rml_parse): AND line.tax_code_id = %s \ AND line.account_id = account.id \ AND account.company_id = %s \ + AND line.period_id IN ('+ period_sql_list +') \ AND account.active \ GROUP BY account.id,account.name,account.code', ('draft',tax_code_id, company_id)) diff --git a/addons/account/wizard/wizard_account_chart.py b/addons/account/wizard/wizard_account_chart.py index f60dfdcf0a2..124a8146c34 100644 --- a/addons/account/wizard/wizard_account_chart.py +++ b/addons/account/wizard/wizard_account_chart.py @@ -41,7 +41,7 @@ class wizard_account_chart(wizard.interface): 'target_move': { 'string': 'Target Moves', 'type': 'selection', - 'selection': [('all','All Entries'),('posted_only','All Posted Entries')], + 'selection': [('all','All Entries'),('posted','All Posted Entries')], 'required': True, 'default': lambda *a:"all", }, @@ -60,7 +60,7 @@ class wizard_account_chart(wizard.interface): result = mod_obj._get_id(cr, uid, 'account', 'action_account_tree') id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id'] result = act_obj.read(cr, uid, [id], context=context)[0] - result['context'] = str({'fiscalyear': data['form']['fiscalyear'],'target_move':data['form']['target_move']}) + result['context'] = str({'fiscalyear': data['form']['fiscalyear'],'state':data['form']['target_move']}) if data['form']['fiscalyear']: result['name']+=':'+pooler.get_pool(cr.dbname).get('account.fiscalyear').read(cr,uid,[data['form']['fiscalyear']])[0]['code'] return result diff --git a/addons/account_tax_include/invoice_tax_incl.xml b/addons/account_tax_include/invoice_tax_incl.xml index 470a1ca0697..2da7895562f 100644 --- a/addons/account_tax_include/invoice_tax_incl.xml +++ b/addons/account_tax_include/invoice_tax_incl.xml @@ -21,7 +21,7 @@ account.invoice - + diff --git a/addons/base_module_quality/README.txt b/addons/base_module_quality/README.txt new file mode 100644 index 00000000000..3819448c9c1 --- /dev/null +++ b/addons/base_module_quality/README.txt @@ -0,0 +1,11 @@ +This module provide a generic framework to define your own quality test. + + +All you have to do is to: +* create a folder with your test in 'base_module_quality' (e.g: mkdir base_module_quality\mytest) +* create a .py file in it with same name as the folder you just created (e.g: touch base_module_quality\mytest\mytest.py) +* edit your file and define a class 'quality_check' that + * inherits the class 'abstract_quality_test' (defined in base_module_quality.py) + * implements the __init__() method accordingly to what you want to test. + + diff --git a/addons/base_module_quality/__init__.py b/addons/base_module_quality/__init__.py new file mode 100644 index 00000000000..1f0d6b5dbe7 --- /dev/null +++ b/addons/base_module_quality/__init__.py @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + +import base_module_quality +import wizard + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/base_module_quality/__terp__.py b/addons/base_module_quality/__terp__.py new file mode 100644 index 00000000000..9c16e9be300 --- /dev/null +++ b/addons/base_module_quality/__terp__.py @@ -0,0 +1,51 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'Base module quality', + 'version': '1.0', + 'category': 'Tiny Specific Modules/Base module quality', + 'description': """ +This module's aim is to check the quality of other modules. + +It defines a wizard on the list of modules in OpenERP, which allow you to +evaluate them on different criteria such as: the respect of OpenERP coding +standards, the speed efficiency... + +This module also provides generic framework to define your own quality test. +For further info, coders may take a look into base_module_quality\README.txt + +WARNING: This module can not work as a ZIP file, you must unzip it before +using it, otherwise it may crash. + """, + 'author': 'Tiny', + 'website': 'http://www.openerp.com', + 'depends': ['base'], + 'init_xml': [], + 'update_xml': ['base_module_quality_wizard.xml', 'base_module_quality_view.xml', 'security/ir.model.access.csv'], + 'demo_xml': [], + 'installable': True, + 'active': False, + 'certificate': '0175119475677', +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_module_quality/base_module_quality.py b/addons/base_module_quality/base_module_quality.py new file mode 100644 index 00000000000..ec1a50adb4a --- /dev/null +++ b/addons/base_module_quality/base_module_quality.py @@ -0,0 +1,250 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## +import os + +import pooler +import osv +import tools +from tools import config +from tools.translate import _ +from osv import osv, fields + +class abstract_quality_check(object): + ''' + This Class provides... + ''' + + def __init__(self): + ''' + this method should initialize the var + ''' + #This float have to store the rating of the module. + #Used to compute the final score (average of all scores). + #0 <= self.score <= 1 + self.score = 0.0 + + #This char have to store the name of the test. + self.name = "" + + #This char have to store the aim of the test and eventually a note. + self.note = "" + + #This char have to store the result. + #Used to display the result of the test. + self.result = "" + + #This char have to store the result with more details. + #Used to provide more details if necessary. + self.result_details = "" + + # This boolean variable defines that if you do not want to calculate score and just only need detail + # or summary report for some test then you will make it False. + self.bool_count_score = True + + #This bool defines if the test can be run only if the module + #is installed. + #True => the module have to be installed. + #False => the module can be uninstalled. + self.bool_installed_only = True + + #This variable is used to give result of test more weight, + #because some tests are more critical than others. + self.ponderation = 1.0 + + #Specify test got an error on module + self.error = False + + #The tests have to subscribe itselfs in this list, that contains + #all the test that have to be performed. + self.tests = [] + self.list_folders = os.listdir(config['addons_path'] + + '/base_module_quality/') + for item in self.list_folders: + self.item = item + path = config['addons_path']+'/base_module_quality/'+item + if os.path.exists(path + '/' + item + '.py') and item not in ['report', 'wizard', 'security']: + item2 = 'base_module_quality.' + item +'.' + item + x_module = __import__(item2) + x_file = getattr(x_module, item) + x_obj = getattr(x_file, item) + self.tests.append(x_obj) +# raise 'Not Implemented' + + def run_test(self, cr, uid, module_path=""): + ''' + this method should do the test and fill the score, result and result_details var + ''' + raise osv.except_osv(_('Programming Error'), _('Test Is Not Implemented')) + + def get_objects(self, cr, uid, module): + # This function returns all object of the given module.. + pool = pooler.get_pool(cr.dbname) + ids2 = pool.get('ir.model.data').search(cr, uid, + [('module', '=', module), ('model', '=', 'ir.model')]) + model_list = [] + model_data = pool.get('ir.model.data').browse(cr, uid, ids2) + for model in model_data: + model_list.append(model.res_id) + obj_list = [] + for mod in pool.get('ir.model').browse(cr, uid, model_list): + obj_list.append(str(mod.model)) + return obj_list + + def get_model_ids(self, cr, uid, models=[]): + # This function returns all ids of the given objects.. + if not models: + return [] + pool = pooler.get_pool(cr.dbname) + return pool.get('ir.model').search(cr, uid, [('model', 'in', models)]) + + def get_ids(self, cr, uid, object_list): + #This method return dictionary with ids of records of object for module + pool = pooler.get_pool(cr.dbname) + result_ids = {} + for obj in object_list: + ids = pool.get(obj).search(cr, uid, []) + ids = filter(lambda id: id != None, ids) + result_ids[obj] = ids + return result_ids + + def format_table(self, header=[], data_list={}): #This function can work forwidget="text_wiki" + detail = "" + detail += (header[0]) % tuple(header[1]) + frow = '\n|-' + for i in header[1]: + frow += '\n| %s' + for key, value in data_list.items(): + detail += (frow) % tuple(value) + detail = detail + '\n|}' + return detail + + def format_html_table(self, header=[], data_list=[]): #This function can work for widget="html_tag" + # function create html table.... + detail = "" + detail += (header[0]) % tuple(header[1]) + frow = '' + for i in header[1]: + frow += '%s' + frow += '' + for key, value in data_list.items(): + detail += (frow) % tuple(value) + return detail + + def add_quatation(self, x_no, y_no): + return x_no/y_no + +class module_quality_check(osv.osv): + _name = 'module.quality.check' + _columns = { + 'name': fields.char('Rated Module', size=64, ), + 'final_score': fields.char('Final Score (%)', size=10,), + 'check_detail_ids': fields.one2many('module.quality.detail', 'quality_check_id', 'Tests',) + } + + def check_quality(self, cr, uid, module_name, module_state=None): + ''' + This function will calculate score of openerp module + It will return data in below format: + Format: {'final_score':'80.50', 'name': 'sale', + 'check_detail_ids': + [(0,0,{'name':'workflow_test', 'score':'100', 'ponderation':'0', 'summary': text_wiki format data, 'detail': html format data, 'state':'done', 'note':'XXXX'}), + ((0,0,{'name':'terp_test', 'score':'60', 'ponderation':'1', 'summary': text_wiki format data, 'detail': html format data, 'state':'done', 'note':'terp desctioption'}), + ..........]} + So here the detail result is in html format and summary will be in text_wiki format. + ''' + #list_folders = os.listdir(config['addons_path']+'/base_module_quality/') + pool = pooler.get_pool(cr.dbname) + obj_module = pool.get('ir.module.module') + if not module_state: + module_id = obj_module.search(cr, uid, [('name', '=', module_name)]) + if module_id: + module_state = obj_module.browse(cr, uid, module_id[0]).state + + abstract_obj = abstract_quality_check() + score_sum = 0.0 + ponderation_sum = 0.0 + create_ids = [] + for test in abstract_obj.tests: + ad = tools.config['addons_path'] + if module_name == 'base': + ad = tools.config['root_path']+'/addons' + module_path = os.path.join(ad, module_name) + val = test.quality_test() + if not val.bool_installed_only or module_state == "installed": + val.run_test(cr, uid, str(module_path)) + if not val.error: + data = { + 'name': val.name, + 'score': val.score * 100, + 'ponderation': val.ponderation, + 'summary': val.result, + 'detail': val.result_details, + 'state': 'done', + 'note': val.note, + } + if val.bool_count_score: + score_sum += val.score * val.ponderation + ponderation_sum += val.ponderation + else: + data = { + 'name': val.name, + 'score': 0, + 'summary': val.result, + 'state': 'skipped', + 'note': val.note, + } + else: + data = { + 'name': val.name, + 'note': val.note, + 'score': 0, + 'state': 'skipped', + 'summary': _("The module has to be installed before running this test.") + } + create_ids.append((0, 0, data)) + + final_score = '%.2f' % (score_sum / ponderation_sum * 100) + data = { + 'name': module_name, + 'final_score': final_score, + 'check_detail_ids' : create_ids, + } + return data + +module_quality_check() + +class module_quality_detail(osv.osv): + _name = 'module.quality.detail' + _columns = { + 'quality_check_id': fields.many2one('module.quality.check', 'Quality'), + 'name': fields.char('Name',size=128,), + 'score': fields.float('Score (%)'), + 'ponderation': fields.float('Ponderation', help='Some tests are more critical than others, so they have a bigger weight in the computation of final rating'), + 'note': fields.text('Note',), + 'summary': fields.text('Summary'), + 'detail': fields.text('Details'), + '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.'), + } + +module_quality_detail() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/base_module_quality/base_module_quality_view.xml b/addons/base_module_quality/base_module_quality_view.xml new file mode 100644 index 00000000000..18ad04415bd --- /dev/null +++ b/addons/base_module_quality/base_module_quality_view.xml @@ -0,0 +1,70 @@ + + + + + Results of Quality Checks + module.quality.check + tree + + + + + + + + + + Results of Quality Checks + module.quality.check + form + +
+ + + + + + + +
+ + Results of Quality Checks with detail + module.quality.detail + form + +
+ + + + + + + + + + + +