diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index 74ecc9a6f04..ec45981081b 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -327,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_data.xml b/bin/addons/base/base_data.xml index 88464eb97c4..a087ad4d620 100644 --- a/bin/addons/base/base_data.xml +++ b/bin/addons/base/base_data.xml @@ -1369,6 +1369,7 @@ COP 0.01 4 + @@ -1376,6 +1377,7 @@ CZK 0.01 4 + @@ -1396,6 +1398,7 @@ HUF 0.01 4 + @@ -1403,6 +1406,7 @@ IDR 0.01 4 + @@ -1449,6 +1453,7 @@ PLN 0.01 4 + @@ -1456,6 +1461,7 @@ SEK 0.01 4 + @@ -1475,6 +1481,7 @@ ARS 0.01 4 + diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml old mode 100644 new mode 100755 index d68c126bf60..83372789a86 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1039,23 +1039,34 @@ form
- + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -1080,8 +1091,22 @@ ir.actions.server form + {'key':'myval'} - + + + 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 index 159707cdd1d..9ed4565169a 100755 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -255,10 +255,6 @@ class act_url(osv.osv): } act_url() -def _get_fields(self, cr, uid, context={}): - - return [('key','Email Value')] - def model_get(self, cr, uid, context={}): wkf_pool = self.pool.get('workflow') ids = wkf_pool.search(cr, uid, []) @@ -273,8 +269,60 @@ def model_get(self, cr, uid, context={}): 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) +# +# 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]}) +# +# #result = super(ir_model_fields, self).name_search(cr, uid, name, [['complete_name','ilike',name]], operator, context, limit) +# return result +# +#ir_model_fields() +## # Actions that are run on the server side # class actions_server(osv.osv): @@ -302,7 +350,8 @@ class actions_server(osv.osv): #'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.selection(_get_fields ,'Email / SMS', 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), @@ -322,6 +371,11 @@ class actions_server(osv.osv): """ } +# def on_change_model(self, cr, uid, ids, model_id): +# print '**************** : method called' +# res = {'value' : {'address': [('key1','Email Value One')]} } +# return res + # # Context should contains: # ids : original ids @@ -344,9 +398,14 @@ 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 + + #TODO : Apply Mail merge in to the Content of the Email + print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ',context + 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)) @@ -361,10 +420,12 @@ class actions_server(osv.osv): 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), @@ -376,15 +437,10 @@ class actions_server(osv.osv): } for act in action.child_ids: - code = """ - action = { - 'res_model': %s, - 'type': %s, - 'name': %s, - 'usage': %s, - } - """ % (action.model_id.model, act.type, act.name, act.usage) - exec action.code in localdict + 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_model.py b/bin/addons/base/ir/ir_model.py index 499a9a4354b..e811c25ef7d 100644 --- a/bin/addons/base/ir/ir_model.py +++ b/bin/addons/base/ir/ir_model.py @@ -122,6 +122,7 @@ class ir_model_fields(osv.osv): 'groups': fields.many2many('res.groups', 'ir_model_fields_group_rel', 'field_id', 'group_id', 'Groups'), 'group_name': fields.char('Group Name', size=128), 'view_load': fields.boolean('View Auto-Load'), + 'complete_name': fields.char('Complete Name', required=True, size=64, select=1), } _defaults = { 'relate': lambda *a: 0, diff --git a/bin/addons/base/module/wizard/wizard_module_upgrade.py b/bin/addons/base/module/wizard/wizard_module_upgrade.py index c9cf6042108..55432bd44f9 100644 --- a/bin/addons/base/module/wizard/wizard_module_upgrade.py +++ b/bin/addons/base/module/wizard/wizard_module_upgrade.py @@ -89,6 +89,15 @@ class wizard_info_get(wizard.interface): mod_obj = pool.get('ir.module.module') ids = mod_obj.search(cr, uid, [ ('state', 'in', ['to upgrade', 'to remove', 'to install'])]) + unmet_packages=[] + mod_dep_obj = pool.get('ir.module.module.dependency') + for mod in mod_obj.browse(cr,uid,ids): + depends_mod_ids=mod_dep_obj.search(cr,uid,[('module_id','=',mod.id)]) + for dep_mod in mod_dep_obj.browse(cr,uid,depends_mod_ids): + if dep_mod.state in ('unknown','uninstalled'): + unmet_packages.append(dep_mod.name) + if len(unmet_packages): + raise wizard.except_wizard('Unmet dependency !','Following modules are uninstalled or unknown. \n\n'+'\n'.join(unmet_packages)) mod_obj.download(cr, uid, ids, context=context) cr.commit() db, pool = pooler.restart_pool(cr.dbname, update_module=True) diff --git a/bin/addons/base/res/partner/partner.py b/bin/addons/base/res/partner/partner.py index 3cac309de11..0d3ff0bf3d9 100644 --- a/bin/addons/base/res/partner/partner.py +++ b/bin/addons/base/res/partner/partner.py @@ -142,6 +142,7 @@ class res_partner(osv.osv): 'user_id': fields.many2one('res.users', 'Dedicated Salesman', help='The internal user that is in charge of communicating with this partner if any.'), 'responsible': fields.many2one('res.users', 'Users'), 'vat': fields.char('VAT',size=32 ,help="Value Added Tax number"), + 'vat_subject': fields.boolean('Subjected to the VAT'), 'bank_ids': fields.one2many('res.partner.bank', 'partner_id', 'Banks'), 'website': fields.char('Website',size=64), 'comment': fields.text('Notes'), diff --git a/bin/addons/base/rng/view.rng b/bin/addons/base/rng/view.rng index 0f4b87f021e..666ab76194b 100644 --- a/bin/addons/base/rng/view.rng +++ b/bin/addons/base/rng/view.rng @@ -6,6 +6,7 @@ + @@ -16,6 +17,7 @@ + @@ -30,10 +32,13 @@ + + + @@ -186,6 +191,7 @@ + diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 5c312503c4f..198a3a17407 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -593,28 +593,28 @@ class orm_template(object): while len(datas): res = {} - try: - (res, other, warning, translate, data_id) = \ - process_liness(self, datas, [], fields_def) - if warning: - cr.rollback() - return (-1, res, warning, '') - id = self.pool.get('ir.model.data')._update(cr, uid, self._name, - current_module, res, xml_id=data_id, mode=mode, - noupdate=noupdate) - for lang in translate: - context2 = context.copy() - context2['lang'] = lang - self.write(cr, uid, [id], translate[lang], context2) - if config.get('commit_mode', False): - cr.commit() - except Exception, e: - logger.notifyChannel("import", netsvc.LOG_ERROR, e) + #try: + (res, other, warning, translate, data_id) = \ + process_liness(self, datas, [], fields_def) + if warning: cr.rollback() - try: - return (-1, res, e[0], warning) - except: - return (-1, res, e[0], '') + return (-1, res, warning, '') + id = self.pool.get('ir.model.data')._update(cr, uid, self._name, + current_module, res, xml_id=data_id, mode=mode, + noupdate=noupdate) + for lang in translate: + context2 = context.copy() + context2['lang'] = lang + self.write(cr, uid, [id], translate[lang], context2) + if config.get('import_partial', False): + cr.commit() + #except Exception, e: + # logger.notifyChannel("import", netsvc.LOG_ERROR, e) + # cr.rollback() + # try: + # return (-1, res, e[0], warning) + # except: + # return (-1, res, e[0], '') done += 1 # # TODO: Send a request with the result and multi-thread ! diff --git a/bin/osv/osv.py b/bin/osv/osv.py index 8e2944eed76..611ba504955 100644 --- a/bin/osv/osv.py +++ b/bin/osv/osv.py @@ -236,7 +236,10 @@ class osv(orm.orm): parent_name = hasattr(cls, '_inherit') and cls._inherit if parent_name: parent_class = pool.get(parent_name).__class__ - assert parent_class, "parent class %s does not exist !" % parent_name + + print cls + print cls._name + assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module) nattr = {} for s in ('_columns', '_defaults', '_inherits', '_constraints', '_sql_constraints'): new = copy.copy(getattr(pool.get(parent_name), s)) diff --git a/bin/tools/config.py b/bin/tools/config.py index 49993b2a534..2083e6fff70 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -58,7 +58,7 @@ class configmanager(object): 'addons_path': None, 'root_path': None, 'debug_mode': False, - 'commit_mode': False, + 'import_partial': "", 'pidfile': None, 'logfile': None, 'secure': False, @@ -114,7 +114,7 @@ class configmanager(object): group.add_option("--db_host", dest="db_host", help="specify the database host") group.add_option("--db_port", dest="db_port", help="specify the database port") group.add_option("--db_maxconn", dest="db_maxconn", default='64', help="specify the the maximum number of physical connections to posgresql") - group.add_option("-C", "--commit-mode", dest="commit_mode", action="store_true", help="Several commit during one file importation. Use this for big data importation.", default=False) + group.add_option("-C", "--commit-mode", dest="import_partial", help="Several commit during one file importation. Use this for big data importation. Provide a filename to store intermediate state.", default=False) parser.add_option_group(group) group = optparse.OptionGroup(parser, "Internationalisation options", @@ -156,7 +156,7 @@ class configmanager(object): self.options['pidfile'] = False for arg in ('interface', 'port', 'db_name', 'db_user', 'db_password', 'db_host', - 'db_port', 'logfile', 'pidfile', 'secure', 'smtp_ssl', 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy', 'netinterface', 'netport', 'db_maxconn', 'commit_mode', 'addons_path'): + 'db_port', 'logfile', 'pidfile', 'secure', 'smtp_ssl', 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy', 'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path'): if getattr(opt, arg): self.options[arg] = getattr(opt, arg) diff --git a/bin/tools/convert.py b/bin/tools/convert.py index bca44cb349f..626052c060d 100644 --- a/bin/tools/convert.py +++ b/bin/tools/convert.py @@ -657,7 +657,7 @@ form: module.record_id""" % (xml_id,) id = self.pool.get('ir.model.data')._update(cr, self.uid, rec_model, self.module, res, rec_id or False, not self.isnoupdate(data_node), noupdate=self.isnoupdate(data_node), mode=self.mode ) if rec_id: self.idref[rec_id] = int(id) - if config.get('commit_mode', False): + if config.get('import_partial', False): cr.commit() return rec_model, id @@ -724,6 +724,15 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init', pool = pooler.get_pool(cr.dbname) + import pickle + if config.get('import_partial'): + if not os.path.isfile(config.get('import_partial')): + pickle.dump({}, file(config.get('import_partial'),'w+')) + data = pickle.load(file(config.get('import_partial'))) + if fname in data: + if not data[fname]: + return + input = StringIO.StringIO(csvcontent) reader = csv.reader(input, quotechar='"', delimiter=',') fields = reader.next() @@ -738,6 +747,10 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init', continue datas.append( map(lambda x:x.decode('utf8').encode('utf8'), line)) pool.get(model).import_data(cr, uid, fields, datas,mode, module,noupdate) + if config.get('import_partial'): + data = pickle.load(file(config.get('import_partial'))) + data[fname] = 0 + pickle.dump(data, file(config.get('import_partial'),'wb')) # # xml import/export