From 63ee6a74a91a630f5b5049f10ae67291df85f760 Mon Sep 17 00:00:00 2001 From: "Divyesh Makwana (Open ERP)" Date: Mon, 9 Jul 2012 17:09:54 +0530 Subject: [PATCH 001/409] [IMP] project : column project_task_history_cumulative.project_id does not exist. lp bug: https://launchpad.net/bugs/1022509 fixed bzr revid: mdi@tinyerp.com-20120709113954-l17wlurxovz6z05i --- addons/project/report/project_cumulative.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml index 3f7f3b26d96..535fbaf5f87 100644 --- a/addons/project/report/project_cumulative.xml +++ b/addons/project/report/project_cumulative.xml @@ -9,7 +9,6 @@ - @@ -63,9 +62,7 @@ - - From e2ba0eb95c38a16839836deeaa9a73b58221e9aa Mon Sep 17 00:00:00 2001 From: "Divyesh Makwana (Open ERP)" Date: Mon, 9 Jul 2012 18:42:59 +0530 Subject: [PATCH 002/409] [IMP] project : Revert the unneccessary changes. bzr revid: mdi@tinyerp.com-20120709131259-c9fl7g3hgwhxutgb --- addons/project/report/project_cumulative.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml index 535fbaf5f87..177e945bc93 100644 --- a/addons/project/report/project_cumulative.xml +++ b/addons/project/report/project_cumulative.xml @@ -9,6 +9,7 @@ + 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 003/409] [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 004/409] [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 005/409] [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 006/409] [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 007/409] [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 008/409] [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 009/409] [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 010/409] [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 011/409] [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 012/409] [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 013/409] [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 014/409] [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 015/409] [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 016/409] [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 017/409] [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 018/409] [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 019/409] [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 020/409] [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 021/409] [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 022/409] [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 023/409] [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 024/409] [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 449a86a51f62c2e3379fc649c55d89080c278fa4 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 24 Sep 2012 12:32:57 +0200 Subject: [PATCH 038/409] [IMP] cache boolean and selection translations for the request (cursor) to avoid fetching them over and over again bzr revid: xmo@openerp.com-20120924103257-1jgc3qhddzzi5c17 --- openerp/addons/base/ir/ir_fields.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py index 10b80511c73..73e748015a3 100644 --- a/openerp/addons/base/ir/ir_fields.py +++ b/openerp/addons/base/ir/ir_fields.py @@ -95,11 +95,20 @@ class ir_fields_converter(orm.Model): return value or False def _get_translations(self, cr, uid, types, src, context): + types = tuple(types) + # Cache translations so they don't have to be reloaded from scratch on + # every row of the file + tnx_cache = cr.cache.setdefault(self._name, {}) + if tnx_cache.setdefault(types, {}) and src in tnx_cache[types]: + return tnx_cache[types][src] + Translations = self.pool['ir.translation'] tnx_ids = Translations.search( cr, uid, [('type', 'in', types), ('src', '=', src)], context=context) tnx = Translations.read(cr, uid, tnx_ids, ['value'], context=context) - return map(operator.itemgetter('value'), tnx) + result = tnx_cache[types][src] = map(operator.itemgetter('value'), tnx) + return result + def _str_to_selection(self, cr, uid, model, column, value, context=None): selection = column.selection From 877e21ffdebeba412b7cb4db5fdf352adfac2ff2 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 24 Sep 2012 12:52:30 +0200 Subject: [PATCH 039/409] [IMP] return fields_get-style translated field strings (if available) in user-readable warning and error messages from import, rather than logical field names bzr revid: xmo@openerp.com-20120924105230-1b7157xbruy2e5zr --- openerp/osv/orm.py | 19 +++++++++++--- .../addons/test_impex/tests/test_load.py | 26 +++++++++---------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 57cc5823dd9..e58d6b76a76 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1585,8 +1585,15 @@ class BaseModel(object): :returns: a list of triplets of (id, xid, record) :rtype: list((int|None, str|None, dict)) """ + if context is None: context = {} Converter = self.pool['ir.fields.converter'] columns = dict((k, v.column) for k, v in self._all_columns.iteritems()) + Translation = self.pool['ir.translation'] + field_names = dict( + (f, (Translation._get_source(cr, uid, self._name + ',' + f, 'field', + context.get('lang', False) or 'en_US') + or column.string or f)) + for f, column in columns.iteritems()) converters = dict( (k, Converter.to_field(cr, uid, self, column, context=context)) for k, column in columns.iteritems()) @@ -1619,18 +1626,24 @@ class BaseModel(object): for field, strvalue in record.iteritems(): if field in (None, 'id', '.id'): continue - message_base = dict(extras, record=stream.index, field=field) + # In warnings and error messages, use translated string as + # field name + message_base = dict( + extras, record=stream.index, field=field_names[field]) with warnings.catch_warnings(record=True) as w: try: converted[field] = converters[field](strvalue) + # In warning and error returned, use logical field name + # as field so client can reverse for warning in w: - log(dict(message_base, type='warning', + log(dict(message_base, type='warning', field=field, message=unicode(warning.message) % message_base)) except ValueError, e: log(dict(message_base, type='error', - message=unicode(e) % message_base + field=field, + message=unicode(e) % message_base, )) yield dbid, xid, converted, dict(extras, record=stream.index) diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index 28957c29555..cf95f5bb6c4 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -186,7 +186,7 @@ class test_boolean_field(ImporterCase): ids, messages = self.import_(['value'], trues) self.assertEqual(len(ids), 10) self.assertEqual(messages, [ - message(u"Unknown value '%s' for boolean field 'value', assuming 'yes'" % v[0], + message(u"Unknown value '%s' for boolean field 'unknown', assuming 'yes'" % v[0], type='warning', from_=i, to_=i, record=i) for i, v in enumerate(trues) if v[0] != 'true' if v[0] != 'yes' if v[0] != '1' @@ -460,7 +460,7 @@ class test_selection(ImporterCase): 'rows': {'from': 0, 'to': 0}, 'record': 0, 'field': 'value', - 'message': "Value 'Baz' not found in selection field 'value'", + 'message': "Value 'Baz' not found in selection field 'unknown'", }]) ids, messages = self.import_(['value'], [[42]]) @@ -470,7 +470,7 @@ class test_selection(ImporterCase): 'rows': {'from': 0, 'to': 0}, 'record': 0, 'field': 'value', - 'message': "Value '42' not found in selection field 'value'", + 'message': "Value '42' not found in selection field 'unknown'", }]) class test_selection_function(ImporterCase): @@ -583,7 +583,7 @@ class test_m2o(ImporterCase): ids, messages = self.import_(['value'], [[name2]]) self.assertEqual( messages, - [message(u"Found multiple matches for field 'value' (2 matches)", + [message(u"Found multiple matches for field 'unknown' (2 matches)", type='warning')]) self.assertEqual(len(ids), 1) self.assertEqual([ @@ -607,7 +607,7 @@ class test_m2o(ImporterCase): [integer_id1], ]) self.assertEqual(messages, [ - message(u"No matching record found for name '%s' in field 'value'" % id, + message(u"No matching record found for name '%s' in field 'unknown'" % id, from_=index, to_=index, record=index) for index, id in enumerate([integer_id1, integer_id2, integer_id1])]) self.assertIs(ids, False) @@ -626,19 +626,19 @@ class test_m2o(ImporterCase): ids, messages = self.import_(['value'], [['nameisnoexist:3']]) self.assertEqual(messages, [message( u"No matching record found for name 'nameisnoexist:3' " - u"in field 'value'")]) + u"in field 'unknown'")]) self.assertIs(ids, False) ids, messages = self.import_(['value/id'], [['noxidhere']]) self.assertEqual(messages, [message( u"No matching record found for external id 'noxidhere' " - u"in field 'value'")]) + u"in field 'unknown'")]) self.assertIs(ids, False) ids, messages = self.import_(['value/.id'], [['66']]) self.assertEqual(messages, [message( u"No matching record found for database id '66' " - u"in field 'value'")]) + u"in field 'unknown'")]) self.assertIs(ids, False) def test_fail_multiple(self): @@ -646,7 +646,7 @@ class test_m2o(ImporterCase): ['value', 'value/id'], [['somename', 'somexid']]) self.assertEqual(messages, [message( - u"Ambiguous specification for field 'value', only provide one of " + u"Ambiguous specification for field 'unknown', only provide one of " u"name, external id or database id")]) self.assertIs(ids, False) @@ -690,7 +690,7 @@ class test_m2m(ImporterCase): ids, messages = self.import_(['value/.id'], [['42']]) self.assertEqual(messages, [message( u"No matching record found for database id '42' in field " - u"'value'")]) + u"'unknown'")]) self.assertIs(ids, False) def test_xids(self): @@ -716,7 +716,7 @@ class test_m2m(ImporterCase): ids, messages = self.import_(['value/id'], [['noxidforthat']]) self.assertEqual(messages, [message( u"No matching record found for external id 'noxidforthat' " - u"in field 'value'")]) + u"in field 'unknown'")]) self.assertIs(ids, False) def test_names(self): @@ -745,7 +745,7 @@ class test_m2m(ImporterCase): ids, messages = self.import_(['value'], [['wherethem2mhavenonames']]) self.assertEqual(messages, [message( u"No matching record found for name 'wherethem2mhavenonames' in " - u"field 'value'")]) + u"field 'unknown'")]) self.assertIs(ids, False) def test_import_to_existing(self): @@ -778,7 +778,7 @@ class test_o2m(ImporterCase): ['const', 'value'], [['5', s]]) self.assertEqual(messages, [message( - u"No matching record found for name '%s' in field 'value'" % s)]) + u"No matching record found for name '%s' in field 'unknown'" % s)]) self.assertIs(ids, False) def test_single(self): From 24a4e57171fd0ce371260370226f4c90607f390b Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Mon, 24 Sep 2012 13:53:20 +0200 Subject: [PATCH 040/409] [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 a9c2cfcdb91c79cc60de909a4e23bd9e9e5f9787 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 24 Sep 2012 16:57:50 +0200 Subject: [PATCH 041/409] [IMP] make help attribute available on all actions bzr revid: xmo@openerp.com-20120924145750-n0gj4bww1d83h3fy --- openerp/addons/base/ir/ir_actions.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 383f78181e9..b14f4cd7e84 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -19,14 +19,11 @@ # ############################################################################## -import ast -import copy import logging import os import re import time import tools -from xml import dom import netsvc from osv import fields,osv @@ -47,6 +44,9 @@ class actions(osv.osv): 'name': fields.char('Name', size=64, required=True), 'type': fields.char('Action Type', required=True, size=32,readonly=True), 'usage': fields.char('Action Usage', size=32), + 'help': fields.text('Action description', + help='Optional help text for the users with a description of the target view, such as its usage and purpose.', + translate=True), } _defaults = { 'usage': lambda *a: False, @@ -107,6 +107,7 @@ class report_xml(osv.osv): r['report_xsl'] and opj('addons',r['report_xsl'])) _name = 'ir.actions.report.xml' + _inherit = 'ir.actions.actions' _table = 'ir_act_report_xml' _sequence = 'ir_actions_id_seq' _order = 'name' @@ -155,6 +156,7 @@ report_xml() class act_window(osv.osv): _name = 'ir.actions.act_window' _table = 'ir_act_window' + _inherit = 'ir.actions.actions' _sequence = 'ir_actions_id_seq' _order = 'name' @@ -245,9 +247,6 @@ class act_window(osv.osv): 'filter': fields.boolean('Filter'), 'auto_search':fields.boolean('Auto Search'), 'search_view' : fields.function(_search_view, type='text', string='Search View'), - 'help': fields.text('Action description', - help='Optional help text for the users with a description of the target view, such as its usage and purpose.', - translate=True), 'multi': fields.boolean('Action on Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view"), } @@ -331,6 +330,7 @@ act_wizard() class act_url(osv.osv): _name = 'ir.actions.url' _table = 'ir_act_url' + _inherit = 'ir.actions.actions' _sequence = 'ir_actions_id_seq' _order = 'name' _columns = { @@ -432,6 +432,7 @@ class actions_server(osv.osv): _name = 'ir.actions.server' _table = 'ir_act_server' + _inherit = 'ir.actions.actions' _sequence = 'ir_actions_id_seq' _order = 'sequence,name' _columns = { From f143902d1afa345c8fad935a80a6b404a9a3cfb7 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 24 Sep 2012 17:04:17 +0200 Subject: [PATCH 042/409] [IMP] allow converters to add data to import messages, formalize message keys bzr revid: xmo@openerp.com-20120924150417-c2y7g7vdsfz66363 --- openerp/addons/base/ir/ir_fields.py | 33 +++++++-- openerp/osv/orm.py | 70 +++++++++++++++---- .../addons/test_impex/tests/test_load.py | 32 +++------ 3 files changed, 94 insertions(+), 41 deletions(-) diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py index 73e748015a3..2256542533b 100644 --- a/openerp/addons/base/ir/ir_fields.py +++ b/openerp/addons/base/ir/ir_fields.py @@ -38,6 +38,26 @@ class ir_fields_converter(orm.Model): By default, tries to get a method on itself with a name matching the pattern ``_$fromtype_$column._type`` and returns it. + Converter callables can either return a value to their caller or raise + ``ValueError``, which will be interpreted as a validation & conversion + failure. + + ValueError can have either one or two parameters. The first parameter + is mandatory, **must** be a unicode string and will be used as the + user-visible message for the error (it should be translatable and + translated). It can contain a ``field`` named format placeholder so the + caller can inject the field's translated, user-facing name (@string). + + The second parameter is optional and, if provided, must be a mapping. + This mapping will be merged into the error dictionary returned to the + client. + + If a converter can perform its function but has to make assumptions + about the data, it can send a warning to the user through signalling + an :class:`~openerp.osv.orm.ImportWarning` (via ``warnings.warn``). The + handling of a warning at the upper levels is the same as + ``ValueError`` above. + :param cr: openerp cursor :param uid: ID of user calling the converter :param column: column object to generate a value for @@ -74,10 +94,9 @@ class ir_fields_converter(orm.Model): )) if value.lower() in falses: return False - warnings.warn( + warnings.warn(orm.ImportWarning( _(u"Unknown value '%s' for boolean field '%%(field)s', assuming '%s'") - % (value, yes), - orm.ImportWarning) + % (value, yes))) return True def _str_to_integer(self, cr, uid, model, column, value, context=None): @@ -124,7 +143,9 @@ class ir_fields_converter(orm.Model): return item raise ValueError( _(u"Value '%s' not found in selection field '%%(field)s'") % ( - value)) + value), { + 'moreinfo': map(operator.itemgetter(1), selection) + }) def db_id_for(self, cr, uid, model, column, subfield, value, context=None): @@ -174,9 +195,9 @@ class ir_fields_converter(orm.Model): cr, uid, name=value, operator='=', context=context) if ids: if len(ids) > 1: - warnings.warn( + warnings.warn(orm.ImportWarning( _(u"Found multiple matches for field '%%(field)s' (%d matches)") - % (len(ids)), orm.ImportWarning) + % (len(ids)))) id, _name = ids[0] else: raise Exception(u"Unknown sub-field '%s'" % subfield) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index e58d6b76a76..98e24075311 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1444,6 +1444,40 @@ class BaseModel(object): def load(self, cr, uid, fields, data, context=None): """ + Attempts to load the data matrix, and returns a list of ids (or + ``False`` if there was an error and no id could be generated) and a + list of messages. + + Each message is a dictionary with the following keys: + + ``type`` + the type of message, either ``warning`` or ``error``. Any ``error`` + message indicates the import failed and was rolled back. + ``message`` + the message's actual text, which should be translated and can be + shown to the user directly + ``rows`` + a dict with 2 keys ``from`` and ``to``, indicates the range of rows + in ``data`` which generated the message + ``record`` + a single integer, for warnings the index of the record which + generated the message (can be obtained from a non-false ``ids`` + result) + ``field`` + the name of the (logical) OpenERP field for which the error or + warning was generated + ``moreinfo`` (optional) + A string, a list or a dict, leading to more information about the + warning. + + * If ``moreinfo`` is a string, it is a supplementary warnings + message which should be hidden by default + * If ``moreinfo`` is a list, it provides a number of possible or + alternative values for the string + * If ``moreinfo`` is a dict, it is an OpenERP action descriptor + which can be executed to get more information about the issues + with the field. If present, the ``help`` key serves as a label + for the action (e.g. the text of the link). :param cr: cursor for the request :param int uid: ID of the user attempting the data import @@ -1598,6 +1632,14 @@ class BaseModel(object): (k, Converter.to_field(cr, uid, self, column, context=context)) for k, column in columns.iteritems()) + def _log(base, field, exception): + type = 'warning' if isinstance(exception, Warning) else 'error' + record = dict(base, field=field, type=type, + message=unicode(exception.args[0]) % base) + if len(exception.args) > 1 and exception.args[1]: + record.update(exception.args[1]) + log(record) + stream = CountingStream(records) for record, extras in stream: dbid = False @@ -1630,21 +1672,23 @@ class BaseModel(object): # field name message_base = dict( extras, record=stream.index, field=field_names[field]) - with warnings.catch_warnings(record=True) as w: - try: + try: + with warnings.catch_warnings(record=True) as ws: converted[field] = converters[field](strvalue) - # In warning and error returned, use logical field name - # as field so client can reverse - for warning in w: - log(dict(message_base, type='warning', field=field, - message=unicode(warning.message) % message_base)) - except ValueError, e: - log(dict(message_base, - type='error', - field=field, - message=unicode(e) % message_base, - )) + for warning in ws: + # bubble non-import warnings upward + if warning.category != ImportWarning: + warnings.warn(warning.message, warning.category) + continue + w = warning.message + if isinstance(w, basestring): + # wrap warning string in an ImportWarning for + # uniform handling + w = ImportWarning(w) + _log(message_base, field, w) + except ValueError, e: + _log(message_base, field, e) yield dbid, xid, converted, dict(extras, record=stream.index) diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index cf95f5bb6c4..f97dafaaf39 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -5,14 +5,10 @@ import openerp from openerp.tests import common from openerp.tools.misc import mute_logger -def message(msg, type='error', from_=0, to_=0, record=0, field='value'): - return { - 'type': type, - 'rows': {'from': from_, 'to': to_}, - 'record': record, - 'field': field, - 'message': msg - } +def message(msg, type='error', from_=0, to_=0, record=0, field='value', **kwargs): + return dict(kwargs, + type=type, rows={'from': from_, 'to': to_}, record=record, + field=field, message=msg) def error(row, message, record=None, **kwargs): """ Failed import of the record ``record`` at line ``row``, with the error @@ -455,23 +451,15 @@ class test_selection(ImporterCase): def test_invalid(self): ids, messages = self.import_(['value'], [['Baz']]) self.assertIs(ids, False) - self.assertEqual(messages, [{ - 'type': 'error', - 'rows': {'from': 0, 'to': 0}, - 'record': 0, - 'field': 'value', - 'message': "Value 'Baz' not found in selection field 'unknown'", - }]) + self.assertEqual(messages, [message( + u"Value 'Baz' not found in selection field 'unknown'", + moreinfo="Foo Bar Qux".split())]) ids, messages = self.import_(['value'], [[42]]) self.assertIs(ids, False) - self.assertEqual(messages, [{ - 'type': 'error', - 'rows': {'from': 0, 'to': 0}, - 'record': 0, - 'field': 'value', - 'message': "Value '42' not found in selection field 'unknown'", - }]) + self.assertEqual(messages, [message( + u"Value '42' not found in selection field 'unknown'", + moreinfo="Foo Bar Qux".split())]) class test_selection_function(ImporterCase): model_name = 'export.selection.function' From 9f2e7ba7ef86808ea5f10af178e7aeb939426323 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 24 Sep 2012 17:15:02 +0200 Subject: [PATCH 043/409] [IMP] return a dict from Model.load for easier future extensibility (if needed) rather than a tuple. also easier/cleaner to unpack on the JS side bzr revid: xmo@openerp.com-20120924151502-4robe639ctpuvb94 --- openerp/osv/orm.py | 6 +- .../addons/test_impex/tests/test_load.py | 378 +++++++++--------- 2 files changed, 192 insertions(+), 192 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 98e24075311..b824be91b96 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1486,7 +1486,7 @@ class BaseModel(object): :param data: row-major matrix of data to import :type data: list(list(str)) :param dict context: - :returns: + :returns: {ids: list(int)|False, messages: [Message]} """ cr.execute('SAVEPOINT model_load') messages = [] @@ -1516,8 +1516,8 @@ class BaseModel(object): messages.append(dict(info, type="error", message=str(e))) if any(message['type'] == 'error' for message in messages): cr.execute('ROLLBACK TO SAVEPOINT model_load') - return False, messages - return ids, messages + ids = False + return {'ids': ids, 'messages': messages} def _extract_records(self, cr, uid, fields_, data, context=None, log=lambda a: None): """ Generates record dicts from the data iterable. diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index f97dafaaf39..060b32c48f5 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -100,9 +100,9 @@ class test_ids_stuff(ImporterCase): model_name = 'export.integer' def test_create_with_id(self): - ids, messages = self.import_(['.id', 'value'], [['42', '36']]) - self.assertIs(ids, False) - self.assertEqual(messages, [{ + result = self.import_(['.id', 'value'], [['42', '36']]) + self.assertIs(result['ids'], False) + self.assertEqual(result['messages'], [{ 'type': 'error', 'rows': {'from': 0, 'to': 0}, 'record': 0, @@ -110,9 +110,9 @@ class test_ids_stuff(ImporterCase): 'message': u"Unknown database identifier '42'", }]) def test_create_with_xid(self): - ids, messages = self.import_(['id', 'value'], [['somexmlid', '42']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['id', 'value'], [['somexmlid', '42']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual( 'somexmlid', self.xid(self.browse()[0])) @@ -123,9 +123,9 @@ class test_ids_stuff(ImporterCase): 36, self.model.browse(self.cr, openerp.SUPERUSER_ID, id).value) - ids, messages = self.import_(['.id', 'value'], [[str(id), '42']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['.id', 'value'], [[str(id), '42']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual( [42], # updated value to imported values(self.read())) @@ -143,12 +143,12 @@ class test_boolean_field(ImporterCase): def test_empty(self): self.assertEqual( self.import_(['value'], []), - ([], [])) + {'ids': [], 'messages': []}) def test_exported(self): - ids, messages = self.import_(['value'], [['False'], ['True'], ]) - self.assertEqual(len(ids), 2) - self.assertFalse(messages) + result = self.import_(['value'], [['False'], ['True'], ]) + self.assertEqual(len(result['ids']), 2) + self.assertFalse(result['messages']) records = self.read() self.assertEqual([ False, @@ -170,18 +170,18 @@ class test_boolean_field(ImporterCase): [u'klaidingas'], # false, lt, ] - ids, messages = self.import_(['value'], falses) - self.assertFalse(messages) - self.assertEqual(len(ids), len(falses)) + result = self.import_(['value'], falses) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), len(falses)) self.assertEqual([False] * len(falses), values(self.read())) def test_trues(self): trues = [['None'], ['nil'], ['()'], ['f'], ['#f'], # Problem: OpenOffice (and probably excel) output localized booleans ['VRAI'], ['ok'], ['true'], ['yes'], ['1'], ] - ids, messages = self.import_(['value'], trues) - self.assertEqual(len(ids), 10) - self.assertEqual(messages, [ + result = self.import_(['value'], trues) + self.assertEqual(len(result['ids']), 10) + self.assertEqual(result['messages'], [ message(u"Unknown value '%s' for boolean field 'unknown', assuming 'yes'" % v[0], type='warning', from_=i, to_=i, record=i) for i, v in enumerate(trues) @@ -197,69 +197,69 @@ class test_integer_field(ImporterCase): def test_none(self): self.assertEqual( self.import_(['value'], []), - ([], [])) + {'ids': [], 'messages': []}) def test_empty(self): - ids, messages = self.import_(['value'], [['']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual( [False], values(self.read())) def test_zero(self): - ids, messages = self.import_(['value'], [['0']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['0']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) - ids, messages = self.import_(['value'], [['-0']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['-0']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual([False, False], values(self.read())) def test_positives(self): - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['1'], ['42'], [str(2**31-1)], ['12345678'] ]) - self.assertEqual(len(ids), 4) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 4) + self.assertFalse(result['messages']) self.assertEqual([ 1, 42, 2**31-1, 12345678 ], values(self.read())) def test_negatives(self): - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['-1'], ['-42'], [str(-(2**31 - 1))], [str(-(2**31))], ['-12345678'] ]) - self.assertEqual(len(ids), 5) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 5) + self.assertFalse(result['messages']) self.assertEqual([ -1, -42, -(2**31 - 1), -(2**31), -12345678 ], values(self.read())) @mute_logger('openerp.sql_db') def test_out_of_range(self): - ids, messages = self.import_(['value'], [[str(2**31)]]) - self.assertIs(ids, False) - self.assertEqual(messages, [{ + result = self.import_(['value'], [[str(2**31)]]) + self.assertIs(result['ids'], False) + self.assertEqual(result['messages'], [{ 'type': 'error', 'rows': {'from': 0, 'to': 0}, 'record': 0, 'message': "integer out of range\n" }]) - ids, messages = self.import_(['value'], [[str(-2**32)]]) - self.assertIs(ids, False) - self.assertEqual(messages, [{ + result = self.import_(['value'], [[str(-2**32)]]) + self.assertIs(result['ids'], False) + self.assertEqual(result['messages'], [{ 'type': 'error', 'rows': {'from': 0, 'to': 0}, 'record': 0, @@ -267,9 +267,9 @@ class test_integer_field(ImporterCase): }]) def test_nonsense(self): - ids, messages = self.import_(['value'], [['zorglub']]) - self.assertIs(ids, False) - self.assertEqual(messages, [{ + result = self.import_(['value'], [['zorglub']]) + self.assertIs(result['ids'], False) + self.assertEqual(result['messages'], [{ 'type': 'error', 'rows': {'from': 0, 'to': 0}, 'record': 0, @@ -282,29 +282,29 @@ class test_float_field(ImporterCase): def test_none(self): self.assertEqual( self.import_(['value'], []), - ([], [])) + {'ids': [], 'messages': []}) def test_empty(self): - ids, messages = self.import_(['value'], [['']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual( [False], values(self.read())) def test_zero(self): - ids, messages = self.import_(['value'], [['0']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['0']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) - ids, messages = self.import_(['value'], [['-0']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['-0']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual([False, False], values(self.read())) def test_positives(self): - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['1'], ['42'], [str(2**31-1)], @@ -312,15 +312,15 @@ class test_float_field(ImporterCase): [str(2**33)], ['0.000001'], ]) - self.assertEqual(len(ids), 6) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 6) + self.assertFalse(result['messages']) self.assertEqual([ 1, 42, 2**31-1, 12345678, 2.0**33, .000001 ], values(self.read())) def test_negatives(self): - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['-1'], ['-42'], [str(-2**31 + 1)], @@ -329,16 +329,16 @@ class test_float_field(ImporterCase): [str(-2**33)], ['-0.000001'], ]) - self.assertEqual(len(ids), 7) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 7) + self.assertFalse(result['messages']) self.assertEqual([ -1, -42, -(2**31 - 1), -(2**31), -12345678, -2.0**33, -.000001 ], values(self.read())) def test_nonsense(self): - ids, messages = self.import_(['value'], [['foobar']]) - self.assertIs(ids, False) - self.assertEqual(messages, [{ + result = self.import_(['value'], [['foobar']]) + self.assertIs(result['ids'], False) + self.assertEqual(result['messages'], [{ 'type': 'error', 'rows': {'from': 0, 'to': 0}, 'record': 0, @@ -350,13 +350,13 @@ class test_string_field(ImporterCase): model_name = 'export.string.bounded' def test_empty(self): - ids, messages = self.import_(['value'], [['']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual([False], values(self.read())) def test_imported(self): - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ [u'foobar'], [u'foobarbaz'], [u'Með suð í eyrum við spilum endalaust'], @@ -364,8 +364,8 @@ class test_string_field(ImporterCase): u"someone he can't pound a nail with a banana doesn't much " u"surprise him."] ]) - self.assertEqual(len(ids), 4) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 4) + self.assertFalse(result['messages']) self.assertEqual([ u"foobar", u"foobarbaz", @@ -377,14 +377,14 @@ class test_unbound_string_field(ImporterCase): model_name = 'export.string' def test_imported(self): - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ [u'í dag viðrar vel til loftárása'], # ackbar.jpg [u"If they ask you about fun, you tell them – fun is a filthy" u" parasite"] ]) - self.assertEqual(len(ids), 2) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 2) + self.assertFalse(result['messages']) self.assertEqual([ u"í dag viðrar vel til loftárása", u"If they ask you about fun, you tell them – fun is a filthy parasite" @@ -394,9 +394,9 @@ class test_text(ImporterCase): model_name = 'export.text' def test_empty(self): - ids, messages = self.import_(['value'], [['']]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['']]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual([False], values(self.read())) def test_imported(self): @@ -406,9 +406,9 @@ class test_text(ImporterCase): u"snúninga 12 tommu vínylplötur (sem geta verið allt að 30 mín " u"hvor hlið).\n\nBreiðskífur eru stundum tvöfaldar og eru þær þá" u" gefnar út á tveimur geisladiskum eða tveimur vínylplötum.") - ids, messages = self.import_(['value'], [[s]]) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [[s]]) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) self.assertEqual([s], values(self.read())) class test_selection(ImporterCase): @@ -420,44 +420,44 @@ class test_selection(ImporterCase): ] def test_imported(self): - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['Qux'], ['Bar'], ['Foo'], ['2'], ]) - self.assertEqual(len(ids), 4) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 4) + self.assertFalse(result['messages']) self.assertEqual([3, 2, 1, 2], values(self.read())) def test_imported_translated(self): self.add_translations( 'export.selection,value', 'selection', 'fr_FR', *self.translations_fr) - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['toto'], ['tete'], ['titi'], ], context={'lang': 'fr_FR'}) - self.assertEqual(len(ids), 3) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 3) + self.assertFalse(result['messages']) self.assertEqual([3, 1, 2], values(self.read())) - ids, messages = self.import_(['value'], [['Foo']], context={'lang': 'fr_FR'}) - self.assertEqual(len(ids), 1) - self.assertFalse(messages) + result = self.import_(['value'], [['Foo']], context={'lang': 'fr_FR'}) + self.assertEqual(len(result['ids']), 1) + self.assertFalse(result['messages']) def test_invalid(self): - ids, messages = self.import_(['value'], [['Baz']]) - self.assertIs(ids, False) - self.assertEqual(messages, [message( + result = self.import_(['value'], [['Baz']]) + self.assertIs(result['ids'], False) + self.assertEqual(result['messages'], [message( u"Value 'Baz' not found in selection field 'unknown'", moreinfo="Foo Bar Qux".split())]) - ids, messages = self.import_(['value'], [[42]]) - self.assertIs(ids, False) - self.assertEqual(messages, [message( + result = self.import_(['value'], [[42]]) + self.assertIs(result['ids'], False) + self.assertEqual(result['messages'], [message( u"Value '42' not found in selection field 'unknown'", moreinfo="Foo Bar Qux".split())]) @@ -476,12 +476,12 @@ class test_selection_function(ImporterCase): import does not actually know that the selection field uses a function """ # NOTE: conflict between a value and a label => pick first - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['3'], ["Grault"], ]) - self.assertEqual(len(ids), 2) - self.assertFalse(messages) + self.assertEqual(len(result['ids']), 2) + self.assertFalse(result['messages']) self.assertEqual( ['3', '1'], values(self.read())) @@ -492,17 +492,17 @@ class test_selection_function(ImporterCase): self.add_translations( 'export.selection,value', 'selection', 'fr_FR', *self.translations_fr) - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['titi'], ['tete'], ], context={'lang': 'fr_FR'}) - self.assertFalse(messages) - self.assertEqual(len(ids), 2) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 2) self.assertEqual(values(self.read()), ['1', '2']) - ids, messages = self.import_(['value'], [['Wheee']], context={'lang': 'fr_FR'}) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + result = self.import_(['value'], [['Wheee']], context={'lang': 'fr_FR'}) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) class test_m2o(ImporterCase): model_name = 'export.many2one' @@ -519,14 +519,14 @@ class test_m2o(ImporterCase): name2 = dict(self.registry('export.integer').name_get( self.cr, openerp.SUPERUSER_ID,[integer_id2]))[integer_id2] - ids , messages = self.import_(['value'], [ + result = self.import_(['value'], [ # import by name_get [name1], [name1], [name2], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 3) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 3) # correct ids assigned to corresponding records self.assertEqual([ (integer_id1, name1), @@ -541,18 +541,18 @@ class test_m2o(ImporterCase): xid = self.xid(ExportInteger.browse( self.cr, openerp.SUPERUSER_ID, [integer_id])[0]) - ids, messages = self.import_(['value/id'], [[xid]]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + result = self.import_(['value/id'], [[xid]]) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) b = self.browse() self.assertEqual(42, b[0].value.value) def test_by_id(self): integer_id = self.registry('export.integer').create( self.cr, openerp.SUPERUSER_ID, {'value': 42}) - ids, messages = self.import_(['value/.id'], [[integer_id]]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + result = self.import_(['value/.id'], [[integer_id]]) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) b = self.browse() self.assertEqual(42, b[0].value.value) @@ -568,12 +568,12 @@ class test_m2o(ImporterCase): # names should be the same self.assertEqual(name1, name2) - ids, messages = self.import_(['value'], [[name2]]) + result = self.import_(['value'], [[name2]]) self.assertEqual( - messages, + result['messages'], [message(u"Found multiple matches for field 'unknown' (2 matches)", type='warning')]) - self.assertEqual(len(ids), 1) + self.assertEqual(len(result['ids']), 1) self.assertEqual([ (integer_id1, name1) ], values(self.read())) @@ -588,55 +588,55 @@ class test_m2o(ImporterCase): self.cr, openerp.SUPERUSER_ID, {'value': 36}) # Because name_search all the things. Fallback schmallback - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ # import by id, without specifying it [integer_id1], [integer_id2], [integer_id1], ]) - self.assertEqual(messages, [ + self.assertEqual(result['messages'], [ message(u"No matching record found for name '%s' in field 'unknown'" % id, from_=index, to_=index, record=index) for index, id in enumerate([integer_id1, integer_id2, integer_id1])]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) def test_sub_field(self): """ Does not implicitly create the record, does not warn that you can't import m2o subfields (at all)... """ - ids, messages = self.import_(['value/value'], [['42']]) - self.assertEqual(messages, [ + result = self.import_(['value/value'], [['42']]) + self.assertEqual(result['messages'], [ message(u"Can not create Many-To-One records indirectly, import " u"the field separately")]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) def test_fail_noids(self): - ids, messages = self.import_(['value'], [['nameisnoexist:3']]) - self.assertEqual(messages, [message( + result = self.import_(['value'], [['nameisnoexist:3']]) + self.assertEqual(result['messages'], [message( u"No matching record found for name 'nameisnoexist:3' " u"in field 'unknown'")]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) - ids, messages = self.import_(['value/id'], [['noxidhere']]) - self.assertEqual(messages, [message( + result = self.import_(['value/id'], [['noxidhere']]) + self.assertEqual(result['messages'], [message( u"No matching record found for external id 'noxidhere' " u"in field 'unknown'")]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) - ids, messages = self.import_(['value/.id'], [['66']]) - self.assertEqual(messages, [message( + result = self.import_(['value/.id'], [['66']]) + self.assertEqual(result['messages'], [message( u"No matching record found for database id '66' " u"in field 'unknown'")]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) def test_fail_multiple(self): - ids, messages = self.import_( + result = self.import_( ['value', 'value/id'], [['somename', 'somexid']]) - self.assertEqual(messages, [message( + self.assertEqual(result['messages'], [message( u"Ambiguous specification for field 'unknown', only provide one of " u"name, external id or database id")]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) class test_m2m(ImporterCase): model_name = 'export.many2many' @@ -656,14 +656,14 @@ class test_m2m(ImporterCase): id5 = self.registry('export.many2many.other').create( self.cr, openerp.SUPERUSER_ID, {'value': 99, 'str': 'record4'}) - ids, messages = self.import_(['value/.id'], [ + result = self.import_(['value/.id'], [ ['%d,%d' % (id1, id2)], ['%d,%d,%d' % (id1, id3, id4)], ['%d,%d,%d' % (id1, id2, id3)], ['%d' % id5] ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 4) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 4) ids = lambda records: [record.id for record in records] @@ -675,11 +675,11 @@ class test_m2m(ImporterCase): self.assertEqual(values(b[2].value), [3, 44, 84]) def test_noids(self): - ids, messages = self.import_(['value/.id'], [['42']]) - self.assertEqual(messages, [message( + result = self.import_(['value/.id'], [['42']]) + self.assertEqual(result['messages'], [message( u"No matching record found for database id '42' in field " u"'unknown'")]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) def test_xids(self): M2O_o = self.registry('export.many2many.other') @@ -689,23 +689,23 @@ class test_m2m(ImporterCase): id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'}) records = M2O_o.browse(self.cr, openerp.SUPERUSER_ID, [id1, id2, id3, id4]) - ids, messages = self.import_(['value/id'], [ + result = self.import_(['value/id'], [ ['%s,%s' % (self.xid(records[0]), self.xid(records[1]))], ['%s' % self.xid(records[3])], ['%s,%s' % (self.xid(records[2]), self.xid(records[1]))], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 3) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 3) b = self.browse() self.assertEqual(values(b[0].value), [3, 44]) self.assertEqual(values(b[2].value), [44, 84]) def test_noxids(self): - ids, messages = self.import_(['value/id'], [['noxidforthat']]) - self.assertEqual(messages, [message( + result = self.import_(['value/id'], [['noxidforthat']]) + self.assertEqual(result['messages'], [message( u"No matching record found for external id 'noxidforthat' " u"in field 'unknown'")]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) def test_names(self): M2O_o = self.registry('export.many2many.other') @@ -717,24 +717,24 @@ class test_m2m(ImporterCase): name = lambda record: dict(record.name_get())[record.id] - ids, messages = self.import_(['value'], [ + result = self.import_(['value'], [ ['%s,%s' % (name(records[1]), name(records[2]))], ['%s,%s,%s' % (name(records[0]), name(records[1]), name(records[2]))], ['%s,%s' % (name(records[0]), name(records[3]))], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 3) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 3) b = self.browse() self.assertEqual(values(b[1].value), [3, 44, 84]) self.assertEqual(values(b[2].value), [3, 9]) def test_nonames(self): - ids, messages = self.import_(['value'], [['wherethem2mhavenonames']]) - self.assertEqual(messages, [message( + result = self.import_(['value'], [['wherethem2mhavenonames']]) + self.assertEqual(result['messages'], [message( u"No matching record found for name 'wherethem2mhavenonames' in " u"field 'unknown'")]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) def test_import_to_existing(self): M2O_o = self.registry('export.many2many.other') @@ -744,12 +744,12 @@ class test_m2m(ImporterCase): id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'}) xid = 'myxid' - ids, messages = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id1, id2)]]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) - ids, messages = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id3, id4)]]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + result = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id1, id2)]]) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) + result = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id3, id4)]]) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) b = self.browse() self.assertEqual(len(b), 1) @@ -762,31 +762,31 @@ class test_o2m(ImporterCase): def test_name_get(self): s = u'Java is a DSL for taking large XML files and converting them ' \ u'to stack traces' - ids, messages = self.import_( + result = self.import_( ['const', 'value'], [['5', s]]) - self.assertEqual(messages, [message( + self.assertEqual(result['messages'], [message( u"No matching record found for name '%s' in field 'unknown'" % s)]) - self.assertIs(ids, False) + self.assertIs(result['ids'], False) def test_single(self): - ids, messages = self.import_(['const', 'value/value'], [ + result = self.import_(['const', 'value/value'], [ ['5', '63'] ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) (b,) = self.browse() self.assertEqual(b.const, 5) self.assertEqual(values(b.value), [63]) def test_multicore(self): - ids, messages = self.import_(['const', 'value/value'], [ + result = self.import_(['const', 'value/value'], [ ['5', '63'], ['6', '64'], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 2) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 2) b1, b2 = self.browse() self.assertEqual(b1.const, 5) @@ -795,27 +795,27 @@ class test_o2m(ImporterCase): self.assertEqual(values(b2.value), [64]) def test_multisub(self): - ids, messages = self.import_(['const', 'value/value'], [ + result = self.import_(['const', 'value/value'], [ ['5', '63'], ['', '64'], ['', '65'], ['', '66'], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) (b,) = self.browse() self.assertEqual(values(b.value), [63, 64, 65, 66]) def test_multi_subfields(self): - ids, messages = self.import_(['value/str', 'const', 'value/value'], [ + result = self.import_(['value/str', 'const', 'value/value'], [ ['this', '5', '63'], ['is', '', '64'], ['the', '', '65'], ['rhythm', '', '66'], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) (b,) = self.browse() self.assertEqual(values(b.value), [63, 64, 65, 66]) @@ -833,11 +833,11 @@ class test_o2m(ImporterCase): 'str': 'Me', 'value': 262 }) - ids, messages = self.import_(['const', 'value/.id'], [ + result = self.import_(['const', 'value/.id'], [ ['42', '%d,%d' % (id1, id2)] ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) [b] = self.browse() self.assertEqual(b.const, 42) @@ -856,12 +856,12 @@ class test_o2m(ImporterCase): 'str': 'Me', 'value': 262 }) - ids, messages = self.import_(['const', 'value/.id'], [ + result = self.import_(['const', 'value/.id'], [ ['42', str(id1)], ['', str(id2)], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) [b] = self.browse() self.assertEqual(b.const, 42) @@ -878,12 +878,12 @@ class test_o2m(ImporterCase): 'str': 'Me', 'value': 262 }) - ids, messages = self.import_(['const', 'value/.id', 'value/value'], [ + result = self.import_(['const', 'value/.id', 'value/value'], [ ['42', str(id1), '1'], ['', str(id2), '2'], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) [b] = self.browse() self.assertEqual(b.const, 42) @@ -894,21 +894,21 @@ class test_o2m_multiple(ImporterCase): model_name = 'export.one2many.multiple' def test_multi_mixed(self): - ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [ + result = self.import_(['const', 'child1/value', 'child2/value'], [ ['5', '11', '21'], ['', '12', '22'], ['', '13', '23'], ['', '14', ''], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) # Oh yeah, that's the stuff [b] = self.browse() self.assertEqual(values(b.child1), [11, 12, 13, 14]) self.assertEqual(values(b.child2), [21, 22, 23]) def test_multi(self): - ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [ + result = self.import_(['const', 'child1/value', 'child2/value'], [ ['5', '11', '21'], ['', '12', ''], ['', '13', ''], @@ -916,15 +916,15 @@ class test_o2m_multiple(ImporterCase): ['', '', '22'], ['', '', '23'], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) [b] = self.browse() self.assertEqual(values(b.child1), [11, 12, 13, 14]) self.assertEqual(values(b.child2), [21, 22, 23]) def test_multi_fullsplit(self): - ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [ + result = self.import_(['const', 'child1/value', 'child2/value'], [ ['5', '11', ''], ['', '12', ''], ['', '13', ''], @@ -933,8 +933,8 @@ class test_o2m_multiple(ImporterCase): ['', '', '22'], ['', '', '23'], ]) - self.assertFalse(messages) - self.assertEqual(len(ids), 1) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) [b] = self.browse() self.assertEqual(b.const, 5) From e6c8f1739a70ba8c0252ed8ace839c30f7e794dc Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 25 Sep 2012 09:42:56 +0200 Subject: [PATCH 044/409] [ADD] 'more info' action to m2o, o2m and m2m linking failures bzr revid: xmo@openerp.com-20120925074256-18puerjbfo3om265 --- openerp/addons/base/ir/ir_fields.py | 31 +++++++------- .../addons/test_impex/tests/test_load.py | 42 +++++++++---------- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py index 2256542533b..cec74e8976e 100644 --- a/openerp/addons/base/ir/ir_fields.py +++ b/openerp/addons/base/ir/ir_fields.py @@ -201,6 +201,21 @@ class ir_fields_converter(orm.Model): id, _name = ids[0] else: raise Exception(u"Unknown sub-field '%s'" % subfield) + + if id is None: + raise ValueError( + _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'") + % {'field_type': field_type, 'value': value}, { + 'moreinfo': { + 'type': 'ir.actions.act_window', + 'target': 'new', + 'res_model': column._obj, + 'view_mode': 'tree,form', + 'view_type': 'form', + 'views': [(False, 'tree', (False, 'form'))], + 'help': _(u"See all possible values") + } + }) return id, field_type def _referencing_subfield(self, record): @@ -235,12 +250,8 @@ class ir_fields_converter(orm.Model): reference = record[subfield] id, subfield_type = self.db_id_for( cr, uid, model, column, subfield, reference, context=context) - - if id is None: - raise ValueError( - _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'") - % {'field_type': subfield_type, 'value': reference}) return id + def _str_to_many2many(self, cr, uid, model, column, value, context=None): [record] = value @@ -250,13 +261,9 @@ class ir_fields_converter(orm.Model): for reference in record[subfield].split(','): id, subfield_type = self.db_id_for( cr, uid, model, column, subfield, reference, context=context) - if id is None: - raise ValueError( - _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'") - % {'field_type': subfield_type, 'value': reference}) ids.append(id) - return [(6, 0, ids)] + def _str_to_one2many(self, cr, uid, model, column, records, context=None): commands = [] @@ -278,10 +285,6 @@ class ir_fields_converter(orm.Model): reference = record[subfield] id, subfield_type = self.db_id_for( cr, uid, model, column, subfield, reference, context=context) - if id is None: - raise ValueError( - _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'") - % {'field_type': subfield_type, 'value': reference}) writable = exclude_ref_fields(record) if id: diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index 060b32c48f5..f625ecb7043 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -9,18 +9,16 @@ def message(msg, type='error', from_=0, to_=0, record=0, field='value', **kwargs return dict(kwargs, type=type, rows={'from': from_, 'to': to_}, record=record, field=field, message=msg) - -def error(row, message, record=None, **kwargs): - """ Failed import of the record ``record`` at line ``row``, with the error - message ``message`` - - :param str message: - :param dict record: - """ - return ( - -1, dict(record or {}, **kwargs), - "Line %d : %s" % (row, message), - '') +def moreaction(model): + return { + 'type': 'ir.actions.act_window', + 'target': 'new', + 'res_model': model, + 'view_mode': 'tree,form', + 'view_type': 'form', + 'views': [(False, 'tree', (False, 'form'))], + 'help': u"See all possible values" + } def values(seq, field='value'): return [item[field] for item in seq] @@ -596,7 +594,8 @@ class test_m2o(ImporterCase): ]) self.assertEqual(result['messages'], [ message(u"No matching record found for name '%s' in field 'unknown'" % id, - from_=index, to_=index, record=index) + from_=index, to_=index, record=index, + moreinfo=moreaction('export.integer')) for index, id in enumerate([integer_id1, integer_id2, integer_id1])]) self.assertIs(result['ids'], False) @@ -614,19 +613,19 @@ class test_m2o(ImporterCase): result = self.import_(['value'], [['nameisnoexist:3']]) self.assertEqual(result['messages'], [message( u"No matching record found for name 'nameisnoexist:3' " - u"in field 'unknown'")]) + u"in field 'unknown'", moreinfo=moreaction('export.integer'))]) self.assertIs(result['ids'], False) result = self.import_(['value/id'], [['noxidhere']]) self.assertEqual(result['messages'], [message( u"No matching record found for external id 'noxidhere' " - u"in field 'unknown'")]) + u"in field 'unknown'", moreinfo=moreaction('export.integer'))]) self.assertIs(result['ids'], False) result = self.import_(['value/.id'], [['66']]) self.assertEqual(result['messages'], [message( u"No matching record found for database id '66' " - u"in field 'unknown'")]) + u"in field 'unknown'", moreinfo=moreaction('export.integer'))]) self.assertIs(result['ids'], False) def test_fail_multiple(self): @@ -678,7 +677,7 @@ class test_m2m(ImporterCase): result = self.import_(['value/.id'], [['42']]) self.assertEqual(result['messages'], [message( u"No matching record found for database id '42' in field " - u"'unknown'")]) + u"'unknown'", moreinfo=moreaction('export.many2many.other'))]) self.assertIs(result['ids'], False) def test_xids(self): @@ -703,8 +702,8 @@ class test_m2m(ImporterCase): def test_noxids(self): result = self.import_(['value/id'], [['noxidforthat']]) self.assertEqual(result['messages'], [message( - u"No matching record found for external id 'noxidforthat' " - u"in field 'unknown'")]) + u"No matching record found for external id 'noxidforthat' in field" + u" 'unknown'", moreinfo=moreaction('export.many2many.other'))]) self.assertIs(result['ids'], False) def test_names(self): @@ -733,7 +732,7 @@ class test_m2m(ImporterCase): result = self.import_(['value'], [['wherethem2mhavenonames']]) self.assertEqual(result['messages'], [message( u"No matching record found for name 'wherethem2mhavenonames' in " - u"field 'unknown'")]) + u"field 'unknown'", moreinfo=moreaction('export.many2many.other'))]) self.assertIs(result['ids'], False) def test_import_to_existing(self): @@ -766,7 +765,8 @@ class test_o2m(ImporterCase): ['const', 'value'], [['5', s]]) self.assertEqual(result['messages'], [message( - u"No matching record found for name '%s' in field 'unknown'" % s)]) + u"No matching record found for name '%s' in field 'unknown'" % s, + moreinfo=moreaction('export.one2many.child'))]) self.assertIs(result['ids'], False) def test_single(self): From 359b4a44aa2d10cac6a0ce9bd623ac6b4e1a17d7 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 25 Sep 2012 12:02:32 +0200 Subject: [PATCH 045/409] [ADD] ability to convert postgres error messages to human-readable ones also convert 'violates not-null constraint' to something about fields being required bzr revid: xmo@openerp.com-20120925100232-bfmxcxda65cki5kv --- openerp/osv/orm.py | 31 ++++++++++++++++++- openerp/tests/addons/test_impex/models.py | 1 + .../addons/test_impex/tests/test_load.py | 15 +++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index b824be91b96..25974760bdd 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -42,6 +42,7 @@ """ import calendar +import collections import copy import datetime import itertools @@ -1493,6 +1494,7 @@ class BaseModel(object): fields = map(fix_import_export_id_paths, fields) ModelData = self.pool['ir.model.data'] + fg = self.fields_get(cr, uid, context=context) mode = 'init' current_module = '' @@ -1509,11 +1511,16 @@ class BaseModel(object): current_module, record, mode=mode, xml_id=xid, noupdate=noupdate, res_id=id, context=context)) cr.execute('RELEASE SAVEPOINT model_load_save') + except psycopg2.Warning, e: + cr.execute('ROLLBACK TO SAVEPOINT model_load_save') + messages.append(dict(info, type='warning', message=str(e))) except psycopg2.Error, e: # Failed to write, log to messages, rollback savepoint (to # avoid broken transaction) and keep going cr.execute('ROLLBACK TO SAVEPOINT model_load_save') - messages.append(dict(info, type="error", message=str(e))) + messages.append(dict( + info, type="error", + **PGERROR_TO_OE[e.pgcode](self, fg, info, e))) if any(message['type'] == 'error' for message in messages): cr.execute('ROLLBACK TO SAVEPOINT model_load') ids = False @@ -5390,4 +5397,26 @@ class ImportWarning(Warning): """ Used to send warnings upwards the stack during the import process """ pass + + +def convert_pgerror_23502(model, fields, info, e): + m = re.match(r'^null value in column "(?P\w+)" violates ' + r'not-null constraint\n$', + str(e)) + if not m or m.group('field') not in fields: + return {'message': unicode(e)} + field = fields[m.group('field')] + return { + 'message': _(u"Missing required value for the field '%(field)s'") % { + 'field': field['string'] + }, + 'field': m.group('field'), + } + +PGERROR_TO_OE = collections.defaultdict( + # shape of mapped converters + lambda: (lambda model, fvg, info, pgerror: {'message': unicode(pgerror)}), { + # not_null_violation + '23502': convert_pgerror_23502, +}) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/tests/addons/test_impex/models.py b/openerp/tests/addons/test_impex/models.py index 37894ccb78c..c56ddc649e2 100644 --- a/openerp/tests/addons/test_impex/models.py +++ b/openerp/tests/addons/test_impex/models.py @@ -17,6 +17,7 @@ models = [ ('float', fields.float()), ('decimal', fields.float(digits=(16, 3))), ('string.bounded', fields.char('unknown', size=16)), + ('string.required', fields.char('unknown', size=None, required=True)), ('string', fields.char('unknown', size=None)), ('date', fields.date()), ('datetime', fields.datetime()), diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index f625ecb7043..eb777a57988 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -388,6 +388,21 @@ class test_unbound_string_field(ImporterCase): u"If they ask you about fun, you tell them – fun is a filthy parasite" ], values(self.read())) +class test_required_string_field(ImporterCase): + model_name = 'export.string.required' + + def test_empty(self): + result = self.import_(['value'], [[]]) + self.assertEqual(result['messages'], [message( + u"Missing required value for the field 'unknown'")]) + self.assertIs(result['ids'], False) + + def test_not_provided(self): + result = self.import_(['const'], [['12']]) + self.assertEqual(result['messages'], [message( + u"Missing required value for the field 'unknown'")]) + self.assertIs(result['ids'], False) + class test_text(ImporterCase): model_name = 'export.text' From aceae3501efeece3366db5a478bf450067e37301 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 25 Sep 2012 12:40:13 +0200 Subject: [PATCH 046/409] [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 047/409] [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 048/409] [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 d5c69fa87e9d17c92c00347af73fce53fb47dcd4 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 25 Sep 2012 15:59:55 +0200 Subject: [PATCH 049/409] [FIX] use lists instead of iterators in BaseModel._extract_records * although it does use an explicit external index, it turns out the code is less complex * the rewrapping of (many) iterators on top of one another ended up blowing Python's stack during ``next`` calls, which Python does *not* like * added a 900-ish import test file to check for these things bzr revid: xmo@openerp.com-20120925135955-oielhopegnefyctm --- openerp/addons/base/ir/ir_fields.py | 5 +- openerp/osv/orm.py | 53 +++++-------------- .../addons/test_impex/tests/test_load.py | 13 +++++ 3 files changed, 30 insertions(+), 41 deletions(-) diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py index cec74e8976e..03d95fc67a6 100644 --- a/openerp/addons/base/ir/ir_fields.py +++ b/openerp/addons/base/ir/ir_fields.py @@ -69,7 +69,7 @@ class ir_fields_converter(orm.Model): """ # FIXME: return None converter = getattr( - self, '_%s_to_%s' % (fromtype.__name__, column._type)) + self, '_%s_to_%s' % (fromtype.__name__, column._type), None) if not converter: return None return functools.partial( @@ -113,6 +113,9 @@ class ir_fields_converter(orm.Model): def _str_to_text(self, cr, uid, model, column, value, context=None): return value or False + def _str_to_binary(self, cr, uid, model, column, value, context=None): + return value or False + def _get_translations(self, cr, uid, types, src, context): types = tuple(types) # Cache translations so they don't have to be reloaded from scratch on diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 25974760bdd..eb7745b2f6e 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1527,7 +1527,7 @@ class BaseModel(object): return {'ids': ids, 'messages': messages} def _extract_records(self, cr, uid, fields_, data, context=None, log=lambda a: None): - """ Generates record dicts from the data iterable. + """ Generates record dicts from the data sequence. The result is a generator of dicts mapping field names to raw (unconverted, unvalidated) values. @@ -1562,12 +1562,11 @@ class BaseModel(object): def only_o2m_values(row, f=get_nono2m_values, g=get_o2m_values): return any(g(row)) and not any(f(row)) - rows = CountingStream(data) + index = 0 while True: - row = next(rows, None) - if row is None: return - record_row_index = rows.index + if index >= len(data): return + row = data[index] # copy non-relational fields to record dict record = dict((field[0], value) for field, value in itertools.izip(fields_, row) @@ -1575,10 +1574,10 @@ class BaseModel(object): # Get all following rows which have relational values attached to # the current record (no non-relational values) - # WARNING: replaces existing ``rows`` - record_span, _rows = span(only_o2m_values, rows) + record_span = itertools.takewhile( + only_o2m_values, itertools.islice(data, index + 1, None)) # stitch record row back on for relational fields - record_span = itertools.chain([row], record_span) + record_span = list(itertools.chain([row], record_span)) for relfield in set( field[0] for field in fields_ if is_relational(field[0])): @@ -1586,8 +1585,6 @@ class BaseModel(object): # FIXME: how to not use _obj without relying on fields_get? Model = self.pool[column._obj] - # copy stream to reuse for next relational field - fieldrows, record_span = itertools.tee(record_span) # get only cells for this sub-field, should be strictly # non-empty, field path [None] is for name_get column indices, subfields = zip(*((index, field[1:] or [None]) @@ -1596,26 +1593,17 @@ class BaseModel(object): # return all rows which have at least one value for the # subfields of relfield - relfield_data = filter(any, map(itemgetter_tuple(indices), fieldrows)) + relfield_data = filter(any, map(itemgetter_tuple(indices), record_span)) record[relfield] = [subrecord for subrecord, _subinfo in Model._extract_records( cr, uid, subfields, relfield_data, context=context, log=log)] - # Ensure full consumption of the span (and therefore advancement of - # ``rows``) even if there are no relational fields. Needs two as - # the code above stiched the row back on (so first call may only - # get the stiched row without advancing the underlying operator row - # itself) - next(record_span, None) - next(record_span, None) - # old rows consumption (by iterating the span) should be done here, - # at this point the old ``rows`` is 1 past `span` (either on the - # next record row or past ``StopIteration``, so wrap new ``rows`` - # (``_rows``) in a counting stream indexed 1-before the old - # ``rows`` - rows = CountingStream(_rows, rows.index - 1) - yield record, {'rows': {'from': record_row_index,'to': rows.index}} + yield record, {'rows': { + 'from': index, + 'to': index + len(record_span) - 1 + }} + index += len(record_span) def _convert_records(self, cr, uid, records, context=None, log=lambda a: None): """ Converts records from the source iterable (recursive dicts of @@ -5369,21 +5357,6 @@ class AbstractModel(BaseModel): _auto = False # don't create any database backend for AbstractModels _register = False # not visible in ORM registry, meant to be python-inherited only -def span(predicate, iterable): - """ Splits the iterable between the longest prefix of ``iterable`` whose - elements satisfy ``predicate`` and the rest. - - If called with a list, equivalent to:: - - takewhile(predicate, lst), dropwhile(predicate, lst) - - :param callable predicate: - :param iterable: - :rtype: (iterable, iterable) - """ - it1, it2 = itertools.tee(iterable) - return (itertools.takewhile(predicate, it1), - itertools.dropwhile(predicate, it2)) def itemgetter_tuple(items): """ Fixes itemgetter inconsistency (useful in some cases) of not returning a tuple if len(items) == 1: always returns an n-tuple where n = len(items) diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index eb777a57988..72442963af5 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +import json +import pkgutil + import openerp.modules.registry import openerp @@ -956,5 +959,15 @@ class test_o2m_multiple(ImporterCase): self.assertEqual(values(b.child1), [11, 12, 13, 14]) self.assertEqual(values(b.child2), [21, 22, 23]) +class test_realworld(common.TransactionCase): + def test_bigfile(self): + data = json.loads(pkgutil.get_data(self.__module__, 'contacts_big.json')) + result = self.registry('res.partner').load( + self.cr, openerp.SUPERUSER_ID, + ['name', 'mobile', 'email', 'image'], + data) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), len(data)) + # function, related, reference: written to db as-is... # => function uses @type for value coercion/conversion From 9906a2bda10ca089fff55521f3252f4f8b178344 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 25 Sep 2012 16:34:33 +0200 Subject: [PATCH 050/409] [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 e61dc509341ed2cd1222869048a81b2db209e21d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 25 Sep 2012 17:59:15 +0200 Subject: [PATCH 051/409] [IMP] convert empty import fields to False values without going through converters simplifies the converter methods by avoiding redundant emptiness checks bzr revid: xmo@openerp.com-20120925155915-82p2s6stpww37p5n --- openerp/addons/base/ir/ir_fields.py | 8 +++----- openerp/osv/orm.py | 4 +++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py index 03d95fc67a6..621dd93d469 100644 --- a/openerp/addons/base/ir/ir_fields.py +++ b/openerp/addons/base/ir/ir_fields.py @@ -100,21 +100,19 @@ class ir_fields_converter(orm.Model): return True def _str_to_integer(self, cr, uid, model, column, value, context=None): - if not value: return False return int(value) def _str_to_float(self, cr, uid, model, column, value, context=None): - if not value: return False return float(value) def _str_to_char(self, cr, uid, model, column, value, context=None): - return value or False + return value def _str_to_text(self, cr, uid, model, column, value, context=None): - return value or False + return value def _str_to_binary(self, cr, uid, model, column, value, context=None): - return value or False + return value def _get_translations(self, cr, uid, types, src, context): types = tuple(types) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index eb7745b2f6e..81063deb180 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -68,7 +68,6 @@ from openerp.tools.safe_eval import safe_eval as eval from openerp.tools.translate import _ from openerp import SUPERUSER_ID from query import Query -from openerp import SUPERUSER_ID _logger = logging.getLogger(__name__) _schema = logging.getLogger(__name__ + '.schema') @@ -1662,6 +1661,9 @@ class BaseModel(object): for field, strvalue in record.iteritems(): if field in (None, 'id', '.id'): continue + if not strvalue: + converted[field] = False + continue # In warnings and error messages, use translated string as # field name From a912bb31890a9d1d81f8b267e2ba2e0d0ca53dbe Mon Sep 17 00:00:00 2001 From: Saurang Suthar Date: Wed, 26 Sep 2012 12:33:39 +0530 Subject: [PATCH 052/409] [IMP]openerp:rename the group Partner Manager -> Contact Creation bzr revid: ssu@tinyerp.com-20120926070339-sr9lv02l5632ml1t --- openerp/addons/base/res/res_security.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_security.xml b/openerp/addons/base/res/res_security.xml index acec903c1a3..783243411ef 100644 --- a/openerp/addons/base/res/res_security.xml +++ b/openerp/addons/base/res/res_security.xml @@ -3,7 +3,7 @@ - Partner Manager + Contact Creation From 627bb128e04991fad61688b8b86ca82061a90977 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 26 Sep 2012 10:25:30 +0200 Subject: [PATCH 053/409] [IMP] adapt base_import to using Model.load instead of Model.import_data bzr revid: xmo@openerp.com-20120926082530-krhladsrn9mzs3lx --- addons/base_import/models.py | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/addons/base_import/models.py b/addons/base_import/models.py index 1e5ad002b84..733532ae095 100644 --- a/addons/base_import/models.py +++ b/addons/base_import/models.py @@ -307,22 +307,14 @@ class ir_import(orm.TransientModel): except ValueError, e: return [{ 'type': 'error', - 'message': str(e), + 'message': unicode(e), 'record': False, }] - try: - _logger.info('importing %d rows...', len(data)) - (code, record, message, _wat) = self.pool[record.res_model].import_data( - cr, uid, import_fields, data, context=context) - _logger.info('done') - - except Exception, e: - _logger.exception("Import failed") - # TODO: remove when exceptions stop being an "expected" - # behavior of import_data on some (most) invalid - # input. - code, record, message = -1, None, str(e) + _logger.info('importing %d rows...', len(data)) + import_result = self.pool[record.res_model].load( + cr, uid, import_fields, data, context=context) + _logger.info('done') # If transaction aborted, RELEASE SAVEPOINT is going to raise # an InternalError (ROLLBACK should work, maybe). Ignore that. @@ -339,14 +331,4 @@ class ir_import(orm.TransientModel): except psycopg2.InternalError: pass - if code != -1: - return [] - - # TODO: add key for error location? - # TODO: error not within normal preview, how to display? Re-preview - # with higher ``count``? - return [{ - 'type': 'error', - 'message': message, - 'record': record or False - }] + return import_result['messages'] From a50dfa668d9de6fe8e054deb24366d99b21e3d96 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 26 Sep 2012 11:53:53 +0200 Subject: [PATCH 054/409] [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 fd5d4e5dd34eeeec885ffd2fe5ae340c5bebb00c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 26 Sep 2012 13:42:35 +0200 Subject: [PATCH 055/409] [IMP] don't display deprecated fields in import window bzr revid: xmo@openerp.com-20120926114235-iqkmi23yk2v1hq7w --- addons/base_import/models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/base_import/models.py b/addons/base_import/models.py index 733532ae095..16bb52d5856 100644 --- a/addons/base_import/models.py +++ b/addons/base_import/models.py @@ -83,6 +83,10 @@ class ir_import(orm.TransientModel): }] fields_got = self.pool[model].fields_get(cr, uid, context=context) for name, field in fields_got.iteritems(): + # an empty string means the field is deprecated, @deprecated must + # be absent or False to mean not-deprecated + if field.get('deprecated', False) is not False: + continue if field.get('readonly'): states = field.get('states') if not states: @@ -97,7 +101,7 @@ class ir_import(orm.TransientModel): 'id': name, 'name': name, 'string': field['string'], - # Y U NO ALWAYS HAVE REQUIRED + # Y U NO ALWAYS HAS REQUIRED 'required': bool(field.get('required')), 'fields': [], } From 0605295602606a7e25f075f5e6bbfdd446e63dfc Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 26 Sep 2012 15:02:41 +0200 Subject: [PATCH 056/409] [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 f6f37632ceb0ed2a6abd043c884e5e9de1cb8d51 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 26 Sep 2012 15:50:13 +0200 Subject: [PATCH 057/409] [IMP] errors display, dryrun management (add button) bzr revid: xmo@openerp.com-20120926135013-rkbvxluu6tqz9a1l --- addons/base_import/static/src/js/import.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index c2deb660ff2..9cb2f74bd48 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -63,7 +63,7 @@ openerp.base_import = function (instance) { {name: 'quoting', label: _lt("Quoting:"), value: '"'} ], events: { - 'change .oe_import_grid input': 'import_dryrun', + // 'change .oe_import_grid input': 'import_dryrun', 'change input.oe_import_file': 'file_update', 'change input.oe_import_has_header, .oe_import_options input': 'settings_updated', 'click a.oe_import_csv': function (e) { @@ -85,9 +85,10 @@ openerp.base_import = function (instance) { var self = this; this._super(parent, { buttons: [ - {text: _t("Import File"), click: function () { - self.do_import(); - }, 'class': 'oe_import_dialog_button'} + {text: _t("Import"), click: self.proxy('do_import'), + 'class': 'oe_import_dialog_button'}, + {text: _t("Validate"), click: self.proxy('import_dryrun'), + 'class': 'oe_import_dialog_button'} ] }); this.res_model = parent.model; @@ -134,11 +135,12 @@ openerp.base_import = function (instance) { .then(this.proxy('preview')); }, preview: function (result) { + this.$el.removeClass('oe_import_preview_error oe_import_error'); this.$el.toggleClass( 'oe_import_noheaders', !this.$('input.oe_import_has_header').prop('checked')); if (result.error) { - this.$el.addClass('oe_import_error'); + this.$el.addClass('oe_import_preview_error oe_import_error'); this.$('.oe_import_error_report').html( QWeb.render('ImportView.preview.error', result)); return; @@ -180,7 +182,7 @@ openerp.base_import = function (instance) { width: 'resolve', dropdownCssClass: 'oe_import_selector' }); - this.import_dryrun(); + //this.import_dryrun(); }, generate_fields_completion: function (root) { var basic = []; @@ -252,7 +254,6 @@ openerp.base_import = function (instance) { //- import itself call_import: function (options) { - var self = this; var fields = this.$('.oe_import_fields input.oe_import_match_field').map(function (index, el) { return $(el).select2('val') || false; }).get(); @@ -260,12 +261,12 @@ openerp.base_import = function (instance) { 'do', [this.id, fields, this.import_options()], options); }, import_dryrun: function () { -// this.call_import({ dryrun: true }) -// .then(this.proxy('render_import_errors')); + return this.call_import({ dryrun: true }) + .then(this.proxy('render_import_errors')); }, do_import: function () { var self = this; - this.call_import({ dryrun: false }).then(function (errors) { + return this.call_import({ dryrun: false }).then(function (errors) { if (_.isEmpty(errors)) { if (self.getParent().reload_content) { self.getParent().reload_content(); From 479dfb7ea079184c60dc39929c68ab37ada639e1 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 26 Sep 2012 17:04:59 +0200 Subject: [PATCH 058/409] [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 27aeae974aa4a001e7c8f13cd01f98a5ca295334 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 26 Sep 2012 18:50:52 +0200 Subject: [PATCH 059/409] [IMP] warning and error reporting during import bzr revid: xmo@openerp.com-20120926165052-7eq4ne62h63zbqqm --- addons/base_import/static/src/css/import.css | 6 ++- addons/base_import/static/src/js/import.js | 41 +++++++++++++++----- addons/base_import/static/src/xml/import.xml | 26 +++++++++++-- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/addons/base_import/static/src/css/import.css b/addons/base_import/static/src/css/import.css index f6258f5aa50..da61473fdba 100644 --- a/addons/base_import/static/src/css/import.css +++ b/addons/base_import/static/src/css/import.css @@ -10,7 +10,8 @@ .oe_import .oe_import_grid, .oe_import .oe_import_error_report, .oe_import .oe_import_with_file, -.oe_import .oe_import_noheaders { +.oe_import .oe_import_noheaders, +.oe_import .oe_import_report_more { display: none; } @@ -19,7 +20,8 @@ } .oe_import.oe_import_error .oe_import_error_report, .oe_import.oe_import_with_file .oe_import_with_file, -.oe_import.oe_import_noheaders .oe_import_noheaders { +.oe_import.oe_import_noheaders .oe_import_noheaders, +.oe_import .oe_import_report_showmore .oe_import_report_more { display: block; } diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index 9cb2f74bd48..d5f059d0656 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -79,6 +79,10 @@ openerp.base_import = function (instance) { ? $el.next() : $el.parent().next()) .toggle(); + }, + 'click .oe_import_report a.oe_import_report_count': function (e) { + e.preventDefault(); + $(e.target).parent().toggleClass('oe_import_report_showmore'); } }, init: function (parent, dataset) { @@ -262,31 +266,50 @@ openerp.base_import = function (instance) { }, import_dryrun: function () { return this.call_import({ dryrun: true }) - .then(this.proxy('render_import_errors')); + .then(this.proxy('render_import_result')); }, do_import: function () { var self = this; - return this.call_import({ dryrun: false }).then(function (errors) { - if (_.isEmpty(errors)) { + return this.call_import({ dryrun: false }).then(function (message) { + if (!_.any(message, function (message) { + return message.type === 'error' })) { if (self.getParent().reload_content) { self.getParent().reload_content(); } self.close(); return; } - self.render_import_errors(errors); + self.render_import_result(message); }); }, - render_import_errors: function (errors) { - if (_.isEmpty(errors)) { + render_import_result: function (message) { + if (_.isEmpty(message)) { this.$el.removeClass('oe_import_error'); return; } - // import failed (or maybe just warnings, if we ever get - // warnings?) + // row indexes come back 0-indexed, spreadsheets + // display 1-indexed. + var offset = 1; + // offset more if header + if (this.import_options().header) { offset += 1; } + this.$el.addClass('oe_import_error'); this.$('.oe_import_error_report').html( - QWeb.render('ImportView.error', {errors: errors})); + QWeb.render('ImportView.error', { + errors: _(message).groupBy('message'), + at: function (rows) { + var from = rows.from + offset; + var to = rows.to + offset; + if (from === to) { + return _.str.sprintf(_t("at row %d"), from); + } + return _.str.sprintf(_t("between rows %d and %d"), + from, to); + }, + more: function (n) { + return _.str.sprintf(_t("(%d times more)"), n); + }, + })); }, }); }; diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml index 386348bea4b..5d36eae4d2d 100644 --- a/addons/base_import/static/src/xml/import.xml +++ b/addons/base_import/static/src/xml/import.xml @@ -86,12 +86,30 @@
      -
    • - - +
    • + + + + + + + +
        +
      • + + + +
      • +
    + + + + + + this.attr('t-if', 'widget.options.import_enabled'); From 4d7576393a3e0efadf639dbe9958725f76ae6f10 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 27 Sep 2012 09:48:45 +0200 Subject: [PATCH 060/409] [ADD] unstyled and incomplete handling of @moreinfo action triggering is still missing bzr revid: xmo@openerp.com-20120927074845-pb3osgymmtddglc0 --- addons/base_import/static/src/js/import.js | 35 +++++++++++++++++++- addons/base_import/static/src/xml/import.xml | 3 +- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index d5f059d0656..ac81f89c7a9 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -83,6 +83,12 @@ openerp.base_import = function (instance) { 'click .oe_import_report a.oe_import_report_count': function (e) { e.preventDefault(); $(e.target).parent().toggleClass('oe_import_report_showmore'); + }, + 'click .oe_import_moreinfo_action a': function (e) { + e.preventDefault(); + // #data will parse the attribute on its own, we don't like that + var action = JSON.parse($(e.target).attr('data-action')); + console.log(action); } }, init: function (parent, dataset) { @@ -307,7 +313,34 @@ openerp.base_import = function (instance) { from, to); }, more: function (n) { - return _.str.sprintf(_t("(%d times more)"), n); + return _.str.sprintf(_t("(%d more)"), n); + }, + info: function (msg) { + if (typeof msg === 'string') { + return _.str.sprintf( + '
    %s
    ', + _.str.escapeHTML(msg)); + } + if (msg instanceof Array) { + return _.str.sprintf( + '
    %s
      %s
    ', + _.str.escapeHTML(_t("Here are the possible values:")), + _(msg).map(function (msg) { + return '
  • ' + + _.str.escapeHTML(msg) + + '
  • '; + }).join()); + } + // Final should be object, action descriptor + return [ + '' + ].join('') }, })); }, diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml index 5d36eae4d2d..2efd0b5a752 100644 --- a/addons/base_import/static/src/xml/import.xml +++ b/addons/base_import/static/src/xml/import.xml @@ -108,7 +108,8 @@ - + + From b80d84aafc7f4d543247d22d445e71752272f925 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Thu, 27 Sep 2012 10:27:04 +0200 Subject: [PATCH 061/409] [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 4787939773e175475c03d70c4e32fdf0eeea1097 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 27 Sep 2012 11:49:50 +0200 Subject: [PATCH 062/409] [FIX] correctly transform 'get all possible values' action links to display list views as list views bzr revid: xmo@openerp.com-20120927094950-pwlgv2kt2a0jz8ji --- addons/base_import/static/src/js/import.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index ac81f89c7a9..8a73bcd5d71 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -86,9 +86,20 @@ openerp.base_import = function (instance) { }, 'click .oe_import_moreinfo_action a': function (e) { e.preventDefault(); - // #data will parse the attribute on its own, we don't like that + // #data will parse the attribute on its own, we don't like + // that sort of things var action = JSON.parse($(e.target).attr('data-action')); - console.log(action); + // FIXME: when JS-side clean_action + action.views = _(action.views).map(function (view) { + var id = view[0], type = view[1]; + return [ + id, + type !== 'tree' ? type + : action.view_type === 'form' ? 'list' + : 'tree' + ]; + }); + this.do_action(_.extend(action, {target: 'new'})); } }, init: function (parent, dataset) { @@ -329,7 +340,7 @@ openerp.base_import = function (instance) { return '
  • ' + _.str.escapeHTML(msg) + '
  • '; - }).join()); + }).join('')); } // Final should be object, action descriptor return [ From 9a721eba322dcdf6c3a7cab27f8538bd98d4d4cc Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 10 Oct 2012 17:38:49 +0200 Subject: [PATCH 063/409] [ADD] forgotten test file bzr revid: xmo@openerp.com-20121010153849-h91mv2dzjk6i0n55 --- openerp/tests/addons/test_impex/tests/contacts_big.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 openerp/tests/addons/test_impex/tests/contacts_big.json diff --git a/openerp/tests/addons/test_impex/tests/contacts_big.json b/openerp/tests/addons/test_impex/tests/contacts_big.json new file mode 100644 index 00000000000..5dfe77ec04b --- /dev/null +++ b/openerp/tests/addons/test_impex/tests/contacts_big.json @@ -0,0 +1 @@ +[["88117cfa", "", "aa48ae52@df356352.com", ""], ["54455583", "0770708969", "75ce07b4@8c061041.com", ""], ["a4f9804e", "0794216989", "6a994598@402c461b.com", ""], ["0cfd7c89", "0788771669", "f2598da7@15f7036b.com", ""], ["220bfe63", "0767248573", "30d7e3f3@993ab043.com", ""], ["33bc0e31", "0747111853", "e86b7718@36a11f08.com", ""], ["ad3d1c39", "0707461083", "17ddff88@de2d370e.com", ""], ["06ba223e", "0793743830", "6c77d328@247685b0.com", ""], ["d457d407", "0723226290", "f497c7a2@c39adaaf.com", ""], ["b24f01d4", "0785727376", "e5c03c2c@be7b89f7.com", ""], ["666bbc2f", "0726730949", "1fbcb995@6b02d029.com", ""], ["8e29a5f9", "0769331825", "17771bb9@4e36debc.com", ""], ["330ee602", "0760467697", "86af9f82@bd3cdfba.com", ""], ["bcd48752", "0747166758", "ccc4c255@05124d59.com", ""], ["4a16c054", "0776729581", "c87cc075@6d84e9ae.com", ""], ["c065ff62", "0708945599", "41391787@d4c3369a.com", ""], ["8636e303", "0798878005", "520e2cee@3506cf0e.com", ""], ["0bdecf04", "0766303691", "7fb38fdd@46f90ec4.com", ""], ["e1ac6628", "0797335906", "5483d5cf@3372b5ea.com", ""], ["f0a24042", "0774112437", "4e99fd6b@7f727830.com", ""], ["41f18eb6", "0757100173", "f904520a@4d42ffde.com", ""], ["c4a8cde7", "", "aa344d15@3dd9bb6f.com", ""], ["abd14d72", "0778342908", "ed9cb7e3@c6fdb61c.com", ""], ["44c65e49", "0711762677", "ef6952c5@a9cd6711.com", ""], ["a3238267", "0758374338", "203081cd@e1263e29.com", ""], ["412069c4", "0745736692", "f2b989ed@67ac8c23.com", ""], ["b332577b", "0783480568", "4382789d@e1dd2623.com", ""], ["84fccf60", "", "ec2987d5@d777ea94.com", ""], ["c633db24", "0780843363", "9c6a9a39@3ba1bc58.com", ""], ["833bdb8f", "", "0c53568d@170c6826.com", ""], ["c6496a37", "0702644587", "808dc444@d3c87550.com", ""], ["3a9cf735", "0732254904", "825cb1f5@9599a25c.com", ""], ["d3bd7567", "0750010894", "3dd53f94@381f30ff.com", ""], ["ec9d38fa", "0722807920", "a63d63c9@9fc07187.com", ""], ["9e858edf", "0759964893", "ee8fc817@4969b884.com", ""], ["3820033b", "0713040363", "846b31dd@1fde871f.com", ""], ["78e3f6fa", "0713215706", "3a1bd069@a2165e02.com", ""], ["833bf332", "0732488435", "e962f524@7a67d172.com", ""], ["ebe0d200", "0791879047", "34a1610c@e30a9051.com", ""], ["e27d3d81", "0702888121", "a6c52338@56630271.com", ""], ["10423400", "0775217021", "24c5bd9d@3b4bbb75.com", ""], ["923f52a7", "0747670735", "19ee7b6b@fb8077b5.com", ""], ["fe50aca6", "0785899752", "99b1c2e4@30f03fdd.com", ""], ["bdbff3f2", "", "cc5cf567@c13f1531.com", ""], ["6dbbeeb9", "0755330628", "33efb58d@1ac1966a.com", ""], ["f88681ce", "", "4d01aa9a@461b4345.com", ""], ["8ff958c9", "0728877017", "c7327902@eae323df.com", ""], ["d8651703", "0711929482", "6aed493b@44b94bb2.com", ""], ["fcf4863f", "0721975645", "c8171bbf@2cefedab.com", ""], ["614949ae", "0708626227", "c54a3aca@bc635fa8.com", ""], ["7b0767ab", "0773868355", "2e5e7b82@bde16366.com", ""], ["ea0fb610", "0714907110", "3781b5b3@6ade96c7.com", ""], ["1833ee8b", "0754159809", "a1fd1724@0a180cd8.com", ""], ["277ea017", "0756815282", "ad93976a@022ff737.com", ""], ["67e662d9", "0789105520", "ecb672e5@df0e020e.com", ""], ["18f2288c", "", "25de55ef@a03da5ef.com", ""], ["32dcbf86", "0738646453", "88e37cac@ec308293.com", ""], ["242eb33b", "0702264598", "d132623d@6a8e65f4.com", ""], ["f2f8e50a", "0731234118", "10bdb9d0@a1dec378.com", ""], ["c414145d", "0723184859", "465e6323@083bdb6f.com", ""], ["1a6d51be", "0782912489", "7f69541f@5e17335f.com", ""], ["ef35d7bc", "0705243855", "0a8f6885@8a236f11.com", ""], ["ac48d3c2", "0714165417", "aa9c4199@1ab6a42c.com", ""], ["5ba7effd", "0731285368", "e7b91cfb@18ab2ca6.com", ""], ["c8349e83", "0711248806", "bf08adeb@72d14356.com", ""], ["ccb97edd", "", "b64dc525@fff1e0b6.com", ""], ["f6b196e8", "0754457697", "915a9cb0@75e21eed.com", ""], ["7a22e438", "0750066621", "4c2ba953@96df5597.com", ""], ["ffb4ecaf", "0791152499", "d9159dc2@6bdedc89.com", ""], ["64d655fb", "0756407008", "498110df@dfc1445a.com", ""], ["f27b441d", "0734603187", "4a23bbf1@ef4d212f.com", ""], ["2405cb10", "0761979851", "92b8250a@125bbd04.com", ""], ["fce58db4", "", "f6dfbd77@704c66d0.com", ""], ["2b16a16b", "0715217717", "d22db762@46605453.com", ""], ["4fbb5479", "0788391407", "e41e70f2@c575eeed.com", ""], ["5929e7ad", "0730836883", "38a50e2f@0cbd9fc0.com", ""], ["9fab30be", "0758240568", "f8422724@eef7fb6f.com", ""], ["57161fa2", "", "913ed6fb@1f9a591c.com", ""], ["787471f3", "0729709798", "45ed74ea@4209730d.com", ""], ["fce02cc8", "0717080949", "0430d0fa@09917e4b.com", ""], ["e5745b08", "", "2e337c3a@038a6c53.com", ""], ["bba2eeb4", "0754696079", "37c75466@05cbd7d1.com", ""], ["f072a1b0", "0774261408", "605c6350@5a7cc516.com", ""], ["95d2b9c0", "", "8935e406@c23ff41c.com", ""], ["8ac4ea3a", "0714072646", "734cfea9@fb198808.com", ""], ["5a523460", "", "2be9f139@0cf11f87.com", ""], ["5b10ec25", "0732185274", "098c0cf3@3676b22d.com", ""], ["8aa42976", "", "2942960c@1ae8ae04.com", ""], ["cdb88ecb", "0758961947", "0ea31305@77af1e9a.com", ""], ["0bd54356", "0784831852", "c437852e@c8e319ee.com", ""], ["1d1768af", "0793590304", "d66c02aa@649e09d1.com", ""], ["c19a3d43", "0749800307", "cf8fc137@761da752.com", ""], ["9c81b4c9", "", "ab84e443@09f1f4ea.com", ""], ["8811594d", "", "53698008@bcc6d45a.com", ""], ["97a8c2d1", "0715236942", "cf88f0ab@fa3f7a28.com", ""], ["fc7d6b5f", "0770870220", "b0e2ee90@41460794.com", ""], ["a158270a", "", "aaab6cf4@d31f8c47.com", ""], ["20bef3ca", "0744837638", "fca8c63c@8dae6b0a.com", ""], ["424b3e69", "", "7d2bb9c4@856ce530.com", ""], ["8ecc1d0a", "", "6df56a62@deac5fbf.com", ""], ["7e1f1b8c", "0795180887", "18d2a24d@a931a1cb.com", ""], ["4546b364", "0771517872", "77ac1ab3@3cd24c25.com", ""], ["a44b23b2", "", "55e75fcb@e20b079d.com", ""], ["90c52454", "0713222790", "e83be6ad@faaa1dcc.com", ""], ["f5fe091e", "0740461816", "fc4b6360@c84d9776.com", ""], ["01052d30", "0790737321", "421a7451@c44558f7.com", ""], ["a65634f3", "0733738433", "a7d57f5f@4f0007cc.com", ""], ["960aae3c", "", "3e2338e3@97fa70e8.com", ""], ["590858c2", "0736114828", "59cec23c@fb9704f4.com", ""], ["75725ca0", "0777217002", "5c7b484a@8c386315.com", ""], ["a16cf653", "0732018015", "a105f736@87a6c14b.com", ""], ["1ee991c1", "0759093690", "1cc3c001@d70dae0e.com", ""], ["48434804", "", "d3cee127@7dbf4217.com", ""], ["edfd871e", "0757718444", "d63d5c26@81eaeb47.com", ""], ["4fcc9a1c", "0738617045", "b114a376@9bd5a931.com", ""], ["b2001895", "0782251612", "a8868ffb@8114353b.com", ""], ["d61261f8", "0717555195", "ac613ffe@d4ee0d8c.com", ""], ["6327118e", "0739171459", "e047cf55@4920c1d3.com", ""], ["f6b14b7a", "0737868032", "418ed43d@b549551d.com", ""], ["22bc0aa9", "0759663409", "90494f38@f50ab03d.com", ""], ["3145a855", "0788697773", "8a0870bd@744b0c6b.com", ""], ["72f043d6", "0780961318", "859d6c8c@d6a29fe3.com", ""], ["98544981", "0707687449", "53a75fab@6ad934ef.com", ""], ["535ddbe3", "0751302080", "5d5dbab7@9b651502.com", ""], ["c3e5f1ac", "", "62955f00@74d50e7c.com", ""], ["6470f36e", "0776617461", "5f6d81a4@e535baa8.com", ""], ["ed39f4ae", "0766428270", "c73a731a@186ebf0c.com", ""], ["6aa1b596", "0720348914", "67d7e38b@5798f6cc.com", ""], ["f5a778ee", "0773231447", "5919b978@2768de0c.com", ""], ["9d530c2b", "0776812615", "4609c18c@aeca697d.com", ""], ["89a13571", "0744825918", "766ddb77@7dfc129d.com", ""], ["90dd9419", "0722654005", "22bef5d1@74801d84.com", ""], ["0d69e61d", "0779495819", "fa2fce6e@d3b9debf.com", ""], ["0a64ee31", "0741511488", "f48455f9@0163e8a5.com", ""], ["87f3e7fd", "0792428108", "a7763cb9@ae893b19.com", ""], ["99a66411", "0785175788", "3abf4513@c90ddc54.com", ""], ["d4d56088", "0748950722", "2dfc3b17@4af80b7c.com", ""], ["1f001808", "0733396761", "59ae4761@17a1bad6.com", ""], ["2d5cac56", "0744393937", "709feac1@1c16f3b0.com", ""], ["d0acb4ea", "0770269511", "66221771@3ff30570.com", ""], ["4f57869d", "0706718397", "1cd2ed99@0ba6e1d3.com", ""], ["a2e66c44", "", "753da3f0@41f8ab02.com", ""], ["843dc71f", "0757529013", "016ff59d@6c1f9655.com", ""], ["c314a28e", "0767460679", "cd2ff99c@8b178d14.com", ""], ["f0d6631d", "0719558518", "0725dfc6@8ce4d6ff.com", ""], ["aa522bd8", "0735252785", "57d3edd6@5eb1bc66.com", ""], ["3f69f804", "0717000930", "6ca23f02@d169a50e.com", ""], ["cc98acfa", "0796356276", "19579c3b@39e71005.com", ""], ["9e6dbdc2", "0769660138", "6349577f@fba33845.com", ""], ["fba0618b", "0758705886", "ae7a9890@e776386f.com", ""], ["f36d563f", "0744525165", "c76184f9@5dccdf5b.com", ""], ["d2df6db1", "0783917910", "f7726c1a@c9e9b839.com", ""], ["8645707d", "0724081473", "842f2369@be456fbb.com", ""], ["95b4296a", "0782845149", "af879705@e8e7bd93.com", ""], ["345ba50c", "0792384168", "ca3ccb91@faf01bf8.com", ""], ["e05de824", "0707660173", "79f09a3d@3deafa86.com", ""], ["de837ee8", "0772243198", "b25275dc@f057ff78.com", ""], ["ae9f1402", "0704963747", "253d5995@6c771579.com", ""], ["259c5532", "0781521724", "cec33738@874afdb1.com", ""], ["1bc82378", "0748931231", "7b3feccd@cd205def.com", ""], ["c73869a0", "0728684210", "790c4825@22921089.com", ""], ["725a20ee", "0716516714", "a5852a47@85846987.com", ""], ["f975f39e", "0732891142", "aea8acea@a6feaa85.com", ""], ["d0fbcd0b", "0753684058", "78f9d7f2@49082702.com", ""], ["d41da511", "0765105657", "bca42072@50aa0f9d.com", ""], ["42be8058", "0776465871", "15d0f988@805b0cb0.com", ""], ["269eda62", "0705841239", "67dc4d59@51389f5b.com", ""], ["2ffc5c2c", "0732437371", "c3b76c4c@9772ea3b.com", ""], ["258e1957", "0768636603", "476831de@98414c35.com", ""], ["a18a68f6", "", "136d0b0e@15864440.com", ""], ["56b9197d", "0734391703", "ab36de76@d7a2bc96.com", ""], ["e1acdbc5", "0790910000", "867827b4@fdffc111.com", ""], ["21e48ef2", "", "4a1bbb5c@29b1ac3a.com", ""], ["aec1a0ea", "0749338116", "64dbedc8@6e81a330.com", ""], ["b1afbf53", "0701600188", "5f1e3fcc@0c6cba23.com", ""], ["bc7e214f", "0725934639", "369caec7@ba1df297.com", ""], ["dd059d1e", "0774510615", "bac60ace@a354f53c.com", ""], ["cbe822f4", "0745859979", "01bebc6e@735bdad1.com", ""], ["961d21e8", "0741358098", "9348702e@ce9c1230.com", ""], ["c8ae2583", "", "3682409d@a15621c4.com", ""], ["c326d443", "0784986501", "0a505045@96938424.com", ""], ["3e51bb13", "0764438578", "b713c235@8e350663.com", ""], ["ad38c924", "0772825196", "ce8d0f19@b2d4ad9f.com", ""], ["65bd5021", "", "3f6318d5@91f006ed.com", ""], ["efd2705b", "0770828242", "736fe829@7c30bc29.com", ""], ["6ebdfef1", "0710559084", "e035b963@a163fb9d.com", ""], ["021358ef", "0711112569", "ecc20e51@547a7cc2.com", ""], ["548d9a59", "0790101525", "d42aa9de@6f91f22e.com", ""], ["262f96db", "0780153799", "094258c8@e03d9795.com", ""], ["a548913a", "0779869470", "6a6999ca@ca0a88d1.com", ""], ["e7beec03", "0796588859", "5e9940fa@eca859cc.com", ""], ["ae5a8077", "", "5ab3a073@18a45934.com", ""], ["eae22551", "0747781534", "6b04366d@7653fc99.com", ""], ["2fb9da57", "0799726898", "895646f6@2a66fe2e.com", ""], ["51d83f2f", "0704387855", "0d2ea467@62feebfc.com", ""], ["3da4bc6d", "0786428049", "db6a479a@37899df4.com", ""], ["c08101a4", "0751956133", "67852281@0bb68d55.com", ""], ["b5f8c156", "0754878556", "bad4eea7@4d5a817a.com", ""], ["ded80b77", "0772054646", "ebb2cd45@54262aec.com", ""], ["7b086cfd", "0776426442", "3b503434@d46b44fe.com", ""], ["7a64e1e8", "0740165572", "e9d50a03@38375fce.com", ""], ["ceaa584b", "0791796518", "b5839977@cfe3ae10.com", ""], ["9c4a8683", "0790187277", "f8e4fe02@02fc1038.com", ""], ["193f99b7", "", "915c1574@50758bc3.com", ""], ["6fb6c30a", "0720403051", "f4bcd3ca@a8ab8216.com", ""], ["9486800f", "0723518103", "a3886d22@6600cdda.com", ""], ["6e09f6bd", "0707095889", "868ffc60@46eb3135.com", ""], ["da1bd13c", "0756382253", "f34abc2c@d18ec367.com", ""], ["3910ae7d", "0786894789", "a8a751a5@9ddf61c7.com", ""], ["32e5be0c", "0738208660", "eab918a8@aeb7a8fe.com", ""], ["c6582498", "0744023415", "b893479d@9ad5c44f.com", ""], ["0c59f520", "", "d552d0fe@8675edcc.com", ""], ["3458ee7a", "", "c1145be6@4043406c.com", ""], ["91fad8e7", "0701771702", "a13640e5@2370e9a4.com", ""], ["2230118a", "0792290165", "529b9444@17c21068.com", ""], ["2df4bff7", "0783219548", "99a9af11@8e5a539d.com", ""], ["0a752397", "0723553802", "b094b6c9@2d8fb162.com", ""], ["918f92a0", "0790485640", "3984cea2@0750289f.com", ""], ["ff811166", "0756833896", "960e71f3@6ded22f4.com", ""], ["6578cd85", "0791455734", "f7e56f2a@35a68ac6.com", ""], ["fd21c33b", "0794847916", "23ae4c63@51515e19.com", ""], ["a12e519d", "0700174532", "d3b4264d@0c9d62f1.com", ""], ["96827dcd", "0780494940", "d70d9ab7@df66a83c.com", ""], ["8cd46009", "", "a8addc7c@c899c5f7.com", ""], ["982fb2ee", "0778368795", "b99de484@d262779b.com", ""], ["dbe5ea51", "0756105541", "ad90b51c@3f1af6d8.com", ""], ["3d963533", "0761709058", "85b32c2c@d99341a7.com", ""], ["064f2df0", "0791023088", "45d63e8f@ce0852ad.com", ""], ["e93edb9d", "0713294122", "b9b82603@a226aaba.com", ""], ["a94ada15", "0796377896", "5dd00c2d@794bcc18.com", ""], ["7de0f3db", "0748976042", "7714652c@3ef8b9d5.com", ""], ["6ff485d2", "0774873001", "77b5b11c@675bf1f7.com", ""], ["e472c175", "0761539211", "dc30792d@00a0ef22.com", ""], ["7a467ead", "0734394099", "e8d5a021@93926f82.com", ""], ["87749969", "0780899950", "dfe454aa@94a8fd44.com", ""], ["c24c8b06", "0777380273", "98dc8782@26872819.com", ""], ["a059abab", "0753758924", "581281a2@890e7bc6.com", ""], ["3b85bdd1", "0784193150", "cf3c82aa@e5df6c1b.com", ""], ["7cbc188d", "0704027570", "c6444b77@8ab56b47.com", ""], ["12ff649b", "0755744514", "a7ce16ba@c054924a.com", ""], ["cc77e0c9", "0724057991", "4e2473d1@4aca6e0e.com", ""], ["026e42e1", "0741456583", "09906c46@e32bed7b.com", ""], ["9e6550e3", "0740725000", "27ddd3ff@c0891335.com", ""], ["700be741", "0715655544", "bcc93b4c@de8854d5.com", ""], ["f15ce066", "0770746966", "aff2e8a9@19f37ff3.com", ""], ["d56faa79", "0780216109", "7119d43e@10e506f6.com", ""], ["d0d97e5c", "0799577373", "9c131514@a5f6fdee.com", ""], ["d3320f24", "0789091392", "e9b8d4a6@e2c9fa38.com", ""], ["c9b3e28b", "0753027473", "d4c85b77@26952326.com", ""], ["5f81787f", "0789741665", "ca7dbbcc@97fc237d.com", ""], ["dd720b39", "0799154501", "9cc0df66@70c2f5d7.com", ""], ["f584f902", "", "38a024f0@27413ff3.com", ""], ["bb37782d", "0788379130", "01ef864a@191fed62.com", ""], ["f6964d05", "0732597248", "32d25b28@6ae6e905.com", ""], ["cfdc9a87", "", "f453b3f6@4ccf20a3.com", ""], ["2c6f8592", "0773589537", "d71824f7@91dd37aa.com", ""], ["ba101360", "0748932503", "674abbfc@81b3b946.com", ""], ["3b35863b", "0759392115", "c249bcc4@e650abe8.com", ""], ["610da7a5", "0712310446", "f4a25391@d7759c5f.com", ""], ["1557e96a", "0796582698", "4aaf8b75@99c557d5.com", ""], ["98519b81", "", "a5050e55@917cd419.com", ""], ["ed820127", "0754946950", "dd82c2c1@7b1ab977.com", ""], ["b78147ee", "0765494006", "53795132@dd38aec7.com", ""], ["3d4859e8", "0782874657", "67b89627@d2269d32.com", ""], ["ce2366c6", "0719814269", "c6200859@0788dca5.com", ""], ["fba51219", "", "b1d107dd@b664bba3.com", ""], ["7469e033", "0742202666", "9cbedb4b@31ba3795.com", ""], ["20c151e6", "0746146553", "90851479@e8a420a4.com", ""], ["14499acc", "0731779256", "c5c930ab@8de927e9.com", ""], ["71297ace", "0771197563", "1bf4547d@f5c8f5b3.com", ""], ["ea630ed8", "0712073290", "245f14c9@9470fedc.com", ""], ["2c54ae4c", "0767896178", "76f988c7@07ade1eb.com", ""], ["e143bc1c", "0798189886", "68717fc3@c4ca3101.com", ""], ["1626281f", "0782558075", "d87d65f6@585b48b9.com", ""], ["3df7b85d", "", "4ef416c6@0e39f805.com", ""], ["101c2c3a", "0754160899", "c77a5ff2@e3dbfd0f.com", ""], ["0e433acb", "", "ce18b2e0@18a803fe.com", ""], ["b454958d", "0758649506", "daadf940@35a7b0e0.com", ""], ["54dd80e3", "", "499da17c@7a6a8e16.com", ""], ["c26e8c0b", "0705458229", "816d4c62@f196940f.com", ""], ["d6c7c2fb", "0712740449", "eb0f3861@028419f0.com", ""], ["ca236785", "0710117939", "74d89d0f@9681f6e2.com", ""], ["03e89273", "0770985481", "a767a13e@202e1c7e.com", ""], ["df528ea6", "0715236243", "4451e8a7@ab9e9cfc.com", ""], ["b369c3a1", "0720792641", "af8e60fb@affbf045.com", ""], ["0e3b3dcb", "0726931283", "b6c80dd6@377de27c.com", ""], ["72f56e12", "0749900046", "dfd0d53e@a04c2e07.com", ""], ["0b616a06", "0788777560", "e520ec34@5a88ce36.com", ""], ["7dcd72da", "0727744886", "c7ecb909@efc93b54.com", ""], ["b6749523", "0755931358", "76b2e187@777e9047.com", ""], ["349f347f", "0772053293", "aed364ad@8f6c1755.com", ""], ["b0a24d58", "0737012558", "b013a7fd@a6d27266.com", ""], ["924dcf44", "0761967844", "539d93ff@4e1741bd.com", ""], ["90781369", "0745086457", "bae1c94b@df7075b3.com", ""], ["7bbf6e08", "0762583195", "c54b4a41@f08e61ec.com", ""], ["696d9ce3", "0753759660", "9be913a2@efd894d9.com", ""], ["32dea399", "0730020519", "b76d0594@9127aaf5.com", ""], ["4aada6ab", "0716703652", "1172d8f6@70029987.com", ""], ["c2b450aa", "0786756810", "05fa85d3@6305e8e2.com", ""], ["f7220cb8", "0776056046", "b14c6af3@ebfcf7d3.com", ""], ["7da05a35", "0741271883", "abe23d1a@35fc89a5.com", ""], ["b277cd48", "0703025387", "ed28c019@feb1fe78.com", ""], ["55a16321", "0740030335", "a3db681b@de92450b.com", ""], ["646ff9aa", "0777457443", "ea0704a8@d6c557b9.com", ""], ["557c863d", "0752298537", "c412a0a1@4db33621.com", ""], ["324da6d3", "", "61e7386a@d4a90843.com", ""], ["144835ab", "", "70744ba9@000ee58a.com", ""], ["eda25157", "0734918749", "efdbfb3e@83133e46.com", ""], ["bf5d4b09", "0712427566", "4b13f413@18c93b1c.com", ""], ["c3745e8a", "0723463789", "e5ccf0c5@00118e4a.com", ""], ["11c0a9da", "0778743010", "865392aa@1c8da31d.com", ""], ["7d0eac7d", "0701997984", "f2990151@e8d055f3.com", ""], ["e701488a", "0712599226", "f0d54316@037ea274.com", ""], ["acac2543", "0771603428", "73cc7388@981dc1a0.com", ""], ["82f371b0", "0758909949", "6ebe0478@2b14af27.com", ""], ["896bb3a8", "", "83158633@aa3fe414.com", ""], ["9ce45cf4", "", "38772abe@078a889f.com", ""], ["fcb5a33a", "0769530741", "29a4e798@effcb6ef.com", ""], ["116d4f92", "0786255405", "e78e003a@cf7ebbc9.com", ""], ["35e5bd6c", "0700694228", "399e4cd6@eb7a9b08.com", ""], ["71df9408", "0798109987", "91433ee1@b3240820.com", ""], ["294e2aa4", "0700947677", "abca0340@4cd61d52.com", ""], ["9553d892", "", "3af85bbd@90ee53d6.com", ""], ["bbcdb933", "0773940915", "de196282@bf4432fe.com", ""], ["3ccbc198", "0742527356", "014618cd@78b4016f.com", ""], ["100d9496", "0786481835", "df9a72cc@123af588.com", ""], ["57cfe177", "0789499193", "f5f0de36@27d22e23.com", ""], ["cdffca88", "0714652673", "4102e3e2@26a0d112.com", ""], ["69c5f300", "0762631167", "14f5940e@fe984955.com", ""], ["819e988a", "0798148053", "b78ed8c4@ef4a213d.com", ""], ["f5c6a92a", "0774167414", "c996df73@8a8a0586.com", ""], ["3d3f9cc9", "0766973558", "f0a43735@47580cbd.com", ""], ["a30056ab", "0787961025", "04256d2d@459d56d8.com", ""], ["7dc0d98e", "0741838356", "2a597e04@f7089dd3.com", ""], ["e19f381b", "", "ce9c237b@4ec0fd84.com", ""], ["34b3c355", "", "77bcc11b@2e791c9a.com", ""], ["4bca2052", "0799612575", "dba5fc2f@600d7b82.com", ""], ["dbc71748", "0726348854", "efc05aff@df67c9ee.com", ""], ["6fee2352", "0786598805", "c8bad10b@f550bfa0.com", ""], ["b56c589c", "0722452846", "43e2ed1c@4e233028.com", ""], ["77f4b627", "0795147567", "6f26728c@015d1c78.com", ""], ["e6e1b439", "0720916434", "6cf4f2cd@d0daef5a.com", ""], ["c4e49a4c", "0787210516", "bfc6dbf7@8f315a9f.com", ""], ["3f717509", "0704228943", "7a9fd98d@112a27be.com", ""], ["8c0f2abf", "0739504671", "b2c6a55d@bf7bb207.com", ""], ["d0ec34db", "0745702321", "4a426510@7c7cc4ba.com", ""], ["cfe0f395", "0708421594", "df815b04@d27562ee.com", ""], ["4ab6a603", "0781614226", "8e7498c4@216eb70c.com", ""], ["53727fa1", "0778595217", "0fef75b6@7e3eee41.com", ""], ["1dd3c6c9", "0795888769", "c88ef6ef@9182a8c1.com", ""], ["5dbdf1c2", "0700853188", "8b2128ff@5a2fa2e4.com", ""], ["5cbf9768", "0752068105", "064d2e97@f4631505.com", ""], ["b81ffbce", "0737952148", "ef90cb7e@7f7bb2d3.com", ""], ["6c9426b4", "0765528647", "571533da@097b853a.com", ""], ["76b87a42", "0735376294", "4fab1c8a@1004c035.com", ""], ["cc67d10f", "", "df05e09c@10cdee9b.com", ""], ["91f2c079", "0727155396", "f70f99d0@e56d0e68.com", ""], ["7687c589", "0723819703", "f4a37237@8306ec54.com", ""], ["cc065203", "0777023625", "235ab1ff@ad59efef.com", ""], ["ada410b8", "0795063396", "d58735f0@1cfd2246.com", ""], ["b17fda79", "0761763470", "06024431@3a90405d.com", ""], ["82c9cf46", "0795927937", "cc7d157e@fe591e61.com", ""], ["1229f23f", "0766794577", "196fbca7@2762695d.com", ""], ["41ee3436", "0751875418", "e789384d@1e8c078b.com", ""], ["b59b1ae3", "0706674618", "eaa7394a@9ca599d5.com", ""], ["32a1572d", "0739902105", "076df342@f7257d5d.com", ""], ["87142aaf", "0773843071", "2d1ed5d0@745442e0.com", ""], ["fd302180", "0752363053", "69d00e9f@4361b9c7.com", ""], ["9b129111", "0711208227", "e3f41ba4@230ff3c7.com", ""], ["00c627e0", "0795414341", "878530d9@891a7047.com", ""], ["f9bd3b66", "0754134870", "36b72937@8fe2912f.com", ""], ["d89c11eb", "0760560969", "6ec530b9@d7f30799.com", ""], ["e2b6ef2f", "0711238958", "6250bb8e@23e30295.com", ""], ["811c4293", "", "81aeac97@4083c108.com", ""], ["96c90ed7", "", "19727897@698b879b.com", ""], ["b82a09af", "", "7527ccbc@4e351f9e.com", ""], ["17e61a75", "", "ffdd4947@541dcc9f.com", ""], ["f97fa25d", "0749784894", "8b419430@4ae116d0.com", ""], ["13b9a7da", "0748292813", "1d2e437d@1f7fd137.com", ""], ["e0879369", "0778630426", "fbc7e460@350c1a55.com", ""], ["1a74805d", "0749531731", "f06e561d@ebbec1ed.com", ""], ["eb5db9c6", "0707095397", "ec71e260@1ab509e1.com", ""], ["9da2dc8e", "0717471756", "23418425@2dffbc70.com", ""], ["a6f6f46f", "0703721541", "037414ed@c1759536.com", ""], ["765a5633", "", "4fd61a7f@e9fc7672.com", ""], ["3a717722", "0785655203", "82f8e536@4aab3d98.com", ""], ["34b938b7", "0712389450", "0ce3ed1c@8d5aec4e.com", ""], ["fa4eaa80", "0760264228", "487d193e@86c36a2b.com", ""], ["6ba54ee3", "0737464908", "ee4791dc@6e7e18cc.com", ""], ["3d02d6e8", "", "b2c13ef3@66a3948e.com", ""], ["ee3c7b2e", "", "2c51c4fc@97eaabe3.com", ""], ["943acb8a", "0775102341", "306ebc20@ad6a778a.com", ""], ["e86c14c3", "0705424432", "40c1518d@76aab128.com", ""], ["0d993e76", "0729633289", "a18fcc70@f04ad1c7.com", ""], ["fec3f43d", "0740081762", "e04dd4d1@615c78e6.com", ""], ["90645f43", "0737009757", "d8ed6970@a5baa38b.com", ""], ["723c41aa", "0732060795", "d42e8f6c@9f01caf6.com", ""], ["96235675", "0755010192", "30d98b6f@fad581d8.com", ""], ["1bfda78b", "0736195102", "f0ba5711@24ec477e.com", ""], ["9fde0750", "0737641391", "f73cf50d@108aad37.com", ""], ["4cf28ec2", "0715717575", "f18063da@f0625607.com", ""], ["96824bd2", "0754345078", "f7b7534d@5c430ea4.com", ""], ["57e1a524", "0775075206", "9b963917@f4c93815.com", ""], ["1a1b212d", "0796156113", "0da3bd5f@60d5c0a3.com", ""], ["73267af7", "", "20364468@e070797b.com", ""], ["c4fcd602", "", "c996b53c@8c9e56e7.com", ""], ["23944725", "0756128345", "3f1043b9@4e705983.com", ""], ["8665f6ee", "", "c562cd48@d44eb942.com", ""], ["5178e72f", "0791852636", "bbcae5ee@428b8ba9.com", ""], ["9de66e8d", "0753385146", "55874b2c@f115714e.com", ""], ["de112089", "0734935576", "789b1706@6d2b21b8.com", ""], ["4e8283b9", "0700426636", "081d48fc@797f0558.com", ""], ["081d4271", "", "99829160@285f8fd8.com", ""], ["69dd706e", "0771351294", "906cc914@01cacc1a.com", ""], ["5de2de11", "", "1edc2268@e01bd776.com", ""], ["e823c600", "", "ecda6d9d@74a5da65.com", ""], ["907e7635", "", "14cbd73f@3c5029c4.com", ""], ["d6236d57", "", "39f3d4ae@1b7b8200.com", ""], ["aa2630bb", "", "75535cee@5391b394.com", ""], ["c6cda97f", "0710755065", "ff4ab3b0@e7638240.com", ""], ["b6661f85", "", "067496c8@1c3d2df6.com", ""], ["c95cf777", "", "afa9a3cb@279aa011.com", ""], ["e575e109", "0785713068", "8601eb2f@7d69d9ef.com", ""], ["c4aed4d1", "0797133251", "0ebd0ca0@44b0db13.com", ""], ["d8799ad6", "0766336482", "c8a2db59@fc20467a.com", ""], ["fe041483", "0747021458", "f1341509@a0d4bfcb.com", ""], ["9c8975f4", "", "1adf2f38@6ef39e01.com", ""], ["fc572eb6", "0707977477", "39ce98ea@c55bd59e.com", ""], ["86b7eeac", "0714499420", "19318930@f8cab44a.com", ""], ["d64977ad", "0761071885", "11a682aa@69ca2391.com", ""], ["ea006f73", "", "dfa103d4@ec0cffab.com", ""], ["0137c08a", "", "4e98808d@f9cbe2ee.com", ""], ["4c3ef173", "", "ad18e541@9c961399.com", ""], ["3a90243d", "0702089544", "73d9e758@a8185f82.com", ""], ["552fcf54", "0711153208", "b425511b@1f62462e.com", ""], ["47f20958", "0709287769", "387a2338@24efeaca.com", ""], ["95568c92", "0753062212", "230b16d8@7c47aa21.com", ""], ["4e00e50d", "0705656877", "e0557aa4@17b9f5a3.com", ""], ["6a744fbc", "0752791693", "f1cb0467@fc01b034.com", ""], ["b00241b5", "0707154247", "8fb98d05@46674fd5.com", ""], ["40bbff33", "0798115729", "238dcde2@3a402b74.com", ""], ["2ff0e839", "0734208035", "b85bc3b0@fb7c2ace.com", ""], ["48db2fd2", "0746707903", "21bd36a0@967fc046.com", ""], ["82ce2569", "0712225501", "b578f1ac@ebb9345c.com", ""], ["bc8eb82a", "", "579a208c@3a587c16.com", ""], ["e6c2ceff", "", "cf4f1954@a02d98a5.com", ""], ["36cc5274", "0794054613", "6a6fba68@59b878ab.com", ""], ["a47d46b0", "0779573055", "7e3b995d@8ba62af1.com", ""], ["abc2eea3", "0770887487", "2d0b55d1@9b58d90f.com", ""], ["3aeec47e", "0798128924", "cc01849a@23ae0c8c.com", ""], ["438153a3", "", "fbf57f49@b868a49c.com", ""], ["c2e79acb", "0790684868", "eefb75e0@e0e96a2f.com", ""], ["975b014e", "0762757057", "aa6a37dc@a30b0c72.com", ""], ["e610d666", "0781184369", "4d3f4b20@97d8a401.com", ""], ["73495ac9", "0719719687", "7a018884@c2c13e7c.com", ""], ["9a445855", "0785545967", "2d196afc@ffff6d02.com", ""], ["ce2ab926", "0700868262", "2cd6763f@b6d56901.com", ""], ["c0fcbafb", "0706968744", "8ab42ade@5692f6e3.com", ""], ["0604c52c", "0772596476", "b71e2f2d@31e533dd.com", ""], ["b4fedfd6", "0700359913", "af1c4ae4@fcbb6631.com", ""], ["1e19fa35", "0742671783", "009e471f@8e4f29d9.com", ""], ["6bc8631a", "", "38a6dc3d@900b535a.com", ""], ["09c221a5", "0712627371", "6b081654@a5d250ba.com", ""], ["55d80d5c", "0710423548", "149c66a4@0adbe042.com", ""], ["bc6f4369", "", "28372894@dfa1fbcc.com", ""], ["7aa8a6a4", "0766166352", "9dbb5873@5731fed6.com", ""], ["5c781ef0", "0790623819", "2d629650@b57c316a.com", ""], ["6830c71c", "", "39897b3b@7ee8cde5.com", ""], ["6af8ee98", "0747825215", "5b56cf20@4c81a082.com", ""], ["5a8bcde3", "0763197608", "e69532c0@34630f3b.com", ""], ["8f9037fe", "0726240186", "df9e5814@e4fc4423.com", ""], ["fb13d5b0", "0721173617", "d475522e@c02f6cd8.com", ""], ["9ce57e77", "0774209520", "288a94c3@2a0fba22.com", ""], ["b54fd99f", "0735610926", "061e00aa@34301c70.com", ""], ["fe1a320c", "0776730222", "53770fab@f7c2cd27.com", ""], ["10c3b647", "", "ae78b399@9c814e5f.com", ""], ["d24be5da", "0797581905", "9394a573@bc5e7a67.com", ""], ["e61273a7", "0730217168", "ef553bd3@fbd3732e.com", ""], ["fb6472b6", "", "cdf00170@f2e89868.com", ""], ["b588bcf8", "0715004480", "21505721@1ce9749f.com", ""], ["36ef226a", "0720093875", "293e85b5@c81c476f.com", ""], ["007c51ec", "0770116496", "b1b68fa0@159369c4.com", ""], ["949c6074", "", "6e66fd1b@434382f3.com", ""], ["4e4f11d2", "0762955197", "66d29d82@531b2e83.com", ""], ["758c58d1", "", "9dd36cae@295af2b4.com", ""], ["99be0c22", "0794398863", "0249fb4e@4786d822.com", ""], ["1298fb9d", "0720206151", "d3c59051@5d59357f.com", ""], ["b97f877d", "0779925184", "f6414a10@13ffe42b.com", ""], ["3e653aa1", "0750192219", "b35e6fe5@1b6bf57b.com", ""], ["8fbab13c", "0732153634", "b0a7711e@52ecc07a.com", ""], ["1a3e75c1", "0743946942", "25786349@8c65834c.com", ""], ["6ca639a0", "0717692914", "ad3be222@b10a9147.com", ""], ["3c8dd318", "", "bcccd36e@cc70d14f.com", ""], ["a6d3e7cd", "", "aa9c8a70@963098a4.com", ""], ["6fc1b3a2", "", "d19b5d6b@934e24f1.com", ""], ["759261f1", "0709242692", "72f51517@87b24cae.com", ""], ["3d7a1d1e", "0715207809", "877c9255@1671ff51.com", ""], ["93278583", "0742390782", "21dca350@2cb6d4ef.com", ""], ["51f96553", "0748353883", "6be176c3@4e96ba7a.com", ""], ["a347fde6", "0741522657", "c133fafa@26d07149.com", ""], ["362bd97e", "", "60ac173a@10183062.com", ""], ["b1a7c0ff", "0764817452", "67e54fec@06bf6f87.com", ""], ["9ee4aa89", "0741377765", "1856ef66@cc9f3fcf.com", ""], ["49a7dbd1", "0783985348", "ce3970b4@ea82bad4.com", ""], ["206b0643", "0767461177", "a897ff67@8adf5df6.com", ""], ["596a240b", "0722068325", "82663950@9a960206.com", ""], ["dc852f2d", "", "381e1687@8bc841b8.com", ""], ["44dbefa1", "0774987561", "391ecd0c@26e9e890.com", ""], ["69e6e40c", "0713319482", "978839d0@5ad63633.com", ""], ["0121d5a7", "0714766437", "8abfc0e0@b6e025bf.com", ""], ["cd5200b5", "0764514081", "6304987a@1d2f7eb9.com", ""], ["536c4831", "", "c0e01f58@cc7a1d56.com", ""], ["31167693", "0712547344", "9e54c7e9@90b5ff9a.com", ""], ["6a240068", "0776430272", "4ae0eabc@345cd527.com", ""], ["c14f594b", "", "7351d1ff@31c0438e.com", ""], ["b290c6f6", "", "9368d514@98711325.com", ""], ["f870b7b6", "0789240289", "4f8593ba@f80fe1b6.com", ""], ["f9c1a49b", "0714414302", "02efd04f@a4f155cd.com", ""], ["51605326", "0704713807", "13a21489@ec8993c8.com", ""], ["88b5f2e2", "0794091627", "a2745c7e@a32c3b1d.com", ""], ["f3b6a422", "", "4e024c4c@022f5e1f.com", ""], ["c2cfc88a", "0761247770", "153b9fe1@9859b8a4.com", ""], ["597f3524", "0761882451", "1982d242@a8f03583.com", ""], ["d694bc4c", "", "864732d7@76277920.com", ""], ["8e859b4a", "", "d16f7f69@0261a0ef.com", ""], ["2d583afa", "", "876b76c6@e55415c1.com", ""], ["1bd3b1ae", "0761041162", "a2ebbee4@9a1b4f54.com", ""], ["a01d3c8b", "0703532365", "d6d7b818@bf578a2a.com", ""], ["6b8ff331", "0705773074", "e1e26a20@144139a8.com", ""], ["bef24803", "0750088813", "fde0039c@4ed43033.com", ""], ["253651f9", "0715013226", "3aebf85d@f7455c19.com", ""], ["34da6189", "0764808908", "03f2bd4a@c73ec94e.com", ""], ["c72f3422", "0754811376", "5941e3ce@769439b1.com", ""], ["1761f923", "0708249762", "20e78457@68b640c2.com", ""], ["a7ddd99c", "0754994431", "ad342d73@622fa530.com", ""], ["1b32b5cb", "0769400739", "510cf15d@1feaf7a5.com", ""], ["2ecd5127", "0788462377", "f2a96f71@c6dadef6.com", ""], ["b2e338ca", "0780233422", "0394850d@c7f808dd.com", ""], ["0999515c", "0708264022", "9214c832@73793633.com", ""], ["b4662820", "0791822790", "378843d9@faad02b6.com", ""], ["b6526e56", "0702391559", "ddd3922e@683a9bc3.com", ""], ["e1d0dfca", "0796434690", "bbea0324@a25f259b.com", ""], ["7507ff74", "0718970953", "957feb53@dd898780.com", ""], ["537fba55", "0712047297", "380f1934@1afa6994.com", ""], ["c03244c8", "0719594534", "d685945b@5f863d81.com", ""], ["7a0b4463", "0726964918", "7dada8d2@632a578b.com", ""], ["01f105bd", "0771635491", "0103cc3d@2c004125.com", ""], ["7c9baaea", "0793949807", "b0aae8e3@23796a56.com", ""], ["05f636c7", "0707511947", "36c7c75f@2d86967f.com", ""], ["71d917a2", "0784386161", "ad18b2df@9366e77f.com", ""], ["d417a204", "", "e3ef2306@48c768ce.com", ""], ["8d6d1bb3", "0705778200", "ee43e84c@f6df11fa.com", ""], ["f4c05035", "0772727935", "c0ced236@b4ea187c.com", ""], ["e6d75e18", "0788952581", "402b9e4d@0b37e829.com", ""], ["1dabeec9", "0727510448", "a0fac12e@0ea007ab.com", ""], ["f71fa168", "0759368909", "2b111301@22da70d4.com", ""], ["23b7c929", "0786848255", "b71bbd84@857f9ec8.com", ""], ["a085c14c", "0740213711", "d32148b7@b67a73ae.com", ""], ["9ac9fa3e", "0701707031", "42cbdd1a@175f318e.com", ""], ["b4e40dc9", "0715864237", "a15c733d@6669b4f7.com", ""], ["94020cfb", "0715193084", "ad45863a@2eaab246.com", ""], ["626c1ee7", "0750957414", "d66ae397@2e895e2f.com", ""], ["1eabc823", "0731567529", "20f8332e@b4b0703c.com", ""], ["e5a98097", "0718031536", "718b7ae2@8504fe2d.com", ""], ["69245c65", "0779488230", "fc645fef@635fbdcf.com", ""], ["247ce107", "0721718937", "2c662519@b0c33ecc.com", ""], ["c4925e4c", "0710565488", "36e178bb@4cb2efd9.com", ""], ["d0ef8f45", "0725811338", "f5404bce@9e12cd0a.com", ""], ["ed80a2b0", "0708451045", "6b9f4393@5ea5c209.com", ""], ["13aab094", "0711289294", "ce0972c1@c202849a.com", ""], ["0154dcda", "0734530650", "e225ca87@12039c6d.com", ""], ["004cecdb", "0741339169", "d85299ff@ce7f5fd2.com", ""], ["bbbcbeb3", "0723560169", "e31d0863@b105423d.com", ""], ["cef7c1a9", "0752786167", "3c76459a@4e492e4a.com", ""], ["c3cb922f", "0779170714", "24e2fd0a@cd086652.com", ""], ["a267897d", "0740299573", "c8ab2622@5d1d5225.com", ""], ["f73c9d67", "0754733442", "433436bc@eaa41a7e.com", ""], ["bb0022c6", "", "016e3dfc@ea644733.com", ""], ["060c6c8f", "0767126800", "24a3b50a@8c364ded.com", ""], ["9f5b5d9a", "0769176462", "20dc7747@ef1ad5b9.com", ""], ["43e67ec3", "0743483082", "8a5f94e8@5e7d39a0.com", ""], ["345e4a33", "0787677047", "3a0c802c@608dbe31.com", ""], ["ec2e7f7d", "0784990090", "23ec5d05@c4bebf51.com", ""], ["e239c87d", "0738679004", "8cfa7063@bcb2bc21.com", ""], ["271fc9e7", "0778470494", "c2d46c92@dcb3dbfc.com", ""], ["3b0585bd", "0795454441", "40772365@1d8f7187.com", ""], ["a1a58875", "0718370412", "2eb10d10@5ec547bd.com", ""], ["4c45c47c", "0739708464", "81d5c8ac@06447b51.com", ""], ["e57e8359", "0751620730", "4b2b8980@c95b69b5.com", ""], ["735270e1", "", "ee37dbee@25a4ff65.com", ""], ["4b44e00f", "0711946373", "0eb6a22a@b320af8f.com", ""], ["8a372c1e", "0770968660", "d6678940@ee818cf4.com", ""], ["88efebf9", "0720205646", "7d6d6bcd@87fecbbb.com", ""], ["6ebf214d", "0780223716", "d28759e2@e323f23f.com", ""], ["2eb46280", "0795896930", "8dae7897@d3854b08.com", ""], ["53bc97c3", "0730645626", "12518a5f@a1fdfaca.com", ""], ["fec1e211", "0754874523", "40655f66@4897f637.com", ""], ["1b8ef046", "0731698966", "cbed8d9a@893a95be.com", ""], ["70099e91", "0725267567", "b75efdd0@8dcf7f96.com", ""], ["00234cba", "0748766899", "9088d159@a1a1f4c1.com", ""], ["35ff23c6", "0747870199", "c961250c@d8a06d24.com", ""], ["9e7417f8", "0746801322", "ba7e50e4@cae69ff0.com", ""], ["3428f8d3", "", "56c21910@48bf2959.com", ""], ["f575e8a6", "0734183553", "4953d608@e2885866.com", ""], ["ee701421", "0762346436", "0eee7492@884b62a5.com", ""], ["197c760a", "0741186587", "8e5f6e2b@ea3cb8da.com", ""], ["691a46aa", "0708195042", "cf89f958@dfa6105e.com", ""], ["b03db786", "0716744355", "3f1c117f@a6c83666.com", ""], ["4be4d96b", "", "48195284@40467121.com", ""], ["dfcd1ada", "0783073475", "9785f27d@1df650f2.com", ""], ["4490c17c", "0786052205", "8e4bab0c@b98b8c4c.com", ""], ["f4e991f7", "0717102345", "e5a0a4fa@0483a00c.com", ""], ["b15003cd", "0771528694", "e012bb67@b1463416.com", ""], ["95e2a50d", "0796484412", "508dbc66@25ef9b72.com", ""], ["c2003313", "", "8856d03c@72d7544b.com", ""], ["276b4bc0", "0789810903", "ef87caba@2741b9cb.com", ""], ["15da925e", "0748450892", "656949ba@78234623.com", ""], ["77e171e3", "0786551610", "a86b4d19@110baa19.com", ""], ["9d9d0504", "0758342738", "0dc0e069@bb5e721e.com", ""], ["f4def247", "0798052097", "e66df9a7@af41f423.com", ""], ["c3ea412f", "0706797533", "4e28af08@8a754fb6.com", ""], ["53812400", "", "6c6215f1@45e33532.com", ""], ["369bfda8", "", "45cf4bdb@6d0980f6.com", ""], ["dbd3b821", "0765939770", "f448784d@35d292f5.com", ""], ["142f350f", "", "41c305cd@fdf34481.com", ""], ["8fcd1626", "0770444423", "323d955b@41ff7d99.com", ""], ["8789a603", "0751524803", "359bc02a@72af402c.com", ""], ["0a675687", "0789901250", "2323249a@619f78c5.com", ""], ["fb011bf6", "0750579472", "7152dcf1@668f96db.com", ""], ["a623d8fd", "0733289400", "482d64cd@8a4e2926.com", ""], ["6d961e75", "", "6fe4f5e1@e9239485.com", ""], ["4f39910e", "0746456899", "e85969c9@cca744af.com", ""], ["81a834a8", "0731458518", "8ffce3c8@8e7ae609.com", ""], ["70472837", "0775526068", "5dbfd52d@0d829cb6.com", ""], ["2d882041", "0708561610", "e5853dfb@b2187974.com", ""], ["deaf54bc", "", "a9dc3872@2506f15e.com", ""], ["a7226533", "0760964433", "2490dcc2@de364340.com", ""], ["36377c3b", "0759911971", "93465967@b06cdaa6.com", ""], ["31724c44", "0757697274", "b04d8ef1@544a5467.com", ""], ["51806270", "0742044114", "417f3dca@cab99b90.com", ""], ["e9b2295d", "", "d9e360f5@4d87b309.com", ""], ["0dee89bb", "0712052963", "4700d9dc@8b9161ce.com", ""], ["8a4b9e30", "0755847836", "b3d261a8@60e7e6d9.com", ""], ["f8f7bc44", "", "ffd58a0e@e40c3e44.com", ""], ["c5d5d713", "0790256137", "35f89e39@5893f2c1.com", ""], ["90f0cbd9", "0737155772", "6d8e7f05@40038b63.com", ""], ["eef1d1a9", "0742179171", "065c13a8@634d0446.com", ""], ["55faa2a4", "0748611843", "22382d4c@d11eb075.com", ""], ["f7913ace", "", "40be2255@400d8d4e.com", ""], ["0d47fd15", "0797162254", "06ec4142@00a16805.com", ""], ["906a5fb1", "0703201953", "4d249ff5@55ffe749.com", ""], ["4b5010c3", "0741317092", "25d81157@6027b9e1.com", ""], ["f79b697f", "0773396997", "2e116cf9@9a6bfcba.com", ""], ["c6d2d0f0", "", "a83108a9@40159f26.com", ""], ["da24f341", "0775328597", "4e7592d1@70f4d9c1.com", ""], ["b20edca2", "0789450137", "d326baf5@1baafa6e.com", ""], ["3e11a76a", "0776368949", "15a351bc@e4b229ff.com", ""], ["3e2fbdc3", "0717744150", "4ebbd18a@de822931.com", ""], ["7e6c9549", "0750887467", "2c5034ed@23402dc1.com", ""], ["9536e16d", "0713928189", "e6cd0a97@d20db0c5.com", ""], ["8358cf78", "0735864901", "4ea98e6a@e1052078.com", ""], ["d12cef0a", "0730971666", "a7f6061d@b6f2822f.com", ""], ["cc2ee54b", "0778562618", "61917c3e@032bcdb5.com", ""], ["21ef6091", "0763511033", "166d075e@522d8051.com", ""], ["f6b7a396", "0772929913", "13ae6bf9@c44fbe8b.com", ""], ["042555cf", "", "b11161b5@143fc047.com", ""], ["9739c45e", "0792544143", "9a57d50c@7545618b.com", ""], ["aad5cccf", "0781328164", "59e7123e@488f0065.com", ""], ["b886493a", "0785224849", "d6499e6f@0688b326.com", ""], ["2c99ee07", "0748501224", "1e582961@799a7165.com", ""], ["72545b19", "0715248877", "637c5be0@c9d62b4b.com", ""], ["6f038b04", "0717198089", "fa325ae7@624b634c.com", ""], ["4f8e0b2a", "0764277265", "cb4a5eab@35f7346a.com", ""], ["03fdeddd", "0721789994", "c0476d68@4d5cd7bd.com", ""], ["89d74e2d", "0760756190", "d6594d52@5dee56e4.com", ""], ["c24acb5f", "0781827089", "3a1ea265@8bd8e1cc.com", ""], ["d1bf9230", "0722180686", "9e582b1e@e8351d46.com", ""], ["9dd2e88d", "0711860229", "56658ca4@132ac241.com", ""], ["a07824cb", "0741457266", "76f4cfea@f25c3adc.com", ""], ["f3897859", "0710503175", "8f23c250@4540617e.com", ""], ["c09a14dd", "", "e9c464ac@f76cfe06.com", ""], ["c9a758e4", "0790149404", "b5fbb29e@2ef70cf1.com", ""], ["dd56f5d4", "0709704673", "8b24db91@663c1804.com", ""], ["1ccf7b2e", "0728115684", "d7610e72@e4a8b643.com", ""], ["32351dff", "0748120068", "3939d0ab@8fdf1e7d.com", ""], ["8c4053c5", "0714496140", "420781c7@8ccbf30e.com", ""], ["ce266357", "0784144894", "de2e719c@22b747ed.com", ""], ["3257e91e", "0783497860", "09f03ee1@a98f49a0.com", ""], ["0180d6f1", "0743825253", "ec4bf604@a0b51abc.com", ""], ["5360eee3", "0719368035", "bb270d1d@984f9d39.com", ""], ["d40e19a5", "", "5ccc6f37@d6870955.com", ""], ["a429a2e0", "", "9372812a@b1676aa3.com", ""], ["45dfc0c2", "0709417666", "fed1b00e@bf665131.com", ""], ["a173558c", "0758991067", "3f706fd9@301776a7.com", ""], ["ca87b3af", "0781867475", "98155b79@adcd5507.com", ""], ["036da0ce", "0778243834", "66467ae3@686faa6d.com", ""], ["c5ddfc00", "0750665015", "4e0a5924@9d77bef0.com", ""], ["40b39118", "0765997451", "7bdfe708@a3cee04d.com", ""], ["a5de4669", "0761205980", "bfac2446@e1515b33.com", ""], ["a62448b2", "0739220943", "3da472cc@73d9e74b.com", ""], ["3b04bf59", "0711824354", "b6ac5778@42772967.com", ""], ["ab56dd06", "0791996063", "3949b2d8@b08c4c5f.com", ""], ["9820b796", "0724164512", "ecad52ea@81041046.com", ""], ["894e5af9", "0706784563", "4b2ee10d@821e0a2e.com", ""], ["dd06ec54", "0782812141", "a2e91578@875cac30.com", ""], ["802f32a7", "0749216707", "8e7171df@898e4f66.com", ""], ["ff30e79e", "", "e09f32d2@e8bed799.com", ""], ["7070b09d", "0707078844", "bfb66733@308be7e8.com", ""], ["fde6085d", "0712529236", "c4750b1e@05266810.com", ""], ["87f4aafd", "0739190648", "1cb92876@1cf2f6df.com", ""], ["94a88efa", "0775446056", "f0ce2f87@410508db.com", ""], ["20f56909", "0740230843", "55997ce7@82f437b1.com", ""], ["1ee26c6c", "0713640395", "6357a25b@fb48f794.com", ""], ["ee1ba135", "0789826448", "097f6423@892f4d97.com", ""], ["7fa6baf5", "0752582669", "6e49ac6d@7012d5a1.com", ""], ["35fc8c1d", "0789186620", "0abe0f3f@2435673a.com", ""], ["0e7434e8", "0791384205", "96c88dc9@8e26852c.com", ""], ["6a899564", "", "65902813@1686d624.com", ""], ["90d1935e", "0756326458", "8ddc4a04@a5572b9d.com", ""], ["f8c69667", "", "c827107a@93f105af.com", ""], ["b2c511ea", "0749010920", "24bb2d69@f4287f85.com", ""], ["6ecc592e", "0788769694", "4c132913@931ce84d.com", ""], ["6722b9db", "0794262991", "52bed401@35003685.com", ""], ["6874d990", "0748452679", "b5dca8b6@97c1b768.com", ""], ["72740c63", "0721748699", "9e10c395@a98c8e1c.com", ""], ["ee0d78e0", "0795469696", "56d8a295@d6ef7c7e.com", ""], ["d5bcb2aa", "0741284724", "34c858aa@5f49689d.com", ""], ["5909a519", "0744679678", "88409af7@e19f4243.com", ""], ["f265acfa", "0792029151", "e34d1172@0e9bba98.com", ""], ["94a5602e", "0709917575", "0464515e@552c3013.com", ""], ["d0d483ad", "0764326930", "86b8c70f@a6382da0.com", ""], ["b9155373", "0725007352", "e3223601@f5a902c8.com", ""], ["600e630d", "", "f4e4d66b@bf8aa87c.com", ""], ["fe12bd24", "0772663541", "8b8b1297@1e02a9bf.com", ""], ["fc11b86a", "", "65f3c1ac@375002e4.com", ""], ["110d8fa4", "0775226701", "3d955f6b@ce7da885.com", ""], ["d3105be1", "0779779352", "ed2be0eb@ccc7485e.com", ""], ["fda61a0b", "0720274167", "6becb3e3@4deb6681.com", ""], ["17f8be17", "0799234608", "73f14970@cb957e59.com", ""], ["e9516a1d", "0760461815", "8ad30006@8df0fd1a.com", ""], ["60177106", "0760558146", "dc029d5c@b6ef2fd2.com", ""], ["3450866c", "0711798090", "cda58109@c2e25542.com", ""], ["06e26393", "0735961481", "305bcf19@6c3ec630.com", ""], ["708af001", "0728438353", "048b067d@80d72f50.com", ""], ["c40ec0a3", "0726279359", "a10d333e@9a89cb7c.com", ""], ["2a2eb847", "0741461630", "d3daf952@7a3408e4.com", ""], ["d01a1813", "0704645200", "f226e03a@f67c7d10.com", ""], ["819cb8a9", "0798337915", "cf70d59b@d1a42e77.com", ""], ["6fa32598", "0701415106", "4a225f04@2534e6a3.com", ""], ["4e441149", "", "456f82ab@ca0b04a5.com", ""], ["f7ff1a4a", "0701515624", "5918544a@4bb3704b.com", ""], ["5738b682", "0724843216", "04c74b30@ed510bac.com", ""], ["f10e2d6a", "0730727806", "415d4081@b1a88a68.com", ""], ["749e83bd", "", "15e0671b@76428121.com", ""], ["3d65b85b", "", "d1eb4053@c363e69a.com", ""], ["a0792a15", "0729947768", "c24f344e@41f87b82.com", ""], ["fb01d572", "0792621720", "9c750d18@7fb1f5ce.com", ""], ["e67acc97", "0789099675", "bdfbe8ff@e2ca97d6.com", ""], ["a9e6cd4b", "0708488791", "1826128f@98d76c9c.com", ""], ["819f95a3", "0788991943", "cf458e5d@44f3c946.com", ""], ["20204d4c", "0714720322", "1efe1d68@5dddd6aa.com", ""], ["a1ea35bb", "0749468567", "480f2ab1@72a338ed.com", ""], ["92ffc165", "0780038157", "4dd11686@daa7a1e3.com", ""], ["4ba3f501", "", "71b12e98@a76b654f.com", ""], ["d7f5285b", "0736359794", "fc0e04a5@dde7291b.com", ""], ["77bfe67f", "0742014858", "b3c8790c@cacf5548.com", ""], ["dbf35774", "0726444745", "2243d1d2@138dfd54.com", ""], ["e9f91a9f", "0760618445", "db7cbba8@4616651c.com", ""], ["04c6be09", "", "9adf3814@5e01afe2.com", ""], ["b57e7ee3", "0722578719", "1736e501@964d3424.com", ""], ["d8114397", "", "6bc5e72a@bc4d7e37.com", ""], ["7ab21681", "", "aa33cd18@d6af8a2b.com", ""], ["290e81e9", "", "4d6f5933@bb9b4aa8.com", ""], ["5a1f2ac9", "0778832081", "53b60c08@8973dcfb.com", ""], ["f8775a07", "0743005567", "3c53f38a@c0918592.com", ""], ["30c7cdb1", "0779422190", "a809f36f@1b3dc9e3.com", ""], ["1c669546", "0793826953", "0b2728a3@f2f4eee2.com", ""], ["229beef7", "", "97621f15@237e6070.com", ""], ["ab8c48d5", "", "8545951c@c7523008.com", ""], ["e4294ab1", "", "6d8bdfd5@e9c1c910.com", ""], ["c9c8fbe2", "0729515527", "bcd2115d@e4500586.com", ""], ["0b6463d3", "0725941332", "e768eb3b@fbd48ad0.com", ""], ["15bbab63", "", "a8fd2422@b236a910.com", ""], ["c181cff0", "0717305018", "fb4e37ed@b611bc36.com", ""], ["03f712cd", "", "a05576b0@e16b8368.com", ""], ["31105e59", "0790432797", "6e4a7e2a@d6902424.com", ""], ["5c868ce0", "0738424344", "36348d0f@342e6bed.com", ""], ["d47bd754", "0793838363", "dd9d97d7@54a56407.com", ""], ["660908ec", "0707537040", "ae9b6681@a9382430.com", ""], ["2c6290a0", "0759084568", "b011def2@e1ac3f5a.com", ""], ["a989f05a", "", "25e59710@79b7f417.com", ""], ["f3c16d3b", "", "ded9819d@a99d7dc3.com", ""], ["1adf7818", "0751467205", "b96aa90a@9791c269.com", ""], ["409cc67e", "0777500182", "5317c827@a2db4c45.com", ""], ["aabd103f", "", "e5d907aa@bcc71e10.com", ""], ["d23bf430", "0777169222", "85e8641e@cc5f3d8b.com", ""], ["69a2879f", "0743889293", "4b5f4141@04205775.com", ""], ["8a3ec274", "0756861440", "ee663794@82c1f4fe.com", ""], ["b4a3cd48", "", "fc399765@64ca060b.com", ""], ["e0ccaed3", "", "6388033c@824e8b90.com", ""], ["c3eee2b9", "", "c0162073@2c2fd2b2.com", ""], ["a73c64c4", "", "f688a2e5@6e30672c.com", ""], ["2d852e73", "0772174434", "7a42d0d9@72486cd3.com", ""], ["a12254f5", "0769384878", "caf08e44@d46ed98b.com", ""], ["f653b74f", "0763997467", "388c7213@1126f95d.com", ""], ["fc93ee15", "0774848627", "beabdaca@2d84271e.com", ""], ["73c04bfd", "0771623831", "8fe53552@31ce4032.com", ""], ["74a5f23f", "0789722672", "82930bac@7dc3e501.com", ""], ["796d3e3d", "0762835594", "1181180a@ec66e2f0.com", ""], ["1bc14fc5", "0704902009", "ed326523@23e42c30.com", ""], ["5c08dcb0", "0765115244", "dd5945cf@f297b86b.com", ""], ["566bf582", "0723354400", "ea731083@ef83ec7c.com", ""], ["f25208d4", "0789906022", "457e0601@4eb796dd.com", ""], ["114eeeb3", "0758751442", "14cfa76b@aee76d12.com", ""], ["2669d4a2", "", "5ea1e2ac@cf638cf0.com", ""], ["6202f1c1", "", "d93e09a6@d3898452.com", ""], ["5126ade5", "", "96601158@cfeca444.com", ""], ["a0cef71f", "", "e9366869@532d79f8.com", ""], ["41bda0e9", "", "c4206b97@966c822f.com", ""], ["a75dc6cc", "", "12906204@892175ee.com", ""], ["79636bcc", "", "c45c9aae@a303f7d9.com", ""], ["e40fb55e", "", "72fe75ec@c1ddfd45.com", ""], ["e0ddb510", "", "ea6c8b14@193b1240.com", ""], ["c7532313", "", "a9361a51@f562d91e.com", ""], ["0158d9f3", "", "1de7b7e6@876beb92.com", ""], ["b2394690", "", "fe1b9570@3cffd682.com", ""], ["79051273", "", "fbb85c72@4532b2d6.com", ""], ["1ea2aeae", "", "6e8d529a@fa5af449.com", ""], ["2c637d3a", "", "b633e7ca@b2e822e5.com", ""], ["ba3b59cc", "", "10e596a4@e2654efc.com", ""], ["631c774b", "", "03b0156e@5f3383bd.com", ""], ["6e4d8e1d", "", "b7026e82@015d71cc.com", ""], ["3d430d86", "", "6af17483@bf92c6e9.com", ""], ["ea26cfde", "", "aeee3cf2@e06f3387.com", ""], ["16596f6f", "", "d1445706@a3282036.com", ""], ["9bc58d49", "", "", ""], ["cc907372", "", "a923bc16@c3febc01.com", ""], ["605dd0be", "", "49daa341@8ee4c07e.com", ""], ["1b1114f0", "", "ec5a8a0b@489a7dd5.com", ""], ["28b0c962", "", "", ""], ["63370e89", "", "44d07879@3c414118.com", ""], ["f3f1db57", "", "", ""], ["ac49009b", "", "e5cd7740@ea261a3b.com", ""], ["9e46dcc0", "", "83a47ee1@a58545dc.com", ""], ["2e95367c", "", "8bee6be7@8906c53f.com", ""], ["ea22c7bb", "", "53b4805b@af24dcf7.com", ""], ["c90f526b", "", "d790585d@8d10cf2a.com", ""], ["7887a62b", "", "7120351b@ff19865b.com", ""], ["64cb3f9d", "", "", ""], ["9e591fa7", "", "c7730953@a714f3a7.com", ""], ["1f16cd07", "", "67bebc78@40ed8809.com", ""], ["287ec13a", "", "9e5e71cb@2bb1c891.com", ""], ["d164c461", "", "1cd6e067@14c6ada1.com", ""], ["36379fd3", "", "72a5809d@9b00b1bb.com", ""], ["9470c307", "", "2816f5ec@451ff875.com", ""], ["1655c648", "", "f06ec4a5@f5ab6d4c.com", ""], ["879040ac", "", "62e235cb@ec8a0c43.com", ""], ["50232cdf", "", "025cd190@2477e789.com", ""], ["5a35f64f", "", "", ""], ["777de661", "", "38640b10@41514086.com", ""], ["705fb8cf", "", "7284860f@b222b1f8.com", ""], ["fcb30c1b", "", "361fde21@1f411552.com", ""], ["079e7250", "", "6bbcefcd@2aeb37af.com", ""], ["4e47023c", "", "d23b6b4d@b0b56474.com", ""], ["1bce884e", "", "1dfab7b8@68a3a0ef.com", ""], ["7088e56a", "", "6570590b@e2a30ae0.com", ""], ["65ce20d2", "", "86106467@58070f61.com", ""], ["68d599aa", "", "e279dc2a@58d99123.com", ""], ["0142c624", "", "9abe7329@cb4a4022.com", ""], ["9e8bcae3", "", "840f16ca@1ed99fc8.com", ""], ["4b854254", "", "fbf12ee9@6499201a.com", ""], ["615d5c95", "", "abce7c9f@ade377af.com", ""], ["d389a4b2", "", "a78f0fc2@a6f959cd.com", ""], ["38be0158", "", "bfa96d44@f363eb7c.com", ""], ["f9e06f7c", "", "542bd29b@97746a9e.com", ""], ["832811a7", "", "9bf9010e@01957fac.com", ""], ["359a78e3", "", "3248a6d3@763ddb24.com", ""], ["27f9817c", "", "07d94000@2aca2301.com", ""], ["013a3bd4", "", "2224822e@fade404f.com", ""], ["a0ef9d39", "", "", ""], ["b024d6ee", "", "0daa6bb1@2ef82615.com", ""], ["a381acc3", "", "bad81f63@dc7acb79.com", ""], ["7610e7b9", "", "59829816@d8a49cb9.com", ""], ["4460acd9", "", "acf4b236@dd8a5e68.com", ""], ["5193bc70", "", "f5620364@f763b237.com", ""], ["9d134fef", "", "df0234b6@ae3b90cf.com", ""], ["8d8c4586", "", "f92d2add@0f93928c.com", ""], ["2d12e299", "", "99162fbe@59bd4569.com", ""], ["bcc4641b", "", "afff34a5@f2e5d247.com", ""], ["5c2243c3", "", "3ef0d599@f34a9ed2.com", ""], ["427913d9", "", "086fe7e8@925e9a12.com", ""], ["3a60c0ec", "", "66c4dfbc@cee34594.com", ""], ["ffca31e8", "", "0a4a245c@68e91e5e.com", ""], ["7df057ab", "", "335cabf9@a17a61b3.com", ""], ["71307e65", "", "c1de44cd@a1add235.com", ""], ["17bf2c39", "", "601cc244@f0efd775.com", ""], ["a8b9e2e1", "", "de175716@d0cfb7a0.com", ""], ["a294ae4d", "", "", ""], ["37859daf", "", "376f0f2b@369a7bcf.com", ""], ["01e1685f", "", "6fed663d@3672e214.com", ""], ["0a32e0c6", "", "0b0791c3@2c33f23e.com", ""], ["5b8ff540", "", "29599ad0@548964c2.com", ""], ["eec1094b", "", "dfa57b8f@80b6e55e.com", ""], ["acf49b4d", "", "4c20a1c0@c6d0e041.com", ""], ["63867c55", "", "", ""], ["873984c8", "", "1cf228b4@b15a1b5f.com", ""], ["ecde582c", "", "cc419b7b@60107818.com", ""], ["039d5e8f", "", "5da65ece@1bb69031.com", ""], ["21f04ac9", "", "8ee84896@25275182.com", ""], ["735349c7", "", "117051ac@3a4fd4d7.com", ""], ["273761c9", "", "0184bda8@198fe950.com", ""], ["200dff3c", "", "cb311031@7c6cc49c.com", ""], ["80a68462", "", "5f3c6275@44263f25.com", ""], ["53ace4f9", "", "733a3c0e@c7fd4969.com", ""], ["484e9625", "", "bfe97c09@d2ef03d6.com", ""], ["b798a822", "", "cd531d09@aa763932.com", ""], ["04cecc11", "", "e173c817@3977a28a.com", ""], ["2a910e01", "", "5e200dad@5cf70a26.com", ""], ["540b1452", "", "c9462faa@cb7652ed.com", ""], ["80261f65", "", "fea8b5bc@e5018e45.com", ""], ["9e4fa7c2", "", "95f3f9c9@f265aefc.com", ""], ["f0227223", "", "702f9660@2006f10b.com", ""], ["500bb986", "", "40a22a5c@ed4055c3.com", ""], ["34c14a29", "", "3d2633f6@206a53a0.com", ""], ["66a868a5", "", "7a2b1e68@9cf601fb.com", ""], ["af8d6986", "", "", ""], ["1fbefa32", "", "e948b9f8@c0fe216c.com", ""], ["ee799cb5", "", "01013bb3@229547a9.com", ""], ["b2ce8d2e", "", "fe3750e1@ee50e669.com", ""], ["ae7c0d5b", "0727494158", "68aad918@674f032f.com", ""], ["1c55c64e", "", "efc9a2bb@1fec90ba.com", ""], ["2eef74a3", "", "238d16ec@14658003.com", ""], ["5ba48a58", "", "c6d52520@65f96971.com", ""], ["e650ca0a", "", "76be4eba@a74dba94.com", ""], ["f977adbb", "0789591713", "68b0f662@c01e961d.com", ""], ["ac083f57", "0718005506", "6443f242@7ed34530.com", ""], ["0c7080de", "0791608592", "4444abf7@63b54852.com", ""], ["599039e0", "0717263596", "34898b46@b248d961.com", ""], ["33656705", "0788380435", "0d6c86a9@0d0b30a4.com", ""], ["f0d6f309", "0766220442", "22d01833@9bba21ab.com", ""], ["7c27f7a0", "0740179768", "69d0ce4f@829116df.com", ""], ["cba407c8", "0745165304", "4e94762c@6033decd.com", ""], ["3a9c0bcd", "0738794804", "ea1ca3ef@bd6258aa.com", ""], ["006b2bde", "0759645406", "822277ef@e36775c4.com", ""], ["fe832f26", "", "", ""], ["03c43ae1", "0776208246", "8e64a53e@d0aefbfb.com", ""], ["4ae6a913", "0798677379", "4affe084@f4ee6d7c.com", ""], ["5d3d3ca1", "0755000779", "0ea61d50@7ffd96e5.com", ""], ["dc58f75f", "0717795899", "119adc66@edbc9bac.com", ""], ["593f7e23", "", "d3161d49@fe2ad83f.com", ""], ["e5075ec4", "0760361665", "2f410a97@1b02d6a2.com", ""], ["a0d86ad4", "0765965949", "0fb55b69@cd1c2b77.com", ""], ["09e6e8a1", "0790479077", "cc542c67@9cb69e36.com", ""], ["77bb6d11", "0720961023", "60ff31ae@d9349e56.com", ""], ["e2f4aed5", "0735608325", "663b0400@671dff5d.com", ""], ["149211a9", "0706545912", "8481da49@233dfe8e.com", ""], ["59a53ba0", "", "3401405f@e1c370ad.com", ""], ["60a4c106", "0746099226", "7003f4bf@6a7770b2.com", ""], ["4483788d", "0728712830", "b30ee032@1694bb85.com", ""], ["ee8a3129", "0712964023", "34ee5c80@c82fb116.com", ""], ["c8bdde49", "", "3ac6c6dd@13bc3322.com", ""], ["65a477be", "0705359300", "a67e1d49@966dedb0.com", ""], ["d1a51add", "", "", ""], ["467392b8", "0765663197", "f878eeb4@7334e9fd.com", ""], ["61b4a1d6", "", "9d7e523e@e334c7d2.com", ""], ["16bbecf4", "0794827711", "39dff936@596fb073.com", ""], ["1cd25515", "0786915799", "d1c9de87@fb823959.com", ""], ["9d653b08", "0783707353", "75f1c3fa@dca1ac44.com", ""], ["cb93adc9", "0757349238", "7c3f098b@cf9bb4fe.com", ""], ["5f879d9e", "0764695115", "0a710345@b99b17e3.com", ""], ["8b840055", "", "", ""], ["d436dacc", "0796095598", "ea120899@3c8f6ea0.com", ""], ["1d0faf93", "0744424802", "3cf588a8@44544be8.com", ""], ["4ee8b8f7", "0764292501", "", ""]] \ No newline at end of file From 9d175bdfd60cda0335c0229876e46f72e7101249 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 27 Sep 2012 11:50:38 +0200 Subject: [PATCH 064/409] [FIX] postgres 9.2 added data at the end of 23502's error message, only use prefix matches not fullstring bzr revid: xmo@openerp.com-20120927095038-m2vm663nqj1s1pne --- openerp/osv/orm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 81063deb180..641d21d6327 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -5376,7 +5376,7 @@ class ImportWarning(Warning): def convert_pgerror_23502(model, fields, info, e): m = re.match(r'^null value in column "(?P\w+)" violates ' - r'not-null constraint\n$', + r'not-null constraint\n', str(e)) if not m or m.group('field') not in fields: return {'message': unicode(e)} From f39730e918bc85c770dfa6edd52394351d54d006 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 27 Sep 2012 12:34:52 +0200 Subject: [PATCH 065/409] [FIX] make conversion errors for floats and integers more predictable Python turns out to have changed the wording of the messages between 2.6 and 2.7 also, these messages need to be translatable *and* use the human-readable field name bzr revid: xmo@openerp.com-20120927103452-cvgv3e8dsvcvnics --- openerp/addons/base/ir/ir_fields.py | 14 ++++++++++++-- openerp/tests/addons/test_impex/tests/test_load.py | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py index 621dd93d469..ba6681bee15 100644 --- a/openerp/addons/base/ir/ir_fields.py +++ b/openerp/addons/base/ir/ir_fields.py @@ -100,10 +100,20 @@ class ir_fields_converter(orm.Model): return True def _str_to_integer(self, cr, uid, model, column, value, context=None): - return int(value) + try: + return int(value) + except ValueError: + raise ValueError( + _(u"'%s' does not seem to be an integer for field '%%(field)s'") + % value) def _str_to_float(self, cr, uid, model, column, value, context=None): - return float(value) + try: + return float(value) + except ValueError: + raise ValueError( + _(u"'%s' does not seem to be a number for field '%%(field)s'") + % value) def _str_to_char(self, cr, uid, model, column, value, context=None): return value diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index 72442963af5..032dd65ef07 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -275,7 +275,7 @@ class test_integer_field(ImporterCase): 'rows': {'from': 0, 'to': 0}, 'record': 0, 'field': 'value', - 'message': u"invalid literal for int() with base 10: 'zorglub'", + 'message': u"'zorglub' does not seem to be an integer for field 'unknown'", }]) class test_float_field(ImporterCase): @@ -344,7 +344,7 @@ class test_float_field(ImporterCase): 'rows': {'from': 0, 'to': 0}, 'record': 0, 'field': 'value', - 'message': u"invalid literal for float(): foobar", + 'message': u"'foobar' does not seem to be a number for field 'unknown'", }]) class test_string_field(ImporterCase): From 4f74d0aee15da72d386b03ba721b8ac67c4ea5a5 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 27 Sep 2012 14:19:54 +0200 Subject: [PATCH 066/409] [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 067/409] [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 87af7a63654b279d79a8b4eb3c5fb675ef7a8708 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 27 Sep 2012 16:43:41 +0200 Subject: [PATCH 068/409] [FIX] replace warnings capture by explicitly returning a list of warnings from converters makes converter code noisier, but ultimately simpler without having access to dynamically scoped variables bzr revid: xmo@openerp.com-20120927144341-j1dx3e0epf3i5ja6 --- openerp/addons/base/ir/ir_fields.py | 82 ++++++++++--------- openerp/osv/orm.py | 10 +-- .../addons/test_impex/tests/test_load.py | 2 +- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py index ba6681bee15..7a4c34c7f30 100644 --- a/openerp/addons/base/ir/ir_fields.py +++ b/openerp/addons/base/ir/ir_fields.py @@ -2,7 +2,6 @@ import functools import operator import itertools -import warnings from openerp.osv import orm, fields from openerp.tools.translate import _ @@ -38,9 +37,9 @@ class ir_fields_converter(orm.Model): By default, tries to get a method on itself with a name matching the pattern ``_$fromtype_$column._type`` and returns it. - Converter callables can either return a value to their caller or raise - ``ValueError``, which will be interpreted as a validation & conversion - failure. + Converter callables can either return a value and a list of warnings + to their caller or raise ``ValueError``, which will be interpreted as a + validation & conversion failure. ValueError can have either one or two parameters. The first parameter is mandatory, **must** be a unicode string and will be used as the @@ -53,10 +52,10 @@ class ir_fields_converter(orm.Model): client. If a converter can perform its function but has to make assumptions - about the data, it can send a warning to the user through signalling - an :class:`~openerp.osv.orm.ImportWarning` (via ``warnings.warn``). The - handling of a warning at the upper levels is the same as - ``ValueError`` above. + about the data, it can send a warning to the user through adding an + instance of :class:`~openerp.osv.orm.ImportWarning` to the second value + it returns. The handling of a warning at the upper levels is the same + as ``ValueError`` above. :param cr: openerp cursor :param uid: ID of user calling the converter @@ -84,7 +83,7 @@ class ir_fields_converter(orm.Model): self._get_translations(cr, uid, ['code'], u"true", context=context), self._get_translations(cr, uid, ['code'], u"yes", context=context), )) - if value.lower() in trues: return True + if value.lower() in trues: return True, [] # potentially broken casefolding? What about locales? falses = set(word.lower() for word in itertools.chain( @@ -92,16 +91,15 @@ class ir_fields_converter(orm.Model): self._get_translations(cr, uid, ['code'], u"false", context=context), self._get_translations(cr, uid, ['code'], u"no", context=context), )) - if value.lower() in falses: return False + if value.lower() in falses: return False, [] - warnings.warn(orm.ImportWarning( + return True, [orm.ImportWarning( _(u"Unknown value '%s' for boolean field '%%(field)s', assuming '%s'") - % (value, yes))) - return True + % (value, yes))] def _str_to_integer(self, cr, uid, model, column, value, context=None): try: - return int(value) + return int(value), [] except ValueError: raise ValueError( _(u"'%s' does not seem to be an integer for field '%%(field)s'") @@ -109,20 +107,20 @@ class ir_fields_converter(orm.Model): def _str_to_float(self, cr, uid, model, column, value, context=None): try: - return float(value) + return float(value), [] except ValueError: raise ValueError( _(u"'%s' does not seem to be a number for field '%%(field)s'") % value) def _str_to_char(self, cr, uid, model, column, value, context=None): - return value + return value, [] def _str_to_text(self, cr, uid, model, column, value, context=None): - return value + return value, [] def _str_to_binary(self, cr, uid, model, column, value, context=None): - return value + return value, [] def _get_translations(self, cr, uid, types, src, context): types = tuple(types) @@ -151,7 +149,7 @@ class ir_fields_converter(orm.Model): cr, uid, ('selection', 'model', 'code'), label, context=context) labels.append(label) if value == unicode(item) or value in labels: - return item + return item, [] raise ValueError( _(u"Value '%s' not found in selection field '%%(field)s'") % ( value), { @@ -173,11 +171,14 @@ class ir_fields_converter(orm.Model): id :param value: value of the reference to match to an actual record :param context: OpenERP request context - :return: a pair of the matched database identifier (if any) and the - translated user-readable name for the field - :rtype: (ID|None, unicode) + :return: a pair of the matched database identifier (if any), the + translated user-readable name for the field and the list of + warnings + :rtype: (ID|None, unicode, list) """ + if context is None: context = {} id = None + warnings = [] RelatedModel = self.pool[column._obj] if subfield == '.id': field_type = _(u"database id") @@ -191,7 +192,7 @@ class ir_fields_converter(orm.Model): if '.' in value: module, xid = value.split('.', 1) else: - module, xid = '', value + module, xid = context.get('_import_current_module', ''), value ModelData = self.pool['ir.model.data'] try: md_id = ModelData._get_id(cr, uid, module, xid) @@ -206,7 +207,7 @@ class ir_fields_converter(orm.Model): cr, uid, name=value, operator='=', context=context) if ids: if len(ids) > 1: - warnings.warn(orm.ImportWarning( + warnings.append(orm.ImportWarning( _(u"Found multiple matches for field '%%(field)s' (%d matches)") % (len(ids)))) id, _name = ids[0] @@ -227,7 +228,7 @@ class ir_fields_converter(orm.Model): 'help': _(u"See all possible values") } }) - return id, field_type + return id, field_type, warnings def _referencing_subfield(self, record): """ Checks the record for the subfields allowing referencing (an @@ -236,8 +237,8 @@ class ir_fields_converter(orm.Model): returns the name of the correct subfield. :param record: - :return: the record subfield to use for referencing - :rtype: str + :return: the record subfield to use for referencing and a list of warnings + :rtype: str, list """ # Can import by name_get, external id or database id fieldset = set(record.iterkeys()) @@ -250,39 +251,42 @@ class ir_fields_converter(orm.Model): # only one field left possible, unpack [subfield] = fieldset - return subfield + return subfield, [] def _str_to_many2one(self, cr, uid, model, column, values, context=None): # Should only be one record, unpack [record] = values - subfield = self._referencing_subfield(record) + subfield, w1 = self._referencing_subfield(record) reference = record[subfield] - id, subfield_type = self.db_id_for( + id, subfield_type, w2 = self.db_id_for( cr, uid, model, column, subfield, reference, context=context) - return id + return id, w1 + w2 def _str_to_many2many(self, cr, uid, model, column, value, context=None): [record] = value - subfield = self._referencing_subfield(record) + subfield, warnings = self._referencing_subfield(record) ids = [] for reference in record[subfield].split(','): - id, subfield_type = self.db_id_for( + id, subfield_type, ws = self.db_id_for( cr, uid, model, column, subfield, reference, context=context) ids.append(id) - return [(6, 0, ids)] + warnings.extend(ws) + return [(6, 0, ids)], warnings def _str_to_one2many(self, cr, uid, model, column, records, context=None): commands = [] + warnings = [] if len(records) == 1 and exclude_ref_fields(records[0]) == {}: # only one row with only ref field, field=ref1,ref2,ref3 as in # m2o/m2m record = records[0] - subfield = self._referencing_subfield(record) + subfield, ws = self._referencing_subfield(record) + warnings.extend(ws) # transform [{subfield:ref1,ref2,ref3}] into # [{subfield:ref1},{subfield:ref2},{subfield:ref3}] records = ({subfield:item} for item in record[subfield].split(',')) @@ -292,10 +296,12 @@ class ir_fields_converter(orm.Model): refs = only_ref_fields(record) # there are ref fields in the record if refs: - subfield = self._referencing_subfield(refs) + subfield, w1 = self._referencing_subfield(refs) + warnings.extend(w1) reference = record[subfield] - id, subfield_type = self.db_id_for( + id, subfield_type, w2 = self.db_id_for( cr, uid, model, column, subfield, reference, context=context) + warnings.extend(w2) writable = exclude_ref_fields(record) if id: @@ -304,4 +310,4 @@ class ir_fields_converter(orm.Model): else: commands.append(CREATE(writable)) - return commands + return commands, warnings diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 641d21d6327..9bd04dd56a8 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1670,15 +1670,9 @@ class BaseModel(object): message_base = dict( extras, record=stream.index, field=field_names[field]) try: - with warnings.catch_warnings(record=True) as ws: - converted[field] = converters[field](strvalue) + converted[field], ws = converters[field](strvalue) - for warning in ws: - # bubble non-import warnings upward - if warning.category != ImportWarning: - warnings.warn(warning.message, warning.category) - continue - w = warning.message + for w in ws: if isinstance(w, basestring): # wrap warning string in an ImportWarning for # uniform handling diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index 032dd65ef07..a5c3dcc5bbf 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -186,7 +186,7 @@ class test_boolean_field(ImporterCase): message(u"Unknown value '%s' for boolean field 'unknown', assuming 'yes'" % v[0], type='warning', from_=i, to_=i, record=i) for i, v in enumerate(trues) - if v[0] != 'true' if v[0] != 'yes' if v[0] != '1' + if v[0] not in ('true', 'yes', '1') ]) self.assertEqual( [True] * 10, From def7e61901dafc41cb0b404b1e74275b00deaa1b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 27 Sep 2012 17:42:44 +0200 Subject: [PATCH 069/409] [IMP] reimplement BaseModel.import_data on top of BaseModel.load adapt tests to assert the corrected behavior of load instead of import_data's broken behavior bzr revid: xmo@openerp.com-20120927154244-e56ygz2yytullg2l --- openerp/osv/orm.py | 196 +++--------------- .../addons/test_impex/tests/test_import.py | 175 +++++++--------- .../addons/test_impex/tests/test_load.py | 4 +- 3 files changed, 98 insertions(+), 277 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 9bd04dd56a8..934b6eaf2e4 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1254,189 +1254,43 @@ class BaseModel(object): :returns: 4-tuple in the form (return_code, errored_resource, error_message, unused) :rtype: (int, dict or 0, str or 0, str or 0) """ - if not context: - context = {} + context = dict(context) if context is not None else {} + context['_import_current_module'] = current_module + fields = map(fix_import_export_id_paths, fields) ir_model_data_obj = self.pool.get('ir.model.data') - # mode: id (XML id) or .id (database id) or False for name_get - def _get_id(model_name, id, current_module=False, mode='id'): - if mode=='.id': - id = int(id) - obj_model = self.pool.get(model_name) - ids = obj_model.search(cr, uid, [('id', '=', int(id))]) - if not len(ids): - raise Exception(_("Database ID doesn't exist: %s : %s") %(model_name, id)) - elif mode=='id': - if '.' in id: - module, xml_id = id.rsplit('.', 1) - else: - module, xml_id = current_module, id - record_id = ir_model_data_obj._get_id(cr, uid, module, xml_id) - ir_model_data = ir_model_data_obj.read(cr, uid, [record_id], ['res_id']) - if not ir_model_data: - raise ValueError('No references to %s.%s' % (module, xml_id)) - id = ir_model_data[0]['res_id'] - else: - obj_model = self.pool.get(model_name) - ids = obj_model.name_search(cr, uid, id, operator='=', context=context) - if not ids: - raise ValueError('No record found for %s' % (id,)) - id = ids[0][0] - return id + def log(m): + if m['type'] == 'error': + raise Exception(m['message']) - # IN: - # datas: a list of records, each record is defined by a list of values - # prefix: a list of prefix fields ['line_ids'] - # position: the line to process, skip is False if it's the first line of the current record - # OUT: - # (res, position, warning, res_id) with - # res: the record for the next line to process (including it's one2many) - # position: the new position for the next line - # res_id: the ID of the record if it's a modification - def process_liness(self, datas, prefix, current_module, model_name, fields_def, position=0, skip=0): - line = datas[position] - row = {} - warning = [] - data_res_id = False - xml_id = False - nbrmax = position+1 - - done = {} - for i, field in enumerate(fields): - res = False - if i >= len(line): - raise Exception(_('Please check that all your lines have %d columns.' - 'Stopped around line %d having %d columns.') % \ - (len(fields), position+2, len(line))) - if not line[i]: - continue - - if field[:len(prefix)] <> prefix: - if line[i] and skip: - return False - continue - field_name = field[len(prefix)] - - #set the mode for m2o, o2m, m2m : xml_id/id/name - if len(field) == len(prefix)+1: - mode = False - else: - mode = field[len(prefix)+1] - - # TODO: improve this by using csv.csv_reader - def many_ids(line, relation, current_module, mode): - res = [] - for db_id in line.split(config.get('csv_internal_sep')): - res.append(_get_id(relation, db_id, current_module, mode)) - return [(6,0,res)] - - # ID of the record using a XML ID - if field_name == 'id': - try: - data_res_id = _get_id(model_name, line[i], current_module) - except ValueError: - pass - xml_id = line[i] - continue - - # ID of the record using a database ID - elif field_name == '.id': - data_res_id = _get_id(model_name, line[i], current_module, '.id') - continue - - field_type = fields_def[field_name]['type'] - # recursive call for getting children and returning [(0,0,{})] or [(1,ID,{})] - if field_type == 'one2many': - if field_name in done: - continue - done[field_name] = True - relation = fields_def[field_name]['relation'] - relation_obj = self.pool.get(relation) - newfd = relation_obj.fields_get( cr, uid, context=context ) - pos = position - - res = [] - - first = 0 - while pos < len(datas): - res2 = process_liness(self, datas, prefix + [field_name], current_module, relation_obj._name, newfd, pos, first) - if not res2: - break - (newrow, pos, w2, data_res_id2, xml_id2) = res2 - nbrmax = max(nbrmax, pos) - warning += w2 - first += 1 - - if (not newrow) or not reduce(lambda x, y: x or y, newrow.values(), 0): - break - - res.append( (data_res_id2 and 1 or 0, data_res_id2 or 0, newrow) ) - - elif field_type == 'many2one': - relation = fields_def[field_name]['relation'] - res = _get_id(relation, line[i], current_module, mode) - - elif field_type == 'many2many': - relation = fields_def[field_name]['relation'] - res = many_ids(line[i], relation, current_module, mode) - - elif field_type == 'integer': - res = line[i] and int(line[i]) or 0 - elif field_type == 'boolean': - res = line[i].lower() not in ('0', 'false', 'off') - elif field_type == 'float': - res = line[i] and float(line[i]) or 0.0 - elif field_type == 'selection': - for key, val in fields_def[field_name]['selection']: - if tools.ustr(line[i]) in [tools.ustr(key), tools.ustr(val)]: - res = key - break - if line[i] and not res: - _logger.warning( - _("key '%s' not found in selection field '%s'"), - tools.ustr(line[i]), tools.ustr(field_name)) - warning.append(_("Key/value '%s' not found in selection field '%s'") % ( - tools.ustr(line[i]), tools.ustr(field_name))) - - else: - res = line[i] - - row[field_name] = res or False - - return row, nbrmax, warning, data_res_id, xml_id - - fields_def = self.fields_get(cr, uid, context=context) - - position = 0 if config.get('import_partial') and filename: with open(config.get('import_partial'), 'rb') as partial_import_file: data = pickle.load(partial_import_file) position = data.get(filename, 0) - while position o2m resolution skipped altogether, - # creates 2 records => remove/don't import columns sideshow columns, - # get completely different semantics - b, b1 = self.browse() + [b] = self.browse() self.assertEqual(b.const, 42) - self.assertEqual(values(b.value), []) - self.assertEqual(b1.const, 4) - self.assertEqual(values(b1.value), []) + # automatically forces link between core record and o2ms + self.assertEqual(values(b.value), [109, 262]) + self.assertEqual(values(b.value, field='parent_id'), [b, b]) def test_link_2(self): O2M_c = self.registry('export.one2many.child') @@ -838,21 +822,10 @@ class test_o2m(ImporterCase): ]), ok(2)) - (b,) = self.browse() - # if an id (db or xid) is provided, expectations that objects are - # *already* linked and emits UPDATE (1, id, {}). - # Noid => CREATE (0, ?, {}) - # TODO: xid ignored aside from getting corresponding db id? + [b] = self.browse() self.assertEqual(b.const, 42) - self.assertEqual(values(b.value), []) - - # FIXME: updates somebody else's records? - self.assertEqual( - O2M_c.read(self.cr, openerp.SUPERUSER_ID, id1), - {'id': id1, 'str': 'Bf', 'value': 1, 'parent_id': False}) - self.assertEqual( - O2M_c.read(self.cr, openerp.SUPERUSER_ID, id2), - {'id': id2, 'str': 'Me', 'value': 2, 'parent_id': False}) + self.assertEqual(values(b.value), [1, 2]) + self.assertEqual(values(b.value, field='parent_id'), [b, b]) class test_o2m_multiple(ImporterCase): model_name = 'export.one2many.multiple' @@ -866,16 +839,10 @@ class test_o2m_multiple(ImporterCase): ['', '14', ''], ]), ok(4)) - # Oh yeah, that's the stuff - (b, b1, b2) = self.browse() - self.assertEqual(values(b.child1), [11]) - self.assertEqual(values(b.child2), [21]) - self.assertEqual(values(b1.child1), [12]) - self.assertEqual(values(b1.child2), [22]) - - self.assertEqual(values(b2.child1), [13, 14]) - self.assertEqual(values(b2.child2), [23]) + [b] = self.browse() + self.assertEqual(values(b.child1), [11, 12, 13, 14]) + self.assertEqual(values(b.child2), [21, 22, 23]) def test_multi(self): self.assertEqual( @@ -888,11 +855,10 @@ class test_o2m_multiple(ImporterCase): ['', '', '23'], ]), ok(6)) - # What the actual fuck? - (b, b1) = self.browse() + + [b] = self.browse() self.assertEqual(values(b.child1), [11, 12, 13, 14]) - self.assertEqual(values(b.child2), [21]) - self.assertEqual(values(b1.child2), [22, 23]) + self.assertEqual(values(b.child2), [21, 22, 23]) def test_multi_fullsplit(self): self.assertEqual( @@ -906,12 +872,11 @@ class test_o2m_multiple(ImporterCase): ['', '', '23'], ]), ok(7)) - # oh wow - (b, b1) = self.browse() + + [b] = self.browse() self.assertEqual(b.const, 5) self.assertEqual(values(b.child1), [11, 12, 13, 14]) - self.assertEqual(b1.const, 36) - self.assertEqual(values(b1.child2), [21, 22, 23]) + self.assertEqual(values(b.child2), [21, 22, 23]) # function, related, reference: written to db as-is... # => function uses @type for value coercion/conversion diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index a5c3dcc5bbf..c141e62b65d 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -394,12 +394,14 @@ class test_unbound_string_field(ImporterCase): class test_required_string_field(ImporterCase): model_name = 'export.string.required' + @mute_logger('openerp.sql_db') def test_empty(self): result = self.import_(['value'], [[]]) self.assertEqual(result['messages'], [message( u"Missing required value for the field 'unknown'")]) self.assertIs(result['ids'], False) + @mute_logger('openerp.sql_db') def test_not_provided(self): result = self.import_(['const'], [['12']]) self.assertEqual(result['messages'], [message( @@ -920,7 +922,7 @@ class test_o2m_multiple(ImporterCase): ]) self.assertFalse(result['messages']) self.assertEqual(len(result['ids']), 1) - # Oh yeah, that's the stuff + [b] = self.browse() self.assertEqual(values(b.child1), [11, 12, 13, 14]) self.assertEqual(values(b.child2), [21, 22, 23]) From 98e4725ce07b6b76a7a5c15fbeaf6ae2df8014d0 Mon Sep 17 00:00:00 2001 From: Vishmita Date: Fri, 28 Sep 2012 12:07:48 +0530 Subject: [PATCH 070/409] [Fix]Pass event on click of download button. bzr revid: vja@tinyerp.com-20120928063748-cnsecd8mmevb2fbu --- addons/web/static/src/js/view_form.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index c888c13e6be..98a558661b5 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -4692,9 +4692,9 @@ instance.web.form.FieldBinaryFile = instance.web.form.FieldBinary.extend({ this._super(); if (this.get("effective_readonly")) { var self = this; - this.$el.find('a').click(function() { + this.$el.find('a').click(function(ev) { if (self.get('value')) { - self.on_save_as(); + self.on_save_as(ev); } return false; }); From aaff4459c438bdbb4b2d5f62bbd95a155904136c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 28 Sep 2012 08:56:54 +0200 Subject: [PATCH 071/409] [DOC] fixes and cleanups bzr revid: xmo@openerp.com-20120928065654-jj3ot17dz8vd3wum --- .bzrignore | 31 ++++++---- doc/api/user_img_specs.rst | 25 ++++++-- doc/conf.py | 24 +++---- openerp/osv/expression.py | 124 ++++++++++++++++++++----------------- openerp/osv/orm.py | 12 +++- openerp/osv/query.py | 14 ++--- 6 files changed, 135 insertions(+), 95 deletions(-) diff --git a/.bzrignore b/.bzrignore index ba5258506be..8531ad42bbb 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,14 +1,19 @@ -.* -*.egg-info -*.orig -*.vim +.*.swp +.bzrignore +.idea +.project +.pydevproject +.ropeproject +.settings +.DS_Store +openerp/addons/* +openerp/filestore* +.Python +*.pyc +*.pyo +bin/* build/ -RE:^bin/ -RE:^dist/ -RE:^include/ - -RE:^share/ -RE:^man/ -RE:^lib/ - -RE:^doc/_build/ +include/ +lib/ +share/ +doc/_build/* diff --git a/doc/api/user_img_specs.rst b/doc/api/user_img_specs.rst index a915529accd..c6729eed920 100644 --- a/doc/api/user_img_specs.rst +++ b/doc/api/user_img_specs.rst @@ -3,9 +3,24 @@ User avatar .. versionadded:: 7.0 -This revision adds an avatar for users. This replaces the use of gravatar to emulate avatars, used in views like the tasks kanban view. Two fields have been added to the res.users model: - - avatar_big, a binary field holding the image. It is base-64 encoded, and PIL-supported. Images stored are resized to 540x450 px, to limitate the binary field size. - - avatar, a function binary field holding an automatically resized version of the avatar_big field. It is also base-64 encoded, and PIL-supported. Dimensions of the resized avatar are 180x150. This field is used as an inteface to get and set the user avatar. -When changing the avatar through the avatar function field, the new image is automatically resized to 540x450, and stored in the avatar_big field. This triggers the function field, that will compute a 180x150 resized version of the image. +This revision adds an avatar for users. This replaces the use of +gravatar to emulate avatars, used in views like the tasks kanban +view. Two fields have been added to the res.users model: -An avatar field has been added to the users form view, as well as in Preferences. When creating a new user, a default avatar is chosen among 6 possible default images. +* ``avatar_big``, a binary field holding the image. It is base-64 + encoded, and PIL-supported. Images stored are resized to 540x450 px, + to limitate the binary field size. + +* ``avatar``, a function binary field holding an automatically resized + version of the avatar_big field. It is also base-64 encoded, and + PIL-supported. Dimensions of the resized avatar are 180x150. This + field is used as an inteface to get and set the user avatar. + +When changing the avatar through the avatar function field, the new +image is automatically resized to 540x450, and stored in the +avatar_big field. This triggers the function field, that will compute +a 180x150 resized version of the image. + +An avatar field has been added to the users form view, as well as in +Preferences. When creating a new user, a default avatar is chosen +among 6 possible default images. diff --git a/doc/conf.py b/doc/conf.py index a5ff6bed7e1..ac5b8907e0e 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -16,9 +16,10 @@ import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) sys.path.append(os.path.abspath('_themes')) -sys.path.insert(0, os.path.abspath('../addons')) -sys.path.insert(0, os.path.abspath('..')) +sys.path.append(os.path.abspath('..')) +sys.path.append(os.path.abspath('../openerp')) # -- General configuration ----------------------------------------------------- @@ -42,7 +43,7 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'OpenERP Web Developers Documentation' +project = u'OpenERP Server Developers Documentation' copyright = u'2012, OpenERP s.a.' # The version info for the project you're documenting, acts as replacement for @@ -50,9 +51,9 @@ copyright = u'2012, OpenERP s.a.' # built documents. # # The short X.Y version. -version = '6.1' +version = '7.0' # The full version, including alpha/beta/rc tags. -release = '6.1' +release = '7.0b' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -170,7 +171,7 @@ html_sidebars = { #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'openerp-web-doc' +htmlhelp_basename = 'openerp-server-doc' # -- Options for LaTeX output -------------------------------------------------- @@ -189,7 +190,7 @@ latex_elements = { # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'openerp-web-doc.tex', u'OpenERP Web Developers Documentation', + ('index', 'openerp-server-doc.tex', u'OpenERP Server Developers Documentation', u'OpenERP s.a.', 'manual'), ] @@ -219,7 +220,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'openerp-web-doc', u'OpenERP Web Developers Documentation', + ('index', 'openerp-server-doc', u'OpenERP Server Developers Documentation', [u'OpenERP s.a.'], 1) ] @@ -233,8 +234,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'OpenERPWebDocumentation', u'OpenERP Web Developers Documentation', - u'OpenERP s.a.', 'OpenERPWebDocumentation', 'Developers documentation for the openerp-web project.', + ('index', 'OpenERPServerDocumentation', u'OpenERP Server Developers Documentation', + u'OpenERP s.a.', 'OpenERPServerDocumentation', 'Developers documentation for the openobject-server project.', 'Miscellaneous'), ] @@ -247,11 +248,10 @@ texinfo_documents = [ # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' -todo_include_todos = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { 'python': ('http://docs.python.org/', None), - 'openerpserver': ('http://doc.openerp.com/trunk/developers/server', None), + 'openerpweb': ('http://doc.openerp.com/trunk/developers/web', None), 'openerpdev': ('http://doc.openerp.com/trunk/developers', None), } diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py index e2a3391c8a4..5f2c0b915c1 100644 --- a/openerp/osv/expression.py +++ b/openerp/osv/expression.py @@ -22,102 +22,114 @@ """ Domain expression processing -The main duty of this module is to compile a domain expression into a SQL -query. A lot of things should be documented here, but as a first step in the -right direction, some tests in test_osv_expression.yml might give you some -additional information. +The main duty of this module is to compile a domain expression into a +SQL query. A lot of things should be documented here, but as a first +step in the right direction, some tests in test_osv_expression.yml +might give you some additional information. -For legacy reasons, a domain uses an inconsistent two-levels abstract syntax -(domains are regular Python data structures). At the first level, a domain -is an expression made of terms (sometimes called leaves) and (domain) operators -used in prefix notation. The available operators at this level are '!', '&', -and '|'. '!' is a unary 'not', '&' is a binary 'and', and '|' is a binary 'or'. -For instance, here is a possible domain. ( stands for an arbitrary term, -more on this later.) +For legacy reasons, a domain uses an inconsistent two-levels abstract +syntax (domains are regular Python data structures). At the first +level, a domain is an expression made of terms (sometimes called +leaves) and (domain) operators used in prefix notation. The available +operators at this level are '!', '&', and '|'. '!' is a unary 'not', +'&' is a binary 'and', and '|' is a binary 'or'. For instance, here +is a possible domain. ( stands for an arbitrary term, more on +this later.):: ['&', '!', , '|', , ] -It is equivalent to this pseudo code using infix notation: +It is equivalent to this pseudo code using infix notation:: (not ) and ( or ) -The second level of syntax deals with the term representation. A term is -a triple of the form (left, operator, right). That is, a term uses an infix -notation, and the available operators, and possible left and right operands -differ with those of the previous level. Here is a possible term: +The second level of syntax deals with the term representation. A term +is a triple of the form (left, operator, right). That is, a term uses +an infix notation, and the available operators, and possible left and +right operands differ with those of the previous level. Here is a +possible term:: ('company_id.name', '=', 'OpenERP') -The left and right operand don't have the same possible values. The left -operand is field name (related to the model for which the domain applies). -Actually, the field name can use the dot-notation to traverse relationships. -The right operand is a Python value whose type should match the used operator -and field type. In the above example, a string is used because the name field -of a company has type string, and because we use the '=' operator. When -appropriate, a 'in' operator can be used, and thus the right operand should be -a list. +The left and right operand don't have the same possible values. The +left operand is field name (related to the model for which the domain +applies). Actually, the field name can use the dot-notation to +traverse relationships. The right operand is a Python value whose +type should match the used operator and field type. In the above +example, a string is used because the name field of a company has type +string, and because we use the '=' operator. When appropriate, a 'in' +operator can be used, and thus the right operand should be a list. -Note: the non-uniform syntax could have been more uniform, but this would hide -an important limitation of the domain syntax. Say that the term representation -was ['=', 'company_id.name', 'OpenERP']. Used in a complete domain, this would -look like: +Note: the non-uniform syntax could have been more uniform, but this +would hide an important limitation of the domain syntax. Say that the +term representation was ['=', 'company_id.name', 'OpenERP']. Used in a +complete domain, this would look like:: - ['!', ['=', 'company_id.name', 'OpenERP']] + ['!', ['=', 'company_id.name', 'OpenERP']] -and you would be tempted to believe something like this would be possible: +and you would be tempted to believe something like this would be +possible:: - ['!', ['=', 'company_id.name', ['&', ..., ...]]] + ['!', ['=', 'company_id.name', ['&', ..., ...]]] -That is, a domain could be a valid operand. But this is not the case. A domain -is really limited to a two-level nature, and can not take a recursive form: a -domain is not a valid second-level operand. +That is, a domain could be a valid operand. But this is not the +case. A domain is really limited to a two-level nature, and can not +take a recursive form: a domain is not a valid second-level operand. Unaccent - Accent-insensitive search -OpenERP will use the SQL function 'unaccent' when available for the 'ilike' and -'not ilike' operators, and enabled in the configuration. -Normally the 'unaccent' function is obtained from the PostgreSQL 'unaccent' -contrib module[0]. +OpenERP will use the SQL function 'unaccent' when available for the +'ilike' and 'not ilike' operators, and enabled in the configuration. +Normally the 'unaccent' function is obtained from `the PostgreSQL +'unaccent' contrib module +`_. +.. todo: The following explanation should be moved in some external + installation guide -..todo: The following explanation should be moved in some external installation - guide +The steps to install the module might differ on specific PostgreSQL +versions. We give here some instruction for PostgreSQL 9.x on a +Ubuntu system. -The steps to install the module might differ on specific PostgreSQL versions. -We give here some instruction for PostgreSQL 9.x on a Ubuntu system. +Ubuntu doesn't come yet with PostgreSQL 9.x, so an alternative package +source is used. We use Martin Pitt's PPA available at +`ppa:pitti/postgresql +`_. -Ubuntu doesn't come yet with PostgreSQL 9.x, so an alternative package source -is used. We use Martin Pitt's PPA available at ppa:pitti/postgresql[1]. See -[2] for instructions. Basically: +.. code-block:: sh > sudo add-apt-repository ppa:pitti/postgresql > sudo apt-get update -Once the package list is up-to-date, you have to install PostgreSQL 9.0 and -its contrib modules. +Once the package list is up-to-date, you have to install PostgreSQL +9.0 and its contrib modules. + +.. code-block:: sh > sudo apt-get install postgresql-9.0 postgresql-contrib-9.0 When you want to enable unaccent on some database: +.. code-block:: sh + > psql9 -f /usr/share/postgresql/9.0/contrib/unaccent.sql -Here 'psql9' is an alias for the newly installed PostgreSQL 9.0 tool, together -with the correct port if necessary (for instance if PostgreSQL 8.4 is running -on 5432). (Other aliases can be used for createdb and dropdb.) +Here :program:`psql9` is an alias for the newly installed PostgreSQL +9.0 tool, together with the correct port if necessary (for instance if +PostgreSQL 8.4 is running on 5432). (Other aliases can be used for +createdb and dropdb.) + +.. code-block:: sh > alias psql9='/usr/lib/postgresql/9.0/bin/psql -p 5433' You can check unaccent is working: +.. code-block:: sh + > psql9 -c"select unaccent('hélène')" Finally, to instruct OpenERP to really use the unaccent function, you have to -start the server specifying the --unaccent flag. - -[0] http://developer.postgresql.org/pgdocs/postgres/unaccent.html -[1] https://launchpad.net/~pitti/+archive/postgresql -[2] https://launchpad.net/+help/soyuz/ppa-sources-list.html +start the server specifying the ``--unaccent`` flag. """ @@ -232,7 +244,7 @@ def is_leaf(element, internal=False): """ Test whether an object is a valid domain term. :param internal: allow or not the 'inselect' internal operator in the term. - This normally should be always left to False. + This normally should be always left to False. """ INTERNAL_OPS = TERM_OPERATORS + ('inselect',) return (isinstance(element, tuple) or isinstance(element, list)) \ diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 934b6eaf2e4..afabda817f4 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1218,7 +1218,11 @@ class BaseModel(object): return {'datas': datas} def import_data(self, cr, uid, fields, datas, mode='init', current_module='', noupdate=False, context=None, filename=None): - """Import given data in given module + """ + .. deprecated:: 7.0 + Use :meth:`~load` instead + + Import given data in given module This method is used when importing data via client menu. @@ -1302,6 +1306,10 @@ class BaseModel(object): ``False`` if there was an error and no id could be generated) and a list of messages. + The ids are those of the records created and saved (in database), in + the same order they were extracted from the file. They can be passed + directly to :meth:`~read` + Each message is a dictionary with the following keys: ``type`` @@ -5065,7 +5073,7 @@ class BaseModel(object): def is_transient(self): """ Return whether the model is transient. - See TransientModel. + See :class:`TransientModel`. """ return self._transient diff --git a/openerp/osv/query.py b/openerp/osv/query.py index 0b2bf47305a..252b301d531 100644 --- a/openerp/osv/query.py +++ b/openerp/osv/query.py @@ -73,15 +73,15 @@ class Query(object): :param connection: a tuple ``(lhs, table, lhs_col, col)``. The join corresponds to the SQL equivalent of:: - ``(lhs.lhs_col = table.col)`` + (lhs.lhs_col = table.col) :param outer: True if a LEFT OUTER JOIN should be used, if possible (no promotion to OUTER JOIN is supported in case the JOIN - was already present in the query, as for the moment - implicit INNER JOINs are only connected from NON-NULL - columns so it would not be correct (e.g. for - ``_inherits`` or when a domain criterion explicitly - adds filtering) + was already present in the query, as for the moment + implicit INNER JOINs are only connected from NON-NULL + columns so it would not be correct (e.g. for + ``_inherits`` or when a domain criterion explicitly + adds filtering) """ (lhs, table, lhs_col, col) = connection lhs = _quote(lhs) @@ -120,4 +120,4 @@ class Query(object): def __str__(self): return '' % self.get_sql() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 0f4529603c667f786f152859ad16e08ce9cc1fea Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 28 Sep 2012 10:52:59 +0200 Subject: [PATCH 072/409] [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 073/409] [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 879886decd0a64ac2e8d62bb9a6e409aa7f8abe8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 28 Sep 2012 11:15:19 +0200 Subject: [PATCH 074/409] [ADD] some import doc bzr revid: xmo@openerp.com-20120928091519-ksdprqdq0tpklggw --- doc/import.rst | 231 +++++++++++++++++++++++++++++++++++++++++++++ doc/index.rst.inc | 1 + doc/o2m.txt | 13 +++ openerp/osv/orm.py | 31 ------ 4 files changed, 245 insertions(+), 31 deletions(-) create mode 100644 doc/import.rst create mode 100644 doc/o2m.txt diff --git a/doc/import.rst b/doc/import.rst new file mode 100644 index 00000000000..f3db5d50bcf --- /dev/null +++ b/doc/import.rst @@ -0,0 +1,231 @@ +.. _bulk-import: + +Bulk Import +=========== + +OpenERP has included a bulk import facility for CSV-ish files for a +long time. With 7.0, both the interface and internal implementation +have been redone, resulting in +:meth:`~openerp.osv.orm.BaseModel.load`. + +.. note:: + + the previous bulk-loading method, + :meth:`~openerp.osv.orm.BaseModel.import_data`, remains for + backwards compatibility but was re-implemented on top of + :meth:`~openerp.osv.orm.BaseModel.load`, while its interface is + unchanged its precise behavior has likely been altered for some + cases (it shouldn't throw exceptions anymore in many cases where + it previously did) + +This document attempts to explain the behavior and limitations of +:meth:`~openerp.osv.orm.BaseModel.load`. + +Data +==== + +The input ``data`` is a regular row-major matrix of strings (in Python +datatype terms, a ``list`` of rows, each row being a ``list`` of +``str``, all rows must be of equal length). Each row must be the same +length as the ``fields`` list preceding it in the argslist. + +Each field of ``fields`` maps to a (potentially relational and nested) +field of the model under import, and the corresponding column of the +``data`` matrix provides a value for the field for each record. + +Generally speaking each row of the input yields a record of output, +and each cell of a row yields a value for the corresponding field of +the row's record. There is currently one exception for this rule: + +One to Many fields +------------------ + +Because O2M fields contain multiple records "embedded" in the main +one, and these sub-records are fully dependent on the main record (are +no other references to the sub-records in the system), they have to be +spliced into the matrix somehow. This is done by adding lines composed +*only* of o2m record fields below the main record: + +.. literalinclude:: o2m.txt + +the sections in double-lines represent the span of two o2m +fields. During parsing, they are extracted into their own ``data`` +matrix for the o2m field they correspond to. + +Import process +============== + +Here are the phases of import. Note that the concept of "phases" is +fuzzy as it's currently more of a pipeline, each record moves through +the entire pipeline before the next one is processed. + +Extraction +---------- + +The first phase of the import is the extraction of the current row +(and potentially a section of rows following it if it has One to Many +fields) into a record dictionary. The keys are the ``fields`` +originally passed to :meth:`~openerp.osv.orm.BaseModel.load`, and the +values are either the string value at the corresponding cell (for +non-relational fields) or a list of sub-records (for all relational +fields). + +This phase also generates the ``rows`` indexes for any +:ref:`import-message` produced thereafter. + +Conversion +---------- + +This second phase takes the record dicts, extracts the :ref:`dbid` and +:ref:`xid` if present and attempts to convert each field to a type +matching what OpenERP expects to write. Empty fields (empty strings) +are replaced with the ``False`` value, and non-empty fields are +converted through +:class:`~openerp.addons.base.ir.ir_fields.ir_fields_converter`: + +Char, text and binary fields +++++++++++++++++++++++++++++ + +Are returned as-is, without any alteration. + +Boolean fields +++++++++++++++ + +The string value is compared (in a case-insensitive manner) to ``0``, +``false`` and ``no`` as well of any translation thereof loaded in the +database. If the value matches one of these, the field is set to +``False``. + +Otherwise the field is compared to ``1``, ``true`` and ``yes`` (and +any translation of these in the database). The field is always set to +``True``, but if the value does not match one of these a warning will +also be output. + +Integers and float fields ++++++++++++++++++++++++++ + +The field is parsed with Python's built-in conversion routines +(``int`` and ``float`` respectively), if the conversion fails an error +is generated. + +Selection fields +++++++++++++++++ + +The field is compared to 1. the values of the selection (first part of +each selection tuple) and 2. all translations of the selection label +found in the database. + +If one of these is matched, the corresponding value is set on the +field. + +Otherwise an error is generated. + +The same process applies to both list-type and function-type selection +fields. + +Many to One field ++++++++++++++++++ + +If the specified field is the relational field itself (``m2o``), the +value is used in a ``name_search``. The first record returned by +``name_search`` is used as the field's value. + +If ``name_search`` finds no value, an error is generated. If +``name_search`` finds multiple value, a warning is generated to warn +the user of ``name_search`` collisions. + +If the specified field is a :ref:`xid` (``m2o/id``), the +corresponding record it looked up in the database and used as the +field's value. If no record is found matching the provided external +ID, an error is generated. + +If the specified field is a :ref:`dbid` (``m2o/.id``), the process is +the same as for external ids (on database identifiers instead of +external ones). + +Many to Many field +++++++++++++++++++ + +The field's value is interpreted as a comma-separated list of names, +external ids or database ids. For each one, the process previously +used for the many to one field is applied. + +One to Many field ++++++++++++++++++ + +For each o2m record extracted, if the record has a ``name``, +:ref:`xid` or :ref:`dbid` the :ref:`dbid` is looked up and checked +through the same process as for m2o fields. + +If a :ref:`dbid` was found, a LINK_TO command is emmitted, followed by +an UPDATE with the non-db values for the relational field. + +Otherwise a CREATE command is emmitted. + +Create/Write +------------ + +If the conversion was successful, the converted record is then saved +to the database via ``(ir.model.data)._update``. + +Error handling +-------------- + +The import process will only catch 2 types of exceptions to convert +them to error messages: ``ValueError`` during the conversion process, +and sub-exceptions of ``psycopg2.Error`` during the create/write +process. + +The import process uses savepoint to: + +* protect the overall transaction from the failure of each ``_update`` + call, if an ``_update`` call fails the savepoint is rolled back and + the import process keeps going in order to obtain as many error + messages as possible during each run. + +* protect the import as a whole, a savepoint is created before + starting and if any error is generated that savepoint is rolled + back. The rest of the transaction (anything not within the import + process) will be left untouched. + +.. _import-message: +.. _import-messages: + +Messages +======== + +A message is a dictionary with 5 mandatory keys and one optional key: + +``type`` + the type of message, either ``warning`` or ``error``. Any + ``error`` message indicates the import failed and was rolled back. + +``message`` + the message's actual text, which should be translated and can be + shown to the user directly + +``rows`` + a dict with 2 keys ``from`` and ``to``, indicates the range of + rows in ``data`` which generated the message + +``record`` + a single integer, for warnings the index of the record which + generated the message (can be obtained from a non-false ``ids`` + result) + +``field`` + the name of the (logical) OpenERP field for which the error or + warning was generated + +``moreinfo`` (optional) + A string, a list or a dict, leading to more information about the + warning. + + * If ``moreinfo`` is a string, it is a supplementary warnings + message which should be hidden by default + * If ``moreinfo`` is a list, it provides a number of possible or + alternative values for the string + * If ``moreinfo`` is a dict, it is an OpenERP action descriptor + which can be executed to get more information about the issues + with the field. If present, the ``help`` key serves as a label + for the action (e.g. the text of the link). diff --git a/doc/index.rst.inc b/doc/index.rst.inc index 6182f6251e9..842888aecb2 100644 --- a/doc/index.rst.inc +++ b/doc/index.rst.inc @@ -5,6 +5,7 @@ OpenERP Server .. toctree:: :maxdepth: 1 + import test-framework Changed in 7.0 diff --git a/doc/o2m.txt b/doc/o2m.txt new file mode 100644 index 00000000000..32218e5ac85 --- /dev/null +++ b/doc/o2m.txt @@ -0,0 +1,13 @@ ++-------+-------+===========+===========+-------+-------+ +|value01|value02‖o2m/value01|o2m/value02‖value03|value04| ++-------+-------+-----------+-----------+-------+-------+ +| | ‖o2m/value11|o2m/value12‖ | | ++-------+-------+-----------+-----------+-------+-------+ +| | ‖o2m/value21|o2m/value22‖ | | ++-------+-------+===========+===========+-------+-------+ +|value11|value12‖o2m/value01|o2m/value02‖value13|value14| ++-------+-------+-----------+-----------+-------+-------+ +| | ‖o2m/value11|o2m/value12‖ | | ++-------+-------+===========+===========+-------+-------+ +|value21|value22| | |value23|value24| ++-------+-------+-----------+-----------+-------+-------+ diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index afabda817f4..da0c93762bc 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1310,37 +1310,6 @@ class BaseModel(object): the same order they were extracted from the file. They can be passed directly to :meth:`~read` - Each message is a dictionary with the following keys: - - ``type`` - the type of message, either ``warning`` or ``error``. Any ``error`` - message indicates the import failed and was rolled back. - ``message`` - the message's actual text, which should be translated and can be - shown to the user directly - ``rows`` - a dict with 2 keys ``from`` and ``to``, indicates the range of rows - in ``data`` which generated the message - ``record`` - a single integer, for warnings the index of the record which - generated the message (can be obtained from a non-false ``ids`` - result) - ``field`` - the name of the (logical) OpenERP field for which the error or - warning was generated - ``moreinfo`` (optional) - A string, a list or a dict, leading to more information about the - warning. - - * If ``moreinfo`` is a string, it is a supplementary warnings - message which should be hidden by default - * If ``moreinfo`` is a list, it provides a number of possible or - alternative values for the string - * If ``moreinfo`` is a dict, it is an OpenERP action descriptor - which can be executed to get more information about the issues - with the field. If present, the ``help`` key serves as a label - for the action (e.g. the text of the link). - :param cr: cursor for the request :param int uid: ID of the user attempting the data import :param fields: list of fields to import, at the same index as the corresponding data From 722bb4461d4ca1d27099bed8293a5ca8d76e2b92 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 28 Sep 2012 11:43:55 +0200 Subject: [PATCH 075/409] [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 076/409] [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 077/409] [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 078/409] [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 112/409] [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 113/409] 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 114/409] [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 115/409] [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 116/409] [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 117/409] 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 118/409] [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 119/409] [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 122/409] [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 123/409] [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 124/409] [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 125/409] [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 126/409] [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 127/409] [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; + + + + + +
    +
    + +
    + dashed lines are asynchronous state transitions (3 seconds) +
    + + + + + + + + + + + diff --git a/addons/base_import/static/lib/javascript-state-machine/state-machine.js b/addons/base_import/static/lib/javascript-state-machine/state-machine.js new file mode 100644 index 00000000000..0d503ee7bdb --- /dev/null +++ b/addons/base_import/static/lib/javascript-state-machine/state-machine.js @@ -0,0 +1,155 @@ +(function (window) { + + StateMachine = { + + //--------------------------------------------------------------------------- + + VERSION: "2.1.0", + + //--------------------------------------------------------------------------- + + Result: { + SUCCEEDED: 1, // the event transitioned successfully from one state to another + NOTRANSITION: 2, // the event was successfull but no state transition was necessary + CANCELLED: 3, // the event was cancelled by the caller in a beforeEvent callback + ASYNC: 4, // the event is asynchronous and the caller is in control of when the transition occurs + }, + + Error: { + INVALID_TRANSITION: 100, // caller tried to fire an event that was innapropriate in the current state + PENDING_TRANSITION: 200, // caller tried to fire an event while an async transition was still pending + INVALID_CALLBACK: 300, // caller provided callback function threw an exception + }, + + WILDCARD: '*', + ASYNC: 'async', + + //--------------------------------------------------------------------------- + + create: function(cfg, target) { + + var initial = (typeof cfg.initial == 'string') ? { state: cfg.initial } : cfg.initial; // allow for a simple string, or an object with { state: 'foo', event: 'setup', defer: true|false } + var fsm = target || cfg.target || {}; + var events = cfg.events || []; + var callbacks = cfg.callbacks || {}; + var map = {}; + + var add = function(e) { + var from = (e.from instanceof Array) ? e.from : (e.from ? [e.from] : [StateMachine.WILDCARD]); // allow 'wildcard' transition if 'from' is not specified + map[e.name] = map[e.name] || {}; + for (var n = 0 ; n < from.length ; n++) + map[e.name][from[n]] = e.to || from[n]; // allow no-op transition if 'to' is not specified + }; + + if (initial) { + initial.event = initial.event || 'startup'; + add({ name: initial.event, from: 'none', to: initial.state }); + } + + for(var n = 0 ; n < events.length ; n++) + add(events[n]); + + for(var name in map) { + if (map.hasOwnProperty(name)) + fsm[name] = StateMachine.buildEvent(name, map[name]); + } + + for(var name in callbacks) { + if (callbacks.hasOwnProperty(name)) + fsm[name] = callbacks[name] + } + + fsm.current = 'none'; + fsm.is = function(state) { return this.current == state; }; + fsm.can = function(event) { return !this.transition && (map[event].hasOwnProperty(this.current) || map[event].hasOwnProperty(StateMachine.WILDCARD)); } + fsm.cannot = function(event) { return !this.can(event); }; + fsm.error = cfg.error || function(name, from, to, args, error, msg) { throw msg; }; // default behavior when something unexpected happens is to throw an exception, but caller can override this behavior if desired (see github issue #3) + + if (initial && !initial.defer) + fsm[initial.event](); + + return fsm; + + }, + + //=========================================================================== + + doCallback: function(fsm, func, name, from, to, args) { + if (func) { + try { + return func.apply(fsm, [name, from, to].concat(args)); + } + catch(e) { + return fsm.error(name, from, to, args, StateMachine.Error.INVALID_CALLBACK, "an exception occurred in a caller-provided callback function"); + } + } + }, + + beforeEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onbefore' + name], name, from, to, args); }, + afterEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onafter' + name] || fsm['on' + name], name, from, to, args); }, + leaveState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onleave' + from], name, from, to, args); }, + enterState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onenter' + to] || fsm['on' + to], name, from, to, args); }, + changeState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onchangestate'], name, from, to, args); }, + + + buildEvent: function(name, map) { + return function() { + + var from = this.current; + var to = map[from] || map[StateMachine.WILDCARD] || from; + var args = Array.prototype.slice.call(arguments); // turn arguments into pure array + + if (this.transition) + return this.error(name, from, to, args, StateMachine.Error.PENDING_TRANSITION, "event " + name + " inappropriate because previous transition did not complete"); + + if (this.cannot(name)) + return this.error(name, from, to, args, StateMachine.Error.INVALID_TRANSITION, "event " + name + " inappropriate in current state " + this.current); + + if (false === StateMachine.beforeEvent(this, name, from, to, args)) + return StateMachine.CANCELLED; + + if (from === to) { + StateMachine.afterEvent(this, name, from, to, args); + return StateMachine.NOTRANSITION; + } + + // prepare a transition method for use EITHER lower down, or by caller if they want an async transition (indicated by an ASYNC return value from leaveState) + var fsm = this; + this.transition = function() { + fsm.transition = null; // this method should only ever be called once + fsm.current = to; + StateMachine.enterState( fsm, name, from, to, args); + StateMachine.changeState(fsm, name, from, to, args); + StateMachine.afterEvent( fsm, name, from, to, args); + }; + + var leave = StateMachine.leaveState(this, name, from, to, args); + if (false === leave) { + this.transition = null; + return StateMachine.CANCELLED; + } + else if ("async" === leave) { + return StateMachine.ASYNC; + } + else { + if (this.transition) + this.transition(); // in case user manually called transition() but forgot to return ASYNC + return StateMachine.SUCCEEDED; + } + + }; + } + + }; // StateMachine + + //=========================================================================== + + if ("function" === typeof define) { + define("statemachine", [], function() { return StateMachine; }); + } + else { + window.StateMachine = StateMachine; + } + +}(this)); + diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index 4135f303513..19d4e466cc7 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -71,14 +71,8 @@ openerp.base_import = function (instance) { ], events: { // 'change .oe_import_grid input': 'import_dryrun', - 'change input.oe_import_file': 'file_update', - 'change input.oe_import_has_header, .oe_import_options input': 'settings_updated', - 'click a.oe_import_csv': function (e) { - e.preventDefault(); - }, - 'click a.oe_import_export': function (e) { - e.preventDefault(); - }, + 'change input.oe_import_file': 'loaded_file', + 'change input.oe_import_has_header, .oe_import_options input': 'settings_changed', 'click a.oe_import_toggle': function (e) { e.preventDefault(); var $el = $(e.target); @@ -109,14 +103,15 @@ openerp.base_import = function (instance) { this.do_action(_.extend(action, {target: 'new'})); }, // buttons - 'click .oe_import_validate': 'import_dryrun', - 'click .oe_import_import': 'do_import', + 'click .oe_import_validate': 'validate', + 'click .oe_import_import': 'import', 'click .oe_import_cancel': function (e) { e.preventDefault(); this.exit(); } }, init: function (parent, params) { + var self = this; this._super.apply(this, arguments); this.res_model = params.model; // import object id @@ -150,42 +145,48 @@ openerp.base_import = function (instance) { }, //- File & settings change section - file_update: function (e) { + onfile_loaded: function () { this.$('.oe_import_button').prop('disabled', true); if (!this.$('input.oe_import_file').val()) { return; } this.$el.removeClass('oe_import_preview oe_import_error'); jsonp(this.$el, { url: '/base_import/set_file' - }, this.proxy('settings_updated')); + }, this.proxy('settings_changed')); }, - settings_updated: function () { + onpreviewing: function () { + var self = this; + this.$('.oe_import_button').prop('disabled', true); this.$el.addClass('oe_import_with_file'); // TODO: test that write // succeeded? - this.Import.call( - 'parse_preview', [this.id, this.import_options()]) - .then(this.proxy('preview')); - }, - preview: function (result) { this.$el.removeClass('oe_import_preview_error oe_import_error'); this.$el.toggleClass( 'oe_import_noheaders', !this.$('input.oe_import_has_header').prop('checked')); - if (result.error) { - this.$('.oe_import_options').show(); - this.$el.addClass('oe_import_preview_error oe_import_error'); - this.$('.oe_import_error_report').html( - QWeb.render('ImportView.preview.error', result)) - .get(0).scrollIntoView(); - return; - } + this.Import.call( + 'parse_preview', [this.id, this.import_options()]) + .then(function (result) { + var signal = result.error ? 'preview_failed' : 'preview_succeeded'; + self[signal](result); + }); + }, + onpreview_error: function (event, from, to, result) { + this.$('.oe_import_options').show(); + this.$el.addClass('oe_import_preview_error oe_import_error'); + this.$('.oe_import_error_report').html( + QWeb.render('ImportView.preview.error', result)) + .get(0).scrollIntoView(); + }, + onpreview_success: function (event, from, to, result) { + this.$('.oe_import_import').removeClass('oe_highlight'); + this.$('.oe_import_validate').addClass('oe_highlight'); this.$('.oe_import_button').prop('disabled', false); this.$el.addClass('oe_import_preview'); this.$('table').html(QWeb.render('ImportView.preview', result)); if (result.headers.length === 1) { this.$('.oe_import_options').show(); - this.render_import_result([{ + this.onresults(null, null, null, [{ type: 'warning', message: _t("A single column was found in the file, this often means the file separator is incorrect") }]); @@ -225,7 +226,6 @@ openerp.base_import = function (instance) { width: 'resolve', dropdownCssClass: 'oe_import_selector' }); - //this.import_dryrun(); }, generate_fields_completion: function (root) { var basic = []; @@ -303,28 +303,31 @@ openerp.base_import = function (instance) { return this.Import.call( 'do', [this.id, fields, this.import_options()], options); }, - import_dryrun: function () { + onvalidate: function () { return this.call_import({ dryrun: true }) - .then(this.proxy('render_import_result')); + .then(this.proxy('validated')); }, - do_import: function () { + onimport: function () { var self = this; return this.call_import({ dryrun: false }).then(function (message) { if (!_.any(message, function (message) { return message.type === 'error' })) { - self.exit(); + self['import_succeeded'](); return; } - self.render_import_result(message); + self['import_failed'](message); }); }, + onimported: function () { + this.exit(); + }, exit: function () { this.do_action({ type: 'ir.actions.client', tag: 'history_back' }); }, - render_import_result: function (message) { + onresults: function (event, from, to, message) { var no_messages = _.isEmpty(message); this.$('.oe_import_import').toggleClass('oe_highlight', no_messages); this.$('.oe_import_validate').toggleClass('oe_highlight', !no_messages); @@ -386,4 +389,23 @@ openerp.base_import = function (instance) { })).get(0).scrollIntoView(); }, }); + // FSM-ize DataImport + StateMachine.create({ + target: instance.web.DataImport.prototype, + events: [ + { name: 'loaded_file', + from: ['none', 'file_loaded', 'preview_error', 'preview_success', 'results'], + to: 'file_loaded' }, + { name: 'settings_changed', + from: ['file_loaded', 'preview_error', 'preview_success', 'results'], + to: 'previewing' }, + { name: 'preview_failed', from: 'previewing', to: 'preview_error' }, + { name: 'preview_succeeded', from: 'previewing', to: 'preview_success' }, + { name: 'validate', from: 'preview_success', to: 'validating' }, + { name: 'validated', from: 'validating', to: 'results' }, + { name: 'import', from: ['preview_success', 'results'], to: 'importing' }, + { name: 'import_succeeded', from: 'importing', to: 'imported'}, + { name: 'import_failed', from: 'importing', to: 'results' } + ] + }) }; From a09b2fdff1586b7cc51053eabc5b3b9f6cc9a8bc Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 3 Oct 2012 17:21:21 +0200 Subject: [PATCH 187/409] [REM] cleanup leftover debug logging bzr revid: odo@openerp.com-20121003152121-yeg4vhph4cy7xgpp --- addons/web/controllers/main.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 7e7282eb231..356e2960346 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -709,7 +709,6 @@ class WebClient(openerpweb.Controller): # Regional languages (ll_CC) must inherit/override their parent lang (ll), but this is # done server-side when the language is loaded, so we only need to load the user's lang. - start = datetime.datetime.now() ir_translation = req.session.model('ir.translation') translations_per_module = {} messages = ir_translation.search_read([('module','in',mods),('lang','=',lang), @@ -721,11 +720,6 @@ class WebClient(openerpweb.Controller): translations_per_module[mod]['messages'].extend({'id': m['src'], 'string': m['value']} \ for m in msg_group) - - print "Loaded translations in ", datetime.datetime.now()-start - import pprint - pprint.pprint(translations_per_module) - return {"modules": translations_per_module, "lang_parameters": lang_params} From 9c9d9781093cf35bb5abec0d605a02bbd9b3f108 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 3 Oct 2012 17:24:44 +0200 Subject: [PATCH 188/409] [IMP] relational field 'more values' dialog list features force display of pager and search view, make list non-selectable bzr revid: xmo@openerp.com-20121003152444-phnn9sc9nqo1ecpn --- addons/base_import/static/src/js/import.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index 19d4e466cc7..2867242749c 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -100,7 +100,15 @@ openerp.base_import = function (instance) { : 'tree' ]; }); - this.do_action(_.extend(action, {target: 'new'})); + this.do_action(_.extend(action, { + target: 'new', + flags: { + search_view: true, + display_title: true, + pager: true, + list: {selectable: false} + } + })); }, // buttons 'click .oe_import_validate': 'validate', From 3744f5c402b05edf50bd4562d0daedbc7cbc08e1 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 3 Oct 2012 17:33:06 +0200 Subject: [PATCH 189/409] [REV] Revert last commit, breaks tests bzr revid: odo@openerp.com-20121003153306-e2ugphdyijvq8x6l --- addons/mail/mail_message.py | 184 ++++++++++++-------- addons/mail/mail_message_view.xml | 11 +- addons/mail/mail_thread.py | 8 +- addons/mail/mail_thread_view.xml | 10 +- addons/mail/static/src/css/mail.css | 2 +- addons/mail/static/src/js/mail.js | 37 ++-- addons/mail/static/src/js/mail_followers.js | 5 +- addons/mail/static/src/xml/mail.xml | 9 +- addons/mail/tests/test_mail.py | 42 +++++ addons/mail/wizard/mail_compose_message.py | 1 + 10 files changed, 195 insertions(+), 114 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index eeefd730f22..bbf68509277 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -134,7 +134,6 @@ class mail_message(osv.Model): 'subtype_id': fields.many2one('mail.message.subtype', 'Subtype'), 'vote_user_ids': fields.many2many('res.users', 'mail_vote', 'message_id', 'user_id', string='Votes', help='Users that voted for this message'), - 'is_private': fields.boolean('Private message'), } def _needaction_domain_get(self, cr, uid, context=None): @@ -222,67 +221,70 @@ class mail_message(osv.Model): 'unread': msg.unread and msg.unread['unread'] or False } - def _message_read_expandable(self, cr, uid, tree, result, message_loaded, domain, context, parent_id, limit): - """ - create the expandable message for all parent message read - this function is used by message_read + def message_read_tree_get_expandable(self, cr, uid, parent_message, last_message, domain=[], current_level=0, level=0, context=None): + """ . """ + base_domain = [('id', '<', last_message['id'])] + if parent_message and current_level < level: + base_domain += [('parent_id', '=', parent_message['id'])] + elif parent_message: + base_domain += [('id', 'child_of', parent_message['id']), ('id', '!=', parent_message['id'])] + if domain: + base_domain += domain + extension = { 'type': 'expandable', + 'domain': base_domain, + 'thread_level': current_level, + 'context': context, + 'id': -1, + } + return extension + + def message_read_tree_flatten(self, cr, uid, parent_message, messages, domain=[], level=0, current_level=0, context=None, limit=None, add_expandable=True): + """ Given a tree with several roots of following structure : + [ {'id': 1, 'child_ids': [ + {'id': 11, 'child_ids': [...] },], + {...} ] + Flatten it to have a maximum number of levels, 0 being flat and + sort messages in a level according to a key of the messages. + Perform the flattening at leafs if above the maximum depth, then get + back in the tree. + :param context: ``sort_key``: key for sorting (id by default) + :param context: ``sort_reverse``: reverser order for sorting (True by default) """ + def _flatten(msg_dict): + """ from {'id': x, 'child_ids': [{child1}, {child2}]} + get [{'id': x, 'child_ids': []}, {child1}, {child2}] + """ + child_ids = msg_dict.pop('child_ids', []) + msg_dict['child_ids'] = [] + return [msg_dict] + child_ids - tree_not = [] - # expandable for not show message - for id_msg in tree: - # get all childs - not_loaded_ids = self.search(cr, SUPERUSER_ID, [['parent_id','=',id_msg],['id','not in',message_loaded]], None, limit=1000) - # group childs not read - id_min=None - id_max=None - nb=0 - for not_loaded_id in not_loaded_ids: - if not_loaded_id not in tree: - nb+=1 - if id_min==None or id_min>not_loaded_id: - id_min=not_loaded_id - if id_max==None or id_max0: - result.append({ - 'domain': [['id','>=',id_min],['id','<=',id_max],['parent_id','=',id_msg]], - 'nb_messages': nb, - 'type': 'expandable', - 'parent_id': id_msg, - 'id': id_min - }) - id_min=None - id_max=None - nb=0 - if nb>0: - result.append({ - 'domain': [['id','>=',id_min],['id','<=',id_max],['parent_id','=',id_msg]], - 'nb_messages': nb, - 'type': 'expandable', - 'parent_id': id_msg, - 'id': id_min - }) + context = context or {} + limit = limit or self._message_read_limit + # Depth-first flattening + for message in messages: + if message.get('type') == 'expandable': + continue + message['child_ids'] = self.message_read_tree_flatten(cr, uid, message, message['child_ids'], domain, level, current_level + 1, context=context, limit=limit) + for child in message['child_ids']: + if child.get('type') == 'expandable': + continue + message['child_nbr'] += child['child_nbr'] + # Flatten if above maximum depth + if current_level < level: + return_list = messages + else: + return_list = [flat_message for message in messages for flat_message in _flatten(message)] - # expandable for limit max - ids = self.search(cr, SUPERUSER_ID, domain+[['id','not in',message_loaded+tree+tree_not]], context=context, limit=1) - if len(ids) > 0: - result.append( - { - 'domain': domain, - 'nb_messages': 0, - 'type': 'expandable', - 'parent_id': parent_id, - 'id': -1 - }); - - - result = sorted(result, key=lambda k: k['id']) - - return result + # Add expandable + return_list = sorted(return_list, key=itemgetter(context.get('sort_key', 'id')), reverse=context.get('sort_reverse', True)) + if return_list and current_level == 0 and add_expandable: + expandable = self.message_read_tree_get_expandable(cr, uid, parent_message, return_list and return_list[-1] or parent_message, domain, current_level, level, context=context) + return_list.append(expandable) + elif return_list and current_level <= level and add_expandable: + expandable = self.message_read_tree_get_expandable(cr, uid, parent_message, return_list and return_list[-1] or parent_message, domain, current_level, level, context=context) + return_list.append(expandable) + return return_list def message_read(self, cr, uid, ids=False, domain=[], level=0, context=None, parent_id=False, limit=None): """ Read messages from mail.message, and get back a structured tree @@ -298,6 +300,7 @@ class mail_message(osv.Model): further parents :return list: list of trees of messages """ + message_loaded = context and context.get('message_loaded') or [0] # don't read the message display by .js, in context message_loaded list @@ -338,7 +341,58 @@ class mail_message(osv.Model): result = sorted(result, key=lambda k: k['id']) - result = self._message_read_expandable(cr, uid, tree, result, message_loaded, domain, context, parent_id, limit) + + tree_not = [] + # expandable for not show message + for id_msg in tree: + # get all childs + not_loaded_ids = self.search(cr, SUPERUSER_ID, [['parent_id','=',id_msg],['id','not in',message_loaded]], None, limit=1000) + # group childs not read + id_min=None + id_max=None + nb=0 + for not_loaded_id in not_loaded_ids: + if not_loaded_id not in tree: + nb+=1 + if id_min==None or id_min>not_loaded_id: + id_min=not_loaded_id + if id_max==None or id_max0: + result.append({ + 'domain': [['id','>=',id_min],['id','<=',id_max],['parent_id','=',id_msg]], + 'nb_messages': nb, + 'type': 'expandable', + 'parent_id': id_msg, + 'id': id_min + }) + nb=0 + if nb>0: + result.append({ + 'domain': [['id','>=',id_min],['parent_id','=',id_msg]], + 'nb_messages': nb, + 'type': 'expandable', + 'parent_id': id_msg, + 'id': id_min + }) + + + # expandable for limit max + ids = self.search(cr, SUPERUSER_ID, domain+[['id','not in',message_loaded+tree+tree_not]], context=context, limit=1) + if len(ids) > 0: + result.append( + { + 'domain': domain, + 'nb_messages': 0, + 'type': 'expandable', + 'parent_id': parent_id, + 'id': -1 + }); + + + result = sorted(result, key=lambda k: k['id']) return result @@ -472,9 +526,11 @@ class mail_message(osv.Model): self.pool.get('ir.attachment').unlink(cr, uid, attachments_to_delete, context=context) return super(mail_message, self).unlink(cr, uid, ids, context=context) - def _notify_followers(self, cr, uid, newid, message, context=None): + def _notify(self, cr, uid, newid, context=None): """ Add the related record followers to the destination partner_ids. + Call mail_notification.notify to manage the email sending """ + message = self.browse(cr, uid, newid, context=context) partners_to_notify = set([]) # message has no subtype_id: pure log message -> no partners, no one notified if not message.subtype_id: @@ -502,14 +558,6 @@ class mail_message(osv.Model): else: self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(3, message.author_id.id)]}, context=context) - def _notify(self, cr, uid, newid, context=None): - """ Add the related record followers to the destination partner_ids if is not a private message. - Call mail_notification.notify to manage the email sending - """ - message = self.browse(cr, uid, newid, context=context) - if message and (message.is_private!=False and message.is_private!=None): - self._notify_followers(cr, uid, newid, message, context=context) - self.pool.get('mail.notification')._notify(cr, uid, newid, context=context) def copy(self, cr, uid, id, default=None, context=None): diff --git a/addons/mail/mail_message_view.xml b/addons/mail/mail_message_view.xml index 6d854d4d701..cc0419352af 100644 --- a/addons/mail/mail_message_view.xml +++ b/addons/mail/mail_message_view.xml @@ -87,15 +87,8 @@ Inbox mail.wall - - - - - Wall - mail.wall - + diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 42b66a53fe5..9f53b4c08b1 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -627,6 +627,7 @@ class mail_thread(osv.AbstractModel): ``(name,content)``, where content is NOT base64 encoded :return: ID of newly created mail.message """ + context = context or {} attachments = attachments or [] assert (not thread_id) or isinstance(thread_id, (int, long)) or \ @@ -678,13 +679,6 @@ class mail_thread(osv.AbstractModel): 'attachment_ids': attachment_ids, 'subtype_id': subtype_id, }) - - # if the parent is private, the message must be private - if parent_id: - msg = messages.browse(cr, uid, parent_id, context=context) - if msg.is_private: - values["is_private"] = msg.is_private - # Avoid warnings about non-existing fields for x in ('from', 'to', 'cc'): values.pop(x, None) diff --git a/addons/mail/mail_thread_view.xml b/addons/mail/mail_thread_view.xml index 4b6709dd2d8..3507e7c449f 100644 --- a/addons/mail/mail_thread_view.xml +++ b/addons/mail/mail_thread_view.xml @@ -18,21 +18,15 @@ - - Wall - - - - Archives - + Sent - + diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 4ffb9013496..364ac7e3165 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -370,7 +370,7 @@ bottom: 0px; top: auto; left: auto; - right: 0; + right: 28px; height: 26px; width: 26px; min-width: 22px; diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 8915f1387e1..e0c9ac9b7fc 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -148,8 +148,8 @@ openerp.mail = function(session) { // handle attachment button this.fileupload_id = _.uniqueId('oe_fileupload'); var button_attach = this.$('button.oe_mail_compose_message_attachment'); - var rendered = $( session.web.qweb.render('mail.compose_message.add_attachment', {'widget': this}) ); - rendered.insertBefore(button_attach); + var rendered = session.web.qweb.render('mail.compose_message.add_attachment', {'widget': this}); + $(rendered).insertBefore(button_attach); // move the button inside div.oe_hidden_input_file var input_node = this.$('input[name=ufile]'); button_attach.detach().insertAfter(input_node); @@ -256,10 +256,10 @@ openerp.mail = function(session) { default_res_id: 0, default_parent_id: false }, options.context || {}); - this.id = options.parameters.id || -1; + this.id = -1; this.parent_id= options.parameters.parent_id || false; this.nb_messages = options.parameters.nb_messages || 0; - this.type = 'expandable'; + this.type = options.parameters.type || false; // record options and data this.parent_thread= parent.messages!= undefined ? parent : options.options.thread._parents[0] ; @@ -501,6 +501,9 @@ openerp.mail = function(session) { } else { self.destroy(); } + for(var i in this.thread.messages){ + this.thread.messages[i].animated_destroy({fadeTime:0}); + } }, on_message_delete: function (event) { @@ -595,8 +598,8 @@ openerp.mail = function(session) { display_vote: function () { var self = this; var vote_element = session.web.qweb.render('mail.thread.message.vote', {'widget': self}); - self.$(".placeholder-mail-vote:first").empty(); - self.$(".placeholder-mail-vote:first").html(vote_element); + self.$(".placeholder-mail-vote").empty(); + self.$(".placeholder-mail-vote").html(vote_element); }, }); @@ -876,7 +879,7 @@ openerp.mail = function(session) { fetch_domain = replace_domain ? replace_domain : this.domain; fetch_context = replace_context ? replace_context : this.context; fetch_context.message_loaded= [this.id||0].concat( self.options.thread._parents[0].get_child_ids() ); - + return this.ds_message.call('message_read', [ids, fetch_domain, (this.options.thread.thread_level+1), fetch_context, this.context.default_parent_id || undefined] ).then(this.proxy('switch_new_message')); }, @@ -942,11 +945,11 @@ openerp.mail = function(session) { } } - if(parent_older) - message.insertBefore(parent_older.$el); - else if(parent_newer) + if(parent_newer) message.insertAfter(parent_newer.$el); - else + else if(parent_older) + message.insertBefore(parent_older.$el); + else message.prependTo(thread.list_ul); return message @@ -1095,7 +1098,6 @@ openerp.mail = function(session) { this._super.apply(this, arguments); var searchview_ready = this.load_searchview({}, false); var thread_displayed = this.message_render(); - this.options.domain = this.options.domain.concat(this.search_results['domain']); return (searchview_ready && thread_displayed); }, @@ -1135,14 +1137,19 @@ openerp.mail = function(session) { /** Clean and display the threads */ message_render: function (search) { + var domain = this.options.domain.concat(this.search_results['domain']); + + var domain = _.extend(this.options.domain, search&&search.domain? search.domain : {}); + var context = _.extend(this.options.context, search&&search.context ? search.context : {}); + this.thread = new mail.Thread(this, { - 'domain' : this.options.domain.concat(this.search_results['domain']), - 'context' : _.extend(this.options.context, search&&search.search_results['context'] ? search.search_results['context'] : {}), + 'domain' : domain, + 'context' : context, 'options': { 'thread' :{ 'thread_level': this.options.thread_level, 'use_composer': true, - 'show_header_compose': 1, + 'show_header_compose': 1, }, 'message': { 'show_reply': this.options.thread_level > 0, diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index ab6a63ea6fa..953b8cd9fc8 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -149,6 +149,7 @@ 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 -
  • +
  • @@ -170,7 +171,7 @@
  • -
  • +
  • Load more messages ( messages not display)... diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py index 1485c40570b..7ec37d952bc 100644 --- a/addons/mail/tests/test_mail.py +++ b/addons/mail/tests/test_mail.py @@ -550,6 +550,48 @@ class test_mail(TestMailMockups): # _compare_structures(struct1[x]['child_ids'], struct2[x]['child_ids'], n + 1) # # print '%send compare' % ('\t' * n) + # # ---------------------------------------- + # # CASE1: Flattening test + # # ---------------------------------------- + + # # Create dummy message structure + # import copy + # tree = [{'id': 2, 'child_nbr': 1, 'child_ids': [ + # {'id': 6, 'child_nbr': 1, 'child_ids': [ + # {'id': 8, 'child_nbr': 0, 'child_ids': []}, + # ]}, + # ]}, + # {'id': 1, 'child_nbr': 3, 'child_ids':[ + # {'id': 7, 'child_nbr': 1, 'child_ids': [ + # {'id': 9, 'child_nbr': 0, 'child_ids': []}, + # ]}, + # {'id': 4, 'child_nbr': 2, 'child_ids': [ + # {'id': 10, 'child_nbr': 0, 'child_ids': []}, + # {'id': 5, 'child_nbr': 0, 'child_ids': []}, + # ]}, + # {'id': 3, 'child_nbr': 0, 'child_ids': []}, + # ]}, + # ] + # # Test: completely flat + # new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 0, limit=15, add_expandable=False) + # _compare_structures(new_tree, new_tree) + # self.assertEqual(len(new_tree), 10, 'message_read_tree_flatten wrong in flat') + # # Test: 1 thread level + # tree_test = [{'id': 2, 'child_ids': [ + # {'id': 8, 'child_ids': []}, {'id': 6, 'child_ids': []}, + # ]}, + # {'id': 1, 'child_ids': [ + # {'id': 10, 'child_ids': []}, {'id': 9, 'child_ids': []}, + # {'id': 7, 'child_ids': []}, {'id': 5, 'child_ids': []}, + # {'id': 4, 'child_ids': []}, {'id': 3, 'child_ids': []}, + # ]}, + # ] + # new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 1, limit=15, add_expandable=False) + # _compare_structures(new_tree, tree_test) + # # Test: 2 thread levels + # new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 2, limit=15, add_expandable=False) + # _compare_structures(new_tree, tree) + # # ---------------------------------------- # # CASE2: message_read test # # ---------------------------------------- diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index b7c51a20125..fbadf76f2fb 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -219,6 +219,7 @@ class mail_compose_message(osv.TransientModel): email(s), rendering any template patterns on the fly if needed. """ if context is None: context = {} + print '**', context active_ids = context.get('active_ids') for wizard in self.browse(cr, uid, ids, context=context): From a3d648f319d29f244f2b8026c031a6b4e70a0398 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 3 Oct 2012 17:58:20 +0200 Subject: [PATCH 190/409] [FIX] account_voucher: fix amount_currency on writeoff line + fixed/improved yaml tests bzr revid: qdp-launchpad@openerp.com-20121003155820-7ozaoklt042b7i6i --- addons/account_voucher/account_voucher.py | 4 +++- addons/account_voucher/test/case1_usd_usd.yml | 14 +++++++++++++- addons/account_voucher/test/case4_cad_chf.yml | 4 ++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 36aa8660bc4..8bb8fe4d9b3 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -667,6 +667,7 @@ class account_voucher(osv.osv): #voucher line creation for line in account_move_lines: + if _remove_noise_in_o2m(): continue @@ -1183,6 +1184,7 @@ class account_voucher(osv.osv): account_id = voucher_brw.partner_id.property_account_receivable.id else: account_id = voucher_brw.partner_id.property_account_payable.id + sign = voucher_brw.type == 'payment' and -1 or 1 move_line = { 'name': write_off_name or name, 'account_id': account_id, @@ -1191,7 +1193,7 @@ class account_voucher(osv.osv): 'date': voucher_brw.date, 'credit': diff > 0 and diff or 0.0, 'debit': diff < 0 and -diff or 0.0, - 'amount_currency': company_currency <> current_currency and voucher_brw.writeoff_amount or False, + 'amount_currency': company_currency <> current_currency and (sign * -1 * voucher_brw.writeoff_amount) or False, 'currency_id': company_currency <> current_currency and current_currency or False, 'analytic_account_id': voucher_brw.analytic_id and voucher_brw.analytic_id.id or False, } diff --git a/addons/account_voucher/test/case1_usd_usd.yml b/addons/account_voucher/test/case1_usd_usd.yml index b706e6f0644..300d565f229 100644 --- a/addons/account_voucher/test/case1_usd_usd.yml +++ b/addons/account_voucher/test/case1_usd_usd.yml @@ -216,6 +216,10 @@ assert move_line.credit == 63.00, "Debtor account has wrong entry." elif move_line.amount_currency == 10.00: assert move_line.debit == 9.00, "Writeoff amount is wrong." + elif move_line.amount_currency == 240.00: + assert move_line.debit == 216.00, "Bank entry is wrong." + else: + assert False, "Unrecognized journal entry" - I check the residual amount of Invoice1, should be 20 in amount_currency - @@ -237,7 +241,7 @@ - On the first April, I create the second voucher of payment with values 45 USD, journal USD, - - !record {model: account.voucher, id: account_voucher_2_case1}: + !record {model: account.voucher, id: account_voucher_2_case1, view: view_vendor_receipt_form}: account_id: account.cash amount: 45.0 company_id: base.main_company @@ -323,8 +327,16 @@ assert move_line.debit == 4.75, "Writeoff amount is wrong." elif move_line.debit == 11.5 and move_line.account_id.reconcile: assert move_line.amount_currency == 0.0 and move_line.reconcile_id.id == reconcile_a, "Exchange difference entry for the invoice of 100$ is wrong" + elif move_line.credit == 11.5: + assert move_line.amount_currency == 0.0 elif move_line.debit == 31.0 and move_line.account_id.reconcile: assert move_line.amount_currency == 0.0 and move_line.reconcile_id.id == reconcile_b, "Exchange difference entry for the invoice of 200$ is wrong" + elif move_line.credit == 31.0: + assert move_line.amount_currency == 0.0 + elif move_line.amount_currency == 45.00: + assert move_line.debit == 42.75, "Bank entry is wrong." + else: + assert False, "Unrecognized journal entry" - I check the residual amount of Invoice1, should be 0 in residual currency and 0 in amount_residual and paid - diff --git a/addons/account_voucher/test/case4_cad_chf.yml b/addons/account_voucher/test/case4_cad_chf.yml index a78669c95ef..a2b252497cd 100644 --- a/addons/account_voucher/test/case4_cad_chf.yml +++ b/addons/account_voucher/test/case4_cad_chf.yml @@ -164,7 +164,7 @@ - I check that my currency rate difference is correct. 0 in debit with no amount_currency - - I check that my writeoff is correct. 11.05 credit and 13.26 amount_currency + I check that my writeoff is correct. 11.05 credit and -13.26 amount_currency - !python {model: account.voucher}: | voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 4'), ('partner_id', '=', ref('base.res_partner_19'))]) @@ -179,7 +179,7 @@ elif move_line.debit == 0.00 and move_line.credit == 0.00: assert move_line.amount_currency == 0.00, "Incorrect Currency Difference." elif move_line.credit == 10.61: - assert move_line.amount_currency == 13.26, "Writeoff amount is wrong." + assert move_line.amount_currency == -13.26, "Writeoff amount is wrong." else: assert False, "Wrong entry" - From d2f3bbf4bc77a64deaaf6d3a4e4a381f32bd776a Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 3 Oct 2012 18:16:41 +0200 Subject: [PATCH 191/409] [REV] Undo header template extraction bzr revid: odo@openerp.com-20121003161641-9zodo9ks2bqjjjfd --- openerp/addons/base/ir/ir.xml | 44 +++++++++---------- .../base/module/wizard/base_module_upgrade.py | 4 +- openerp/addons/base/res/res_widget_view.xml | 4 +- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/openerp/addons/base/ir/ir.xml b/openerp/addons/base/ir/ir.xml index 2f25f24c394..3189870aa68 100644 --- a/openerp/addons/base/ir/ir.xml +++ b/openerp/addons/base/ir/ir.xml @@ -1170,9 +1170,9 @@ ir.translation
    - +
    - +
    @@ -1733,30 +1733,26 @@ Config Wizard Steps - +
    + + + + + + + + + +
    diff --git a/openerp/addons/base/module/wizard/base_module_upgrade.py b/openerp/addons/base/module/wizard/base_module_upgrade.py index 98ea0ac0482..04b7e785e48 100644 --- a/openerp/addons/base/module/wizard/base_module_upgrade.py +++ b/openerp/addons/base/module/wizard/base_module_upgrade.py @@ -47,10 +47,10 @@ class base_module_upgrade(osv.osv_memory): ids = self.get_module_list(cr, uid, context=context) if not ids: res['arch'] = '''
    - +
    ''' diff --git a/openerp/addons/base/res/res_widget_view.xml b/openerp/addons/base/res/res_widget_view.xml index 764f319de7b..bad582f97db 100644 --- a/openerp/addons/base/res/res_widget_view.xml +++ b/openerp/addons/base/res/res_widget_view.xml @@ -82,11 +82,11 @@ res.widget.wizard
    - +
    From 2514a564513918231a43785bfc48df753d16d700 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 3 Oct 2012 18:35:04 +0200 Subject: [PATCH 192/409] [FIX] coresetup: avoid losing whitespace after qweb translations bzr revid: odo@openerp.com-20121003163504-64piei7sjv0b41wx --- addons/web/static/src/js/coresetup.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/addons/web/static/src/js/coresetup.js b/addons/web/static/src/js/coresetup.js index 4a30a312b7a..d55408ebc83 100644 --- a/addons/web/static/src/js/coresetup.js +++ b/addons/web/static/src/js/coresetup.js @@ -542,13 +542,9 @@ instance.web.qweb.preprocess_node = function() { if (translation && translation.value === 'off') { return; } - var ts = _.str.trim(this.node.data); - if (ts.length === 0) { - return; - } - var tr = instance.web._t(ts); - if (tr !== ts) { - this.node.data = tr; + var match = /^(\s*)(.+?)(\s*)$/.exec(this.node.data); + if (match) { + this.node.data = match[1] + instance.web._t(match[2]) + match[3]; } break; case 1: From 3c26ec305a6aa003a6d764048a82bd39a16e5792 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse <> Date: Thu, 4 Oct 2012 06:46:24 +0200 Subject: [PATCH 193/409] [IMP] mail: move the code from publisher_warranty to mail bzr revid: stw@openerp.com-20121004044624-hwa3kztl58zrjguh --- addons/mail/__init__.py | 1 + addons/mail/data/mail_data.xml | 14 +++++ addons/mail/mail_message.py | 2 +- addons/mail/update.py | 112 +++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 addons/mail/update.py diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py index 92e882ae6d8..abf714ad534 100644 --- a/addons/mail/__init__.py +++ b/addons/mail/__init__.py @@ -33,6 +33,7 @@ import report import wizard import res_config import mail_group_menu +import update # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml index 5fe1ee45b1d..522cbe8c7a7 100644 --- a/addons/mail/data/mail_data.xml +++ b/addons/mail/data/mail_data.xml @@ -13,6 +13,20 @@ + + Update Notification + + + 1 + weeks + -1 + + + + + 1000 + + comment diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index bbf68509277..9c873a31097 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -504,7 +504,7 @@ class mail_message(osv.Model): if not values.get('message_id') and values.get('res_id') and values.get('model'): values['message_id'] = tools.generate_tracking_message_id('%(model)s-%(res_id)s' % values) newid = super(mail_message, self).create(cr, uid, values, context) - self._notify(cr, 1, newid, context=context) + self._notify(cr, SUPERUSER_ID, newid, context=context) return newid def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): diff --git a/addons/mail/update.py b/addons/mail/update.py new file mode 100644 index 00000000000..0e10ee0a7f1 --- /dev/null +++ b/addons/mail/update.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +import datetime +import logging +import sys +import urllib +import urllib2 + +import pooler +import release +from osv import osv, fields +from tools.translate import _ +from tools.safe_eval import safe_eval +from tools.config import config +from tools import misc + +_logger = logging.getLogger(__name__) + +""" +Time interval that will be used to determine up to which date we will +check the logs to see if a message we just received was already logged. +@type: datetime.timedelta +""" +_PREVIOUS_LOG_CHECK = datetime.timedelta(days=365) + +def get_sys_logs(cr, uid): + """ + Utility method to send a publisher warranty get logs messages. + """ + pool = pooler.get_pool(cr.dbname) + + dbuuid = pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') + db_create_date = pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date') + limit_date = datetime.datetime.now() + limit_date = limit_date - datetime.timedelta(15) + limit_date_str = limit_date.strftime(misc.DEFAULT_SERVER_DATETIME_FORMAT) + nbr_users = pool.get("res.users").search(cr, uid, [], count=True) + nbr_active_users = pool.get("res.users").search(cr, uid, [("date", ">=", limit_date_str)], count=True) + nbr_share_users = False + nbr_active_share_users = False + if "share" in pool.get("res.users")._all_columns: + nbr_share_users = pool.get("res.users").search(cr, uid, [("share", "=", True)], count=True) + nbr_active_share_users = pool.get("res.users").search(cr, uid, [("share", "=", True), ("date", ">=", limit_date_str)], count=True) + user = pool.get("res.users").browse(cr, uid, uid) + msg = { + "dbuuid": dbuuid, + "nbr_users": nbr_users, + "nbr_active_users": nbr_active_users, + "nbr_share_users": nbr_share_users, + "nbr_active_share_users": nbr_active_share_users, + "dbname": cr.dbname, + "db_create_date": db_create_date, + "version": release.version, + "language": user.lang, + } + msg.update(pool.get("res.company").read(cr,uid,[1],["name","email","phone"])[0]) + + add_arg = {"timeout":30} if sys.version_info >= (2,6) else {} + arguments = {'arg0': msg, "action": "update",} + arguments_raw = urllib.urlencode(arguments) + + url = config.get("publisher_warranty_url") + uo = urllib2.urlopen(url, arguments_raw, **add_arg) + result = {} + try: + submit_result = uo.read() + result = safe_eval(submit_result) + finally: + uo.close() + return result + +class publisher_warranty_contract(osv.osv): + _name = "publisher_warranty.contract" + + def update_notification(self, cr, uid, ids, cron_mode=True, context=None): + """ + Send a message to OpenERP's publisher warranty server to check the + validity of the contracts, get notifications, etc... + + @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron). + @type cron_mode: boolean + """ + try: + try: + result = get_sys_logs(cr, uid) + except Exception: + if cron_mode: # we don't want to see any stack trace in cron + return False + _logger.debug("Exception while sending a get logs messages", exc_info=1) + raise osv.except_osv(_("Error"), _("Error during communication with the publisher warranty server.")) + limit_date = (datetime.datetime.now() - _PREVIOUS_LOG_CHECK).strftime(misc.DEFAULT_SERVER_DATETIME_FORMAT) + # old behavior based on res.log; now on mail.message, that is not necessarily installed + proxy = self.pool.get('mail.message') + + model, res_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'group_all_employees') + + for message in result["messages"]: + values = { + 'body' : message, + 'model' : 'mail.group', + 'res_id' : res_id, + 'user_id' : False, + } + proxy.create(cr, uid, values, context=context) + except Exception: + if cron_mode: + return False # we don't want to see any stack trace in cron + else: + raise + return True + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + From 2fdcc19dcb7c7d3a147d3630155f870cfc9f7262 Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of openerp <> Date: Thu, 4 Oct 2012 05:19:06 +0000 Subject: [PATCH 194/409] Launchpad automatic translations update. bzr revid: launchpad_translations_on_behalf_of_openerp-20121004051906-19h9v4f5p768ky0x --- openerp/addons/base/i18n/ab.po | 4 +- openerp/addons/base/i18n/af.po | 4 +- openerp/addons/base/i18n/am.po | 4 +- openerp/addons/base/i18n/ar.po | 4 +- openerp/addons/base/i18n/bg.po | 4 +- openerp/addons/base/i18n/bs.po | 4 +- openerp/addons/base/i18n/ca.po | 4 +- openerp/addons/base/i18n/cs.po | 4 +- openerp/addons/base/i18n/da.po | 4 +- openerp/addons/base/i18n/de.po | 1500 +++++++++++++++++++++----- openerp/addons/base/i18n/el.po | 4 +- openerp/addons/base/i18n/en_GB.po | 4 +- openerp/addons/base/i18n/es.po | 4 +- openerp/addons/base/i18n/es_AR.po | 57 +- openerp/addons/base/i18n/es_CL.po | 4 +- openerp/addons/base/i18n/es_CR.po | 4 +- openerp/addons/base/i18n/es_EC.po | 4 +- openerp/addons/base/i18n/es_MX.po | 4 +- openerp/addons/base/i18n/et.po | 4 +- openerp/addons/base/i18n/eu.po | 4 +- openerp/addons/base/i18n/fa.po | 82 +- openerp/addons/base/i18n/fa_AF.po | 4 +- openerp/addons/base/i18n/fi.po | 4 +- openerp/addons/base/i18n/fr.po | 4 +- openerp/addons/base/i18n/gl.po | 4 +- openerp/addons/base/i18n/gu.po | 4 +- openerp/addons/base/i18n/he.po | 4 +- openerp/addons/base/i18n/hr.po | 4 +- openerp/addons/base/i18n/hu.po | 4 +- openerp/addons/base/i18n/hy.po | 4 +- openerp/addons/base/i18n/id.po | 4 +- openerp/addons/base/i18n/is.po | 4 +- openerp/addons/base/i18n/it.po | 4 +- openerp/addons/base/i18n/ja.po | 4 +- openerp/addons/base/i18n/ka.po | 4 +- openerp/addons/base/i18n/kk.po | 4 +- openerp/addons/base/i18n/ko.po | 4 +- openerp/addons/base/i18n/lt.po | 4 +- openerp/addons/base/i18n/lv.po | 4 +- openerp/addons/base/i18n/mk.po | 4 +- openerp/addons/base/i18n/mn.po | 4 +- openerp/addons/base/i18n/nb.po | 4 +- openerp/addons/base/i18n/nl.po | 31 +- openerp/addons/base/i18n/nl_BE.po | 4 +- openerp/addons/base/i18n/pl.po | 4 +- openerp/addons/base/i18n/pt.po | 4 +- openerp/addons/base/i18n/pt_BR.po | 245 ++++- openerp/addons/base/i18n/ro.po | 4 +- openerp/addons/base/i18n/ru.po | 4 +- openerp/addons/base/i18n/sk.po | 4 +- openerp/addons/base/i18n/sl.po | 4 +- openerp/addons/base/i18n/sq.po | 4 +- openerp/addons/base/i18n/sr.po | 4 +- openerp/addons/base/i18n/sr@latin.po | 4 +- openerp/addons/base/i18n/sv.po | 4 +- openerp/addons/base/i18n/th.po | 4 +- openerp/addons/base/i18n/tlh.po | 4 +- openerp/addons/base/i18n/tr.po | 4 +- openerp/addons/base/i18n/uk.po | 4 +- openerp/addons/base/i18n/ur.po | 4 +- openerp/addons/base/i18n/vi.po | 4 +- openerp/addons/base/i18n/zh_CN.po | 4 +- openerp/addons/base/i18n/zh_HK.po | 4 +- openerp/addons/base/i18n/zh_TW.po | 4 +- 64 files changed, 1720 insertions(+), 431 deletions(-) diff --git a/openerp/addons/base/i18n/ab.po b/openerp/addons/base/i18n/ab.po index ac0496223b8..6186cb742ec 100644 --- a/openerp/addons/base/i18n/ab.po +++ b/openerp/addons/base/i18n/ab.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:35+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:09+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/af.po b/openerp/addons/base/i18n/af.po index 608d495e608..10c4ef3a73d 100644 --- a/openerp/addons/base/i18n/af.po +++ b/openerp/addons/base/i18n/af.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:35+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:09+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/am.po b/openerp/addons/base/i18n/am.po index 25698246ad6..27aaf0c5a05 100644 --- a/openerp/addons/base/i18n/am.po +++ b/openerp/addons/base/i18n/am.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:35+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:10+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/ar.po b/openerp/addons/base/i18n/ar.po index 7c09854ed2a..180e7fc450e 100644 --- a/openerp/addons/base/i18n/ar.po +++ b/openerp/addons/base/i18n/ar.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:35+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:10+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/bg.po b/openerp/addons/base/i18n/bg.po index d44cade6cce..cb97a8e030b 100644 --- a/openerp/addons/base/i18n/bg.po +++ b/openerp/addons/base/i18n/bg.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:36+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:10+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/bs.po b/openerp/addons/base/i18n/bs.po index b5fc1a1f74b..138f14299fd 100644 --- a/openerp/addons/base/i18n/bs.po +++ b/openerp/addons/base/i18n/bs.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:36+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:10+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/ca.po b/openerp/addons/base/i18n/ca.po index afd47adabb8..823ff68dda8 100644 --- a/openerp/addons/base/i18n/ca.po +++ b/openerp/addons/base/i18n/ca.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:36+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:11+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/cs.po b/openerp/addons/base/i18n/cs.po index 22250c36dde..f35a33d13a4 100644 --- a/openerp/addons/base/i18n/cs.po +++ b/openerp/addons/base/i18n/cs.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:36+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:11+0000\n" +"X-Generator: Launchpad (build 16061)\n" "X-Poedit-Language: Czech\n" #. module: base diff --git a/openerp/addons/base/i18n/da.po b/openerp/addons/base/i18n/da.po index 601a032c80b..2a2ed7015c9 100644 --- a/openerp/addons/base/i18n/da.po +++ b/openerp/addons/base/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:36+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:11+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/de.po b/openerp/addons/base/i18n/de.po index f60a6ef6a22..8b79ca7b746 100644 --- a/openerp/addons/base/i18n/de.po +++ b/openerp/addons/base/i18n/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:37+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:12+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh @@ -35,7 +35,7 @@ msgstr "Datum/Zeit" #. module: base #: model:ir.module.module,shortdesc:base.module_project_mailgate msgid "Tasks-Mail Integration" -msgstr "Aufgaben EMail Integration" +msgstr "EMail-Integration in Aufgaben" #. module: base #: code:addons/fields.py:582 @@ -51,7 +51,7 @@ msgstr "" #: field:ir.ui.view,arch:0 #: field:ir.ui.view.custom,arch:0 msgid "View Architecture" -msgstr "Aufbau ansehen" +msgstr "Aufbau des Ansichts-Formulars" #. module: base #: model:ir.module.module,description:base.module_project @@ -105,7 +105,7 @@ msgstr "Arbeitsablauf" #. module: base #: selection:ir.sequence,implementation:0 msgid "No gap" -msgstr "Ohne Lücken" +msgstr "Lückenlos" #. module: base #: selection:base.language.install,lang:0 @@ -5336,6 +5336,18 @@ msgid "" "modules like share, lunch, pad, idea, survey and subscription.\n" " " msgstr "" +"\n" +"Modul zur Installation von versteckten Extras wie Lunch, Survey, Idee, " +"Teilen, usw.\n" +"=============================================================================" +"==============\n" +"\n" +"Macht versteckte Extra Konfigurationen verfügbar, mittels denen Sie Module " +"wie\n" +"Teilen (gemeinsam nutzen), Mittagessen (lunch), pad, Idee, Fragebogen und " +"Abonnement \n" +"einrichten können.\n" +" " #. module: base #: model:ir.module.category,name:base.module_category_specific_industry_applications @@ -9198,7 +9210,7 @@ msgstr "Kontakt" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_at msgid "Austria - Accounting" -msgstr "Österreich - Buchhaltung" +msgstr "Österreichische Buchführung" #. module: base #: model:ir.model,name:base.model_ir_ui_menu @@ -9557,7 +9569,7 @@ msgstr "Plattform für Zusammenarbeit" #. module: base #: model:ir.module.module,shortdesc:base.module_account_anglo_saxon msgid "Anglo-Saxon Accounting" -msgstr "Angelsächsische Buchungslogik" +msgstr "Angelsächsische Buchführung" #. module: base #: model:res.country,name:base.np @@ -10756,7 +10768,7 @@ msgstr "" #. module: base #: model:ir.module.module,description:base.module_google_base_account msgid "The module adds google user in res user" -msgstr "" +msgstr "Dieses Modul fügt google-Benutzer in res.user ein" #. module: base #: selection:base.language.install,state:0 @@ -10905,6 +10917,7 @@ msgstr "Just in Time Terminierung" #: model:ir.module.module,shortdesc:base.module_account_bank_statement_extensions msgid "Bank Statement extensions to support e-banking" msgstr "" +"Erweiterung bezüglich Bank-Kontoauszügen zur Unterstützung von eBanking" #. module: base #: view:ir.actions.server:0 @@ -10983,6 +10996,19 @@ msgid "" "fund status.\n" " " msgstr "" +"\n" +"Beschaffung von Fördermitteln.\n" +"==============================\n" +"\n" +"Wenn Sie Ihre Organisation oder eine Kampagne unterstützen wollen, können " +"Sie alle\n" +"Maßnahmen zur Beschaffung von Geldern hier nachvollziehen. Das Menü eröffnet " +"eine\n" +"Liste in der Sie Spendenbeschreibungen, eMail, Verlauf und " +"Erfolgswahrscheinlichkeiten.\n" +"Einige Aktionsschaltflächen ermöglichen die einfache Veränderung ihres " +"Mittelstatus\n" +" " #. module: base #: model:ir.module.module,shortdesc:base.module_sale_margin @@ -11056,6 +11082,12 @@ msgid "" "This module is the base module for other multi-company modules.\n" " " msgstr "" +"\n" +"Dieses Modul dient der Verwaltung einer Mehrfach-Unternehmens-Umgebung.\n" +"=================================================================\n" +"\n" +"Dieses Modul ist die Basis für andere Module für Mehrfach-Unternehmen.\n" +" " #. module: base #: sql_constraint:res.currency:0 @@ -11168,6 +11200,33 @@ msgid "" "module named account_voucher.\n" " " msgstr "" +"\n" +"Finanzbuchhaltung und Finanzverwaltung.\n" +"====================================\n" +"\n" +"Modul für Finanzen und Buchhaltung liefert:\n" +"----------------------------------------------------------------------\n" +"Allgemeine Finanzbuchhaltung\n" +"Kostenstellenrechnung\n" +"Mandantenfähigkeit\n" +"Steuerverwaltung\n" +"Budgetverwaltung\n" +"Kunden- und Lieferantenrechnungen\n" +"Kontoauszüge der Bank\n" +"Mahnwesen Partnerbezogen\n" +"\n" +"Erzeugt eine Pinnwand für Buchhalter mit:\n" +"* Liste zu bewilligender Kundenrechnungen\n" +"* Unternehmensanalyse\n" +"* Diagramm überfälliger Forderungen\n" +"* Diagramm der Finanzen\n" +"\n" +"Die Prozesse, wie Führung des Hauptbuchs, werden durch vorgegebene " +"Finanzberichte (Verschiebung von Einträgen\n" +"oder Gruppierung werden im Berichtsblatt eingestellt) im bestimmten " +"Geschäftsjahr. Zur Vorbereitung von \n" +"Gutschriften gibt es ein separates Modul namens account_voucher.\n" +" " #. module: base #: help:ir.actions.act_window,view_type:0 @@ -11236,6 +11295,12 @@ msgid "" "- SSL/TLS: SMTP sessions are encrypted with SSL/TLS through a dedicated port " "(default: 465)" msgstr "" +"Wählen Sie das Verbindungs-Verschlüsselungs-Schema:\n" +" - Keine: SMTP-Sitzungen erfolgen im Klartext.\n" +" - TLS (STARTTLS): TLS -Verschlüsselung wird zu Beginn der SMTP-Sitzung " +"angefordert (empfohlen)\n" +" - SSL/TLS: SMTP-Sitzungen sind mit SSL/TLS über einen didizierten Port " +"(Standard 465) verschlüsselt" #. module: base #: view:ir.model:0 @@ -11254,6 +11319,14 @@ msgid "" "modules like base_report_designer and base_report_creator.\n" " " msgstr "" +"\n" +"Installationsassistent für versteckte Berichtsmodule.\n" +"===============================================\n" +"\n" +"Macht versteckte Berichtsmodule verfügbar. Mit diesen können Sie dann Module " +"wie\n" +"base_report_designer und base_report_creator installieren.\n" +" " #. module: base #: model:ir.module.module,shortdesc:base.module_base_synchro @@ -11315,7 +11388,7 @@ msgstr "Ansicht" #. module: base #: model:ir.module.module,shortdesc:base.module_wiki_sale_faq msgid "Wiki: Sale FAQ" -msgstr "" +msgstr "Wiki: Verkaufs-FAQ" #. module: base #: selection:ir.module.module,state:0 @@ -11359,6 +11432,13 @@ msgid "" "outlook, Sunbird, ical, ...\n" " " msgstr "" +"\n" +"Ermöglicht die Sysnchronisierung mit Kalendern anderer Anwendungen.\n" +"===============================================================\n" +"\n" +"Ermöglicht Ihnen den Abgleich der OpenERP-Kalender mit denen Ihres Telefons, " +"von Outlook, Sunbird, iCal, ...\n" +" " #. module: base #: model:res.country,name:base.lr @@ -11448,7 +11528,7 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_google_map msgid "Google Maps on Customers" -msgstr "" +msgstr "Kunden in Google-Maps finden" #. module: base #: model:ir.actions.report.xml,name:base.preview_report @@ -11557,12 +11637,12 @@ msgstr "Fehler !" #. module: base #: model:ir.module.module,shortdesc:base.module_marketing_campaign_crm_demo msgid "Marketing Campaign - Demo" -msgstr "" +msgstr "Beispiel einer Marketing-Kampagne" #. module: base #: model:ir.module.module,shortdesc:base.module_fetchmail_hr_recruitment msgid "eMail Gateway for Applicants" -msgstr "" +msgstr "eMail Zugang für Bewerber" #. module: base #: model:ir.module.module,shortdesc:base.module_account_coda @@ -11589,7 +11669,7 @@ msgstr "Diese Methode existiert zwischenzeitlich nicht mehr" #. module: base #: model:ir.module.module,shortdesc:base.module_import_google msgid "Google Import" -msgstr "" +msgstr "Google-Import" #. module: base #: model:res.partner.category,name:base.res_partner_category_12 @@ -11665,7 +11745,7 @@ msgstr "Zu erledigen" #. module: base #: model:ir.module.module,shortdesc:base.module_product_visible_discount msgid "Prices Visible Discounts" -msgstr "" +msgstr "Sichtbare Preisnachlässe" #. module: base #: field:ir.attachment,datas:0 @@ -11906,6 +11986,12 @@ msgid "" "Provide Templates for Chart of Accounts, Taxes for Uruguay\n" "\n" msgstr "" +"\n" +"Allgemeiner Kontenplan für Uruguay\n" +"================================\n" +"\n" +"Liefert Vorlagen für Kontenplan und Steuern für Uruguay.\n" +"\n" #. module: base #: help:res.company,bank_ids:0 @@ -11987,7 +12073,7 @@ msgstr "Estonian / Eesti keel" #. module: base #: field:res.partner,email:0 msgid "E-mail" -msgstr "E-Mail" +msgstr "EMail" #. module: base #: selection:ir.module.module,license:0 @@ -12030,6 +12116,16 @@ msgid "" " http://files.me.com/nbessi/06n92k.mov\n" " " msgstr "" +"\n" +"Beispiele für den Webkit-Berichtserzeuger (report_webkit).\n" +"===================================================\n" +"\n" +"Eine Beispiel-Rechnung wird mit eingerichtet, als auch ein Assistent um\n" +"Webkit-Berichte jedem Dokument des Systems hinzuzufügen.\n" +"\n" +"Sie müssen nur noch die \"Druck\"-Schalter mittels Assistent anlegen.\n" +"Siehe auch: http://files.me.com/nbessi/06n92k.mov\n" +" " #. module: base #: selection:base.language.install,lang:0 @@ -12059,8 +12155,8 @@ msgid "" "You can not read this document (%s) ! Be sure your user belongs to one of " "these groups: %s." msgstr "" -"Sie haben kein Leserecht für diesen Satz (%s) ! Stellen Sie sicher, dass der " -"Benutzer Mitglied der folgenden Gruppe ist: %s." +"Sie haben kein Leserecht für dieses Dokument (%s)! Stellen Sie sicher, dass " +"Sie Mitglied der folgenden Gruppe sind: %s." #. module: base #: view:res.bank:0 @@ -12087,7 +12183,7 @@ msgstr "Installierte Version" #. module: base #: selection:base.language.install,lang:0 msgid "Mongolian / монгол" -msgstr "Mongolian / монгол" +msgstr "Mongolisch / монгол" #. module: base #: model:res.country,name:base.mr @@ -12113,22 +12209,32 @@ msgid "" " * Product Attributes\n" " " msgstr "" +"\n" +"Ein Modul, welches Hersteller-Information im Produktformular hinzu.\n" +"==========================================================\n" +"\n" +"Sie können die folgenden Angaben zu Produkten erfassen:\n" +" * Hersteller\n" +" * Produktname beim Hersteller\n" +" * Produktkennung (Bestellnummer) des Herstellers\n" +" * Produktmerkmale\n" +" " #. module: base #: model:ir.model,name:base.model_ir_actions_todo_category msgid "Configuration Wizard Category" -msgstr "Konfigurations Assistent Kategorie" +msgstr "Assistent zur Konfiguration der Kategorien" #. module: base #: view:base.module.update:0 msgid "Module update result" -msgstr "Modul Aktualisierung Ergebnis" +msgstr "Ergebnis der Modulaktualisierung" #. module: base #: view:workflow.activity:0 #: field:workflow.workitem,act_id:0 msgid "Activity" -msgstr "Aktion" +msgstr "Aktivität" #. module: base #: view:res.partner:0 @@ -12139,7 +12245,7 @@ msgstr "Postanschrift" #. module: base #: field:res.company,parent_id:0 msgid "Parent Company" -msgstr "Konzern" +msgstr "Stamm-Unternehmen" #. module: base #: model:ir.module.module,description:base.module_base_iban @@ -12154,6 +12260,15 @@ msgid "" "accounts with a single statement.\n" " " msgstr "" +"\n" +"Dieses Modul stellt die Basis für IBAN (Intern. Bank Accounting Number) -" +"Bankkonten mit Gültigkeitsprüfung.\n" +"=============================================================================" +"==============\n" +"\n" +"Bietet die Möglichkeit richtig dargestellte lokale Bankkonten durch IBAN-" +"Konten in einem Ausdruck.\n" +" " #. module: base #: model:ir.model,name:base.model_ir_mail_server @@ -12183,7 +12298,7 @@ msgstr "" #. module: base #: field:res.currency.rate,rate:0 msgid "Rate" -msgstr "Zinskondition" +msgstr "Wechselkurs" #. module: base #: model:res.country,name:base.cg @@ -12209,7 +12324,7 @@ msgstr "Bundesland" #. module: base #: model:ir.ui.menu,name:base.next_id_5 msgid "Sequences & Identifiers" -msgstr "Sequenzen und Identifizierungsmerkmale" +msgstr "Folgen- und Identifizierungsmerkmale" #. module: base #: model:ir.module.module,description:base.module_l10n_th @@ -12221,6 +12336,12 @@ msgid "" "Thai accounting chart and localization.\n" " " msgstr "" +"\n" +"Kontenrahmen für Thailand.\n" +"===============================\n" +"\n" +"Thailändische Kontenrahmen und Lokalisierung.\n" +" " #. module: base #: model:res.country,name:base.kn @@ -12244,6 +12365,14 @@ msgid "" " * Company Contribution Management\n" " " msgstr "" +"\n" +"Allgemeine Lohnbuchhaltung.\n" +"==========================\n" +"\n" +" * Spesenerfassung\n" +" * Auszahlungserfassung\n" +" * Verwaltung von Unternehmensbeiträgen\n" +" " #. module: base #: code:addons/base/res/res_currency.py:190 @@ -12253,9 +12382,10 @@ msgid "" "for the currency: %s \n" "at the date: %s" msgstr "" -"Konnte keinen Wechselkurs ermitteln, \n" -"für die Währung %s \n" -"am Stichtag: %s" +"Konnte für die \n" +"Währung %s am\n" +"Stichtag: %s\n" +"keinen Wechselkurs ermitteln." #. module: base #: model:ir.module.module,description:base.module_point_of_sale @@ -12275,6 +12405,20 @@ msgid "" " * Allow to refund former sales.\n" " " msgstr "" +"\n" +"Dieses Modul stellt einen schnellen und einfachen Verkaufsvorgang zur " +"Verfügung.\n" +"====================================================================\n" +"\n" +"Hauptmerkmale:\n" +" * Schnelle Erfassung der Verkäufe.\n" +" * Auswahl einer Zahlweise (einfach) oder mehrere Zahlungen mit versch. " +"Zahlweisen.\n" +" * Rückgeldermittlung.\n" +" * Anlegen und Bestätigung der Kommissionierung (autom.)\n" +" * Benutzer kann Rechnung autom. anlegen.\n" +" * Ermöglicht vorige Verkäufe gutzuschreiben.\n" +" " #. module: base #: model:ir.actions.act_window,help:base.action_ui_view_custom @@ -12282,8 +12426,8 @@ msgid "" "Customized views are used when users reorganize the content of their " "dashboard views (via web client)" msgstr "" -"Individuelle Ansichten werden aktuell z.B für die persönliche Pinnwand " -"Ansichte eingesetzt." +"Individuelle Ansichten werden aktuell z. B. für die persönliche Pinnwand-" +"Ansichten eingesetzt." #. module: base #: help:publisher_warranty.contract,check_opw:0 @@ -12291,6 +12435,8 @@ msgid "" "Checked if this is an OpenERP Publisher's Warranty contract (versus older " "contract types" msgstr "" +"Anwählen, wenn dies ein OpenERP Herausgeber-Gewährleistungsvertrag ist (im " +"Gegensatz zu älteren Vertragsarten)" #. module: base #: field:ir.model.fields,model:0 @@ -12336,7 +12482,7 @@ msgstr "" #. module: base #: help:ir.model.fields,model_id:0 msgid "The model this field belongs to" -msgstr "Das Datenmodell zu dem dieses Feld angehört." +msgstr "Das Datenmodell dem dieses Feld angehört." #. module: base #: model:res.country,name:base.mq @@ -12354,11 +12500,21 @@ msgid "" "for Wiki Sale FAQ.\n" " " msgstr "" +"\n" +"Dieses Modul stellt eine Wiki mit Vorlagen zu Fragen & Antworten des " +"Verkaufs zur Verfügung.\n" +"=============================================================================" +"=\n" +"\n" +"Es werden Beispieldaten angelegt. Dabei werden eine Wiki-Gruppe und eine " +"Wiki-Seite als\n" +"Grundlage für eine Wiki mit \"Fragen & Antworten zum Verkauf\" angelegt.\n" +" " #. module: base #: view:ir.sequence.type:0 msgid "Sequences Type" -msgstr "Sequenz Typ" +msgstr "Folgenart" #. module: base #: model:ir.module.module,description:base.module_base_action_rule @@ -12376,6 +12532,19 @@ msgid "" "trigger an automatic reminder email.\n" " " msgstr "" +"\n" +"Dieses Modul führt regelbasierte Aktionen auf Objekte in das System ein.\n" +"=============================================================\n" +"\n" +"Automatisierte Aktionen verwenden Sie für automatisch ausgelöste Aktionen\n" +"in den unterschiedlichsten Sichten.\n" +"\n" +"Beispiel: Einem Fall in Vorverhandlungen (Leads) mit einem bestimmten \n" +"Benutzer wird automatisch ein bestimmtes Verkaufsteam zugewiesen. Oder\n" +"eine nach 14 Tagen unverändert im Zustand \"wartend\" befindliche \n" +"Gelegenheit löst automatisch eine Erinnerungs-Mitteilung an den \n" +"zuständigen Mitarbeiter aus.\n" +" " #. module: base #: model:ir.actions.act_window,name:base.res_request-act @@ -12417,6 +12586,15 @@ msgid "" "The wizard to launch the report has several options to help you get the data " "you need.\n" msgstr "" +"\n" +"Fügt Berichte zum Menü der Produkte hinzu, welches Verkaufszahlen, Käufe, " +"Margen und \n" +"andere interessante Indikatoren aus Rechnungen errechnet.\n" +"==========================================================================\n" +"\n" +"Der Assistent bietet für die Berichterstellung diverse Optionen, um bei der " +"Ermittelung der \n" +"gewünschten Daten behilflich zu sein.\n" #. module: base #: model:res.country,name:base.al @@ -12450,27 +12628,28 @@ msgid "" "Please be patient, this operation may take a few minutes (depending on the " "number of modules currently installed)..." msgstr "" -"Geduld ! Dieser Vorgang kann einige Zeit dauern (in Abhängigkeit von der " -"Anzahl der installierten Module)" +"Bitte geduldig sein! Dieser Vorgang kann einige Zeit dauern (Abhängig von " +"der Anzahl derzeit installierter Module)" #. module: base #: field:ir.ui.menu,child_id:0 msgid "Child IDs" -msgstr "untergeordnete ID's" +msgstr "untergeordnete Kennungen" #. module: base #: code:addons/base/ir/ir_actions.py:748 #: code:addons/base/ir/ir_actions.py:751 #, python-format msgid "Problem in configuration `Record Id` in Server Action!" -msgstr "Problem in Konfiguration 'Datensatznummer' in der Server Aktion!" +msgstr "" +"Problem mit der Konfiguration der 'Datensatznummer' in Server-Aktion!" #. module: base #: code:addons/orm.py:2682 #: code:addons/orm.py:2692 #, python-format msgid "ValidateError" -msgstr "ValidierungsFehler" +msgstr "Validierungsfehler" #. module: base #: view:base.module.import:0 @@ -12489,6 +12668,13 @@ msgid "" "Price and Cost Price.\n" " " msgstr "" +"\n" +"Dieses Modul fügt die \"Marge\" auf Verkaufsaufträge hinzu.\n" +"================================================\n" +"\n" +"Dies gibt die Gewinnspanne durch Berechnung der Differenz zwischen \n" +"Einzelpreis (VK) und Anschaffungskosten (EK) an.\n" +" " #. module: base #: model:ir.actions.act_window,help:base.action_res_bank_form @@ -12499,12 +12685,12 @@ msgstr "" #. module: base #: view:base.module.import:0 msgid "Import module" -msgstr "Import Module" +msgstr "Import-Modul" #. module: base #: field:ir.actions.server,loop_action:0 msgid "Loop Action" -msgstr "Schleife Aktion" +msgstr "Wiederholungsaktion" #. module: base #: help:ir.actions.report.xml,report_file:0 @@ -12512,7 +12698,7 @@ msgid "" "The path to the main report file (depending on Report Type) or NULL if the " "content is in another field" msgstr "" -"Das Verzeichnis zum Hauptreport (je nach Report Typ) oder NULL, wenn der " +"Das Verzeichnis zum Hauptreport (je nach Reportart) oder NULL, wenn der " "Inhalt in einem anderen Feld steht" #. module: base @@ -12526,7 +12712,7 @@ msgstr "Laos" #: field:res.company,email:0 #: field:res.users,user_email:0 msgid "Email" -msgstr "E-Mail:" +msgstr "EMail" #. module: base #: field:res.users,action_id:0 @@ -12574,6 +12760,17 @@ msgid "" " - uid: current user id\n" " - context: current context" msgstr "" +"Bedingung, die geprüft wird bevor die Aktion ausgeführt wird, anderenfalls " +"die Auführung unterbindet.\n" +"Beispiel: object.list_price > 5000\n" +"Es ist ein Python-Ausdruck der folgende Werte nutzen kann:\n" +"- self: ORM-Modell des Datensatzes über den die Aktion ausgelöst wurde\n" +"- object oder obj: browse_record über den die Aktion ausgelöst wurde\n" +"- pool: Pool des ORM-Modells (also z. B. : self.pool)\n" +"- time: Python Zeitmodul\n" +"- cr: Datenbank-Cursor\n" +"- uid: Nutzerkennung des aktuellen Benutzers\n" +"- context: Aktueller Kontext" #. module: base #: view:ir.rule:0 @@ -12599,17 +12796,17 @@ msgstr "Andere geschützte" #. module: base #: model:res.country,name:base.ec msgid "Ecuador" -msgstr "Ekuador" +msgstr "Equador" #. module: base #: selection:workflow.activity,kind:0 msgid "Stop All" -msgstr "Stop" +msgstr "Alle stoppen" #. module: base #: model:ir.module.module,shortdesc:base.module_analytic_user_function msgid "Jobs on Contracts" -msgstr "" +msgstr "Vertragsarbeiten" #. module: base #: model:ir.module.module,description:base.module_import_sugarcrm @@ -12619,13 +12816,18 @@ msgid "" " \"Contacts\", \"Employees\", Meetings, Phonecalls, Emails, and " "Project, Project Tasks Data into OpenERP Module." msgstr "" +"Dieses Modul importiert \"Leads\", \"Gelegenheiten\", \"Benutzer\", " +"\"Konten\", \"Kontakte\",\n" +"\"Mitarbeiter\", \"Termine\", \"Anrufe\", \"EMails\" und \"Projekte\" bzw. " +"\"Projektaufgaben\" \n" +"in das OpenERP-System." #. module: base #: model:ir.actions.act_window,name:base.action_publisher_warranty_contract_add_wizard #: model:ir.ui.menu,name:base.menu_publisher_warranty_contract_add #: view:publisher_warranty.contract.wizard:0 msgid "Register a Contract" -msgstr "Registrieren" +msgstr "Vertrag aufnehmen" #. module: base #: model:ir.module.module,description:base.module_l10n_ve @@ -12636,6 +12838,13 @@ msgid "" "\n" "Este módulo es para manejar un catálogo de cuentas ejemplo para Venezuela.\n" msgstr "" +"\n" +"Dieses Modul Modul stellt Kontenrahmen der Buchhaltung in Venezuela für " +"OpenERP zur Verfügung.\n" +"=============================================================================" +"=====\n" +"\n" +"Este módulo es para manejar un catálogo de cuentas ejemplo para Venezuela.\n" #. module: base #: view:ir.model.data:0 @@ -12650,7 +12859,7 @@ msgstr "3. %x ,%X ==> 12/05/08, 18:25:20" #. module: base #: selection:ir.model.fields,on_delete:0 msgid "Cascade" -msgstr "Kaskadierend" +msgstr "Mehrstufig" #. module: base #: field:workflow.transition,group_id:0 @@ -12670,7 +12879,7 @@ msgstr "" #. module: base #: selection:base.language.install,lang:0 msgid "Arabic / الْعَرَبيّة" -msgstr "Arabic / الْعَرَبيّة" +msgstr "Arabisch / الْعَرَبيّة" #. module: base #: model:ir.module.module,shortdesc:base.module_web_hello @@ -12680,7 +12889,7 @@ msgstr "Hallo" #. module: base #: view:ir.actions.configuration.wizard:0 msgid "Next Configuration Step" -msgstr "Nächste Konfiguration" +msgstr "Nächster Konfigurationsschritt" #. module: base #: field:res.groups,comment:0 @@ -12699,12 +12908,12 @@ msgstr "Personalleiter" #: field:ir.rule,domain_force:0 #: field:res.partner.title,domain:0 msgid "Domain" -msgstr "Domain" +msgstr "Domäne" #. module: base #: model:ir.module.module,shortdesc:base.module_marketing_campaign msgid "Marketing Campaigns" -msgstr "Marketing Kampagnen" +msgstr "Marketing-Kampagnen" #. module: base #: code:addons/base/publisher_warranty/publisher_warranty.py:144 @@ -12730,7 +12939,7 @@ msgstr "Aktualisere Übersetzungen" #. module: base #: field:workflow.activity,join_mode:0 msgid "Join Mode" -msgstr "Anschlußmodus" +msgstr "Vereinigungs-Modus" #. module: base #: field:res.users,context_tz:0 @@ -12740,7 +12949,7 @@ msgstr "Zeitzone" #. module: base #: model:ir.module.module,shortdesc:base.module_wiki_faq msgid "Wiki: Internal FAQ" -msgstr "" +msgstr "Wiki: Interne Fragen & Antworten" #. module: base #: model:ir.model,name:base.model_ir_actions_report_xml @@ -12761,13 +12970,23 @@ msgid "" "handle an issue.\n" " " msgstr "" +"\n" +"Dieses Modul fügt Unterstützung für Zeitnachweise zu Problemen und -Fehlern " +"der Projektplanung hinzu.\n" +"=============================================================================" +"===========\n" +"\n" +"Arbeitsprotokolle (Rapporte) können verwendet werden, um die für " +"Problembehebung und \n" +"Fehlerbeseitigung aufgebrachte Zeit festzuhalten und Nachweis zu führen.\n" +" " #. module: base #: model:ir.actions.act_window,name:base.ir_sequence_form #: view:ir.sequence:0 #: model:ir.ui.menu,name:base.menu_ir_sequence_form msgid "Sequences" -msgstr "Sequenzen" +msgstr "Folgen" #. module: base #: model:res.partner.title,shortcut:base.res_partner_title_miss @@ -12782,7 +13001,9 @@ msgstr "ir.ui.view" #. module: base #: help:res.lang,code:0 msgid "This field is used to set/get locales for user" -msgstr "Dieses Feld bestimmt die LOCAL Variable für diese Benutzer" +msgstr "" +"Mit diesem Feld wird die \"locale\" (Ländereinstellungen) des Benutzers " +"festgelegt" #. module: base #: model:res.partner.category,name:base.res_partner_category_2 @@ -12796,7 +13017,7 @@ msgid "" "Unable to install module \"%s\" because an external dependency is not met: %s" msgstr "" "Es ist nicht möglich das Modul \"%s\" zu installieren, da eine Abhängigkeit " -"nicht erfüllt werden kann: %s" +"nicht erfüllt ist: %s" #. module: base #: view:ir.module.module:0 @@ -12816,7 +13037,7 @@ msgstr "Weißrussland" #: field:ir.actions.server,name:0 #: field:ir.actions.url,name:0 msgid "Action Name" -msgstr "Aktion Bezeichnung" +msgstr "Aktionsbezeichnung" #. module: base #: model:ir.actions.act_window,help:base.action_res_users @@ -12839,7 +13060,7 @@ msgstr "Normal" #. module: base #: model:ir.module.module,shortdesc:base.module_purchase_double_validation msgid "Double Validation on Purchases" -msgstr "" +msgstr "Doppelte Kontrolle bei Bestellungen" #. module: base #: field:res.bank,street2:0 @@ -12851,7 +13072,7 @@ msgstr "Straße 2" #. module: base #: model:ir.actions.act_window,name:base.action_view_base_module_update msgid "Module Update" -msgstr "Module aktualisieren" +msgstr "Modulaktualisierung" #. module: base #: code:addons/base/module/wizard/base_module_upgrade.py:95 @@ -12923,7 +13144,7 @@ msgstr "Grenada" #. module: base #: view:ir.actions.server:0 msgid "Trigger Configuration" -msgstr "Bericht konfigurieren" +msgstr "Auslösung konfigurieren" #. module: base #: view:base.language.install:0 @@ -12942,6 +13163,14 @@ msgid "" "picking and invoice. The message is triggered by the form's onchange event.\n" " " msgstr "" +"\n" +"Modul zur Auslösung von Warnungen in OpenERP-Objekten.\n" +"==================================================\n" +"\n" +"Warn-Hinweise können für Objekte, wie Verkaufsaufträge, Bestellungen,\n" +"Kommissionierungen und Rechnungen, ausgelöst werden. Die Mitteilung \n" +"wird ausgelöst durch das Onchange-Ereignis des jeweiligen Formulars.\n" +" " #. module: base #: code:addons/osv.py:150 @@ -13002,6 +13231,17 @@ msgid "" "it to all the users.\n" " " msgstr "" +"\n" +"Dieses Modul ergänzt die Funktionalität Mitteilungen aus der " +"Projektbearbeitung heraus zu versenden.\n" +"=============================================================================" +"=======\n" +"\n" +"Ein Anwender kann hiermit individuelle Mitteilungen an andere Benutzer " +"verschicken.\n" +"Es sind sogar \"Rundschreiben\" möglich, bei denen eine Mitteilung an alle " +"anderen versendet werden.\n" +" " #. module: base #: model:ir.module.module,shortdesc:base.module_hr @@ -13040,6 +13280,15 @@ msgid "" "This module gives the details of the goods traded between the countries of " "European Union " msgstr "" +"\n" +"Dieses Modul fügt Intrastat-Berichte in das System ein.\n" +"===============================================\n" +"\n" +"Das Modul ergänzt Produkt-Details für den Handel zwischen Ländern \n" +"der Europäischen Union (EU) gem. der EG-Verordnung Nr. 638/2004 über \n" +"die Gemeinschaftsstatistiken des Warenverkehrs zwischen Mitgliedstaaten.\n" +"Die Abgabe dieser Meldungen ist in allen EU-Mitgliedstaaten i. d. R. " +"verbindlich. " #. module: base #: model:ir.module.module,description:base.module_stock_invoice_directly @@ -13052,6 +13301,13 @@ msgid "" "the invoicing wizard if the delivery is to be invoiced.\n" " " msgstr "" +"\n" +"Rechnungsassisten für Lieferungen.\n" +"===============================\n" +"\n" +"Wenn Sie Waren versenden oder anliefern, hilft Ihnen dieses Modul\n" +"über einen Assistenten die Lieferung in Rechnung zu stellen.\n" +" " #. module: base #: code:addons/orm.py:1388 @@ -13068,7 +13324,7 @@ msgstr "Standard" #. module: base #: view:partner.wizard.ean.check:0 msgid "Correct EAN13" -msgstr "richtige EAN13" +msgstr "Richtiger EAN13" #. module: base #: selection:res.company,paper_format:0 @@ -13114,11 +13370,28 @@ msgid "" "lines: Unit price=225, Discount=0,00, Net price=225\n" " " msgstr "" +"\n" +"Dieses Modul berechnet Rabatte für Auftrags- und Rechnungspositionen bezogen " +"auf des Partners Preisliste.\n" +"=============================================================================" +"============\n" +"\n" +"Hiermit wird eine neue Kontrollbox \"Sichtbarer Rabatt\" im Formular der " +"Preisliste hinzugefügt.\n" +"\n" +"Beispiel:\n" +" Das Produkt PC1 beim Partner Asustek: Listenpreis=450, aus der " +"Preisliste von \n" +" Asustek ergibt sich ein Preis von 225\n" +" Wenn nun die Kontrollbox aktiviert wird, erhalten wir auf dem Auftrag: \n" +" Einzelpreis=450, Rabatt=50 (%), Nettopreis=225\n" +" Mit deaktivierter Kontrollbox: Einzelpreis=Nettopreis=225, Rabatt=0.\n" +" " #. module: base #: field:ir.module.module,shortdesc:0 msgid "Short Description" -msgstr "Kurzbeschreibung" +msgstr "Kurzbezeichnung" #. module: base #: field:res.country,code:0 @@ -13148,7 +13421,7 @@ msgstr "Wähle Feldmerkmal" #. module: base #: field:res.request.history,date_sent:0 msgid "Date sent" -msgstr "Sendedatum" +msgstr "Versanddatum" #. module: base #: view:ir.sequence:0 @@ -13173,7 +13446,7 @@ msgstr "Monat: %(month)s" #: field:res.widget.user,sequence:0 #: field:wizard.ir.model.menu.create.line,sequence:0 msgid "Sequence" -msgstr "Sequenz" +msgstr "Reihenfolge" #. module: base #: model:res.country,name:base.tn @@ -13206,7 +13479,7 @@ msgstr "Entwurf und Aktiv" #: view:ir.actions.server:0 #: model:ir.ui.menu,name:base.menu_server_action msgid "Server Actions" -msgstr "Server Aktion" +msgstr "Server-Aktion" #. module: base #: field:res.partner.bank.type,format_layout:0 @@ -13242,11 +13515,26 @@ msgid "" "HR Applicant and Project Issue from selected mails.\n" " " msgstr "" +"\n" +"Dieses Modul wird für das Thunderbird-Plugin benötig, damit dieses " +"funktionieren kann.\n" +"========================================================================\n" +"\n" +"Das Plugin erlaubt Ihnen die Archivierung von EMail mitsamt Anhängen in " +"OpenERP-Objekten.\n" +"Sie können einen Partner, einer Aufgabe, ein Projekt, ein analytisches Konto " +"oder ein beliebiges \n" +"anderes Objekt in OpenERP auswählen und die gewünschte EMail als .eml-Datei " +"dem Objekt als\n" +"Anhang anfügen. Sie können aus der EMail neue Dokumente, in den Bereichen " +"Kunden-Leads,\n" +"Personal-Bewerber und Projekt-Problembearbeitung, anlegen.\n" +" " #. module: base #: view:res.lang:0 msgid "Legends for Date and Time Formats" -msgstr "Legende Datum und Zeit" +msgstr "Legende für Datum- und Zeit-Darstellungen" #. module: base #: selection:ir.actions.server,state:0 @@ -13261,7 +13549,7 @@ msgstr "Verwaltung von Emails" #. module: base #: field:ir.actions.server,trigger_name:0 msgid "Trigger Signal" -msgstr "Signalauslöser" +msgstr "Auslösesignal" #. module: base #: code:addons/base/res/res_users.py:119 @@ -13288,18 +13576,29 @@ msgid "" " * Repair quotation report\n" " * Notes for the technician and for the final customer\n" msgstr "" +"\n" +"Aufgabe dieses Moduls ist die Verwaltung von Produktreparaturen.\n" +"========================================================\n" +"\n" +"Die folgenden Aufgaben werden durch das Modul zur Verfügung gestellt:\n" +" * Zu reparierende Produkte hinzufügen und löschen\n" +" * Auswirkung auf Lagerbestände\n" +" * Rechnungsstellung (Produkte wie auch Leistung)\n" +" * Umsetzung von Garantie- und Gewährleitsungskonzepten\n" +" * Ausdruck von Reparaturangeboten\n" +" * Hinweise für den Techniker wie auch den Endkunden\n" #. module: base #: model:ir.actions.act_window,name:base.action_country_state #: model:ir.ui.menu,name:base.menu_country_state_partner msgid "Fed. States" -msgstr "Partner Regionen" +msgstr "Bundesländer / Regionen" #. module: base #: view:ir.model:0 #: view:res.groups:0 msgid "Access Rules" -msgstr "Berechtigungen Regeln" +msgstr "Zugriffsberechtigungen" #. module: base #: model:ir.module.module,description:base.module_knowledge @@ -13313,11 +13612,19 @@ msgid "" "document and Wiki based Hidden.\n" " " msgstr "" +"\n" +"Installationsmodul für versteckte, wissens-bezogene Module.\n" +"===================================================\n" +"\n" +"Macht die Konfiguration der Wissensanwendung verfügbar, über die Sie \n" +"die versteckten Module Dokument-Wissen und Wiki-Wissen installieren\n" +"können.\n" +" " #. module: base #: field:res.groups,trans_implied_ids:0 msgid "Transitively inherits" -msgstr "Vorübergehende Vererbung" +msgstr "Erbt übergangsweise" #. module: base #: field:ir.default,ref_table:0 @@ -13368,7 +13675,7 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_account_analytic_plans msgid "Multiple Analytic Plans" -msgstr "" +msgstr "Mehrschichtige analytische Pläne" #. module: base #: model:ir.module.module,description:base.module_project_timesheet @@ -13384,6 +13691,18 @@ msgid "" "\n" " " msgstr "" +"\n" +"Abgleich von Arbeit/Aufgaben aus Projekten mit Einträgen ausZeitnachweisen.\n" +"==================================================================\n" +"\n" +"Dieses Modul gibt Ihnen die Möglichkeit Aufgaben aus dem Projektmanagement\n" +"in Zeitnachweis-Einträge für bestimmte Mitarbeiter und an bestimmten Daten " +"zu \n" +"überführen, wobei sowohl auf Projekt- wie auch die Zeitnachweiseseite " +"effektiv \n" +"Einträge angelegt, bearbeitet und gelöscht werden können.\n" +"\n" +" " #. module: base #: view:ir.sequence:0 @@ -13417,6 +13736,20 @@ msgid "" " \n" "%(country_code)s: the code of the country" msgstr "" +"Sie können hier das übliche Format angeben, in dem Adressen dieses Landes " +"wiedergegeben werden.\n" +"\n" +"Sie können Zeichenketten im Stile von Python mit allen Feldern einer Adresse " +"verwenden \n" +"(z. B. '%(street)s' um das Feld 'street' anzuzeigen) und\n" +"\n" +"%(state_name)s für das Bundesland\n" +"\n" +"%(state_code)s für das Kürzel des Bundeslandes\n" +"\n" +"%(country_name)s für den Namen des Landes\n" +"\n" +"%(country_code)s für die Kurzform / die Kennung" #. module: base #: model:ir.module.module,description:base.module_pad @@ -13430,6 +13763,15 @@ msgid "" "(by default, http://ietherpad.com/).\n" " " msgstr "" +"\n" +"Fügt dem Web-Klienten erweiterte Unterstützung für (Ether)Pad-Zubehör " +"hinzu.\n" +"==================================================================\n" +"\n" +"Läßt das Unternehmen einstellen, welche Pad-Installation verwendet werden " +"soll,\n" +"um neue Pad-Geräte zu verbinden (Vorgabe: http://etherpad.com/).\n" +" " #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_uk @@ -13465,6 +13807,31 @@ msgid "" " * http://controlchaos.com\n" " " msgstr "" +"\n" +"Dieses Modul setzt alle methodischen Konzepte eines Scrum-Projekt-" +"Managements von IT-Unternehmen um.\n" +"=============================================================================" +"============\n" +"\n" +" * Projekte mit Sprints, Projektbesitzer, Scrum-Meister\n" +" * Sprints mit Prüfung, Tägliche Treffen, Rückmeldungen\n" +" * Produkt Rückblick\n" +" * Sprint Rückblick\n" +"\n" +"Es fügt einige Konzepte dem Modul Projekt-Management hinzu:\n" +" * Mittel- und Langfristige Vorausplanung (Road-Maps)\n" +" * Kunden- und Funktionale Anfragen vs. Technischer Anfragen\n" +"\n" +"Es werden auch neue Berichte ergänzt:\n" +" * Burn-Down Diagramm\n" +"\n" +"Scrum-Projekte und -Aufgaben teilen Ihre Daten mit realen Projekten,\n" +"so dass Sie wie gewohnt an normalen Aufgaben arbeiten können. Hier\n" +"werden lediglich auch Aufgaben aus Scrum-Projekten zusätzlich erscheinen.\n" +"\n" +"Mehr Information zu diesen Methoden:\n" +" http://controlchaos.com\n" +" " #. module: base #: code:addons/base/ir/ir_model.py:371 @@ -13473,8 +13840,9 @@ msgid "" "Changing the type of a column is not yet supported. Please drop it and " "create it again!" msgstr "" -"Wechsel der Datentyps eines Feldes wird nicht unterstützt. Bite brechen Sie " -"den Vorgang ab oder erstellen einen neuen Schüssel von Anfang an" +"Wechsel der Datentyps eines Feldes wird (noch) nicht unterstützt. Bitte " +"löschen Sie das Feld \r\n" +"und legen es mit gewünschtem Datentyp neu an." #. module: base #: field:ir.ui.view_sc,user_id:0 @@ -13485,7 +13853,7 @@ msgstr "Benutzer Referenz" #: code:addons/base/res/res_users.py:118 #, python-format msgid "Warning !" -msgstr "Warnung !" +msgstr "Warnung!" #. module: base #: model:res.widget,title:base.google_maps_widget @@ -13527,7 +13895,7 @@ msgstr "Guatemala Buchführung" #. module: base #: help:ir.cron,args:0 msgid "Arguments to be passed to the method, e.g. (uid,)." -msgstr "Argumente, die der Methode übergeben werden." +msgstr "Argumente, die der Methode übergeben werden, zum Bsp. (uid,)." #. module: base #: model:res.partner.category,name:base.res_partner_category_5 @@ -13569,7 +13937,7 @@ msgstr "Libanon" #: view:ir.actions.report.xml:0 #: field:ir.actions.report.xml,report_type:0 msgid "Report Type" -msgstr "Report Type" +msgstr "Berichtsart" #. module: base #: field:ir.actions.todo,state:0 @@ -13600,6 +13968,22 @@ msgid "" "in the form of pdf file. Implements a dashboard for My Current Evaluations\n" " " msgstr "" +"\n" +"Ermöglicht die Anlage von Mitarbeiter-Bewertungen-\n" +"=============================================\n" +"\n" +"Eine Bewertung kann durch einen Mitarbeiter für seine Untergebenen, \n" +"Auszubildende wie auch den eigenen Vorgesetzten angelegt werden.\n" +"Die Evaluierung verläuft nach einem Plan in dem unterschiedliche \n" +"Fragebögen angelegt werden können. Es kann dabei festgelegt werden, \n" +"welche Stufe der Mitarbeiterhierarchie bestimmte Information\n" +"ausfüllen darf / muss und schließlich wird der Vorgesetzte den\n" +"Abschluss durch Prüfung und Schlussevaluierung vornehmen.\n" +"Jede (eigene) Evaluierung kann durch die Mitarbeiter selbst in\n" +"Form eines PDF eingesehen werden.\n" +"Eine Pinnwand wird für die Mitarbeiter angelegt in dem \n" +"\"Meine aktuellen Evalierungen\" erscheinen.\n" +" " #. module: base #: selection:base.language.install,lang:0 @@ -13625,12 +14009,12 @@ msgstr "Lade offizielle Übersetzung" #. module: base #: view:res.currency:0 msgid "Miscelleanous" -msgstr "Diverses" +msgstr "Verschiedenes" #. module: base #: model:res.partner.category,name:base.res_partner_category_10 msgid "Open Source Service Company" -msgstr "Open Source Service Company" +msgstr "Open Source Dienstleistungsunternehmen" #. module: base #: selection:base.language.install,lang:0 @@ -13666,7 +14050,7 @@ msgstr "Verbindungsinformationen" #. module: base #: view:ir.attachment:0 msgid "Created" -msgstr "Erzeugt" +msgstr "Angelegt" #. module: base #: help:ir.actions.wizard,multi:0 @@ -13674,8 +14058,7 @@ msgid "" "If set to true, the wizard will not be displayed on the right toolbar of a " "form view." msgstr "" -"Wenn aktiviert, dann wird der Assistent nicht im rechten Werkzeugkasten " -"angezeigt." +"Wenn aktiviert, wird der Assistent nicht im rechten Werkzeugkasten angezeigt." #. module: base #: view:base.language.import:0 @@ -13693,8 +14076,8 @@ msgid "" "External Key/Identifier that can be used for data integration with third-" "party systems" msgstr "" -"Externer Schlüssel, der für die Datenintegration mit 3-Anbietern verwendet " -"werden kann." +"Externer Schlüssel, der für die Datenintegration mit Systemen von " +"Drittanbietern verwendet werden kann." #. module: base #: model:ir.module.module,description:base.module_mrp_operations @@ -13729,6 +14112,41 @@ msgid "" "\n" " " msgstr "" +"\n" +"Dieses Modul fügt Status, Anfangsdatum, Enddatum in Arbeitsaufträgen von " +"Fertigungsaufträgen ein\n" +"(im Fertigungsstellen-Reiter)\n" +"=============================================================================" +"========\n" +"\n" +"Status: Entwurf, Bestätigt, Erledigt, Abgebrochen\n" +"Wenn Fertigungsaufträge erledigt, bestätigt oder abgebrochen werden, werden " +"auch alle \n" +"Arbeitsaufträge entsprechenden Status erhalten.\n" +"\n" +"Angelegte, neue Menüs:\n" +"Fertigung -> FErtigung -> Arbeitsaufträge\n" +"\n" +"Dies stellt eine Sicht auf die Fertigungstellen-Positionen des bezogenen " +"Fertigungsauftrages dar.\n" +"\n" +"Es werden neue Schalter in den Formularen der Fertigungsaufträge im Reiter \n" +"Fertigungsstellen angelegt:\n" +"* Start (Status wird \"Begonnen\"), Anfangsdatum wird festgesetzt\n" +"* Erledigt (Status wird \"Erledigt\"), Enddatum wird festgelsetzt\n" +"* Entwurf (Status wird \"Entwurf\")\n" +"* Abbruch (Status wird zu \"Abgebrochen\")\n" +"\n" +"Wenn der Fertigungsauftrag \"Bereit zur Fertigung\" ist, werden " +"Arbeitsaufträge\n" +"\"Bestätigt\". Ist der Fertigungsauftrag \"Erledigt\" werden alle " +"Arbeitsaufträge \n" +"als Erledigt gesetzt.\n" +"\n" +"Das Feld Dauer stellt die Durchlaufzeit (Enddatum - Anfangsdatum) dar.\n" +"Hier kann der theoretische Durchlauf mit dem realen verglichen werden.\n" +"\n" +" " #. module: base #: model:ir.module.module,description:base.module_auction @@ -13752,6 +14170,24 @@ msgid "" " * Objects By Day (graph)\n" " " msgstr "" +"\n" +"Dieses Modul verwaltet Einträge Künstlern, Auktionsartikeln, Käufern und " +"Verkäufern.\n" +"========================================================================\n" +"\n" +"Dies ist einevollständige Verwaltung einer Auktion mit Verwaltung der " +"Gebote, \n" +"Nachverfolgung der Verkauften Artikel/Produkte zusammen mit den Zahlungen\n" +"bzw. offenen Posten und schließlich der Auslieferung der Ware.\n" +"\n" +"Die Pinnwand für Auktionen schließt ein:\n" +" * Liste der zuletzt eingestellten Objekte,\n" +" * Liste der letzten Gebote,\n" +" * Liste der Objektkennzahlen,\n" +" * Diagramm der Zuschlagssummen,\n" +" * Diagramm Min./Zuschl/Max. -Verlauf\n" +" * Diagramm Tagesverkaufszahlen nach Tagen\n" +" " #. module: base #: model:ir.module.module,description:base.module_base_crypt @@ -13797,7 +14233,7 @@ msgstr "Ansicht Referenz" #. module: base #: model:ir.module.category,description:base.module_category_sales_management msgid "Helps you handle your quotations, sale orders and invoicing." -msgstr "Erstellen Sie Angebote, Aufträge und Rechnungen." +msgstr "Unterstützt Sie bei Ihren Angeboten, Aufträgen und Rechnungen." #. module: base #: field:res.groups,implied_ids:0 @@ -13826,7 +14262,7 @@ msgstr "Icon URL" #: field:ir.actions.url,type:0 #: field:ir.actions.wizard,type:0 msgid "Action Type" -msgstr "Aktion" +msgstr "Aktionart" #. module: base #: model:res.country,name:base.vn @@ -13847,6 +14283,16 @@ msgid "" "Chad, Togo.\n" " " msgstr "" +"Dieses Modul setzt die Buchhaltung für Länder der OHADA-Region um.\n" +" Es ermöglich einem Unternehmen oder Konzern die eigene Finanzbuchhaltung " +"zu verwalten.\n" +" Länder, die OHADA-Buchhaltung verwenden sind:\n" +" Benin, Burkina Faso, Kamerun, Zentral-Afrikanische Republik, Komoros, " +"Kongo,\n" +" Elfenbeinküste, Gabun, Guinea, Guinea Bissau, Äquatorial Guinea, Mali, " +"Niger,\n" +" Demokratische Republik Kongo, Senegal, Tschad, Togo.\n" +" " #. module: base #: view:base.language.import:0 @@ -13858,7 +14304,7 @@ msgstr "Importiere Übersetzung" #. module: base #: field:res.partner.bank.type,field_ids:0 msgid "Type fields" -msgstr "Felder Typen" +msgstr "Typfelder" #. module: base #: view:ir.actions.todo:0 @@ -13950,6 +14396,15 @@ msgid "" "you can modify in OpenOffice. Once you have modified it you can\n" "upload the report using the same wizard.\n" msgstr "" +"\n" +"Dieses Modul wird zusammen mit dem OpenERP OpenOffice-Plugin verwendet.\n" +"==================================================================\n" +"\n" +"Dieses Modul fügt dem System einen Assistenten hinzu mit dem .SXW Berichte\n" +"nach OpenOffice Im- bzw. Exportiert werden und dort verändert werden " +"können.\n" +"Die angepaßten Berichte können über den gleichen Assistenten wieder in das \n" +"OpenERP-Berichtssystem hochgeladen werden.\n" #. module: base #: view:ir.sequence:0 @@ -13964,7 +14419,7 @@ msgstr "Entferne Haken, um den Kontakt in der Ansicht zu verstecken" #. module: base #: model:ir.model,name:base.model_res_widget_wizard msgid "Add a widget for User" -msgstr "Assistent hinzufügen für Benutzer" +msgstr "Hinzufügen eines Anzeigeelements" #. module: base #: model:res.country,name:base.dk @@ -13987,6 +14442,19 @@ msgid "" "If you need to manage your meetings, you should install the CRM module.\n" " " msgstr "" +"\n" +"Dies ist ein Vollwertiges Kalendersystem.\n" +"==================================\n" +"\n" +"Es unterstützt:\n" +" - Veranstaltungskalender\n" +" - Alarme (Anlegen von Anfragen)\n" +" - Wiederkehrende Termine\n" +" - Einladungen an Personen\n" +"\n" +"Wenn Sie Ihre (Zusammen-) Treffen verwalten müssen, sollten Sie die \n" +"Kundenverwaltung (CRM) installieren.\n" +" " #. module: base #: view:ir.rule:0 @@ -14002,7 +14470,7 @@ msgstr "workflow.instance" #: code:addons/orm.py:471 #, python-format msgid "Unknown attribute %s in %s " -msgstr "Unbekannte Attribute %s in %s " +msgstr "Unbekanntes Attribut %s in %s " #. module: base #: view:res.lang:0 @@ -14018,7 +14486,7 @@ msgstr "nicht definierte 'get' Funktion" #. module: base #: selection:base.language.install,lang:0 msgid "Norwegian Bokmål / Norsk bokmål" -msgstr "Norwegian Bokmål / Norsk bokmål" +msgstr "Norwegische Buchhaltung" #. module: base #: model:res.partner.title,name:base.res_partner_title_madam @@ -14049,17 +14517,17 @@ msgstr "Lohnbuchhaltung" #. module: base #: help:ir.attachment,type:0 msgid "Binary File or external URL" -msgstr "Binäres Feld oder externe URL" +msgstr "Binäre Datei oder externe URL" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_order_dates msgid "Dates on Sales Order" -msgstr "" +msgstr "Daten auf Verkaufsaufträgen" #. module: base #: view:ir.attachment:0 msgid "Creation Month" -msgstr "Monat Erstellung" +msgstr "Erstellungsmonat" #. module: base #: model:res.country,name:base.nl @@ -14081,11 +14549,22 @@ msgid "" "technical OpenERP documentation at http://doc.openerp.com\n" " " msgstr "" +"\n" +"Stellt eine allgemeine EDI-Schnittstelle für andere Module zur Verfügung\n" +"============================================================\n" +"\n" +"OpenERP stellt ein allg. EDI-Format zur Verfügung um Geschäftdokumente \n" +"mit anderen Anwendungen auszutauschen und stellt hierfür generelle\n" +"Mechanismen für Import und Export bereit.\n" +"\n" +"Weitere Details über das in OpenERP verwendete EDI-Format erhalten Sie \n" +"in der technischen Dokumentation unter http://doc.openerp.com\n" +" " #. module: base #: model:ir.ui.menu,name:base.next_id_4 msgid "Low Level Objects" -msgstr "Detailebene Objekte" +msgstr "Objekte auf Detailebene" #. module: base #: help:ir.values,model:0 @@ -14095,7 +14574,7 @@ msgstr "Modell für das dieser Eintrag gilt" #. module: base #: field:res.country,address_format:0 msgid "Address Format" -msgstr "Adressen Format" +msgstr "Adressenformat" #. module: base #: model:ir.model,name:base.model_ir_values @@ -14119,7 +14598,7 @@ msgid "" "Here is what we got instead:\n" " %s" msgstr "" -"Hier sehen Sie was wir anstelle bekommen haben:\n" +"Hier sehen Sie, was wir an Stelle dessen bekommen haben:\n" " %s" #. module: base @@ -14132,7 +14611,7 @@ msgstr "Externe Identifikationen" #. module: base #: model:res.groups,name:base.group_sale_salesman msgid "User - Own Leads Only" -msgstr "" +msgstr "Nur eigene Leads" #. module: base #: model:res.country,name:base.cd @@ -14142,14 +14621,14 @@ msgstr "Demokratische Republik Kongo" #. module: base #: selection:base.language.install,lang:0 msgid "Malayalam / മലയാളം" -msgstr "Malayalam / മലയാളം" +msgstr "Malaysisch / മലയാളം" #. module: base #: view:res.request:0 #: field:res.request,body:0 #: field:res.request.history,req_id:0 msgid "Request" -msgstr "Anforderung" +msgstr "Anfrage" #. module: base #: model:ir.actions.act_window,help:base.act_ir_actions_todo_form @@ -14165,7 +14644,7 @@ msgstr "" #. module: base #: view:res.company:0 msgid "Portrait" -msgstr "Porträt" +msgstr "Hochformat" #. module: base #: field:ir.cron,numbercall:0 @@ -14182,7 +14661,7 @@ msgstr "Bank" #: view:base.module.upgrade:0 #: field:base.module.upgrade,module_info:0 msgid "Modules to update" -msgstr "Module Updates" +msgstr "Zu aktualisierende Module" #. module: base #: help:ir.actions.server,sequence:0 @@ -14190,13 +14669,13 @@ msgid "" "Important when you deal with multiple actions, the execution order will be " "decided based on this, low number is higher priority." msgstr "" -"Wichtig für mehrere Aktionen. Die Reihenfolge der Ausführung erfolgt nach " -"aufsteigenden Nummern." +"Wichtig beim Umgang mit mehreren Aktionen. Die Reihenfolge der Ausführung " +"erfolgt nach aufsteigenden Nummern." #. module: base #: field:ir.actions.report.xml,header:0 msgid "Add RML header" -msgstr "Hinzu RML header" +msgstr "Füge RML header ein" #. module: base #: model:ir.module.module,description:base.module_l10n_tr @@ -14211,6 +14690,16 @@ msgid "" "hesap bilgileriniz,ilgili para birimi gibi bilgiler isteyecek.\n" " " msgstr "" +"\n" +"Türkische Buchhaltung...\n" +"Türkiye için Tek düzen hesap planı şablonu OpenERP Modülü.\n" +"=============================================================================" +"=\n" +"\n" +"Bu modül kurulduktan sonra, Muhasebe yapılandırma sihirbazı çalışır\n" +"* Sihirbaz sizden hesap planı şablonu, planın kurulacağı şirket,banka hesap " +"bilgileriniz,ilgili para birimi gibi bilgiler isteyecek.\n" +" " #. module: base #: view:res.config:0 @@ -14220,12 +14709,12 @@ msgstr "Anwenden" #. module: base #: field:res.request,trigger_date:0 msgid "Trigger Date" -msgstr "Trigger Datum" +msgstr "Auslösedatum" #. module: base #: selection:base.language.install,lang:0 msgid "Croatian / hrvatski jezik" -msgstr "Croatian / hrvatski jezik" +msgstr "Kroatien / hrvatski jezik" #. module: base #: sql_constraint:res.country:0 @@ -14239,6 +14728,9 @@ msgid "" " OpenERP Web kanban view.\n" " " msgstr "" +"\n" +" OpenERP-Web-Kanbanansicht\n" +" " #. module: base #: model:ir.ui.menu,name:base.menu_project_management_time_tracking @@ -14248,13 +14740,13 @@ msgstr "Zeiterfassung" #. module: base #: view:res.partner.category:0 msgid "Partner Category" -msgstr "Partner Kategorie" +msgstr "Partnerkategorie" #. module: base #: view:ir.actions.server:0 #: selection:ir.actions.server,state:0 msgid "Trigger" -msgstr "Trigger" +msgstr "Auslöser" #. module: base #: model:ir.module.category,description:base.module_category_warehouse_management @@ -14262,8 +14754,8 @@ msgid "" "Helps you manage your inventory and main stock operations: delivery orders, " "receptions, etc." msgstr "" -"Management von Lagerorten und Verwaltung von Beständen, z.B. durch Erfassen " -"von Lieferungen, Durchführung von Inventuren, etc." +"Management Ihrer Bestände, Erfassen von Bestandsveränderungen, Durchführung " +"von Inventuren." #. module: base #: model:ir.model,name:base.model_base_module_update @@ -14368,11 +14860,92 @@ msgid "" "\n" " " msgstr "" +"\n" +"Fügt Unterstützung für eine Authentifizierung durch LDAP-Server hinzu.\n" +"============================================================\n" +"\n" +"Dieses Modul erlaubt Benutzern sich mit ihrem LDAP-Benutzernamen\n" +"und -Passwort anzumelden und legt automatisch OpenERP-Benutzer\n" +"an.\n" +"** Hinweis** Dieses Modul funktioniert nur mit Servern auf denen\n" +"das Python-LDAP-Modul installiert ist.\n" +"\n" +"Einrichtung:\n" +"++++++++++++\n" +"Nach der Installation dieses Moduls müssen Sie die LDAP-Einstellungen\n" +"im Formular LDAP der Unternehmenseinstellungen eintragen. \n" +"Verschiedene Unternehmen mögen unterschiedliche LDAP-Server\n" +"nutzen, solange sie eindeutig unterscheidbare Benutzernamen\n" +"verwenden. OpenERP erfordert, auch bei mehreren eingerichteten\n" +"Unternehmen, eindeutige Benutzer.\n" +"Anonyme LDAP-Anbindung wird ebenfalls unterstützt (sofern\n" +"die LDAP-Server dies zulassen), dabei wird einfach das Benutzer-\n" +"und Passwort-Feld der LDAP-Konfiguration jeweils leer gelassen.\n" +"Dies erlaubt **nicht** die anonyme Anmeldung durch Benutzer.\n" +"Dies ist nur für den Haupt-LDAP-Nutzerzugang über den die \n" +"Existenz eines Benutzers geprpft wird bevor er authentifiziert wird.\n" +"Die Absicherung der Verbindung mittels STARTTLS ist verfügbar\n" +"bei LDAP-Servern, die dies unterstützen. Dabei muss diese \n" +"Einstellung bei der LDAP-Konfiguration eingestellt werden.\n" +"Für weitergehende Einstellung schauen Sie bitte nach in \n" +"ldap.conf manpage :manpage:`ldap.conf(5)`.\n" +"\n" +"Sicherheitsbetrachtungen:\n" +"+++++++++++++++++++++++\n" +"Passwörter von LDAP-Nutzern werden niemals in der OpenERP-\n" +"eigenen Datenbank gespeichert, der LDAP-Server wird für\n" +"jeden Bedarf einer Authentifizierung angefragt. Damit ist\n" +"die Duplizierung von Einträgen vermieden und die Verwaltung\n" +"findet nur an einer Stelle statt.\n" +"OpenERP ist für diese Verwaltung nicht zuständig und so muss\n" +"die Änderung von Zugangsdaten (Passwort) über andere\n" +"Möglichkeiten der LDAP-Verwaltung erfolgen.\n" +"\n" +"Es ist auch möglich, neben den LDAP-Benutzern, lokale OpenERP-\n" +"Benutzer zu pflegen. Der Administrator ist ein typisches und\n" +"offensichtliches Beispiel.\n" +"\n" +"Und so funktioniert es:\n" +"* Das System versucht zunächst den Benutzer in der lokalen\n" +"OpenERP-Datenbank zu finden und zu authentifizieren,\n" +"*Schlägt dies fehl, vielleicht weil der Benutzer nicht lokal \n" +"angelegt ist, versucht das System die Authentifizierung durch \n" +"Anfrage beim LDAP-Server.\n" +"Bei Nutzung von STARTTLS während der Authentifizierung ist\n" +"die Verschlüsselung der Anfrage sichergestellt.\n" +"\n" +"Benutzer-Vorlage\n" +"+++++++++++++++\n" +"Bei der Konfiguration von LDAP in den Unternehmens-Einstellungen\n" +"ist es auch möglich eine *Benutzer-Vorlage* auszuwählen. Ist diese\n" +"eingestellt, werden die Einstellungen aus dieser Vorlage herange-\n" +"zogen, wenn sich ein LDAP-Benutzer zum ersten Mal anmeldet.\n" +"Somit ist die Voreinstellung der Standard-Gruppzugehörigkeiten\n" +"und der Menüs von Erstnutzern möglich.\n" +"\n" +"**Warnung** Wenn Sie ein Kennwort in der Benutzer-Vorlage\n" +"setzen, gilt dieses gleiche Kennwort für alle über diese Vorlage\n" +"neu angelegten Benutzer bis diese es manuell abändern.\n" +"Dieses Verhalten werden Sie in aller Regel nicht wünschen.\n" +"Ein einfacher Weg eine solchen Vorlage einzurichten ist die \n" +"einmalige Anmeldung mittels gültigem LDAP-Benutzer. OpenERP\n" +"legt dann einen leeren, lokalen Benutzer mit dem selben Namen \n" +"(und leerem Passwort) an. Sie benennen nun diesen neuen Benutzer \n" +"auf einen im LDAP nicht existierenden Benutzer um. Bei diesem \n" +"richten Sie nun die Gruppen und Menüs wunschgemäß ein.\n" +"\n" +"Interaktion mit base_crypt\n" +"+++++++++++++++++++++++++++\n" +"Das base_crypt-Modul verträgt sich mit diesem LDAP-Modul \n" +"nicht. Es wird die LDAP-Authentifizierung deaktivieren, wenn\n" +"es gleichzeitig installiert sein sollte.\n" +"\n" +" " #. module: base #: field:res.request.history,body:0 msgid "Body" -msgstr "Hauptteil Seite" +msgstr "Textkörper" #. module: base #: code:addons/base/ir/ir_mail_server.py:199 @@ -14383,7 +14956,7 @@ msgstr "Verbindungstest erfolgreich" #. module: base #: view:partner.massmail.wizard:0 msgid "Send Email" -msgstr "Send Email" +msgstr "EMail senden" #. module: base #: field:res.users,menu_id:0 @@ -14411,7 +14984,9 @@ msgstr "auswählen" msgid "" "Indicates whether this object model lives in memory only, i.e. is not " "persisted (osv.osv_memory)" -msgstr "Zeigt an, ob dieses Modell nur im Memory existiert, (osv.osv_memoy)" +msgstr "" +"Zeigt an, ob dieses Modell nur im Speicher existiert, und damit nicht " +"persistent ist (osv.osv_memoy)" #. module: base #: code:addons/base/ir/ir_mail_server.py:415 @@ -14434,6 +15009,10 @@ msgid "" "Python code to be executed if condition is met.\n" "It is a Python block that can use the same values as for the condition field" msgstr "" +"Auszuführender Python-Programmcode, für den Fall, dass die Bedingung erfüllt " +"ist.\n" +"Dies ist ein Python-Code-Block, der die gleichen Werte nutzen kann wie in " +"der Bedingungsprüfung." #. module: base #: model:ir.actions.act_window,name:base.action_partner_supplier_form @@ -14465,7 +15044,7 @@ msgstr "Gabun" #. module: base #: model:res.groups,name:base.group_multi_company msgid "Multi Companies" -msgstr "" +msgstr "Mehrteilige Unternehmen (z. B. Filialbetrieb)" #. module: base #: view:ir.model:0 @@ -14484,7 +15063,7 @@ msgstr "Grönland" #. module: base #: model:res.groups,name:base.group_sale_salesman_all_leads msgid "User - All Leads" -msgstr "" +msgstr "Benutzer - Alle Leads" #. module: base #: field:res.partner.bank,acc_number:0 @@ -14535,6 +15114,27 @@ msgid "" "\n" " " msgstr "" +"\n" +"Dieses Modul ermöglicht eine JIT-Zeitplanung für das Beschaffungswesen.\n" +"==============================================================\n" +"\n" +"Wenn Sie dieses Modul installieren, werden Sie nicht mehr die reguläre " +"Terminierung\n" +"der Beschaffung verwenden müssen. (Die Meldebestandsregeln müssen jedoch " +"immer \n" +"noch überwacht werden, z. B. einmal am Tag)\n" +"Alle Beschaffung wird spontan bearbeitet, was gelegentlich zu kleinen " +"Performance-\n" +"einbußen führen kann.\n" +"\n" +"Dies könnte auch zu einer Erhöhung der Bestände führen, da Produkte so früh " +"wie \n" +"möglich reserviert werden und die Terminierung-Zeitplanung nicht mehr\n" +"berücksichtigt wird. In diesem Fall müssen Sie auch auf Prioritäten bei der " +"\n" +"Kommissionierung verzichten.\n" +"\n" +" " #. module: base #: model:res.country,name:base.cy @@ -14546,12 +15146,12 @@ msgstr "Zypern" #: field:partner.massmail.wizard,subject:0 #: field:res.request,name:0 msgid "Subject" -msgstr "Thema" +msgstr "Betreff" #. module: base #: selection:res.currency,position:0 msgid "Before Amount" -msgstr "" +msgstr "Vorherige Menge" #. module: base #: field:res.request,act_from:0 @@ -14603,6 +15203,13 @@ msgid "" "marketing_campaign.\n" " " msgstr "" +"\n" +"Beispieldaten für das Modul \"Marketing-Kampagne\".\n" +"=============================================\n" +"\n" +"Legt für das Modul Marketingkampagne Beispieldaten an, z. B. Leads, " +"Kampagnen, Segmentierung\n" +" " #. module: base #: selection:ir.actions.act_window.view,view_mode:0 @@ -14617,8 +15224,8 @@ msgid "" "The Selection Options expression is must be in the [('key','Label'), ...] " "format!" msgstr "" -"Der Ausdruck für die Auswahloptionen muss in Form eines [('key','Label'), " -"...] Formats definiert sein!" +"Der Ausdruck für die Auswahloptionen muss in der Schreibweise " +"[('key','Label'), ...] vorliegen!" #. module: base #: view:ir.filters:0 @@ -14654,7 +15261,7 @@ msgid "" "workflow)" msgstr "" "Das Objekt, dass das Arbeitsfluss Signal empfangen soll (muss einen " -"definierten Arbeitsfluss haben)" +"zugeordneten Arbeitsfluss haben)" #. module: base #: model:ir.module.category,description:base.module_category_account_voucher @@ -14699,8 +15306,8 @@ msgid "" "template for a new language example)." msgstr "" "Dieser Assistent findet nicht übersetzte Begriffe, die Sie sodann manuell " -"übersetzen oder einen kompletten Export durchführen können( zB als Vorlage " -"für eine neue Sprache)" +"übersetzen oder einen kompletten Export durchführen können (z. B. als " +"Vorlage für eine neue Sprache/Übersetzung)" #. module: base #: model:ir.module.module,description:base.module_l10n_ch @@ -14770,7 +15377,7 @@ msgid "" "Expression, must be True to match\n" "use context.get or user (browse)" msgstr "" -"Der Ausdruck muss Wahr sein \n" +"Der Ausdruck muss für eine Übereinstimmung Wahr sein, \n" "verwenden Sie context.get oder user (browse)" #. module: base @@ -14781,7 +15388,8 @@ msgstr "Bulgarien" #. module: base #: view:publisher_warranty.contract.wizard:0 msgid "Publisher warranty contract successfully registered!" -msgstr "Wartungsvertrag des Herausgebers wurde erfolgreich registriert" +msgstr "" +"Gewährleistungsvertrag des Herausgebers wurde erfolgreich registriert" #. module: base #: model:res.country,name:base.ao @@ -14811,7 +15419,7 @@ msgstr "5. %y, %Y ==> 08, 2008" #. module: base #: model:res.partner.title,shortcut:base.res_partner_title_ltd msgid "ltd" -msgstr "Ltd" +msgstr "mbH" #. module: base #: field:res.log,res_id:0 @@ -14843,13 +15451,13 @@ msgstr "Iran" #: model:ir.actions.act_window,name:base.res_widget_user_act_window #: model:ir.ui.menu,name:base.menu_res_widget_user_act_window msgid "Widgets per User" -msgstr "Widgets je Benutzer" +msgstr "Anzeigeelemente je Benutzer" #. module: base #: model:ir.actions.act_window,name:base.action_publisher_warranty_contract_form #: model:ir.ui.menu,name:base.menu_publisher_warranty_contract msgid "Contracts" -msgstr "Wartungsvertrag" +msgstr "Verträge" #. module: base #: field:base.language.export,state:0 @@ -14893,6 +15501,28 @@ msgid "" "using it, otherwise it may crash.\n" " " msgstr "" +"\n" +"Ziel dieses Moduls ist die Qualitätsüberwachung von anderen Modulen.\n" +"============================================================\n" +"\n" +"Es legt einen Assistenten mit einer Liste aller Module von OpenERP an. Hier " +"können die\n" +"Module nach verschiedenen Kriterien beurteilt werden, so z. B. in Bezug auf " +"\n" +"- OpenERP-Programmier-Standards,\n" +"- Ausführungs-Geschwindigkeit, \n" +"- ...\n" +"\n" +"Dieses Modul liefert darüber hinaus einen allg. Rahmen für Ihre eigenen " +"Qualitätsprüfungen.\n" +"Für weitergehende Information können Programmierer gerne mal eine Blick in " +"die Datei\n" +"base_module_quality/README.txt werfen.\n" +"\n" +"WARNUNG: Dieses Modul kann als ZIP-Datei nicht funktionieren, Sie müssen es " +"zuvor \n" +"auspacken, sonst könnte es zu Abstürzen führen.\n" +" " #. module: base #: field:res.partner.bank,bank_name:0 @@ -14913,7 +15543,7 @@ msgstr "Irak" #: model:ir.module.category,name:base.module_category_association #: model:ir.ui.menu,name:base.menu_association msgid "Association" -msgstr "Verein" +msgstr "Verein/Gesellschaft" #. module: base #: model:ir.module.module,description:base.module_stock_no_autopicking @@ -14930,6 +15560,18 @@ msgid "" "supplier in the routing of the assembly operation.\n" " " msgstr "" +"\n" +"Dieses Modul bietet die zwischengeschaltete Kommissionierung um Rohstoffe zu " +"Fertigungsaufträgen zuzuführen.\n" +"=============================================================================" +"=================\n" +"\n" +"Ein Beispiel der Anwendung mag die Verwaltung einer Fertigung durch einen " +"Zulieferer sein (Sub-Contracting).\n" +"Um dies zu verwirklichen, wird das Fremdgefertigte Teil auf \"Ohne Auto-" +"Kommission\" gesetzt und setze die\n" +"Lieferantenadresse in das Routing der Fertigung ein.\n" +" " #. module: base #: view:ir.actions.server:0 @@ -14943,9 +15585,9 @@ msgid "" "are available. To add a new language, you can use the 'Load an Official " "Translation' wizard available from the 'Administration' menu." msgstr "" -"Die Standardsprache der Benutzerschnittstelle, wenn die entsprehcende " -"Übersetzung vorhanden ist. Mit dem Assistenen \"Lade offizielle " -"Übersetzung\" können Sie weitere Sprachen laden." +"Die Standardsprache der Benutzerschnittstelle, wenn die entsprechende " +"Übersetzungen vorhanden sind. Mit dem Assistenen \"Lade offizielle " +"Übersetzung\" können Sie weitere Sprachen hinzufügen." #. module: base #: model:ir.module.module,description:base.module_l10n_es @@ -14964,6 +15606,21 @@ msgid "" "Note: You should install the l10n_ES_account_balance_report module\n" "for yearly account reporting (balance, profit & losses).\n" msgstr "" +"\n" +"Spanische Buchhaltung (PGCE 2008)\n" +"=================================\n" +"\n" +"Legt die folgenenden Kontenrahmen an:\n" +" * Allg. spanischer Kontenrahmen 2008\n" +" * Allg. soanischer Kontenrahmen 2008 für kleine und mittlere " +"Unternehmen.\n" +"Es werden Vorlagen für Verkaufs- und Erwerbssteuern (Umsatz- und Vorsteuer) " +"eingerichtet.\n" +"Es werden die verschiedenen Steuerregularien eingerichtet\n" +"\n" +"Hinweis: Sie sollten das Modul l10n_ES_account_balance_report für " +"Jahresbilanz bzw.\n" +"Gewinn und Verlust -berechnung installieren.\n" #. module: base #: model:ir.model,name:base.model_ir_sequence_type @@ -14973,7 +15630,7 @@ msgstr "ir.sequence.type" #. module: base #: selection:base.language.export,format:0 msgid "CSV File" -msgstr "CSV Datei" +msgstr "CSV-Datei" #. module: base #: code:addons/base/res/res_company.py:154 @@ -14984,13 +15641,13 @@ msgstr "Telefon: " #. module: base #: field:res.company,account_no:0 msgid "Account No." -msgstr "Konto Nummer" +msgstr "Kontonummer" #. module: base #: code:addons/base/res/res_lang.py:187 #, python-format msgid "Base Language 'en_US' can not be deleted !" -msgstr "Basis Sprache 'en_US' kann nicht gelöscht werden !" +msgstr "Basis Sprache 'en_US' kann nicht gelöscht werden!" #. module: base #: selection:ir.model,state:0 @@ -15014,6 +15671,17 @@ msgid "" "plans.\n" " " msgstr "" +"\n" +"Das Basis-Modul für die Kostenstellen- bzw. Kostenartenartenrechnung und " +"das Bestellwesen.\n" +"=============================================================================" +"==\n" +"\n" +"Ermöglicht die Anlage mehrerer analytischer Kostenrechnungen. Diese bieten " +"Ihnen die Möglichkeit\n" +"eine Bestellposition auf mehrere Konten und Kostenrechnungen geeignet " +"aufzuteilen.\n" +" " #. module: base #: field:res.company,vat:0 @@ -15130,6 +15798,26 @@ msgid "" "state are scheduled with taking the phase's start date\n" " " msgstr "" +"\n" +"Langfristige Projekt-Verwaltung, mittels der Planung, Terminierung, " +"Ressourcenzuweisung verfolgt werden kann.\n" +"=============================================================================" +"=================\n" +"\n" +"Leistungen:\n" +" * Verwaltung großer Projekte.\n" +" * Festlegen verschiedener Projekt-Phasen.\n" +" * Phasen-Zeitplanung berechnen: Start- und Enddatum von Abschnitten " +"berechnen, die innerhalb des Projektes \n" +" im Entwurf, offen oder in Bearbeitung sind.\n" +" - Ist kein Projekt angegeben, so werden alle Entwürfe, offene oder " +"in Bearbeitung befindliche Projektphasen \n" +" terminiert.\n" +" * Aufgaben-Zeitplanung: Verwendung analog der Phasen-Zeitplanung.\n" +" * Aufgabentermine ermitteln: Alle Aufgaben im Entwurf, in Bearbeitung " +"oder Ausstehend werden auf den \n" +" Beginn der zugehörigen Projektphase abgeglichen.\n" +" " #. module: base #: model:ir.actions.act_window,name:base.action_workflow_activity_form @@ -15147,7 +15835,7 @@ msgstr "Produkte und Preislisten" #. module: base #: field:ir.actions.act_window,auto_refresh:0 msgid "Auto-Refresh" -msgstr "Autospeicherung..." +msgstr "Automatisch aktualisieren" #. module: base #: code:addons/base/ir/ir_model.py:74 @@ -15169,7 +15857,7 @@ msgstr "Spanische Buchführung (PGCE 2008)" #. module: base #: model:ir.module.module,shortdesc:base.module_stock_no_autopicking msgid "Picking Before Manufacturing" -msgstr "Lieferschein vor Produktion" +msgstr "Kommissionierung vor Fertigung" #. module: base #: model:res.country,name:base.wf @@ -15179,7 +15867,7 @@ msgstr "Wallis- und Futuna-Inseln" #. module: base #: help:multi_company.default,name:0 msgid "Name it to easily find a record" -msgstr "Der Datensatz kann über das Name Feld leicht gefunden werden" +msgstr "Benennen Sie den Datensatz um Ihn leichter wiederzufinden" #. module: base #: model:res.country,name:base.gr @@ -15235,7 +15923,7 @@ msgid "" "try again in a few minutes" msgstr "" "Die cron-Aufgabe wird derzeit ausgeführt und kann nicht verändert werden. " -"Versuchen Sie es in einigen Minuten wieder." +"Versuchen Sie es in einigen Minuten nochmal." #. module: base #: model:ir.module.module,description:base.module_product_expiry @@ -15252,6 +15940,17 @@ msgid "" "\n" "Used, for example, in food industries." msgstr "" +"\n" +"Verschiedene Daten zu Produkten und Fertigungslosen verfolgen.\n" +"========================================================\n" +"\n" +"Folgende Daten können hier verfolgt werden:\n" +" - Ende des Lebenszyklus\n" +" - Haltbarkeitsdatum\n" +" - Datum der Beseitigung/Entfernung\n" +" - Datum einer Warnung\n" +"\n" +"Wird z. B. in Lebensmittel-Branchen verwendet." #. module: base #: field:ir.exports.line,export_id:0 @@ -15267,7 +15966,7 @@ msgstr "Holländische Buchführung" #: field:res.bank,bic:0 #: field:res.partner.bank,bank_bic:0 msgid "Bank Identifier Code" -msgstr "Bank Identifikation" +msgstr "Bank Identifikations-Code" #. module: base #: model:res.country,name:base.tm @@ -15281,6 +15980,9 @@ msgid "" " OpenERP Web process view.\n" " " msgstr "" +"\n" +" OpenERP-Web-Prozessansicht.\n" +" " #. module: base #: model:ir.module.module,description:base.module_account_chart @@ -15293,6 +15995,9 @@ msgid "" msgstr "" "\n" "Minimalen Kontenplan entfernen.\n" +"=============================\n" +"\n" +"Deaktiviert einen minimalen Kontenplan/Kontenrahmen.\n" #. module: base #: code:addons/base/ir/ir_actions.py:653 @@ -15330,7 +16035,7 @@ msgstr "Fehler" #. module: base #: model:ir.module.module,shortdesc:base.module_base_crypt msgid "DB Password Encryption" -msgstr "" +msgstr "Datenbank-Verschlüsselung mittels Passwort" #. module: base #: help:workflow.transition,act_to:0 @@ -15340,7 +16045,7 @@ msgstr "Zielaktivität" #. module: base #: model:ir.module.module,shortdesc:base.module_account_check_writing msgid "Check writing" -msgstr "Scheck Schreibung" +msgstr "Ausstellung von Schecks" #. module: base #: model:ir.module.module,description:base.module_sale_layout @@ -15356,6 +16061,17 @@ msgid "" "\n" " " msgstr "" +"\n" +"Dieses Modul erweitert die Möglichkeiten bei der Auslegung von " +"Verkaufsaufträgen.\n" +"========================================================================\n" +"\n" +"Es bietet die Möglichkeit von\n" +" * Sortierung aller Auftragspositionen\n" +" * Hinzufügen von Titeln, Kommentaren, Zwischensummen\n" +" * Zeichnen von Trennlinien und Seitenumbrüchen\n" +"\n" +" " #. module: base #: view:base.module.update:0 @@ -15367,7 +16083,7 @@ msgstr "Aktualisieren" #. module: base #: model:ir.actions.report.xml,name:base.ir_module_reference_print msgid "Technical guide" -msgstr "Technisches Wissen" +msgstr "Technischer Leitfaden" #. module: base #: view:res.company:0 @@ -15397,17 +16113,17 @@ msgstr "Weihnachtsinseln" #. module: base #: model:ir.module.module,shortdesc:base.module_web_livechat msgid "Live Chat Support" -msgstr "Live Chat Unterstützung" +msgstr "Unterstützung für Live-Chat" #. module: base #: view:ir.actions.server:0 msgid "Other Actions Configuration" -msgstr "Andere Aktionen" +msgstr "Einstellungen für sonstige Aktionen" #. module: base #: selection:ir.module.module.dependency,state:0 msgid "Uninstallable" -msgstr "Uninstallierbar" +msgstr "Nicht installierbar" #. module: base #: model:ir.module.module,description:base.module_web_dashboard @@ -15416,6 +16132,10 @@ msgid "" " OpenERP Web dashboard view.\n" " " msgstr "" +"\n" +" Open'ERP-Web Pinnwand-Ansicht.\n" +"=================================\n" +" " #. module: base #: view:res.partner:0 @@ -15450,6 +16170,20 @@ msgid "" " * Salary Maj, ONSS, Withholding Tax, Child Allowance, ...\n" " " msgstr "" +"\n" +"Belgische Lohn- und Gehaltsabrechnung\n" +"==================================\n" +"\n" +" * Mitarbeiter-angaben\n" +" * Mitarbeiterverträge\n" +" * Reisepassgestützte Verträge\n" +" * Zulagen / Abzüge\n" +" * Einstellung von Grundlohn / Lohnerhöhungen / Nettobezüge\n" +" * Lohnbescheinigung\n" +" * Monatliche Lohnabrechnung\n" +" * Mit Urlaubsplanung integriert\n" +" * Lohn berücksichtigt: Maj, ONSS, Steuerabzüge, Kindergeld, ...\n" +" " #. module: base #: model:ir.model,name:base.model_partner_wizard_ean_check @@ -15464,7 +16198,7 @@ msgstr "Kunden" #. module: base #: sql_constraint:res.users:0 msgid "You can not have two users with the same login !" -msgstr "2 Benuzter können nicht den gleichen Login Code haben." +msgstr "Zwei Benuzter dürfen nicht den gleichen Benutzernamen verwenden!" #. module: base #: model:ir.model,name:base.model_res_request_history @@ -15474,12 +16208,12 @@ msgstr "res.request.history" #. module: base #: model:ir.model,name:base.model_multi_company_default msgid "Default multi company" -msgstr "Standard Multi Mandant" +msgstr "Standard für Mehrteilige Unternehmung" #. module: base #: view:res.request:0 msgid "Send" -msgstr "Sende" +msgstr "Versenden" #. module: base #: model:ir.module.module,description:base.module_process @@ -15495,6 +16229,16 @@ msgid "" "\n" " " msgstr "" +"\n" +"Dieses Modul zeigt die grundlegenden Prozesse der ausgewählten Module und " +"die Reihenfolge in der sie auftreten können.\n" +"=============================================================================" +"========================\n" +"\n" +"Hinweis: Dies trifft auf Module mit \"modulname_prozess_xml\" zu, so z.B. " +"für product/process/product_process_xml.\n" +"\n" +" " #. module: base #: field:res.users,menu_tips:0 @@ -15509,7 +16253,7 @@ msgstr "Quelle" #. module: base #: help:res.partner.address,partner_id:0 msgid "Keep empty for a private address, not related to partner." -msgstr "Leer nur bei Privat" +msgstr "Bei Privat-Kontakten, ohne Bezug zu Partnern, leer lassen." #. module: base #: model:res.country,name:base.vu @@ -15519,12 +16263,12 @@ msgstr "Vanuatu" #. module: base #: view:res.company:0 msgid "Internal Header/Footer" -msgstr "InternerHeader/Footer" +msgstr "Interne Kopf-/Fußzeile" #. module: base #: model:ir.module.module,shortdesc:base.module_crm msgid "CRM" -msgstr "CRM" +msgstr "Kundenverwaltung" #. module: base #: code:addons/base/module/wizard/base_export_language.py:59 @@ -15534,12 +16278,12 @@ msgid "" "may be uploaded to launchpad." msgstr "" "Speichere dieses Dokument als .tgz Datei. Dieses Archiv enthält UTF-8 %s " -"Dateien und können nach launchpad hochgeladen werden." +"Dateien und kann nach launchpad hochgeladen werden." #. module: base #: view:base.module.upgrade:0 msgid "Start configuration" -msgstr "Start Konfiguration" +msgstr "Einrichtung beginnen" #. module: base #: view:base.language.export:0 @@ -15549,7 +16293,7 @@ msgstr "_Export" #. module: base #: model:ir.module.module,shortdesc:base.module_account_followup msgid "Followup Management" -msgstr "Offene Posten Verwaltung" +msgstr "Mahnwesen" #. module: base #: model:ir.module.module,description:base.module_l10n_fr @@ -15560,6 +16304,11 @@ msgid "" "\n" "Credits: Sistheo Zeekom CrysaLEAD\n" msgstr "" +"\n" +"Dieses Modul enthält die französichen Kontenrahmen für OpenERP.\n" +"==========================================================\n" +"\n" +"Credits: Sistheo Zeekom CrysaLEAD\n" #. module: base #: selection:base.language.install,lang:0 @@ -15579,7 +16328,7 @@ msgstr "Dominikanische Republik" #. module: base #: selection:base.language.install,lang:0 msgid "Serbian (Cyrillic) / српски" -msgstr "Serbisch (Cyrillic) / српски" +msgstr "Serbisch (Kyrillisch) / српски" #. module: base #: code:addons/orm.py:2527 @@ -15588,8 +16337,8 @@ msgid "" "Invalid group_by specification: \"%s\".\n" "A group_by specification must be a list of valid fields." msgstr "" -"Fehlerhafte Spezifikation der Gruppierung: \"%s\".\n" -"Eine group_by Spezifikation sollte eine gültige Liste mit Feldern aufweisen." +"Fehlerhafte Angabe der Gruppierung: \"%s\".\n" +"Eine \"Gruppiere...\"-Angabe muss eine gültige Liste mit Feldern aufweisen." #. module: base #: selection:ir.mail_server,smtp_encryption:0 @@ -15600,7 +16349,7 @@ msgstr "TLS (STARTTLS)" #: help:ir.actions.act_window,usage:0 msgid "Used to filter menu and home actions from the user form." msgstr "" -"Wird verwendet um Menu und Startseiten des Benutzer Formulars zu filtern" +"Wird verwendet um Menu und Startseiten des Benutzer-Formulars zu filtern" #. module: base #: model:res.country,name:base.sa @@ -15611,12 +16360,12 @@ msgstr "Saudi Arabien" #: help:res.company,rml_header1:0 msgid "Appears by default on the top right corner of your printed documents." msgstr "" -"Scheint standardmäßig im oberen rechten Eck der gedruckten Berichte auf." +"Erscheint standardmäßig im oberen, rechten Eck von gedruckten Berichten." #. module: base #: model:ir.module.module,shortdesc:base.module_fetchmail_crm_claim msgid "eMail Gateway for CRM Claim" -msgstr "" +msgstr "EMail-Schnittstelle für das Beschwerdemodul in der Kundenverwaltung" #. module: base #: help:res.partner,supplier:0 @@ -15625,18 +16374,19 @@ msgid "" "people will not see it when encoding a purchase order." msgstr "" "Hake diese Box an falls Ihr Partner Lieferant ist, Falls dieser Haken nicht " -"gesetzt wird, wird der Einkäufer diese Position nicht in Suchlisten finden." +"gesetzt wird, wird der Einkäufer diesen Partner bei einer Lieferantensuche " +"(Lieferanten-Auswahlfeld) nicht finden." #. module: base #: field:ir.actions.server,trigger_obj_id:0 #: field:ir.model.fields,relation_field:0 msgid "Relation Field" -msgstr "erforderliches Feld" +msgstr "Beziehungs-Feld" #. module: base #: view:res.partner.event:0 msgid "Event Logs" -msgstr "Ereignisse Aufzeichnungen" +msgstr "Ereignissprotokoll" #. module: base #: code:addons/base/module/wizard/base_module_configuration.py:38 @@ -15647,7 +16397,7 @@ msgstr "System Konfiguration erledigt" #. module: base #: view:ir.actions.server:0 msgid "Create / Write / Copy" -msgstr "Erzeugen / Schreiben / Kopieren" +msgstr "Anlegen / Schreiben / Kopieren" #. module: base #: field:workflow.triggers,instance_id:0 @@ -15658,7 +16408,7 @@ msgstr "Zielobjekt" #: field:ir.actions.act_window,multi:0 #: field:ir.actions.wizard,multi:0 msgid "Action on Multiple Doc." -msgstr "Aktion für mehrfache Dokumente" +msgstr "Aktion für mehrere Dokumente" #. module: base #: view:base.language.export:0 @@ -15673,7 +16423,7 @@ msgstr "Exportiere Übersetzungen" #. module: base #: field:ir.actions.report.xml,report_xml:0 msgid "XML path" -msgstr "XML" +msgstr "XML-Pfad" #. module: base #: help:ir.sequence,implementation:0 @@ -15682,9 +16432,9 @@ msgid "" "later is slower than the former but forbids any gap in the sequence (while " "they are possible in the former)." msgstr "" -"2 Arten von Sequenzen werden unterstützt. \r\n" -"* Standard: schneller mit Lücken.\r\n" -"* Ohne Lücken: etwas langsamer, aber erstellt lückenlose Nummerierung." +"2 Arten von Folgen werden unterstützt. \r\n" +"* Standard: Schneller jedoch mit Lücken.\r\n" +"* Ohne Lücken: Etwas langsamer, erstellt aber lückenlose Nummerierung." #. module: base #: model:res.country,name:base.gn @@ -15762,6 +16512,16 @@ msgid "" "After installing the module, it adds a menu to define a custom report in\n" "the Administration / Customization / Reporting menu.\n" msgstr "" +"\n" +"Dieses Modul ermöglich die Erstellung von Statistiken zu verschiedenen " +"Objekten.\n" +"====================================================================\n" +"\n" +"Es ist ein SQL-Abfrage-Werkzeug mit Datenanzeige für Endanwender.\n" +"\n" +"Nach der Installation des Moduls wird ein Menüpunkt in\n" +"Einstellungen / Personalisierung / Berichtswesen\n" +"mit der Bezeichnung \"Individuelle Berichte\" hinzugefügt.\n" #. module: base #: model:ir.module.module,shortdesc:base.module_report_designer @@ -15796,16 +16556,19 @@ msgid "" " OpenERP Web calendar view.\n" " " msgstr "" +"\n" +" OpenERP-Web-Kalenderformular.\n" +" " #. module: base #: model:ir.ui.menu,name:base.menu_crm_config_lead msgid "Leads & Opportunities" -msgstr "Kontakte und Chancen" +msgstr "Leads und Chancen" #. module: base #: selection:base.language.install,lang:0 msgid "Romanian / română" -msgstr "Romanian / română" +msgstr "Romänisch / română" #. module: base #: view:res.log:0 @@ -15822,7 +16585,7 @@ msgstr "und" #: help:ir.values,res_id:0 msgid "" "Database identifier of the record to which this applies. 0 = for all records" -msgstr "" +msgstr "Kennung des Datensatzes auf den dies zutrifft. 0 = alle Datensatze" #. module: base #: field:ir.model.fields,relation:0 @@ -15854,7 +16617,7 @@ msgstr "ir.actions.act_window" #. module: base #: field:ir.rule,perm_create:0 msgid "Apply For Create" -msgstr "Setze Erzeugungsberechtigung" +msgstr "Anwenden zur Anlage" #. module: base #: model:res.country,name:base.vi @@ -15875,7 +16638,7 @@ msgstr "Wechselkurs" #: field:workflow,osv:0 #: field:workflow.instance,res_type:0 msgid "Resource Object" -msgstr "Ressource Object" +msgstr "Ressourcen-Objekt" #. module: base #: model:ir.module.module,shortdesc:base.module_crm_helpdesk @@ -15899,7 +16662,7 @@ msgstr "" #. module: base #: field:ir.ui.view,field_parent:0 msgid "Child Field" -msgstr "(Unter-) Konto" +msgstr "(Unter-) Feld" #. module: base #: view:ir.rule:0 @@ -15933,8 +16696,8 @@ msgid "" "Lets you install various interesting but non-essential tools like Survey, " "Lunch and Ideas box." msgstr "" -"Optionale Erweiterung interessanter, aber nicht zwingend zu installierender " -"Applikationen, wie z.B. Umfragen, Vorschlagswesen etc." +"Optionale Erweiterung interessanter, aber nicht notwendiger Module, wie z.B. " +"Umfragen, Vorschlagswesen etc." #. module: base #: selection:ir.module.module,state:0 @@ -15965,6 +16728,28 @@ msgid "" "Print product labels with barcode.\n" " " msgstr "" +"\n" +"Dies ist das Grundmodul für die Verwaltung von Produkten und Preislisten in " +"OpenERP.\n" +"========================================================================\n" +"\n" +"Produkte können Varianten haben, verschieden Preisgestaltungen besitzen, " +"Lieferanten-\n" +"Information erhalten, Beschaffungsdetails, Maßeinheiten, Verpackungen und " +"andere\n" +"Eigenschaften zugewiesen bekommen.\n" +"\n" +"Preislisten unterstützen:\n" +" * Mehrstufige Rabatte (nach Produktn Kategorie, Menge)\n" +" * Preisberechnung beruht auf versch. Kriterien:\n" +" - Andere Preisliste,\n" +" - Anschaffungskosten,\n" +" - Listen-/Katalog-Preis,\n" +" - Lieferantenpreis, ...\n" +"\n" +"Preislisten-Einstellungen je Produkt und Partner,\n" +"Ettikettendruck mitsamt Barcode (Strichcode).\n" +" " #. module: base #: report:ir.module.reference.graph:0 @@ -15974,7 +16759,7 @@ msgstr "Sicht :" #. module: base #: field:ir.model.fields,view_load:0 msgid "View Auto-Load" -msgstr "Ansicht Autorefresh" +msgstr "Autom. Öffnen des Ansichtsformulars" #. module: base #: code:addons/base/ir/ir_model.py:264 @@ -16006,12 +16791,12 @@ msgstr "Web Icon Datei" #: view:base.module.upgrade:0 #: model:ir.ui.menu,name:base.menu_view_base_module_upgrade msgid "Apply Scheduled Upgrades" -msgstr "Starte Installation" +msgstr "Starte geplante Aktualsierungen" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_journal msgid "Invoicing Journals" -msgstr "Eingangsrechnungsjournale" +msgstr "Rechnungsbericht" #. module: base #: selection:base.language.install,lang:0 @@ -16035,7 +16820,7 @@ msgid "" "Supported file formats: *.csv (Comma-separated values) or *.po (GetText " "Portable Objects)" msgstr "" -"Unterstützte Dateiformate: *.csv (Comma-separated values) or *.po (GetText " +"Unterstützte Dateiformate: *.csv (Comma-separated values) oder *.po (GetText " "Portable Objects)" #. module: base @@ -16046,7 +16831,7 @@ msgid "" "these groups: %s." msgstr "" "Sie können diesen Beleg (%s) nicht löschen. Stellen Sie sicher, dass Sie als " -"Benutzer der folgenden Gruppe angehören: %s." +"Benutzer einer der folgenden Gruppen angehören: %s." #. module: base #: model:ir.module.module,description:base.module_web_livechat @@ -16058,6 +16843,12 @@ msgid "" "Add \"Support\" button in header from where you can access OpenERP Support.\n" " " msgstr "" +"\n" +"Bietet Unterstzung für Live-Chat für Vertragnehmer mit Wartungsvertrag.\n" +"\n" +"Fügt den \"Support\"-Schalter in den Kopf ein, über den Sie OpenERP-" +"Unterstützung erhalten.\n" +" " #. module: base #: model:ir.model,name:base.model_base_module_configuration @@ -16072,6 +16863,10 @@ msgid "" " This module provides the core of the OpenERP web client.\n" " " msgstr "" +"\n" +" OpenERP-Web-Kernmodul.\n" +" Dieses Modul liefert die Hauptbestandteile des OpenERP-Web-Klienten.\n" +" " #. module: base #: sql_constraint:res.country:0 @@ -16082,7 +16877,7 @@ msgstr "Der Name des Landes muss eindeutig sein!" #: field:base.language.export,name:0 #: field:ir.attachment,datas_fname:0 msgid "Filename" -msgstr "Dateinamen" +msgstr "Dateiname" #. module: base #: field:ir.model,access_ids:0 @@ -16098,7 +16893,7 @@ msgstr "Slowakische Republik" #. module: base #: model:ir.ui.menu,name:base.publisher_warranty msgid "Publisher Warranty" -msgstr "Wartungsvertrag" +msgstr "Gewährleistung des Herausgebers" #. module: base #: model:res.country,name:base.aw @@ -16129,11 +16924,24 @@ msgid "" "and decide on their status as they evolve.\n" " " msgstr "" +"\n" +"Dieses Modul stellt eine Projektverwaltung für Probleme/Fehler zur " +"Verfügung.\n" +"==================================================================\n" +"\n" +"OpenERP ermöglicht die Verwaltung von in Projekten möglicherweise " +"aufkommenden\n" +"Problemen, wie z. B. Systemfehler, Beschwerden oder Materialfehler. Eine " +"Listenansicht\n" +"erlaubt dem Verwalter die Fälle zu sichten, diese zuzuweisen und über deren " +"Status\n" +"im Laufe der Entwicklung zu wachen und daraus Entscheidungen zu treffen.\n" +" " #. module: base #: field:res.groups,full_name:0 msgid "Group Name" -msgstr "Gruppe Bezeichnung" +msgstr "Gruppenbezeichnung" #. module: base #: model:res.country,name:base.bh @@ -16195,7 +17003,7 @@ msgstr "" #. module: base #: view:res.partner.address:0 msgid "Search Contact" -msgstr "Suche Kontakt" +msgstr "Suche Ansprechpartner" #. module: base #: view:ir.attachment:0 @@ -16238,7 +17046,7 @@ msgstr "Wartungsvertrag des Herausgebers" #. module: base #: selection:base.language.install,lang:0 msgid "Bulgarian / български език" -msgstr "Bulgarian / български език" +msgstr "Bulgarisch / български език" #. module: base #: model:ir.ui.menu,name:base.menu_aftersale @@ -16258,7 +17066,7 @@ msgstr "Ausführen" #. module: base #: model:ir.module.module,shortdesc:base.module_caldav msgid "Share Calendar using CalDAV" -msgstr "Kalender mit CalDAV freigeben" +msgstr "Kalender mit CalDAV veröffentlichen" #. module: base #: field:ir.actions.act_window,limit:0 @@ -16270,8 +17078,7 @@ msgstr "Limit" msgid "" "The group that a user must have to be authorized to validate this transition." msgstr "" -"Die Gruppe der ein Benutzer angehören muss, um diese Transition zu " -"validieren." +"Die Gruppe der ein Benutzer angehören muss, um diesen Ablauf zu genehmigen." #. module: base #: code:addons/orm.py:791 @@ -16288,7 +17095,7 @@ msgstr "Jamaika" #: field:res.partner,color:0 #: field:res.partner.address,color:0 msgid "Color Index" -msgstr "Farb Index" +msgstr "Farbkennzeichnung" #. module: base #: model:ir.actions.act_window,help:base.action_partner_category_form @@ -16298,11 +17105,11 @@ msgid "" "categories have a hierarchy structure: a partner belonging to a category " "also belong to his parent category." msgstr "" -"Verwaltung der Partner Kategorien, um eine bessere Klassifizierung für die " -"Verfolgung von Vorgängen und zu Analyse und Suchzwecken zu ermöglichen. Ein " -"Partner kann dabei mehreren Kategorien zugewiesen werden. Kategorien haben " -"üblicherweise auch eine hierachische Struktur. Dabei gilt, daß eine direkt " -"zugeordnete Kategorie i.d.R. auch selbst einer Hauptkategorie zugeordnet ist." +"Verwaltung der Partnerkategorien, um eine Klassifizierung für die Verfolgung " +"von Vorgängen, Analysezwecke und Suche zu vereinfachen. Ein Partner kann " +"dabei mehreren Kategorien zugewiesen werden. Kategorien haben üblicherweise " +"auch eine hierachische Struktur. Dabei folgt aus einer Zugeordnung zu einer " +"Kategorie auch die Zuordnung zu übergeordneten Kategorien." #. module: base #: model:res.country,name:base.az @@ -16319,7 +17126,7 @@ msgstr "Warnung" #. module: base #: model:ir.module.module,shortdesc:base.module_edi msgid "Electronic Data Interchange (EDI)" -msgstr "" +msgstr "Elektronischer Datenaustausch (EDI)" #. module: base #: model:ir.module.category,name:base.module_category_tools @@ -16388,16 +17195,57 @@ msgid "" "\n" " " msgstr "" +"\n" +"EMail-Vorlagen (vereinfachte Version des Originals \"Power Email\" von " +"Openlabs)\n" +"==================================================================\n" +"\n" +"Läßt Sie vollständige EMail-Vorlagen in Bezug auf jedes OpenERP-Dokument " +"(Verkaufaufträge,\n" +"Rechnungen, ...) inklusive Versender, Empfänger, Thema Textkörper (HTML wie " +"auch Normaltext).\n" +" Sie können auch automatisch Dateien an die daraus erstellten Dokumente " +"anhängen lassen.\n" +"\n" +"Bei fortgeschrittener Anwendung können die Vorlagen auch dynamische " +"Dokumentattribute \n" +"enthalten. Zum Beispiel können Sie den Landesnamen des Partners einsetzen, " +"wenn dieser \n" +"angeschrieben wird, zugleich eine Vorgabe angebend falls diese Angabe mal " +"nicht vorliegt.\n" +"Jede Vorlage hat einen Assistenten, der Ihnen beim Einsatz dieser " +"dynamischen Werte \n" +"bei Seite steht.\n" +"\n" +"Wenn Sie diese Option einschalten, der Zusammenstellungs-Assistent auch in " +"der Seitenleiste\n" +"erscheinen, wenn aus dieser Vorlage erstellte Dokumente geöffnet sind. Somit " +"kann schnell \n" +"auch eine Vorlagenbasierte EMail ggf. nach Prüfung und Anpassung erstellt " +"und versandt \n" +"werden. Dieser Kompositions-Assistent kann auch zu einem Massen-Mail-System " +"verwandelt\n" +"werden, wenn er auf mehrere Dokumente zugleich angewandt wird.\n" +"\n" +"Diese EMail-Vorlagen sind auch das Herz des Marketing-Kampagnen-Systems " +"(siehe dort),\n" +"sofern Sie Dokumenten-spezifisch größere Kampagnen automatisieren müssen.\n" +"\n" +"Technischer Hinweis: Es wurde nur das Vorlagen-System des Originals \"Power-" +"EMail\" \n" +"von Openlabs übernommen.\n" +"\n" +" " #. module: base #: selection:base.language.install,lang:0 msgid "Czech / Čeština" -msgstr "Czech / Čeština" +msgstr "Tschechisch / Čeština" #. module: base #: model:ir.module.category,name:base.module_category_generic_modules msgid "Generic Modules" -msgstr "Generische Module" +msgstr "Allgemeine Module" #. module: base #: model:ir.actions.act_window,help:base.action_partner_supplier_form @@ -16407,8 +17255,8 @@ msgid "" "uncheck the 'Suppliers' filter button in order to search in all your " "partners, including customers and prospects." msgstr "" -"Alle Lieferantendaten können in dem Lieferantenformular bearbeitet " -"werden.(FiBu, Mails, Meetings, Einkäufe,...). Nach Deaktivierung des " +"Alle Lieferantendaten können in dem Lieferantenformular bearbeitet werden. " +"(FiBu, Mails, Termine, Einkäufe,...). Nach Deaktivierung des " "Lieferantenfilters werden alle Partner angezeigt." #. module: base @@ -16435,17 +17283,35 @@ msgid "" "to set up a management by affair.\n" " " msgstr "" +"\n" +"Dieses Modul setzt ein Zeitnachweis-System um.\n" +"========================================\n" +"\n" +"Jeder Mitarbeiter kann in verschiedenen Projekten eingebrachte Zeit " +"einpflegen und verfolgen.\n" +"Einem Projekt entspricht dabei ein analytisches Konto, eingesetzte Zeit " +"verursacht nun Projekt-\n" +"kosten die auf dieses analytische Konto verbucht werden.\n" +"\n" +"Einige Berichte und Auswertungen zur Zeiten und Mitarbeitern werden " +"verfügbar gemacht.\n" +"\n" +"Es ist vollständig integriert in die \"Kostenstellenrechnung\" und ermöglich " +"den Ansatz der\n" +"Projektbezogenen Kostenverwaltung.\n" +" " #. module: base #: help:ir.mail_server,smtp_port:0 msgid "SMTP Port. Usually 465 for SSL, and 25 or 587 for other cases." msgstr "" -"SMTP Port. normalerweise 465 für SSL, und 25 oder 587 für alle anderen." +"SMTP Port. Normalerweise 465 für SSL, und 25 oder 587 in allen anderen " +"Fällen." #. module: base #: view:ir.sequence:0 msgid "Day of the week (0:Monday): %(weekday)s" -msgstr "Tag der Woche (0:Monday): %(weekday)s" +msgstr "Wochentag (0:Monday): %(weekday)s" #. module: base #: model:res.country,name:base.ck @@ -16508,6 +17374,45 @@ msgid "" " * Opportunities by Stage (graph)\n" " * Planned Revenue by Stage and User (graph)\n" msgstr "" +"\n" +"Das allgemeine Kundenverwaltungsmodul (CRM) von OpenERP.\n" +"=====================================================\n" +"\n" +"Dieses System ermöglicht einer Gruppe von Menschen (Mitarbeiter, Abteilung) " +"die\n" +"intilligente, effiziente Verwaltung von Vorverhandlungen (Leads), " +"Gelegenheiten\n" +"(opportunities), Terminen (meeting), Anrufen (phonecall), ...\n" +"Es werden Hauptaufgaben, wie z. B. Kommunikation, Erfassung, Pririsierung,\n" +"Zuständigkeit, Problemklärung und Mitteilungsdienste umgesetzt.\n" +"\n" +"OpenERP stellt dabei sicher, dass alle Fälle durch Benutzer, Kunden und " +"Lieferanten\n" +"erfolgreich nachvollzogen werden können. Es werden automatisch Erinnerungen\n" +"verschickt, Anfragen werden eskaliert (an Vorgesetzte hoch-delegiert), " +"besondere \n" +"Aufgaben und Methoden ausgelöst und viele andere Aktionen, die auch von " +"Ihren\n" +"Unternehmensregeln abhängen, ausgelöst.\n" +"\n" +"Das schönste an diesem System ist die Tatsache, dass der Anwender nicht " +"besonderes \n" +"tun muss. Dieser sendet nur eine EMail an die Anfrageverfolgung. OpenERP " +"kümmert\n" +"sich um eine dankende Antwort und die automatische Weiterleitung an das " +"richtige \n" +"Personal. Das System stellt darüber hinaus sicher, dass auch künftiger " +"Schriftverkehr\n" +"an den richtigen Empfänger gelangt.\n" +"\n" +"Das Kundenverwaltungsmodul enthält eine EMail-Schnittstelle zur " +"Synchrnonisierung\n" +"von empfangenen Mails mit OpenERP.\n" +"\n" +"Es wird eine Pinnwand der Kundenverwaltung angelegt. Sie enthält:\n" +" * Gelegenheiten nach Kategorie (Diagramm)\n" +" * Gelegenheiten nach Entwicklungsstand (Diagramm)\n" +" * Plan-Umsätze nach Entwicklung und Bearbeiter (Diagramm)\n" #. module: base #: model:ir.module.category,description:base.module_category_accounting_and_finance @@ -16515,6 +17420,10 @@ msgid "" "Helps you handle your accounting needs, if you are not an accountant, we " "suggest you to install only the Invoicing." msgstr "" +"Unterstützt Sie bei Ihrem Bedarf an Finanzbuchhaltung. Sind Sie kein " +"Buchhalten, so empfehlen wir Ihnen\r\n" +"(sofern wegen anderer Abhängigkeiten möglich) nur das Rechnungswesen zu " +"installieren." #. module: base #: model:ir.module.module,shortdesc:base.module_plugin_thunderbird @@ -16551,11 +17460,14 @@ msgid "" " OpenERP Web test suite.\n" " " msgstr "" +"\n" +" OpenERP-Web Testanwendungen.\n" +" " #. module: base #: view:ir.values:0 msgid "Action Bindings/Defaults" -msgstr "Aktion Bindungen / Standardwerte" +msgstr "Aktionen-Bindungen / -Standardwerte" #. module: base #: view:ir.rule:0 @@ -16563,8 +17475,8 @@ msgid "" "1. Global rules are combined together with a logical AND operator, and with " "the result of the following steps" msgstr "" -"1. Allgemeine Regeln werden mit logisch UND verknüpft und dann mit den " -"Ergebnissen der folgenden Schritte" +"1. Globale Regeln werden untereinander und mit den Ergebnissen der folgenden " +"Schritte logisch UND-verknüpft" #. module: base #: view:res.partner:0 @@ -16585,7 +17497,7 @@ msgstr "Gruppen auswählen" #. module: base #: view:res.lang:0 msgid "%X - Appropriate time representation." -msgstr "%X - Erwartete Zeitpräsentation." +msgstr "%X - Angebrachte Zeitpräsentation." #. module: base #: selection:base.language.install,lang:0 @@ -16600,11 +17512,10 @@ msgid "" "1,06,500;[1,2,-1] will represent it to be 106,50,0;[3] will represent it as " "106,500. Provided ',' as the thousand separator in each case." msgstr "" -"Das Trennzeichenformat sollte sein wie [,n] wenn 0 < n :startend von " -"Einheitenziffer.-1 wird die Trennung anzeigen. Z.B. [3,2,-1] wird " -"repräsentiert 106500 muss sein1,06,500;[1,2,-1] will represent it to be " -"106,50,0;[3] will represent it as 106,500. Provided ',' as the thousand " -"separator in each case." +"Das Trennzeichenformat sollte [,n] entsprechen mit 0 < n, beginnenend bei " +"Einer-Stelle. -1 beendet die Trennung. Z. B. [3,2,-1] bei 106500 entspricht " +"1,06,500; [1,2,-1] würde dann 106,50,0 ergeben; [3] wird 106,500 daraus " +"erstellen. Vorausgesetzt ',' sei jeweils der Tausender-Trenner." #. module: base #: field:ir.module.module,auto_install:0 @@ -16620,12 +17531,12 @@ msgstr "Japan" #: code:addons/base/ir/ir_model.py:357 #, python-format msgid "Can only rename one column at a time!" -msgstr "Es kann lediglich eine Spalte gleichzeitig umbenannt werden!" +msgstr "Es kann jeweils nur eine Spalte umbenannt werden!" #. module: base #: selection:ir.translation,type:0 msgid "Wizard Button" -msgstr "Assistent Button" +msgstr "Assistent-Taste" #. module: base #: selection:ir.translation,type:0 @@ -16661,13 +17572,51 @@ msgid "" "Leads.\n" " " msgstr "" +"\n" +"Dieses Modul stellt Automatismen für Lead-Managent aus Marketingmassnahmen " +"zur Verfügung. \n" +"=============================================================================" +"====\n" +"\n" +"(Tatsächlich können Kampagnen auf jeder Ressource aufgebaut werden, nicht " +"nur an Kundenbeziehungen) \n" +"\n" +"Kampagnen sind dynamisch und Mehrspurig. Die Durchführung sieht " +"folgendermassen aus:\n" +" * Entwerfen Sie Marketingkampagnen wie Arbeitsabläufe, einschl. EMail-" +"Vorlagen zum Versenden,\n" +" Berichte zum Versenden per EMail und zum Drucken, Individuelle " +"Aktionen, ...\n" +" * Festlegen der Eingangs-Segmentierung, die den Zugang der Ressource in " +"die Kampagne steuert\n" +" (z. B. potentielle Kunden aus bestimmten Ländern, ...)\n" +" * Lassen Sie die Kampagne als Simulation laufen, testen Sie diese in " +"Echtzeit oder im Schnelldurchlauf\n" +" und treffen Sie Maßnahmen für eine Feinabstimmung.\n" +" * Sie können die tatsächliche Kampagne auch im Handbetrieb starten, bei " +"dem jeder Schritt einzeln \n" +" bestätigt (freigegeben) werden muss.\n" +" * Schließlich starten Sie Ihre Kampagne und beobachten die Statistiken " +"während die Kampagne alles\n" +" voll-automatisch durchführt.\n" +"\n" +"Auch während einer laufenden Kampagne können Sie selbstverständlich noch " +"Feinabstimmung vornehmen,\n" +"die Zugangs-Segmente verändern und Abläufe anpassen...\n" +"\n" +"Hinweis: Sollten Sie Beispieldaten benötigen, können Sie auf das " +"\"marketing_campaign_crm_demo_module\" \n" +"zurückgreifen; diese Beispieldaten hängen jedoch auch vom Kunden-Modul wie " +"auch der Leads-Verwaltung\n" +"ab und installieren diese ggf. auch.\n" +" " #. module: base #: selection:ir.actions.act_window.view,view_mode:0 #: selection:ir.ui.view,type:0 #: selection:wizard.ir.model.menu.create.line,view_type:0 msgid "Graph" -msgstr "Graphik Verlauf" +msgstr "Diagramm" #. module: base #: model:ir.model,name:base.model_ir_actions_server @@ -16687,12 +17636,12 @@ msgstr "Kanadische Buchführung" #: model:ir.ui.menu,name:base.menu_ir_actions_todo_form #: model:ir.ui.menu,name:base.next_id_11 msgid "Configuration Wizards" -msgstr "Installationsassistent" +msgstr "Installationsassistenten" #. module: base #: field:res.lang,code:0 msgid "Locale Code" -msgstr "LOCALE Code" +msgstr "Landesschlüssel (locale)" #. module: base #: field:workflow.activity,split_mode:0 @@ -16707,7 +17656,7 @@ msgstr "Beachten Sie, dass dieser Vorgang einige Zeit dauern kann." #. module: base #: model:ir.ui.menu,name:base.menu_localisation msgid "Localisation" -msgstr "Partner Herkunft" +msgstr "Landestypische Einstellungen" #. module: base #: field:ir.sequence,implementation:0 @@ -16734,22 +17683,23 @@ msgstr "Ausführung" #: view:ir.values:0 #: field:workflow.transition,condition:0 msgid "Condition" -msgstr "Bedingung" +msgstr "Zustand" #. module: base #: help:res.currency,rate:0 msgid "The rate of the currency to the currency of rate 1." msgstr "" +"Der Kurs der Währung verglichen mit der Vergleichswährung zum Kurs von 1" #. module: base #: field:ir.ui.view,name:0 msgid "View Name" -msgstr "Ansicht Bezeichnung" +msgstr "Ansichtsbezeichnung" #. module: base #: model:ir.module.module,shortdesc:base.module_document_ftp msgid "Shared Repositories (FTP)" -msgstr "Gemeinsames Verzeichnis (FTP)" +msgstr "Gemeinsame Verzeichnisse (FTP)" #. module: base #: model:ir.model,name:base.model_res_groups @@ -16783,7 +17733,7 @@ msgstr "Kroatien" #. module: base #: field:ir.actions.server,mobile:0 msgid "Mobile No" -msgstr "Mobile" +msgstr "Handy-Nr." #. module: base #: model:ir.actions.act_window,name:base.action_partner_by_category @@ -16792,7 +17742,7 @@ msgstr "Mobile" #: model:ir.ui.menu,name:base.menu_partner_category_form #: view:res.partner.category:0 msgid "Partner Categories" -msgstr "Partner Kategorien" +msgstr "Partnerkategorien" #. module: base #: view:base.module.upgrade:0 @@ -16802,12 +17752,12 @@ msgstr "Systemaktualisierung" #. module: base #: selection:ir.translation,type:0 msgid "Wizard Field" -msgstr "Assistent Datenfeld" +msgstr "Assistent.Datenfeld" #. module: base #: help:ir.sequence,prefix:0 msgid "Prefix value of the record for the sequence" -msgstr "Vorlauf (Prefix) einer Sequenz" +msgstr "Präfix einer Folgen" #. module: base #: model:res.country,name:base.sc @@ -16828,7 +17778,7 @@ msgstr "Bankkonten" #: field:ir.model,modules:0 #: field:ir.model.fields,modules:0 msgid "In modules" -msgstr "In Modul" +msgstr "In Modulen" #. module: base #: model:res.country,name:base.sl @@ -16839,7 +17789,7 @@ msgstr "Sierra Leone" #: view:res.company:0 #: view:res.partner:0 msgid "General Information" -msgstr "Grundinformation" +msgstr "Allgemeine Informationen" #. module: base #: model:res.country,name:base.tc @@ -16849,18 +17799,18 @@ msgstr "Turks- und Caicosinseln" #. module: base #: model:ir.module.module,shortdesc:base.module_fetchmail_project_issue msgid "eMail Gateway for Project Issues" -msgstr "" +msgstr "EMail-Schnittstelle zu Projektprobleme" #. module: base #: field:res.partner.bank,partner_id:0 msgid "Account Owner" -msgstr "Konto Inhaber" +msgstr "Konto-Inhaber" #. module: base #: code:addons/base/res/res_users.py:270 #, python-format msgid "Company Switch Warning" -msgstr "Unternehmenswechsel Warnhinweis" +msgstr "Warnhinweis zum Unternehmenswechsel" #. module: base #: model:res.country,name:base.ge @@ -16872,19 +17822,22 @@ msgstr "Georgien" msgid "" "Helps you manage your manufacturing processes and generate reports on those " "processes." -msgstr "Management Ihrer Fertigungsprozesse und Erstellung von Auswertungen" +msgstr "" +"Unterstützt Sie bei Ihren Produktionsprozessen und stellt die Berichte für " +"diese Prozesse zur Verfügung." #. module: base #: help:ir.sequence,number_increment:0 msgid "The next number of the sequence will be incremented by this number" -msgstr "Die nächste Nummer dieser Sequenz wir um diese Zahl erhöht." +msgstr "Die nächste Zahl dieser Folge wird um diesen Wert erhöht." #. module: base #: code:addons/orm.py:341 #, python-format msgid "Wrong ID for the browse record, got %r, expected an integer." msgstr "" -"Falsche ID für den Datensatz, erhalte %r, erwarte aber einen integer Wert" +"Falsche Kennung für den gesuchten Datensatz, erhielt %r, erwartet wurde ein " +"ganzzahliger Wert." #. module: base #: field:res.partner.address,function:0 @@ -16895,7 +17848,7 @@ msgstr "Funktion" #. module: base #: view:res.widget:0 msgid "Search Widget" -msgstr "Such Widget" +msgstr "Anzeigeelement für Suche" #. module: base #: model:ir.module.category,description:base.module_category_customer_relationship_management @@ -16903,6 +17856,12 @@ msgid "" "Manage relations with prospects and customers using leads, opportunities, " "requests or issues." msgstr "" +"Verwalten Sie Ihre Beziehungen zu Interessenten und Kunden. Nutzen Sie dabei " +"\r\n" +"Leads = Vorverhandlungen, \r\n" +"Opportunities = Gelegenheiten, \r\n" +"Requests = Anfragen oder \r\n" +"Issues = Problembearbeitungen." #. module: base #: selection:res.partner.address,type:0 @@ -16913,7 +17872,7 @@ msgstr "Lieferung" #: model:res.partner.title,name:base.res_partner_title_pvt_ltd #: model:res.partner.title,shortcut:base.res_partner_title_pvt_ltd msgid "Corp." -msgstr "GmbH" +msgstr "Gesellschaft" #. module: base #: model:ir.module.module,shortdesc:base.module_purchase_requisition @@ -16928,7 +17887,7 @@ msgstr "Monate" #. module: base #: view:workflow.instance:0 msgid "Workflow Instances" -msgstr "Workflow Objekte" +msgstr "Arbeitsablauf-Abschnitte" #. module: base #: code:addons/base/res/res_partner.py:284 @@ -16949,7 +17908,7 @@ msgstr "Nordkorea" #. module: base #: selection:ir.actions.server,state:0 msgid "Create Object" -msgstr "Erzeuge Objekt" +msgstr "Objekt anlegen" #. module: base #: view:ir.filters:0 @@ -16960,7 +17919,7 @@ msgstr "Kontext" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_mrp msgid "Sales and MRP Management" -msgstr "Verkauf und Prokuktions Management" +msgstr "Verkaufs- und Fertigungsplanung" #. module: base #: model:ir.actions.act_window,name:base.action_partner_sms_send @@ -16975,12 +17934,12 @@ msgstr "Interessent" #. module: base #: model:ir.module.module,shortdesc:base.module_stock_invoice_directly msgid "Invoice Picking Directly" -msgstr "" +msgstr "Rechnung aus Lieferung" #. module: base #: selection:base.language.install,lang:0 msgid "Polish / Język polski" -msgstr "Polish / Język polski" +msgstr "Polnisch / Język polski" #. module: base #: model:ir.module.module,description:base.module_base_tools @@ -16993,11 +17952,19 @@ msgid "" "are accessible if installed.\n" " " msgstr "" +"\n" +"Gemeinsame Grundlagen für Hilfs-Module.\n" +"===================================\n" +"\n" +"Legt ein Menü an, in dem Hilfsmittel wie Umfrage, Mittagspause, Ideen, ... " +"verfügbar gemacht \n" +"werden, sobald diese installiert werden.\n" +" " #. module: base #: field:ir.exports,name:0 msgid "Export Name" -msgstr "Export Name" +msgstr "Exportbezeichnung" #. module: base #: help:res.partner.address,type:0 @@ -17005,14 +17972,14 @@ msgid "" "Used to select automatically the right address according to the context in " "sales and purchases documents." msgstr "" -"Wird angewendet um automatisch die eingestellten Zuordnungen wählen zu " -"können." +"Wird angewendet um automatisch die eingestellten Zuordnungen zu\r\n" +"Verkäufen und Einkäufen wählen zu können." #. module: base #: model:ir.actions.act_window,name:base.res_widget_act_window #: model:ir.ui.menu,name:base.menu_res_widget_act_window msgid "Homepage Widgets" -msgstr "Homepage Widgets" +msgstr "Startseiten Anzeige-Elemente" #. module: base #: help:res.company,rml_footer2:0 @@ -17020,6 +17987,9 @@ msgid "" "This field is computed automatically based on bank accounts defined, having " "the display on footer checkbox set." msgstr "" +"Dieses Feld wird, basierend auf Ihren Kontoangaben, automatisch " +"zusammengestellt, wenn Sie\r\n" +"'Anzeige in Fusszeile' eingeschaltet haben." #. module: base #: model:ir.module.module,description:base.module_mrp_subproduct @@ -17039,6 +18009,20 @@ msgid "" " A + B + C -> D + E\n" " " msgstr "" +"\n" +"Dieses Modul setzt die Herstellung mehrerer Produkte aus einem " +"Fertigungsauftrag um.\n" +"=========================================================================\n" +"\n" +"Sie können Teilprodukte in der Stückliste festlegen.\n" +"\n" +"Ohne das Modul ist:\n" +" A + B + C -> D\n" +"\n" +"Mit diesem Modul ist auch:\n" +" A + B + C -> D + E\n" +"im System darstellbar.\n" +" " #. module: base #: model:res.country,name:base.lk @@ -17071,11 +18055,43 @@ msgid "" "module.\n" " " msgstr "" +"\n" +"Dieses Modul ermöglicht Ihnen die Anlage eines neuen Moduls ohne jede " +"Entwicklung.\n" +"========================================================================\n" +"\n" +"Es zeichnet alle Tätigkeiten/Vorgänge an Objekten während einer " +"Aufnahmesitzung auf\n" +"und speichert diese als .ZIP-Archiv ab. Auf diese Weise erstellen Sie Ihr " +"eigenes Modul \n" +"unmittelbar vom OpenERP-Klienten aus.\n" +"\n" +"Diese Version erlaubt dabei die Erstellung und Aktualisierung bestehender " +"Datensätze.\n" +"Es werden Abhängikeiten und Verknüpfung zwischen allerlei Dargestellter " +"Elemente \n" +"(m:1, m:n, ...) ermittelt. Ebenso werden Arbeitsabläufe und Beispiel-" +"/Testdaten \n" +"unterstützt.\n" +"\n" +"Dies sollte es Ihnen leichter machen wiederverwendbare und veröffentlichbare " +"Module\n" +"für individuelle Konfigurationen wie auch Testumgebungen zu erstellen.\n" +"\n" +"Wie wird es verwendet?\n" +"Rufe \n" +"Administration/Einstellungen/Modulerstellung/Assistent Anpassungen als Modul " +"exportieren\n" +"auf.\n" +"Gebe Sie Zeit/Datum der Aufzeichnung und der betroffenen Objekte an und " +"beginnen\n" +"dann die Aufzeichnung.\n" +" " #. module: base #: selection:base.language.install,lang:0 msgid "Russian / русский язык" -msgstr "Russian / русский язык" +msgstr "Russisch / русский язык" #~ msgid "Metadata" #~ msgstr "Metadaten" diff --git a/openerp/addons/base/i18n/el.po b/openerp/addons/base/i18n/el.po index 32caf4f4d84..494dd7644b9 100644 --- a/openerp/addons/base/i18n/el.po +++ b/openerp/addons/base/i18n/el.po @@ -12,8 +12,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:37+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:12+0000\n" +"X-Generator: Launchpad (build 16061)\n" "X-Poedit-Country: GREECE\n" "X-Poedit-Language: Greek\n" "X-Poedit-SourceCharset: utf-8\n" diff --git a/openerp/addons/base/i18n/en_GB.po b/openerp/addons/base/i18n/en_GB.po index 1d2ab6fd748..dd91a5c2cd6 100644 --- a/openerp/addons/base/i18n/en_GB.po +++ b/openerp/addons/base/i18n/en_GB.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:17+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/es.po b/openerp/addons/base/i18n/es.po index c556dbc1078..1f9565339c8 100644 --- a/openerp/addons/base/i18n/es.po +++ b/openerp/addons/base/i18n/es.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:41+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:16+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/es_AR.po b/openerp/addons/base/i18n/es_AR.po index b7aad7682c3..81edd41b083 100644 --- a/openerp/addons/base/i18n/es_AR.po +++ b/openerp/addons/base/i18n/es_AR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:17+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh @@ -25,17 +25,17 @@ msgstr "Santa Helena" #. module: base #: view:ir.actions.report.xml:0 msgid "Other Configuration" -msgstr "" +msgstr "Otra configuración" #. module: base #: selection:ir.property,type:0 msgid "DateTime" -msgstr "" +msgstr "Fecha y hora" #. module: base #: model:ir.module.module,shortdesc:base.module_project_mailgate msgid "Tasks-Mail Integration" -msgstr "" +msgstr "Integración Tareas-Email" #. module: base #: code:addons/fields.py:582 @@ -44,6 +44,8 @@ msgid "" "The second argument of the many2many field %s must be a SQL table !You used " "%s, which is not a valid SQL table name." msgstr "" +"¡El segundo argumento del campo many2many %s debe ser una tabla SQL! Has " +"utilizado %s, que no es un nombre de tabla SQL válido." #. module: base #: field:ir.ui.view,arch:0 @@ -70,6 +72,21 @@ msgid "" " * Graph of My Remaining Hours by Project\n" " " msgstr "" +"\n" +"El módulo de Gestión de Proyectos permite gestionar proyectos con varios " +"niveles, tareas, trabajo realizado en tareas, etc.\n" +"=============================================================================" +"=========\n" +"\n" +"Es capaz de generar planificaciones, ordenar tareas, etc.\n" +"\n" +"El tablero de control para los miembros del proyecto incluye:\n" +"--------------------------------------------\n" +"* Lista de mis tareas abiertas\n" +"* Lista de mis tareas delegadas\n" +"* Gráfico de mis proyectos: Planificado vs Horas totales\n" +"* Gráfico de mis horas pendientes por proyecto\n" +" " #. module: base #: field:base.language.import,code:0 @@ -89,7 +106,7 @@ msgstr "Workflow" #. module: base #: selection:ir.sequence,implementation:0 msgid "No gap" -msgstr "" +msgstr "Sin hueco" #. module: base #: selection:base.language.install,lang:0 @@ -99,7 +116,7 @@ msgstr "Húngaro / Magyar" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (PY) / Español (PY)" -msgstr "" +msgstr "Español (UY) / Español (UY)" #. module: base #: model:ir.module.category,description:base.module_category_project_management @@ -107,22 +124,26 @@ msgid "" "Helps you manage your projects and tasks by tracking them, generating " "plannings, etc..." msgstr "" +"Le ayuda a gestionar sus proyectos y tareas realizando un seguimiento de los " +"mismos, generando planificaciones, ..." #. module: base #: field:ir.actions.act_window,display_menu_tip:0 msgid "Display Menu Tips" -msgstr "" +msgstr "Mostrar consejos de menú" #. module: base #: help:ir.cron,model:0 msgid "" "Model name on which the method to be called is located, e.g. 'res.partner'." msgstr "" +"Nombre del módelo en el que se encuentra el método al que se llama, por " +"ejemplo 'res.partner'." #. module: base #: view:ir.module.module:0 msgid "Created Views" -msgstr "" +msgstr "Vistas creadas" #. module: base #: code:addons/base/ir/ir_model.py:532 @@ -131,6 +152,8 @@ msgid "" "You can not write in this document (%s) ! Be sure your user belongs to one " "of these groups: %s." msgstr "" +"¡No puede escribir en este documento (%s)! Asegúrese que su usuario " +"pertenezca a alguno de estos grupos: %s." #. module: base #: model:ir.module.module,description:base.module_event_project @@ -141,6 +164,11 @@ msgid "" "\n" "This module allows you to create retro planning for managing your events.\n" msgstr "" +"\n" +"Organización y gestión de eventos.\n" +"======================================\n" +"\n" +"Este módulo permite crear retro planning para gestionar tus eventos.\n" #. module: base #: help:ir.model.fields,domain:0 @@ -149,16 +177,19 @@ msgid "" "specified as a Python expression defining a list of triplets. For example: " "[('color','=','red')]" msgstr "" +"El dominio opcional para restringir los posibles valores para los campos de " +"relación, se especifica como una expresión Python compuesta por una lista de " +"tripletas. Por ejemplo: [('color','=',' red')]" #. module: base #: field:res.partner,ref:0 msgid "Reference" -msgstr "" +msgstr "Referencia" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_be_invoice_bba msgid "Belgium - Structured Communication" -msgstr "" +msgstr "Bélgica - Comunicación Estructurada" #. module: base #: field:ir.actions.act_window,target:0 @@ -168,12 +199,12 @@ msgstr "Ventana destino" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_analytic_plans msgid "Sales Analytic Distribution" -msgstr "" +msgstr "Distribución Analítica de Ventas" #. module: base #: model:ir.module.module,shortdesc:base.module_web_process msgid "Process" -msgstr "" +msgstr "Procesar" #. module: base #: model:ir.module.module,shortdesc:base.module_analytic_journal_billing_rate diff --git a/openerp/addons/base/i18n/es_CL.po b/openerp/addons/base/i18n/es_CL.po index 50a7f8e0821..aedc3181be1 100644 --- a/openerp/addons/base/i18n/es_CL.po +++ b/openerp/addons/base/i18n/es_CL.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:17+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/es_CR.po b/openerp/addons/base/i18n/es_CR.po index c2e8afd5c28..636ed963d30 100644 --- a/openerp/addons/base/i18n/es_CR.po +++ b/openerp/addons/base/i18n/es_CR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:43+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:18+0000\n" +"X-Generator: Launchpad (build 16061)\n" "Language: \n" #. module: base diff --git a/openerp/addons/base/i18n/es_EC.po b/openerp/addons/base/i18n/es_EC.po index 60f34c370f2..84617d0a2bc 100644 --- a/openerp/addons/base/i18n/es_EC.po +++ b/openerp/addons/base/i18n/es_EC.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:43+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:18+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/es_MX.po b/openerp/addons/base/i18n/es_MX.po index 57fa84aff0b..3e7f975f118 100644 --- a/openerp/addons/base/i18n/es_MX.po +++ b/openerp/addons/base/i18n/es_MX.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:43+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:18+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/et.po b/openerp/addons/base/i18n/et.po index 57ffc20ad23..9d8b95b83c9 100644 --- a/openerp/addons/base/i18n/et.po +++ b/openerp/addons/base/i18n/et.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:37+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:11+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/eu.po b/openerp/addons/base/i18n/eu.po index 277c9ff2d1d..cf88512fe08 100644 --- a/openerp/addons/base/i18n/eu.po +++ b/openerp/addons/base/i18n/eu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:36+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:10+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/fa.po b/openerp/addons/base/i18n/fa.po index 5eaefa28efb..98f1b514c4b 100644 --- a/openerp/addons/base/i18n/fa.po +++ b/openerp/addons/base/i18n/fa.po @@ -9,8 +9,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:39+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:14+0000\n" +"X-Generator: Launchpad (build 16061)\n" "X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n" "X-Poedit-Language: Persian\n" @@ -22,7 +22,7 @@ msgstr "سنت هلن" #. module: base #: view:ir.actions.report.xml:0 msgid "Other Configuration" -msgstr "" +msgstr "پیکربندی های دیگر" #. module: base #: selection:ir.property,type:0 @@ -81,12 +81,12 @@ msgstr "کد (مثلا:en__US)" #: field:workflow.transition,wkf_id:0 #: field:workflow.workitem,wkf_id:0 msgid "Workflow" -msgstr "کارگردش" +msgstr "گردش کار" #. module: base #: selection:ir.sequence,implementation:0 msgid "No gap" -msgstr "" +msgstr "بدون فاصله" #. module: base #: selection:base.language.install,lang:0 @@ -96,7 +96,7 @@ msgstr "مجاری / Magyar" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (PY) / Español (PY)" -msgstr "" +msgstr "اسپانیایی" #. module: base #: model:ir.module.category,description:base.module_category_project_management @@ -108,7 +108,7 @@ msgstr "" #. module: base #: field:ir.actions.act_window,display_menu_tip:0 msgid "Display Menu Tips" -msgstr "" +msgstr "نمایش منوی نکات" #. module: base #: help:ir.cron,model:0 @@ -150,12 +150,12 @@ msgstr "" #. module: base #: field:res.partner,ref:0 msgid "Reference" -msgstr "" +msgstr "ارجاع" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_be_invoice_bba msgid "Belgium - Structured Communication" -msgstr "" +msgstr "بلژیک ساختار ارتباطات" #. module: base #: field:ir.actions.act_window,target:0 @@ -170,7 +170,7 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_web_process msgid "Process" -msgstr "" +msgstr "روند" #. module: base #: model:ir.module.module,shortdesc:base.module_analytic_journal_billing_rate @@ -181,7 +181,7 @@ msgstr "" #: code:addons/base/res/res_users.py:558 #, python-format msgid "Warning!" -msgstr "" +msgstr "هشدار!" #. module: base #: code:addons/base/ir/ir_model.py:344 @@ -217,12 +217,12 @@ msgstr "سوازیلند" #: code:addons/orm.py:4206 #, python-format msgid "created." -msgstr "" +msgstr "ایجاد میشود." #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_tr msgid "Turkey - Accounting" -msgstr "" +msgstr "ترکیه - حسابداری" #. module: base #: model:ir.module.module,shortdesc:base.module_mrp_subproduct @@ -260,7 +260,7 @@ msgstr "" #: model:ir.module.category,name:base.module_category_sales_management #: model:ir.module.module,shortdesc:base.module_sale msgid "Sales Management" -msgstr "" +msgstr "مدیریت فروش" #. module: base #: view:res.partner:0 @@ -271,7 +271,7 @@ msgstr "جستجوی همکار" #: code:addons/base/module/wizard/base_export_language.py:60 #, python-format msgid "new" -msgstr "تازه" +msgstr "جدید" #. module: base #: field:ir.actions.report.xml,multi:0 @@ -304,7 +304,7 @@ msgstr "اندازه بیشینه" #: model:ir.ui.menu,name:base.next_id_73 #: model:ir.ui.menu,name:base.reporting_menu msgid "Reporting" -msgstr "" +msgstr "گزارش" #. module: base #: view:res.partner:0 @@ -337,7 +337,7 @@ msgstr "" #. module: base #: sql_constraint:res.lang:0 msgid "The name of the language must be unique !" -msgstr "" +msgstr "نام زبان باید منحصر به فرد باشد !" #. module: base #: model:ir.module.module,description:base.module_import_base @@ -356,7 +356,7 @@ msgstr "نام تردست" #. module: base #: model:res.groups,name:base.group_partner_manager msgid "Partner Manager" -msgstr "" +msgstr "مدیریت شریک" #. module: base #: model:ir.module.category,name:base.module_category_customer_relationship_management @@ -366,7 +366,7 @@ msgstr "" #. module: base #: view:ir.module.module:0 msgid "Extra" -msgstr "" +msgstr "اضافی" #. module: base #: code:addons/orm.py:2526 @@ -387,7 +387,7 @@ msgstr "حد اعتبار" #. module: base #: model:ir.module.module,description:base.module_web_graph msgid "Openerp web graph view" -msgstr "" +msgstr "مشاهده گراف Openerp در وب" #. module: base #: field:ir.model.data,date_update:0 @@ -402,7 +402,7 @@ msgstr "" #. module: base #: view:ir.attachment:0 msgid "Owner" -msgstr "" +msgstr "مالک‌" #. module: base #: field:ir.actions.act_window,src_model:0 @@ -428,7 +428,7 @@ msgstr "ir.ui.view_sc" #: field:res.widget.user,widget_id:0 #: field:res.widget.wizard,widgets_list:0 msgid "Widget" -msgstr "" +msgstr "ویجت" #. module: base #: view:ir.model.access:0 @@ -454,7 +454,7 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_pad_project msgid "Specifications on PADs" -msgstr "" +msgstr "مشخصات به روی پد" #. module: base #: help:ir.filters,user_id:0 @@ -466,7 +466,7 @@ msgstr "" #. module: base #: help:res.partner,website:0 msgid "Website of Partner." -msgstr "" +msgstr "وب سایت همکار" #. module: base #: help:ir.actions.act_window,views:0 @@ -495,13 +495,13 @@ msgstr "قالب تاریخ" #. module: base #: model:ir.module.module,shortdesc:base.module_base_report_designer msgid "OpenOffice Report Designer" -msgstr "" +msgstr "طراح گزارش اپن آفیس" #. module: base #: field:res.bank,email:0 #: field:res.partner.address,email:0 msgid "E-Mail" -msgstr "ایمیل" +msgstr "پست الکترونیکی" #. module: base #: model:res.country,name:base.an @@ -532,7 +532,7 @@ msgstr "" #. module: base #: model:res.country,name:base.gf msgid "French Guyana" -msgstr "امریکا/گویانا" +msgstr "گوویان فرانسوی" #. module: base #: field:ir.ui.view.custom,ref_id:0 @@ -556,22 +556,22 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_layout msgid "Sales Orders Print Layout" -msgstr "" +msgstr "چیدمان سفارش های فروش در چاپ" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (VE) / Español (VE)" -msgstr "" +msgstr "اسپانیایی (VE)" #. module: base #: model:ir.module.module,shortdesc:base.module_hr_timesheet_invoice msgid "Invoice on Timesheets" -msgstr "" +msgstr "فاکتور در جداول زمانبندی" #. module: base #: view:base.module.upgrade:0 msgid "Your system will be updated." -msgstr "" +msgstr "سیستم شما به روز خواهد شد." #. module: base #: field:ir.actions.todo,note:0 @@ -641,7 +641,7 @@ msgstr "فروش‌ها و خریدها" #. module: base #: view:ir.translation:0 msgid "Untranslated" -msgstr "" +msgstr "ترجمه‌نشده" #. module: base #: help:ir.actions.act_window,context:0 @@ -670,7 +670,7 @@ msgstr "نام فیلدهای دلخواه باید با 'x_' آغاز شوند! #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_mx msgid "Mexico - Accounting" -msgstr "" +msgstr "حسابداری - مکزیک" #. module: base #: help:ir.actions.server,action_id:0 @@ -680,17 +680,17 @@ msgstr "پنچره کُنش، گزارش، تَردست را برای اجرا #. module: base #: model:res.country,name:base.ai msgid "Anguilla" -msgstr "آنگیل" +msgstr "آنگولا" #. module: base #: view:base.language.export:0 msgid "Export done" -msgstr "برونش انجام شد" +msgstr "صادرات انجام شد" #. module: base #: model:ir.module.module,shortdesc:base.module_plugin_outlook msgid "Outlook Plug-In" -msgstr "" +msgstr "پلاگین Outlook" #. module: base #: view:ir.model:0 @@ -717,7 +717,7 @@ msgstr "اردن" #. module: base #: help:ir.cron,nextcall:0 msgid "Next planned execution date for this job." -msgstr "" +msgstr "تاریخ برنامه ریزی شده بعدی برای انجام این کار" #. module: base #: code:addons/base/ir/ir_model.py:139 @@ -733,24 +733,24 @@ msgstr "اریتره" #. module: base #: sql_constraint:res.company:0 msgid "The company name must be unique !" -msgstr "" +msgstr "نام شرکت باید منحصر به فرد باشد !" #. module: base #: view:res.config:0 #: view:res.config.installer:0 msgid "description" -msgstr "" +msgstr "توضیحات" #. module: base #: model:ir.ui.menu,name:base.menu_base_action_rule #: model:ir.ui.menu,name:base.menu_base_action_rule_admin msgid "Automated Actions" -msgstr "" +msgstr "عملیات خودکار" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_ro msgid "Romania - Accounting" -msgstr "" +msgstr "حسابداری - رومانی" #. module: base #: view:partner.wizard.ean.check:0 diff --git a/openerp/addons/base/i18n/fa_AF.po b/openerp/addons/base/i18n/fa_AF.po index 705225800be..4455b4b1bc2 100644 --- a/openerp/addons/base/i18n/fa_AF.po +++ b/openerp/addons/base/i18n/fa_AF.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:43+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:18+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/fi.po b/openerp/addons/base/i18n/fi.po index 8872be9f858..a636d8a94c2 100644 --- a/openerp/addons/base/i18n/fi.po +++ b/openerp/addons/base/i18n/fi.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:37+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:11+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/fr.po b/openerp/addons/base/i18n/fr.po index a34898b563d..5401ac31f42 100644 --- a/openerp/addons/base/i18n/fr.po +++ b/openerp/addons/base/i18n/fr.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:37+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:12+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/gl.po b/openerp/addons/base/i18n/gl.po index 42b2e066b40..4d020749af9 100644 --- a/openerp/addons/base/i18n/gl.po +++ b/openerp/addons/base/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:37+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:12+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/gu.po b/openerp/addons/base/i18n/gu.po index 11b6b06b141..da4a5d6d519 100644 --- a/openerp/addons/base/i18n/gu.po +++ b/openerp/addons/base/i18n/gu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:38+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:12+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/he.po b/openerp/addons/base/i18n/he.po index 03864ff34aa..dc41897f839 100644 --- a/openerp/addons/base/i18n/he.po +++ b/openerp/addons/base/i18n/he.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:38+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:12+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/hr.po b/openerp/addons/base/i18n/hr.po index 78d5591663d..9006415c054 100644 --- a/openerp/addons/base/i18n/hr.po +++ b/openerp/addons/base/i18n/hr.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:40+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:15+0000\n" +"X-Generator: Launchpad (build 16061)\n" "Language: hr\n" #. module: base diff --git a/openerp/addons/base/i18n/hu.po b/openerp/addons/base/i18n/hu.po index 85823b7f6f2..d421d8874de 100644 --- a/openerp/addons/base/i18n/hu.po +++ b/openerp/addons/base/i18n/hu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:38+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:12+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/hy.po b/openerp/addons/base/i18n/hy.po index 14dce614f0b..038dd4c0a68 100644 --- a/openerp/addons/base/i18n/hy.po +++ b/openerp/addons/base/i18n/hy.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:35+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:10+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/id.po b/openerp/addons/base/i18n/id.po index c72c52beeb4..57806edb71c 100644 --- a/openerp/addons/base/i18n/id.po +++ b/openerp/addons/base/i18n/id.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:38+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:13+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/is.po b/openerp/addons/base/i18n/is.po index e136665ae18..e5fa01a9dbd 100644 --- a/openerp/addons/base/i18n/is.po +++ b/openerp/addons/base/i18n/is.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:38+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:13+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/it.po b/openerp/addons/base/i18n/it.po index e2e252f260c..cf39f48fe37 100644 --- a/openerp/addons/base/i18n/it.po +++ b/openerp/addons/base/i18n/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:38+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:13+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/ja.po b/openerp/addons/base/i18n/ja.po index 4ef99b6c764..8a6a41057ec 100644 --- a/openerp/addons/base/i18n/ja.po +++ b/openerp/addons/base/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-21 04:41+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:13+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/ka.po b/openerp/addons/base/i18n/ka.po index d8eddbdd1c9..00a06bf9ba3 100644 --- a/openerp/addons/base/i18n/ka.po +++ b/openerp/addons/base/i18n/ka.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:37+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:12+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/kk.po b/openerp/addons/base/i18n/kk.po index 30d6d020389..b17421be2f6 100644 --- a/openerp/addons/base/i18n/kk.po +++ b/openerp/addons/base/i18n/kk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:38+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:13+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/ko.po b/openerp/addons/base/i18n/ko.po index bb02ef1a9c1..7a568c31b84 100644 --- a/openerp/addons/base/i18n/ko.po +++ b/openerp/addons/base/i18n/ko.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:39+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:13+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/lt.po b/openerp/addons/base/i18n/lt.po index 1c0589ae931..e08c3f152b9 100644 --- a/openerp/addons/base/i18n/lt.po +++ b/openerp/addons/base/i18n/lt.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:39+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:14+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/lv.po b/openerp/addons/base/i18n/lv.po index e02fdd7e749..27705b72e48 100644 --- a/openerp/addons/base/i18n/lv.po +++ b/openerp/addons/base/i18n/lv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:39+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:14+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/mk.po b/openerp/addons/base/i18n/mk.po index e7b89f876f9..2d66015cdb7 100644 --- a/openerp/addons/base/i18n/mk.po +++ b/openerp/addons/base/i18n/mk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:39+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:14+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/mn.po b/openerp/addons/base/i18n/mn.po index 4dbca25f61f..1264b368a92 100644 --- a/openerp/addons/base/i18n/mn.po +++ b/openerp/addons/base/i18n/mn.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:39+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:14+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/nb.po b/openerp/addons/base/i18n/nb.po index 677dbb18e89..2a83f20f87f 100644 --- a/openerp/addons/base/i18n/nb.po +++ b/openerp/addons/base/i18n/nb.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:39+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:14+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/nl.po b/openerp/addons/base/i18n/nl.po index f4b58866f1a..4ec2d171e4d 100644 --- a/openerp/addons/base/i18n/nl.po +++ b/openerp/addons/base/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:36+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:11+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh @@ -397,7 +397,7 @@ msgstr "Naam assistent" #. module: base #: model:res.groups,name:base.group_partner_manager msgid "Partner Manager" -msgstr "Relatie manager" +msgstr "Relatiemanager" #. module: base #: model:ir.module.category,name:base.module_category_customer_relationship_management @@ -1403,7 +1403,7 @@ msgstr "Document Beheer Systeem" #. module: base #: model:ir.module.module,shortdesc:base.module_crm_claim msgid "Claims Management" -msgstr "Claimsmanagement" +msgstr "Klachtenregistratie" #. module: base #: model:ir.ui.menu,name:base.menu_purchase_root @@ -1453,7 +1453,7 @@ msgid "" " * Effective Date\n" msgstr "" "\n" -"deze module voegt extra informatie toe aan een verkooporder.\n" +"Deze module voegt extra informatie toe aan een verkooporder.\n" "===================================================\n" "\n" "U kunt de navolgende extra data toevoegen aan een verkooporder:\n" @@ -2502,8 +2502,8 @@ msgstr "" "Helpdesk management.\n" "===================\n" "\n" -"Net als administratie en verwerking van claims is de Helpdesk en " -"ondersteuning tool, een goed instrument\n" +"Net als de klachtenregistratie module is de Helpdesk en ondersteuning tool, " +"een goed instrument\n" "om uw acties vast te leggen. Dit menu is meer aangepast aan de mondelinge " "communicatie,\n" "die niet noodzakelijkerwijs verband houden met een claim. Selecteer een " @@ -2614,7 +2614,7 @@ msgstr "Ideeën" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_crm msgid "Opportunity to Quotation" -msgstr "Verkoopkans naar offerte" +msgstr "Prospect naar offerte" #. module: base #: model:ir.module.module,description:base.module_sale_analytic_plans @@ -4255,6 +4255,15 @@ msgid "" "automatically new claims based on incoming emails.\n" " " msgstr "" +"\n" +"Met deze module kunt u alle klachten van uw klanten en leveranciers " +"registreren.\n" +"==================================================================\n" +"\n" +"Deze module is volledig geïntegreerd met de e-mail gateway, zodat u " +"automatisch\n" +"nieuwe klachten kunt registreren op basis van inkomende e-mails.\n" +" " #. module: base #: selection:workflow.activity,join_mode:0 @@ -7672,7 +7681,7 @@ msgstr "Canada" #: code:addons/base/res/res_company.py:158 #, python-format msgid "Reg: " -msgstr "Reg: " +msgstr "KVK: " #. module: base #: help:res.currency.rate,currency_rate_type_id:0 @@ -12076,7 +12085,7 @@ msgstr "Wizards welke worden gestart" #: model:ir.module.category,name:base.module_category_manufacturing #: model:ir.ui.menu,name:base.menu_mrp_root msgid "Manufacturing" -msgstr "Productie" +msgstr "Productiebeheer" #. module: base #: model:res.country,name:base.km @@ -14542,7 +14551,7 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_fetchmail_crm_claim msgid "eMail Gateway for CRM Claim" -msgstr "E-mail Gateway voor CRM Claims" +msgstr "E-mail Gateway voor klachtenregistratie" #. module: base #: help:res.partner,supplier:0 diff --git a/openerp/addons/base/i18n/nl_BE.po b/openerp/addons/base/i18n/nl_BE.po index 0a395831749..1313f114d81 100644 --- a/openerp/addons/base/i18n/nl_BE.po +++ b/openerp/addons/base/i18n/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:17+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/pl.po b/openerp/addons/base/i18n/pl.po index 52e1c9360e5..4ad08ff73d8 100644 --- a/openerp/addons/base/i18n/pl.po +++ b/openerp/addons/base/i18n/pl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:39+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:14+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/pt.po b/openerp/addons/base/i18n/pt.po index 14363c33a2d..11e1ff3a38e 100644 --- a/openerp/addons/base/i18n/pt.po +++ b/openerp/addons/base/i18n/pt.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:40+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:15+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/pt_BR.po b/openerp/addons/base/i18n/pt_BR.po index 342d9754602..eb3b7918c24 100644 --- a/openerp/addons/base/i18n/pt_BR.po +++ b/openerp/addons/base/i18n/pt_BR.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:17+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh @@ -1944,6 +1944,47 @@ msgid "" "\n" " " msgstr "" +"\n" +"Validação de IVA para os números Parceiros 'IVA\n" +"========================================\n" +"\n" +"Depois de instalar este módulo, os valores inseridos no domínio do IVA de " +"parceiros\n" +"ser validado para todos os países suportados. O país é inferida a partir da\n" +"2-letra código do país que prefixos o número de IVA, por exemplo, `` `` " +"BE0477472701\n" +"será validado usando as regras belgas.\n" +"\n" +"Existem dois níveis diferentes de validação Número de IVA:\n" +"\n" +"  * Por padrão, uma verificação off-line simples é realizado utilizando a " +"validação conhecido\n" +"    regras para o país, geralmente uma verificação simples dígito. Isto é " +"rápido e\n" +"    sempre disponível, mas permite que os números que não são " +"verdadeiramente talvez alocados,\n" +"    ou não mais válido.\n" +"  * Quando os \"VIES IVA Verifique\" está activada (na configuração do " +"usuário do\n" +"    Empresa), números de IVA será submetido ao invés linha UE VIES\n" +"    banco de dados, o que vai realmente verificar se o número é válido e, " +"atualmente,\n" +"    atribuídos a uma empresa da UE. Este é um pouco mais lento do que o " +"simples\n" +"    off-line, cheque, requer uma ligação à Internet, e pode não estar " +"disponível\n" +"    o tempo todo. Se o serviço não está disponível ou não suporta o\n" +"    país requerido (por exemplo, para países fora da UE), uma simples " +"verificação será realizada\n" +"    em vez disso.\n" +"\n" +"Países suportados atualmente são os países da UE, e alguns países não " +"comunitários\n" +"como Chile, Colômbia, México, Noruega ou a Rússia. Para os países não " +"suportados,\n" +"apenas o código do país serão validados.\n" +"\n" +" " #. module: base #: view:ir.sequence:0 @@ -2467,6 +2508,22 @@ msgid "" "re-invoice your customer's expenses if your work by project.\n" " " msgstr "" +"\n" +"Este módulo tem como objetivo gerenciar as despesas dos funcionários.\n" +"===============================================\n" +"\n" +"O fluxo de trabalho inteiro é implementado:\n" +"     * Projeto de despesa\n" +"     * Confirmação da folha pelo empregado\n" +"     * Validação por seu empresário\n" +"     * A validação pelo contador e criação de fatura\n" +"     * Pagamento da fatura para o empregado\n" +"\n" +"Este módulo também utiliza a contabilidade analítica e é compatível com a\n" +"a fatura no módulo de folha de ponto, de modo que você vai ser capaz de " +"automaticamente\n" +"cobrar seu cliente despesas se você trabalhar por projeto.\n" +" " #. module: base #: field:ir.values,action_id:0 @@ -2948,6 +3005,31 @@ msgid "" "performing those tasks.\n" " " msgstr "" +"\n" +"Este módulo implementa todos os conceitos definidos pela metodologia GTD - " +"Getting Things Done.\n" +"================================================== " +"=================================\n" +"\n" +"Este módulo implementa um simples lista Todo pessoal baseado em tarefas. Ele " +"acrescenta\n" +"a aplicação do projeto uma lista editável de tarefas simplificadas para o " +"mínimo\n" +"campos obrigatórios.\n" +"\n" +"A lista de afazeres é baseado na metodologia GTD. Esta metodologia " +"mundialmente utilizada\n" +"é utilizado para a melhoria pessoal de gerenciamento de tempo.\n" +"\n" +"Getting Things Done (comumente abreviado como GTD) é uma ação de gestão\n" +"método criado por David Allen, e descrito em um livro de mesmo nome.\n" +"\n" +"GTD se baseia no princípio de que uma pessoa precisa para mover as tarefas " +"fora da mente por\n" +"gravá-las externamente. Dessa forma, a mente se liberta do trabalho de\n" +"lembrando de tudo que precisa ser feito, e pode se concentrar em realmente\n" +"executar essas tarefas.\n" +" " #. module: base #: model:res.country,name:base.tt @@ -3084,7 +3166,7 @@ msgstr "Erro!" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_fr_rib msgid "French RIB Bank Details" -msgstr "" +msgstr "Detalhes do RIB do Banco Francês" #. module: base #: view:res.lang:0 @@ -3200,12 +3282,12 @@ msgid "" "The decimal precision is configured per company.\n" msgstr "" "\n" -"Você precisa configurar a precisão do preço para diferentes tipos de uso: " -"contabilidade, venda, compras, etc.\n" +"Configurar a precisão preço que você precisa para diferentes tipos de uso: " +"contabilidade, vendas, compras, etc\n" "=============================================================================" "=========================\n" "\n" -"A precisão decimal é configurada por empresa.\n" +"A precisão decimal é configurado por empresa.\n" #. module: base #: model:ir.module.module,description:base.module_l10n_pl @@ -3223,6 +3305,18 @@ msgid "" "że wszystkie towary są w obrocie hurtowym.\n" " " msgstr "" +"\n" +"Este é o módulo para gerenciar o gráfico contabilidade e impostos para a " +"Polónia no OpenERP.\n" +"================================================== " +"================================\n" +"\n" +"To jest moduł do tworzenia wzorcowego planu kont i podstawowych ustawień do " +"podatków\n" +"VAT 0%, 7% i 22%. Moduł ustawia też konta do kupna i sprzedaży towarów " +"zakładając,\n" +"że wszystkie towary są w obrocie hurtowym.\n" +" " #. module: base #: field:ir.actions.client,params_store:0 @@ -3258,6 +3352,21 @@ msgid "" "since it's the same which has been renamed.\n" " " msgstr "" +"\n" +"Este módulo permite aos usuários executar a segmentação entre os parceiros.\n" +"================================================== ===============\n" +"\n" +"Ele utiliza os critérios de perfis a partir do módulo de segmentação mais " +"cedo e melhorá-lo. Graças ao novo conceito de questionário. Agora você pode " +"reagrupar as perguntas em um questionário e usá-lo diretamente em um " +"parceiro.\n" +"\n" +"Ele também foi fundida com a anterior ferramenta de CRM & SRM segmentação " +"porque foram sobrepostos.\n" +"\n" +"     * Nota: Este módulo não é compatível com o módulo de segmentação, já " +"que é o mesmo que foi renomeado.\n" +" " #. module: base #: code:addons/report_sxw.py:434 @@ -3379,6 +3488,30 @@ msgid "" "\n" " " msgstr "" +"\n" +" \n" +"Localização belga para as facturas em-e de saída (pré-requisito para " +"account_coda):\n" +"     Rótulos 'referência' Renomear campo para 'Comunicação' -\n" +"     - Adicionar suporte para comunicação estruturada belga\n" +"\n" +"Uma comunicação estruturada pode ser gerado automaticamente em faturas de " +"saída de acordo com os seguintes algoritmos:\n" +"     1) aleatória: + + + RRR / RRRR / RRRDD + + +\n" +"         R. R =. Dígitos aleatórios, Dígitos DD = Verificar\n" +"     2) Data: + + + DOY / ano / SSSDD + + +\n" +"         Doy = dia do ano, o SSS = número de seqüência, DD dígitos = " +"Verificar)\n" +"     3) Referência ao Cliente + + + RRR / RRRR / SSSDDD + + +\n" +"         R.. = R Referência do cliente sem caracteres não numéricos, SSS = " +"Número sequencial, DD dígitos = Verificar)\n" +"        \n" +"O tipo preferido de comunicação estruturada e algoritmo associado pode ser " +"especificado nos registros de parceiros.\n" +"Uma comunicação \"aleatória\" estruturado gerado se nenhum algoritmo é " +"especificado no registro de parceiros. \n" +"\n" +" " #. module: base #: model:ir.module.module,shortdesc:base.module_wiki_quality_manual @@ -3515,6 +3648,14 @@ msgid "" "for Wiki FAQ.\n" " " msgstr "" +"\n" +"Este módulo oferece um Wiki Modelo FAQ.\n" +"=========================================\n" +"\n" +"Ele fornece dados de demonstração, criando um Grupo de wiki e uma página " +"Wiki\n" +"para Wiki FAQ.\n" +" " #. module: base #: view:ir.actions.server:0 @@ -3789,6 +3930,13 @@ msgid "" " * the Tax Code Chart for Luxembourg\n" " * the main taxes used in Luxembourg" msgstr "" +"\n" +"Este é o módulo de base para gerenciar o Plano Contábil de Luxemburgo.\n" +"================================================== ====================\n" +"\n" +"     * Quadro da KLUWER de Contas,\n" +"     * O Gráfico Código Tributário para o Luxemburgo\n" +"     * Os principais impostos usados ​​no Luxemburgo" #. module: base #: field:ir.module.module,demo:0 @@ -3813,6 +3961,21 @@ msgid "" "module 'share'.\n" " " msgstr "" +"\n" +"Este módulo define \"portais\" para personalizar o acesso ao seu banco de " +"dados OpenERP\n" +"para usuários externos.\n" +"\n" +"Um portal define menu de usuário personalizada e direitos de acesso para um " +"grupo de usuários\n" +"(os associados a esse portal). Ela também se associa grupos de usuários para " +"o\n" +"usuários do portal (adicionando um grupo no portal adiciona automaticamente " +"para o portal\n" +"usuários, etc.) Essa característica é muito útil quando utilizada em " +"combinação com a\n" +"'share' módulo.\n" +" " #. module: base #: selection:res.request,priority:0 @@ -3959,6 +4122,22 @@ msgid "" "\n" " " msgstr "" +"\n" +"Este módulo oferece alguns recursos para melhorar o layout das faturas.\n" +"================================================== =======================\n" +"\n" +"Ele lhe dá a possibilidade de:\n" +"--------------------------------\n" +"     * Ordem todas as linhas de uma fatura\n" +"     * Adicionar títulos, linhas de comentário, sub total de linhas\n" +"     * Desenhar linhas horizontais e colocar quebras de página\n" +"\n" +"Além disso, há uma opção que permite a impressão de todas as faturas " +"selecionados com uma mensagem dada especial na parte inferior do mesmo. Este " +"recurso pode ser muito útil para imprimir as suas facturas com o fim-de-ano " +"desejos, condições especiais pontuais.\n" +"\n" +" " #. module: base #: constraint:res.partner:0 @@ -4156,6 +4335,14 @@ msgid "" "templates to target objects.\n" " " msgstr "" +"\n" +" * Apoio a Multi Idiomas de Plano de Contas, Impostos, códigos fiscais, " +"diários, Modelos de Contabilidade,\n" +"         Plano de Contas Analítico e Diários analíticos.\n" +"     * Assistente de Configuração mudanças\n" +"         - Copia traduções para COA, Imposto de Código Tributário, e Posição " +"Fiscal a partir de modelos para objetos de destino.\n" +" " #. module: base #: view:ir.actions.todo:0 @@ -4547,6 +4734,15 @@ msgid "" "automatically new claims based on incoming emails.\n" " " msgstr "" +"\n" +"Este módulo permite que você acompanhe as solicitações de seus clientes / " +"fornecedores.\n" +"================================================== " +"==============================\n" +"\n" +"É totalmente integrado com o gateway de e-mail para que você possa criar\n" +"automaticamente novos pedidos baseados em e-mails recebidos.\n" +" " #. module: base #: selection:workflow.activity,join_mode:0 @@ -6667,6 +6863,26 @@ msgid "" "an other object.\n" " " msgstr "" +"\n" +"Este módulo permite que você gerencie seus contatos\n" +"==============================================\n" +"\n" +"Ele permite que você definir:\n" +"     * Contatos não relacionados a um parceiro,\n" +"     * Contatos trabalhando em vários endereços (possivelmente para " +"parceiros diferentes),\n" +"     * Contatos com funções possivelmente diferentes para cada um dos " +"endereços do seu trabalho\n" +"\n" +"Ele também adiciona novos itens de menu localizado na\n" +"     Compras / Livro de Endereços / Contatos\n" +"     Vendas / Livro de Endereços / Contatos\n" +"\n" +"Preste atenção que este módulo converte os endereços existentes em " +"\"endereços + contatos\". Isso significa que alguns campos dos endereços vai " +"estar ausente (como o nome do contato), uma vez que estes devem ser " +"definidos em um outro objeto.\n" +" " #. module: base #: model:ir.actions.act_window,name:base.act_res_partner_event @@ -8017,6 +8233,14 @@ msgid "" "that exceeds minimum amount set by configuration wizard.\n" " " msgstr "" +"\n" +"Dupla-validação para compras superiores a quantidade mínima.\n" +"================================================== =======\n" +"\n" +"Este módulo modifica o fluxo de trabalho de compra, a fim de validar " +"compras\n" +"que exceder o valor mínimo fixado pelo assistente de configuração.\n" +" " #. module: base #: field:res.currency,rounding:0 @@ -14393,6 +14617,15 @@ msgid "" "plans.\n" " " msgstr "" +"\n" +"O módulo base para gerenciar a distribuição analítica e ordens de compra.\n" +"================================================== ==================\n" +"\n" +"Permite que o usuário manter planos de análise diversas. Estes permitem-lhe " +"dividir\n" +"uma linha em um pedido de compra de fornecedores em várias contas e planos " +"analíticos.\n" +" " #. module: base #: field:res.company,vat:0 diff --git a/openerp/addons/base/i18n/ro.po b/openerp/addons/base/i18n/ro.po index 8576dce8f84..8f673e6138f 100644 --- a/openerp/addons/base/i18n/ro.po +++ b/openerp/addons/base/i18n/ro.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:40+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:15+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/ru.po b/openerp/addons/base/i18n/ru.po index 82e7869a7ce..57175fa581f 100644 --- a/openerp/addons/base/i18n/ru.po +++ b/openerp/addons/base/i18n/ru.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-25 04:44+0000\n" -"X-Generator: Launchpad (build 16019)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:15+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/sk.po b/openerp/addons/base/i18n/sk.po index b119359ec95..ec4981d65af 100644 --- a/openerp/addons/base/i18n/sk.po +++ b/openerp/addons/base/i18n/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:40+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:15+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/sl.po b/openerp/addons/base/i18n/sl.po index 3abc2191ca1..6f5fea1a902 100644 --- a/openerp/addons/base/i18n/sl.po +++ b/openerp/addons/base/i18n/sl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:41+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:15+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/sq.po b/openerp/addons/base/i18n/sq.po index c73b4e69686..f0ae2c5c50f 100644 --- a/openerp/addons/base/i18n/sq.po +++ b/openerp/addons/base/i18n/sq.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:35+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:10+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/sr.po b/openerp/addons/base/i18n/sr.po index 2c32b7fd61a..d1da84e99c3 100644 --- a/openerp/addons/base/i18n/sr.po +++ b/openerp/addons/base/i18n/sr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:40+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:15+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/sr@latin.po b/openerp/addons/base/i18n/sr@latin.po index 98d86237ce2..c7ead346847 100644 --- a/openerp/addons/base/i18n/sr@latin.po +++ b/openerp/addons/base/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:43+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:19+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/sv.po b/openerp/addons/base/i18n/sv.po index 5c6ffb07321..693f4042c34 100644 --- a/openerp/addons/base/i18n/sv.po +++ b/openerp/addons/base/i18n/sv.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:41+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:16+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/th.po b/openerp/addons/base/i18n/th.po index 455fe808228..5c973f1c0f8 100644 --- a/openerp/addons/base/i18n/th.po +++ b/openerp/addons/base/i18n/th.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:41+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:16+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/tlh.po b/openerp/addons/base/i18n/tlh.po index 78e31dfc564..7c81a8298b4 100644 --- a/openerp/addons/base/i18n/tlh.po +++ b/openerp/addons/base/i18n/tlh.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:41+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:16+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/tr.po b/openerp/addons/base/i18n/tr.po index c51ba45a1b4..890ce6474dc 100644 --- a/openerp/addons/base/i18n/tr.po +++ b/openerp/addons/base/i18n/tr.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:41+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:16+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/uk.po b/openerp/addons/base/i18n/uk.po index 792501814dd..84c39337199 100644 --- a/openerp/addons/base/i18n/uk.po +++ b/openerp/addons/base/i18n/uk.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:41+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:16+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/ur.po b/openerp/addons/base/i18n/ur.po index 5163f59f157..58b2ffd8cdf 100644 --- a/openerp/addons/base/i18n/ur.po +++ b/openerp/addons/base/i18n/ur.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:16+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/vi.po b/openerp/addons/base/i18n/vi.po index 26fce52ba3f..b071215c34c 100644 --- a/openerp/addons/base/i18n/vi.po +++ b/openerp/addons/base/i18n/vi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:17+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/zh_CN.po b/openerp/addons/base/i18n/zh_CN.po index a8f2da01e50..b6261de14ba 100644 --- a/openerp/addons/base/i18n/zh_CN.po +++ b/openerp/addons/base/i18n/zh_CN.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:43+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:18+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/zh_HK.po b/openerp/addons/base/i18n/zh_HK.po index 46f538a7125..daf05edeaac 100644 --- a/openerp/addons/base/i18n/zh_HK.po +++ b/openerp/addons/base/i18n/zh_HK.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:17+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh diff --git a/openerp/addons/base/i18n/zh_TW.po b/openerp/addons/base/i18n/zh_TW.po index 9f7c2baf4ef..4951c2fff9a 100644 --- a/openerp/addons/base/i18n/zh_TW.po +++ b/openerp/addons/base/i18n/zh_TW.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-09-20 04:42+0000\n" -"X-Generator: Launchpad (build 15985)\n" +"X-Launchpad-Export-Date: 2012-10-04 05:18+0000\n" +"X-Generator: Launchpad (build 16061)\n" #. module: base #: model:res.country,name:base.sh From 3856dcd5f1d03fb953d2cab7d17217286d5585e1 Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of openerp <> Date: Thu, 4 Oct 2012 05:33:37 +0000 Subject: [PATCH 195/409] Launchpad automatic translations update. bzr revid: launchpad_translations_on_behalf_of_openerp-20121004053337-541ss7diwg0ae2lw --- addons/web_calendar/i18n/fa.po | 144 +++++++++++++++++++++++++++++++++ addons/web_diagram/i18n/fa.po | 81 +++++++++++++++++++ addons/web_gantt/i18n/fa.po | 28 +++++++ addons/web_graph/i18n/fa.po | 98 ++++++++++++++++++++++ addons/web_kanban/i18n/fa.po | 66 +++++++++++++++ 5 files changed, 417 insertions(+) create mode 100644 addons/web_calendar/i18n/fa.po create mode 100644 addons/web_diagram/i18n/fa.po create mode 100644 addons/web_gantt/i18n/fa.po create mode 100644 addons/web_graph/i18n/fa.po create mode 100644 addons/web_kanban/i18n/fa.po diff --git a/addons/web_calendar/i18n/fa.po b/addons/web_calendar/i18n/fa.po new file mode 100644 index 00000000000..7c322bdc2ae --- /dev/null +++ b/addons/web_calendar/i18n/fa.po @@ -0,0 +1,144 @@ +# Persian translation for openerp-web +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-07-02 09:06+0200\n" +"PO-Revision-Date: 2012-10-03 10:24+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Persian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n" +"X-Generator: Launchpad (build 16061)\n" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:11 +msgid "Calendar" +msgstr "تقویم" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:70 +msgid "Filter" +msgstr "فیلتر" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:144 +msgid "Today" +msgstr "امروز" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:145 +msgid "Day" +msgstr "روز" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:146 +msgid "Week" +msgstr "هفته" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:147 +msgid "Month" +msgstr "ماه" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:148 +msgid "New event" +msgstr "رویداد جدید" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:149 +msgid "Save" +msgstr "ذخیره" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:150 +msgid "Cancel" +msgstr "لغو کردن" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:151 +msgid "Details" +msgstr "جزئیات ‌" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:152 +msgid "Edit" +msgstr "ویرایش" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:153 +msgid "Delete" +msgstr "حذف" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:155 +msgid "Event will be deleted permanently, are you sure?" +msgstr "رویداد حذف خواهد شد. آیا مطمئن هستید؟" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:156 +#: addons/web_calendar/static/src/js/calendar.js:169 +msgid "Description" +msgstr "توضیحات" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:157 +msgid "Time period" +msgstr "بازه زمانی" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:158 +msgid "Full day" +msgstr "تمام روز" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:161 +msgid "Do you want to edit the whole set of repeated events?" +msgstr "آیا میخواهید مجموعه کامل رویدادهای تکراری را ویرایش کنید؟" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:162 +msgid "Repeat event" +msgstr "تکرار رویداد" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:163 +msgid "Disabled" +msgstr "غیرفعال" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:164 +msgid "Enabled" +msgstr "فعال" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:167 +#: addons/web_calendar/static/src/js/calendar.js:175 +msgid "Agenda" +msgstr "دستور کار" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:168 +msgid "Date" +msgstr "تاریخ" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:172 +msgid "Year" +msgstr "سال" + +#. openerp-web +#: addons/web_calendar/static/src/xml/web_calendar.xml:5 +#: addons/web_calendar/static/src/xml/web_calendar.xml:6 +msgid " " +msgstr "" + +#~ msgid "Navigator" +#~ msgstr "هدایتگر" diff --git a/addons/web_diagram/i18n/fa.po b/addons/web_diagram/i18n/fa.po new file mode 100644 index 00000000000..061e2ca2950 --- /dev/null +++ b/addons/web_diagram/i18n/fa.po @@ -0,0 +1,81 @@ +# Persian translation for openerp-web +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-07-02 09:06+0200\n" +"PO-Revision-Date: 2012-10-03 10:07+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Persian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n" +"X-Generator: Launchpad (build 16061)\n" + +#. openerp-web +#: addons/web_diagram/static/src/js/diagram.js:11 +msgid "Diagram" +msgstr "نمودار" + +#. openerp-web +#: addons/web_diagram/static/src/js/diagram.js:165 +msgid "Are you sure?" +msgstr "آیا مطمئن هستید؟" + +#. openerp-web +#: addons/web_diagram/static/src/js/diagram.js:195 +msgid "" +"Deleting this node cannot be undone.\n" +"It will also delete all connected transitions.\n" +"\n" +"Are you sure ?" +msgstr "" +"عمل حذف برگشت پذیر نیست.\n" +"همچنین تمام اتصال ها را نیز حذف میکند.\n" +"\n" +"آیا مطمئن هستید؟" + +#. openerp-web +#: addons/web_diagram/static/src/js/diagram.js:213 +msgid "" +"Deleting this transition cannot be undone.\n" +"\n" +"Are you sure ?" +msgstr "" +"حذف این انتقال برگشت پذیر نیست.\n" +"\n" +"آیا از خذف مطمئن هستید؟" + +#. openerp-web +#: addons/web_diagram/static/src/js/diagram.js:224 +#: addons/web_diagram/static/src/js/diagram.js:257 +msgid "Activity" +msgstr "فعالیت" + +#. openerp-web +#: addons/web_diagram/static/src/js/diagram.js:232 +#: addons/web_diagram/static/src/js/diagram.js:296 +msgid "Open: " +msgstr "باز: " + +#. openerp-web +#: addons/web_diagram/static/src/js/diagram.js:262 +#: addons/web_diagram/static/src/js/diagram.js:314 +msgid "Create:" +msgstr "ایجاد کردن" + +#. openerp-web +#: addons/web_diagram/static/src/js/diagram.js:289 +#: addons/web_diagram/static/src/js/diagram.js:308 +msgid "Transition" +msgstr "انتقال" + +#. openerp-web +#: addons/web_diagram/static/src/xml/base_diagram.xml:6 +msgid "New Node" +msgstr "گره جدید" diff --git a/addons/web_gantt/i18n/fa.po b/addons/web_gantt/i18n/fa.po new file mode 100644 index 00000000000..1312a750199 --- /dev/null +++ b/addons/web_gantt/i18n/fa.po @@ -0,0 +1,28 @@ +# Persian translation for openerp-web +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-07-02 09:06+0200\n" +"PO-Revision-Date: 2012-10-03 10:11+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Persian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n" +"X-Generator: Launchpad (build 16061)\n" + +#. openerp-web +#: addons/web_gantt/static/src/js/gantt.js:11 +msgid "Gantt" +msgstr "گانت" + +#. openerp-web +#: addons/web_gantt/static/src/xml/web_gantt.xml:10 +msgid "Create" +msgstr "ایجاد کردن" diff --git a/addons/web_graph/i18n/fa.po b/addons/web_graph/i18n/fa.po new file mode 100644 index 00000000000..c21101d1941 --- /dev/null +++ b/addons/web_graph/i18n/fa.po @@ -0,0 +1,98 @@ +# Persian translation for openerp-web +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-07-02 09:06+0200\n" +"PO-Revision-Date: 2012-10-03 10:12+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Persian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n" +"X-Generator: Launchpad (build 16061)\n" + +#. openerp-web +#: addons/web_graph/static/src/js/graph.js:19 +msgid "Graph" +msgstr "گراف" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:5 +msgid "Graph Options" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:7 +msgid "Graph Mode" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:11 +msgid "Pie" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:12 +msgid "Bars" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:14 +msgid "Lines" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:15 +msgid "Areas" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:18 +msgid "Radar" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:20 +msgid "Legend" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:24 +msgid "Hidden" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:25 +msgid "Inside" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:26 +msgid "Top" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:28 +msgid "Actions" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:32 +msgid "Switch Axis" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:33 +msgid "Show Data" +msgstr "" + +#. openerp-web +#: addons/web_graph/static/src/xml/web_graph.xml:34 +msgid "Download as PNG" +msgstr "" diff --git a/addons/web_kanban/i18n/fa.po b/addons/web_kanban/i18n/fa.po new file mode 100644 index 00000000000..77588970169 --- /dev/null +++ b/addons/web_kanban/i18n/fa.po @@ -0,0 +1,66 @@ +# Persian translation for openerp-web +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-07-02 09:06+0200\n" +"PO-Revision-Date: 2012-10-03 10:14+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Persian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n" +"X-Generator: Launchpad (build 16061)\n" + +#. openerp-web +#: addons/web_kanban/static/src/js/kanban.js:10 +msgid "Kanban" +msgstr "" + +#. openerp-web +#: addons/web_kanban/static/src/js/kanban.js:293 +msgid "Undefined" +msgstr "تعریف نشده" + +#. openerp-web +#: addons/web_kanban/static/src/js/kanban.js:471 +msgid "Are you sure you want to delete this record ?" +msgstr "آیا از حذف این رکورد مطمئن هستید؟" + +#. openerp-web +#: addons/web_kanban/static/src/js/kanban.js:839 +msgid "Create: " +msgstr "" + +#. openerp-web +#: addons/web_kanban/static/src/xml/web_kanban.xml:41 +msgid "Show more... (" +msgstr "نمایش بیشتر" + +#. openerp-web +#: addons/web_kanban/static/src/xml/web_kanban.xml:41 +msgid "remaining)" +msgstr "" + +#. openerp-web +#: addons/web_kanban/static/src/xml/web_kanban.xml:71 +msgid "Add" +msgstr "" + +#. openerp-web +#: addons/web_kanban/static/src/xml/web_kanban.xml:71 +msgid "or" +msgstr "" + +#. openerp-web +#: addons/web_kanban/static/src/xml/web_kanban.xml:72 +msgid "Cancel" +msgstr "" + +#~ msgid "Create" +#~ msgstr "ایجاد کردن" From 601568f5f9431338886aa1aeda240a7137f16173 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 4 Oct 2012 08:42:15 +0200 Subject: [PATCH 196/409] [FIX] don't import empty cells at all rather than set them to False, to allow defaults handling to do its job before actually creating the record bzr revid: xmo@openerp.com-20121004064215-fqgir3ovmte2v438 --- openerp/osv/orm.py | 1 - openerp/tests/addons/test_impex/models.py | 10 ++++++++++ .../tests/addons/test_impex/tests/test_load.py | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 4f21a159cdd..b0b0fad88fa 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1501,7 +1501,6 @@ class BaseModel(object): for field, strvalue in record.iteritems(): if field in (None, 'id', '.id'): continue if not strvalue: - converted[field] = False continue # In warnings and error messages, use translated string as diff --git a/openerp/tests/addons/test_impex/models.py b/openerp/tests/addons/test_impex/models.py index 3c85b56fff7..50340082d08 100644 --- a/openerp/tests/addons/test_impex/models.py +++ b/openerp/tests/addons/test_impex/models.py @@ -123,3 +123,13 @@ class Many2ManyChild(orm.Model): , context=context) if isinstance(name, basestring) and name.split(':')[0] == self._name else []) + +class SelectionWithDefault(orm.Model): + _name = 'export.selection.withdefault' + + _columns = { + 'value': fields.selection([(1, "Foo"), (2, "Bar")], required=True), + } + _defaults = { + 'value': 2, + } diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py index 18b26a16354..65c4b6e9e57 100644 --- a/openerp/tests/addons/test_impex/tests/test_load.py +++ b/openerp/tests/addons/test_impex/tests/test_load.py @@ -474,6 +474,21 @@ class test_selection(ImporterCase): u"Value '42' not found in selection field 'unknown'", moreinfo="Foo Bar Qux 4".split())]) +class test_selection_with_default(ImporterCase): + model_name = 'export.selection.withdefault' + + def test_skip_empty(self): + """ Empty cells should be entirely skipped so that default values can + be inserted by the ORM + """ + result = self.import_(['value'], [['']]) + self.assertFalse(result['messages']) + self.assertEqual(len(result['ids']), 1) + + self.assertEqual( + values(self.read()), + [2]) + class test_selection_function(ImporterCase): model_name = 'export.selection.function' translations_fr = [ From c51c904e7d45b3c1aba82dd1217c6258a3021b17 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Thu, 4 Oct 2012 09:00:55 +0200 Subject: [PATCH 197/409] [FIX] Fixed bug in 'SelectCreatePopup', it didn't returned the corrrect stuff (r.result->r). bzr revid: vta@openerp.com-20121004070055-dq6kvaqlph6q1ei6 --- addons/web/static/src/js/view_form.js | 4 ++-- addons/web/static/src/js/views.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index bf6b869482b..1c32d5ef63e 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2081,7 +2081,7 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w var self = this; var trans = new instance.web.DataSet(this, 'ir.translation'); return trans.call_button('translate_fields', [this.view.dataset.model, this.view.datarecord.id, this.name, this.view.dataset.get_context()]).then(function(r) { - self.do_action(r.result); + self.do_action(r); }); }, }); @@ -4282,7 +4282,7 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({ this.dataset.create_function = function(data, sup) { var fct = self.options.create_function || sup; return fct.call(this, data).then(function(r) { - self.created_elements.push(r.result); + self.created_elements.push(r); }); }; this.dataset.write_function = function(id, data, options, sup) { diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 2fff0e7b683..7b5fcc70289 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -1190,7 +1190,7 @@ instance.web.View = instance.web.Widget.extend({ var context = new instance.web.CompoundContext(dataset.get_context(), action_data.context || {}); var handler = function (r) { - var action = r.result; + var action = r; if (action && action.constructor == Object) { var ncontext = new instance.web.CompoundContext(context); if (record_id) { From 6aba62a847daf134ea56e5421eae9496485b06ec Mon Sep 17 00:00:00 2001 From: "Jalpesh Patel (OpenERP)" Date: Thu, 4 Oct 2012 12:32:27 +0530 Subject: [PATCH 198/409] [fix]fix problem of send RFQ bzr revid: pja@tinyerp.com-20121004070227-rqo5ec0mckj5vqx8 --- addons/email_template/email_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py index 1dc79dc634c..37dca4ceddb 100644 --- a/addons/email_template/email_template.py +++ b/addons/email_template/email_template.py @@ -319,7 +319,7 @@ class email_template(osv.osv): ext = "." + format if not report_name.endswith(ext): report_name += ext - attachments.append(report_name, result) + attachments.append((report_name, result)) # Add template attachments for attach in template.attachment_ids: From 29a53e19546570b97932d163a0c2d0a2acf4a7ff Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 4 Oct 2012 09:46:10 +0200 Subject: [PATCH 199/409] [REV] header template extraction bzr revid: xmo@openerp.com-20121004074610-o2wk9nspzgqjj4y1 --- addons/web/static/src/xml/base.xml | 6 ---- doc/images/templates/ui.Header.png | Bin 2844 -> 0 bytes doc/index.rst | 2 -- doc/templates.rst | 45 ----------------------------- 4 files changed, 53 deletions(-) delete mode 100644 doc/images/templates/ui.Header.png delete mode 100644 doc/templates.rst diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index dfe86036c45..cead483ead6 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -2,12 +2,6 @@ - -
    - -
    -
    -
    diff --git a/doc/images/templates/ui.Header.png b/doc/images/templates/ui.Header.png deleted file mode 100644 index c5a1e2a8ef87c2d50eaf371dc07152aa436b7820..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2844 zcmX|DXFMBPAEwpU9;I5fwYj~jHjP<(kEm5@Bt~P`OeMsOO{-L0qZNCE8Y!jJrrg?M z)K)Y046PvE^j`1#;hf+3@chm>|Mfgi++&b7BONCl1qB78u8xKY1qEe3`OHmog}keC zYu8aw&@Jg|sG1?Bw%?tYn&LUT5BXqS7)Kf7D#5br?UJe@S$U@J*b!F+mu==_|I#Dy zt_VCnA0`w(UjDdn`-P)7CsJ1k@ zd*@hA?tCTH0vwMLip+hK5=^Daa%^u10?pO?6^jcAg?C`imQ#v&6#fM;1_&>RsSS0d45hjZf#A=%b~M(QRmg?xJ!eoVx~6=y?XU(%#(@_%(SkwbZ+!CzvkJm zB=p)&H2rhW>py1hUE;Lz_hZ-}xb64fN}FEXy$~L2h9(e~b;NVgZrFE}-pPKORoPEJVPMy7dC|dC^@rDw@v70DZ zP=TO+?2)CItW12raA>`+y121pjN-rfE~7xJS!HmITIL58&nz@v2voIo2mXy(775(x`lHwk`v4`-osH zwt+xEs;j4*pFf%p#^*pf7FVRr$^^h7K z1!D8x3##@nddL20)6QWhwM4w;!ElYHn%W6ru9SM-!C@pJ^lq=T?AU~$k=}<^lIXqY zvcxY#cf#RZJrJGJ-n>Na0llERHXtN7qC*Boq8 z%vFI=?ViGWcLfF}L8sim6Bie?I5~?v=e0(_d~i%kN;2#XBbV9!zUk7^n2qRaG8MIQ z`ui;g=1O0|tL8N7TnCozL)mLDX|E-pIn_62@!gL0F(^KILmF-3SnAUZF9C%oiX`dj zaKCc0Bi)ZH(B^mPPJ?S|j++UIxH=MBI@y=@`UW-SYl0U4`xF2nI zPK3P1R{A006RN1xuiKP{BK4d8_5^;0K~RiF(j1zilgO&dcdZ#}A2tR5EQ# zrI?HyJwaUya#)E>d6S;bL|w?H_v<`(SkXpGT)$wo zK&h`n)pX--IOeLvhiGXrc11;rOmHL`M67;-(N@Dp+^FLdro}5NHq=^5O0F#ly`)81 zdRQXhlk@WzgWn-|zk1Xs_b6W8#GVn;;FX?;IND$^8Yt!W7@+1cD<8^x?hBchsOLVX zQ*M#;*hfWR4L84dQ^o*KSCo``3JP@dub=nioAereFjR`I=QC_=@0!LyW zdcZ|`;aJjMp-YXt_S1SKJfGJ;{K=NFI=t5Cs9hcxZ)#Pk<;-f%9$?30si~`)Pqg^lC=?b|yks&xt*`UDG zqWg=!+zN>hPu#Y=*zFqTJL_(l9B~nq3uxJ>Z7?BuW~7*o@jp_)auZCAPQyfcUSeYN)>fcRSlGyB zIbS~@3*^k>7!fT|ZJ45Wnhq&>o2H9InzQQO5?$Lc$qgWyg_q>1-!mQ4X|T3hUK<41 zLet`YGfCmd`dht~=0g3$v$KQQ8M?WUX)t?3J>&Q|lbP9DDylt2MY`G90EEkIjcdEz zP}Qg^omdxkL$+A(2 zOaBX2mOALU^TvH;j+^r86AL)rkuY}Xoi{u0C)QZb@&!|goso3QOs0MArc_ULeYkjS z^O>OdRcV_>{!UEeOkiIxAWO?}jOA^u{mYg<5Sy3;h8VQC^9xnh_IIwv>%1&W@2!9rwIJwGq3b* zAS(z0NwBF{I(*lBUVFYayc!#OAYx57GlKwwfv1AQwa*!mKMxw4GQOSSa7odqA3x5< z%7%SxE_s84#DH^#!F0Ye!w_6y>e5)NMmCip4)lN8J&AF?mbpW2(pr73XW0NmSEoDp zMyr`DRFYA0WRa7>TWqyE{p9VWdKQzhdl%HNa(L5_LsGAASxSbL%z%A>SqLQfsG-tp zU}LOaRFr8W`isJy)i|f-80yRuH2POuIgxmz27#cnA>nm!blC&HaVNgiIw!_~)e5U9 z3D0b9ZnJ`dWn{p@9_AW(a;BYdluO(U^jBn<3?katMh4Kqd2&eEQ1r=n3NG@K``mU5 zNYN-Ytn;@w20#V(vC_~=OKero(`qgB8yqWp>h{J)j#p*8x|*~i+HSgbb8wa7U$sE} z#ZS|&B&_&DK-gdGsqd@)0hrG>n6H&3wEpv+x*FZ*8DVE<>fq@p6~ckg`Cf+y{HODo z?4|#x`Nxc5%!KM~Nbo<4Zx{{2I=c^6=qnhU@h?*!@DO;|+c#TIV3%+r*-dSAw13f$ z{OSb>Z3>#Z71{|&$W*Cf5#?2(vHUTabJ_kUyQLi7ar&o12=6GbHZ}E1qwHx#qW9A*Gr+R3DT%gvqSwCt!a{b diff --git a/doc/index.rst b/doc/index.rst index a6d2248cedf..6a0d8dee2d4 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -22,8 +22,6 @@ Contents: list-view form-notes - templates - guides/client-action Indices and tables diff --git a/doc/templates.rst b/doc/templates.rst deleted file mode 100644 index 3f7a3a18743..00000000000 --- a/doc/templates.rst +++ /dev/null @@ -1,45 +0,0 @@ -.. highlight:: xml - -Generic templates -================= - -Generic template names should be prefixed by ``ui.`` to indicate their -special role. - -Global Header: ``ui.Header`` ----------------------------- - -Role -++++ - -This template is mostly dedicated to client actions taking over the -whole content area, and full-HTML form views (especially those opening -in the ``inline`` target). - -It is used to display a buttons container (and can also be used for -status bars). The buttons should simply be placed inside the -``ui.Header`` body. - -Arguments -+++++++++ - -The template only uses its body as argument. - -Example -+++++++ - -:: - - -