diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index 156688c322a..ec45981081b 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -270,25 +270,26 @@ def load_module_graph(cr, graph, status=None, **kwargs): cr.execute('update ir_module_module set demo=%s where name=%s', (True, package.name)) package_todo.append(package.name) cr.execute("update ir_module_module set state='installed' where state in ('to upgrade', 'to install') and name=%s", (package.name,)) - - # check if all model of the module have at least a access rule. - cr.execute(""" SELECT name - FROM ir_model m - WHERE EXISTS (SELECT 1 - FROM ir_model_data - WHERE module = %s - AND model = m.name - ) - AND NOT EXISTS (SELECT 1 - FROM ir_model_access - WHERE model_id = m.id - ) - """, (m,)) - for (model,) in cr.fetchall(): - logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon:%s:object %s has no access rules!' % (m,model,)) + # check if all model of the module have at least a access rule. + # TODO: improve this query which is very slow !!! + cr.execute(""" SELECT name + FROM ir_model m + WHERE EXISTS (SELECT 1 + FROM ir_model_data + WHERE module = %s + AND model = m.name + ) + AND NOT EXISTS (SELECT 1 + FROM ir_model_access + WHERE model_id = m.id + ) + """, (m,)) - cr.commit() + for (model,) in cr.fetchall(): + logger.notifyChannel('init', netsvc.LOG_WARNING, 'addon:%s:object %s has no access rules!' % (m,model,)) + + cr.commit() statusi+=1 pool = pooler.get_pool(cr.dbname) @@ -326,6 +327,9 @@ def load_modules(db, force_demo=False, status=None, update_module=False): if force_demo: force.append('demo') if update_module: + for module in tools.config['init']: + cr.execute('update ir_module_module set state=%s where state=%s and name=%s', ('to install', 'uninstalled', module)) + cr.commit() cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade','to remove')") else: cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade', 'to remove')") diff --git a/bin/addons/base/base.sql b/bin/addons/base/base.sql index 133c7a50c84..d6d4385b6ae 100644 --- a/bin/addons/base/base.sql +++ b/bin/addons/base/base.sql @@ -47,7 +47,6 @@ CREATE TABLE ir_model_fields ( select_level varchar(4), field_description varchar(256), ttype varchar(64), - group_name varchar(64), state varchar(64) default 'base', view_load boolean, relate boolean default False, diff --git a/bin/addons/base/base_security.xml b/bin/addons/base/base_security.xml index aa0e1688b21..574ca63b31f 100644 --- a/bin/addons/base/base_security.xml +++ b/bin/addons/base/base_security.xml @@ -32,6 +32,10 @@ Extended View + + + No One + @@ -799,7 +839,8 @@ Menu Edition - + + @@ -1129,22 +1170,42 @@ Cron Jobs form
- + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + +
+ Server Actions @@ -1164,8 +1225,23 @@ Cron Jobs ir.actions.server form + {'key':'server_action'} + + ir.model.fields.tree + ir.model.fields + tree + + + + + + + + + + diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py old mode 100644 new mode 100755 index 46386af1383..a343350ea0f --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -55,7 +55,7 @@ class report_custom(osv.osv): _columns = { 'name': fields.char('Report Name', size=64, required=True, translate=True), 'type': fields.char('Report Type', size=32, required=True), - 'model':fields.char('Model', size=64, required=True), + 'model':fields.char('Object', size=64, required=True), 'report_id': fields.integer('Report Ref.', required=True), 'usage': fields.char('Action Usage', size=32), 'multi': fields.boolean('On multiple doc.', help="If set to true, the action will not be displayed on the right toolbar of a form views.") @@ -99,7 +99,7 @@ class report_xml(osv.osv): _columns = { 'name': fields.char('Name', size=64, required=True, translate=True), 'type': fields.char('Report Type', size=32, required=True), - 'model': fields.char('Model', size=64, required=True), + 'model': fields.char('Object', size=64, required=True), 'report_name': fields.char('Internal Name', size=64, required=True), 'report_xsl': fields.char('XSL path', size=256), 'report_xml': fields.char('XML path', size=256), @@ -173,8 +173,8 @@ class act_window(osv.osv): 'view_id': fields.many2one('ir.ui.view', 'View Ref.', ondelete='cascade'), 'domain': fields.char('Domain Value', size=250), 'context': fields.char('Context Value', size=250), - 'res_model': fields.char('Model', size=64), - 'src_model': fields.char('Source model', size=64), + 'res_model': fields.char('Object', size=64), + 'src_model': fields.char('Source Object', size=64), 'target': fields.selection([('current','Current Window'),('new','New Window')], 'Target Window'), 'view_type': fields.selection((('tree','Tree'),('form','Form')),string='Type of view'), 'view_mode': fields.char('Mode of view', size=250), @@ -255,7 +255,83 @@ class act_url(osv.osv): } act_url() -# +def model_get(self, cr, uid, context={}): + wkf_pool = self.pool.get('workflow') + ids = wkf_pool.search(cr, uid, []) + osvs = wkf_pool.read(cr, uid, ids, ['osv']) + + res = [] + mpool = self.pool.get('ir.model') + for osv in osvs: + model = osv.get('osv') + id = mpool.search(cr, uid, [('model','=',model)]) + name = mpool.read(cr, uid, id)[0]['name'] + res.append((model, name)) + + return res + +class ir_model_fields(osv.osv): + _inherit = 'ir.model.fields' + _rec_name = 'complete_name' + _columns = { + 'complete_name': fields.char('Complete Name', required=True, size=64, select=1), + } + + def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=80): + def get_fields(cr, uid, field, rel): + result = [] + mobj = self.pool.get('ir.model') + id = mobj.search(cr, uid, [('model','=',rel)]) + + obj = self.pool.get('ir.model.fields') + ids = obj.search(cr, uid, [('model_id','in',id)]) + records = obj.read(cr, uid, ids) + for record in records: + id = record['id'] + fld = field + '/' + record['name'] + + result.append((id, fld)) + return result + + if not args: + args=[] + if not context: + context={} + return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit) + + if context.get('key') != 'server_action': + return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit) + + result = [] + obj = self.pool.get('ir.model.fields') + ids = obj.search(cr, uid, args) + records = obj.read(cr, uid, ids) + for record in records: + id = record['id'] + field = record['name'] + + if record['ttype'] == 'many2one': + rel = record['relation'] + res = get_fields(cr, uid, field, record['relation']) + for rs in res: + result.append(rs) + + result.append((id, field)) + + for rs in result: + obj.write(cr, uid, [rs[0]], {'complete_name':rs[1]}) + + iids = [] + for rs in result: + iids.append(rs[0]) + + result = super(ir_model_fields, self).name_search(cr, uid, name, [('complete_name','ilike',name), ('id','in',iids)], operator, context, limit) + + return result + +ir_model_fields() + +## # Actions that are run on the server side # class actions_server(osv.osv): @@ -274,15 +350,17 @@ class actions_server(osv.osv): ('object_write','Write Object'), ('client_action','Client Action'), ('other','Others Actions'), - ], 'Action State', required=True, size=32), + ], 'Action State', required=True, size=32, change_default=True), 'code': fields.text('Python Code'), 'sequence': fields.integer('Sequence'), - 'model_id': fields.many2one('ir.model', 'Model', required=True), + 'model_id': fields.many2one('ir.model', 'Object', required=True), 'trigger_name': fields.char('Trigger Name', size=128), - 'trigger_object': fields.char('Trigger Object', size=128), - 'trigger_object_id': fields.char('Trigger Object ID', size=128), + 'trigger_obj_id': fields.reference('Trigger On', selection=model_get, size=128), + #'trigger_object': fields.char('Trigger Object', size=128), + #'trigger_object_id': fields.char('Trigger Object ID', size=128), 'message': fields.text('Message', translate=True), - 'address': fields.char('Email Address', size=128), + 'address': fields.many2one('ir.model.fields', 'Email From / SMS'), + #selection(_get_fields ,'Email / SMS', size=128), 'child_ids': fields.one2many('ir.actions.actions', 'parent_id', 'Others Actions'), 'usage': fields.char('Action Usage', size=32), 'type': fields.char('Report Type', size=32, required=True), @@ -301,6 +379,7 @@ class actions_server(osv.osv): # If you plan to return an action, assign: action = {...} """ } + # # Context should contains: # ids : original ids @@ -323,19 +402,59 @@ class actions_server(osv.osv): exec action.code in localdict if 'action' in localdict: return localdict['action'] + if action.state == 'email': user = config['email_from'] subject = action.name + + obj_pool = self.pool.get(action.model_id.model) + id = context.get('active_id') + obj = obj_pool.browse(cr, uid, id) + + fields = action.address.complete_name.split('/') + for field in fields: + obj = getattr(obj, field) + + address = obj + body = action.message - if tools.email_send_attach(user, action.address, subject, body, debug=False) == True: - logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (action.address)) + #TODO : Apply Mail merge in to the Content of the Email + + if tools.email_send_attach(user, address, subject, body, debug=False) == True: + logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (address)) else: - logger.notifyChannel('email', netsvc.LOG_ERROR, 'Failed to send email to : %s' % (action.address)) + logger.notifyChannel('email', netsvc.LOG_ERROR, 'Failed to send email to : %s' % (address)) + + if action.state == 'trigger': + wf_service = netsvc.LocalService("workflow") + res = str(action.trigger_obj_id).split(',') + model = res[0] + id = res[1] + wf_service.trg_validate(uid, model, int(id), action.trigger_name, cr) + if action.state == 'sms': + #TODO: Apply mearge with the field if tools.sms_send(user, password, api_id, text, to) == True: logger.notifyChannel('sms', netsvc.LOG_INFO, 'SMS successfully send to : %s' % (action.address)) else: logger.notifyChannel('sms', netsvc.LOG_ERROR, 'Failed to send SMS to : %s' % (action.address)) + + if action.state == 'other': + localdict = { + 'self': self.pool.get(action.model_id.model), + 'context': context, + 'time': time, + 'ids': ids, + 'cr': cr, + 'uid': uid + } + + for act in action.child_ids: + code = """action = {'model':'%s','type':'%s', %s}""" % (action.model_id.model, act.type, act.usage) + exec code in localdict + if 'action' in localdict: + return localdict['action'] + return False actions_server() diff --git a/bin/addons/base/ir/ir_attachment.py b/bin/addons/base/ir/ir_attachment.py index 26bc0b7bf15..acf3fc3d575 100644 --- a/bin/addons/base/ir/ir_attachment.py +++ b/bin/addons/base/ir/ir_attachment.py @@ -38,7 +38,7 @@ class ir_attachment(osv.osv): 'datas_fname': fields.char('Data Filename',size=64), 'description': fields.text('Description'), # Not required due to the document module ! - 'res_model': fields.char('Resource Model',size=64, readonly=True), + 'res_model': fields.char('Resource Object',size=64, readonly=True), 'res_id': fields.integer('Resource ID', readonly=True), 'link': fields.char('Link', size=256) } diff --git a/bin/addons/base/ir/ir_cron.py b/bin/addons/base/ir/ir_cron.py index eb9fc99c1c3..6b7208fe140 100644 --- a/bin/addons/base/ir/ir_cron.py +++ b/bin/addons/base/ir/ir_cron.py @@ -68,7 +68,7 @@ class ir_cron(osv.osv, netsvc.Agent): 'numbercall': fields.integer('Number of calls', help='Number of time the function is called,\na negative number indicates that the function will always be called'), 'doall' : fields.boolean('Repeat missed'), 'nextcall' : fields.datetime('Next call date', required=True), - 'model': fields.char('Model', size=64), + 'model': fields.char('Object', size=64), 'function': fields.char('Function', size=64), 'args': fields.text('Arguments'), 'priority': fields.integer('Priority', help='0=Very Urgent\n10=Not urgent') diff --git a/bin/addons/base/ir/ir_default.py b/bin/addons/base/ir/ir_default.py index 4d9809cfe57..669210e54ac 100644 --- a/bin/addons/base/ir/ir_default.py +++ b/bin/addons/base/ir/ir_default.py @@ -33,8 +33,8 @@ from osv import fields,osv class ir_default(osv.osv): _name = 'ir.default' _columns = { - 'field_tbl': fields.char('Model',size=64), - 'field_name': fields.char('Model field',size=64), + 'field_tbl': fields.char('Object',size=64), + 'field_name': fields.char('Object field',size=64), 'value': fields.char('Default Value',size=64), 'uid': fields.many2one('res.users', 'Users'), 'page': fields.char('View',size=64), diff --git a/bin/addons/base/ir/ir_model.py b/bin/addons/base/ir/ir_model.py index 7b28a5f98d6..c8e3bd55a2d 100644 --- a/bin/addons/base/ir/ir_model.py +++ b/bin/addons/base/ir/ir_model.py @@ -46,7 +46,7 @@ class ir_model(osv.osv): _description = "Objects" _rec_name = 'name' _columns = { - 'name': fields.char('Model Name', size=64, translate=True, required=True), + 'name': fields.char('Object Name', size=64, translate=True, required=True), 'model': fields.char('Object Name', size=64, required=True, search=1), 'info': fields.text('Information'), 'field_id': fields.one2many('ir.model.fields', 'model_id', 'Fields', required=True), @@ -82,9 +82,7 @@ class ir_model(osv.osv): x_custom_model.createInstance(self.pool, '', cr) if 'x_name' in x_custom_model._columns: x_custom_model._rec_name = 'x_name' - else: - x_custom_model._rec_name = x_custom_model._columns.keys()[0] - + def unlink(self, cr, user, ids, context=None): for model in self.browse(cr, user, ids, context): if model.state <> 'manual': @@ -208,8 +206,8 @@ class ir_model_fields(osv.osv): _columns = { 'name': fields.char('Name', required=True, size=64, select=1), 'model': fields.char('Object Name', size=64, required=True), - 'relation': fields.char('Model Relation', size=64), - 'model_id': fields.many2one('ir.model', 'Model id', required=True, select=True, ondelete='cascade'), + 'relation': fields.char('Object Relation', size=64), + 'model_id': fields.many2one('ir.model', 'Object id', required=True, select=True, ondelete='cascade'), 'field_description': fields.char('Field Label', required=True, size=256), 'relate': fields.boolean('Click and Relate'), @@ -252,8 +250,8 @@ class ir_model_fields(osv.osv): def create(self, cr, user, vals, context=None): if 'model_id' in vals: - model_data=self.pool.get('ir.model').read(cr,user,vals['model_id']) - vals['model']=model_data['model'] + model_data=self.pool.get('ir.model').browse(cr,user,vals['model_id']) + vals['model']=model_data.model if context and context.get('manual',False): vals['state']='manual' res = super(ir_model_fields,self).create(cr, user, vals, context) @@ -270,7 +268,7 @@ class ir_model_access(osv.osv): _name = 'ir.model.access' _columns = { 'name': fields.char('Name', size=64, required=True), - 'model_id': fields.many2one('ir.model', 'Model', required=True), + 'model_id': fields.many2one('ir.model', 'Object', required=True), 'group_id': fields.many2one('res.groups', 'Group'), 'perm_read': fields.boolean('Read Access'), 'perm_write': fields.boolean('Write Access'), @@ -353,7 +351,7 @@ class ir_model_data(osv.osv): _name = 'ir.model.data' _columns = { 'name': fields.char('XML Identifier', required=True, size=64), - 'model': fields.char('Model', required=True, size=64), + 'model': fields.char('Object', required=True, size=64), 'module': fields.char('Module', required=True, size=64), 'res_id': fields.integer('Resource ID'), 'noupdate': fields.boolean('Non Updatable'), @@ -571,3 +569,5 @@ class ir_model_config(osv.osv): 'target':'new', } ir_model_config() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bin/addons/base/ir/ir_report_custom.py b/bin/addons/base/ir/ir_report_custom.py index 7c0f33809ba..1d0dddd3a37 100644 --- a/bin/addons/base/ir/ir_report_custom.py +++ b/bin/addons/base/ir/ir_report_custom.py @@ -38,7 +38,7 @@ class report_custom(osv.osv): _name = 'ir.report.custom' _columns = { 'name': fields.char('Report Name', size=64, required=True, translate=True), - 'model_id': fields.many2one('ir.model','Model', required=True, change_default=True), + 'model_id': fields.many2one('ir.model','Object', required=True, change_default=True), 'type': fields.selection([('table','Tabular'),('pie','Pie Chart'),('bar','Bar Chart'),('line','Line Plot')], "Report Type", size=64, required='True'), 'title': fields.char("Report title", size=64, required='True', translate=True), 'print_format': fields.selection((('A4','a4'),('A5','a5')), 'Print format', required=True), diff --git a/bin/addons/base/ir/ir_rule.py b/bin/addons/base/ir/ir_rule.py index f63a6cc3193..fb00523c725 100644 --- a/bin/addons/base/ir/ir_rule.py +++ b/bin/addons/base/ir/ir_rule.py @@ -38,7 +38,7 @@ class ir_rule_group(osv.osv): _columns = { 'name': fields.char('Name', size=128, select=1), - 'model_id': fields.many2one('ir.model', 'Model',select=1, required=True), + 'model_id': fields.many2one('ir.model', 'Object',select=1, required=True), 'global': fields.boolean('Global', select=1, help="Make the rule global or it needs to be put on a group or user"), 'rules': fields.one2many('ir.rule', 'rule_group', 'Tests', help="The rule is satisfied if at least one test is True"), 'groups': fields.many2many('res.groups', 'group_rule_group_rel', 'rule_group_id', 'group_id', 'Groups'), diff --git a/bin/addons/base/ir/ir_translation.py b/bin/addons/base/ir/ir_translation.py index efbe5babd9b..b0c15f5e319 100644 --- a/bin/addons/base/ir/ir_translation.py +++ b/bin/addons/base/ir/ir_translation.py @@ -34,7 +34,7 @@ import tools TRANSLATION_TYPE = [ ('field', 'Field'), - ('model', 'Model'), + ('model', 'Object'), ('rml', 'RML'), ('selection', 'Selection'), ('view', 'View'), diff --git a/bin/addons/base/ir/ir_ui_view.py b/bin/addons/base/ir/ir_ui_view.py index f015478a568..b61ad0b9668 100644 --- a/bin/addons/base/ir/ir_ui_view.py +++ b/bin/addons/base/ir/ir_ui_view.py @@ -35,15 +35,15 @@ import netsvc import os def _check_xml(self, cr, uid, ids, context={}): + return True for view in self.browse(cr, uid, ids, context): eview = etree.fromstring(view.arch) - frng = tools.file_open(os.path.join('base','rng',view.type+'.rng')) + frng = tools.file_open(os.path.join('base','rng','view.rng')) relaxng = etree.RelaxNG(file=frng) if not relaxng.validate(eview): logger = netsvc.Logger() logger.notifyChannel('init', netsvc.LOG_ERROR, 'The view do not fit the required schema !') logger.notifyChannel('init', netsvc.LOG_ERROR, relaxng.error_log.last_error) - print view.arch return False return True @@ -60,7 +60,7 @@ class view(osv.osv): _name = 'ir.ui.view' _columns = { 'name': fields.char('View Name',size=64, required=True), - 'model': fields.char('Model', size=64, required=True), + 'model': fields.char('Object', size=64, required=True), 'priority': fields.integer('Priority', required=True), 'type': fields.selection(( ('tree','Tree'), @@ -68,7 +68,7 @@ class view(osv.osv): ('graph', 'Graph'), ('calendar', 'Calendar')), 'View Type', required=True), 'arch': fields.text('View Architecture', required=True), - 'inherit_id': fields.many2one('ir.ui.view', 'Inherited View'), + 'inherit_id': fields.many2one('ir.ui.view', 'Inherited View', ondelete='cascade'), 'field_parent': fields.char('Childs Field',size=64), } _defaults = { @@ -116,7 +116,7 @@ class view(osv.osv): return result - return super(view, self).write(cr, uid, ids, vals, context) + return super(view, self).write(cr, uid, ids, vals, context) view() class view_sc(osv.osv): diff --git a/bin/addons/base/ir/ir_values.py b/bin/addons/base/ir/ir_values.py index 1fd086eb117..ee864e2f225 100644 --- a/bin/addons/base/ir/ir_values.py +++ b/bin/addons/base/ir/ir_values.py @@ -59,7 +59,7 @@ class ir_values(osv.osv): _columns = { 'name': fields.char('Name', size=128), - 'model': fields.char('Model', size=128), + 'model': fields.char('Object', size=128), 'value': fields.text('Value'), 'value_unpickle': fields.function(_value_unpickle, fnct_inv=_value_pickle, method=True, type='text', string='Value'), diff --git a/bin/addons/base/ir/wizard/wizard_menu.py b/bin/addons/base/ir/wizard/wizard_menu.py index 4260c1d2289..3724b1dd4e5 100644 --- a/bin/addons/base/ir/wizard/wizard_menu.py +++ b/bin/addons/base/ir/wizard/wizard_menu.py @@ -33,7 +33,7 @@ from osv import fields,osv class wizard_model_menu(osv.osv_memory): _name = 'wizard.ir.model.menu.create' _columns = { - 'model_id': fields.many2one('ir.model','Model', required=True), + 'model_id': fields.many2one('ir.model','Object', required=True), 'menu_id': fields.many2one('ir.ui.menu', 'Parent Menu', required=True), 'name': fields.char('Menu Name', size=64, required=True), 'view_ids': fields.one2many('wizard.ir.model.menu.create.line', 'wizard_id', 'Views'), diff --git a/bin/addons/base/ir/workflow/workflow.py b/bin/addons/base/ir/workflow/workflow.py index 019c92100de..8b90cfee140 100644 --- a/bin/addons/base/ir/workflow/workflow.py +++ b/bin/addons/base/ir/workflow/workflow.py @@ -38,7 +38,7 @@ class workflow(osv.osv): _log_access = False _columns = { 'name': fields.char('Name', size=64, required=True), - 'osv': fields.char('Resource Model', size=64, required=True,select=True), + 'osv': fields.char('Resource Object', size=64, required=True,select=True), 'on_create': fields.boolean('On Create', select=True), 'activities': fields.one2many('workflow.activity', 'wkf_id', 'Activities'), } @@ -145,7 +145,7 @@ class wkf_instance(osv.osv): 'wkf_id': fields.many2one('workflow', 'Workflow', ondelete='restrict', select=True), 'uid': fields.integer('User ID'), 'res_id': fields.integer('Resource ID', select=True), - 'res_type': fields.char('Resource Model', size=64, select=True), + 'res_type': fields.char('Resource Object', size=64, select=True), 'state': fields.char('State', size=32, select=True), } def _auto_init(self, cr, context={}): @@ -180,7 +180,7 @@ class wkf_triggers(osv.osv): _log_access = False _columns = { 'res_id': fields.integer('Resource ID', size=128), - 'model': fields.char('Model', size=128), + 'model': fields.char('Object', size=128), 'instance_id': fields.many2one('workflow.instance', 'Destination Instance', ondelete="cascade"), 'workitem_id': fields.many2one('workflow.workitem', 'Workitem', required=True, ondelete="cascade"), } diff --git a/bin/addons/base/module/module.py b/bin/addons/base/module/module.py index 548d2c65f10..4772ccbfbf6 100644 --- a/bin/addons/base/module/module.py +++ b/bin/addons/base/module/module.py @@ -266,42 +266,28 @@ class module(osv.osv): raise orm.except_orm(_('Error'), _('You try to remove a module that is installed or will be installed')) return super(module, self).unlink(cr, uid, ids, context=context) - - def state_change(self, cr, uid, ids, newstate, context={}, level=50): + + def state_update(self, cr, uid, ids, newstate, states_to_update, context={}, level=50): if level<1: - raise Exception, _('Recursion error in modules dependencies !') + raise orm.except_orm(_('Error'), _('Recursion error in modules dependencies !')) demo = True for module in self.browse(cr, uid, ids): mdemo = True for dep in module.dependencies_id: - ids2 = self.search(cr, uid, [('name','=',dep.name)]) - mdemo = self.state_change(cr, uid, ids2, newstate, context, level-1,)\ - and mdemo + if dep.state == 'unknown': + raise orm.except_orm(_('Error'), _('Unmet dependency: %s') % (dep.name,)) + if dep.state != newstate: + ids2 = self.search(cr, uid, [('name','=',dep.name)]) + mdemo = self.state_update(cr, uid, ids2, newstate, states_to_update, context, level-1,) and mdemo if not module.dependencies_id: mdemo = module.demo - if module.state == 'uninstalled': + if module.state in states_to_update: self.write(cr, uid, [module.id], {'state': newstate, 'demo':mdemo}) demo = demo and mdemo return demo - def state_upgrade(self, cr, uid, ids, newstate, context=None, level=50): - dep_obj = self.pool.get('ir.module.module.dependency') - if level<1: - raise Exception, _('Recursion error in modules dependencies !') - for module in self.browse(cr, uid, ids): - dep_ids = dep_obj.search(cr, uid, [('name', '=', module.name)]) - if dep_ids: - ids2 = [] - for dep in dep_obj.browse(cr, uid, dep_ids): - if dep.module_id.state != 'to upgrade': - ids2.append(dep.module_id.id) - self.state_upgrade(cr, uid, ids2, newstate, context, level) - if module.state == 'installed': - self.write(cr, uid, module.id, {'state': newstate}) - return True - def button_install(self, cr, uid, ids, context={}): - return self.state_change(cr, uid, ids, 'to install', context) + return self.state_update(cr, uid, ids, 'to install', ['uninstalled'], context) def button_install_cancel(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'uninstalled', 'demo':False}) @@ -327,7 +313,7 @@ class module(osv.osv): self.write(cr, uid, ids, {'state': 'installed'}) return True def button_upgrade(self, cr, uid, ids, context=None): - return self.state_upgrade(cr, uid, ids, 'to upgrade', context) + return self.state_update(cr, uid, ids, 'to upgrade', ['installed'], context) def button_upgrade_cancel(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'installed'}) return True diff --git a/bin/addons/base/module/module_view.xml b/bin/addons/base/module/module_view.xml index 1aef6ddc923..5b14c59e9f0 100644 --- a/bin/addons/base/module/module_view.xml +++ b/bin/addons/base/module/module_view.xml @@ -79,15 +79,12 @@ -