diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py
index 7364ea505f6..0debdf11492 100644
--- a/addons/audittrail/audittrail.py
+++ b/addons/audittrail/audittrail.py
@@ -20,7 +20,7 @@
##############################################################################
from openerp.osv import fields, osv
-from openerp.osv.osv import object_proxy
+import openerp.service.model
from openerp.tools.translate import _
from openerp import pooler
import time
@@ -171,355 +171,360 @@ class audittrail_log_line(osv.osv):
'field_description': fields.char('Field Description', size=64),
}
-class audittrail_objects_proxy(object_proxy):
- """ Uses Object proxy for auditing changes on object of subscribed Rules"""
+# Monkeypatch the model RPC endpoint for auditing changes.
- def get_value_text(self, cr, uid, pool, resource_pool, method, field, value):
- """
- Gets textual values for the fields.
- If the field is a many2one, it returns the name.
- If it's a one2many or a many2many, it returns a list of name.
- In other cases, it just returns the value.
- :param cr: the current row, from the database cursor,
- :param uid: the current user’s ID for security checks,
- :param pool: current db's pooler object.
- :param resource_pool: pooler object of the model which values are being changed.
- :param field: for which the text value is to be returned.
- :param value: value of the field.
- :param recursive: True or False, True will repeat the process recursively
- :return: string value or a list of values(for O2M/M2M)
- """
+def get_value_text(cr, uid, pool, resource_pool, method, field, value):
+ """
+ Gets textual values for the fields.
+ If the field is a many2one, it returns the name.
+ If it's a one2many or a many2many, it returns a list of name.
+ In other cases, it just returns the value.
+ :param cr: the current row, from the database cursor,
+ :param uid: the current user’s ID for security checks,
+ :param pool: current db's pooler object.
+ :param resource_pool: pooler object of the model which values are being changed.
+ :param field: for which the text value is to be returned.
+ :param value: value of the field.
+ :param recursive: True or False, True will repeat the process recursively
+ :return: string value or a list of values(for O2M/M2M)
+ """
- field_obj = (resource_pool._all_columns.get(field)).column
- if field_obj._type in ('one2many','many2many'):
- data = pool.get(field_obj._obj).name_get(cr, uid, value)
- #return the modifications on x2many fields as a list of names
- res = map(lambda x:x[1], data)
- elif field_obj._type == 'many2one':
- #return the modifications on a many2one field as its value returned by name_get()
- res = value and value[1] or value
- else:
- res = value
- return res
+ field_obj = (resource_pool._all_columns.get(field)).column
+ if field_obj._type in ('one2many','many2many'):
+ data = pool.get(field_obj._obj).name_get(cr, uid, value)
+ #return the modifications on x2many fields as a list of names
+ res = map(lambda x:x[1], data)
+ elif field_obj._type == 'many2one':
+ #return the modifications on a many2one field as its value returned by name_get()
+ res = value and value[1] or value
+ else:
+ res = value
+ return res
- def create_log_line(self, cr, uid, log_id, model, lines=None):
- """
- Creates lines for changed fields with its old and new values
+def create_log_line(cr, uid, log_id, model, lines=None):
+ """
+ Creates lines for changed fields with its old and new values
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param model: Object which values are being changed
- @param lines: List of values for line is to be created
- """
- if lines is None:
- lines = []
- pool = pooler.get_pool(cr.dbname)
- obj_pool = pool.get(model.model)
- model_pool = pool.get('ir.model')
- field_pool = pool.get('ir.model.fields')
- log_line_pool = pool.get('audittrail.log.line')
- for line in lines:
- field_obj = obj_pool._all_columns.get(line['name'])
- assert field_obj, _("'%s' field does not exist in '%s' model" %(line['name'], model.model))
- field_obj = field_obj.column
- old_value = line.get('old_value', '')
- new_value = line.get('new_value', '')
- search_models = [model.id]
- if obj_pool._inherits:
- search_models += model_pool.search(cr, uid, [('model', 'in', obj_pool._inherits.keys())])
- field_id = field_pool.search(cr, uid, [('name', '=', line['name']), ('model_id', 'in', search_models)])
- if field_obj._type == 'many2one':
- old_value = old_value and old_value[0] or old_value
- new_value = new_value and new_value[0] or new_value
- vals = {
- "log_id": log_id,
- "field_id": field_id and field_id[0] or False,
- "old_value": old_value,
- "new_value": new_value,
- "old_value_text": line.get('old_value_text', ''),
- "new_value_text": line.get('new_value_text', ''),
- "field_description": field_obj.string
- }
- line_id = log_line_pool.create(cr, uid, vals)
- return True
-
- def log_fct(self, cr, uid_orig, model, method, fct_src, *args, **kw):
- """
- Logging function: This function is performing the logging operation
- @param model: Object whose values are being changed
- @param method: method to log: create, read, write, unlink, action or workflow action
- @param fct_src: execute method of Object proxy
-
- @return: Returns result as per method of Object proxy
- """
- pool = pooler.get_pool(cr.dbname)
- resource_pool = pool.get(model)
- model_pool = pool.get('ir.model')
- model_ids = model_pool.search(cr, SUPERUSER_ID, [('model', '=', model)])
- model_id = model_ids and model_ids[0] or False
- assert model_id, _("'%s' Model does not exist..." %(model))
- model = model_pool.browse(cr, SUPERUSER_ID, model_id)
-
- # fields to log. currently only used by log on read()
- field_list = []
- old_values = new_values = {}
-
- if method == 'create':
- res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
- if res:
- res_ids = [res]
- new_values = self.get_data(cr, uid_orig, pool, res_ids, model, method)
- elif method == 'read':
- res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
- # build the res_ids and the old_values dict. Here we don't use get_data() to
- # avoid performing an additional read()
- res_ids = []
- for record in res:
- res_ids.append(record['id'])
- old_values[(model.id, record['id'])] = {'value': record, 'text': record}
- # log only the fields read
- field_list = args[1]
- elif method == 'unlink':
- res_ids = args[0]
- old_values = self.get_data(cr, uid_orig, pool, res_ids, model, method)
- res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
- else: # method is write, action or workflow action
- res_ids = []
- if args:
- res_ids = args[0]
- if isinstance(res_ids, (long, int)):
- res_ids = [res_ids]
- if res_ids:
- # store the old values into a dictionary
- old_values = self.get_data(cr, uid_orig, pool, res_ids, model, method)
- # process the original function, workflow trigger...
- res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
- if method == 'copy':
- res_ids = [res]
- if res_ids:
- # check the new values and store them into a dictionary
- new_values = self.get_data(cr, uid_orig, pool, res_ids, model, method)
- # compare the old and new values and create audittrail log if needed
- self.process_data(cr, uid_orig, pool, res_ids, model, method, old_values, new_values, field_list)
- return res
-
- def get_data(self, cr, uid, pool, res_ids, model, method):
- """
- This function simply read all the fields of the given res_ids, and also recurisvely on
- all records of a x2m fields read that need to be logged. Then it returns the result in
- convenient structure that will be used as comparison basis.
-
- :param cr: the current row, from the database cursor,
- :param uid: the current user’s ID. This parameter is currently not used as every
- operation to get data is made as super admin. Though, it could be usefull later.
- :param pool: current db's pooler object.
- :param res_ids: Id's of resource to be logged/compared.
- :param model: Object whose values are being changed
- :param method: method to log: create, read, unlink, write, actions, workflow actions
- :return: dict mapping a tuple (model_id, resource_id) with its value and textual value
- { (model_id, resource_id): { 'value': ...
- 'textual_value': ...
- },
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param model: Object which values are being changed
+ @param lines: List of values for line is to be created
+ """
+ if lines is None:
+ lines = []
+ pool = pooler.get_pool(cr.dbname)
+ obj_pool = pool.get(model.model)
+ model_pool = pool.get('ir.model')
+ field_pool = pool.get('ir.model.fields')
+ log_line_pool = pool.get('audittrail.log.line')
+ for line in lines:
+ field_obj = obj_pool._all_columns.get(line['name'])
+ assert field_obj, _("'%s' field does not exist in '%s' model" %(line['name'], model.model))
+ field_obj = field_obj.column
+ old_value = line.get('old_value', '')
+ new_value = line.get('new_value', '')
+ search_models = [model.id]
+ if obj_pool._inherits:
+ search_models += model_pool.search(cr, uid, [('model', 'in', obj_pool._inherits.keys())])
+ field_id = field_pool.search(cr, uid, [('name', '=', line['name']), ('model_id', 'in', search_models)])
+ if field_obj._type == 'many2one':
+ old_value = old_value and old_value[0] or old_value
+ new_value = new_value and new_value[0] or new_value
+ vals = {
+ "log_id": log_id,
+ "field_id": field_id and field_id[0] or False,
+ "old_value": old_value,
+ "new_value": new_value,
+ "old_value_text": line.get('old_value_text', ''),
+ "new_value_text": line.get('new_value_text', ''),
+ "field_description": field_obj.string
}
- """
- data = {}
- resource_pool = pool.get(model.model)
- # read all the fields of the given resources in super admin mode
- for resource in resource_pool.read(cr, SUPERUSER_ID, res_ids):
- values = {}
- values_text = {}
- resource_id = resource['id']
- # loop on each field on the res_ids we just have read
- for field in resource:
- if field in ('__last_update', 'id'):
- continue
- values[field] = resource[field]
- # get the textual value of that field for this record
- values_text[field] = self.get_value_text(cr, SUPERUSER_ID, pool, resource_pool, method, field, resource[field])
+ line_id = log_line_pool.create(cr, uid, vals)
+ return True
- field_obj = resource_pool._all_columns.get(field).column
- if field_obj._type in ('one2many','many2many'):
- # check if an audittrail rule apply in super admin mode
- if self.check_rules(cr, SUPERUSER_ID, field_obj._obj, method):
- # check if the model associated to a *2m field exists, in super admin mode
- x2m_model_ids = pool.get('ir.model').search(cr, SUPERUSER_ID, [('model', '=', field_obj._obj)])
- x2m_model_id = x2m_model_ids and x2m_model_ids[0] or False
- assert x2m_model_id, _("'%s' Model does not exist..." %(field_obj._obj))
- x2m_model = pool.get('ir.model').browse(cr, SUPERUSER_ID, x2m_model_id)
- field_resource_ids = list(set(resource[field]))
- if model.model == x2m_model.model:
- # we need to remove current resource_id from the many2many to prevent an infinit loop
- if resource_id in field_resource_ids:
- field_resource_ids.remove(resource_id)
- data.update(self.get_data(cr, SUPERUSER_ID, pool, field_resource_ids, x2m_model, method))
-
- data[(model.id, resource_id)] = {'text':values_text, 'value': values}
- return data
+def log_fct(cr, uid_orig, model, method, fct_src, *args, **kw):
+ """
+ Logging function: This function is performing the logging operation
+ @param model: Object whose values are being changed
+ @param method: method to log: create, read, write, unlink, action or workflow action
+ @param fct_src: execute method of Object proxy
- def prepare_audittrail_log_line(self, cr, uid, pool, model, resource_id, method, old_values, new_values, field_list=None):
- """
- This function compares the old data (i.e before the method was executed) and the new data
- (after the method was executed) and returns a structure with all the needed information to
- log those differences.
+ @return: Returns result as per method of Object proxy
+ """
+ pool = pooler.get_pool(cr.dbname)
+ resource_pool = pool.get(model)
+ model_pool = pool.get('ir.model')
+ model_ids = model_pool.search(cr, SUPERUSER_ID, [('model', '=', model)])
+ model_id = model_ids and model_ids[0] or False
+ assert model_id, _("'%s' Model does not exist..." %(model))
+ model = model_pool.browse(cr, SUPERUSER_ID, model_id)
+
+ # fields to log. currently only used by log on read()
+ field_list = []
+ old_values = new_values = {}
+
+ if method == 'create':
+ res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
+ if res:
+ res_ids = [res]
+ new_values = get_data(cr, uid_orig, pool, res_ids, model, method)
+ elif method == 'read':
+ res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
+ # build the res_ids and the old_values dict. Here we don't use get_data() to
+ # avoid performing an additional read()
+ res_ids = []
+ for record in res:
+ res_ids.append(record['id'])
+ old_values[(model.id, record['id'])] = {'value': record, 'text': record}
+ # log only the fields read
+ field_list = args[1]
+ elif method == 'unlink':
+ res_ids = args[0]
+ old_values = get_data(cr, uid_orig, pool, res_ids, model, method)
+ res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
+ else: # method is write, action or workflow action
+ res_ids = []
+ if args:
+ res_ids = args[0]
+ if isinstance(res_ids, (long, int)):
+ res_ids = [res_ids]
+ if res_ids:
+ # store the old values into a dictionary
+ old_values = get_data(cr, uid_orig, pool, res_ids, model, method)
+ # process the original function, workflow trigger...
+ res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
+ if method == 'copy':
+ res_ids = [res]
+ if res_ids:
+ # check the new values and store them into a dictionary
+ new_values = get_data(cr, uid_orig, pool, res_ids, model, method)
+ # compare the old and new values and create audittrail log if needed
+ process_data(cr, uid_orig, pool, res_ids, model, method, old_values, new_values, field_list)
+ return res
+
+def get_data(cr, uid, pool, res_ids, model, method):
+ """
+ This function simply read all the fields of the given res_ids, and also recurisvely on
+ all records of a x2m fields read that need to be logged. Then it returns the result in
+ convenient structure that will be used as comparison basis.
:param cr: the current row, from the database cursor,
:param uid: the current user’s ID. This parameter is currently not used as every
operation to get data is made as super admin. Though, it could be usefull later.
:param pool: current db's pooler object.
- :param model: model object which values are being changed
- :param resource_id: ID of record to which values are being changed
+ :param res_ids: Id's of resource to be logged/compared.
+ :param model: Object whose values are being changed
:param method: method to log: create, read, unlink, write, actions, workflow actions
- :param old_values: dict of values read before execution of the method
- :param new_values: dict of values read after execution of the method
- :param field_list: optional argument containing the list of fields to log. Currently only
- used when performing a read, it could be usefull later on if we want to log the write
- on specific fields only.
-
- :return: dictionary with
- * keys: tuples build as ID of model object to log and ID of resource to log
- * values: list of all the changes in field values for this couple (model, resource)
- return {
- (model.id, resource_id): []
- }
-
- The reason why the structure returned is build as above is because when modifying an existing
- record, we may have to log a change done in a x2many field of that object
- """
- if field_list is None:
- field_list = []
- key = (model.id, resource_id)
- lines = {
- key: []
- }
- # loop on all the fields
- for field_name, field_definition in pool.get(model.model)._all_columns.items():
- if field_name in ('__last_update', 'id'):
+ :return: dict mapping a tuple (model_id, resource_id) with its value and textual value
+ { (model_id, resource_id): { 'value': ...
+ 'textual_value': ...
+ },
+ }
+ """
+ data = {}
+ resource_pool = pool.get(model.model)
+ # read all the fields of the given resources in super admin mode
+ for resource in resource_pool.read(cr, SUPERUSER_ID, res_ids):
+ values = {}
+ values_text = {}
+ resource_id = resource['id']
+ # loop on each field on the res_ids we just have read
+ for field in resource:
+ if field in ('__last_update', 'id'):
continue
- #if the field_list param is given, skip all the fields not in that list
- if field_list and field_name not in field_list:
- continue
- field_obj = field_definition.column
+ values[field] = resource[field]
+ # get the textual value of that field for this record
+ values_text[field] = get_value_text(cr, SUPERUSER_ID, pool, resource_pool, method, field, resource[field])
+
+ field_obj = resource_pool._all_columns.get(field).column
if field_obj._type in ('one2many','many2many'):
- # checking if an audittrail rule apply in super admin mode
- if self.check_rules(cr, SUPERUSER_ID, field_obj._obj, method):
- # checking if the model associated to a *2m field exists, in super admin mode
+ # check if an audittrail rule apply in super admin mode
+ if check_rules(cr, SUPERUSER_ID, field_obj._obj, method):
+ # check if the model associated to a *2m field exists, in super admin mode
x2m_model_ids = pool.get('ir.model').search(cr, SUPERUSER_ID, [('model', '=', field_obj._obj)])
x2m_model_id = x2m_model_ids and x2m_model_ids[0] or False
assert x2m_model_id, _("'%s' Model does not exist..." %(field_obj._obj))
x2m_model = pool.get('ir.model').browse(cr, SUPERUSER_ID, x2m_model_id)
- # the resource_ids that need to be checked are the sum of both old and previous values (because we
- # need to log also creation or deletion in those lists).
- x2m_old_values_ids = old_values.get(key, {'value': {}})['value'].get(field_name, [])
- x2m_new_values_ids = new_values.get(key, {'value': {}})['value'].get(field_name, [])
- # We use list(set(...)) to remove duplicates.
- res_ids = list(set(x2m_old_values_ids + x2m_new_values_ids))
+ field_resource_ids = list(set(resource[field]))
if model.model == x2m_model.model:
# we need to remove current resource_id from the many2many to prevent an infinit loop
- if resource_id in res_ids:
- res_ids.remove(resource_id)
- for res_id in res_ids:
- lines.update(self.prepare_audittrail_log_line(cr, SUPERUSER_ID, pool, x2m_model, res_id, method, old_values, new_values, field_list))
- # if the value value is different than the old value: record the change
- if key not in old_values or key not in new_values or old_values[key]['value'][field_name] != new_values[key]['value'][field_name]:
- data = {
- 'name': field_name,
- 'new_value': key in new_values and new_values[key]['value'].get(field_name),
- 'old_value': key in old_values and old_values[key]['value'].get(field_name),
- 'new_value_text': key in new_values and new_values[key]['text'].get(field_name),
- 'old_value_text': key in old_values and old_values[key]['text'].get(field_name)
- }
- lines[key].append(data)
- return lines
+ if resource_id in field_resource_ids:
+ field_resource_ids.remove(resource_id)
+ data.update(get_data(cr, SUPERUSER_ID, pool, field_resource_ids, x2m_model, method))
- def process_data(self, cr, uid, pool, res_ids, model, method, old_values=None, new_values=None, field_list=None):
- """
- This function processes and iterates recursively to log the difference between the old
- data (i.e before the method was executed) and the new data and creates audittrail log
- accordingly.
+ data[(model.id, resource_id)] = {'text':values_text, 'value': values}
+ return data
- :param cr: the current row, from the database cursor,
- :param uid: the current user’s ID,
- :param pool: current db's pooler object.
- :param res_ids: Id's of resource to be logged/compared.
- :param model: model object which values are being changed
- :param method: method to log: create, read, unlink, write, actions, workflow actions
- :param old_values: dict of values read before execution of the method
- :param new_values: dict of values read after execution of the method
- :param field_list: optional argument containing the list of fields to log. Currently only
- used when performing a read, it could be usefull later on if we want to log the write
- on specific fields only.
- :return: True
- """
- if field_list is None:
- field_list = []
- # loop on all the given ids
- for res_id in res_ids:
- # compare old and new values and get audittrail log lines accordingly
- lines = self.prepare_audittrail_log_line(cr, uid, pool, model, res_id, method, old_values, new_values, field_list)
+def prepare_audittrail_log_line(cr, uid, pool, model, resource_id, method, old_values, new_values, field_list=None):
+ """
+ This function compares the old data (i.e before the method was executed) and the new data
+ (after the method was executed) and returns a structure with all the needed information to
+ log those differences.
- # if at least one modification has been found
- for model_id, resource_id in lines:
- name = pool.get(model.model).name_get(cr, uid, [resource_id])[0][1]
- vals = {
- 'method': method,
- 'object_id': model_id,
- 'user_id': uid,
- 'res_id': resource_id,
- 'name': name,
- }
- if (model_id, resource_id) not in old_values and method not in ('copy', 'read'):
- # the resource was not existing so we are forcing the method to 'create'
- # (because it could also come with the value 'write' if we are creating
- # new record through a one2many field)
- vals.update({'method': 'create'})
- if (model_id, resource_id) not in new_values and method not in ('copy', 'read'):
- # the resource is not existing anymore so we are forcing the method to 'unlink'
- # (because it could also come with the value 'write' if we are deleting the
- # record through a one2many field)
- vals.update({'method': 'unlink'})
- # create the audittrail log in super admin mode, only if a change has been detected
- if lines[(model_id, resource_id)]:
- log_id = pool.get('audittrail.log').create(cr, SUPERUSER_ID, vals)
- model = pool.get('ir.model').browse(cr, uid, model_id)
- self.create_log_line(cr, SUPERUSER_ID, log_id, model, lines[(model_id, resource_id)])
- return True
+ :param cr: the current row, from the database cursor,
+ :param uid: the current user’s ID. This parameter is currently not used as every
+ operation to get data is made as super admin. Though, it could be usefull later.
+ :param pool: current db's pooler object.
+ :param model: model object which values are being changed
+ :param resource_id: ID of record to which values are being changed
+ :param method: method to log: create, read, unlink, write, actions, workflow actions
+ :param old_values: dict of values read before execution of the method
+ :param new_values: dict of values read after execution of the method
+ :param field_list: optional argument containing the list of fields to log. Currently only
+ used when performing a read, it could be usefull later on if we want to log the write
+ on specific fields only.
- def check_rules(self, cr, uid, model, method):
- """
- Checks if auditrails is installed for that db and then if one rule match
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID,
- @param model: value of _name of the object which values are being changed
- @param method: method to log: create, read, unlink,write,actions,workflow actions
- @return: True or False
- """
- pool = pooler.get_pool(cr.dbname)
- if 'audittrail.rule' in pool.models:
- model_ids = pool.get('ir.model').search(cr, SUPERUSER_ID, [('model', '=', model)])
- model_id = model_ids and model_ids[0] or False
- if model_id:
- rule_ids = pool.get('audittrail.rule').search(cr, SUPERUSER_ID, [('object_id', '=', model_id), ('state', '=', 'subscribed')])
- for rule in pool.get('audittrail.rule').read(cr, SUPERUSER_ID, rule_ids, ['user_id','log_read','log_write','log_create','log_unlink','log_action','log_workflow']):
- if len(rule['user_id']) == 0 or uid in rule['user_id']:
- if rule.get('log_'+method,0):
+ :return: dictionary with
+ * keys: tuples build as ID of model object to log and ID of resource to log
+ * values: list of all the changes in field values for this couple (model, resource)
+ return {
+ (model.id, resource_id): []
+ }
+
+ The reason why the structure returned is build as above is because when modifying an existing
+ record, we may have to log a change done in a x2many field of that object
+ """
+ if field_list is None:
+ field_list = []
+ key = (model.id, resource_id)
+ lines = {
+ key: []
+ }
+ # loop on all the fields
+ for field_name, field_definition in pool.get(model.model)._all_columns.items():
+ if field_name in ('__last_update', 'id'):
+ continue
+ #if the field_list param is given, skip all the fields not in that list
+ if field_list and field_name not in field_list:
+ continue
+ field_obj = field_definition.column
+ if field_obj._type in ('one2many','many2many'):
+ # checking if an audittrail rule apply in super admin mode
+ if check_rules(cr, SUPERUSER_ID, field_obj._obj, method):
+ # checking if the model associated to a *2m field exists, in super admin mode
+ x2m_model_ids = pool.get('ir.model').search(cr, SUPERUSER_ID, [('model', '=', field_obj._obj)])
+ x2m_model_id = x2m_model_ids and x2m_model_ids[0] or False
+ assert x2m_model_id, _("'%s' Model does not exist..." %(field_obj._obj))
+ x2m_model = pool.get('ir.model').browse(cr, SUPERUSER_ID, x2m_model_id)
+ # the resource_ids that need to be checked are the sum of both old and previous values (because we
+ # need to log also creation or deletion in those lists).
+ x2m_old_values_ids = old_values.get(key, {'value': {}})['value'].get(field_name, [])
+ x2m_new_values_ids = new_values.get(key, {'value': {}})['value'].get(field_name, [])
+ # We use list(set(...)) to remove duplicates.
+ res_ids = list(set(x2m_old_values_ids + x2m_new_values_ids))
+ if model.model == x2m_model.model:
+ # we need to remove current resource_id from the many2many to prevent an infinit loop
+ if resource_id in res_ids:
+ res_ids.remove(resource_id)
+ for res_id in res_ids:
+ lines.update(prepare_audittrail_log_line(cr, SUPERUSER_ID, pool, x2m_model, res_id, method, old_values, new_values, field_list))
+ # if the value value is different than the old value: record the change
+ if key not in old_values or key not in new_values or old_values[key]['value'][field_name] != new_values[key]['value'][field_name]:
+ data = {
+ 'name': field_name,
+ 'new_value': key in new_values and new_values[key]['value'].get(field_name),
+ 'old_value': key in old_values and old_values[key]['value'].get(field_name),
+ 'new_value_text': key in new_values and new_values[key]['text'].get(field_name),
+ 'old_value_text': key in old_values and old_values[key]['text'].get(field_name)
+ }
+ lines[key].append(data)
+ return lines
+
+def process_data(cr, uid, pool, res_ids, model, method, old_values=None, new_values=None, field_list=None):
+ """
+ This function processes and iterates recursively to log the difference between the old
+ data (i.e before the method was executed) and the new data and creates audittrail log
+ accordingly.
+
+ :param cr: the current row, from the database cursor,
+ :param uid: the current user’s ID,
+ :param pool: current db's pooler object.
+ :param res_ids: Id's of resource to be logged/compared.
+ :param model: model object which values are being changed
+ :param method: method to log: create, read, unlink, write, actions, workflow actions
+ :param old_values: dict of values read before execution of the method
+ :param new_values: dict of values read after execution of the method
+ :param field_list: optional argument containing the list of fields to log. Currently only
+ used when performing a read, it could be usefull later on if we want to log the write
+ on specific fields only.
+ :return: True
+ """
+ if field_list is None:
+ field_list = []
+ # loop on all the given ids
+ for res_id in res_ids:
+ # compare old and new values and get audittrail log lines accordingly
+ lines = prepare_audittrail_log_line(cr, uid, pool, model, res_id, method, old_values, new_values, field_list)
+
+ # if at least one modification has been found
+ for model_id, resource_id in lines:
+ name = pool.get(model.model).name_get(cr, uid, [resource_id])[0][1]
+ vals = {
+ 'method': method,
+ 'object_id': model_id,
+ 'user_id': uid,
+ 'res_id': resource_id,
+ 'name': name,
+ }
+ if (model_id, resource_id) not in old_values and method not in ('copy', 'read'):
+ # the resource was not existing so we are forcing the method to 'create'
+ # (because it could also come with the value 'write' if we are creating
+ # new record through a one2many field)
+ vals.update({'method': 'create'})
+ if (model_id, resource_id) not in new_values and method not in ('copy', 'read'):
+ # the resource is not existing anymore so we are forcing the method to 'unlink'
+ # (because it could also come with the value 'write' if we are deleting the
+ # record through a one2many field)
+ vals.update({'method': 'unlink'})
+ # create the audittrail log in super admin mode, only if a change has been detected
+ if lines[(model_id, resource_id)]:
+ log_id = pool.get('audittrail.log').create(cr, SUPERUSER_ID, vals)
+ model = pool.get('ir.model').browse(cr, uid, model_id)
+ create_log_line(cr, SUPERUSER_ID, log_id, model, lines[(model_id, resource_id)])
+ return True
+
+def check_rules(cr, uid, model, method):
+ """
+ Checks if auditrails is installed for that db and then if one rule match
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID,
+ @param model: value of _name of the object which values are being changed
+ @param method: method to log: create, read, unlink,write,actions,workflow actions
+ @return: True or False
+ """
+ pool = pooler.get_pool(cr.dbname)
+ if 'audittrail.rule' in pool.models:
+ model_ids = pool.get('ir.model').search(cr, SUPERUSER_ID, [('model', '=', model)])
+ model_id = model_ids and model_ids[0] or False
+ if model_id:
+ rule_ids = pool.get('audittrail.rule').search(cr, SUPERUSER_ID, [('object_id', '=', model_id), ('state', '=', 'subscribed')])
+ for rule in pool.get('audittrail.rule').read(cr, SUPERUSER_ID, rule_ids, ['user_id','log_read','log_write','log_create','log_unlink','log_action','log_workflow']):
+ if len(rule['user_id']) == 0 or uid in rule['user_id']:
+ if rule.get('log_'+method,0):
+ return True
+ elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create', 'read_group', 'import_data'):
+ if rule['log_action']:
return True
- elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create', 'read_group', 'import_data'):
- if rule['log_action']:
- return True
- def execute_cr(self, cr, uid, model, method, *args, **kw):
- fct_src = super(audittrail_objects_proxy, self).execute_cr
- if self.check_rules(cr,uid,model,method):
- return self.log_fct(cr, uid, model, method, fct_src, *args, **kw)
- return fct_src(cr, uid, model, method, *args, **kw)
+# Replace the openerp.service.model functions.
- def exec_workflow_cr(self, cr, uid, model, method, *args, **kw):
- fct_src = super(audittrail_objects_proxy, self).exec_workflow_cr
- if self.check_rules(cr,uid,model,'workflow'):
- return self.log_fct(cr, uid, model, method, fct_src, *args, **kw)
- return fct_src(cr, uid, model, method, *args, **kw)
+original_execute_cr = openerp.service.model.execute_cr
+original_exec_workflow_cr = openerp.service.model.exec_workflow_cr
-audittrail_objects_proxy()
+def execute_cr(cr, uid, model, method, *args, **kw):
+ fct_src = original_execute_cr
+ if check_rules(cr,uid,model,method):
+ return log_fct(cr, uid, model, method, fct_src, *args, **kw)
+ return fct_src(cr, uid, model, method, *args, **kw)
+
+def exec_workflow_cr(cr, uid, model, method, *args, **kw):
+ fct_src = original_exec_workflow_cr
+ if check_rules(cr,uid,model,'workflow'):
+ return log_fct(cr, uid, model, method, fct_src, *args, **kw)
+ return fct_src(cr, uid, model, method, *args, **kw)
+
+openerp.service.model.execute_cr = execute_cr
+openerp.service.model.exec_workflow_cr = exec_workflow_cr
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py
index ab0d8d324b4..ca75c9e20fc 100644
--- a/addons/base_calendar/base_calendar.py
+++ b/addons/base_calendar/base_calendar.py
@@ -24,12 +24,13 @@ from dateutil import parser
from dateutil import rrule
from dateutil.relativedelta import relativedelta
from openerp.osv import fields, osv
-from openerp.service import web_services
from openerp.tools.translate import _
import pytz
import re
import time
+
from openerp import tools, SUPERUSER_ID
+import openerp.service.report
months = {
1: "January", 2: "February", 3: "March", 4: "April", \
@@ -1729,27 +1730,25 @@ class ir_model(osv.osv):
ir_model()
-class virtual_report_spool(web_services.report_spool):
+original_exp_report = openerp.service.report.exp_report
- def exp_report(self, db, uid, object, ids, data=None, context=None):
- """
- Export Report
- @param self: The object pointer
- @param db: get the current database,
- @param uid: the current user's ID for security checks,
- @param context: A standard dictionary for contextual values
- """
+def exp_report(db, uid, object, ids, data=None, context=None):
+ """
+ Export Report
+ @param db: get the current database,
+ @param uid: the current user's ID for security checks,
+ @param context: A standard dictionary for contextual values
+ """
- if object == 'printscreen.list':
- return super(virtual_report_spool, self).exp_report(db, uid, \
- object, ids, data, context)
- new_ids = []
- for id in ids:
- new_ids.append(base_calendar_id2real_id(id))
- if data.get('id', False):
- data['id'] = base_calendar_id2real_id(data['id'])
- return super(virtual_report_spool, self).exp_report(db, uid, object, new_ids, data, context)
+ if object == 'printscreen.list':
+ original_exp_report(db, uid, object, ids, data, context)
+ new_ids = []
+ for id in ids:
+ new_ids.append(base_calendar_id2real_id(id))
+ if data.get('id', False):
+ data['id'] = base_calendar_id2real_id(data['id'])
+ return original_exp_report(db, uid, object, new_ids, data, context)
-virtual_report_spool()
+openerp.service.report.exp_report = exp_report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/base_import/i18n/hr.po b/addons/base_import/i18n/hr.po
index 7a119f19aaf..bc644bdfad5 100644
--- a/addons/base_import/i18n/hr.po
+++ b/addons/base_import/i18n/hr.po
@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME
\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-12-22 06:07+0000\n"
-"X-Generator: Launchpad (build 16378)\n"
+"X-Launchpad-Export-Date: 2013-02-13 04:36+0000\n"
+"X-Generator: Launchpad (build 16491)\n"
#. module: base_import
#. openerp-web
@@ -29,7 +29,7 @@ msgstr "Dohvati sve moguće vrijednosti"
#: code:addons/base_import/static/src/xml/import.xml:71
#, python-format
msgid "Need to import data from an other application?"
-msgstr ""
+msgstr "Potreban je uvoz podataka iz druge aplikacije?"
#. module: base_import
#. openerp-web
@@ -47,6 +47,15 @@ msgid ""
"give \n"
" you an example for Products and their Categories."
msgstr ""
+"Kada koristite vanjske ID-eve, možete uvesti csv datoteke \n"
+" sa kolonom \"External ID\" "
+"definirate vanjski ID svakog zapisa \n"
+" koji uvozite. Tada ćete biti "
+"u mogućnosti napraviti referencu \n"
+" na taj zapis sa kolonama tipa "
+"\"polje/External ID\". Sljedeća dvije \n"
+" csv datoteke daju primjer za "
+"proizvode i njihove kategorije."
#. module: base_import
#. openerp-web
@@ -56,13 +65,16 @@ msgid ""
"How to export/import different tables from an SQL \n"
" application to OpenERP?"
msgstr ""
+"Kako izvesti/uvesti različite tablice iz SQL \n"
+" "
+"programa u OpenERP"
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/js/import.js:310
#, python-format
msgid "Relation Fields"
-msgstr ""
+msgstr "Relacijska polja"
#. module: base_import
#. openerp-web
@@ -72,6 +84,9 @@ msgid ""
"Country/Database ID: the unique OpenERP ID for a \n"
" record, defined by the ID postgresql column"
msgstr ""
+"Država/ID baze: jedinstveni OpenERP ID za \n"
+" "
+" zapis, definran kolonom postgres kolonom ID"
#. module: base_import
#. openerp-web
@@ -87,6 +102,16 @@ msgid ""
"\n"
" have a unique Database ID)"
msgstr ""
+"Korištenje \n"
+" Država/ID "
+"BAze : ovo bi trebali rijetko koristiti\n"
+" za "
+"označavanje. Ovo je većinom korišteno od strane programera\n"
+" jer je "
+"glavna prednost ovoga to što nikad nema konflikata \n"
+" (možete "
+"imati više zapisa istog naziva, ali uvjek sa jedinstvenim IDentifikatorom u "
+"Bazi)"
#. module: base_import
#. openerp-web
@@ -96,6 +121,9 @@ msgid ""
"For the country \n"
" Belgium, you can use one of these 3 ways to import:"
msgstr ""
+"Za državu \n"
+" "
+" Belgiju, možete koristiti jedan od ova 3 načina uza uvoz:"
#. module: base_import
#. openerp-web
@@ -121,13 +149,20 @@ msgid ""
"companies) TO \n"
" '/tmp/company.csv' with CSV HEADER;"
msgstr ""
+"kopirajte \n"
+" (select "
+"'company_'||id as \"External ID\",company_name\n"
+" as "
+"\"Name\",'True' as \"Is a Company\" from companies) TO\n"
+" "
+"'/tmp/company.csv' with CSV HEADER;"
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/xml/import.xml:206
#, python-format
msgid "CSV file for Manufacturer, Retailer"
-msgstr ""
+msgstr "CSV datoteka za Proizvođače, Veletrgovce"
#. module: base_import
#. openerp-web
@@ -139,6 +174,11 @@ msgid ""
"\n"
" data from a third party application."
msgstr ""
+"Koristi \n"
+" Država/Vanjski ID. "
+"koristite vanjski ID kad uvozite \n"
+" podatke iz drugih "
+"aplikacija."
#. module: base_import
#. openerp-web
@@ -152,7 +192,7 @@ msgstr ""
#: code:addons/base_import/static/src/xml/import.xml:80
#, python-format
msgid "XXX/External ID"
-msgstr ""
+msgstr "XXX/Vanjski ID"
#. module: base_import
#. openerp-web
@@ -181,6 +221,14 @@ msgid ""
"\n"
" See the following question."
msgstr ""
+"Primjetite da vaša csv datoteka \n"
+" ima tabulator za "
+"odvajanje, a OpenERP neće \n"
+" primjetiti ta odvajanja. "
+"Morate promjineiti format \n"
+" zapisa u vašem tabličnom "
+"kalkulatoru. \n"
+" Vidi sljedeće pitanje."
#. module: base_import
#. openerp-web
@@ -199,7 +247,7 @@ msgstr ""
#: code:addons/base_import/static/src/xml/import.xml:239
#, python-format
msgid "Can I import several times the same record?"
-msgstr ""
+msgstr "Mogu li isti zapis uvesti nekoliko puta?"
#. module: base_import
#. openerp-web
@@ -213,7 +261,7 @@ msgstr "Potvrdi"
#: code:addons/base_import/static/src/xml/import.xml:55
#, python-format
msgid "Map your data to OpenERP"
-msgstr ""
+msgstr "Mapirajte vaše podatke na OpenERP"
#. module: base_import
#. openerp-web
@@ -224,6 +272,10 @@ msgid ""
" the easiest way when your data come from CSV files \n"
" that have been created manually."
msgstr ""
+"Korištenje Države: ovo je \n"
+" najlakši način kada vaši "
+"podaci dolaze iz csv datoteka\n"
+" koje su sastavljene ručno."
#. module: base_import
#. openerp-web
@@ -233,6 +285,8 @@ msgid ""
"What's the difference between Database ID and \n"
" External ID?"
msgstr ""
+"Koja je razlika izmeži ID Baze i \n"
+" vanjski ID?"
#. module: base_import
#. openerp-web
@@ -244,25 +298,30 @@ msgid ""
"\n"
" you 3 different fields to import:"
msgstr ""
+"Na primjer, \n"
+" referenciranje države "
+"kontakta, OpenERP predlaže \n"
+" 3 različita polja za "
+"uvoz :"
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/xml/import.xml:175
#, python-format
msgid "What can I do if I have multiple matches for a field?"
-msgstr ""
+msgstr "Što da radim ako imam više istih zapisa za polje?"
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/xml/import.xml:302
#, python-format
msgid "External ID,Name,Is a Company"
-msgstr ""
+msgstr "Vanjski ID , Naziv, Je Tvrtka"
#. module: base_import
#: field:base_import.tests.models.preview,somevalue:0
msgid "Some Value"
-msgstr ""
+msgstr "Neka vrijednost"
#. module: base_import
#. openerp-web
@@ -272,6 +331,9 @@ msgid ""
"The following CSV file shows how to import \n"
" suppliers and their respective contacts"
msgstr ""
+"Sljedeća csv datoteka pokazuje kako uvesti \n"
+" "
+" dobavljače i njihove pripadne kontakte"
#. module: base_import
#. openerp-web
@@ -281,6 +343,9 @@ msgid ""
"How can I change the CSV file format options when \n"
" saving in my spreadsheet application?"
msgstr ""
+"Kako da promijenim opcije csv formata \n"
+" "
+"kada spremam datoteku u tabličnom kalkulatoru?"
#. module: base_import
#. openerp-web
@@ -301,6 +366,21 @@ msgid ""
"orignial \n"
" database)."
msgstr ""
+"kako možete vidjeti iz ove datoteke, Fabien i Laurence \n"
+" "
+" rade za organizaciju Biggies (company_1), a \n"
+" "
+" Eric radi za Organi. Pozezivanje osoba i "
+"organizacija se radi \n"
+" "
+" korištenjem Vanjskog ID-a organizacije. Morali smo "
+"staviti prefix \n"
+" "
+" naziva tablice na Vanjski ID da izbjegnemo konflikt "
+"istog ID-a osobe \n"
+" "
+" i organizacije (osoba_1 i organizacija_1 koji dijele "
+"isti ID u originalnoj bazi)."
#. module: base_import
#. openerp-web
@@ -315,13 +395,20 @@ msgid ""
"\n"
" '/tmp/person.csv' with CSV"
msgstr ""
+"kopirajte \n"
+" (select'person_'||id as \"External ID\",person_name "
+"as\n"
+" \"Name\",'False' as \"Is a "
+"Company\",'company_'||company_id\n"
+" as \"Related Company/External ID\" from persons) TO\n"
+" '/tmp/person.csv' with CSV"
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/xml/import.xml:148
#, python-format
msgid "Country: Belgium"
-msgstr ""
+msgstr "Država : Belgija"
#. module: base_import
#: model:ir.model,name:base_import.model_base_import_tests_models_char_stillreadonly
@@ -342,7 +429,7 @@ msgstr ""
#: code:addons/base_import/static/src/xml/import.xml:233
#, python-format
msgid "Suppliers and their respective contacts"
-msgstr ""
+msgstr "Dobavljači i njihovi pripadni kontakti"
#. module: base_import
#. openerp-web
@@ -375,6 +462,11 @@ msgid ""
"\n"
" PSQL:"
msgstr ""
+"Za stvaranje csv datoteke za osobe povezane sa \n"
+" "
+" organizacijama, koristimo ljedeću SQL naredbu u \n"
+" "
+" PSQL:"
#. module: base_import
#. openerp-web
@@ -386,6 +478,13 @@ msgid ""
" (in 'Save As' dialog box > click 'Tools' dropdown \n"
" list > Encoding tab)."
msgstr ""
+"Microsoft Excell će vam omogućiti \n"
+" da promjenite kodnu stranu "
+"jedino kod snimanja \n"
+" (U 'Save as' dijalogu > "
+"kliknite na 'Tools' padajući izbornik > \n"
+" odaberite 'Encoding' "
+"karticu)"
#. module: base_import
#: field:base_import.tests.models.preview,othervalue:0
@@ -402,6 +501,13 @@ msgid ""
" later, it's thus good practice to specify it\n"
" whenever possible"
msgstr ""
+"će također biti korišteno za ažuriranje originalnog \n"
+" "
+"uvoza, ako kasnije trebate ponovo uvesti \n"
+" "
+"izmjenjene podatke, zato se smatra dobrom praksom \n"
+" "
+"koristiti kad god je moguće"
#. module: base_import
#. openerp-web
@@ -411,6 +517,9 @@ msgid ""
"file to import. If you need a sample importable file, you\n"
" can use the export tool to generate one."
msgstr ""
+"datoteka za uvoz. Ako trebate uzorak datoteke koja se može uvesti,\n"
+" možete koristiti "
+"alat za izvoz da napravite jednu."
#. module: base_import
#. openerp-web
@@ -419,7 +528,7 @@ msgstr ""
msgid ""
"Country/Database \n"
" ID: 21"
-msgstr ""
+msgstr "Država/Baza"
#. module: base_import
#: model:ir.model,name:base_import.model_base_import_tests_models_char
@@ -429,14 +538,14 @@ msgstr ""
#. module: base_import
#: help:base_import.import,file:0
msgid "File to check and/or import, raw binary (not base64)"
-msgstr ""
+msgstr "Datoteke za provjeru i/ili uvoz, raw binary ( ne base64)"
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/xml/import.xml:230
#, python-format
msgid "Purchase orders with their respective purchase order lines"
-msgstr ""
+msgstr "Narudžbe i njihove pripadne stavke"
#. module: base_import
#. openerp-web
@@ -448,6 +557,14 @@ msgid ""
" field corresponding to the column. This makes imports\n"
" simpler especially when the file has many columns."
msgstr ""
+"Ako datoteka sadrži\n"
+" nazive kolona, OpenERP može "
+"pokušati \n"
+" automatski odrediti polja koja "
+"odgovaraju kolonama. \n"
+" Ovo čini uvoz jednostavnijim "
+"pogotovo ako datoteka ima \n"
+" mnogo kolona."
#. module: base_import
#. openerp-web
@@ -464,6 +581,8 @@ msgid ""
". The issue is\n"
" usually an incorrect file encoding."
msgstr ""
+". Problem je \n"
+" obično netočna kodna strana."
#. module: base_import
#: model:ir.model,name:base_import.model_base_import_tests_models_m2o_required
@@ -519,7 +638,7 @@ msgstr "ID baze podataka"
#: code:addons/base_import/static/src/xml/import.xml:313
#, python-format
msgid "It will produce the following CSV file:"
-msgstr ""
+msgstr "Će napraviti sljedeću csv datoteku:"
#. module: base_import
#. openerp-web
@@ -548,7 +667,7 @@ msgstr ""
#: code:addons/base_import/static/src/xml/import.xml:360
#, python-format
msgid "Import preview failed due to:"
-msgstr ""
+msgstr "Predpregled uvoza nije uspio zbog:"
#. module: base_import
#. openerp-web
@@ -643,7 +762,7 @@ msgstr "Uvezi CSV datoteku"
#: code:addons/base_import/static/src/js/import.js:74
#, python-format
msgid "Quoting:"
-msgstr ""
+msgstr "Navođenje:"
#. module: base_import
#: model:ir.model,name:base_import.model_base_import_tests_models_m2o_required_related
@@ -670,7 +789,7 @@ msgstr "Uvoz"
#: code:addons/base_import/static/src/js/import.js:407
#, python-format
msgid "Here are the possible values:"
-msgstr ""
+msgstr "Evo mogućih vrijednosti:"
#. module: base_import
#. openerp-web
@@ -687,13 +806,15 @@ msgid ""
"A single column was found in the file, this often means the file separator "
"is incorrect"
msgstr ""
+"U datoteci je nađena samo jedna kolona, to često znači da je format "
+"razdjelnika neispravan."
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/xml/import.xml:293
#, python-format
msgid "dump of such a PostgreSQL database"
-msgstr ""
+msgstr "dump takve PostgereSQL baze"
#. module: base_import
#. openerp-web
@@ -710,6 +831,9 @@ msgid ""
"The following CSV file shows how to import purchase \n"
" orders with their respective purchase order lines:"
msgstr ""
+"Sljedeća csv datoteka pokazuje kako uvesti \n"
+" naloge za nabavu sa "
+"njihovm pripadnim stavkama :"
#. module: base_import
#. openerp-web
@@ -719,6 +843,9 @@ msgid ""
"What can I do when the Import preview table isn't \n"
" displayed correctly?"
msgstr ""
+"Što mogu uraditi kada se tablice Predpregleda za uvoz\n"
+" "
+" ne prikazuju ispravno?"
#. module: base_import
#: field:base_import.tests.models.char,value:0
@@ -770,7 +897,7 @@ msgstr ""
#: code:addons/base_import/static/src/js/import.js:396
#, python-format
msgid "(%d more)"
-msgstr ""
+msgstr "(%d više)"
#. module: base_import
#. openerp-web
@@ -829,7 +956,7 @@ msgstr ""
#: code:addons/base_import/static/src/js/import.js:373
#, python-format
msgid "Everything seems valid."
-msgstr ""
+msgstr "Sve se čini u redu."
#. module: base_import
#. openerp-web
@@ -914,6 +1041,15 @@ msgid ""
" will set the EMPTY value in the field, instead of \n"
" assigning the default value."
msgstr ""
+"Ako ne postavite sva polja u vašoj csv datoteci, \n"
+" OpenERP će "
+"dodijeliti zadane vrijednosti za svako \n"
+" nedefinirano "
+"polje, ali ako postavite polja sa praznim virjenostima u csv-u \n"
+" OpenERP će "
+"postaviti vrijednost tih polja na \"PRAZNO\", umjesto da im \n"
+" dodijeli zadane "
+"vrijednosti"
#. module: base_import
#. openerp-web
@@ -930,6 +1066,9 @@ msgid ""
"What happens if I do not provide a value for a \n"
" specific field?"
msgstr ""
+"Što se dešava ako ne dajem vrijednost za \n"
+" "
+"pojedino polje?"
#. module: base_import
#. openerp-web
@@ -957,6 +1096,11 @@ msgid ""
"spreadsheet \n"
" application."
msgstr ""
+"Ovo vam \n"
+" omogućuje da "
+"koristite alat za Uvoz/Izvoz OpenERP-a \n"
+" za izmjenu serija "
+"zapisa u vašem omiljenom tabličnom kalkulatoru"
#. module: base_import
#. openerp-web
@@ -993,14 +1137,14 @@ msgstr ""
#: code:addons/base_import/static/src/xml/import.xml:169
#, python-format
msgid "CSV file for categories"
-msgstr ""
+msgstr "CSV datoteka za kategorije"
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/js/import.js:309
#, python-format
msgid "Normal Fields"
-msgstr ""
+msgstr "Normalna polja"
#. module: base_import
#. openerp-web
@@ -1012,6 +1156,11 @@ msgid ""
" identifier from the original application and\n"
" map it to the"
msgstr ""
+"kako bi ponovo napravili relacije između\n"
+" "
+"različitih zapisa, trebali bi koristiti jedinstveni\n"
+" "
+"identifikator iz originalnog zapisa i njega mapirati na"
#. module: base_import
#. openerp-web
@@ -1054,7 +1203,7 @@ msgstr "Naziv"
#: code:addons/base_import/static/src/xml/import.xml:80
#, python-format
msgid "to the original unique identifier."
-msgstr ""
+msgstr "originalni jedinstveni identifikator"
#. module: base_import
#. openerp-web
@@ -1131,14 +1280,14 @@ msgstr "Vanjski ID"
#: code:addons/base_import/static/src/xml/import.xml:39
#, python-format
msgid "File Format Options…"
-msgstr ""
+msgstr "Opcije Formata datoteka..."
#. module: base_import
#. openerp-web
#: code:addons/base_import/static/src/js/import.js:392
#, python-format
msgid "between rows %d and %d"
-msgstr ""
+msgstr "između reda %d i %d"
#. module: base_import
#. openerp-web
@@ -1163,4 +1312,4 @@ msgstr ""
#. module: base_import
#: field:base_import.import,file:0
msgid "File"
-msgstr ""
+msgstr "Datoteka"
diff --git a/addons/document/document.py b/addons/document/document.py
index 1671b6bc1ba..85468e00509 100644
--- a/addons/document/document.py
+++ b/addons/document/document.py
@@ -31,11 +31,11 @@ from StringIO import StringIO
import psycopg2
import openerp
-from openerp import netsvc
from openerp import pooler
from openerp import tools
from openerp.osv import fields, osv
from openerp.osv.orm import except_orm
+import openerp.report.interface
from openerp.tools.misc import ustr
from openerp.tools.translate import _
from openerp.tools.safe_eval import safe_eval
@@ -456,7 +456,7 @@ class document_directory_content(osv.osv):
if node.extension != '.pdf':
raise Exception("Invalid content: %s" % node.extension)
report = self.pool.get('ir.actions.report.xml').browse(cr, uid, node.report_id, context=context)
- srv = netsvc.Service._services['report.'+report.report_name]
+ srv = openerp.report.interface.report_int._reports['report.'+report.report_name]
ctx = node.context.context.copy()
ctx.update(node.dctx)
pdf,pdftype = srv.create(cr, uid, [node.act_id,], {}, context=ctx)
diff --git a/addons/document_ftp/ftpserver/abstracted_fs.py b/addons/document_ftp/ftpserver/abstracted_fs.py
index a9efac5819c..b746f189700 100644
--- a/addons/document_ftp/ftpserver/abstracted_fs.py
+++ b/addons/document_ftp/ftpserver/abstracted_fs.py
@@ -10,6 +10,7 @@ import glob
import fnmatch
from openerp import pooler, netsvc, sql_db
+import openerp.service
from openerp.service import security
from openerp.osv import osv
@@ -60,7 +61,7 @@ class abstracted_fs(object):
def db_list(self):
"""Get the list of available databases, with FTPd support
"""
- s = netsvc.ExportService.getService('db')
+ s = openerp.service.db
result = s.exp_list(document=True)
self.db_name_list = []
for db_name in result:
diff --git a/addons/document_webdav/dav_fs.py b/addons/document_webdav/dav_fs.py
index e5756f5df91..1781a02d76e 100644
--- a/addons/document_webdav/dav_fs.py
+++ b/addons/document_webdav/dav_fs.py
@@ -38,6 +38,7 @@ except ImportError:
import openerp
from openerp import pooler, sql_db, netsvc
+import openerp.service
from openerp.tools import misc
from cache import memoize
@@ -372,7 +373,7 @@ class openerp_dav_handler(dav_interface):
@memoize(4)
def _all_db_list(self):
"""return all databases who have module document_webdav installed"""
- s = netsvc.ExportService.getService('db')
+ s = openerp.service.db
result = s.exp_list()
self.db_name_list=[]
for db_name in result:
diff --git a/addons/edi/edi_service.py b/addons/edi/edi_service.py
index fd911139170..d5dc5c09f74 100644
--- a/addons/edi/edi_service.py
+++ b/addons/edi/edi_service.py
@@ -21,45 +21,46 @@
import logging
import openerp
-import openerp.netsvc as netsvc
_logger = logging.getLogger(__name__)
-class edi(netsvc.ExportService):
+# TODO this is not needed anymore:
+# - the exposed new service just forward to the model service
+# - the service is called by the web controller, which can
+# now directly call into openerp as the web server is always
+# embedded in openerp.
- def __init__(self, name="edi"):
- netsvc.ExportService.__init__(self, name)
+def _edi_dispatch(db_name, method_name, *method_args):
+ try:
+ registry = openerp.modules.registry.RegistryManager.get(db_name)
+ assert registry, 'Unknown database %s' % db_name
+ edi = registry['edi.edi']
+ cr = registry.db.cursor()
+ res = None
+ res = getattr(edi, method_name)(cr, *method_args)
+ cr.commit()
+ except Exception, e:
+ _logger.exception('Failed to execute EDI method %s with args %r.',
+ method_name, method_args)
+ raise
+ finally:
+ cr.close()
+ return res
- def _edi_dispatch(self, db_name, method_name, *method_args):
- try:
- registry = openerp.modules.registry.RegistryManager.get(db_name)
- assert registry, 'Unknown database %s' % db_name
- edi = registry['edi.edi']
- cr = registry.db.cursor()
- res = None
- res = getattr(edi, method_name)(cr, *method_args)
- cr.commit()
- except Exception:
- _logger.exception('Failed to execute EDI method %s with args %r.', method_name, method_args)
- raise
- finally:
- cr.close()
- return res
+def exp_import_edi_document(db_name, uid, passwd, edi_document, context=None):
+ return _edi_dispatch(db_name, 'import_edi', uid, edi_document, None)
- def exp_import_edi_document(self, db_name, uid, passwd, edi_document, context=None):
- return self._edi_dispatch(db_name, 'import_edi', uid, edi_document, None)
+def exp_import_edi_url(db_name, uid, passwd, edi_url, context=None):
+ return _edi_dispatch(db_name, 'import_edi', uid, None, edi_url)
- def exp_import_edi_url(self, db_name, uid, passwd, edi_url, context=None):
- return self._edi_dispatch(db_name, 'import_edi', uid, None, edi_url)
+@openerp.http.rpc('edi')
+def dispatch(method, params):
+ if method in ['import_edi_document', 'import_edi_url']:
+ (db, uid, passwd) = params[0:3]
+ openerp.service.security.check(db, uid, passwd)
+ else:
+ raise KeyError("Method not found: %s." % method)
+ fn = globals()['exp_' + method]
+ return fn(*params)
- def dispatch(self, method, params):
- if method in ['import_edi_document', 'import_edi_url']:
- (db, uid, passwd ) = params[0:3]
- openerp.service.security.check(db, uid, passwd)
- else:
- raise KeyError("Method not found: %s." % method)
- fn = getattr(self, 'exp_'+method)
- return fn(*params)
-
-edi()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mail/i18n/hu.po b/addons/mail/i18n/hu.po
index 65385c23ef0..3d3117c1b51 100644
--- a/addons/mail/i18n/hu.po
+++ b/addons/mail/i18n/hu.po
@@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
-"PO-Revision-Date: 2012-12-21 10:09+0000\n"
-"Last-Translator: Herczeg Péter
\n" +"Nincs privát üzenet.\n" +"
\n" +"Ez a lista az önnek küldött üzeneteket tartalmazza.\n" +"
\n" +" " #. module: mail #: model:mail.group,name:mail.group_rd msgid "R&D" -msgstr "" +msgstr "R&D" #. module: mail #. openerp-web #: code:addons/mail/static/src/xml/mail.xml:61 #, python-format msgid "/web/binary/upload_attachment" -msgstr "" +msgstr "/web/binary/upload_attachment" #. module: mail #: model:ir.model,name:mail.model_mail_thread msgid "Email Thread" -msgstr "" +msgstr "E-mail összafűzés" #. module: mail #: view:mail.mail:0 @@ -647,19 +679,19 @@ msgstr "Speciális" #: code:addons/mail/static/src/xml/mail.xml:226 #, python-format msgid "Move to Inbox" -msgstr "" +msgstr "Bejövő üzenetekbe mozgatás" #. module: mail #: code:addons/mail/wizard/mail_compose_message.py:165 #, python-format msgid "Re:" -msgstr "" +msgstr "Vissza:" #. module: mail #: field:mail.compose.message,to_read:0 #: field:mail.message,to_read:0 msgid "To read" -msgstr "" +msgstr "Elolvas" #. module: mail #: code:addons/mail/res_users.py:79 @@ -668,19 +700,21 @@ msgid "" "You may not create a user. To create new users, you should use the " "\"Settings > Users\" menu." msgstr "" +"Talán nem hozott létre felhasználót. Egy felhasználó létrehozásához, " +"használja a \"Beállítások > Felhasználók\" menüt." #. module: mail #: help:mail.followers,res_model:0 #: help:mail.wizard.invite,res_model:0 msgid "Model of the followed resource" -msgstr "" +msgstr "A követett forrás modellje" #. module: mail #. openerp-web #: code:addons/mail/static/src/xml/mail.xml:286 #, python-format msgid "like" -msgstr "" +msgstr "hasonló" #. module: mail #: view:mail.compose.message:0 @@ -694,12 +728,12 @@ msgstr "Mégsem" #: code:addons/mail/static/src/xml/mail.xml:44 #, python-format msgid "Share with my followers..." -msgstr "" +msgstr "Üzenet a követőimnek..." #. module: mail #: field:mail.notification,partner_id:0 msgid "Contact" -msgstr "" +msgstr "Kapcsolat" #. module: mail #: view:mail.group:0 @@ -707,21 +741,23 @@ msgid "" "Only the invited followers can read the\n" " discussions on this group." msgstr "" +"Csak a meghívott követők olvashatják ennek a\n" +" csoportnak a beszélgetését." #. module: mail #: model:ir.model,name:mail.model_ir_ui_menu msgid "ir.ui.menu" -msgstr "" +msgstr "ir.ui.menu" #. module: mail #: view:mail.message:0 msgid "Has attachments" -msgstr "" +msgstr "Vannak mellékletei" #. module: mail #: view:mail.mail:0 msgid "on" -msgstr "" +msgstr "ezen:" #. module: mail #: code:addons/mail/mail_message.py:916 @@ -730,6 +766,8 @@ msgid "" "The following partners chosen as recipients for the email have no email " "address linked :" msgstr "" +"A következő partnerek lettek kiválasztva mint címzettek, azokhoz az e-" +"mailekhez amelyekhez nem lett kapcsolva e-mail cím :" #. module: mail #: help:mail.alias,alias_defaults:0 @@ -737,11 +775,13 @@ msgid "" "A Python dictionary that will be evaluated to provide default values when " "creating new records for this alias." msgstr "" +"Egy Python szótár aminak a kiértékelésével alapértékeket biztosít, ha ehhez " +"az álnévhez új rekordokat hoz létre." #. module: mail #: model:ir.model,name:mail.model_mail_message_subtype msgid "Message subtypes" -msgstr "" +msgstr "Üzenet altípusok" #. module: mail #: help:mail.compose.message,notified_partner_ids:0 @@ -749,13 +789,15 @@ msgstr "" msgid "" "Partners that have a notification pushing this message in their mailboxes" msgstr "" +"Partnerek akiknek van egy értesítésük ennek az üzenetnek a levelező " +"ládájukba való mozgatására" #. module: mail #: selection:mail.compose.message,type:0 #: view:mail.mail:0 #: selection:mail.message,type:0 msgid "Comment" -msgstr "" +msgstr "Megjegyzés" #. module: mail #: model:ir.actions.client,help:mail.action_mail_inbox_feeds @@ -771,18 +813,28 @@ msgid "" " \n" " " msgstr "" +"\n" +" Szép munka! Az ön postafiókja üres.\n" +"
\n" +" A \"Beérkezett üzenetek\" az önnek küldött privát " +"üzeneteket vagy email-eket,\n" +" továbbá az ön által követett dokumentumokhoz vagy " +"emberekhez kapcsolódó\n" +" információkat tartalmaz.\n" +"
\n" +" " #. module: mail #: field:mail.mail,notification:0 msgid "Is Notification" -msgstr "" +msgstr "Ez egy üzenet" #. module: mail #. openerp-web #: code:addons/mail/static/src/xml/mail.xml:170 #, python-format msgid "Compose a new message" -msgstr "" +msgstr "Új üzenet küldés" #. module: mail #: view:mail.mail:0 @@ -795,6 +847,7 @@ msgstr "Küldés most" msgid "" "Unable to send email, please configure the sender's email address or alias." msgstr "" +"Nem tud e-mailt küldeni, kérem állítsa be a küldő e-mail címét vagy álnevet" #. module: mail #: help:res.users,alias_id:0 @@ -802,11 +855,13 @@ msgid "" "Email address internally associated with this user. Incoming emails will " "appear in the user's notifications." msgstr "" +"E-mail cím belsőleg összekapcsolva ezzel a felhasználóval. Bejövő e-mail-ok " +"megjelennek a felhasználó értesítéseinél." #. module: mail #: field:mail.group,image:0 msgid "Photo" -msgstr "" +msgstr "Fénykép" #. module: mail #. openerp-web @@ -815,13 +870,13 @@ msgstr "" #: view:mail.wizard.invite:0 #, python-format msgid "or" -msgstr "" +msgstr "vagy" #. module: mail #: help:mail.compose.message,vote_user_ids:0 #: help:mail.message,vote_user_ids:0 msgid "Users that voted for this message" -msgstr "" +msgstr "Felhasználók akik szavaztak erre az üzenetre" #. module: mail #: help:mail.group,alias_id:0 @@ -829,6 +884,8 @@ msgid "" "The email address associated with this group. New emails received will " "automatically create new topics." msgstr "" +"Az ezzel a csoporttal társított e-mail cím. Új beérkezett e-mailek " +"automatikusan új témákat hoznak létre." #. module: mail #: view:mail.mail:0 @@ -844,7 +901,7 @@ msgstr "E-mail keresésée" #: field:mail.compose.message,child_ids:0 #: field:mail.message,child_ids:0 msgid "Child Messages" -msgstr "" +msgstr "Alcsoportba rakott üzenetek" #. module: mail #: field:mail.alias,alias_user_id:0 @@ -927,12 +984,12 @@ msgstr "" #. module: mail #: view:mail.wizard.invite:0 msgid "Add Followers" -msgstr "" +msgstr "Követők hozzáadása" #. module: mail #: view:mail.compose.message:0 msgid "Followers of selected items and" -msgstr "" +msgstr "A kijelölt elemek követői és" #. module: mail #: field:mail.alias,alias_force_thread_id:0 @@ -942,7 +999,7 @@ msgstr "" #. module: mail #: model:ir.ui.menu,name:mail.mail_group_root msgid "My Groups" -msgstr "" +msgstr "Saját csoportok" #. module: mail #: model:ir.actions.client,help:mail.action_mail_archives_feeds @@ -1063,7 +1120,7 @@ msgstr "Dátum" #: code:addons/mail/static/src/xml/mail.xml:34 #, python-format msgid "Post" -msgstr "" +msgstr "Elküld" #. module: mail #: view:mail.mail:0 @@ -1075,14 +1132,14 @@ msgstr "Kiterjesztett szűrők…" #: code:addons/mail/static/src/xml/mail.xml:107 #, python-format msgid "To:" -msgstr "" +msgstr "Címzett:" #. module: mail #. openerp-web #: code:addons/mail/static/src/xml/mail.xml:175 #, python-format msgid "Write to my followers" -msgstr "" +msgstr "Bejegyzés írás a követőimnek" #. module: mail #: model:ir.model,name:mail.model_res_groups @@ -1169,7 +1226,7 @@ msgstr "" #: code:addons/mail/static/src/xml/mail_followers.xml:13 #, python-format msgid "Following" -msgstr "" +msgstr "Követés" #. module: mail #: sql_constraint:mail.alias:0 @@ -1257,14 +1314,14 @@ msgstr "" #. module: mail #: model:mail.message.subtype,name:mail.mt_comment msgid "Discussions" -msgstr "" +msgstr "Hozzászólások" #. module: mail #. openerp-web #: code:addons/mail/static/src/xml/mail_followers.xml:11 #, python-format msgid "Follow" -msgstr "" +msgstr "Követ" #. module: mail #: field:mail.group,name:0 @@ -1413,7 +1470,7 @@ msgstr "" #: model:ir.actions.act_window,name:mail.action_view_groups #: model:ir.ui.menu,name:mail.mail_allgroups msgid "Join a group" -msgstr "" +msgstr "Csoporthoz csatlakozás" #. module: mail #: model:ir.actions.client,help:mail.action_mail_group_feeds @@ -1492,7 +1549,7 @@ msgstr "" #: model:ir.actions.client,name:mail.action_mail_star_feeds #: model:ir.ui.menu,name:mail.mail_starfeeds msgid "To-do" -msgstr "" +msgstr "Feladat" #. module: mail #: view:mail.alias:0 @@ -1598,7 +1655,7 @@ msgstr "" #. module: mail #: selection:mail.group,public:0 msgid "Private" -msgstr "" +msgstr "Privát" #. module: mail #: model:ir.actions.client,help:mail.action_mail_star_feeds diff --git a/addons/product/i18n/lo.po b/addons/product/i18n/lo.po new file mode 100644 index 00000000000..0f63a200e88 --- /dev/null +++ b/addons/product/i18n/lo.po @@ -0,0 +1,2479 @@ +# Lao translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR\n" +" Click to add a new packaging type.\n" +"
\n" +" The packaging type define the dimensions as well as the " +"number\n" +" of products per package. This will ensure salesperson sell " +"the\n" +" right number of products according to the package selected.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: field:product.template,product_manager:0 +msgid "Product Manager" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_7_product_template +msgid "17” LCD Monitor" +msgstr "" + +#. module: product +#: field:product.supplierinfo,product_name:0 +msgid "Supplier Product Name" +msgstr "" + +#. module: product +#: view:product.pricelist:0 +msgid "Products Price Search" +msgstr "" + +#. module: product +#: view:product.template:0 +#: field:product.template,description_sale:0 +msgid "Sale Description" +msgstr "" + +#. module: product +#: help:product.packaging,length:0 +msgid "The length of the package" +msgstr "" + +#. module: product +#: field:product.product,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: product +#: help:product.template,weight_net:0 +msgid "The net weight in Kg." +msgstr "" + +#. module: product +#: field:pricelist.partnerinfo,min_quantity:0 +#: field:product.supplierinfo,qty:0 +msgid "Quantity" +msgstr "" + +#. module: product +#: view:product.price_list:0 +msgid "Calculate Product Price per Unit Based on Pricelist Version." +msgstr "" + +#. module: product +#: help:product.pricelist.item,product_id:0 +msgid "" +"Specify a product if this rule only applies to one product. Keep empty " +"otherwise." +msgstr "" + +#. module: product +#: model:product.uom.categ,name:product.product_uom_categ_kgm +msgid "Weight" +msgstr "" + +#. module: product +#: help:product.product,virtual_available:0 +msgid "" +"Forecast quantity (computed as Quantity On Hand - Outgoing + Incoming)\n" +"In a context with a single Stock Location, this includes goods stored in " +"this location, or any of its children.\n" +"In a context with a single Warehouse, this includes goods stored in the " +"Stock Location of this Warehouse, or any of its children.\n" +"In a context with a single Shop, this includes goods stored in the Stock " +"Location of the Warehouse of this Shop, or any of its children.\n" +"Otherwise, this includes goods stored in any Stock Location with 'internal' " +"type." +msgstr "" + +#. module: product +#: field:product.packaging,height:0 +msgid "Height" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Procurements" +msgstr "" + +#. module: product +#: model:res.groups,name:product.group_mrp_properties +msgid "Manage Properties of Product" +msgstr "" + +#. module: product +#: help:product.uom,factor:0 +msgid "" +"How much bigger or smaller this unit is compared to the reference Unit of " +"Measure for this category:\n" +"1 * (reference unit) = ratio * (this unit)" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_pricelist_partnerinfo +msgid "pricelist.partnerinfo" +msgstr "" + +#. module: product +#: field:product.price_list,qty2:0 +msgid "Quantity-2" +msgstr "" + +#. module: product +#: field:product.price_list,qty3:0 +msgid "Quantity-3" +msgstr "" + +#. module: product +#: field:product.price_list,qty1:0 +msgid "Quantity-1" +msgstr "" + +#. module: product +#: field:product.price_list,qty4:0 +msgid "Quantity-4" +msgstr "" + +#. module: product +#: view:res.partner:0 +msgid "Sales & Purchases" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_44_product_template +msgid "GrapWorks Software" +msgstr "" + +#. module: product +#: model:product.uom.categ,name:product.uom_categ_wtime +msgid "Working Time" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_42_product_template +msgid "Office Suite" +msgstr "" + +#. module: product +#: field:product.template,mes_type:0 +msgid "Measure Type" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_32_product_template +msgid "Headset standard" +msgstr "" + +#. module: product +#: model:product.uom,name:product.product_uom_day +msgid "Day(s)" +msgstr "ມື້" + +#. module: product +#: help:product.product,incoming_qty:0 +msgid "" +"Quantity of products that are planned to arrive.\n" +"In a context with a single Stock Location, this includes goods arriving to " +"this Location, or any of its children.\n" +"In a context with a single Warehouse, this includes goods arriving to the " +"Stock Location of this Warehouse, or any of its children.\n" +"In a context with a single Shop, this includes goods arriving to the Stock " +"Location of the Warehouse of this Shop, or any of its children.\n" +"Otherwise, this includes goods arriving to any Stock Location with " +"'internal' type." +msgstr "" + +#. module: product +#: constraint:product.template:0 +msgid "" +"Error: The default Unit of Measure and the purchase Unit of Measure must be " +"in the same category." +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_uom_categ +msgid "Product uom categ" +msgstr "" + +#. module: product +#: model:product.ul,name:product.product_ul_box +msgid "Box 20x20x40" +msgstr "" + +#. module: product +#: field:product.template,warranty:0 +msgid "Warranty" +msgstr "ຮັບປະກັນ" + +#. module: product +#: view:product.pricelist.item:0 +msgid "Price Computation" +msgstr "" + +#. module: product +#: constraint:product.product:0 +msgid "" +"You provided an invalid \"EAN13 Barcode\" reference. You may use the " +"\"Internal Reference\" field instead." +msgstr "" + +#. module: product +#: model:res.groups,name:product.group_purchase_pricelist +msgid "Purchase Pricelists" +msgstr "ລາຍການລາຄາຊື້" + +#. module: product +#: model:product.template,name:product.product_product_5_product_template +msgid "PC Assemble + Custom (PC on Demand)" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_27_product_template +msgid "Custom Laptop based on customer's requirement." +msgstr "" + +#. module: product +#: help:product.packaging,width:0 +msgid "The width of the package" +msgstr "" + +#. module: product +#: code:addons/product/product.py:361 +#, python-format +msgid "Unit of Measure categories Mismatch!" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_36_product_template +msgid "Blank DVD-RW" +msgstr "" + +#. module: product +#: selection:product.category,type:0 +msgid "View" +msgstr "ເບຶ່ງ" + +#. module: product +#: model:ir.actions.act_window,name:product.product_template_action_tree +msgid "Product Templates" +msgstr "" + +#. module: product +#: field:product.category,parent_left:0 +msgid "Left Parent" +msgstr "" + +#. module: product +#: help:product.pricelist.item,price_max_margin:0 +msgid "Specify the maximum amount of margin over the base price." +msgstr "" + +#. module: product +#: constraint:product.pricelist.item:0 +msgid "" +"Error! You cannot assign the Main Pricelist as Other Pricelist in PriceList " +"Item!" +msgstr "" + +#. module: product +#: view:product.price_list:0 +msgid "or" +msgstr "ຫຼື" + +#. module: product +#: constraint:product.packaging:0 +msgid "Error: Invalid ean code" +msgstr "" + +#. module: product +#: field:product.pricelist.item,min_quantity:0 +msgid "Min. Quantity" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_12_product_template +msgid "Mouse, Wireless" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_22_product_template +msgid "Processor Core i5 2.70 Ghz" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_price_type +msgid "Price Type" +msgstr "" + +#. module: product +#: view:product.pricelist.item:0 +msgid "Max. Margin" +msgstr "" + +#. module: product +#: view:product.pricelist.item:0 +msgid "Base Price" +msgstr "" + +#. module: product +#: help:product.supplierinfo,name:0 +msgid "Supplier of this product" +msgstr "" + +#. module: product +#: help:product.pricelist.version,active:0 +msgid "" +"When a version is duplicated it is set to non active, so that the dates do " +"not overlaps with original version. You should change the dates and " +"reactivate the pricelist" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_18_product_template +msgid "HDD SH-2" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_17_product_template +msgid "HDD SH-1" +msgstr "" + +#. module: product +#: field:product.supplierinfo,name:0 +#: field:product.template,seller_ids:0 +msgid "Supplier" +msgstr "ຜູ້ສະໜອງ" + +#. module: product +#: help:product.template,cost_method:0 +msgid "" +"Standard Price: The cost price is manually updated at the end of a specific " +"period (usually every year). \n" +"Average Price: The cost price is recomputed at each incoming shipment." +msgstr "" + +#. module: product +#: field:product.product,qty_available:0 +msgid "Quantity On Hand" +msgstr "" + +#. module: product +#: field:product.price.type,name:0 +msgid "Price Name" +msgstr "" + +#. module: product +#: help:product.product,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: product +#: field:product.product,ean13:0 +msgid "EAN13 Barcode" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.action_product_price_list +#: model:ir.model,name:product.model_product_price_list +#: view:product.price_list:0 +#: report:product.pricelist:0 +#: field:product.pricelist.version,pricelist_id:0 +msgid "Price List" +msgstr "ລາຍການລາຄາ" + +#. module: product +#: field:product.product,virtual_available:0 +msgid "Forecasted Quantity" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Purchase" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_33_product_template +msgid "Headset USB" +msgstr "" + +#. module: product +#: view:product.template:0 +msgid "Suppliers" +msgstr "" + +#. module: product +#: model:res.groups,name:product.group_sale_pricelist +msgid "Sales Pricelists" +msgstr "" + +#. module: product +#: view:product.pricelist.item:0 +msgid "New Price =" +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_7 +msgid "Accessories" +msgstr "" + +#. module: product +#: model:process.transition,name:product.process_transition_supplierofproduct0 +msgid "Supplier of the product" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_28_product_template +msgid "External Hard disk" +msgstr "" + +#. module: product +#: help:product.template,standard_price:0 +msgid "" +"Cost price of the product used for standard stock valuation in accounting " +"and used as a base price on purchase orders." +msgstr "" + +#. module: product +#: field:product.category,child_id:0 +msgid "Child Categories" +msgstr "" + +#. module: product +#: field:product.pricelist.version,date_end:0 +msgid "End Date" +msgstr "" + +#. module: product +#: model:product.uom,name:product.product_uom_litre +msgid "Liter(s)" +msgstr "" + +#. module: product +#: view:product.price_list:0 +msgid "Print" +msgstr "" + +#. module: product +#: view:product.product:0 +#: field:product.ul,type:0 +#: field:product.uom,uom_type:0 +msgid "Type" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.product_pricelist_action2 +#: model:ir.actions.act_window,name:product.product_pricelist_action_for_purchase +#: model:ir.ui.menu,name:product.menu_product_pricelist_action2 +#: model:ir.ui.menu,name:product.menu_product_pricelist_main +msgid "Pricelists" +msgstr "" + +#. module: product +#: field:product.product,partner_ref:0 +msgid "Customer ref" +msgstr "" + +#. module: product +#: field:product.pricelist.type,key:0 +msgid "Key" +msgstr "" + +#. module: product +#: model:ir.actions.report.xml,name:product.report_product_pricelist +#: model:ir.model,name:product.model_product_pricelist +#: field:product.product,pricelist_id:0 +#: view:product.supplierinfo:0 +msgid "Pricelist" +msgstr "" + +#. module: product +#: model:product.uom,name:product.product_uom_hour +msgid "Hour(s)" +msgstr "" + +#. module: product +#: selection:product.template,state:0 +msgid "In Development" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_res_partner +msgid "Partner" +msgstr "" + +#. module: product +#: model:process.transition,note:product.process_transition_supplierofproduct0 +msgid "" +"1 or several supplier(s) can be linked to a product. All information stands " +"in the product form." +msgstr "" + +#. module: product +#: field:product.pricelist.item,price_round:0 +msgid "Price Rounding" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_1_product_template +msgid "On Site Monitoring" +msgstr "" + +#. module: product +#: view:product.template:0 +msgid "days" +msgstr "" + +#. module: product +#: model:process.node,name:product.process_node_supplier0 +#: view:product.supplierinfo:0 +msgid "Supplier Information" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_res_currency +#: field:product.price.type,currency_id:0 +#: report:product.pricelist:0 +#: field:product.pricelist,currency_id:0 +msgid "Currency" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_46_product_template +msgid "Datacard" +msgstr "" + +#. module: product +#: help:product.template,uos_coeff:0 +msgid "" +"Coefficient to convert default Unit of Measure to Unit of Sale\n" +" uos = uom * coeff" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.product_category_action_form +#: model:ir.ui.menu,name:product.menu_product_category_action_form +#: view:product.category:0 +msgid "Product Categories" +msgstr "" + +#. module: product +#: view:product.template:0 +msgid "Procurement & Locations" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_20_product_template +msgid "Motherboard I9P57" +msgstr "" + +#. module: product +#: field:product.packaging,weight:0 +msgid "Total Package Weight" +msgstr "" + +#. module: product +#: help:product.packaging,code:0 +msgid "The code of the transport unit." +msgstr "" + +#. module: product +#: view:product.price.type:0 +msgid "Products Price Type" +msgstr "" + +#. module: product +#: field:product.product,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: product +#: field:product.product,price_extra:0 +msgid "Variant Price Extra" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_supplierinfo +msgid "Information about a product supplier" +msgstr "" + +#. module: product +#: help:product.uom,factor_inv:0 +msgid "" +"How many times this Unit of Measure is bigger than the reference Unit of " +"Measure in this category:\n" +"1 * (this unit) = ratio * (reference unit)" +msgstr "" + +#. module: product +#: view:product.template:0 +#: field:product.template,description_purchase:0 +msgid "Purchase Description" +msgstr "" + +#. module: product +#: constraint:product.pricelist.version:0 +msgid "You cannot have 2 pricelist versions that overlap!" +msgstr "" + +#. module: product +#: help:product.pricelist.item,min_quantity:0 +msgid "" +"Specify the minimum quantity that needs to be bought/sold for the rule to " +"apply." +msgstr "" + +#. module: product +#: help:product.pricelist.version,date_start:0 +msgid "First valid date for the version." +msgstr "" + +#. module: product +#: help:product.supplierinfo,delay:0 +msgid "" +"Lead time in days between the confirmation of the purchase order and the " +"reception of the products in your warehouse. Used by the scheduler for " +"automatic computation of the purchase order planning." +msgstr "" + +#. module: product +#: model:product.template,description_sale:product.product_product_3_product_template +msgid "" +"17\" LCD Monitor\n" +"Processor AMD 8-Core\n" +"512MB RAM\n" +"HDD SH-1" +msgstr "" + +#. module: product +#: selection:product.template,type:0 +msgid "Stockable Product" +msgstr "" + +#. module: product +#: field:product.packaging,code:0 +msgid "Code" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_27_product_template +msgid "Laptop Customized" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_ul +msgid "Shipping Unit" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_35_product_template +msgid "Blank CD" +msgstr "" + +#. module: product +#: field:pricelist.partnerinfo,suppinfo_id:0 +msgid "Partner Information" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_normal_action_sell +msgid "" +"\n" +" Click to define a new product.\n" +"
\n" +" You must define a product for everything you sell, whether " +"it's\n" +" a physical product, a consumable or a service you offer to\n" +" customers.\n" +"
\n" +" The product form contains information to simplify the sale\n" +" process: price, notes in the quotation, accounting data,\n" +" procurement methods, etc.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: view:product.price_list:0 +msgid "Cancel" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_37_product_template +msgid "All in one hi-speed printer with fax and scanner." +msgstr "" + +#. module: product +#: help:product.supplierinfo,min_qty:0 +msgid "" +"The minimal quantity to purchase to this supplier, expressed in the supplier " +"Product Unit of Measure if not empty, in the default unit of measure of the " +"product otherwise." +msgstr "" + +#. module: product +#: view:product.product:0 +#: view:product.template:0 +msgid "Information" +msgstr "" + +#. module: product +#: view:product.pricelist.item:0 +msgid "Products Listprices Items" +msgstr "" + +#. module: product +#: view:product.packaging:0 +msgid "Other Info" +msgstr "" + +#. module: product +#: field:product.pricelist.version,items_id:0 +msgid "Price List Items" +msgstr "" + +#. module: product +#: field:pricelist.partnerinfo,price:0 +msgid "Unit Price" +msgstr "" + +#. module: product +#: field:product.category,parent_right:0 +msgid "Right Parent" +msgstr "" + +#. module: product +#: field:product.product,price:0 +msgid "Price" +msgstr "" + +#. module: product +#: field:product.pricelist.item,price_surcharge:0 +msgid "Price Surcharge" +msgstr "" + +#. module: product +#: field:product.product,code:0 +#: field:product.product,default_code:0 +msgid "Internal Reference" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_8_product_template +msgid "USB Keyboard, QWERTY" +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_9 +msgid "Softwares" +msgstr "" + +#. module: product +#: field:product.product,packaging:0 +msgid "Logistical Units" +msgstr "" + +#. module: product +#: field:product.category,complete_name:0 +#: field:product.category,name:0 +#: field:product.pricelist.type,name:0 +#: field:product.pricelist.version,name:0 +#: field:product.product,name_template:0 +#: field:product.template,name:0 +#: field:product.ul,name:0 +#: field:product.uom.categ,name:0 +msgid "Name" +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_4 +msgid "Computers" +msgstr "" + +#. module: product +#: help:product.product,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: product +#: model:product.uom,name:product.product_uom_kgm +msgid "kg" +msgstr "" + +#. module: product +#: selection:product.template,state:0 +msgid "Obsolete" +msgstr "" + +#. module: product +#: model:product.uom,name:product.product_uom_km +msgid "km" +msgstr "" + +#. module: product +#: field:product.template,standard_price:0 +msgid "Cost" +msgstr "" + +#. module: product +#: help:product.category,sequence:0 +msgid "" +"Gives the sequence order when displaying a list of product categories." +msgstr "" + +#. module: product +#: model:product.uom,name:product.product_uom_dozen +msgid "Dozen(s)" +msgstr "" + +#. module: product +#: field:product.uom,factor:0 +#: field:product.uom,factor_inv:0 +msgid "Ratio" +msgstr "" + +#. module: product +#: field:product.packaging,width:0 +msgid "Width" +msgstr "" + +#. module: product +#: help:product.price.type,field:0 +msgid "Associated field in the product form." +msgstr "" + +#. module: product +#: view:product.product:0 +#: view:product.template:0 +#: field:product.template,uom_id:0 +#: field:product.uom,name:0 +msgid "Unit of Measure" +msgstr "" + +#. module: product +#: report:product.pricelist:0 +msgid "Printing Date" +msgstr "" + +#. module: product +#: field:product.template,uos_id:0 +msgid "Unit of Sale" +msgstr "" + +#. module: product +#: field:product.product,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.product_uom_categ_form_action +#: model:ir.ui.menu,name:product.menu_product_uom_categ_form_action +msgid "Unit of Measure Categories" +msgstr "" + +#. module: product +#: help:product.product,seller_id:0 +msgid "Main Supplier who has highest priority in Supplier List." +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_5 +#: view:product.product:0 +msgid "Services" +msgstr "" + +#. module: product +#: help:product.product,ean13:0 +msgid "International Article Number used for product identification." +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_category_action +msgid "" +"\n" +" Here is a list of all your products classified by category. " +"You\n" +" can click a category to get the list of all products linked " +"to\n" +" this category or to a child of this category.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: code:addons/product/product.py:361 +#, python-format +msgid "" +"New Unit of Measure '%s' must belong to same Unit of Measure category '%s' " +"as of old Unit of Measure '%s'. If you need to change the unit of measure, " +"you may deactivate this product from the 'Procurements' tab and create a new " +"one." +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.product_normal_action +#: model:ir.actions.act_window,name:product.product_normal_action_puchased +#: model:ir.actions.act_window,name:product.product_normal_action_sell +#: model:ir.actions.act_window,name:product.product_normal_action_tree +#: model:ir.ui.menu,name:product.menu_products +#: model:ir.ui.menu,name:product.prod_config_main +#: view:product.product:0 +msgid "Products" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_32_product_template +msgid "" +"Hands free headset for laptop PC with in-line microphone and headphone plug." +msgstr "" + +#. module: product +#: help:product.packaging,rows:0 +msgid "The number of layers on a pallet or box" +msgstr "" + +#. module: product +#: help:product.pricelist.item,price_min_margin:0 +msgid "Specify the minimum amount of margin over the base price." +msgstr "" + +#. module: product +#: field:product.template,weight_net:0 +msgid "Net Weight" +msgstr "" + +#. module: product +#: view:product.packaging:0 +#: view:product.product:0 +msgid "Pallet Dimension" +msgstr "" + +#. module: product +#: help:product.product,image:0 +msgid "" +"This field holds the image used as image for the product, limited to " +"1024x1024px." +msgstr "" + +#. module: product +#: help:product.pricelist.item,categ_id:0 +msgid "" +"Specify a product category if this rule only applies to products belonging " +"to this category or its children categories. Keep empty otherwise." +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Inventory" +msgstr "" + +#. module: product +#: field:product.product,seller_info_id:0 +msgid "Supplier Info" +msgstr "" + +#. module: product +#: code:addons/product/product.py:729 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_2_product_template +msgid "On Site Assistance" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_39_product_template +msgid "Toner Cartridge" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.product_uom_form_action +#: model:ir.ui.menu,name:product.menu_product_uom_form_action +#: model:ir.ui.menu,name:product.next_id_16 +#: view:product.uom:0 +msgid "Units of Measure" +msgstr "" + +#. module: product +#: field:product.supplierinfo,min_qty:0 +msgid "Minimal Quantity" +msgstr "" + +#. module: product +#: help:product.supplierinfo,product_code:0 +msgid "" +"This supplier's product code will be used when printing a request for " +"quotation. Keep empty to use the internal one." +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_43_product_template +msgid "Zed+ Antivirus" +msgstr "" + +#. module: product +#: field:product.pricelist.item,price_version_id:0 +msgid "Price List Version" +msgstr "" + +#. module: product +#: help:product.pricelist.item,sequence:0 +msgid "" +"Gives the order in which the pricelist items will be checked. The evaluation " +"gives highest priority to lowest sequence and stops as soon as a matching " +"item is found." +msgstr "" + +#. module: product +#: view:product.product:0 +#: selection:product.template,type:0 +msgid "Consumable" +msgstr "" + +#. module: product +#: help:product.price.type,currency_id:0 +msgid "The currency the field is expressed in." +msgstr "" + +#. module: product +#: help:product.template,weight:0 +msgid "The gross weight in Kg." +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_37_product_template +msgid "Printer, All-in-one" +msgstr "" + +#. module: product +#: view:product.template:0 +msgid "Procurement" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_23_product_template +msgid "Processor AMD 8-Core" +msgstr "" + +#. module: product +#: view:product.product:0 +#: view:product.template:0 +msgid "Weights" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Description for Quotations" +msgstr "" + +#. module: product +#: help:pricelist.partnerinfo,price:0 +msgid "" +"This price will be considered as a price for the supplier Unit of Measure if " +"any or the default Unit of Measure of the product otherwise" +msgstr "" + +#. module: product +#: field:product.template,uom_po_id:0 +msgid "Purchase Unit of Measure" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Group by..." +msgstr "" + +#. module: product +#: field:product.product,image_medium:0 +msgid "Medium-sized image" +msgstr "" + +#. module: product +#: selection:product.ul,type:0 +#: model:product.uom.categ,name:product.product_uom_categ_unit +msgid "Unit" +msgstr "" + +#. module: product +#: field:product.pricelist.version,date_start:0 +msgid "Start Date" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_38_product_template +msgid "Ink Cartridge" +msgstr "" + +#. module: product +#: model:product.uom,name:product.product_uom_cm +msgid "cm" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_uom +msgid "Product Unit of Measure" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_pricelist_action +msgid "" +"\n" +" Click to add a pricelist version.\n" +"
\n" +" There can be more than one version of a pricelist, each of\n" +" these must be valid during a certain period of time. Some\n" +" examples of versions: Main Prices, 2010, 2011, Summer " +"Sales,\n" +" etc.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: help:product.template,uom_po_id:0 +msgid "" +"Default Unit of Measure used for purchase orders. It must be in the same " +"category than the default unit of measure." +msgstr "" + +#. module: product +#: view:product.pricelist:0 +msgid "Products Price" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_26_product_template +msgid "" +"17\" Monitor\n" +"6GB RAM\n" +"Hi-Speed 234Q Processor\n" +"QWERTY keyboard" +msgstr "" + +#. module: product +#: field:product.uom,rounding:0 +msgid "Rounding Precision" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Consumable products" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_21_product_template +msgid "Motherboard A20Z7" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_1_product_template +#: model:product.template,description_sale:product.product_product_1_product_template +msgid "This type of service include basic monitoring of products." +msgstr "" + +#. module: product +#: help:product.pricelist.version,date_end:0 +msgid "Last valid date for the version." +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_19_product_template +msgid "HDD on Demand" +msgstr "" + +#. module: product +#: field:product.price.type,active:0 +#: field:product.pricelist,active:0 +#: field:product.pricelist.version,active:0 +#: field:product.product,active:0 +#: field:product.uom,active:0 +msgid "Active" +msgstr "" + +#. module: product +#: field:product.product,price_margin:0 +msgid "Variant Price Margin" +msgstr "" + +#. module: product +#: field:product.pricelist,name:0 +msgid "Pricelist Name" +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_1 +msgid "Saleable" +msgstr "" + +#. module: product +#: sql_constraint:product.uom:0 +msgid "The conversion ratio for a unit of measure cannot be 0!" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_24_product_template +msgid "Graphics Card" +msgstr "" + +#. module: product +#: help:product.packaging,ean:0 +msgid "The EAN code of the package unit." +msgstr "" + +#. module: product +#: help:product.supplierinfo,product_uom:0 +msgid "This comes from the product form." +msgstr "" + +#. module: product +#: field:product.packaging,weight_ul:0 +msgid "Empty Package Weight" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_41_product_template +msgid "Windows Home Server 2011" +msgstr "" + +#. module: product +#: field:product.price.type,field:0 +msgid "Product Field" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_5_product_template +msgid "Custom computer assembled on order based on customer's requirement." +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.product_price_type_action +#: model:ir.ui.menu,name:product.menu_product_price_type +msgid "Price Types" +msgstr "" + +#. module: product +#: help:product.template,uom_id:0 +msgid "Default Unit of Measure used for all stock operation." +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Sales" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_uom_categ_form_action +msgid "" +"\n" +" Click to add a new unit of measure category.\n" +"
\n" +" Units of measure belonging to the same category can be\n" +" converted between each others. For example, in the category\n" +" 'Time', you will have the following units of " +"measure:\n" +" Hours, Days.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: help:pricelist.partnerinfo,min_quantity:0 +msgid "" +"The minimal quantity to trigger this rule, expressed in the supplier Unit of " +"Measure if any or in the default Unit of Measure of the product otherrwise." +msgstr "" + +#. module: product +#: selection:product.uom,uom_type:0 +msgid "Smaller than the reference Unit of Measure" +msgstr "" + +#. module: product +#: model:product.pricelist,name:product.list0 +msgid "Public Pricelist" +msgstr "" + +#. module: product +#: field:product.supplierinfo,product_code:0 +msgid "Supplier Product Code" +msgstr "" + +#. module: product +#: help:product.pricelist,active:0 +msgid "" +"If unchecked, it will allow you to hide the pricelist without removing it." +msgstr "" + +#. module: product +#: selection:product.ul,type:0 +msgid "Pallet" +msgstr "" + +#. module: product +#: field:product.packaging,ul_qty:0 +msgid "Package by layer" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_product +#: model:process.node,name:product.process_node_product0 +#: model:process.process,name:product.process_process_productprocess0 +#: field:product.packaging,product_id:0 +#: field:product.pricelist.item,product_id:0 +#: view:product.product:0 +#: field:product.supplierinfo,product_id:0 +#: model:res.request.link,name:product.req_link_product +msgid "Product" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Price:" +msgstr "" + +#. module: product +#: field:product.template,weight:0 +msgid "Gross Weight" +msgstr "" + +#. module: product +#: help:product.packaging,qty:0 +msgid "The total number of products you can put by pallet or box." +msgstr "" + +#. module: product +#: field:product.product,variants:0 +msgid "Variants" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.product_category_action +#: model:ir.ui.menu,name:product.menu_products_category +msgid "Products by Category" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_16_product_template +msgid "Computer Case" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_9_product_template +msgid "USB Keyboard, AZERTY" +msgstr "" + +#. module: product +#: help:product.supplierinfo,sequence:0 +msgid "Assigns the priority to the list of product supplier." +msgstr "" + +#. module: product +#: constraint:product.pricelist.item:0 +msgid "Error! The minimum margin should be lower than the maximum margin." +msgstr "" + +#. module: product +#: model:res.groups,name:product.group_uos +msgid "Manage Secondary Unit of Measure" +msgstr "" + +#. module: product +#: help:product.uom,rounding:0 +msgid "" +"The computed quantity will be a multiple of this value. Use 1.0 for a Unit " +"of Measure that cannot be further split, such as a piece." +msgstr "" + +#. module: product +#: view:product.pricelist.item:0 +msgid "Rounding Method" +msgstr "" + +#. module: product +#: model:ir.actions.report.xml,name:product.report_product_label +msgid "Products Labels" +msgstr "" + +#. module: product +#: model:product.ul,name:product.product_ul_big_box +msgid "Box 30x40x60" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_47_product_template +msgid "Switch, 24 ports" +msgstr "" + +#. module: product +#: selection:product.uom,uom_type:0 +msgid "Bigger than the reference Unit of Measure" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_consultant_product_template +#: selection:product.template,type:0 +msgid "Service" +msgstr "" + +#. module: product +#: view:product.template:0 +msgid "Internal Description" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_48_product_template +msgid "USB Adapter" +msgstr "" + +#. module: product +#: help:product.template,uos_id:0 +msgid "" +"Sepcify a unit of measure here if invoicing is made in another unit of " +"measure than inventory. Keep empty to use the default unit of measure." +msgstr "" + +#. module: product +#: code:addons/product/product.py:208 +#, python-format +msgid "Cannot change the category of existing Unit of Measure '%s'." +msgstr "" + +#. module: product +#: help:product.packaging,height:0 +msgid "The height of the package" +msgstr "" + +#. module: product +#: view:product.pricelist:0 +msgid "Products Price List" +msgstr "" + +#. module: product +#: field:product.pricelist,company_id:0 +#: field:product.pricelist.item,company_id:0 +#: field:product.pricelist.version,company_id:0 +#: view:product.product:0 +#: field:product.supplierinfo,company_id:0 +#: field:product.template,company_id:0 +msgid "Company" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_26_product_template +msgid "Laptop S3450" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Default Unit of Measure" +msgstr "" + +#. module: product +#: code:addons/product/pricelist.py:377 +#, python-format +msgid "Partner section of the product form" +msgstr "" + +#. module: product +#: help:product.price.type,name:0 +msgid "Name of this kind of price." +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_3 +msgid "Other Products" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_9_product_template +msgid "This product is configured with example of push/pull flows" +msgstr "" + +#. module: product +#: field:product.product,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: product +#: model:product.uom,name:product.product_uom_unit +msgid "Unit(s)" +msgstr "" + +#. module: product +#: code:addons/product/product.py:176 +#, python-format +msgid "Error!" +msgstr "" + +#. module: product +#: field:product.packaging,length:0 +msgid "Length" +msgstr "" + +#. module: product +#: model:product.uom.categ,name:product.uom_categ_length +msgid "Length / Distance" +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_8 +msgid "Components" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_pricelist_type +#: field:product.pricelist,type:0 +msgid "Pricelist Type" +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_6 +msgid "External Devices" +msgstr "" + +#. module: product +#: field:product.product,color:0 +msgid "Color Index" +msgstr "" + +#. module: product +#: help:product.template,sale_ok:0 +msgid "Specify if the product can be selected in a sales order line." +msgstr "" + +#. module: product +#: view:product.product:0 +#: field:product.template,sale_ok:0 +msgid "Can be Sold" +msgstr "" + +#. module: product +#: field:product.template,produce_delay:0 +msgid "Manufacturing Lead Time" +msgstr "" + +#. module: product +#: field:product.supplierinfo,pricelist_ids:0 +msgid "Supplier Pricelist" +msgstr "" + +#. module: product +#: field:product.pricelist.item,base:0 +msgid "Based on" +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_10 +msgid "Raw Materials" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_13_product_template +msgid "RAM SR5" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_14_product_template +msgid "RAM SR2" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_normal_action_puchased +msgid "" +"\n" +" Click to define a new product.\n" +"
\n" +" You must define a product for everything you purchase, " +"whether\n" +" it's a physical product, a consumable or services you buy " +"to\n" +" subcontractants.\n" +"
\n" +" The product form contains detailed information to improve " +"the\n" +" purchase process: prices, procurement logistics, accounting " +"data,\n" +" available suppliers, etc.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: model:product.template,description_sale:product.product_product_44_product_template +msgid "Full featured image editing software." +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_pricelist_version +#: view:product.pricelist:0 +#: view:product.pricelist.version:0 +msgid "Pricelist Version" +msgstr "" + +#. module: product +#: view:product.pricelist.item:0 +msgid "* ( 1 + " +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_31_product_template +msgid "Multimedia Speakers" +msgstr "" + +#. module: product +#: field:product.product,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Sale Conditions" +msgstr "" + +#. module: product +#: view:product.packaging:0 +#: view:product.product:0 +msgid "Palletization" +msgstr "" + +#. module: product +#: report:product.pricelist:0 +msgid "Price List Name" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Description for Suppliers" +msgstr "" + +#. module: product +#: field:product.supplierinfo,delay:0 +msgid "Delivery Lead Time" +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "months" +msgstr "" + +#. module: product +#: help:product.uom,active:0 +msgid "" +"By unchecking the active field you can disable a unit of measure without " +"deleting it." +msgstr "" + +#. module: product +#: field:product.product,seller_delay:0 +msgid "Supplier Lead Time" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_decimal_precision +msgid "decimal.precision" +msgstr "" + +#. module: product +#: selection:product.ul,type:0 +msgid "Box" +msgstr "" + +#. module: product +#: help:product.pricelist.item,price_surcharge:0 +msgid "" +"Specify the fixed amount to add or substract(if negative) to the amount " +"calculated with the discount." +msgstr "" + +#. module: product +#: help:product.product,qty_available:0 +msgid "" +"Current quantity of products.\n" +"In a context with a single Stock Location, this includes goods stored at " +"this Location, or any of its children.\n" +"In a context with a single Warehouse, this includes goods stored in the " +"Stock Location of this Warehouse, or any of its children.\n" +"In a context with a single Shop, this includes goods stored in the Stock " +"Location of the Warehouse of this Shop, or any of its children.\n" +"Otherwise, this includes goods stored in any Stock Location with 'internal' " +"type." +msgstr "" + +#. module: product +#: help:product.template,type:0 +msgid "" +"Consumable: Will not imply stock management for this product. \n" +"Stockable product: Will imply stock management for this product." +msgstr "" + +#. module: product +#: help:product.pricelist.type,key:0 +msgid "" +"Used in the code to select specific prices based on the context. Keep " +"unchanged." +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_normal_action +msgid "" +"\n" +" Click to define a new product.\n" +"
\n" +" You must define a product for everything you buy or sell,\n" +" whether it's a physical product, a consumable or service.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: view:product.product:0 +msgid "Context..." +msgstr "" + +#. module: product +#: field:product.packaging,ul:0 +msgid "Type of Package" +msgstr "" + +#. module: product +#: help:product.category,type:0 +msgid "" +"A category of the view type is a virtual category that can be used as the " +"parent of another category to create a hierarchical structure." +msgstr "" + +#. module: product +#: selection:product.ul,type:0 +msgid "Pack" +msgstr "" + +#. module: product +#: help:product.pricelist.item,product_tmpl_id:0 +msgid "" +"Specify a template if this rule only applies to one product template. Keep " +"empty otherwise." +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_2_product_template +msgid "" +"This type of service include assistance for security questions, system " +"configuration requirements, implementation or special needs." +msgstr "" + +#. module: product +#: field:product.product,image:0 +msgid "Image" +msgstr "" + +#. module: product +#: view:product.uom.categ:0 +msgid "Units of Measure categories" +msgstr "" + +#. module: product +#: model:product.template,description_sale:product.product_product_4_product_template +msgid "" +"19\" LCD Monitor\n" +"Processor Core i5 2.70 Ghz\n" +"2GB RAM\n" +"HDD SH-1" +msgstr "" + +#. module: product +#: view:product.template:0 +msgid "Descriptions" +msgstr "" + +#. module: product +#: model:res.groups,name:product.group_stock_packaging +msgid "Manage Product Packaging" +msgstr "" + +#. module: product +#: model:product.category,name:product.product_category_2 +msgid "Internal" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_45_product_template +msgid "Router R430" +msgstr "" + +#. module: product +#: help:product.packaging,sequence:0 +msgid "Gives the sequence order when displaying a list of packaging." +msgstr "" + +#. module: product +#: selection:product.category,type:0 +#: selection:product.template,state:0 +msgid "Normal" +msgstr "" + +#. module: product +#: code:addons/product/pricelist.py:179 +#, python-format +msgid "" +"At least one pricelist has no active version !\n" +"Please create or activate one." +msgstr "" + +#. module: product +#: field:product.pricelist.item,price_max_margin:0 +msgid "Max. Price Margin" +msgstr "" + +#. module: product +#: view:product.pricelist.item:0 +msgid "Min. Margin" +msgstr "" + +#. module: product +#: help:product.supplierinfo,product_name:0 +msgid "" +"This supplier's product name will be used when printing a request for " +"quotation. Keep empty to use the internal one." +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_pricelist_action_for_purchase +msgid "" +"\n" +" Click to create a pricelist.\n" +"
\n" +" A price list contains rules to be evaluated in order to " +"compute\n" +" the purchase price. The default price list has only one " +"rule; use\n" +" the cost price defined on the product form, so that you do " +"not have to\n" +" worry about supplier pricelists if you have very simple " +"needs.\n" +"
\n" +" But you can also import complex price lists form your " +"supplier\n" +" that may depends on the quantities ordered or the current\n" +" promotions.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: selection:product.template,mes_type:0 +msgid "Variable" +msgstr "" + +#. module: product +#: field:product.template,rental:0 +msgid "Can be Rent" +msgstr "" + +#. module: product +#: model:product.price.type,name:product.standard_price +msgid "Cost Price" +msgstr "" + +#. module: product +#: field:product.pricelist.item,price_min_margin:0 +msgid "Min. Price Margin" +msgstr "" + +#. module: product +#: model:res.groups,name:product.group_uom +msgid "Manage Multiple Units of Measure" +msgstr "" + +#. module: product +#: help:product.packaging,weight:0 +msgid "The weight of a full package, pallet or box." +msgstr "" + +#. module: product +#: view:product.uom:0 +msgid "e.g: 1 * (this unit) = ratio * (reference unit)" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_25_product_template +msgid "" +"17\" Monitor\n" +"4GB RAM\n" +"Standard-1294P Processor\n" +"QWERTY keyboard" +msgstr "" + +#. module: product +#: field:product.category,sequence:0 +#: field:product.packaging,sequence:0 +#: field:product.pricelist.item,sequence:0 +#: field:product.supplierinfo,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: product +#: help:product.template,produce_delay:0 +msgid "" +"Average delay in days to produce this product. In the case of multi-level " +"BOM, the manufacturing lead times of the components will be added." +msgstr "" + +#. module: product +#: model:product.template,name:product.product_assembly_product_template +msgid "Assembly Service Cost" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_pricelist_item +msgid "Pricelist item" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_uom_form_action +msgid "" +"\n" +" Click to add a new unit of measure.\n" +"
\n" +" You must define a conversion rate between several Units of\n" +" Measure within the same category.\n" +"
\n" +" " +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_11_product_template +msgid "Mouse, Laser" +msgstr "" + +#. module: product +#: view:product.template:0 +msgid "Delays" +msgstr "" + +#. module: product +#: field:product.category,type:0 +msgid "Category Type" +msgstr "" + +#. module: product +#: model:process.node,note:product.process_node_product0 +msgid "Creation of the product" +msgstr "" + +#. module: product +#: field:pricelist.partnerinfo,name:0 +#: field:product.packaging,name:0 +#: report:product.pricelist:0 +#: view:product.product:0 +#: field:product.template,description:0 +msgid "Description" +msgstr "" + +#. module: product +#: field:product.packaging,ean:0 +msgid "EAN" +msgstr "" + +#. module: product +#: view:product.pricelist.item:0 +msgid " ) + " +msgstr "" + +#. module: product +#: field:product.template,volume:0 +#: model:product.uom.categ,name:product.product_uom_categ_vol +msgid "Volume" +msgstr "" + +#. module: product +#: help:product.product,image_small:0 +msgid "" +"Small-sized image of the product. It is automatically resized as a 64x64px " +"image, with aspect ratio preserved. Use this field anywhere a small image is " +"required." +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_40_product_template +msgid "Windows 7 Professional" +msgstr "" + +#. module: product +#: selection:product.uom,uom_type:0 +msgid "Reference Unit of Measure for this category" +msgstr "" + +#. module: product +#: field:product.supplierinfo,product_uom:0 +msgid "Supplier Unit of Measure" +msgstr "" + +#. module: product +#: view:product.product:0 +#: model:res.groups,name:product.group_product_variant +msgid "Product Variant" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_6_product_template +msgid "15” LCD Monitor" +msgstr "" + +#. module: product +#: code:addons/product/pricelist.py:376 +#: field:product.pricelist.item,base_pricelist_id:0 +#, python-format +msgid "Other Pricelist" +msgstr "" + +#. module: product +#: model:ir.actions.act_window,help:product.product_pricelist_action2 +msgid "" +"\n" +" Click to create a pricelist.\n" +"
\n" +" A price list contains rules to be evaluated in order to " +"compute\n" +" the sales price of the products.\n" +"
\n" +" Price lists may have several versions (2010, 2011, Promotion " +"of\n" +" February 2010, etc.) and each version may have several " +"rules.\n" +" (e.g. the customer price of a product category will be based " +"on\n" +" the supplier price multiplied by 1.80).\n" +"
\n" +" " +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_template +#: field:product.pricelist.item,product_tmpl_id:0 +#: field:product.product,product_tmpl_id:0 +#: view:product.template:0 +msgid "Product Template" +msgstr "" + +#. module: product +#: field:product.template,cost_method:0 +#: model:res.groups,name:product.group_costing_method +msgid "Costing Method" +msgstr "" + +#. module: product +#: model:ir.model,name:product.model_product_category +#: field:product.pricelist.item,categ_id:0 +msgid "Product Category" +msgstr "" + +#. module: product +#: model:product.template,description:product.product_product_19_product_template +msgid "On demand hard-disk having capacity based on requirement." +msgstr "" + +#. module: product +#: selection:product.template,state:0 +msgid "End of Lifecycle" +msgstr "" + +#. module: product +#: model:product.template,name:product.product_product_15_product_template +msgid "RAM SR3" +msgstr "" + +#. module: product +#: help:product.product,packaging:0 +msgid "" +"Gives the different ways to package the same product. This has no impact on " +"the picking order and is mainly used if you use the EDI module." +msgstr "" + +#. module: product +#: model:ir.actions.act_window,name:product.product_pricelist_action +#: model:ir.ui.menu,name:product.menu_product_pricelist_action +#: field:product.pricelist,version_id:0 +msgid "Pricelist Versions" +msgstr "" + +#. module: product +#: help:product.pricelist.item,price_round:0 +msgid "" +"Sets the price so that it is a multiple of this value.\n" +"Rounding is applied after the discount and before the surcharge.\n" +"To have prices that end in 9.99, set rounding 10, surcharge -0.01" +msgstr "" + +#. module: product +#: field:product.template,list_price:0 +msgid "Sale Price" +msgstr "" + +#. module: product +#: help:product.uom,category_id:0 +msgid "" +"Conversion between Units of Measure can only occur if they belong to the " +"same category. The conversion will be made based on the ratios." +msgstr "" + +#. module: product +#: constraint:product.category:0 +msgid "Error ! You cannot create recursive categories." +msgstr "" + +#. module: product +#: help:product.product,image_medium:0 +msgid "" +"Medium-sized image of the product. It is automatically resized as a " +"128x128px image, with aspect ratio preserved, only when the image exceeds " +"one of those sizes. Use this field in form views or some kanban views." +msgstr "" + +#. module: product +#: view:product.uom:0 +msgid "e.g: 1 * (reference unit) = ratio * (this unit)" +msgstr "" + +#. module: product +#: help:product.supplierinfo,qty:0 +msgid "This is a quantity which is converted into Default Unit of Measure." +msgstr "" + +#. module: product +#: help:product.template,volume:0 +msgid "The volume in m3." +msgstr "" + +#. module: product +#: field:product.pricelist.item,price_discount:0 +msgid "Price Discount" +msgstr "" diff --git a/addons/report_webkit/ir_report.py b/addons/report_webkit/ir_report.py index 1385f504928..01b65987a8e 100644 --- a/addons/report_webkit/ir_report.py +++ b/addons/report_webkit/ir_report.py @@ -30,21 +30,22 @@ ############################################################################## from openerp.osv import fields, osv -from openerp import netsvc -from webkit_report import WebKitParser +import openerp.report.interface from openerp.report.report_sxw import rml_parse +from webkit_report import WebKitParser + def register_report(name, model, tmpl_path, parser=rml_parse): """Register the report into the services""" name = 'report.%s' % name - if netsvc.Service._services.get(name, False): - service = netsvc.Service._services[name] + if name in openerp.report.interface.report_int._reports: + service = openerp.report.interface.report_int[name] if isinstance(service, WebKitParser): #already instantiated properly, skip it return if hasattr(service, 'parser'): parser = service.parser - del netsvc.Service._services[name] + del openerp.report.interface.report_int[name] WebKitParser(name, model, tmpl_path, parser=parser)