From f9ad472466645f8ab9dc4dbc66a049042d97b8f9 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Wed, 11 Jul 2012 12:40:54 +0530 Subject: [PATCH 001/275] [ADD] add new http service translation. bzr revid: tpa@tinyerp.com-20120711071054-rfreaxwys8b1fqbc --- openerp/service/web_services.py | 50 +++++++++++++++++++++++++++++++++ openerp/tools/translate.py | 17 +++++++++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 330bb86dcfc..6762426d8cd 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -777,6 +777,55 @@ class report_spool(netsvc.ExportService): else: raise Exception, 'ReportNotFound' +class translation(netsvc.ExportService): + + def __init__(self, name="translation"): + netsvc.ExportService.__init__(self, name) + + def exp_load(self, db, modules, langs, flag=None, context=None): + translated_data = [] + cr = pooler.get_db(db).cursor() + for module_name in modules: + modpath = openerp.modules.get_module_path(module_name) + if not modpath: + # unable to find the module. we skip + continue + for lang in langs: + iso_lang = tools.get_iso_codes(lang) + f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') + context2 = context and context.copy() or {} + if f and '_' in iso_lang: + iso_lang2 = iso_lang.split('_')[0] + f2 = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang2 + '.po') + if f2: + _logger.info('module %s: loading base translation file %s for language %s', module_name, iso_lang2, lang) + translated_data.append(tools.trans_load(cr, f2, lang, verbose=False, flag=flag, context=context)) + context2['overwrite'] = True + # Implementation notice: we must first search for the full name of + # the language derivative, like "en_UK", and then the generic, + # like "en". + if (not f) and '_' in iso_lang: + iso_lang = iso_lang.split('_')[0] + f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') + if f: + _logger.info('module %s: loading translation file (%s) for language %s', module_name, iso_lang, lang) + translated_data.append(tools.trans_load(cr, f, lang, verbose=False, flag=flag, context=context2)) + elif iso_lang != 'en': + _logger.warning('module %s: no translation for language %s', module_name, iso_lang) + cr.commit() + cr.close() + return translated_data + + def dispatch(self, method, params): + if method in ['load']: + # No security check for these methods + pass + else: + raise KeyError("Method not found: %s" % method) + fn = getattr(self, 'exp_'+method) + return fn(*params) + +translation() def start_web_services(): db() @@ -784,6 +833,7 @@ def start_web_services(): objects_proxy() wizard() report_spool() + translation() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index eb5dbe24077..0d3802bd5c0 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -43,6 +43,7 @@ import misc from misc import UpdateableStr from misc import SKIPPED_ELEMENT_TYPES import osutil +import babel.messages.pofile _logger = logging.getLogger(__name__) @@ -842,12 +843,22 @@ def trans_generate(lang, modules, cr): return out -def trans_load(cr, filename, lang, verbose=True, context=None): +def trans_load(cr, filename, lang, verbose=True, flag=None, context=None): try: fileobj = misc.file_open(filename) + pool = pooler.get_pool(cr.dbname) + traslation_obj = pool.get('ir.translation') _logger.info("loading %s", filename) - fileformat = os.path.splitext(filename)[-1][1:].lower() - r = trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, context=context) + if flag == 'web': + transl = {"messages":[]} + po = babel.messages.pofile.read_po(fileobj) + for x in po: + if x.id and x.string and "openerp-web" in x.auto_comments: + transl["messages"].append({'id': x.id, 'string': x.string}) + return transl + else: + fileformat = os.path.splitext(filename)[-1][1:].lower() + r = trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, context=context) fileobj.close() return r except IOError: From 67aa9fa31a7c64bf59a1b942ecbe6dc83c878241 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Wed, 11 Jul 2012 12:44:05 +0530 Subject: [PATCH 002/275] [IMP] load translation using 'translation' http service bzr revid: tpa@tinyerp.com-20120711071405-g0biuqlctedlbcs9 --- addons/web/controllers/main.py | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 412ea9abda2..5d7aa93f3a5 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -353,25 +353,15 @@ class WebClient(openerpweb.Controller): langs = lang.split(separator) langs = [separator.join(langs[:x]) for x in range(1, len(langs) + 1)] - transs = {} - for addon_name in mods: - transl = {"messages":[]} - transs[addon_name] = transl - addons_path = openerpweb.addons_manifest[addon_name]['addons_path'] - for l in langs: - f_name = os.path.join(addons_path, addon_name, "i18n", l + ".po") - if not os.path.exists(f_name): - continue - try: - with open(f_name) as t_file: - po = babel.messages.pofile.read_po(t_file) - except Exception: - continue - for x in po: - if x.id and x.string and "openerp-web" in x.auto_comments: - transl["messages"].append({'id': x.id, 'string': x.string}) - return {"modules": transs, - "lang_parameters": lang_obj} + messages = {} + for mod in mods: + messages[mod] = {"messages":[]} + proxy = req.session.proxy("translation") + trans = proxy.load(req.session._db, [mod], langs, "web") + if trans: + messages[mod] = trans + return {"modules": {'messages': messages}, + "lang_parameters": lang_obj} @openerpweb.jsonrequest def version_info(self, req): From 4ea3ad65b24ad8b89d1c06d36bffc40e3ea9a865 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 10:51:11 +0530 Subject: [PATCH 003/275] [ADD] added module field in ir.translation and improved code for that. bzr revid: tpa@tinyerp.com-20120712052111-5qq9noxd5vd9dlwv --- openerp/addons/base/ir/ir_translation.py | 20 ++++++++++---------- openerp/addons/base/module/module.py | 4 ++-- openerp/service/web_services.py | 4 ++-- openerp/tools/translate.py | 12 ++++++------ 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py index 61e40e807d4..2f8f87a0a2a 100644 --- a/openerp/addons/base/ir/ir_translation.py +++ b/openerp/addons/base/ir/ir_translation.py @@ -70,7 +70,6 @@ class ir_translation_import_cursor(object): cr.execute('''CREATE TEMP TABLE %s( imd_model VARCHAR(64), - imd_module VARCHAR(64), imd_name VARCHAR(128) ) INHERITS (%s) ''' % (self._table_name, self._parent_table)) @@ -80,10 +79,10 @@ class ir_translation_import_cursor(object): self._cr.execute("INSERT INTO " + self._table_name \ + """(name, lang, res_id, src, type, - imd_model, imd_module, imd_name, value) + imd_model, module, imd_name, value) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s)""", (ddict['name'], ddict['lang'], ddict.get('res_id'), ddict['src'], ddict['type'], - ddict.get('imd_model'), ddict.get('imd_module'), ddict.get('imd_name'), + ddict.get('imd_model'), ddict.get('module'), ddict.get('imd_name'), ddict['value'])) def finish(self): @@ -101,18 +100,18 @@ class ir_translation_import_cursor(object): SET res_id = imd.res_id FROM ir_model_data AS imd WHERE ti.res_id IS NULL - AND ti.imd_module IS NOT NULL AND ti.imd_name IS NOT NULL + AND ti.module IS NOT NULL AND ti.imd_name IS NOT NULL - AND ti.imd_module = imd.module AND ti.imd_name = imd.name + AND ti.module = imd.module AND ti.imd_name = imd.name AND ti.imd_model = imd.model; """ % self._table_name) if self._debug: - cr.execute("SELECT imd_module, imd_model, imd_name FROM %s " \ - "WHERE res_id IS NULL AND imd_module IS NOT NULL" % self._table_name) + cr.execute("SELECT module, imd_model, imd_name FROM %s " \ + "WHERE res_id IS NULL AND module IS NOT NULL" % self._table_name) for row in cr.fetchall(): _logger.debug("ir.translation.cursor: missing res_id for %s. %s/%s ", *row) - cr.execute("DELETE FROM %s WHERE res_id IS NULL AND imd_module IS NOT NULL" % \ + cr.execute("DELETE FROM %s WHERE res_id IS NULL AND module IS NOT NULL" % \ self._table_name) # Records w/o res_id must _not_ be inserted into our db, because they are @@ -132,8 +131,8 @@ class ir_translation_import_cursor(object): # Step 3: insert new translations - cr.execute("""INSERT INTO %s(name, lang, res_id, src, type, value) - SELECT name, lang, res_id, src, type, value + cr.execute("""INSERT INTO %s(name, lang, res_id, src, type, value, module) + SELECT name, lang, res_id, src, type, value, module FROM %s AS ti WHERE NOT EXISTS(SELECT 1 FROM ONLY %s AS irt WHERE %s); """ % (self._parent_table, self._table_name, self._parent_table, find_expr)) @@ -167,6 +166,7 @@ class ir_translation(osv.osv): 'type': fields.selection(TRANSLATION_TYPE, string='Type', size=16, select=True), 'src': fields.text('Source'), 'value': fields.text('Translation Value'), + 'module': fields.char('Module Name', size=128), } _sql_constraints = [ ('lang_fkey_res_lang', 'FOREIGN KEY(lang) REFERENCES res_lang(code)', diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 392850f7b77..1a3b41513b4 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -620,7 +620,7 @@ class module(osv.osv): f2 = modules.get_module_resource(mod.name, 'i18n', iso_lang2 + '.po') if f2: _logger.info('module %s: loading base translation file %s for language %s', mod.name, iso_lang2, lang) - tools.trans_load(cr, f2, lang, verbose=False, context=context) + tools.trans_load(cr, f2, lang, verbose=False, module_name=mod.name, context=context) context2['overwrite'] = True # Implementation notice: we must first search for the full name of # the language derivative, like "en_UK", and then the generic, @@ -630,7 +630,7 @@ class module(osv.osv): f = modules.get_module_resource(mod.name, 'i18n', iso_lang + '.po') if f: _logger.info('module %s: loading translation file (%s) for language %s', mod.name, iso_lang, lang) - tools.trans_load(cr, f, lang, verbose=False, context=context2) + tools.trans_load(cr, f, lang, verbose=False, module_name=mod.name, context=context2) elif iso_lang != 'en': _logger.warning('module %s: no translation for language %s', mod.name, iso_lang) diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 6762426d8cd..2dbaa67a425 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -799,7 +799,7 @@ class translation(netsvc.ExportService): f2 = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang2 + '.po') if f2: _logger.info('module %s: loading base translation file %s for language %s', module_name, iso_lang2, lang) - translated_data.append(tools.trans_load(cr, f2, lang, verbose=False, flag=flag, context=context)) + translated_data.append(tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context)) context2['overwrite'] = True # Implementation notice: we must first search for the full name of # the language derivative, like "en_UK", and then the generic, @@ -809,7 +809,7 @@ class translation(netsvc.ExportService): f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') if f: _logger.info('module %s: loading translation file (%s) for language %s', module_name, iso_lang, lang) - translated_data.append(tools.trans_load(cr, f, lang, verbose=False, flag=flag, context=context2)) + translated_data.append(tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2)) elif iso_lang != 'en': _logger.warning('module %s: no translation for language %s', module_name, iso_lang) cr.commit() diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index 0d3802bd5c0..83576d8d7b9 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -843,7 +843,7 @@ def trans_generate(lang, modules, cr): return out -def trans_load(cr, filename, lang, verbose=True, flag=None, context=None): +def trans_load(cr, filename, lang, verbose=True, flag=None, module_name=None, context=None): try: fileobj = misc.file_open(filename) pool = pooler.get_pool(cr.dbname) @@ -858,7 +858,7 @@ def trans_load(cr, filename, lang, verbose=True, flag=None, context=None): return transl else: fileformat = os.path.splitext(filename)[-1][1:].lower() - r = trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, context=context) + r = trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, module_name=module_name, context=context) fileobj.close() return r except IOError: @@ -866,7 +866,7 @@ def trans_load(cr, filename, lang, verbose=True, flag=None, context=None): _logger.error("couldn't read translation file %s", filename) return None -def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, context=None): +def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, module_name=None, context=None): """Populates the ir_translation table.""" if verbose: _logger.info('loading translation file for language %s', lang) @@ -896,7 +896,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, break elif fileformat == 'po': reader = TinyPoFile(fileobj) - f = ['type', 'name', 'res_id', 'src', 'value'] + f = ['type', 'name', 'res_id', 'src', 'value', 'module'] else: _logger.error('Bad file format: %s', fileformat) raise Exception(_('Bad file format')) @@ -929,6 +929,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, if res_id and isinstance(res_id, (int, long)) \ or (isinstance(res_id, basestring) and res_id.isdigit()): dic['res_id'] = int(res_id) + dic['module'] = module_name else: try: tmodel = dic['name'].split(',')[0] @@ -938,9 +939,8 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, tmodule = dic_module tname = res_id dic['imd_model'] = tmodel - dic['imd_module'] = tmodule + dic['module'] = tmodule dic['imd_name'] = tname - dic['res_id'] = None except Exception: _logger.warning("Could not decode resource for %s, please fix the po file.", From d87adc497e11e3f5c22da7069720b6f9270d7ada Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 14:28:38 +0530 Subject: [PATCH 004/275] [IMP] improved code to get translation from database. bzr revid: tpa@tinyerp.com-20120712085838-pqzj86fptp96eag6 --- openerp/service/web_services.py | 10 +++++++--- openerp/tools/translate.py | 13 ++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 2dbaa67a425..7f6b201d9c3 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -783,7 +783,7 @@ class translation(netsvc.ExportService): netsvc.ExportService.__init__(self, name) def exp_load(self, db, modules, langs, flag=None, context=None): - translated_data = [] + translated_data = {'messages':[]} cr = pooler.get_db(db).cursor() for module_name in modules: modpath = openerp.modules.get_module_path(module_name) @@ -799,7 +799,9 @@ class translation(netsvc.ExportService): f2 = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang2 + '.po') if f2: _logger.info('module %s: loading base translation file %s for language %s', module_name, iso_lang2, lang) - translated_data.append(tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context)) + trans = tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context) + if trans: + translated_data['messages'].extend(trans) context2['overwrite'] = True # Implementation notice: we must first search for the full name of # the language derivative, like "en_UK", and then the generic, @@ -809,7 +811,9 @@ class translation(netsvc.ExportService): f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') if f: _logger.info('module %s: loading translation file (%s) for language %s', module_name, iso_lang, lang) - translated_data.append(tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2)) + trans = tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2) + if trans: + translated_data['messages'].extend(trans) elif iso_lang != 'en': _logger.warning('module %s: no translation for language %s', module_name, iso_lang) cr.commit() diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index 83576d8d7b9..4067133e2a9 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -849,12 +849,11 @@ def trans_load(cr, filename, lang, verbose=True, flag=None, module_name=None, co pool = pooler.get_pool(cr.dbname) traslation_obj = pool.get('ir.translation') _logger.info("loading %s", filename) - if flag == 'web': - transl = {"messages":[]} - po = babel.messages.pofile.read_po(fileobj) - for x in po: - if x.id and x.string and "openerp-web" in x.auto_comments: - transl["messages"].append({'id': x.id, 'string': x.string}) + if flag == 'web' and module_name == 'web': + transl = [] + trans_ids = traslation_obj.search(cr, 1, [('module','=', module_name),('lang','=',lang)]) + for trans in traslation_obj.browse(cr, 1, trans_ids, context=context): + transl.append({'id': trans.src, 'string': trans.value}) return transl else: fileformat = os.path.splitext(filename)[-1][1:].lower() @@ -913,7 +912,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, # dictionary which holds values for this line of the csv file # {'lang': ..., 'type': ..., 'name': ..., 'res_id': ..., - # 'src': ..., 'value': ...} + # 'src': ..., 'value': ..., 'module':...} dic = {'lang': lang} dic_module = False for i in range(len(f)): From 20646e9104a1e36a2375f0b688dc5a5ed18665b1 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 15:01:30 +0530 Subject: [PATCH 005/275] [IMP] move load function to the ir_translation.py bzr revid: tpa@tinyerp.com-20120712093130-rcis1aamb7bbptdd --- openerp/addons/base/ir/ir_translation.py | 36 ++++++++++++++++++++++++ openerp/service/web_services.py | 35 ++--------------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py index 2f8f87a0a2a..404dfb842a3 100644 --- a/openerp/addons/base/ir/ir_translation.py +++ b/openerp/addons/base/ir/ir_translation.py @@ -22,6 +22,7 @@ from osv import fields, osv import tools import logging +import openerp.modules _logger = logging.getLogger(__name__) @@ -322,6 +323,41 @@ class ir_translation(osv.osv): """ Return a cursor-like object for fast inserting translations """ return ir_translation_import_cursor(cr, uid, self, context=context) + + def load(self, cr, modules, langs, flag, context=None): + translated_data = {'messages':[]} + for module_name in modules: + modpath = openerp.modules.get_module_path(module_name) + if not modpath: + # unable to find the module. we skip + continue + for lang in langs: + iso_lang = tools.get_iso_codes(lang) + f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') + context2 = context and context.copy() or {} + if f and '_' in iso_lang: + iso_lang2 = iso_lang.split('_')[0] + f2 = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang2 + '.po') + if f2: + _logger.info('module %s: loading base translation file %s for language %s', module_name, iso_lang2, lang) + trans = tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context) + if trans: + translated_data['messages'].extend(trans) + context2['overwrite'] = True + # Implementation notice: we must first search for the full name of + # the language derivative, like "en_UK", and then the generic, + # like "en". + if (not f) and '_' in iso_lang: + iso_lang = iso_lang.split('_')[0] + f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') + if f: + _logger.info('module %s: loading translation file (%s) for language %s', module_name, iso_lang, lang) + trans = tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2) + if trans: + translated_data['messages'].extend(trans) + elif iso_lang != 'en': + _logger.warning('module %s: no translation for language %s', module_name, iso_lang) + return translated_data ir_translation() diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 7f6b201d9c3..17935efda54 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -783,39 +783,10 @@ class translation(netsvc.ExportService): netsvc.ExportService.__init__(self, name) def exp_load(self, db, modules, langs, flag=None, context=None): - translated_data = {'messages':[]} cr = pooler.get_db(db).cursor() - for module_name in modules: - modpath = openerp.modules.get_module_path(module_name) - if not modpath: - # unable to find the module. we skip - continue - for lang in langs: - iso_lang = tools.get_iso_codes(lang) - f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') - context2 = context and context.copy() or {} - if f and '_' in iso_lang: - iso_lang2 = iso_lang.split('_')[0] - f2 = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang2 + '.po') - if f2: - _logger.info('module %s: loading base translation file %s for language %s', module_name, iso_lang2, lang) - trans = tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context) - if trans: - translated_data['messages'].extend(trans) - context2['overwrite'] = True - # Implementation notice: we must first search for the full name of - # the language derivative, like "en_UK", and then the generic, - # like "en". - if (not f) and '_' in iso_lang: - iso_lang = iso_lang.split('_')[0] - f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') - if f: - _logger.info('module %s: loading translation file (%s) for language %s', module_name, iso_lang, lang) - trans = tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2) - if trans: - translated_data['messages'].extend(trans) - elif iso_lang != 'en': - _logger.warning('module %s: no translation for language %s', module_name, iso_lang) + pool = pooler.get_pool(cr.dbname) + traslation_obj = pool.get('ir.translation') + translated_data = traslation_obj.load(cr, modules, langs, flag, context=context) cr.commit() cr.close() return translated_data From 976944bce2f4a39f0d1f0b22737a2b0603479b32 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 15:21:31 +0530 Subject: [PATCH 006/275] [IMP] improved code in module.py to load translation. bzr revid: tpa@tinyerp.com-20120712095131-3tt25snidvafflhb --- openerp/addons/base/ir/ir_translation.py | 2 +- openerp/addons/base/module/module.py | 30 +++--------------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py index 404dfb842a3..ad7d7013127 100644 --- a/openerp/addons/base/ir/ir_translation.py +++ b/openerp/addons/base/ir/ir_translation.py @@ -324,7 +324,7 @@ class ir_translation(osv.osv): """ return ir_translation_import_cursor(cr, uid, self, context=context) - def load(self, cr, modules, langs, flag, context=None): + def load(self, cr, modules, langs, flag=None, context=None): translated_data = {'messages':[]} for module_name in modules: modpath = openerp.modules.get_module_path(module_name) diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 1a3b41513b4..963fb292946 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -596,8 +596,8 @@ class module(osv.osv): def update_translations(self, cr, uid, ids, filter_lang=None, context=None): if context is None: context = {} + pool = pooler.get_pool(cr.dbname) if not filter_lang: - pool = pooler.get_pool(cr.dbname) lang_obj = pool.get('res.lang') lang_ids = lang_obj.search(cr, uid, [('translatable', '=', True)]) filter_lang = [lang.code for lang in lang_obj.browse(cr, uid, lang_ids)] @@ -607,32 +607,8 @@ class module(osv.osv): for mod in self.browse(cr, uid, ids): if mod.state != 'installed': continue - modpath = modules.get_module_path(mod.name) - if not modpath: - # unable to find the module. we skip - continue - for lang in filter_lang: - iso_lang = tools.get_iso_codes(lang) - f = modules.get_module_resource(mod.name, 'i18n', iso_lang + '.po') - context2 = context and context.copy() or {} - if f and '_' in iso_lang: - iso_lang2 = iso_lang.split('_')[0] - f2 = modules.get_module_resource(mod.name, 'i18n', iso_lang2 + '.po') - if f2: - _logger.info('module %s: loading base translation file %s for language %s', mod.name, iso_lang2, lang) - tools.trans_load(cr, f2, lang, verbose=False, module_name=mod.name, context=context) - context2['overwrite'] = True - # Implementation notice: we must first search for the full name of - # the language derivative, like "en_UK", and then the generic, - # like "en". - if (not f) and '_' in iso_lang: - iso_lang = iso_lang.split('_')[0] - f = modules.get_module_resource(mod.name, 'i18n', iso_lang + '.po') - if f: - _logger.info('module %s: loading translation file (%s) for language %s', mod.name, iso_lang, lang) - tools.trans_load(cr, f, lang, verbose=False, module_name=mod.name, context=context2) - elif iso_lang != 'en': - _logger.warning('module %s: no translation for language %s', mod.name, iso_lang) + traslation_obj = pool.get('ir.translation') + traslation_obj.load(cr, [mod.name], filter_lang, context=context) def check(self, cr, uid, ids, context=None): for mod in self.browse(cr, uid, ids, context=context): From f0f4ba6d413ce89e016b26895f1e3fb62450d2ae Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 16:11:10 +0530 Subject: [PATCH 007/275] [IMP] improved code. bzr revid: tpa@tinyerp.com-20120712104110-wot1evq0affpx2tp --- addons/web/controllers/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 5d7aa93f3a5..eb60b178ad2 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -360,7 +360,7 @@ class WebClient(openerpweb.Controller): trans = proxy.load(req.session._db, [mod], langs, "web") if trans: messages[mod] = trans - return {"modules": {'messages': messages}, + return {"modules": messages, "lang_parameters": lang_obj} @openerpweb.jsonrequest From 4bbbef1929fc41b9928690ac77112ec5aa3db452 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 16:29:55 +0530 Subject: [PATCH 008/275] [IMP] improved code for load translation when run web without embedded mode. bzr revid: tpa@tinyerp.com-20120712105955-szwm5vb49va6o4dp --- addons/web/controllers/main.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index eb60b178ad2..75feed44c69 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -360,6 +360,24 @@ class WebClient(openerpweb.Controller): trans = proxy.load(req.session._db, [mod], langs, "web") if trans: messages[mod] = trans + # keep loading from .po (Reason to run web without embedded mode) + if not messages['web']['messages']: + for addon_name in mods: + transl = {'messages':[]} + messages[addon_name] = transl + addons_path = openerpweb.addons_manifest[addon_name]['addons_path'] + for l in langs: + f_name = os.path.join(addons_path, addon_name, "i18n", l + ".po") + if not os.path.exists(f_name): + continue + try: + with open(f_name) as t_file: + po = babel.messages.pofile.read_po(t_file) + except Exception: + continue + for x in po: + if x.id and x.string and "openerp-web" in x.auto_comments: + transl["messages"].append({'id': x.id, 'string': x.string}) return {"modules": messages, "lang_parameters": lang_obj} From bc76991e24edc42353fc637624fa7ff4bfa8a34f Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 18:53:08 +0530 Subject: [PATCH 009/275] [IMP] improved code. bzr revid: tpa@tinyerp.com-20120712132308-1qvurv572sxmsnqe --- openerp/addons/base/ir/ir_translation.py | 8 ++------ openerp/tools/translate.py | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py index ad7d7013127..0a3124b36ce 100644 --- a/openerp/addons/base/ir/ir_translation.py +++ b/openerp/addons/base/ir/ir_translation.py @@ -340,9 +340,7 @@ class ir_translation(osv.osv): f2 = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang2 + '.po') if f2: _logger.info('module %s: loading base translation file %s for language %s', module_name, iso_lang2, lang) - trans = tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context) - if trans: - translated_data['messages'].extend(trans) + translated_data['messages'].extend(tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context)) context2['overwrite'] = True # Implementation notice: we must first search for the full name of # the language derivative, like "en_UK", and then the generic, @@ -352,9 +350,7 @@ class ir_translation(osv.osv): f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') if f: _logger.info('module %s: loading translation file (%s) for language %s', module_name, iso_lang, lang) - trans = tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2) - if trans: - translated_data['messages'].extend(trans) + translated_data['messages'].extend(tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2)) elif iso_lang != 'en': _logger.warning('module %s: no translation for language %s', module_name, iso_lang) return translated_data diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index 4067133e2a9..517b39e6999 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -857,9 +857,9 @@ def trans_load(cr, filename, lang, verbose=True, flag=None, module_name=None, co return transl else: fileformat = os.path.splitext(filename)[-1][1:].lower() - r = trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, module_name=module_name, context=context) + trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, module_name=module_name, context=context) fileobj.close() - return r + return [] except IOError: if verbose: _logger.error("couldn't read translation file %s", filename) From e9c78767dd87c003c6e93f679e531e34b90d04c7 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 18:55:42 +0530 Subject: [PATCH 010/275] [IMP] improved code bzr revid: tpa@tinyerp.com-20120712132542-c19ysod7jm5jmukc --- addons/web/controllers/main.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 75feed44c69..6c0e2e4dc9b 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -357,9 +357,7 @@ class WebClient(openerpweb.Controller): for mod in mods: messages[mod] = {"messages":[]} proxy = req.session.proxy("translation") - trans = proxy.load(req.session._db, [mod], langs, "web") - if trans: - messages[mod] = trans + messages[mod] = proxy.load(req.session._db, [mod], langs, "web") # keep loading from .po (Reason to run web without embedded mode) if not messages['web']['messages']: for addon_name in mods: From c17ea49de98e6cbe2ba2c760f3bc70323bfc9202 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Thu, 12 Jul 2012 18:57:00 +0530 Subject: [PATCH 011/275] [IMP] improved code bzr revid: tpa@tinyerp.com-20120712132700-zc4co6o4plhzoi60 --- openerp/tools/translate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index 517b39e6999..e9b830302f7 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -849,7 +849,7 @@ def trans_load(cr, filename, lang, verbose=True, flag=None, module_name=None, co pool = pooler.get_pool(cr.dbname) traslation_obj = pool.get('ir.translation') _logger.info("loading %s", filename) - if flag == 'web' and module_name == 'web': + if flag == 'web': transl = [] trans_ids = traslation_obj.search(cr, 1, [('module','=', module_name),('lang','=',lang)]) for trans in traslation_obj.browse(cr, 1, trans_ids, context=context): From f05ee5dfdb3dc5ec3f2db9b7685e5ed9e8e8fc01 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Fri, 13 Jul 2012 11:23:30 +0530 Subject: [PATCH 012/275] [IMP] improved code. bzr revid: tpa@tinyerp.com-20120713055330-avz6ebzuqvcpxdd5 --- openerp/addons/base/module/module.py | 5 ++--- openerp/service/web_services.py | 4 +--- openerp/tools/translate.py | 8 +++----- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 963fb292946..bbf3f3f5b64 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -594,9 +594,9 @@ class module(osv.osv): self.write(cr, uid, [mod_browse.id], {'category_id': p_id}) def update_translations(self, cr, uid, ids, filter_lang=None, context=None): + pool = pooler.get_pool(cr.dbname) if context is None: context = {} - pool = pooler.get_pool(cr.dbname) if not filter_lang: lang_obj = pool.get('res.lang') lang_ids = lang_obj.search(cr, uid, [('translatable', '=', True)]) @@ -607,8 +607,7 @@ class module(osv.osv): for mod in self.browse(cr, uid, ids): if mod.state != 'installed': continue - traslation_obj = pool.get('ir.translation') - traslation_obj.load(cr, [mod.name], filter_lang, context=context) + pool.get('ir.translation').load(cr, [mod.name], filter_lang, context=context) def check(self, cr, uid, ids, context=None): for mod in self.browse(cr, uid, ids, context=context): diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 17935efda54..0cfcf468a2b 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -784,9 +784,7 @@ class translation(netsvc.ExportService): def exp_load(self, db, modules, langs, flag=None, context=None): cr = pooler.get_db(db).cursor() - pool = pooler.get_pool(cr.dbname) - traslation_obj = pool.get('ir.translation') - translated_data = traslation_obj.load(cr, modules, langs, flag, context=context) + translated_data = pooler.get_pool(db).get('ir.translation').load(cr, modules, langs, flag, context=context) cr.commit() cr.close() return translated_data diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index e9b830302f7..bbada8c2efc 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -846,20 +846,18 @@ def trans_generate(lang, modules, cr): def trans_load(cr, filename, lang, verbose=True, flag=None, module_name=None, context=None): try: fileobj = misc.file_open(filename) - pool = pooler.get_pool(cr.dbname) - traslation_obj = pool.get('ir.translation') + traslation_obj = pooler.get_pool(cr.dbname).get('ir.translation') _logger.info("loading %s", filename) + transl = [] if flag == 'web': - transl = [] trans_ids = traslation_obj.search(cr, 1, [('module','=', module_name),('lang','=',lang)]) for trans in traslation_obj.browse(cr, 1, trans_ids, context=context): transl.append({'id': trans.src, 'string': trans.value}) - return transl else: fileformat = os.path.splitext(filename)[-1][1:].lower() trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, module_name=module_name, context=context) fileobj.close() - return [] + return transl except IOError: if verbose: _logger.error("couldn't read translation file %s", filename) From 402ba23000ed38f2d4c95d5b240d6327d70b3731 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Fri, 13 Jul 2012 12:25:21 +0530 Subject: [PATCH 013/275] [IMP] improved code to retun traslation in proper format from server bzr revid: tpa@tinyerp.com-20120713065521-07a7qdfxfio673cq --- openerp/addons/base/ir/ir_translation.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py index 0a3124b36ce..cd6fa271852 100644 --- a/openerp/addons/base/ir/ir_translation.py +++ b/openerp/addons/base/ir/ir_translation.py @@ -325,8 +325,9 @@ class ir_translation(osv.osv): return ir_translation_import_cursor(cr, uid, self, context=context) def load(self, cr, modules, langs, flag=None, context=None): - translated_data = {'messages':[]} + translated_data = {} for module_name in modules: + translated_data[module_name] = {'messages':[]} modpath = openerp.modules.get_module_path(module_name) if not modpath: # unable to find the module. we skip @@ -340,7 +341,7 @@ class ir_translation(osv.osv): f2 = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang2 + '.po') if f2: _logger.info('module %s: loading base translation file %s for language %s', module_name, iso_lang2, lang) - translated_data['messages'].extend(tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context)) + translated_data[module_name]['messages'].extend(tools.trans_load(cr, f2, lang, verbose=False, flag=flag, module_name=module_name, context=context)) context2['overwrite'] = True # Implementation notice: we must first search for the full name of # the language derivative, like "en_UK", and then the generic, @@ -350,7 +351,7 @@ class ir_translation(osv.osv): f = openerp.modules.get_module_resource(module_name, 'i18n', iso_lang + '.po') if f: _logger.info('module %s: loading translation file (%s) for language %s', module_name, iso_lang, lang) - translated_data['messages'].extend(tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2)) + translated_data[module_name]['messages'].extend(tools.trans_load(cr, f, lang, verbose=False, flag=flag, module_name=module_name, context=context2)) elif iso_lang != 'en': _logger.warning('module %s: no translation for language %s', module_name, iso_lang) return translated_data From 0d4bd736e1bd8c8acb78f63e190111b1c72b05af Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Fri, 13 Jul 2012 12:30:48 +0530 Subject: [PATCH 014/275] [IMP] improved code to get formeted traslation from server. bzr revid: tpa@tinyerp.com-20120713070048-7yxm3fcajemiingc --- addons/web/controllers/main.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 6c0e2e4dc9b..7cde4040e4f 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -353,11 +353,8 @@ class WebClient(openerpweb.Controller): langs = lang.split(separator) langs = [separator.join(langs[:x]) for x in range(1, len(langs) + 1)] - messages = {} - for mod in mods: - messages[mod] = {"messages":[]} - proxy = req.session.proxy("translation") - messages[mod] = proxy.load(req.session._db, [mod], langs, "web") + proxy = req.session.proxy("translation") + messages = proxy.load(req.session._db, mods, langs, "web") # keep loading from .po (Reason to run web without embedded mode) if not messages['web']['messages']: for addon_name in mods: From 8383d6a2459588b332ecdcb0a26c38f92c5ab317 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Fri, 13 Jul 2012 14:58:38 +0530 Subject: [PATCH 015/275] [IMP] Fetch only traslated and distinct strings using sql. bzr revid: tpa@tinyerp.com-20120713092838-5th251msbdkgjdnb --- openerp/tools/translate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index bbada8c2efc..11801326ba3 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -850,9 +850,9 @@ def trans_load(cr, filename, lang, verbose=True, flag=None, module_name=None, co _logger.info("loading %s", filename) transl = [] if flag == 'web': - trans_ids = traslation_obj.search(cr, 1, [('module','=', module_name),('lang','=',lang)]) - for trans in traslation_obj.browse(cr, 1, trans_ids, context=context): - transl.append({'id': trans.src, 'string': trans.value}) + cr.execute("select DISTINCT src,value from ir_translation where module='%s' AND value != ''"% (module_name)) + for src, value in cr.fetchall(): + transl.append({'id': src, 'string': value}) else: fileformat = os.path.splitext(filename)[-1][1:].lower() trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, module_name=module_name, context=context) From 48a344c1e8d88b005eaf29128890196fd096b441 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Fri, 13 Jul 2012 15:24:48 +0530 Subject: [PATCH 016/275] [IMP] improved code. bzr revid: tpa@tinyerp.com-20120713095448-ghr750h2jk9ivsj2 --- openerp/tools/translate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index 11801326ba3..25e80e260fa 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -850,7 +850,7 @@ def trans_load(cr, filename, lang, verbose=True, flag=None, module_name=None, co _logger.info("loading %s", filename) transl = [] if flag == 'web': - cr.execute("select DISTINCT src,value from ir_translation where module='%s' AND value != ''"% (module_name)) + cr.execute("select DISTINCT src,value from ir_translation where module='%s' AND lang='%s' AND value != ''"% (module_name,lang)) for src, value in cr.fetchall(): transl.append({'id': src, 'string': value}) else: From 58e20e9c8f0f40b93a0d4dd1ff68666d49311949 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Mon, 16 Jul 2012 11:30:56 +0530 Subject: [PATCH 017/275] [IMP] improved code to load data from po. bzr revid: tpa@tinyerp.com-20120716060056-3az6awpd6gw39hii --- addons/web/controllers/main.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 7cde4040e4f..024360ce5e6 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -355,14 +355,11 @@ class WebClient(openerpweb.Controller): proxy = req.session.proxy("translation") messages = proxy.load(req.session._db, mods, langs, "web") - # keep loading from .po (Reason to run web without embedded mode) - if not messages['web']['messages']: - for addon_name in mods: - transl = {'messages':[]} - messages[addon_name] = transl - addons_path = openerpweb.addons_manifest[addon_name]['addons_path'] + for mod in messages: + if not messages[mod]['messages']: + addons_path = openerpweb.addons_manifest[mod]['addons_path'] for l in langs: - f_name = os.path.join(addons_path, addon_name, "i18n", l + ".po") + f_name = os.path.join(addons_path, mod, "i18n", l + ".po") if not os.path.exists(f_name): continue try: @@ -372,7 +369,7 @@ class WebClient(openerpweb.Controller): continue for x in po: if x.id and x.string and "openerp-web" in x.auto_comments: - transl["messages"].append({'id': x.id, 'string': x.string}) + messages[mod]["messages"].append({'id': x.id, 'string': x.string}) return {"modules": messages, "lang_parameters": lang_obj} From d931a099ac4551a4d24724a09ecc12d3951a82b6 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Mon, 16 Jul 2012 16:04:58 +0530 Subject: [PATCH 018/275] [ADD] added test case for translation load in tests_xmlrpc.py. bzr revid: tpa@tinyerp.com-20120716103458-p2l9p38g4ubl7d2i --- openerp/tests/common.py | 1 + openerp/tests/test_xmlrpc.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/openerp/tests/common.py b/openerp/tests/common.py index ef5b0586136..351645c41f2 100644 --- a/openerp/tests/common.py +++ b/openerp/tests/common.py @@ -72,6 +72,7 @@ class RpcCase(unittest2.TestCase): self.proxy.common_61 = xmlrpclib.ServerProxy(url_61 + 'common') self.proxy.db_61 = xmlrpclib.ServerProxy(url_61 + 'db') self.proxy.model_61 = xmlrpclib.ServerProxy(url_61 + 'model/' + DB) + self.proxy.translation_61 = xmlrpclib.ServerProxy(url_61 + 'translation') @classmethod def generate_database_name(cls): diff --git a/openerp/tests/test_xmlrpc.py b/openerp/tests/test_xmlrpc.py index 37655e72718..5f73325fe4c 100644 --- a/openerp/tests/test_xmlrpc.py +++ b/openerp/tests/test_xmlrpc.py @@ -71,6 +71,11 @@ class test_xmlrpc(common.RpcCase): """ assert self.proxy.db_60.drop(ADMIN_PASSWORD, DB) is True + def test_xmlrpc_61_translation_load(self): + """ Try a load translation service like web. """ + messages = self.proxy.translation_61.load(DB, ['base', 'web'], ['ru_RU'], 'web') + assert messages + if __name__ == '__main__': unittest2.main() From 74fd43b82c211d416fef8f9b1ff10bc43d5aaab8 Mon Sep 17 00:00:00 2001 From: "Turkesh Patel (Open ERP)" Date: Mon, 16 Jul 2012 16:13:05 +0530 Subject: [PATCH 019/275] [IMP] change language. bzr revid: tpa@tinyerp.com-20120716104305-ws8igxbfx7m0bwy9 --- openerp/tests/test_xmlrpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/tests/test_xmlrpc.py b/openerp/tests/test_xmlrpc.py index 5f73325fe4c..70ac6b1f75f 100644 --- a/openerp/tests/test_xmlrpc.py +++ b/openerp/tests/test_xmlrpc.py @@ -73,7 +73,7 @@ class test_xmlrpc(common.RpcCase): def test_xmlrpc_61_translation_load(self): """ Try a load translation service like web. """ - messages = self.proxy.translation_61.load(DB, ['base', 'web'], ['ru_RU'], 'web') + messages = self.proxy.translation_61.load(DB, ['base', 'web'], ['en_US'], 'web') assert messages if __name__ == '__main__': From ca9c79727541fbf87f316906887e920e79b9550c Mon Sep 17 00:00:00 2001 From: Amit Parik Date: Wed, 5 Sep 2012 17:03:13 +0530 Subject: [PATCH 020/275] [FIX]:project_timesheet impossible to edit task work bzr revid: pja@tinyerp.com-20120905113313-c2cbi37xqr6mnvrc --- addons/project_timesheet/project_timesheet.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/project_timesheet/project_timesheet.py b/addons/project_timesheet/project_timesheet.py index 1e50848201c..12d1eedbeb2 100644 --- a/addons/project_timesheet/project_timesheet.py +++ b/addons/project_timesheet/project_timesheet.py @@ -166,10 +166,7 @@ class project_work(osv.osv): vals_line['name'] = '%s: %s' % (tools.ustr(task.task_id.name), tools.ustr(vals['name']) or '/') if 'user_id' in vals: vals_line['user_id'] = vals['user_id'] - result = self.get_user_related_details(cr, uid, vals.get('user_id', task.user_id.id)) - for fld in ('product_id', 'general_account_id', 'journal_id', 'product_uom_id'): - if result.get(fld, False): - vals_line[fld] = result[fld] + if 'date' in vals: vals_line['date'] = vals['date'][:10] @@ -177,7 +174,10 @@ class project_work(osv.osv): default_uom = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id.id vals_line['unit_amount'] = vals['hours'] prod_id = vals_line.get('product_id', line_id.product_id.id) # False may be set - + result = self.get_user_related_details(cr, uid, vals.get('user_id', task.user_id.id)) + for fld in ('product_id', 'general_account_id', 'journal_id', 'product_uom_id'): + if result.get(fld, False): + vals_line[fld] = result[fld] if result.get('product_uom_id',False) and (not result['product_uom_id'] == default_uom): vals_line['unit_amount'] = uom_obj._compute_qty(cr, uid, default_uom, vals['hours'], result['product_uom_id']) From 09ba29883c06d1f1de06c40e89c864c85f53d5c7 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 11 Sep 2012 15:52:54 +0200 Subject: [PATCH 021/275] [FIX] ir.translation: typo in last sync with trunk bzr revid: odo@openerp.com-20120911135254-uqi1s4n8qh0e3d1y --- openerp/addons/base/ir/ir_translation.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py index 68b413344b2..c8f9cf8e6fe 100644 --- a/openerp/addons/base/ir/ir_translation.py +++ b/openerp/addons/base/ir/ir_translation.py @@ -68,7 +68,6 @@ class ir_translation_import_cursor(object): # Note that Postgres will NOT inherit the constraints or indexes # of ir_translation, so this copy will be much faster. - cr.execute('''CREATE TEMP TABLE %s( imd_model VARCHAR(64), imd_name VARCHAR(128) @@ -77,16 +76,14 @@ class ir_translation_import_cursor(object): def push(self, trans_dict): """Feed a translation, as a dictionary, into the cursor """ - params = dict(trans_dict, - state="translated" if trans_dict['value'] else "to_translate") + params = dict(trans_dict, state="translated" if trans_dict['value'] else "to_translate") self._cr.execute("""INSERT INTO %s (name, lang, res_id, src, type, imd_model, module, imd_name, value, state) - VALUES (%(name)s, %(lang)s, %(res_id)s, %(src)s, %(type)s, %(imd_model)s, %(module)s, %(imd_name)s, %(value)s, %(state)s)""", - params) + VALUES (%%(name)s, %%(lang)s, %%(res_id)s, %%(src)s, %%(type)s, %%(imd_model)s, %%(module)s, %%(imd_name)s, %%(value)s, %%(state)s)""" % self._table_name, + params) def finish(self): """ Transfer the data from the temp table to ir.translation """ - cr = self._cr if self._debug: cr.execute("SELECT count(*) FROM %s" % self._table_name) @@ -129,7 +126,6 @@ class ir_translation_import_cursor(object): """ % (self._parent_table, self._table_name, find_expr)) # Step 3: insert new translations - cr.execute("""INSERT INTO %s(name, lang, res_id, src, type, value, module, state) SELECT name, lang, res_id, src, type, value, module, state FROM %s AS ti From 550751b35825d60af0ed5985cd46b4ff4e2d3d01 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 13 Sep 2012 16:29:20 +0200 Subject: [PATCH 022/275] [IMP] translations: wip, remove unnecessary code, support loading PO comments and storing them, split ir.translation view data in separate XML file bzr revid: odo@openerp.com-20120913142920-ggpeqth4s2wwqwd2 --- openerp/addons/base/__openerp__.py | 1 + openerp/addons/base/ir/ir.xml | 69 ------------- openerp/addons/base/ir/ir_translation.py | 123 ++++++++++++----------- openerp/addons/base/ir/ir_ui_view.py | 5 +- openerp/addons/base/module/module.py | 16 +-- openerp/service/web_services.py | 24 ----- openerp/tests/common.py | 1 - openerp/tests/test_xmlrpc.py | 5 - openerp/tools/translate.py | 61 ++++++----- 9 files changed, 98 insertions(+), 207 deletions(-) diff --git a/openerp/addons/base/__openerp__.py b/openerp/addons/base/__openerp__.py index 937c9cbd20b..082cf260373 100644 --- a/openerp/addons/base/__openerp__.py +++ b/openerp/addons/base/__openerp__.py @@ -44,6 +44,7 @@ The kernel of OpenERP, needed for all installation. 'data/res.country.state.csv', 'ir/wizard/wizard_menu_view.xml', 'ir/ir.xml', + 'ir/ir_translation_view.xml', 'ir/ir_filters.xml', 'ir/ir_config_parameter_view.xml', 'ir/workflow/workflow_view.xml', diff --git a/openerp/addons/base/ir/ir.xml b/openerp/addons/base/ir/ir.xml index 29bb681981a..515d9641001 100644 --- a/openerp/addons/base/ir/ir.xml +++ b/openerp/addons/base/ir/ir.xml @@ -1147,75 +1147,6 @@ - - - - Translations - ir.translation - - - - - - - - - - - - - Translations - ir.translation - -
-
- -
- - - - - - - - - - - - - - - - - - -
-
-
- - Translations - ir.translation - - - - - - - - - - - - - Translated Terms - ir.translation - form - - - - + + @@ -917,7 +920,7 @@ -
+
From 24a4e57171fd0ce371260370226f4c90607f390b Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Mon, 24 Sep 2012 13:53:20 +0200 Subject: [PATCH 030/275] [FIX] point_of_sale: show the opening cash control bzr revid: stw@openerp.com-20120924115320-nkbfhfnyab4bhxrc --- addons/point_of_sale/point_of_sale_view.xml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/addons/point_of_sale/point_of_sale_view.xml b/addons/point_of_sale/point_of_sale_view.xml index d88e1f73cc2..131909a1fd3 100644 --- a/addons/point_of_sale/point_of_sale_view.xml +++ b/addons/point_of_sale/point_of_sale_view.xml @@ -896,11 +896,7 @@ - - - + From aceae3501efeece3366db5a478bf450067e37301 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 25 Sep 2012 12:40:13 +0200 Subject: [PATCH 031/275] [IMP] auth_signup: extend the login form to allow signups bzr revid: rco@openerp.com-20120925104013-f2vfqcjknx7zyo26 --- addons/auth_signup/controllers/main.py | 49 +++++-- addons/auth_signup/res_users.py | 121 ++++++++---------- .../auth_signup/static/src/js/auth_signup.js | 104 ++++++++------- .../static/src/xml/auth_signup.xml | 43 +++---- 4 files changed, 172 insertions(+), 145 deletions(-) diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 821ef44f459..343c660ff7d 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -1,25 +1,58 @@ -import logging - -import werkzeug.urls +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2012-today OpenERP SA () +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see +# +############################################################################## +from openerp import SUPERUSER_ID from openerp.modules.registry import RegistryManager from openerp.addons.web.controllers.main import login_and_redirect import openerp.addons.web.common.http as openerpweb -from openerp import SUPERUSER_ID +import werkzeug + +import logging _logger = logging.getLogger(__name__) -class OpenIDController(openerpweb.Controller): +class Controller(openerpweb.Controller): _cp_path = '/auth_signup' + @openerpweb.jsonrequest + def retrieve(self, req, dbname, token): + """ retrieve the user info (name, login or email) corresponding to a signup token """ + registry = RegistryManager.get(dbname) + user_info = None + with registry.cursor() as cr: + res_partner = registry.get('res.partner') + user_info = res_partner.signup_retrieve_info(cr, SUPERUSER_ID, token) + user_info.update(db=dbname, token=token) + return user_info + @openerpweb.httprequest - def signup(self, req, dbname, name, login, password): + def signup(self, req, dbname, token, name, login, password): + """ sign up a user (new or existing), and log it in """ url = '/' registry = RegistryManager.get(dbname) with registry.cursor() as cr: try: - Users = registry.get('res.users') - credentials = Users.auth_signup(cr, SUPERUSER_ID, name, login, password) + res_users = registry.get('res.users') + values = {'name': name, 'login': login, 'password': password} + credentials = res_users.signup(cr, SUPERUSER_ID, values, token) cr.commit() return login_and_redirect(req, *credentials) except AttributeError: diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index f37c547ad8c..600ed9c000e 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -29,8 +29,8 @@ import random import urlparse def random_token(): - # the token has an entropy of 120 bits (6 bits/char * 20 chars) - chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + # the token has an entropy of about 120 bits (6 bits/char * 20 chars) + chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' return ''.join(random.choice(chars) for i in xrange(20)) def now(): @@ -39,12 +39,25 @@ def now(): class res_partner(osv.Model): _inherit = 'res.partner' + + def signup_get_url(self, cr, uid, partner_ids, name, arg, context=None): + """ determine a url for the partner_id to sign up """ + base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + res = {} + for partner in self.browse(cr, uid, partner_ids, context): + token = partner.signup_token + if not token: + token = self._signup_generate_token(cr, uid, partner.id, context=context) + res[partner.id] = urlparse.urljoin(base_url, '#action=login&db=%s&token=%s' % (cr.dbname, token)) + return res + _columns = { 'signup_token': fields.char(size=24, string='Signup Ticket'), 'signup_expiration': fields.datetime(string='Signup Expiration'), + 'signup_url': fields.function(signup_get_url, type='char', string='Signup URL'), } - def signup_generate_token(self, cr, uid, partner_id, context=None): + def _signup_generate_token(self, cr, uid, partner_id, expiration=False, context=None): """ generate a new token for a partner, and return it :param partner_id: the partner id :param expiration: the expiration datetime of the token (string, optional) @@ -52,25 +65,45 @@ class res_partner(osv.Model): """ # generate a unique token token = random_token() - while self.signup_retrieve_partner(cr, uid, token, context): + while self._signup_retrieve_partner(cr, uid, token, context=context): token = random_token() self.write(cr, uid, [partner_id], {'signup_token': token, 'signup_expiration': expiration}, context=context) return token - def signup_retrieve_partner(self, cr, uid, token, raise_exception=False, context=None): - """ find the partner corresponding to a token, and return its partner id or False """ + def _signup_retrieve_partner(self, cr, uid, token, raise_exception=False, context=None): + """ find the partner corresponding to a token, and check its validity + :return: partner (browse record) or False (if raise_exception is False) + :raise: when token not valid (if raise_exception is True) + """ partner_ids = self.search(cr, uid, [('signup_token', '=', token)], context=context) - return partner_ids and partner_ids[0] or False + if not partner_ids: + if raise_exception: + raise Exception("Signup token '%s' is not valid" % token) + return False + partner = self.browse(cr, uid, partner_ids[0], context) + if partner.signup_expiration and partner.signup_expiration < now(): + if raise_exception: + raise Exception("Signup token '%s' is no longer valid" % token) + return False + return partner - def signup_get_url(self, cr, uid, partner_id, context): - """ determine a url for the partner_id to sign up """ - base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - token = self.browse(cr, uid, partner_id, context).signup_token - if not token: - token = self.signup_generate_token(cr, uid, partner_id, context=context) - return urlparse.urljoin(base_url, '/login?db=%s#action=signup&token=%s' % (cr.dbname, token)) + def signup_retrieve_info(self, cr, uid, token, context=None): + """ retrieve the user info about the token + :return: either {'name': ..., 'login': ...} if a user exists for that token, + or {'name': ..., 'email': ...} otherwise + """ + partner = self._signup_retrieve_partner(cr, uid, token, raise_exception=True, context=None) + if partner.user_ids: + return {'name': partner.name, 'login': partner.user_ids[0].login} + else: + return {'name': partner.name, 'email': partner.email} - def signup(self, cr, values, token=None, context=None): + + +class res_users(osv.Model): + _inherit = 'res.users' + + def signup(self, cr, uid, values, token=None, context=None): """ signup a user, to either: - create a new user (no token), or - create a user for a partner (with token, but no user for partner), or @@ -84,13 +117,8 @@ class res_partner(osv.Model): if token: # signup with a token: find the corresponding partner id - partner_id = self.signup_retrieve_partner(cr, uid, token, context=None) - if not partner_id: - raise Exception('Signup token is not valid') - partner = self.browse(cr, uid, partner_id, context) - if partner.signup_expiration and partner.signup_expiration < now(): - raise Exception('Signup token is no longer valid') - + res_partner = self.pool.get('res.partner') + partner = res_partner._signup_retrieve_partner(cr, uid, token, raise_exception=True, context=None) if partner.user_ids: # user exists, modify its password and clear token partner.user_ids[0].write({ @@ -129,51 +157,6 @@ class res_partner(osv.Model): template_user_id = ir_config_parameter.get_param(cr, uid, 'auth_signup.template_user_id') assert template_user_id, 'Signup: missing template user' - values['active'] = True - return self.pool.get('res.users').copy(cr, uid, template_user_id, values, context=context) + values.update({'active': True, 'signup_token': False, 'signup_expiration': False}) + return self.copy(cr, uid, template_user_id, values, context=context) - - -class res_users(osv.Model): - _inherit = 'res.users' - - def auth_signup_create(self, cr, uid, new_user, context=None): - # new_user: - # login - # email - # name (optional) - # partner_id (optional) - # groups (optional) - # sign (for partner_id and groups) - # - user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth_signup.template_user_id', 0) - if user_template_id: - self.pool.get('res.users').copy(cr, SUPERUSER_ID, user_template_id, new_user, context=context) - else: - self.pool.get('res.users').create(cr, SUPERUSER_ID, new_user, context=context) - - def auth_signup(self, cr, uid, name, login, password, context=None): - r = (cr.dbname, login, password) - res = self.search(cr, uid, [("login", "=", login)]) - if res: - # Existing user - user_id = res[0] - try: - self.check(cr.dbname, user_id, password) - # Same password - except openerp.exceptions.AccessDenied: - # Different password - raise - else: - # New user - new_user = { - 'name': name, - 'login': login, - 'user_email': login, - 'password': password, - 'active': True, - } - self.auth_signup_create(cr, uid, new_user) - return r - -# diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js index 2ab13aa7598..bec32ce2803 100644 --- a/addons/auth_signup/static/src/js/auth_signup.js +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -5,56 +5,68 @@ openerp.auth_signup = function(instance) { instance.web.Login.include({ start: function() { var self = this; - this.$('a.oe_signup').click(function() { - var dbname = self.$("form [name=db]").val(); - self.do_action({ - type: 'ir.actions.client', - tag: 'auth_signup.signup', - params: {'dbname': dbname}, - target: 'new', - name: 'Sign up' - }); - return true; - }); - return this._super(); + var d = this._super(); + // hide the signup fields in the case of a regular login + self.on_change_mode() + self.$("form input[name=signup]").click(self.on_change_mode); + // in case of a signup, retrieve the user information from the token + if (self.params.db && self.params.token) { + d = self.rpc("/auth_signup/retrieve", {dbname: self.params.db, token: self.params.token}) + .done(self.on_token_loaded) + .fail(self.on_token_failed); + } + return d; }, - }); - - - instance.auth_signup.Signup = instance.web.Widget.extend({ - template: 'auth_signup.signup', - init: function(parent, params) { - this.params = params; - return this._super(); + on_token_loaded: function(result) { + // set the name and login of user + this.selected_db = result.db; + this.on_db_loaded({db_list: [result.db]}); + this.$("form input[name=signup]").val(result.login ? [] : ["check_signup"]); + this.$("form input[name=name]").val(result.name); + this.$("form input[name=login]").val(result.login || result.email); + this.$("form input[name=password]").val(""); + this.$("form input[name=confirm_password]").val(""); + this.on_change_mode(); }, - start: function() { - var self = this; - this.$('input[name=password_confirmation]').keyup(function() { - var v = $(this).val(); - var $b = self.$('button'); - if (_.isEmpty(v) || self.$('input[name=password]').val() === v) { - $b.removeAttr('disabled'); + on_token_failed: function(result) { + // currently does nothing + }, + on_change_mode: function() { + // 'mode' has changed: regular login, sign up, reset password + var is_signup = this.$("input[name=signup]:checked").val(); + this.$(".oe_signup").toggleClass('oe_form_invisible', false && !is_signup); + return true; + }, + on_submit: function(ev) { + if (ev) { + ev.preventDefault(); + } + if (this.params.token || this.$("input[name=signup]:checked").val()) { + // signup user (or reset password) + var db = this.params.db; + var name = this.$("form input[name=name]").val(); + var login = this.$("form input[name=login]").val(); + var password = this.$("form input[name=password]").val(); + var confirm_password = this.$("form input[name=confirm_password]").val(); + + if (password && password === confirm_password) { + var params = { + dbname : db, + token: this.params.token, + name: name, + login: login, + password: password, + }; + var url = "/auth_signup/signup?" + $.param(params); + window.location = url; } else { - $b.attr('disabled', 'disabled'); + alert('Incorrect password; please retype your password.'); } - }); - - this.$('form').submit(function(ev) { - if(ev) { - ev.preventDefault(); - } - var params = { - dbname : self.params.dbname, - name: self.$('input[name=name]').val(), - login: self.$('input[name=email]').val(), - password: self.$('input[name=password]').val(), - }; - var url = "/auth_signup/signup?" + $.param(params); - window.location = url; - }); - return this._super(); - } + } else { + // regular login + this._super(ev); + } + }, }); - instance.web.client_actions.add("auth_signup.signup", "instance.auth_signup.Signup"); }; diff --git a/addons/auth_signup/static/src/xml/auth_signup.xml b/addons/auth_signup/static/src/xml/auth_signup.xml index c2eec846d15..73e26eb6ba8 100644 --- a/addons/auth_signup/static/src/xml/auth_signup.xml +++ b/addons/auth_signup/static/src/xml/auth_signup.xml @@ -1,28 +1,27 @@ - + - - -
  • - -
  • + + + + + + + +
  • Username
  • +
    + + + +
    -
    - - -
    -
    - Name =
    - Email =
    - Password =
    - Confirmation =
    - -
    -
    -
    - -
    From 597919467d4ecedddb2b3e14798c10bdf020f7ea Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 25 Sep 2012 14:45:57 +0200 Subject: [PATCH 032/275] [IMP] auth_signup: add css bzr revid: rco@openerp.com-20120925124557-2yka4yu0x7528atl --- addons/auth_signup/__openerp__.py | 1 + addons/auth_signup/static/src/css/Makefile | 3 +++ addons/auth_signup/static/src/css/base.css | 4 ++++ addons/auth_signup/static/src/css/base.sass | 7 +++++++ 4 files changed, 15 insertions(+) create mode 100644 addons/auth_signup/static/src/css/Makefile create mode 100644 addons/auth_signup/static/src/css/base.css create mode 100644 addons/auth_signup/static/src/css/base.sass diff --git a/addons/auth_signup/__openerp__.py b/addons/auth_signup/__openerp__.py index 9cfe89cdc1c..5bb3aab4ec0 100644 --- a/addons/auth_signup/__openerp__.py +++ b/addons/auth_signup/__openerp__.py @@ -36,5 +36,6 @@ Allow users to sign up. 'res_config.xml', ], 'js': ['static/src/js/auth_signup.js'], + 'css' : ['static/src/css/base.css'], 'qweb': ['static/src/xml/auth_signup.xml'], } diff --git a/addons/auth_signup/static/src/css/Makefile b/addons/auth_signup/static/src/css/Makefile new file mode 100644 index 00000000000..d6b4f4b2fc8 --- /dev/null +++ b/addons/auth_signup/static/src/css/Makefile @@ -0,0 +1,3 @@ +base.css: base.sass + sass --trace -t expanded base.sass base.css + diff --git a/addons/auth_signup/static/src/css/base.css b/addons/auth_signup/static/src/css/base.css new file mode 100644 index 00000000000..153f27bd129 --- /dev/null +++ b/addons/auth_signup/static/src/css/base.css @@ -0,0 +1,4 @@ +@charset "utf-8"; +.openerp .oe_login input[type="checkbox"] { + width: 21px !important; +} diff --git a/addons/auth_signup/static/src/css/base.sass b/addons/auth_signup/static/src/css/base.sass new file mode 100644 index 00000000000..87bdb623727 --- /dev/null +++ b/addons/auth_signup/static/src/css/base.sass @@ -0,0 +1,7 @@ +@charset "utf-8" + +.openerp + // Login form + .oe_login + input[type="checkbox"] + width: 21px !important From e184913f346f891fd74c2c6f1e0f048beb283fbb Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 25 Sep 2012 14:55:22 +0200 Subject: [PATCH 033/275] [FIX] auth_signup: store and retrieve config parameters that may be null bzr revid: rco@openerp.com-20120925125522-2t74fta15yfoesc1 --- addons/auth_signup/res_config.py | 11 +++++++---- addons/auth_signup/res_users.py | 8 +++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/addons/auth_signup/res_config.py b/addons/auth_signup/res_config.py index 36732d439f5..c69c01127f6 100644 --- a/addons/auth_signup/res_config.py +++ b/addons/auth_signup/res_config.py @@ -20,6 +20,7 @@ ############################################################################## from openerp.osv import osv, fields +from openerp.tools.safe_eval import safe_eval class base_config_settings(osv.TransientModel): _inherit = 'base.config.settings' @@ -31,13 +32,15 @@ class base_config_settings(osv.TransientModel): def get_default_auth_signup_template_user_id(self, cr, uid, fields, context=None): icp = self.pool.get('ir.config_parameter') + # we use safe_eval on the result, since the value of the parameter is a nonempty string return { - 'auth_signup_uninvited': icp.get_param(cr, uid, 'auth_signup.allow_uninvited', False), - 'auth_signup_template_user_id': icp.get_param(cr, uid, 'auth_signup.template_user_id', False), + 'auth_signup_uninvited': safe_eval(icp.get_param(cr, uid, 'auth_signup.allow_uninvited', 'False')), + 'auth_signup_template_user_id': safe_eval(icp.get_param(cr, uid, 'auth_signup.template_user_id', 'False')), } def set_auth_signup_template_user_id(self, cr, uid, ids, context=None): config = self.browse(cr, uid, ids[0], context=context) icp = self.pool.get('ir.config_parameter') - icp.set_param(cr, uid, 'auth_signup.allow_uninvited', config.auth_signup_uninvited) - icp.set_param(cr, uid, 'auth_signup.template_user_id', config.auth_signup_template_user_id.id) + # we store the repr of the values, since the value of the parameter is a required string + icp.set_param(cr, uid, 'auth_signup.allow_uninvited', repr(config.auth_signup_uninvited)) + icp.set_param(cr, uid, 'auth_signup.template_user_id', repr(config.auth_signup_template_user_id.id)) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 600ed9c000e..6956c8e2109 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -23,6 +23,7 @@ import openerp from openerp.osv import osv, fields from openerp import SUPERUSER_ID from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT +from openerp.tools.safe_eval import safe_eval import time import random @@ -152,10 +153,11 @@ class res_users(osv.Model): """ create a new user from the template user """ # check that uninvited users may sign up ir_config_parameter = self.pool.get('ir.config_parameter') - if token and not ir_config_parameter.get_param(cr, uid, 'auth_signup.allow_uninvited', False): - raise Exception('Signup is not allowed for uninvited users') + if not token: + if not safe_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.allow_uninvited', 'False')): + raise Exception('Signup is not allowed for uninvited users') - template_user_id = ir_config_parameter.get_param(cr, uid, 'auth_signup.template_user_id') + template_user_id = safe_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.template_user_id', 'False')) assert template_user_id, 'Signup: missing template user' values.update({'active': True, 'signup_token': False, 'signup_expiration': False}) return self.copy(cr, uid, template_user_id, values, context=context) From 9906a2bda10ca089fff55521f3252f4f8b178344 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 25 Sep 2012 16:34:33 +0200 Subject: [PATCH 034/275] [IMP] auth_signup: improve error message handling in web client bzr revid: rco@openerp.com-20120925143433-p4r2gl6t37dw0s17 --- addons/auth_signup/controllers/main.py | 8 +-- .../auth_signup/static/src/js/auth_signup.js | 61 ++++++++++++++----- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 343c660ff7d..6e053715c09 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -55,14 +55,10 @@ class Controller(openerpweb.Controller): credentials = res_users.signup(cr, SUPERUSER_ID, values, token) cr.commit() return login_and_redirect(req, *credentials) - except AttributeError: - # auth_signup is not installed - _logger.exception('attribute error when signup') - url = "/#action=auth_signup&error=NA" # Not Available - except Exception: + except Exception as e: # signup error _logger.exception('error when signup') - url = "/#action=auth_signup&error=UE" # Unexcpected Error + url = "/#action=login&error_message=%s" % werkzeug.urls.url_quote(e.message) return werkzeug.utils.redirect(url) # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js index bec32ce2803..9c90358d9e3 100644 --- a/addons/auth_signup/static/src/js/auth_signup.js +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -6,9 +6,21 @@ openerp.auth_signup = function(instance) { start: function() { var self = this; var d = this._super(); + // hide the signup fields in the case of a regular login self.on_change_mode() self.$("form input[name=signup]").click(self.on_change_mode); + + // if there is an error message, show it then forget it + if (self.params.error_message) { + this.$el.addClass('oe_login_invalid'); + this.$(".oe_login_error_message").text(self.params.error_message); + delete self.params.error_message; + } else { + this.$el.removeClass('oe_login_invalid'); + this.$(".oe_login_error_message").text("Invalid username or password"); + } + // in case of a signup, retrieve the user information from the token if (self.params.db && self.params.token) { d = self.rpc("/auth_signup/retrieve", {dbname: self.params.db, token: self.params.token}) @@ -28,8 +40,14 @@ openerp.auth_signup = function(instance) { this.$("form input[name=confirm_password]").val(""); this.on_change_mode(); }, - on_token_failed: function(result) { - // currently does nothing + on_token_failed: function(result, ev) { + if (ev) { + ev.preventDefault(); + } + this.$el.addClass('oe_login_invalid'); + this.$(".oe_login_error_message").text("Invalid signup token"); + delete this.params.db; + delete this.params.token; }, on_change_mode: function() { // 'mode' has changed: regular login, sign up, reset password @@ -43,25 +61,36 @@ openerp.auth_signup = function(instance) { } if (this.params.token || this.$("input[name=signup]:checked").val()) { // signup user (or reset password) - var db = this.params.db; + var db = this.$("form [name=db]").val(); var name = this.$("form input[name=name]").val(); var login = this.$("form input[name=login]").val(); var password = this.$("form input[name=password]").val(); var confirm_password = this.$("form input[name=confirm_password]").val(); - - if (password && password === confirm_password) { - var params = { - dbname : db, - token: this.params.token, - name: name, - login: login, - password: password, - }; - var url = "/auth_signup/signup?" + $.param(params); - window.location = url; - } else { - alert('Incorrect password; please retype your password.'); + if (!db) { + this.do_warn("Login", "No database selected !"); + return false; + } else if (!name) { + this.do_warn("Login", "Please enter a name.") + return false; + } else if (!login) { + this.do_warn("Login", "Please enter a username.") + return false; + } else if (!password || !confirm_password) { + this.do_warn("Login", "Please enter a password and confirm it.") + return false; + } else if (password !== confirm_password) { + this.do_warn("Login", "Passwords do not match; please retype them.") + return false; } + var params = { + dbname : db, + token: this.params.token || "", + name: name, + login: login, + password: password, + }; + var url = "/auth_signup/signup?" + $.param(params); + window.location = url; } else { // regular login this._super(ev); From a50dfa668d9de6fe8e054deb24366d99b21e3d96 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 26 Sep 2012 11:53:53 +0200 Subject: [PATCH 035/275] [IMP] auth_signup: improve error message handling with method show_error() bzr revid: rco@openerp.com-20120926095353-7cgcby7biohfx0i2 --- addons/auth_signup/static/src/js/auth_signup.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js index 9c90358d9e3..282221bc87e 100644 --- a/addons/auth_signup/static/src/js/auth_signup.js +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -11,14 +11,10 @@ openerp.auth_signup = function(instance) { self.on_change_mode() self.$("form input[name=signup]").click(self.on_change_mode); - // if there is an error message, show it then forget it + // if there is an error message in params, show it then forget it if (self.params.error_message) { - this.$el.addClass('oe_login_invalid'); - this.$(".oe_login_error_message").text(self.params.error_message); + this.show_error(self.params.error_message); delete self.params.error_message; - } else { - this.$el.removeClass('oe_login_invalid'); - this.$(".oe_login_error_message").text("Invalid username or password"); } // in case of a signup, retrieve the user information from the token @@ -44,8 +40,7 @@ openerp.auth_signup = function(instance) { if (ev) { ev.preventDefault(); } - this.$el.addClass('oe_login_invalid'); - this.$(".oe_login_error_message").text("Invalid signup token"); + this.show_error("Invalid signup token"); delete this.params.db; delete this.params.token; }, From 0605295602606a7e25f075f5e6bbfdd446e63dfc Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 26 Sep 2012 15:02:41 +0200 Subject: [PATCH 036/275] [IMP] auth_signup: improve web look-and-feel bzr revid: rco@openerp.com-20120926130241-wlzeyzrsr1xwjdcm --- addons/auth_signup/static/src/css/base.css | 10 ++++-- addons/auth_signup/static/src/css/base.sass | 12 +++++-- .../auth_signup/static/src/js/auth_signup.js | 32 +++++++++++-------- .../static/src/xml/auth_signup.xml | 31 +++++++++--------- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/addons/auth_signup/static/src/css/base.css b/addons/auth_signup/static/src/css/base.css index 153f27bd129..3f97e7a9301 100644 --- a/addons/auth_signup/static/src/css/base.css +++ b/addons/auth_signup/static/src/css/base.css @@ -1,4 +1,10 @@ @charset "utf-8"; -.openerp .oe_login input[type="checkbox"] { - width: 21px !important; +.openerp .oe_login .oe_signup_show { + display: none; +} +.openerp .oe_login_signup .oe_signup_show { + display: block !important; +} +.openerp .oe_login_signup .oe_signup_hide { + display: none; } diff --git a/addons/auth_signup/static/src/css/base.sass b/addons/auth_signup/static/src/css/base.sass index 87bdb623727..f97665d192c 100644 --- a/addons/auth_signup/static/src/css/base.sass +++ b/addons/auth_signup/static/src/css/base.sass @@ -1,7 +1,13 @@ @charset "utf-8" .openerp - // Login form + // Regular login form .oe_login - input[type="checkbox"] - width: 21px !important + .oe_signup_show + display: none + // Signup form + .oe_login_signup + .oe_signup_show + display: block !important + .oe_signup_hide + display: none diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js index 282221bc87e..927ee8de0c5 100644 --- a/addons/auth_signup/static/src/js/auth_signup.js +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -7,9 +7,14 @@ openerp.auth_signup = function(instance) { var self = this; var d = this._super(); - // hide the signup fields in the case of a regular login - self.on_change_mode() - self.$("form input[name=signup]").click(self.on_change_mode); + // to switch between the signup and regular login form + this.$('a.oe_signup_signup').click(function() { + self.$el.addClass("oe_login_signup"); + }); + this.$('a.oe_signup_back').click(function() { + self.$el.removeClass("oe_login_signup"); + delete self.params.token; + }); // if there is an error message in params, show it then forget it if (self.params.error_message) { @@ -26,15 +31,20 @@ openerp.auth_signup = function(instance) { return d; }, on_token_loaded: function(result) { - // set the name and login of user + // switch to signup mode + this.$el.addClass("oe_login_signup"); + // select the right the database this.selected_db = result.db; this.on_db_loaded({db_list: [result.db]}); - this.$("form input[name=signup]").val(result.login ? [] : ["check_signup"]); - this.$("form input[name=name]").val(result.name); - this.$("form input[name=login]").val(result.login || result.email); + // set the name and login of user + this.$("form input[name=name]").val(result.name).attr("readonly", "readonly"); + if (result.login) { + this.$("form input[name=login]").val(result.login).attr("readonly", "readonly"); + } else { + this.$("form input[name=login]").val(result.email); + } this.$("form input[name=password]").val(""); this.$("form input[name=confirm_password]").val(""); - this.on_change_mode(); }, on_token_failed: function(result, ev) { if (ev) { @@ -44,12 +54,6 @@ openerp.auth_signup = function(instance) { delete this.params.db; delete this.params.token; }, - on_change_mode: function() { - // 'mode' has changed: regular login, sign up, reset password - var is_signup = this.$("input[name=signup]:checked").val(); - this.$(".oe_signup").toggleClass('oe_form_invisible', false && !is_signup); - return true; - }, on_submit: function(ev) { if (ev) { ev.preventDefault(); diff --git a/addons/auth_signup/static/src/xml/auth_signup.xml b/addons/auth_signup/static/src/xml/auth_signup.xml index 73e26eb6ba8..e63bd5863b0 100644 --- a/addons/auth_signup/static/src/xml/auth_signup.xml +++ b/addons/auth_signup/static/src/xml/auth_signup.xml @@ -3,24 +3,25 @@ - - - - + + + -
  • Username
  • + +
    - - - + + + + + + + + + +
  • +
  • From 479dfb7ea079184c60dc39929c68ab37ada639e1 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 26 Sep 2012 17:04:59 +0200 Subject: [PATCH 037/275] [FIX] auth_signup: fix the creation of a user attached to a partner from a user template bzr revid: rco@openerp.com-20120926150459-9degade1ra9sk0ds --- addons/auth_signup/res_users.py | 44 +++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 6956c8e2109..4d5bdc28b8f 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -97,7 +97,7 @@ class res_partner(osv.Model): if partner.user_ids: return {'name': partner.name, 'login': partner.user_ids[0].login} else: - return {'name': partner.name, 'email': partner.email} + return {'name': partner.name, 'email': partner.email or ''} @@ -120,23 +120,19 @@ class res_users(osv.Model): # signup with a token: find the corresponding partner id res_partner = self.pool.get('res.partner') partner = res_partner._signup_retrieve_partner(cr, uid, token, raise_exception=True, context=None) + # invalidate signup token + partner.write({'signup_token': False, 'signup_expiration': False}) if partner.user_ids: - # user exists, modify its password and clear token - partner.user_ids[0].write({ - 'password': values['password'], - 'signup_token': False, - 'signup_expiration': False, - }) + # user exists, modify its password + partner.user_ids[0].write({'password': values['password']}) else: # user does not exist: sign up invited user self._signup_create_user(cr, uid, { - 'name': partner.name, 'login': values['login'], 'password': values['password'], 'email': values['login'], 'partner_id': partner.id, - }, token=token, context=context) - + }, context=context) return result # sign up an external user @@ -149,16 +145,28 @@ class res_users(osv.Model): }, context=context) return result - def _signup_create_user(self, cr, uid, values, token=None, context=None): + def _signup_create_user(self, cr, uid, values, context=None): """ create a new user from the template user """ - # check that uninvited users may sign up ir_config_parameter = self.pool.get('ir.config_parameter') - if not token: + template_user_id = safe_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.template_user_id', 'False')) + assert template_user_id and self.exists(cr, uid, template_user_id, context=context), 'Signup: invalid template user' + + values['active'] = True + if values.get('partner_id'): + # create a copy of the template user attached to values['partner_id'] + # note: we do not include 'partner_id' here, as copy() does not handle it correctly + safe_values = {'login': values['login'], 'password': values['password']} + user_id = self.copy(cr, uid, template_user_id, safe_values, context=context) + # problem: the res.partner part of the template user has been duplicated + # solution: unlink it, and replace it by values['partner_id'] + user = self.browse(cr, uid, user_id, context=context) + partner = user.partner_id + user.write(values) + partner.unlink() + else: + # check that uninvited users may sign up if not safe_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.allow_uninvited', 'False')): raise Exception('Signup is not allowed for uninvited users') + user_id = self.copy(cr, uid, template_user_id, values, context=context) - template_user_id = safe_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.template_user_id', 'False')) - assert template_user_id, 'Signup: missing template user' - values.update({'active': True, 'signup_token': False, 'signup_expiration': False}) - return self.copy(cr, uid, template_user_id, values, context=context) - + return user_id From b80d84aafc7f4d543247d22d445e71752272f925 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Thu, 27 Sep 2012 10:27:04 +0200 Subject: [PATCH 038/275] [IMP] auth_signup: remove temporary function field signup_url, and clean methods bzr revid: rco@openerp.com-20120927082704-wtuvir9tm2pgsvnq --- addons/auth_signup/res_users.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 4d5bdc28b8f..333686d4ca5 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -41,24 +41,21 @@ def now(): class res_partner(osv.Model): _inherit = 'res.partner' - def signup_get_url(self, cr, uid, partner_ids, name, arg, context=None): - """ determine a url for the partner_id to sign up """ - base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - res = {} - for partner in self.browse(cr, uid, partner_ids, context): - token = partner.signup_token - if not token: - token = self._signup_generate_token(cr, uid, partner.id, context=context) - res[partner.id] = urlparse.urljoin(base_url, '#action=login&db=%s&token=%s' % (cr.dbname, token)) - return res - _columns = { 'signup_token': fields.char(size=24, string='Signup Ticket'), 'signup_expiration': fields.datetime(string='Signup Expiration'), - 'signup_url': fields.function(signup_get_url, type='char', string='Signup URL'), } - def _signup_generate_token(self, cr, uid, partner_id, expiration=False, context=None): + def signup_get_url(self, cr, uid, partner_id, context=None): + """ determine a signup url for the given partner_id """ + base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + partner = self.browse(cr, uid, partner_id, context) + token = partner.signup_token + if not token: + token = self.signup_generate_token(cr, uid, partner.id, context=context) + return urlparse.urljoin(base_url, '#action=login&db=%s&token=%s' % (cr.dbname, token)) + + def signup_generate_token(self, cr, uid, partner_id, expiration=False, context=None): """ generate a new token for a partner, and return it :param partner_id: the partner id :param expiration: the expiration datetime of the token (string, optional) From 4f74d0aee15da72d386b03ba721b8ac67c4ea5a5 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 27 Sep 2012 14:19:54 +0200 Subject: [PATCH 039/275] [FIX] point_of_sale: show the cash_register_balance when we are in closing_control bzr revid: stw@openerp.com-20120927121954-1safkpgurh4nu9kc --- addons/point_of_sale/point_of_sale_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/point_of_sale/point_of_sale_view.xml b/addons/point_of_sale/point_of_sale_view.xml index c08695ee993..5b30ced93dd 100644 --- a/addons/point_of_sale/point_of_sale_view.xml +++ b/addons/point_of_sale/point_of_sale_view.xml @@ -934,7 +934,7 @@
    - + From ff211c375a2bc589082d6dd05484fd01c2068d6e Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 27 Sep 2012 14:20:22 +0200 Subject: [PATCH 040/275] [FIX] point_of_sale: return the session id in the context for the call of the pos.ui bzr revid: stw@openerp.com-20120927122022-fy2gx1z1xtkk14xt --- addons/point_of_sale/point_of_sale.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 590718b48f0..920e70b7b7d 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -439,10 +439,10 @@ class pos_session(osv.osv): context = {} if not ids: return {} - context.update({'session_id' : ids[0]}) + context.update({'active_id': ids[0]}) return { 'type' : 'ir.actions.client', - 'name' : 'Start Point Of Sale', + 'name' : _('Start Point Of Sale'), 'tag' : 'pos.ui', 'context' : context, } From 0f4529603c667f786f152859ad16e08ce9cc1fea Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 28 Sep 2012 10:52:59 +0200 Subject: [PATCH 041/275] [FIX] auth_signup: change test to determine when signing in bzr revid: rco@openerp.com-20120928085259-cb51yq7e7mivxsw3 --- addons/auth_signup/static/src/js/auth_signup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js index 927ee8de0c5..9bc775c8355 100644 --- a/addons/auth_signup/static/src/js/auth_signup.js +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -58,7 +58,7 @@ openerp.auth_signup = function(instance) { if (ev) { ev.preventDefault(); } - if (this.params.token || this.$("input[name=signup]:checked").val()) { + if (this.$el.hasClass("oe_login_signup")) { // signup user (or reset password) var db = this.$("form [name=db]").val(); var name = this.$("form input[name=name]").val(); From bf5395ab3dc4dfe1a26faa7f9d490a46c80271f7 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 28 Sep 2012 10:58:43 +0200 Subject: [PATCH 042/275] [IMP] auth_signup: add function fields signup_valid, signup_url, and method prepare_signup bzr revid: rco@openerp.com-20120928085843-0erxrzva9lk5tqfh --- addons/auth_signup/res_users.py | 57 +++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 333686d4ca5..0624b25b357 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -41,32 +41,49 @@ def now(): class res_partner(osv.Model): _inherit = 'res.partner' + def _get_signup_valid(self, cr, uid, ids, name, arg, context=None): + dt = now() + res = {} + for partner in self.browse(cr, uid, ids, context): + res[partner.id] = bool(partner.signup_token) and (partner.signup_expiration or '') <= dt + return res + + def _get_signup_url(self, cr, uid, ids, name, arg, context=None): + """ determine a signup url for a given partner """ + base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + template_url = '#action=login&db=%s&token=%s' + + # if required, make sure that every partner has a valid signup token + if context and context.get('signup_valid'): + self.signup_prepare(cr, uid, ids, context=context) + + res = dict.fromkeys(ids, False) + for partner in self.browse(cr, uid, ids, context): + if partner.signup_token: + res[partner.id] = urlparse.urljoin(base_url, template_url % (cr.dbname, partner.signup_token)) + return res + _columns = { - 'signup_token': fields.char(size=24, string='Signup Ticket'), + 'signup_token': fields.char(size=24, string='Signup Token'), 'signup_expiration': fields.datetime(string='Signup Expiration'), + 'signup_valid': fields.function(_get_signup_valid, type='boolean', string='Signup Token is Valid'), + 'signup_url': fields.function(_get_signup_url, type='char', string='Signup URL'), } - def signup_get_url(self, cr, uid, partner_id, context=None): - """ determine a signup url for the given partner_id """ - base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - partner = self.browse(cr, uid, partner_id, context) - token = partner.signup_token - if not token: - token = self.signup_generate_token(cr, uid, partner.id, context=context) - return urlparse.urljoin(base_url, '#action=login&db=%s&token=%s' % (cr.dbname, token)) + def action_signup_prepare(self, cr, uid, ids, context=None): + return self.signup_prepare(cr, uid, ids, context=context) - def signup_generate_token(self, cr, uid, partner_id, expiration=False, context=None): - """ generate a new token for a partner, and return it - :param partner_id: the partner id + def signup_prepare(self, cr, uid, ids, expiration=False, context=None): + """ generate a new token for the partners with the given validity, if necessary :param expiration: the expiration datetime of the token (string, optional) - :return: the token (string) """ - # generate a unique token - token = random_token() - while self._signup_retrieve_partner(cr, uid, token, context=context): - token = random_token() - self.write(cr, uid, [partner_id], {'signup_token': token, 'signup_expiration': expiration}, context=context) - return token + for partner in self.browse(cr, uid, ids, context): + if expiration or not partner.signup_valid: + token = random_token() + while self._signup_retrieve_partner(cr, uid, token, context=context): + token = random_token() + partner.write({'signup_token': token, 'signup_expiration': expiration}) + return True def _signup_retrieve_partner(self, cr, uid, token, raise_exception=False, context=None): """ find the partner corresponding to a token, and check its validity @@ -79,7 +96,7 @@ class res_partner(osv.Model): raise Exception("Signup token '%s' is not valid" % token) return False partner = self.browse(cr, uid, partner_ids[0], context) - if partner.signup_expiration and partner.signup_expiration < now(): + if not partner.signup_valid: if raise_exception: raise Exception("Signup token '%s' is no longer valid" % token) return False From 722bb4461d4ca1d27099bed8293a5ca8d76e2b92 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 28 Sep 2012 11:43:55 +0200 Subject: [PATCH 043/275] [ADD] ir.translation: add separate view file - missing in previous commits bzr revid: odo@openerp.com-20120928094355-rjx12zjju09tmyew --- .../addons/base/ir/ir_translation_view.xml | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 openerp/addons/base/ir/ir_translation_view.xml diff --git a/openerp/addons/base/ir/ir_translation_view.xml b/openerp/addons/base/ir/ir_translation_view.xml new file mode 100644 index 00000000000..70ccb902cc9 --- /dev/null +++ b/openerp/addons/base/ir/ir_translation_view.xml @@ -0,0 +1,79 @@ + + + + + Translations + ir.translation + + + + + + + + + + + + + + Translations + ir.translation + +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + Translations + ir.translation + + + + + + + + + + + + + Translated Terms + ir.translation + form + + + + + +
    +
    \ No newline at end of file From a6ef1d4a428674b71710c84590dcccc1b89f82b4 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Fri, 28 Sep 2012 11:50:35 +0200 Subject: [PATCH 044/275] [IMP] mrp: cleaning of stock move name bzr revid: qdp-launchpad@openerp.com-20120928095035-w1g06od25auo52ev --- addons/mrp/mrp.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 049c7c712fb..c14b852d08e 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -902,12 +902,11 @@ class mrp_production(osv.osv): # Internal shipment is created for Stockable and Consumer Products if production_line.product_id.type not in ('product', 'consu'): return False - move_name = _('PROD: %s') % production.name source_location_id = production.location_src_id.id if not destination_location_id: destination_location_id = source_location_id return stock_move.create(cr, uid, { - 'name': move_name, + 'name': production.name, 'picking_id': shipment_id, 'product_id': production_line.product_id.id, 'product_qty': production_line.product_qty, @@ -957,9 +956,8 @@ class mrp_production(osv.osv): stock_move = self.pool.get('stock.move') source_location_id = production.product_id.product_tmpl_id.property_stock_production.id destination_location_id = production.location_dest_id.id - move_name = _('PROD: %s') + production.name data = { - 'name': move_name, + 'name': production.name, 'date': production.date_planned, 'product_id': production.product_id.id, 'product_qty': production.product_qty, @@ -982,12 +980,11 @@ class mrp_production(osv.osv): # Internal shipment is created for Stockable and Consumer Products if production_line.product_id.type not in ('product', 'consu'): return False - move_name = _('PROD: %s') % production.name destination_location_id = production.product_id.product_tmpl_id.property_stock_production.id if not source_location_id: source_location_id = production.location_src_id.id move_id = stock_move.create(cr, uid, { - 'name': move_name, + 'name': production.name, 'date': production.date_planned, 'product_id': production_line.product_id.id, 'product_qty': production_line.product_qty, From 20bf037ea40d38f600a7166ea948b81840c613a0 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Fri, 28 Sep 2012 11:54:58 +0200 Subject: [PATCH 045/275] [IMP] sale: added a test to verify the the product onchange in sale order line was correctly triggered bzr revid: qdp-launchpad@openerp.com-20120928095458-vjwd4xt0nun8lfjx --- addons/sale/test/sale_order_demo.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/sale/test/sale_order_demo.yml b/addons/sale/test/sale_order_demo.yml index 05109efbea2..5b1c08bb5e1 100644 --- a/addons/sale/test/sale_order_demo.yml +++ b/addons/sale/test/sale_order_demo.yml @@ -7,8 +7,12 @@ payment_term: account.account_payment_term - !record {model: sale.order.line, id: line}: - name : 'LCD Monitor' order_id: sale_order_test1 product_id: product.product_product_7 - price_unit: 190.50 product_uom_qty: 8 +- + I verify that the onchange was correctly triggered +- + !assert {model: sale.order.line, id: sale.line, string: The onchange function of product was not correctly triggered}: + - l.name == '17” LCD Monitor' + - l.price_unit == 1350.0 From 6251b57b39ac2a01d907f1f5f6fccf13a0319830 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Fri, 28 Sep 2012 12:15:31 +0200 Subject: [PATCH 046/275] [IMP] sale_stock: added a test to verify the the product onchange in sale order line was correctly triggered bzr revid: qdp-launchpad@openerp.com-20120928101531-sw1r2d5tc034ie23 --- addons/sale_stock/__openerp__.py | 1 + addons/sale_stock/sale_stock.py | 2 +- addons/sale_stock/sale_stock_view.xml | 6 ++--- .../sale_stock/test/sale_order_onchange.yml | 24 +++++++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 addons/sale_stock/test/sale_order_onchange.yml diff --git a/addons/sale_stock/__openerp__.py b/addons/sale_stock/__openerp__.py index 2a670000581..10773b44a3f 100644 --- a/addons/sale_stock/__openerp__.py +++ b/addons/sale_stock/__openerp__.py @@ -61,6 +61,7 @@ You can choose flexible invoicing methods: 'test': ['test/cancel_order_sale_stock.yml', 'test/picking_order_policy.yml', 'test/prepaid_order_policy.yml', + 'test/sale_order_onchange.yml', ], 'installable': True, 'auto_install': True, diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index a48b766f3bb..aea39590152 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -625,7 +625,7 @@ class sale_order_line(osv.osv): uom = False if not uom2: uom2 = product_obj.uom_id - + compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding) if (product_obj.type=='product') and int(compare_qty) == -1 \ and (product_obj.procure_method=='make_to_stock'): diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml index 7efb2849a52..09a8cd51af8 100644 --- a/addons/sale_stock/sale_stock_view.xml +++ b/addons/sale_stock/sale_stock_view.xml @@ -1,7 +1,7 @@ - + sale.shop.inherit.form sale.shop @@ -13,7 +13,7 @@ - + sale.shop.sale.stock sale.shop @@ -41,7 +41,7 @@ -
  • - +
  • Reset password
  • + From 5763e40506f9f155e09b2fccbc7ffa4247b02b9b Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 1 Oct 2012 17:14:21 +0200 Subject: [PATCH 071/275] [IMP] orm: remove trailing spaces bzr revid: chs@openerp.com-20121001151421-vdfkzuf864rz8q20 --- openerp/osv/orm.py | 60 +++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 47afda39e5e..8b78621db03 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -372,7 +372,7 @@ class browse_record(object): else: return attr else: - error_msg = "Field '%s' does not exist in object '%s'" % (name, self) + error_msg = "Field '%s' does not exist in object '%s'" % (name, self) self.__logger.warning(error_msg) if self.__logger.isEnabledFor(logging.DEBUG): self.__logger.debug(''.join(traceback.format_stack())) @@ -712,7 +712,7 @@ class BaseModel(object): def log(self, cr, uid, id, message, secondary=False, context=None): return _logger.warning("log() is deprecated. Please use OpenChatter notification system instead of the res.log mechanism.") - + def view_init(self, cr, uid, fields_list, context=None): """Override this method to do specific things when a view on the object is opened.""" pass @@ -902,7 +902,7 @@ class BaseModel(object): # If new class defines a constraint with # same function name, we let it override # the old one. - + new[c2] = c exist = True break @@ -1596,7 +1596,7 @@ class BaseModel(object): def user_has_groups(self, cr, uid, groups, context=None): """Return true if the user is at least member of one of the groups in groups_str. Typically used to resolve ``groups`` attribute - in view and model definitions. + in view and model definitions. :param str groups: comma-separated list of fully-qualified group external IDs, e.g.: ``base.group_user,base.group_system`` @@ -1639,7 +1639,7 @@ class BaseModel(object): the field should be completely removed from the view, as it is completely unavailable for non-members - :return: True if field should be included in the result of fields_view_get + :return: True if field should be included in the result of fields_view_get """ if node.tag == 'field' and node.get('name') in self._all_columns: column = self._all_columns[node.get('name')].column @@ -1914,7 +1914,7 @@ class BaseModel(object): def _get_default_calendar_view(self, cr, user, context=None): """ Generates a default calendar view by trying to infer calendar fields from a number of pre-set attribute names - + :param cr: database cursor :param int user: user id :param dict context: connection context @@ -1993,7 +1993,7 @@ class BaseModel(object): def raise_view_error(error_msg, child_view_id): view, child_view = self.pool.get('ir.ui.view').browse(cr, user, [view_id, child_view_id], context) - error_msg = error_msg % {'parent_xml_id': view.xml_id} + error_msg = error_msg % {'parent_xml_id': view.xml_id} raise AttributeError("View definition error for inherited view '%s' on model '%s': %s" % (child_view.xml_id, self._name, error_msg)) @@ -2029,7 +2029,7 @@ class BaseModel(object): if all(node.get(attr) == spec.get(attr) \ for attr in spec.attrib if attr not in ('position','version')): - # Version spec should match parent's root element's version + # Version spec should match parent's root element's version if spec.get('version') and spec.get('version') != source.get('version'): return None return node @@ -2103,7 +2103,7 @@ class BaseModel(object): raise_view_error("Mismatching view API version for element '%s': %r vs %r in parent view '%%(parent_xml_id)s'" % \ (tag, spec.get('version'), source.get('version')), inherit_id) raise_view_error("Element '%s' not found in parent view '%%(parent_xml_id)s'" % tag, inherit_id) - + return source def apply_view_inheritance(cr, user, source, inherit_id): @@ -2318,7 +2318,7 @@ class BaseModel(object): or ``'='``. :param int limit: optional max number of records to return :rtype: list - :return: list of pairs ``(id,text_repr)`` for all matching records. + :return: list of pairs ``(id,text_repr)`` for all matching records. """ return self._name_search(cr, user, name, args, operator, context, limit) @@ -2448,7 +2448,7 @@ class BaseModel(object): # This is useful to implement kanban views for instance, where all columns # should be displayed even if they don't contain any record. - # Grab the list of all groups that should be displayed, including all present groups + # Grab the list of all groups that should be displayed, including all present groups present_group_ids = [x[groupby][0] for x in read_group_result if x[groupby]] all_groups,folded = self._group_by_full[groupby](self, cr, uid, present_group_ids, domain, read_group_order=read_group_order, @@ -2824,28 +2824,28 @@ class BaseModel(object): def _m2o_fix_foreign_key(self, cr, source_table, source_field, dest_model, ondelete): # Find FK constraint(s) currently established for the m2o field, - # and see whether they are stale or not + # and see whether they are stale or not cr.execute("""SELECT confdeltype as ondelete_rule, conname as constraint_name, cl2.relname as foreign_table FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, pg_attribute as att1, pg_attribute as att2 - WHERE con.conrelid = cl1.oid - AND cl1.relname = %s - AND con.confrelid = cl2.oid - AND array_lower(con.conkey, 1) = 1 - AND con.conkey[1] = att1.attnum - AND att1.attrelid = cl1.oid - AND att1.attname = %s - AND array_lower(con.confkey, 1) = 1 - AND con.confkey[1] = att2.attnum - AND att2.attrelid = cl2.oid - AND att2.attname = %s + WHERE con.conrelid = cl1.oid + AND cl1.relname = %s + AND con.confrelid = cl2.oid + AND array_lower(con.conkey, 1) = 1 + AND con.conkey[1] = att1.attnum + AND att1.attrelid = cl1.oid + AND att1.attname = %s + AND array_lower(con.confkey, 1) = 1 + AND con.confkey[1] = att2.attnum + AND att2.attrelid = cl2.oid + AND att2.attname = %s AND con.contype = 'f'""", (source_table, source_field, 'id')) constraints = cr.dictfetchall() if constraints: if len(constraints) == 1: # Is it the right constraint? - cons, = constraints + cons, = constraints if cons['ondelete_rule'] != POSTGRES_CONFDELTYPES.get((ondelete or 'set null').upper(), 'a')\ or cons['foreign_table'] != dest_model._table: _schema.debug("Table '%s': dropping obsolete FK constraint: '%s'", @@ -3218,7 +3218,7 @@ class BaseModel(object): def _o2m_raise_on_missing_reference(self, cr, f): # TODO this check should be a method on fields.one2many. - + other = self.pool.get(f._obj) if other: # TODO the condition could use fields_get_keys(). @@ -3735,7 +3735,7 @@ class BaseModel(object): the length of `ids`, and raise an appropriate exception if it does not. """ if cr.rowcount != len(ids): - # Attempt to distinguish record rule restriction vs deleted records, + # Attempt to distinguish record rule restriction vs deleted records, # to provide a more specific error message cr.execute('SELECT id FROM ' + self._table + ' WHERE id IN %s', (tuple(ids),)) if cr.rowcount != len(ids): @@ -3790,13 +3790,13 @@ class BaseModel(object): self._check_record_rules_result_count(cr, uid, sub_ids, operation, context=context) def _workflow_trigger(self, cr, uid, ids, trigger, context=None): - """Call given workflow trigger as a result of a CRUD operation""" + """Call given workflow trigger as a result of a CRUD operation""" wf_service = netsvc.LocalService("workflow") for res_id in ids: getattr(wf_service, trigger)(uid, self._name, res_id, cr) def _workflow_signal(self, cr, uid, ids, signal, context=None): - """Send given workflow signal""" + """Send given workflow signal""" wf_service = netsvc.LocalService("workflow") for res_id in ids: wf_service.trg_validate(uid, self._name, res_id, signal, cr) @@ -3827,7 +3827,7 @@ class BaseModel(object): self.check_access_rights(cr, uid, 'unlink') ir_property = self.pool.get('ir.property') - + # Check if the records are used as default properties. domain = [('res_id', '=', False), ('value_reference', 'in', ['%s,%s' % (self._name, i) for i in ids]), @@ -4955,7 +4955,7 @@ class BaseModel(object): :return: map of ids to their fully qualified XML ID, defaulting to an empty string when there's none - (to be usable as a function field), + (to be usable as a function field), e.g.:: { 'id': 'module.ext_id', From 9d8ea41d450f738afe77c47b1f86c212e3132e33 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 1 Oct 2012 17:19:17 +0200 Subject: [PATCH 072/275] wip bzr revid: nicolas.vanhoren@openerp.com-20121001151917-o095dj2m8aypm3da --- addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml | 1 - addons/hr_timesheet_sheet/static/src/js/timesheet.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml index 6ff3e5c43e0..78fc997d15e 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml @@ -73,7 +73,6 @@ - This is a test. diff --git a/addons/hr_timesheet_sheet/static/src/js/timesheet.js b/addons/hr_timesheet_sheet/static/src/js/timesheet.js index 1cde7a80a90..9b186443217 100644 --- a/addons/hr_timesheet_sheet/static/src/js/timesheet.js +++ b/addons/hr_timesheet_sheet/static/src/js/timesheet.js @@ -21,7 +21,7 @@ openerp.hr_timesheet_sheet = function(instance) { this.on("change:sheets", this, this.update_sheets); this.res_o2m_drop = new instance.web.DropMisordered(); this.render_drop = new instance.web.DropMisordered(); - this.description_line = _t("No description"); + this.description_line = _t("/"); }, query_sheets: function() { var self = this; From b7e5519b4c0b4c212ef1268a09dacdfb26b704d8 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 1 Oct 2012 17:37:53 +0200 Subject: [PATCH 073/275] [FIX] orm: handle fields.char() with not size correctly bzr revid: chs@openerp.com-20121001153753-um68vpz1caojm17r --- openerp/osv/orm.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 8b78621db03..ec995c6a8cc 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2967,14 +2967,14 @@ class BaseModel(object): ('numeric', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), ('float8', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), ] - if f_pg_type == 'varchar' and f._type == 'char' and f_pg_size < f.size: + if f_pg_type == 'varchar' and f._type == 'char' and ((f.size is None and f_pg_size) or f_pg_size < f.size): cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, pg_varchar(f.size))) cr.execute('UPDATE "%s" SET "%s"=temp_change_size::%s' % (self._table, k, pg_varchar(f.size))) cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,)) cr.commit() _schema.debug("Table '%s': column '%s' (type varchar) changed size from %s to %s", - self._table, k, f_pg_size, f.size) + self._table, k, f_pg_size or 'unlimited', f.size or 'unlimited') for c in casts: if (f_pg_type==c[0]) and (f._type==c[1]): if f_pg_type != f_obj_type: @@ -3207,8 +3207,7 @@ class BaseModel(object): # attlen is the number of bytes necessary to represent the type when # the type has a fixed size. If the type has a varying size attlen is # -1 and atttypmod is the size limit + 4, or -1 if there is no limit. - # Thus the query can return a negative size for a unlimited varchar. - cr.execute("SELECT c.relname,a.attname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,t.typname,CASE WHEN a.attlen=-1 THEN a.atttypmod-4 ELSE a.attlen END as size " \ + cr.execute("SELECT c.relname,a.attname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,t.typname,CASE WHEN a.attlen=-1 THEN (CASE WHEN a.atttypmod=-1 THEN 0 ELSE a.atttypmod-4 END) ELSE a.attlen END as size " \ "FROM pg_class c,pg_attribute a,pg_type t " \ "WHERE c.relname=%s " \ "AND c.oid=a.attrelid " \ From 7812c73354d9ca924c109b3c6331bfbe1986f388 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 1 Oct 2012 17:38:06 +0200 Subject: [PATCH 074/275] [IMP] yaml processing: improved previous patch by replacing the old parameter view with the result of fields_view_get() directly, to avoid having an extra parameter a bit useless bzr revid: qdp-launchpad@openerp.com-20121001153806-k40ly5vdzh1v3hv3 --- openerp/tools/yaml_import.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/openerp/tools/yaml_import.py b/openerp/tools/yaml_import.py index f88f253c0f2..a5de5873908 100644 --- a/openerp/tools/yaml_import.py +++ b/openerp/tools/yaml_import.py @@ -313,14 +313,13 @@ class YamlInterpreter(object): #context = self.get_context(record, self.eval_context) #TOFIX: record.context like {'withoutemployee':True} should pass from self.eval_context. example: test_project.yml in project module context = record.context - fields_view_get_result = False + view_info = False if view_id: varg = view_id if view_id is True: varg = False - fields_view_get_result = model.fields_view_get(self.cr, SUPERUSER_ID, varg, 'form', context) - view_id = etree.fromstring(fields_view_get_result['arch'].encode('utf-8')) + view_info = model.fields_view_get(self.cr, SUPERUSER_ID, varg, 'form', context) - record_dict = self._create_record(model, fields, view_id, default=default, fields_view_get=fields_view_get_result) + record_dict = self._create_record(model, fields, view_info, default=default) _logger.debug("RECORD_DICT %s" % record_dict) id = self.pool.get('ir.model.data')._update(self.cr, SUPERUSER_ID, record.model, \ self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode, context=context) @@ -328,7 +327,8 @@ class YamlInterpreter(object): if config.get('import_partial'): self.cr.commit() - def _create_record(self, model, fields, view=False, parent={}, default=True, fields_view_get=None): + def _create_record(self, model, fields, view_info=False, parent={}, default=True): + view = view_info and etree.fromstring(view_info['arch'].encode('utf-8')) or False if view is not False: defaults = default and model._add_missing_default_values(self.cr, SUPERUSER_ID, {}, context=self.context) or {} fg = model.fields_get(self.cr, SUPERUSER_ID, context=self.context) @@ -357,17 +357,15 @@ class YamlInterpreter(object): field_name = el.attrib['name'] assert field_name in fg, "The field '%s' is defined in the form view but not on the object '%s'!" % (field_name, model._name) if field_name in fields: - view2 = None + one2many_form_view = None # if the form view is not inline, we call fields_view_get if (view is not False) and (fg[field_name]['type']=='one2many'): - tmp = fields_view_get['fields'][field_name]['views'] - if tmp.has_key('form'): - view2 = tmp.get('form') - if not view2: - view2 = self.pool.get(fg[field_name]['relation']).fields_view_get(self.cr, SUPERUSER_ID, False, 'form', self.context) - view2 = etree.fromstring(view2['arch'].encode('utf-8')) + one2many_form_view = view_info['fields'][field_name]['views'].get('form') + if not one2many_form_view: + one2many_form_view = self.pool.get(fg[field_name]['relation']).fields_view_get(self.cr, SUPERUSER_ID, False, 'form', self.context) - field_value = self._eval_field(model, field_name, fields[field_name], view2, parent=record_dict, default=default, fields_view_get=fields_view_get) + view_info = one2many_form_view or view_info + field_value = self._eval_field(model, field_name, fields[field_name], view_info, parent=record_dict, default=default) record_dict[field_name] = field_value #if (field_name in defaults) and defaults[field_name] == field_value: # print '*** You can remove these lines:', field_name, field_value @@ -412,7 +410,7 @@ class YamlInterpreter(object): for field_name, expression in fields.items(): if field_name in record_dict: continue - field_value = self._eval_field(model, field_name, expression, default=False, fields_view_get=fields_view_get) + field_value = self._eval_field(model, field_name, expression, default=False) record_dict[field_name] = field_value return record_dict @@ -443,7 +441,7 @@ class YamlInterpreter(object): def process_eval(self, node): return eval(node.expression, self.eval_context) - def _eval_field(self, model, field_name, expression, view=False, parent={}, default=True, fields_view_get=None): + def _eval_field(self, model, field_name, expression, view_info=False, parent={}, default=True): # TODO this should be refactored as something like model.get_field() in bin/osv if field_name in model._columns: column = model._columns[field_name] @@ -464,7 +462,7 @@ class YamlInterpreter(object): value = self.get_id(expression) elif column._type == "one2many": other_model = self.get_model(column._obj) - value = [(0, 0, self._create_record(other_model, fields, view, parent, default=default, fields_view_get=fields_view_get)) for fields in expression] + value = [(0, 0, self._create_record(other_model, fields, view_info, parent, default=default)) for fields in expression] elif column._type == "many2many": ids = [self.get_id(xml_id) for xml_id in expression] value = [(6, 0, ids)] From 4d35720a57190f21edac89d1755d3d990c79fd83 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 1 Oct 2012 17:44:49 +0200 Subject: [PATCH 075/275] [IMP] translation import/export: more cleanup bzr revid: odo@openerp.com-20121001154449-146dte5i8ge1y1pj --- .../module/wizard/base_export_language.py | 16 ++------ .../wizard/base_export_language_view.xml | 4 +- .../module/wizard/base_import_language.py | 39 ++++++++----------- .../wizard/base_import_language_view.xml | 2 +- 4 files changed, 23 insertions(+), 38 deletions(-) diff --git a/openerp/addons/base/module/wizard/base_export_language.py b/openerp/addons/base/module/wizard/base_export_language.py index 80cb2d70292..95f1d85bf6c 100644 --- a/openerp/addons/base/module/wizard/base_export_language.py +++ b/openerp/addons/base/module/wizard/base_export_language.py @@ -45,7 +45,6 @@ class base_language_export(osv.osv_memory): ('tgz', 'TGZ Archive')], 'File Format', required=True), 'modules': fields.many2many('ir.module.module', 'rel_modules_langexport', 'wiz_id', 'module_id', 'Modules To Export', domain=[('state','=','installed')]), 'data': fields.binary('File', readonly=True), - 'advice': fields.text('Note', readonly=True), 'state': fields.selection([('choose', 'choose'), # choose language ('get', 'get')]) # get the file } @@ -62,18 +61,10 @@ class base_language_export(osv.osv_memory): mods = map(lambda m: m.name, this.modules) or ['all'] mods.sort() buf = cStringIO.StringIO() - tools.trans_export(this.lang, mods, buf, this.format, cr) - if this.format == 'csv': - this.advice = _("Save this document as a .CSV file and open it with your favourite spreadsheet software. The file encoding is UTF-8. You have to translate the last column before reimporting it.") - elif this.format == 'po': - if not lang: - this.format = 'pot' - this.advice = _("Save this document as a %s file and edit it with a PO editor or a text editor. The file encoding is UTF-8.") % ('.'+this.format,) - elif this.format == 'tgz': - this.advice = _('Save this document as a .tgz file. This archive contains UTF-8 %s files and may be uploaded to launchpad.') - filename = _('new') + tools.trans_export(lang, mods, buf, this.format, cr) + filename = 'new' if lang: - filename = get_iso_codes(this.lang) + filename = get_iso_codes(lang) elif len(mods) == 1: filename = mods[0] this.name = "%s.%s" % (filename, this.format) @@ -81,7 +72,6 @@ class base_language_export(osv.osv_memory): buf.close() self.write(cr, uid, ids, {'state': 'get', 'data': out, - 'advice': this.advice, 'name':this.name}, context=context) return True diff --git a/openerp/addons/base/module/wizard/base_export_language_view.xml b/openerp/addons/base/module/wizard/base_export_language_view.xml index 2e50b3bed8f..cbf7104f957 100644 --- a/openerp/addons/base/module/wizard/base_export_language_view.xml +++ b/openerp/addons/base/module/wizard/base_export_language_view.xml @@ -2,10 +2,10 @@ - Translations Export + Export Translations base.language.export -
    + diff --git a/openerp/addons/base/module/wizard/base_import_language.py b/openerp/addons/base/module/wizard/base_import_language.py index 6f09dc43d90..9c36c9d7c54 100644 --- a/openerp/addons/base/module/wizard/base_import_language.py +++ b/openerp/addons/base/module/wizard/base_import_language.py @@ -30,8 +30,8 @@ class base_language_import(osv.osv_memory): _name = "base.language.import" _description = "Language Import" _columns = { - 'name': fields.char('Language Name',size=64 , required=True), - 'code': fields.char('Code (eg:en__US)',size=5 , required=True), + 'name': fields.char('Language Name', size=64 , required=True), + 'code': fields.char('ISO Code', size=5, help="ISO Language and Country code, e.g. en_US", required=True), 'data': fields.binary('File', required=True), 'overwrite': fields.boolean('Overwrite Existing Terms', help="If you enable this option, existing translations (including custom ones) " @@ -39,30 +39,25 @@ class base_language_import(osv.osv_memory): } def import_lang(self, cr, uid, ids, context=None): - """ - Import Language - @param cr: the current row, from the database cursor. - @param uid: the current user’s ID for security checks. - @param ids: the ID or list of IDs - @param context: A standard dictionary - """ if context is None: context = {} - import_data = self.browse(cr, uid, ids)[0] - if import_data.overwrite: + this = self.browse(cr, uid, ids[0]) + if this.overwrite: context.update(overwrite=True) fileobj = TemporaryFile('w+') - fileobj.write(base64.decodestring(import_data.data)) - - # now we determine the file format - fileobj.seek(0) - first_line = fileobj.readline().strip().replace('"', '').replace(' ', '') - fileformat = first_line.endswith("type,name,res_id,src,value") and 'csv' or 'po' - fileobj.seek(0) - - tools.trans_load_data(cr, fileobj, fileformat, import_data.code, lang_name=import_data.name, context=context) - fileobj.close() - return {} + try: + fileobj.write(base64.decodestring(this.data)) + + # now we determine the file format + fileobj.seek(0) + first_line = fileobj.readline().strip().replace('"', '').replace(' ', '') + fileformat = first_line.endswith("type,name,res_id,src,value") and 'csv' or 'po' + fileobj.seek(0) + + tools.trans_load_data(cr, fileobj, fileformat, this.code, lang_name=this.name, context=context) + finally: + fileobj.close() + return True # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/module/wizard/base_import_language_view.xml b/openerp/addons/base/module/wizard/base_import_language_view.xml index 727de4e381b..5e2aada7766 100644 --- a/openerp/addons/base/module/wizard/base_import_language_view.xml +++ b/openerp/addons/base/module/wizard/base_import_language_view.xml @@ -8,7 +8,7 @@ - + From 7c1339928b1e69a17e84c66bd366144dec6fed8e Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 1 Oct 2012 17:46:05 +0200 Subject: [PATCH 076/275] Removed day by day bzr revid: nicolas.vanhoren@openerp.com-20121001154605-nemay3pze49ejjld --- .../hr_timesheet_sheet/hr_timesheet_sheet.py | 157 +----------------- .../hr_timesheet_sheet_view.xml | 17 +- 2 files changed, 8 insertions(+), 166 deletions(-) diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py index 13c11cf72c7..1c29a4e736f 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py @@ -27,80 +27,6 @@ from osv import fields, osv from tools.translate import _ import netsvc -class one2many_mod2(fields.one2many): - def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): - if context is None: - context = {} - - if values is None: - values = {} - - # res6 = {id: date_current, ...} - res6 = dict([(rec['id'], rec['date_current']) - for rec in obj.read(cr, user, ids, ['date_current'], context=context)]) - - dom = [] - for c, id in enumerate(ids): - if id in res6: - if c: # skip first - dom.insert(0 ,'|') - dom.append('&') - dom.append('&') - dom.append(('name', '>=', res6[id])) - dom.append(('name', '<=', res6[id])) - dom.append(('sheet_id', '=', id)) - - ids2 = obj.pool.get(self._obj).search(cr, user, dom, limit=self._limit) - - res = {} - for i in ids: - res[i] = [] - - for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_read'): - if r[self._fields_id]: - res[r[self._fields_id][0]].append(r['id']) - return res - - def set(self, cr, obj, id, field, values, user=None, context=None): - if context is None: - context = {} - - context = context.copy() - context['sheet_id'] = id - return super(one2many_mod2, self).set(cr, obj, id, field, values, user=user, context=context) - - -class one2many_mod(fields.one2many): - def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): - if context is None: - context = {} - - if values is None: - values = {} - - - res5 = obj.read(cr, user, ids, ['date_current'], context=context) - res6 = {} - for r in res5: - res6[r['id']] = r['date_current'] - - ids2 = [] - for id in ids: - dom = [] - if id in res6: - dom = [('date', '=', res6[id]), ('sheet_id', '=', id)] - ids2.extend(obj.pool.get(self._obj).search(cr, user, - dom, limit=self._limit)) - res = {} - for i in ids: - res[i] = [] - for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, - [self._fields_id], context=context, load='_classic_read'): - if r[self._fields_id]: - res[r[self._fields_id][0]].append(r['id']) - - return res - class hr_timesheet_sheet(osv.osv): _name = "hr_timesheet_sheet.sheet" _inherit = "mail.thread" @@ -111,8 +37,7 @@ class hr_timesheet_sheet(osv.osv): def _total_attendances(self, cr, uid, ids, name, args, context=None): """ Get the total attendance for the timesheets Returns a dict like : - {id: {'date_current': '2011-06-17', - 'total_per_day': {day: timedelta, ...}, + {id: {'total_per_day': {day: timedelta, ...}, }, ... } @@ -122,7 +47,6 @@ class hr_timesheet_sheet(osv.osv): res = {} for sheet_id in ids: sheet = self.browse(cr, uid, sheet_id, context=context) - date_current = sheet.date_current # field attendances_ids of hr_timesheet_sheet.sheet only # returns attendances of timesheet's current date attendance_ids = attendance_obj.search(cr, uid, [('sheet_id', '=', sheet_id)], context=context) @@ -143,20 +67,7 @@ class hr_timesheet_sheet(osv.osv): else: total_attendance[day] += attendance_interval - # if the delta is negative, it means that a sign out is missing - # in a such case, we want to have the time to the end of the day - # for a past date, and the time to now for the current date - if total_attendance[day] < timedelta(0): - if day == date_current: - now = datetime.now() - total_attendance[day] += timedelta(hours=now.hour, - minutes=now.minute, - seconds=now.second) - else: - total_attendance[day] += timedelta(days=1) - - res[sheet_id] = {'date_current': date_current, - 'total_per_day': total_attendance} + res[sheet_id] = {'total_per_day': total_attendance} return res def _total_timesheet(self, cr, uid, ids, name, args, context=None): @@ -210,24 +121,16 @@ class hr_timesheet_sheet(osv.osv): all_attendances_sheet = all_timesheet_attendances[id] - date_current = all_attendances_sheet['date_current'] total_attendances_sheet = all_attendances_sheet['total_per_day'] total_attendances_all_days = sum_all_days(total_attendances_sheet) - total_attendances_day = total_attendances_sheet.get(date_current, timedelta(seconds=0)) total_timesheets_sheet = all_timesheet_lines[id] total_timesheets_all_days = sum_all_days(total_timesheets_sheet) - total_timesheets_day = total_timesheets_sheet.get(date_current, timedelta(seconds=0)) total_difference_all_days = total_attendances_all_days - total_timesheets_all_days - total_difference_day = total_attendances_day - total_timesheets_day res[id]['total_attendance'] = timedelta_to_hours(total_attendances_all_days) res[id]['total_timesheet'] = timedelta_to_hours(total_timesheets_all_days) res[id]['total_difference'] = timedelta_to_hours(total_difference_all_days) - - res[id]['total_attendance_day'] = timedelta_to_hours(total_attendances_day) - res[id]['total_timesheet_day'] = timedelta_to_hours(total_timesheets_day) - res[id]['total_difference_day'] = timedelta_to_hours(total_difference_day) return res def check_employee_attendance_state(self, cr, uid, sheet_id, context=None): @@ -277,44 +180,6 @@ class hr_timesheet_sheet(osv.osv): raise osv.except_osv(_('Warning!'), _('Please verify that the total difference of the sheet is lower than %.2f.') %(di,)) return True - def date_today(self, cr, uid, ids, context=None): - for sheet in self.browse(cr, uid, ids, context=context): - if datetime.today() <= datetime.strptime(sheet.date_from, '%Y-%m-%d'): - self.write(cr, uid, [sheet.id], {'date_current': sheet.date_from,}, context=context) - elif datetime.now() >= datetime.strptime(sheet.date_to, '%Y-%m-%d'): - self.write(cr, uid, [sheet.id], {'date_current': sheet.date_to,}, context=context) - else: - self.write(cr, uid, [sheet.id], {'date_current': time.strftime('%Y-%m-%d')}, context=context) - return True - - def date_previous(self, cr, uid, ids, context=None): - for sheet in self.browse(cr, uid, ids, context=context): - if datetime.strptime(sheet.date_current, '%Y-%m-%d') <= datetime.strptime(sheet.date_from, '%Y-%m-%d'): - self.write(cr, uid, [sheet.id], {'date_current': sheet.date_from,}, context=context) - else: - self.write(cr, uid, [sheet.id], { - 'date_current': (datetime.strptime(sheet.date_current, '%Y-%m-%d') + relativedelta(days=-1)).strftime('%Y-%m-%d'), - }, context=context) - return True - - def date_next(self, cr, uid, ids, context=None): - for sheet in self.browse(cr, uid, ids, context=context): - if datetime.strptime(sheet.date_current, '%Y-%m-%d') >= datetime.strptime(sheet.date_to, '%Y-%m-%d'): - self.write(cr, uid, [sheet.id], {'date_current': sheet.date_to,}, context=context) - else: - self.write(cr, uid, [sheet.id], { - 'date_current': (datetime.strptime(sheet.date_current, '%Y-%m-%d') + relativedelta(days=1)).strftime('%Y-%m-%d'), - }, context=context) - return True - - def button_dummy(self, cr, uid, ids, context=None): - for sheet in self.browse(cr, uid, ids, context=context): - if datetime.strptime(sheet.date_current, '%Y-%m-%d') <= datetime.strptime(sheet.date_from, '%Y-%m-%d'): - self.write(cr, uid, [sheet.id], {'date_current': sheet.date_from,}, context=context) - elif datetime.strptime(sheet.date_current, '%Y-%m-%d') >= datetime.strptime(sheet.date_to, '%Y-%m-%d'): - self.write(cr, uid, [sheet.id], {'date_current': sheet.date_to,}, context=context) - return True - def attendance_action_change(self, cr, uid, ids, context=None): hr_employee = self.pool.get('hr.employee') employee_ids = [] @@ -329,14 +194,13 @@ class hr_timesheet_sheet(osv.osv): 'user_id': fields.related('employee_id', 'user_id', type="many2one", relation="res.users", store=True, string="User", required=False, readonly=True),#fields.many2one('res.users', 'User', required=True, select=1, states={'confirm':[('readonly', True)], 'done':[('readonly', True)]}), 'date_from': fields.date('Date from', required=True, select=1, readonly=True, states={'new':[('readonly', False)]}), 'date_to': fields.date('Date to', required=True, select=1, readonly=True, states={'new':[('readonly', False)]}), - 'date_current': fields.date('Current date', required=True, select=1), - 'timesheet_ids' : one2many_mod('hr.analytic.timesheet', 'sheet_id', - 'Timesheet lines', domain=[('date', '=', time.strftime('%Y-%m-%d'))], + 'timesheet_ids' : fields.one2many('hr.analytic.timesheet', 'sheet_id', + 'Timesheet lines', readonly=True, states={ 'draft': [('readonly', False)], 'new': [('readonly', False)]} ), - 'attendances_ids' : one2many_mod2('hr.attendance', 'sheet_id', 'Attendances'), + 'attendances_ids' : fields.one2many('hr.attendance', 'sheet_id', 'Attendances'), 'state' : fields.selection([ ('new', 'New'), ('draft','Open'), @@ -346,9 +210,6 @@ class hr_timesheet_sheet(osv.osv): \n* The \'Confirmed\' state is used for to confirm the timesheet by user. \ \n* The \'Done\' state is used when users timesheet is accepted by his/her senior.'), 'state_attendance' : fields.related('employee_id', 'state', type='selection', selection=[('absent', 'Absent'), ('present', 'Present')], string='Current Status', readonly=True), - 'total_attendance_day': fields.function(_total, method=True, string='Total Attendance', multi="_total"), - 'total_timesheet_day': fields.function(_total, method=True, string='Total Timesheet', multi="_total"), - 'total_difference_day': fields.function(_total, method=True, string='Difference', multi="_total"), 'total_attendance': fields.function(_total, method=True, string='Total Attendance', multi="_total"), 'total_timesheet': fields.function(_total, method=True, string='Total Timesheet', multi="_total"), 'total_difference': fields.function(_total, method=True, string='Difference', multi="_total"), @@ -386,7 +247,6 @@ class hr_timesheet_sheet(osv.osv): _defaults = { 'date_from' : _default_date_from, - 'date_current' : lambda *a: time.strftime('%Y-%m-%d'), 'date_to' : _default_date_to, 'state': 'new', 'employee_id': _default_employee, @@ -406,16 +266,9 @@ class hr_timesheet_sheet(osv.osv): return False return True - def _date_current_check(self, cr, uid, ids, context=None): - for sheet in self.browse(cr, uid, ids, context=context): - if sheet.date_current < sheet.date_from or sheet.date_current > sheet.date_to: - return False - return True - _constraints = [ (_sheet_date, 'You cannot have 2 timesheets that overlaps !\nPlease use the menu \'My Current Timesheet\' to avoid this problem.', ['date_from','date_to']), - (_date_current_check, 'You must select a Current date which is in the timesheet dates !', ['date_current']), ] def action_set_to_draft(self, cr, uid, ids, *args): diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml index 78fc997d15e..7dd2b9a1b88 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml @@ -76,19 +76,8 @@ - -
    -
    -
    -
    -
    - + @@ -105,9 +94,9 @@ - + - + From 7d46e337633ff4265642d8a7bf9a8a9157a80c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Mon, 1 Oct 2012 17:49:16 +0200 Subject: [PATCH 077/275] [IMP] css: animations for kanban notes bzr revid: fva@openerp.com-20121001154916-r5mq1z4icc54jmgz --- addons/web_kanban/static/src/css/kanban.css | 9 ++++++--- addons/web_kanban/static/src/css/kanban.sass | 14 ++++++++++++-- addons/web_kanban/static/src/js/kanban.js | 6 ++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index 6846171a82a..60e8eefcf37 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -9,7 +9,6 @@ .openerp .oe_kanban_view .ui-sortable-placeholder { border: 1px solid rgba(0, 0, 0, 0.1); visibility: visible !important; - height: 60px !important; } .openerp .oe_kanban_view .ui-sortable-helper { -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.3); @@ -19,6 +18,9 @@ -webkit-transform: rotate(3deg); -o-transform: rotate(3deg); -ms-transform: rotate(3deg); + -webkit-transition: -webkit-transform 100ms linear; + -moz-transition: -moz-transform 100ms linear; + transition: transform 100ms linear; } .openerp .oe_kanban_view .oe_kanban_left { float: left; @@ -364,17 +366,18 @@ border-bottom-color: rgba(0, 0, 0, 0.3); padding: 8px; display: block; + -webkit-transition: -webkit-transform, -webkit-box-shadow, border 200ms linear; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } -.openerp .oe_kanban_view .oe_kanban_card:hover, .openerp .oe_kanban_view .oe_kanban_quick_create:hover { +.openerp .oe_kanban_view .oe_kanban_card:not(.ui-sortable-helper):hover, .openerp .oe_kanban_view .oe_kanban_quick_create:not(.ui-sortable-helper):hover { border: 1px solid #7c7bad; -moz-box-shadow: 0 0 4px #7c7bad; -webkit-box-shadow: 0 0 4px #7c7bad; -box-shadow: 0 0 4px #7c7bad; } -.openerp .oe_kanban_view .oe_kanban_card:hover .oe_dropdown_kanban > span, .openerp .oe_kanban_view .oe_kanban_quick_create:hover .oe_dropdown_kanban > span { +.openerp .oe_kanban_view .oe_kanban_card:not(.ui-sortable-helper):hover .oe_dropdown_kanban > span, .openerp .oe_kanban_view .oe_kanban_quick_create:not(.ui-sortable-helper):hover .oe_dropdown_kanban > span { visibility: visible; } .openerp .oe_kanban_view .oe_kanban_card h3, .openerp .oe_kanban_view .oe_kanban_quick_create h3 { diff --git a/addons/web_kanban/static/src/css/kanban.sass b/addons/web_kanban/static/src/css/kanban.sass index 88b60134f24..1210e9bf640 100644 --- a/addons/web_kanban/static/src/css/kanban.sass +++ b/addons/web_kanban/static/src/css/kanban.sass @@ -37,6 +37,13 @@ -webkit-transform: $transform -o-transform: $transform -ms-transform: $transform + +@mixin transition($transition: all 200ms linear) + -webkit-transition: $transition + -moz-transition: $transition + -ms-transition: $transition + -o-transition: $transition + transition: $transition // }}} .openerp .oe_kanban_view @@ -49,10 +56,12 @@ .ui-sortable-placeholder border: 1px solid rgba(0,0,0,0.1) visibility: visible !important - height: 60px !important .ui-sortable-helper @include box-shadow(0 1px 10px rgba(0, 0, 0, 0.3)) @include transform(rotate(3deg)) + -webkit-transition: -webkit-transform 100ms linear + -moz-transition: -moz-transform 100ms linear + transition: transform 100ms linear .oe_kanban_left float: left .oe_kanban_right @@ -328,8 +337,9 @@ border-bottom-color: rgba(0,0,0,0.3) padding: 8px display: block + -webkit-transition: -webkit-transform, -webkit-box-shadow, border 200ms linear @include radius(4px) - &:hover + &:not(.ui-sortable-helper):hover border: 1px solid #7C7BAD @include box-shadow(0 0 4px #7C7BAD) .oe_dropdown_kanban > span diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index bd36dcbf4ba..d8e93efa580 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -309,8 +309,14 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ ui.item.find('*').on('click.prevent', function(ev) { return false; }); + ui.placeholder.height(ui.item.height()); + }, + revert: 150, + beforeStop: function(event,ui){ + console.log('beforeStop:',ui); }, stop: function(event, ui) { + console.log('stop:',ui); var record = ui.item.data('widget'); var old_index = self.currently_dragging.index; var new_index = ui.item.index(); From 2b07b4e35c5ee619eaf93a7bb4fb14a37e55fb0e Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 1 Oct 2012 18:08:54 +0200 Subject: [PATCH 078/275] [FIX] sale, sale_stock: yaml tests on product_id_change() + fix in that same function (type is defined in sale_stock now) bzr revid: qdp-launchpad@openerp.com-20121001160854-7d2xew5pol6u27b2 --- addons/sale/sale.py | 1 - addons/sale/sale_view.xml | 5 ++--- addons/sale/test/sale_order_demo.yml | 14 ++++++-------- addons/sale_stock/test/sale_order_onchange.yml | 14 ++++++-------- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 96f44d353d6..f9dc3c62281 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -899,7 +899,6 @@ class sale_order_line(osv.osv): fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False if update_tax: #The quantity only have changed result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id) - result.update({'type': product_obj.procure_method}) if not flag: result['name'] = self.pool.get('product.product').name_get(cr, uid, [product_obj.id], context=context_partner)[0][1] diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 23d2c556f40..620991d8053 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -200,8 +200,7 @@ -
    - + From 90b90bb01e93f578abd482db0ebc6be985aa2ede Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 1 Oct 2012 19:09:20 +0200 Subject: [PATCH 081/275] [FIX] sale_stock: product_id_change fix bzr revid: qdp-launchpad@openerp.com-20121001170920-fv2ueuyecml908gi --- addons/sale_stock/sale_stock.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index aea39590152..dfd310fce3a 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -610,14 +610,18 @@ class sale_order_line(osv.osv): lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context) if not product: - return {'value': {'th_weight': 0, 'product_packaging': False, - 'product_uos_qty': qty}, 'domain': {'product_uom': [], - 'product_uos': []}} + res['value'].update({'product_packaging': False}) + return res + + #update of result obtained in super function res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context) res['value'].update(res_packing.get('value', {})) warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or '' product_obj = product_obj.browse(cr, uid, product, context=context) res['value']['delay'] = (product_obj.sale_delay or 0.0) + res['value']['type'] = product_obj.type + + #check if product is available, and if not: raise an error uom2 = False if uom: uom2 = product_uom_obj.browse(cr, uid, uom) @@ -625,7 +629,6 @@ class sale_order_line(osv.osv): uom = False if not uom2: uom2 = product_obj.uom_id - compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding) if (product_obj.type=='product') and int(compare_qty) == -1 \ and (product_obj.procure_method=='make_to_stock'): @@ -634,7 +637,8 @@ class sale_order_line(osv.osv): max(0,product_obj.virtual_available), product_obj.uom_id.name, max(0,product_obj.qty_available), product_obj.uom_id.name) warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n" - # get unit price + + #update of warning messages if warning_msgs: warning = { 'title': _('Configuration Error!'), From feaa3bf3ab40c40dd64f32916de2194e4cb9d5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Mon, 1 Oct 2012 19:12:26 +0200 Subject: [PATCH 082/275] [FIX] css: removed bold from active menu items, it made the menu wobble bzr revid: fva@openerp.com-20121001171226-xw275mzmhc43faeu --- addons/web/static/src/css/base.css | 3 +-- addons/web/static/src/css/base.sass | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 18db06c44a1..aadc73e3511 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -1081,9 +1081,8 @@ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4) inset; } .openerp .oe_menu > li > .oe_active { - background: rgba(0, 0, 0, 0.2); + background: rgba(0, 0, 0, 0.3); text-shadow: black 0px 0px 3px; - font-weight: bold; -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4) inset; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4) inset; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4) inset; diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 851d0c3f9c9..818cd7dc450 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -875,9 +875,8 @@ $sheet-max-width: 860px color: white @include box-shadow(0 1px 2px rgba(0,0,0,0.4) inset) > .oe_active - background: rgba(0,0,0,0.2) + background: rgba(0,0,0,0.30) text-shadow: black 0px 0px 3px - font-weight: bold @include box-shadow(0 1px 2px rgba(0,0,0,0.4) inset) .oe_user_menu From 48a8367968fb897b0778eb094033458ea399b361 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 1 Oct 2012 19:13:41 +0200 Subject: [PATCH 083/275] [FIX] sale_stock: stupid wrong field used bzr revid: qdp-launchpad@openerp.com-20121001171341-dj97xdjw9qu0nkxr --- addons/sale_stock/sale_stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index dfd310fce3a..e079386b15d 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -619,7 +619,7 @@ class sale_order_line(osv.osv): warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or '' product_obj = product_obj.browse(cr, uid, product, context=context) res['value']['delay'] = (product_obj.sale_delay or 0.0) - res['value']['type'] = product_obj.type + res['value']['type'] = product_obj.procure_method #check if product is available, and if not: raise an error uom2 = False From 6664ca2653d47a2856272758a018bdb383668359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Mon, 1 Oct 2012 19:16:10 +0200 Subject: [PATCH 084/275] [FIX] css: disabled required inputs should not be highlighted bzr revid: fva@openerp.com-20121001171610-lyshewqacnl0me7s --- addons/web/static/src/css/base.css | 2 +- addons/web/static/src/css/base.sass | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index aadc73e3511..7cd189f8d4b 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -2240,7 +2240,7 @@ .openerp .oe_form .oe_datepicker_root { display: inline-block; } -.openerp .oe_form .oe_form_required input, .openerp .oe_form .oe_form_required select, .openerp .oe_form .oe_form_required textarea { +.openerp .oe_form .oe_form_required input:not([disabled]), .openerp .oe_form .oe_form_required select:not([disabled]), .openerp .oe_form .oe_form_required textarea:not([disabled]) { background-color: #d2d2ff !important; } .openerp .oe_form .oe_form_invalid input, .openerp .oe_form .oe_form_invalid select, .openerp .oe_form .oe_form_invalid textarea { diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 818cd7dc450..06890b991dc 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -1772,8 +1772,8 @@ $sheet-max-width: 860px display: none .oe_datepicker_root display: inline-block - .oe_form_required - input, select, textarea + .oe_form_required + input:not([disabled]), select:not([disabled]), textarea:not([disabled]) background-color: #D2D2FF !important .oe_form_invalid input, select, textarea From b3e7f809b2ff854beb99487fc3a9aa30d7d3d4a1 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 2 Oct 2012 09:53:04 +0200 Subject: [PATCH 085/275] [FIX] portal: adapt tests to new signup process bzr revid: rco@openerp.com-20121002075304-62r768sg7vt4i9z3 --- addons/portal/tests/test_portal.py | 73 +++++++++++++++--------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/addons/portal/tests/test_portal.py b/addons/portal/tests/test_portal.py index 653a05d40aa..fe26f3280a2 100644 --- a/addons/portal/tests/test_portal.py +++ b/addons/portal/tests/test_portal.py @@ -33,6 +33,7 @@ class test_portal(test_mail.TestMailMockups): self.mail_group = self.registry('mail.group') self.mail_mail = self.registry('mail.mail') self.mail_message = self.registry('mail.message') + self.mail_invite = self.registry('mail.wizard.invite') self.res_users = self.registry('res.users') self.res_partner = self.registry('res.partner') @@ -41,19 +42,17 @@ class test_portal(test_mail.TestMailMockups): {'name': 'Pigs', 'description': 'Fans of Pigs, unite !'}) # Find Portal group - group_portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal') - self.group_portal_id = group_portal_ref and group_portal_ref[1] or False + group_portal = self.registry('ir.model.data').get_object(cr, uid, 'portal', 'group_portal') + self.group_portal_id = group_portal.id # Create Chell (portal user) self.user_chell_id = self.res_users.create(cr, uid, {'name': 'Chell Gladys', 'login': 'chell', 'groups_id': [(6, 0, [self.group_portal_id])]}) - self.user_chell = self.res_users.browse(cr, uid, self.user_chell_id) - self.partner_chell_id = self.user_chell.partner_id.id + user_chell = self.res_users.browse(cr, uid, self.user_chell_id) + self.partner_chell_id = user_chell.partner_id.id def test_00_access_rights(self): """ Test basic mail_message and mail_group access rights for portal users. """ cr, uid = self.cr, self.uid - partner_chell_id = self.partner_chell_id - user_chell_id = self.user_chell_id # Prepare group: Pigs (portal) self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message') @@ -64,56 +63,56 @@ class test_portal(test_mail.TestMailMockups): # ---------------------------------------- # Do: Chell reads Pigs messages, ok because restricted to portal group - message_ids = self.mail_group.read(cr, user_chell_id, self.group_pigs_id, ['message_ids'])['message_ids'] - self.mail_message.read(cr, user_chell_id, message_ids) + message_ids = self.mail_group.read(cr, self.user_chell_id, self.group_pigs_id, ['message_ids'])['message_ids'] + self.mail_message.read(cr, self.user_chell_id, message_ids) + # Do: Chell posts a message on Pigs, crash because can not write on group or is not in the followers - self.assertRaises(except_orm, - self.mail_group.message_post, - cr, user_chell_id, self.group_pigs_id, body='Message') + with self.assertRaises(except_orm): + self.mail_group.message_post(cr, self.user_chell_id, self.group_pigs_id, body='Message') + # Do: Chell is added to Pigs followers - self.mail_group.message_subscribe(cr, uid, [self.group_pigs_id], [partner_chell_id]) + self.mail_group.message_subscribe(cr, uid, [self.group_pigs_id], [self.partner_chell_id]) + # Test: Chell posts a message on Pigs, ok because in the followers - self.mail_group.message_post(cr, user_chell_id, self.group_pigs_id, body='Message') + self.mail_group.message_post(cr, self.user_chell_id, self.group_pigs_id, body='Message') def test_50_mail_invite(self): cr, uid = self.cr, self.uid user_admin = self.res_users.browse(cr, uid, uid) - self.mail_invite = self.registry('mail.wizard.invite') base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url', default='') - portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal') - portal_id = portal_ref and portal_ref[1] or False - # 0 - Admin - p_a_id = user_admin.partner_id.id + partner_admin_id = user_admin.partner_id.id # 1 - Bert Tartopoils, with email, should receive emails for comments and emails - p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'}) + partner_bert_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'}) # ---------------------------------------- - # CASE1: generated URL + # CASE: invite Bert to follow Pigs # ---------------------------------------- - url = self.mail_mail._generate_signin_url(cr, uid, p_b_id, portal_id, 1234) - self.assertEqual(url, base_url + '/login?action=signin&partner_id=%s&group=%s&key=%s' % (p_b_id, portal_id, 1234), - 'generated signin URL incorrect') - - # ---------------------------------------- - # CASE2: invite Bert - # ---------------------------------------- - - _sent_email_subject = 'Invitation to follow Pigs' - _sent_email_body = append_content_to_html('
    You have been invited to follow Pigs.
    ', url) - # Do: create a mail_wizard_invite, validate it self._init_mock_build_email() - mail_invite_id = self.mail_invite.create(cr, uid, {'partner_ids': [(4, p_b_id)]}, {'default_res_model': 'mail.group', 'default_res_id': self.group_pigs_id}) + context = {'default_res_model': 'mail.group', 'default_res_id': self.group_pigs_id} + mail_invite_id = self.mail_invite.create(cr, uid, {'partner_ids': [(4, partner_bert_id)]}, context) self.mail_invite.add_followers(cr, uid, [mail_invite_id]) - group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) # Test: Pigs followers should contain Admin and Bert + group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) follower_ids = [follower.id for follower in group_pigs.message_follower_ids] - self.assertEqual(set(follower_ids), set([p_a_id, p_b_id]), 'Pigs followers after invite is incorrect') - # Test: sent email subject, body + self.assertEqual(set(follower_ids), set([partner_admin_id, partner_bert_id]), 'Pigs followers after invite is incorrect') + + # Test: partner must have been prepared for signup + partner_bert = self.res_partner.browse(cr, uid, partner_bert_id) + self.assertTrue(partner_bert.signup_valid, 'partner has not been prepared for signup') + self.assertTrue(base_url in partner_bert.signup_url, 'signup url is incorrect') + self.assertTrue(cr.dbname in partner_bert.signup_url, 'signup url is incorrect') + self.assertTrue(partner_bert.signup_token in partner_bert.signup_url, 'signup url is incorrect') + + # Test: (pretend to) send email and check subject, body self.assertEqual(len(self._build_email_kwargs_list), 1, 'sent email number incorrect, should be only for Bert') for sent_email in self._build_email_kwargs_list: - self.assertEqual(sent_email.get('subject'), _sent_email_subject, 'sent email subject incorrect') - self.assertEqual(sent_email.get('body'), _sent_email_body, 'sent email body incorrect') + self.assertEqual(sent_email.get('subject'), 'Invitation to follow Pigs', + 'subject of invitation email is incorrect') + self.assertTrue('You have been invited to follow Pigs' in sent_email.get('body'), + 'body of invitation email is incorrect') + self.assertTrue(partner_bert.signup_url in sent_email.get('body'), + 'body of invitation email does not contain signup url') From 42ae23d0323ff1377d5e6a3dad490c871af5b810 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 2 Oct 2012 11:33:59 +0200 Subject: [PATCH 086/275] [FIX] base.xml: disable translation on CSS style element bzr revid: odo@openerp.com-20121002093359-dxdd60auidfra3rj --- addons/web/static/src/xml/base.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 58bc224918c..b035c2c8c14 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1119,7 +1119,7 @@ - width: 83px; + width: 83px; + From e87aec12f9fb5124ee8e1dcceecd540254f3698e Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Mon, 8 Oct 2012 14:43:02 +0200 Subject: [PATCH 236/275] [FIX] Typo in previous commit. bzr revid: vta@openerp.com-20121008124302-8t8h11ry9erxvqvk --- addons/process/static/src/js/process.js | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/process/static/src/js/process.js b/addons/process/static/src/js/process.js index c80ce3316ed..c593c1569fc 100644 --- a/addons/process/static/src/js/process.js +++ b/addons/process/static/src/js/process.js @@ -240,7 +240,6 @@ instance.web.ViewManager.include({ }); var form_controller = pop.view_form; pop.on('on_write_complete', self, self.initialize_process_view); - }); } }); }; From 46b112f1295a4302b81d043b49df869a1aa3affe Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 8 Oct 2012 14:44:29 +0200 Subject: [PATCH 237/275] Not possible to add an already existing account bzr revid: nicolas.vanhoren@openerp.com-20121008124429-j65gc8s6jb4a8u8f --- addons/hr_timesheet_sheet/static/src/js/timesheet.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/hr_timesheet_sheet/static/src/js/timesheet.js b/addons/hr_timesheet_sheet/static/src/js/timesheet.js index 8cf9d5415c7..8f200f487b2 100644 --- a/addons/hr_timesheet_sheet/static/src/js/timesheet.js +++ b/addons/hr_timesheet_sheet/static/src/js/timesheet.js @@ -188,7 +188,12 @@ openerp.hr_timesheet_sheet = function(instance) { attrs: { name: "account", type: "many2one", - domain: [['type','in',['normal', 'contract']], ['state', '<>', 'close'], ['use_timesheets','=',1]], + domain: [ + ['type','in',['normal', 'contract']], + ['state', '<>', 'close'], + ['use_timesheets','=',1], + ['id', 'not in', _.pluck(self.accounts, "account")], + ], modifiers: '{"required": true}', }, }); From d54120565152cc0f1c8164bf7538802f7d527332 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 8 Oct 2012 15:02:45 +0200 Subject: [PATCH 238/275] [FIX] portal: add test email address for outgoing emails sent during tests bzr revid: odo@openerp.com-20121008130245-7n1ed3i2ez9bzniy --- addons/portal/tests/test_portal.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/portal/tests/test_portal.py b/addons/portal/tests/test_portal.py index 653a05d40aa..10392be53ff 100644 --- a/addons/portal/tests/test_portal.py +++ b/addons/portal/tests/test_portal.py @@ -49,6 +49,9 @@ class test_portal(test_mail.TestMailMockups): self.user_chell = self.res_users.browse(cr, uid, self.user_chell_id) self.partner_chell_id = self.user_chell.partner_id.id + # Set an email address for the user running the tests, used as Sender for outgoing mails + self.res_users.write(cr, uid, uid, {'email': 'test@localhost'}) + def test_00_access_rights(self): """ Test basic mail_message and mail_group access rights for portal users. """ cr, uid = self.cr, self.uid From d9d07f9a13092c2132abc954d6114784ecb02a2f Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 8 Oct 2012 15:03:09 +0200 Subject: [PATCH 239/275] [FIX] removed console.log bzr revid: nicolas.vanhoren@openerp.com-20121008130309-bdl7ryns0phy158t --- addons/mail/static/src/js/mail_followers.js | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 953b8cd9fc8..6c016c6c679 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -149,7 +149,6 @@ openerp_mail_followers = function(session, mail) { var self = this; var node_user_list = this.$('ul.oe_mail_followers_display').empty(); this.$('div.oe_mail_recthread_followers h4').html(this.options.title + (records.length>=5 ? ' (' + records.length + ')' : '') ); - console.log(records); for(var i=0; i Date: Mon, 8 Oct 2012 15:08:31 +0200 Subject: [PATCH 240/275] [IMP] crm: remove 'sale team' from res.partner search view bzr revid: qdp-launchpad@openerp.com-20121008130831-hjm46vehb54tqc74 --- addons/crm/res_partner_view.xml | 16 ---------------- addons/hr_expense/hr_expense_view.xml | 2 +- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 84a0bd4cf49..4b313bcef71 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -15,28 +15,12 @@
    - - view.res.partner.tree.crm.inherited2 - res.partner - - - - - - - - - view.res.partner.search.crm.inherited3 res.partner - - - - diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml index 2032d3f0567..67d629eee6a 100644 --- a/addons/hr_expense/hr_expense_view.xml +++ b/addons/hr_expense/hr_expense_view.xml @@ -158,7 +158,7 @@ - + From 635c3225dbf78dd6ff548b9f979f549a49a663da Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 8 Oct 2012 16:08:57 +0200 Subject: [PATCH 241/275] [FIX] project_long_term: demo project with phases should be marked as `use_phases` bzr revid: odo@openerp.com-20121008140857-zd3kcyq8t2ewyfno --- addons/project_long_term/project_long_term_demo.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/project_long_term/project_long_term_demo.xml b/addons/project_long_term/project_long_term_demo.xml index bca8231fdaa..fda481d5a11 100644 --- a/addons/project_long_term/project_long_term_demo.xml +++ b/addons/project_long_term/project_long_term_demo.xml @@ -7,6 +7,7 @@ + From a9b9412f182c3bc7e53b7a001d5edfa0b21b24bf Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 8 Oct 2012 16:26:19 +0200 Subject: [PATCH 242/275] [IMP] crm: remove 'country_id' from res.partner search view bzr revid: qdp-launchpad@openerp.com-20121008142619-mxqis0ubc8m3o4z9 --- addons/crm/res_partner_view.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 4b313bcef71..b7aa334a9c3 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -21,9 +21,6 @@ - - - From 6210cf76a6fba0d3054dcbe837e0824858eeea4b Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 8 Oct 2012 16:27:57 +0200 Subject: [PATCH 243/275] [IMP] base: module search view imp bzr revid: qdp-launchpad@openerp.com-20121008142757-c3597to9h42e56tl --- openerp/addons/base/module/module_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/module/module_view.xml b/openerp/addons/base/module/module_view.xml index 729d3ef7b4c..c3b3684f07c 100644 --- a/openerp/addons/base/module/module_view.xml +++ b/openerp/addons/base/module/module_view.xml @@ -39,7 +39,7 @@ + 'ilike', self)]" string="Module"/> From 5db1b37797c2e2e8ed2743e89cac8dd7489b6d8d Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 8 Oct 2012 16:47:22 +0200 Subject: [PATCH 244/275] [IMP] crm: opportunity search view imp bzr revid: qdp-launchpad@openerp.com-20121008144722-r6th49qhfzq8jmbf --- addons/crm/crm_lead_view.xml | 3 +-- addons/crm_partner_assign/crm_lead_view.xml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 0c6d1d1fe96..6a152f44b67 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -580,9 +580,8 @@ domain="['|', ('section_id.user_id','=',uid), ('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}" help="Opportunities that are assigned to either me or one of the sale teams I manage" /> - - + diff --git a/addons/crm_partner_assign/crm_lead_view.xml b/addons/crm_partner_assign/crm_lead_view.xml index cd2e3f08c9a..2cffb6fb899 100644 --- a/addons/crm_partner_assign/crm_lead_view.xml +++ b/addons/crm_partner_assign/crm_lead_view.xml @@ -56,7 +56,7 @@ - + From a1922458f5eeafd67cf364dca2c003c4bc63c7ae Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 8 Oct 2012 17:11:31 +0200 Subject: [PATCH 245/275] [FIX] mail: in record rule, use partner id in mail_follower_ids instead of user id bzr revid: rco@openerp.com-20121008151131-wi86wmjqxo44c7sq --- addons/mail/security/mail_security.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/security/mail_security.xml b/addons/mail/security/mail_security.xml index b503565bd11..be3bb667628 100644 --- a/addons/mail/security/mail_security.xml +++ b/addons/mail/security/mail_security.xml @@ -7,7 +7,7 @@ Mail.group: access only public and joined groups - ['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.id]), '&', ('public','=','groups'), ('group_public_id','in', [x.id for x in user.groups_id])] + ['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.partner_id.id]), '&', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]