From 63ee6a74a91a630f5b5049f10ae67291df85f760 Mon Sep 17 00:00:00 2001
From: "Divyesh Makwana (Open ERP)"
Date: Mon, 9 Jul 2012 17:09:54 +0530
Subject: [PATCH 001/171] [IMP] project : column
project_task_history_cumulative.project_id does not exist.
lp bug: https://launchpad.net/bugs/1022509 fixed
bzr revid: mdi@tinyerp.com-20120709113954-l17wlurxovz6z05i
---
addons/project/report/project_cumulative.xml | 3 ---
1 file changed, 3 deletions(-)
diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml
index 3f7f3b26d96..535fbaf5f87 100644
--- a/addons/project/report/project_cumulative.xml
+++ b/addons/project/report/project_cumulative.xml
@@ -9,7 +9,6 @@
-
@@ -63,9 +62,7 @@
-
-
From e2ba0eb95c38a16839836deeaa9a73b58221e9aa Mon Sep 17 00:00:00 2001
From: "Divyesh Makwana (Open ERP)"
Date: Mon, 9 Jul 2012 18:42:59 +0530
Subject: [PATCH 002/171] [IMP] project : Revert the unneccessary changes.
bzr revid: mdi@tinyerp.com-20120709131259-c9fl7g3hgwhxutgb
---
addons/project/report/project_cumulative.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml
index 535fbaf5f87..177e945bc93 100644
--- a/addons/project/report/project_cumulative.xml
+++ b/addons/project/report/project_cumulative.xml
@@ -9,6 +9,7 @@
+
From 9805c665c89784bdaa5234668ed79ca2280cb124 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Wed, 19 Sep 2012 13:40:47 +0200
Subject: [PATCH 003/171] [ADD] big bit on new import: pretty much everything
but o2m
bzr revid: xmo@openerp.com-20120919114047-w4paoim95oxr91zb
---
openerp/addons/base/ir/__init__.py | 1 +
openerp/addons/base/ir/ir_fields.py | 193 ++++
openerp/osv/fields.py | 42 +-
openerp/osv/orm.py | 226 +++-
.../tests/addons/test_impex/tests/__init__.py | 3 +-
.../addons/test_impex/tests/test_load.py | 987 ++++++++++++++++++
openerp/tests/test_misc.py | 38 +-
openerp/tools/misc.py | 34 +
setup.py | 1 +
9 files changed, 1507 insertions(+), 18 deletions(-)
create mode 100644 openerp/addons/base/ir/ir_fields.py
create mode 100644 openerp/tests/addons/test_impex/tests/test_load.py
diff --git a/openerp/addons/base/ir/__init__.py b/openerp/addons/base/ir/__init__.py
index bc4f3eecfbf..ba8b785f39d 100644
--- a/openerp/addons/base/ir/__init__.py
+++ b/openerp/addons/base/ir/__init__.py
@@ -40,6 +40,7 @@ import wizard
import ir_config_parameter
import osv_memory_autovacuum
import ir_mail_server
+import ir_fields
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
new file mode 100644
index 00000000000..f73067c9f6c
--- /dev/null
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -0,0 +1,193 @@
+# -*- coding: utf-8 -*-
+import functools
+import operator
+import warnings
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+
+class ConversionNotFound(ValueError): pass
+
+class ir_fields_converter(orm.Model):
+ _name = 'ir.fields.converter'
+
+ def to_field(self, cr, uid, model, column, fromtype=str, context=None):
+ """ Fetches a converter for the provided column object, from the
+ specified type.
+
+ A converter is simply a callable taking a value of type ``fromtype``
+ (or a composite of ``fromtype``, e.g. list or dict) and returning a
+ value acceptable for a write() on the column ``column``.
+
+ By default, tries to get a method on itself with a name matching the
+ pattern ``_$fromtype_$column._type`` and returns it.
+
+ :param cr: openerp cursor
+ :param uid: ID of user calling the converter
+ :param column: column object to generate a value for
+ :type column: :class:`fields._column`
+ :param type fromtype: type to convert to something fitting for ``column``
+ :param context: openerp request context
+ :return: a function (fromtype -> column.write_type), if a converter is found
+ :rtype: Callable | None
+ """
+ # FIXME: return None
+ converter = getattr(
+ self, '_%s_to_%s' % (fromtype.__name__, column._type))
+ if not converter: return None
+
+ return functools.partial(
+ converter, cr, uid, model, column, context=context)
+
+ def _str_to_boolean(self, cr, uid, model, column, value, context=None):
+ return value.lower() not in ('', '0', 'false', 'off')
+
+ def _str_to_integer(self, cr, uid, model, column, value, context=None):
+ if not value: return False
+ return int(value)
+
+ def _str_to_float(self, cr, uid, model, column, value, context=None):
+ if not value: return False
+ return float(value)
+
+ def _str_to_char(self, cr, uid, model, column, value, context=None):
+ return value or False
+
+ def _str_to_text(self, cr, uid, model, column, value, context=None):
+ return value or False
+
+ def _get_translations(self, cr, uid, types, src, context):
+ Translations = self.pool['ir.translation']
+ tnx_ids = Translations.search(
+ cr, uid, [('type', 'in', types), ('src', '=', src)], context=context)
+ tnx = Translations.read(cr, uid, tnx_ids, ['value'], context=context)
+ return map(operator.itemgetter('value'), tnx)
+ def _str_to_selection(self, cr, uid, model, column, value, context=None):
+
+ selection = column.selection
+ if not isinstance(selection, (tuple, list)):
+ # FIXME: Don't pass context to avoid translations?
+ # Or just copy context & remove lang?
+ selection = selection(model, cr, uid)
+ for item, label in selection:
+ labels = self._get_translations(
+ cr, uid, ('selection', 'model'), label, context=context)
+ labels.append(label)
+ if value == unicode(item) or value in labels:
+ return item
+ raise ValueError(
+ _(u"Value '%s' not found in selection field '%%(field)s'") % (
+ value))
+
+
+ def db_id_for(self, cr, uid, model, column, subfield, value, context=None):
+ """ Finds a database id for the reference ``value`` in the referencing
+ subfield ``subfield`` of the provided column of the provided model.
+
+ :param cr: OpenERP cursor
+ :param uid: OpenERP user id
+ :param model: model to which the column belongs
+ :param column: relational column for which references are provided
+ :param subfield: a relational subfield allowing building of refs to
+ existing records: ``None`` for a name_get/name_search,
+ ``id`` for an external id and ``.id`` for a database
+ id
+ :param value: value of the reference to match to an actual record
+ :param context: OpenERP request context
+ :return: a pair of the matched database identifier (if any) and the
+ translated user-readable name for the field
+ :rtype: (ID|None, unicode)
+ """
+ id = None
+ RelatedModel = self.pool[column._obj]
+ if subfield == '.id':
+ field_type = _(u"database id")
+ try: tentative_id = int(value)
+ except ValueError: tentative_id = value
+ if RelatedModel.search(cr, uid, [('id', '=', tentative_id)],
+ context=context):
+ id = tentative_id
+ elif subfield == 'id':
+ field_type = _(u"external id")
+ if '.' in value:
+ module, xid = value.split('.', 1)
+ else:
+ module, xid = '', value
+ ModelData = self.pool['ir.model.data']
+ try:
+ md_id = ModelData._get_id(cr, uid, module, xid)
+ model_data = ModelData.read(cr, uid, [md_id], ['res_id'],
+ context=context)
+ if model_data:
+ id = model_data[0]['res_id']
+ except ValueError: pass # leave id is None
+ elif subfield is None:
+ field_type = _(u"name")
+ ids = RelatedModel.name_search(
+ cr, uid, name=value, operator='=', context=context)
+ if ids:
+ if len(ids) > 1:
+ warnings.warn(
+ _(u"Found multiple matches for field '%%(field)s' (%d matches)")
+ % (len(ids)), orm.ImportWarning)
+ id, _name = ids[0]
+ else:
+ raise Exception(u"Unknown sub-field '%s'" % subfield)
+ return id, field_type
+
+ def _referencing_subfield(self, record):
+ """ Checks the record for the subfields allowing referencing (an
+ existing record in an other table), errors out if it finds potential
+ conflicts (multiple referencing subfields) or non-referencing subfields
+ returns the name of the correct subfield.
+
+ :param record:
+ :return: the record subfield to use for referencing
+ :rtype: str
+ """
+ # Can import by name_get, external id or database id
+ allowed_fields = set([None, 'id', '.id'])
+ fieldset = set(record.iterkeys())
+ if fieldset - allowed_fields:
+ raise ValueError(
+ _(u"Can not create Many-To-One records indirectly, import the field separately"))
+ if len(fieldset) > 1:
+ raise ValueError(
+ _(u"Ambiguous specification for field '%(field)s', only provide one of name, external id or database id"))
+
+ # only one field left possible, unpack
+ [subfield] = fieldset
+ return subfield
+
+ def _str_to_many2one(self, cr, uid, model, column, values, context=None):
+ # Should only be one record, unpack
+ [record] = values
+
+ subfield = self._referencing_subfield(record)
+
+ reference = record[subfield]
+ id, subfield_type = self.db_id_for(
+ cr, uid, model, column, subfield, reference, context=context)
+
+ if id is None:
+ raise ValueError(
+ _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'")
+ % {'field_type': subfield_type, 'value': reference})
+ return id
+ def _str_to_many2many(self, cr, uid, model, column, value, context=None):
+ [record] = value
+
+ subfield = self._referencing_subfield(record)
+
+ ids = []
+ for reference in record[subfield].split(','):
+ id, subfield_type = self.db_id_for(
+ cr, uid, model, column, subfield, reference, context=context)
+ if id is None:
+ raise ValueError(
+ _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'")
+ % {'field_type': subfield_type, 'value': reference})
+ ids.append(id)
+
+ return [(6, 0, ids)]
+ def _str_to_one2many(self, cr, uid, model, column, value, context=None):
+ return value
diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py
index 037d2a90986..36c6600a7e5 100644
--- a/openerp/osv/fields.py
+++ b/openerp/osv/fields.py
@@ -1588,19 +1588,32 @@ def field_to_dict(model, cr, user, field, context=None):
class column_info(object):
- """Struct containing details about an osv column, either one local to
- its model, or one inherited via _inherits.
+ """ Struct containing details about an osv column, either one local to
+ its model, or one inherited via _inherits.
- :attr name: name of the column
- :attr column: column instance, subclass of osv.fields._column
- :attr parent_model: if the column is inherited, name of the model
- that contains it, None for local columns.
- :attr parent_column: the name of the column containing the m2o
- relationship to the parent model that contains
- this column, None for local columns.
- :attr original_parent: if the column is inherited, name of the original
- parent model that contains it i.e in case of multilevel
- inheritence, None for local columns.
+ .. attribute:: name
+
+ name of the column
+
+ .. attribute:: column
+
+ column instance, subclass of :class:`_column`
+
+ .. attribute:: parent_model
+
+ if the column is inherited, name of the model that contains it,
+ ``None`` for local columns.
+
+ .. attribute:: parent_column
+
+ the name of the column containing the m2o relationship to the
+ parent model that contains this column, ``None`` for local columns.
+
+ .. attribute:: original_parent
+
+ if the column is inherited, name of the original parent model that
+ contains it i.e in case of multilevel inheritance, ``None`` for
+ local columns.
"""
def __init__(self, name, column, parent_model=None, parent_column=None, original_parent=None):
self.name = name
@@ -1609,5 +1622,10 @@ class column_info(object):
self.parent_column = parent_column
self.original_parent = original_parent
+ def __str__(self):
+ return '%s(%s, %s, %s, %s, %s)' % (
+ self.__name__, self.name, self.column,
+ self.parent_model, self.parent_column, self.original_parent)
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index 9d3b92a3d31..57cc5823dd9 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -52,13 +52,17 @@ import re
import simplejson
import time
import types
+
+import psycopg2
from lxml import etree
+import warnings
import fields
import openerp
import openerp.netsvc as netsvc
import openerp.tools as tools
from openerp.tools.config import config
+from openerp.tools.misc import CountingStream
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
@@ -1242,7 +1246,7 @@ class BaseModel(object):
* The last item is currently unused, with no specific semantics
:param fields: list of fields to import
- :param data: data to import
+ :param datas: data to import
:param mode: 'init' or 'update' for record creation
:param current_module: module name
:param noupdate: flag for record creation
@@ -1438,6 +1442,199 @@ class BaseModel(object):
self._parent_store_compute(cr)
return position, 0, 0, 0
+ def load(self, cr, uid, fields, data, context=None):
+ """
+
+ :param cr: cursor for the request
+ :param int uid: ID of the user attempting the data import
+ :param fields: list of fields to import, at the same index as the corresponding data
+ :type fields: list(str)
+ :param data: row-major matrix of data to import
+ :type data: list(list(str))
+ :param dict context:
+ :returns:
+ """
+ cr.execute('SAVEPOINT model_load')
+ messages = []
+
+ fields = map(fix_import_export_id_paths, fields)
+ ModelData = self.pool['ir.model.data']
+
+ mode = 'init'
+ current_module = ''
+ noupdate = False
+
+ ids = []
+ for id, xid, record, info in self._convert_records(cr, uid,
+ self._extract_records(cr, uid, fields, data,
+ context=context, log=messages.append),
+ context=context, log=messages.append):
+ cr.execute('SAVEPOINT model_load_save')
+ try:
+ ids.append(ModelData._update(cr, uid, self._name,
+ current_module, record, mode=mode, xml_id=xid,
+ noupdate=noupdate, res_id=id, context=context))
+ cr.execute('RELEASE SAVEPOINT model_load_save')
+ except psycopg2.Error, e:
+ # Failed to write, log to messages, rollback savepoint (to
+ # avoid broken transaction) and keep going
+ cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
+ messages.append(dict(info, type="error", message=str(e)))
+ if any(message['type'] == 'error' for message in messages):
+ cr.execute('ROLLBACK TO SAVEPOINT model_load')
+ return False, messages
+ return ids, messages
+ def _extract_records(self, cr, uid, fields_, data,
+ context=None, log=lambda a: None):
+ """ Generates record dicts from the data iterable.
+
+ The result is a generator of dicts mapping field names to raw
+ (unconverted, unvalidated) values.
+
+ For relational fields, if sub-fields were provided the value will be
+ a list of sub-records
+
+ The following sub-fields may be set on the record (by key):
+ * None is the name_get for the record (to use with name_create/name_search)
+ * "id" is the External ID for the record
+ * ".id" is the Database ID for the record
+
+ :param ImportLogger logger:
+ """
+ columns = dict((k, v.column) for k, v in self._all_columns.iteritems())
+ # Fake columns to avoid special cases in extractor
+ columns[None] = fields.char('rec_name')
+ columns['id'] = fields.char('External ID')
+ columns['.id'] = fields.integer('Database ID')
+
+ # m2o fields can't be on multiple lines so exclude them from the
+ # is_relational field rows filter, but special-case it later on to
+ # be handled with relational fields (as it can have subfields)
+ is_relational = lambda field: columns[field]._type in ('one2many', 'many2many', 'many2one')
+ get_o2m_values = itemgetter_tuple(
+ [index for index, field in enumerate(fields_)
+ if columns[field[0]]._type == 'one2many'])
+ get_nono2m_values = itemgetter_tuple(
+ [index for index, field in enumerate(fields_)
+ if columns[field[0]]._type != 'one2many'])
+ # Checks if the provided row has any non-empty non-relational field
+ def only_o2m_values(row, f=get_nono2m_values, g=get_o2m_values):
+ return any(g(row)) and not any(f(row))
+
+ rows = CountingStream(data)
+ while True:
+ row = next(rows, None)
+ if row is None: return
+ record_row_index = rows.index
+
+ # copy non-relational fields to record dict
+ record = dict((field[0], value)
+ for field, value in itertools.izip(fields_, row)
+ if not is_relational(field[0]))
+
+ # Get all following rows which have relational values attached to
+ # the current record (no non-relational values)
+ # WARNING: replaces existing ``rows``
+ record_span, _rows = span(only_o2m_values, rows)
+ # stitch record row back on for relational fields
+ record_span = itertools.chain([row], record_span)
+ for relfield in set(
+ field[0] for field in fields_
+ if is_relational(field[0])):
+ column = columns[relfield]
+ # FIXME: how to not use _obj without relying on fields_get?
+ Model = self.pool[column._obj]
+
+ # copy stream to reuse for next relational field
+ fieldrows, record_span = itertools.tee(record_span)
+ # get only cells for this sub-field, should be strictly
+ # non-empty, field path [None] is for name_get column
+ indices, subfields = zip(*((index, field[1:] or [None])
+ for index, field in enumerate(fields_)
+ if field[0] == relfield))
+
+ # return all rows which have at least one value for the
+ # subfields of relfield
+ relfield_data = filter(any, map(itemgetter_tuple(indices), fieldrows))
+ record[relfield] = [subrecord
+ for subrecord, _subinfo in Model._extract_records(
+ cr, uid, subfields, relfield_data,
+ context=context, log=log)]
+ # Ensure full consumption of the span (and therefore advancement of
+ # ``rows``) even if there are no relational fields. Needs two as
+ # the code above stiched the row back on (so first call may only
+ # get the stiched row without advancing the underlying operator row
+ # itself)
+ next(record_span, None)
+ next(record_span, None)
+
+ # old rows consumption (by iterating the span) should be done here,
+ # at this point the old ``rows`` is 1 past `span` (either on the
+ # next record row or past ``StopIteration``, so wrap new ``rows``
+ # (``_rows``) in a counting stream indexed 1-before the old
+ # ``rows``
+ rows = CountingStream(_rows, rows.index - 1)
+ yield record, {'rows': {'from': record_row_index,'to': rows.index}}
+ def _convert_records(self, cr, uid, records,
+ context=None, log=lambda a: None):
+ """ Converts records from the source iterable (recursive dicts of
+ strings) into forms which can be written to the database (via
+ self.create or (ir.model.data)._update)
+
+ :param ImportLogger parent_logger:
+ :returns: a list of triplets of (id, xid, record)
+ :rtype: list((int|None, str|None, dict))
+ """
+ Converter = self.pool['ir.fields.converter']
+ columns = dict((k, v.column) for k, v in self._all_columns.iteritems())
+ converters = dict(
+ (k, Converter.to_field(cr, uid, self, column, context=context))
+ for k, column in columns.iteritems())
+
+ stream = CountingStream(records)
+ for record, extras in stream:
+ dbid = False
+ xid = False
+ converted = {}
+ # name_get/name_create
+ if None in record: pass
+ # xid
+ if 'id' in record:
+ xid = record['id']
+ # dbid
+ if '.id' in record:
+ try:
+ dbid = int(record['.id'])
+ except ValueError:
+ # in case of overridden id column
+ dbid = record['.id']
+ if not self.search(cr, uid, [('id', '=', dbid)], context=context):
+ log(dict(extras,
+ type='error',
+ record=stream.index,
+ field='.id',
+ message=_(u"Unknown database identifier '%s'") % dbid))
+ dbid = False
+
+ for field, strvalue in record.iteritems():
+ if field in (None, 'id', '.id'): continue
+
+ message_base = dict(extras, record=stream.index, field=field)
+ with warnings.catch_warnings(record=True) as w:
+ try:
+ converted[field] = converters[field](strvalue)
+
+ for warning in w:
+ log(dict(message_base, type='warning',
+ message=unicode(warning.message) % message_base))
+ except ValueError, e:
+ log(dict(message_base,
+ type='error',
+ message=unicode(e) % message_base
+ ))
+
+ yield dbid, xid, converted, dict(extras, record=stream.index)
+
def get_invalid_fields(self, cr, uid):
return list(self._invalids)
@@ -5108,5 +5305,32 @@ class AbstractModel(BaseModel):
_auto = False # don't create any database backend for AbstractModels
_register = False # not visible in ORM registry, meant to be python-inherited only
+def span(predicate, iterable):
+ """ Splits the iterable between the longest prefix of ``iterable`` whose
+ elements satisfy ``predicate`` and the rest.
+ If called with a list, equivalent to::
+
+ takewhile(predicate, lst), dropwhile(predicate, lst)
+
+ :param callable predicate:
+ :param iterable:
+ :rtype: (iterable, iterable)
+ """
+ it1, it2 = itertools.tee(iterable)
+ return (itertools.takewhile(predicate, it1),
+ itertools.dropwhile(predicate, it2))
+def itemgetter_tuple(items):
+ """ Fixes itemgetter inconsistency (useful in some cases) of not returning
+ a tuple if len(items) == 1: always returns an n-tuple where n = len(items)
+ """
+ if len(items) == 0:
+ return lambda a: ()
+ if len(items) == 1:
+ return lambda gettable: (gettable[items[0]],)
+ return operator.itemgetter(*items)
+class ImportWarning(Warning):
+ """ Used to send warnings upwards the stack during the import process
+ """
+ pass
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/openerp/tests/addons/test_impex/tests/__init__.py b/openerp/tests/addons/test_impex/tests/__init__.py
index d6af53cba1b..8cab56fcc9a 100644
--- a/openerp/tests/addons/test_impex/tests/__init__.py
+++ b/openerp/tests/addons/test_impex/tests/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-from . import test_export, test_import
+from . import test_export, test_import, test_load
fast_suite = [
]
@@ -8,6 +8,7 @@ fast_suite = [
checks = [
test_export,
test_import,
+ test_load,
]
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
new file mode 100644
index 00000000000..80e5cfe9c8f
--- /dev/null
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -0,0 +1,987 @@
+# -*- coding: utf-8 -*-
+import openerp.modules.registry
+import openerp
+
+from openerp.tests import common
+from openerp.tools.misc import mute_logger
+
+def message(msg, type='error', from_=0, to_=0, record=0, field='value'):
+ return {
+ 'type': type,
+ 'rows': {'from': from_, 'to': to_},
+ 'record': record,
+ 'field': field,
+ 'message': msg
+ }
+
+def error(row, message, record=None, **kwargs):
+ """ Failed import of the record ``record`` at line ``row``, with the error
+ message ``message``
+
+ :param str message:
+ :param dict record:
+ """
+ return (
+ -1, dict(record or {}, **kwargs),
+ "Line %d : %s" % (row, message),
+ '')
+
+def values(seq, field='value'):
+ return [item[field] for item in seq]
+
+class ImporterCase(common.TransactionCase):
+ model_name = False
+
+ def __init__(self, *args, **kwargs):
+ super(ImporterCase, self).__init__(*args, **kwargs)
+ self.model = None
+
+ def setUp(self):
+ super(ImporterCase, self).setUp()
+ self.model = self.registry(self.model_name)
+ self.registry('ir.model.data').clear_caches()
+
+ def import_(self, fields, rows, context=None):
+ return self.model.load(
+ self.cr, openerp.SUPERUSER_ID, fields, rows, context=context)
+ def read(self, fields=('value',), domain=(), context=None):
+ return self.model.read(
+ self.cr, openerp.SUPERUSER_ID,
+ self.model.search(self.cr, openerp.SUPERUSER_ID, domain, context=context),
+ fields=fields, context=context)
+ def browse(self, domain=(), context=None):
+ return self.model.browse(
+ self.cr, openerp.SUPERUSER_ID,
+ self.model.search(self.cr, openerp.SUPERUSER_ID, domain, context=context),
+ context=context)
+
+ def xid(self, record):
+ ModelData = self.registry('ir.model.data')
+
+ ids = ModelData.search(
+ self.cr, openerp.SUPERUSER_ID,
+ [('model', '=', record._table_name), ('res_id', '=', record.id)])
+ if ids:
+ d = ModelData.read(
+ self.cr, openerp.SUPERUSER_ID, ids, ['name', 'module'])[0]
+ if d['module']:
+ return '%s.%s' % (d['module'], d['name'])
+ return d['name']
+
+ name = dict(record.name_get())[record.id]
+ # fix dotted name_get results, otherwise xid lookups blow up
+ name = name.replace('.', '-')
+ ModelData.create(self.cr, openerp.SUPERUSER_ID, {
+ 'name': name,
+ 'model': record._table_name,
+ 'res_id': record.id,
+ 'module': '__test__'
+ })
+ return '__test__.' + name
+
+class test_ids_stuff(ImporterCase):
+ model_name = 'export.integer'
+
+ def test_create_with_id(self):
+ ids, messages = self.import_(['.id', 'value'], [['42', '36']])
+ self.assertIs(ids, False)
+ self.assertEqual(messages, [{
+ 'type': 'error',
+ 'rows': {'from': 0, 'to': 0},
+ 'record': 0,
+ 'field': '.id',
+ 'message': u"Unknown database identifier '42'",
+ }])
+ def test_create_with_xid(self):
+ ids, messages = self.import_(['id', 'value'], [['somexmlid', '42']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+ self.assertEqual(
+ 'somexmlid',
+ self.xid(self.browse()[0]))
+
+ def test_update_with_id(self):
+ id = self.model.create(self.cr, openerp.SUPERUSER_ID, {'value': 36})
+ self.assertEqual(
+ 36,
+ self.model.browse(self.cr, openerp.SUPERUSER_ID, id).value)
+
+ ids, messages = self.import_(['.id', 'value'], [[str(id), '42']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+ self.assertEqual(
+ [42], # updated value to imported
+ values(self.read()))
+
+ def test_update_with_xid(self):
+ self.import_(['id', 'value'], [['somexmlid', '36']])
+ self.assertEqual([36], values(self.read()))
+
+ self.import_(['id', 'value'], [['somexmlid', '1234567']])
+ self.assertEqual([1234567], values(self.read()))
+
+class test_boolean_field(ImporterCase):
+ model_name = 'export.boolean'
+
+ def test_empty(self):
+ self.assertEqual(
+ self.import_(['value'], []),
+ ([], []))
+
+ def test_exported(self):
+ ids, messages = self.import_(['value'], [['False'], ['True'], ])
+ self.assertEqual(len(ids), 2)
+ self.assertFalse(messages)
+ records = self.read()
+ self.assertEqual([
+ False,
+ True,
+ ], values(records))
+
+ def test_falses(self):
+ ids, messages = self.import_(
+ ['value'],
+ [[u'0'], [u'off'],
+ [u'false'], [u'FALSE'],
+ [u'OFF'], [u''],
+ ])
+ self.assertEqual(len(ids), 6)
+ self.assertFalse(messages)
+ self.assertEqual([
+ False,
+ False,
+ False,
+ False,
+ False,
+ False,
+ ],
+ values(self.read()))
+
+ def test_trues(self):
+ ids, messages = self.import_(
+ ['value'],
+ [['no'],
+ ['None'],
+ ['nil'],
+ ['()'],
+ ['f'],
+ ['#f'],
+ # Problem: OpenOffice (and probably excel) output localized booleans
+ ['VRAI'],
+ ])
+ self.assertEqual(len(ids), 7)
+ # FIXME: should warn for values which are not "true", "yes" or "1"
+ self.assertFalse(messages)
+ self.assertEqual(
+ [True] * 7,
+ values(self.read()))
+
+class test_integer_field(ImporterCase):
+ model_name = 'export.integer'
+
+ def test_none(self):
+ self.assertEqual(
+ self.import_(['value'], []),
+ ([], []))
+
+ def test_empty(self):
+ ids, messages = self.import_(['value'], [['']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+ self.assertEqual(
+ [False],
+ values(self.read()))
+
+ def test_zero(self):
+ ids, messages = self.import_(['value'], [['0']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+
+ ids, messages = self.import_(['value'], [['-0']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+
+ self.assertEqual([False, False], values(self.read()))
+
+ def test_positives(self):
+ ids, messages = self.import_(['value'], [
+ ['1'],
+ ['42'],
+ [str(2**31-1)],
+ ['12345678']
+ ])
+ self.assertEqual(len(ids), 4)
+ self.assertFalse(messages)
+
+ self.assertEqual([
+ 1, 42, 2**31-1, 12345678
+ ], values(self.read()))
+
+ def test_negatives(self):
+ ids, messages = self.import_(['value'], [
+ ['-1'],
+ ['-42'],
+ [str(-(2**31 - 1))],
+ [str(-(2**31))],
+ ['-12345678']
+ ])
+ self.assertEqual(len(ids), 5)
+ self.assertFalse(messages)
+ self.assertEqual([
+ -1, -42, -(2**31 - 1), -(2**31), -12345678
+ ], values(self.read()))
+
+ @mute_logger('openerp.sql_db')
+ def test_out_of_range(self):
+ ids, messages = self.import_(['value'], [[str(2**31)]])
+ self.assertIs(ids, False)
+ self.assertEqual(messages, [{
+ 'type': 'error',
+ 'rows': {'from': 0, 'to': 0},
+ 'record': 0,
+ 'message': "integer out of range\n"
+ }])
+
+ ids, messages = self.import_(['value'], [[str(-2**32)]])
+ self.assertIs(ids, False)
+ self.assertEqual(messages, [{
+ 'type': 'error',
+ 'rows': {'from': 0, 'to': 0},
+ 'record': 0,
+ 'message': "integer out of range\n"
+ }])
+
+ def test_nonsense(self):
+ ids, messages = self.import_(['value'], [['zorglub']])
+ self.assertIs(ids, False)
+ self.assertEqual(messages, [{
+ 'type': 'error',
+ 'rows': {'from': 0, 'to': 0},
+ 'record': 0,
+ 'field': 'value',
+ 'message': u"invalid literal for int() with base 10: 'zorglub'",
+ }])
+
+class test_float_field(ImporterCase):
+ model_name = 'export.float'
+ def test_none(self):
+ self.assertEqual(
+ self.import_(['value'], []),
+ ([], []))
+
+ def test_empty(self):
+ ids, messages = self.import_(['value'], [['']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+ self.assertEqual(
+ [False],
+ values(self.read()))
+
+ def test_zero(self):
+ ids, messages = self.import_(['value'], [['0']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+
+ ids, messages = self.import_(['value'], [['-0']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+
+ self.assertEqual([False, False], values(self.read()))
+
+ def test_positives(self):
+ ids, messages = self.import_(['value'], [
+ ['1'],
+ ['42'],
+ [str(2**31-1)],
+ ['12345678'],
+ [str(2**33)],
+ ['0.000001'],
+ ])
+ self.assertEqual(len(ids), 6)
+ self.assertFalse(messages)
+
+ self.assertEqual([
+ 1, 42, 2**31-1, 12345678, 2.0**33, .000001
+ ], values(self.read()))
+
+ def test_negatives(self):
+ ids, messages = self.import_(['value'], [
+ ['-1'],
+ ['-42'],
+ [str(-2**31 + 1)],
+ [str(-2**31)],
+ ['-12345678'],
+ [str(-2**33)],
+ ['-0.000001'],
+ ])
+ self.assertEqual(len(ids), 7)
+ self.assertFalse(messages)
+ self.assertEqual([
+ -1, -42, -(2**31 - 1), -(2**31), -12345678, -2.0**33, -.000001
+ ], values(self.read()))
+
+ def test_nonsense(self):
+ ids, messages = self.import_(['value'], [['foobar']])
+ self.assertIs(ids, False)
+ self.assertEqual(messages, [{
+ 'type': 'error',
+ 'rows': {'from': 0, 'to': 0},
+ 'record': 0,
+ 'field': 'value',
+ 'message': u"invalid literal for float(): foobar",
+ }])
+
+class test_string_field(ImporterCase):
+ model_name = 'export.string.bounded'
+
+ def test_empty(self):
+ ids, messages = self.import_(['value'], [['']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+ self.assertEqual([False], values(self.read()))
+
+ def test_imported(self):
+ ids, messages = self.import_(['value'], [
+ [u'foobar'],
+ [u'foobarbaz'],
+ [u'Með suð í eyrum við spilum endalaust'],
+ [u"People 'get' types. They use them all the time. Telling "
+ u"someone he can't pound a nail with a banana doesn't much "
+ u"surprise him."]
+ ])
+ self.assertEqual(len(ids), 4)
+ self.assertFalse(messages)
+ self.assertEqual([
+ u"foobar",
+ u"foobarbaz",
+ u"Með suð í eyrum ",
+ u"People 'get' typ",
+ ], values(self.read()))
+
+class test_unbound_string_field(ImporterCase):
+ model_name = 'export.string'
+
+ def test_imported(self):
+ ids, messages = self.import_(['value'], [
+ [u'í dag viðrar vel til loftárása'],
+ # ackbar.jpg
+ [u"If they ask you about fun, you tell them – fun is a filthy"
+ u" parasite"]
+ ])
+ self.assertEqual(len(ids), 2)
+ self.assertFalse(messages)
+ self.assertEqual([
+ u"í dag viðrar vel til loftárása",
+ u"If they ask you about fun, you tell them – fun is a filthy parasite"
+ ], values(self.read()))
+
+class test_text(ImporterCase):
+ model_name = 'export.text'
+
+ def test_empty(self):
+ ids, messages = self.import_(['value'], [['']])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+ self.assertEqual([False], values(self.read()))
+
+ def test_imported(self):
+ s = (u"Breiðskífa er notað um útgefna hljómplötu sem inniheldur "
+ u"stúdíóupptökur frá einum flytjanda. Breiðskífur eru oftast "
+ u"milli 25-80 mínútur og er lengd þeirra oft miðuð við 33⅓ "
+ u"snúninga 12 tommu vínylplötur (sem geta verið allt að 30 mín "
+ u"hvor hlið).\n\nBreiðskífur eru stundum tvöfaldar og eru þær þá"
+ u" gefnar út á tveimur geisladiskum eða tveimur vínylplötum.")
+ ids, messages = self.import_(['value'], [[s]])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+ self.assertEqual([s], values(self.read()))
+
+class test_selection(ImporterCase):
+ model_name = 'export.selection'
+ translations_fr = [
+ ("Qux", "toto"),
+ ("Bar", "titi"),
+ ("Foo", "tete"),
+ ]
+
+ def test_imported(self):
+ ids, messages = self.import_(['value'], [
+ ['Qux'],
+ ['Bar'],
+ ['Foo'],
+ ['2'],
+ ])
+ self.assertEqual(len(ids), 4)
+ self.assertFalse(messages)
+ self.assertEqual([3, 2, 1, 2], values(self.read()))
+
+ def test_imported_translated(self):
+ self.registry('res.lang').create(self.cr, openerp.SUPERUSER_ID, {
+ 'name': u'Français',
+ 'code': 'fr_FR',
+ 'translatable': True,
+ 'date_format': '%d.%m.%Y',
+ 'decimal_point': ',',
+ 'thousand_sep': ' ',
+ })
+ Translations = self.registry('ir.translation')
+ for source, value in self.translations_fr:
+ Translations.create(self.cr, openerp.SUPERUSER_ID, {
+ 'name': 'export.selection,value',
+ 'lang': 'fr_FR',
+ 'type': 'selection',
+ 'src': source,
+ 'value': value
+ })
+
+ ids, messages = self.import_(['value'], [
+ ['toto'],
+ ['tete'],
+ ['titi'],
+ ], context={'lang': 'fr_FR'})
+ self.assertEqual(len(ids), 3)
+ self.assertFalse(messages)
+
+ self.assertEqual([3, 1, 2], values(self.read()))
+
+ ids, messages = self.import_(['value'], [['Foo']], context={'lang': 'fr_FR'})
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+
+ def test_invalid(self):
+ ids, messages = self.import_(['value'], [['Baz']])
+ self.assertIs(ids, False)
+ self.assertEqual(messages, [{
+ 'type': 'error',
+ 'rows': {'from': 0, 'to': 0},
+ 'record': 0,
+ 'field': 'value',
+ 'message': "Value 'Baz' not found in selection field 'value'",
+ }])
+
+ ids, messages = self.import_(['value'], [[42]])
+ self.assertIs(ids, False)
+ self.assertEqual(messages, [{
+ 'type': 'error',
+ 'rows': {'from': 0, 'to': 0},
+ 'record': 0,
+ 'field': 'value',
+ 'message': "Value '42' not found in selection field 'value'",
+ }])
+
+class test_selection_function(ImporterCase):
+ model_name = 'export.selection.function'
+ translations_fr = [
+ ("Corge", "toto"),
+ ("Grault", "titi"),
+ ("Whee", "tete"),
+ ("Moog", "tutu"),
+ ]
+
+ def test_imported(self):
+ """ import uses fields_get, so translates import label (may or may not
+ be good news) *and* serializes the selection function to reverse it:
+ import does not actually know that the selection field uses a function
+ """
+ # NOTE: conflict between a value and a label => ?
+ ids, messages = self.import_(['value'], [
+ ['3'],
+ ["Grault"],
+ ])
+ self.assertEqual(len(ids), 2)
+ self.assertFalse(messages)
+ self.assertEqual(
+ ['3', '1'],
+ values(self.read()))
+
+ def test_translated(self):
+ """ Expects output of selection function returns translated labels
+ """
+ self.registry('res.lang').create(self.cr, openerp.SUPERUSER_ID, {
+ 'name': u'Français',
+ 'code': 'fr_FR',
+ 'translatable': True,
+ 'date_format': '%d.%m.%Y',
+ 'decimal_point': ',',
+ 'thousand_sep': ' ',
+ })
+ Translations = self.registry('ir.translation')
+ for source, value in self.translations_fr:
+ Translations.create(self.cr, openerp.SUPERUSER_ID, {
+ 'name': 'export.selection,value',
+ 'lang': 'fr_FR',
+ 'type': 'selection',
+ 'src': source,
+ 'value': value
+ })
+ ids, messages = self.import_(['value'], [
+ ['toto'],
+ ['tete'],
+ ], context={'lang': 'fr_FR'})
+ self.assertIs(ids, False)
+ self.assertEqual(messages, [{
+ 'type': 'error',
+ 'rows': {'from': 1, 'to': 1},
+ 'record': 1,
+ 'field': 'value',
+ 'message': "Value 'tete' not found in selection field 'value'",
+ }])
+ ids, messages = self.import_(['value'], [['Wheee']], context={'lang': 'fr_FR'})
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+
+class test_m2o(ImporterCase):
+ model_name = 'export.many2one'
+
+ def test_by_name(self):
+ # create integer objects
+ integer_id1 = self.registry('export.integer').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 42})
+ integer_id2 = self.registry('export.integer').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 36})
+ # get its name
+ name1 = dict(self.registry('export.integer').name_get(
+ self.cr, openerp.SUPERUSER_ID,[integer_id1]))[integer_id1]
+ name2 = dict(self.registry('export.integer').name_get(
+ self.cr, openerp.SUPERUSER_ID,[integer_id2]))[integer_id2]
+
+ ids , messages = self.import_(['value'], [
+ # import by name_get
+ [name1],
+ [name1],
+ [name2],
+ ])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 3)
+ # correct ids assigned to corresponding records
+ self.assertEqual([
+ (integer_id1, name1),
+ (integer_id1, name1),
+ (integer_id2, name2),],
+ values(self.read()))
+
+ def test_by_xid(self):
+ ExportInteger = self.registry('export.integer')
+ integer_id = ExportInteger.create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 42})
+ xid = self.xid(ExportInteger.browse(
+ self.cr, openerp.SUPERUSER_ID, [integer_id])[0])
+
+ ids, messages = self.import_(['value/id'], [[xid]])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
+ b = self.browse()
+ self.assertEqual(42, b[0].value.value)
+
+ def test_by_id(self):
+ integer_id = self.registry('export.integer').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 42})
+ ids, messages = self.import_(['value/.id'], [[integer_id]])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
+ b = self.browse()
+ self.assertEqual(42, b[0].value.value)
+
+ def test_by_names(self):
+ integer_id1 = self.registry('export.integer').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 42})
+ integer_id2 = self.registry('export.integer').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 42})
+ name1 = dict(self.registry('export.integer').name_get(
+ self.cr, openerp.SUPERUSER_ID,[integer_id1]))[integer_id1]
+ name2 = dict(self.registry('export.integer').name_get(
+ self.cr, openerp.SUPERUSER_ID,[integer_id2]))[integer_id2]
+ # names should be the same
+ self.assertEqual(name1, name2)
+
+ ids, messages = self.import_(['value'], [[name2]])
+ self.assertEqual(
+ messages,
+ [message(u"Found multiple matches for field 'value' (2 matches)",
+ type='warning')])
+ self.assertEqual(len(ids), 1)
+ self.assertEqual([
+ (integer_id1, name1)
+ ], values(self.read()))
+
+ def test_fail_by_implicit_id(self):
+ """ Can't implicitly import records by id
+ """
+ # create integer objects
+ integer_id1 = self.registry('export.integer').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 42})
+ integer_id2 = self.registry('export.integer').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 36})
+
+ # Because name_search all the things. Fallback schmallback
+ ids, messages = self.import_(['value'], [
+ # import by id, without specifying it
+ [integer_id1],
+ [integer_id2],
+ [integer_id1],
+ ])
+ self.assertEqual(messages, [
+ message(u"No matching record found for name '%s' in field 'value'" % id,
+ from_=index, to_=index, record=index)
+ for index, id in enumerate([integer_id1, integer_id2, integer_id1])])
+ self.assertIs(ids, False)
+
+ def test_sub_field(self):
+ """ Does not implicitly create the record, does not warn that you can't
+ import m2o subfields (at all)...
+ """
+ ids, messages = self.import_(['value/value'], [['42']])
+ self.assertEqual(messages, [
+ message(u"Can not create Many-To-One records indirectly, import "
+ u"the field separately")])
+ self.assertIs(ids, False)
+
+ def test_fail_noids(self):
+ ids, messages = self.import_(['value'], [['nameisnoexist:3']])
+ self.assertEqual(messages, [message(
+ u"No matching record found for name 'nameisnoexist:3' "
+ u"in field 'value'")])
+ self.assertIs(ids, False)
+
+ ids, messages = self.import_(['value/id'], [['noxidhere']])
+ self.assertEqual(messages, [message(
+ u"No matching record found for external id 'noxidhere' "
+ u"in field 'value'")])
+ self.assertIs(ids, False)
+
+ ids, messages = self.import_(['value/.id'], [['66']])
+ self.assertEqual(messages, [message(
+ u"No matching record found for database id '66' "
+ u"in field 'value'")])
+ self.assertIs(ids, False)
+
+ def test_fail_multiple(self):
+ ids, messages = self.import_(
+ ['value', 'value/id'],
+ [['somename', 'somexid']])
+ self.assertEqual(messages, [message(
+ u"Ambiguous specification for field 'value', only provide one of "
+ u"name, external id or database id")])
+ self.assertIs(ids, False)
+
+class test_m2m(ImporterCase):
+ model_name = 'export.many2many'
+
+ # apparently, one and only thing which works is a
+ # csv_internal_sep-separated list of ids, xids, or names (depending if
+ # m2m/.id, m2m/id or m2m[/anythingelse]
+ def test_ids(self):
+ id1 = self.registry('export.many2many.other').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 3, 'str': 'record0'})
+ id2 = self.registry('export.many2many.other').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 44, 'str': 'record1'})
+ id3 = self.registry('export.many2many.other').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 84, 'str': 'record2'})
+ id4 = self.registry('export.many2many.other').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
+ id5 = self.registry('export.many2many.other').create(
+ self.cr, openerp.SUPERUSER_ID, {'value': 99, 'str': 'record4'})
+
+ ids, messages = self.import_(['value/.id'], [
+ ['%d,%d' % (id1, id2)],
+ ['%d,%d,%d' % (id1, id3, id4)],
+ ['%d,%d,%d' % (id1, id2, id3)],
+ ['%d' % id5]
+ ])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 4)
+
+ ids = lambda records: [record.id for record in records]
+
+ b = self.browse()
+ self.assertEqual(ids(b[0].value), [id1, id2])
+ self.assertEqual(values(b[0].value), [3, 44])
+
+ self.assertEqual(ids(b[2].value), [id1, id2, id3])
+ self.assertEqual(values(b[2].value), [3, 44, 84])
+
+ def test_noids(self):
+ ids, messages = self.import_(['value/.id'], [['42']])
+ self.assertEqual(messages, [message(
+ u"No matching record found for database id '42' in field "
+ u"'value'")])
+ self.assertIs(ids, False)
+
+ def test_xids(self):
+ M2O_o = self.registry('export.many2many.other')
+ id1 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 3, 'str': 'record0'})
+ id2 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 44, 'str': 'record1'})
+ id3 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 84, 'str': 'record2'})
+ id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
+ records = M2O_o.browse(self.cr, openerp.SUPERUSER_ID, [id1, id2, id3, id4])
+
+ ids, messages = self.import_(['value/id'], [
+ ['%s,%s' % (self.xid(records[0]), self.xid(records[1]))],
+ ['%s' % self.xid(records[3])],
+ ['%s,%s' % (self.xid(records[2]), self.xid(records[1]))],
+ ])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 3)
+
+ b = self.browse()
+ self.assertEqual(values(b[0].value), [3, 44])
+ self.assertEqual(values(b[2].value), [44, 84])
+ def test_noxids(self):
+ ids, messages = self.import_(['value/id'], [['noxidforthat']])
+ self.assertEqual(messages, [message(
+ u"No matching record found for external id 'noxidforthat' "
+ u"in field 'value'")])
+ self.assertIs(ids, False)
+
+ def test_names(self):
+ M2O_o = self.registry('export.many2many.other')
+ id1 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 3, 'str': 'record0'})
+ id2 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 44, 'str': 'record1'})
+ id3 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 84, 'str': 'record2'})
+ id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
+ records = M2O_o.browse(self.cr, openerp.SUPERUSER_ID, [id1, id2, id3, id4])
+
+ name = lambda record: dict(record.name_get())[record.id]
+
+ ids, messages = self.import_(['value'], [
+ ['%s,%s' % (name(records[1]), name(records[2]))],
+ ['%s,%s,%s' % (name(records[0]), name(records[1]), name(records[2]))],
+ ['%s,%s' % (name(records[0]), name(records[3]))],
+ ])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 3)
+
+ b = self.browse()
+ self.assertEqual(values(b[1].value), [3, 44, 84])
+ self.assertEqual(values(b[2].value), [3, 9])
+
+ def test_nonames(self):
+ ids, messages = self.import_(['value'], [['wherethem2mhavenonames']])
+ self.assertEqual(messages, [message(
+ u"No matching record found for name 'wherethem2mhavenonames' in "
+ u"field 'value'")])
+ self.assertIs(ids, False)
+
+ def test_import_to_existing(self):
+ M2O_o = self.registry('export.many2many.other')
+ id1 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 3, 'str': 'record0'})
+ id2 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 44, 'str': 'record1'})
+ id3 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 84, 'str': 'record2'})
+ id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
+
+ xid = 'myxid'
+ ids, messages = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id1, id2)]])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
+ ids, messages = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id3, id4)]])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
+
+ b = self.browse()
+ self.assertEqual(len(b), 1)
+ # TODO: replacement of existing m2m values is correct?
+ self.assertEqual(values(b[0].value), [84, 9])
+
+class test_o2m(ImporterCase):
+ model_name = 'export.one2many'
+
+ def test_name_get(self):
+ # FIXME: bloody hell why can't this just name_create the record?
+ self.assertRaises(
+ IndexError,
+ self.import_,
+ ['const', 'value'],
+ [['5', u'Java is a DSL for taking large XML files'
+ u' and converting them to stack traces']])
+
+ def test_single(self):
+ ids, messages = self.import_(['const', 'value/value'], [
+ ['5', '63']
+ ])
+ self.assertEqual(len(ids), 1)
+ self.assertFalse(messages)
+
+ (b,) = self.browse()
+ self.assertEqual(b.const, 5)
+ self.assertEqual(values(b.value), [63])
+
+ def test_multicore(self):
+ ids, messages = self.import_(['const', 'value/value'], [
+ ['5', '63'],
+ ['6', '64'],
+ ])
+ self.assertEqual(len(ids), 2)
+ self.assertFalse(messages)
+
+ b1, b2 = self.browse()
+ self.assertEqual(b1.const, 5)
+ self.assertEqual(values(b1.value), [63])
+ self.assertEqual(b2.const, 6)
+ self.assertEqual(values(b2.value), [64])
+
+ def test_multisub(self):
+ ids, messages = self.import_(['const', 'value/value'], [
+ ['5', '63'],
+ ['', '64'],
+ ['', '65'],
+ ['', '66'],
+ ])
+ self.assertEqual(len(ids), 4)
+ self.assertFalse(messages)
+
+ (b,) = self.browse()
+ self.assertEqual(values(b.value), [63, 64, 65, 66])
+
+ def test_multi_subfields(self):
+ ids, messages = self.import_(['value/str', 'const', 'value/value'], [
+ ['this', '5', '63'],
+ ['is', '', '64'],
+ ['the', '', '65'],
+ ['rhythm', '', '66'],
+ ])
+ self.assertEqual(len(ids), 4)
+ self.assertFalse(messages)
+
+ (b,) = self.browse()
+ self.assertEqual(values(b.value), [63, 64, 65, 66])
+ self.assertEqual(
+ values(b.value, 'str'),
+ 'this is the rhythm'.split())
+
+ def test_link_inline(self):
+ id1 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
+ 'str': 'Bf', 'value': 109
+ })
+ id2 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
+ 'str': 'Me', 'value': 262
+ })
+
+ try:
+ self.import_(['const', 'value/.id'], [
+ ['42', '%d,%d' % (id1, id2)]
+ ])
+ self.fail("Should have raised a valueerror")
+ except ValueError, e:
+ # should be Exception(Database ID doesn't exist: export.one2many.child : $id1,$id2)
+ self.assertIs(type(e), ValueError)
+ self.assertEqual(
+ e.args[0],
+ "invalid literal for int() with base 10: '%d,%d'" % (id1, id2))
+
+ def test_link(self):
+ id1 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
+ 'str': 'Bf', 'value': 109
+ })
+ id2 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
+ 'str': 'Me', 'value': 262
+ })
+
+ ids, messages = self.import_(['const', 'value/.id'], [
+ ['42', str(id1)],
+ ['', str(id2)],
+ ])
+ self.assertEqual(len(ids), 2)
+ self.assertFalse(messages)
+
+ # No record values alongside id => o2m resolution skipped altogether,
+ # creates 2 records => remove/don't import columns sideshow columns,
+ # get completely different semantics
+ b, b1 = self.browse()
+ self.assertEqual(b.const, 42)
+ self.assertEqual(values(b.value), [])
+ self.assertEqual(b1.const, 4)
+ self.assertEqual(values(b1.value), [])
+
+ def test_link_2(self):
+ O2M_c = self.registry('export.one2many.child')
+ id1 = O2M_c.create(self.cr, openerp.SUPERUSER_ID, {
+ 'str': 'Bf', 'value': 109
+ })
+ id2 = O2M_c.create(self.cr, openerp.SUPERUSER_ID, {
+ 'str': 'Me', 'value': 262
+ })
+
+ ids, messages = self.import_(['const', 'value/.id', 'value/value'], [
+ ['42', str(id1), '1'],
+ ['', str(id2), '2'],
+ ])
+ self.assertEqual(len(ids), 2)
+ self.assertFalse(messages)
+
+ (b,) = self.browse()
+ # if an id (db or xid) is provided, expectations that objects are
+ # *already* linked and emits UPDATE (1, id, {}).
+ # Noid => CREATE (0, ?, {})
+ # TODO: xid ignored aside from getting corresponding db id?
+ self.assertEqual(b.const, 42)
+ self.assertEqual(values(b.value), [])
+
+ # FIXME: updates somebody else's records?
+ self.assertEqual(
+ O2M_c.read(self.cr, openerp.SUPERUSER_ID, id1),
+ {'id': id1, 'str': 'Bf', 'value': 1, 'parent_id': False})
+ self.assertEqual(
+ O2M_c.read(self.cr, openerp.SUPERUSER_ID, id2),
+ {'id': id2, 'str': 'Me', 'value': 2, 'parent_id': False})
+
+class test_o2m_multiple(ImporterCase):
+ model_name = 'export.one2many.multiple'
+
+ def test_multi_mixed(self):
+ ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
+ ['5', '11', '21'],
+ ['', '12', '22'],
+ ['', '13', '23'],
+ ['', '14', ''],
+ ])
+ self.assertEqual(len(ids), 4)
+ self.assertFalse(messages)
+ # Oh yeah, that's the stuff
+ (b, b1, b2) = self.browse()
+ self.assertEqual(values(b.child1), [11])
+ self.assertEqual(values(b.child2), [21])
+
+ self.assertEqual(values(b1.child1), [12])
+ self.assertEqual(values(b1.child2), [22])
+
+ self.assertEqual(values(b2.child1), [13, 14])
+ self.assertEqual(values(b2.child2), [23])
+
+ def test_multi(self):
+ ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
+ ['5', '11', '21'],
+ ['', '12', ''],
+ ['', '13', ''],
+ ['', '14', ''],
+ ['', '', '22'],
+ ['', '', '23'],
+ ])
+ self.assertEqual(len(ids), 6)
+ self.assertFalse(messages)
+ # What the actual fuck?
+ (b, b1) = self.browse()
+ self.assertEqual(values(b.child1), [11, 12, 13, 14])
+ self.assertEqual(values(b.child2), [21])
+ self.assertEqual(values(b1.child2), [22, 23])
+
+ def test_multi_fullsplit(self):
+ ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
+ ['5', '11', ''],
+ ['', '12', ''],
+ ['', '13', ''],
+ ['', '14', ''],
+ ['', '', '21'],
+ ['', '', '22'],
+ ['', '', '23'],
+ ])
+ self.assertEqual(len(ids), 7)
+ self.assertFalse(messages)
+ # oh wow
+ (b, b1) = self.browse()
+ self.assertEqual(b.const, 5)
+ self.assertEqual(values(b.child1), [11, 12, 13, 14])
+ self.assertEqual(b1.const, 36)
+ self.assertEqual(values(b1.child2), [21, 22, 23])
+
+# function, related, reference: written to db as-is...
+# => function uses @type for value coercion/conversion
diff --git a/openerp/tests/test_misc.py b/openerp/tests/test_misc.py
index 7661f253b17..54ae69899a6 100644
--- a/openerp/tests/test_misc.py
+++ b/openerp/tests/test_misc.py
@@ -2,12 +2,12 @@
# > PYTHONPATH=. python2 openerp/tests/test_misc.py
import unittest2
+from ..tools import misc
-class test_misc(unittest2.TestCase):
+class append_content_to_html(unittest2.TestCase):
""" Test some of our generic utility functions """
def test_append_to_html(self):
- from openerp.tools import append_content_to_html
test_samples = [
('some content ', '--\nYours truly', True,
'some content \n--\nYours truly \n'),
@@ -15,7 +15,37 @@ class test_misc(unittest2.TestCase):
'some content \n\n\n--
\nYours truly
\n\n\n'),
]
for html, content, flag, expected in test_samples:
- self.assertEqual(append_content_to_html(html,content,flag), expected, 'append_content_to_html is broken')
+ self.assertEqual(misc.append_content_to_html(html,content,flag), expected, 'append_content_to_html is broken')
+
+class test_countingstream(unittest2.TestCase):
+ def test_empty_stream(self):
+ s = misc.CountingStream(iter([]))
+ self.assertEqual(s.index, -1)
+ self.assertIsNone(next(s, None))
+ self.assertEqual(s.index, 0)
+
+ def test_single(self):
+ s = misc.CountingStream(xrange(1))
+ self.assertEqual(s.index, -1)
+ self.assertEqual(next(s, None), 0)
+ self.assertIsNone(next(s, None))
+ self.assertEqual(s.index, 1)
+
+ def test_full(self):
+ s = misc.CountingStream(xrange(42))
+ for _ in s:
+ pass
+ self.assertEqual(s.index, 42)
+
+ def test_repeated(self):
+ """ Once the CountingStream has stopped iterating, the index should not
+ increase anymore (the internal state should not be allowed to change)
+ """
+ s = misc.CountingStream(iter([]))
+ self.assertIsNone(next(s, None))
+ self.assertEqual(s.index, 0)
+ self.assertIsNone(next(s, None))
+ self.assertEqual(s.index, 0)
if __name__ == '__main__':
- unittest2.main()
\ No newline at end of file
+ unittest2.main()
diff --git a/openerp/tools/misc.py b/openerp/tools/misc.py
index 9a7b3499425..1ee3caf98d9 100644
--- a/openerp/tools/misc.py
+++ b/openerp/tools/misc.py
@@ -1220,4 +1220,38 @@ class mute_logger(object):
with self:
return func(*args, **kwargs)
return deco
+
+_ph = object()
+class CountingStream(object):
+ """ Stream wrapper counting the number of element it has yielded. Similar
+ role to ``enumerate``, but for use when the iteration process of the stream
+ isn't fully under caller control (the stream can be iterated from multiple
+ points including within a library)
+
+ ``start`` allows overriding the starting index (the index before the first
+ item is returned).
+
+ On each iteration (call to :meth:`~.next`), increases its :attr:`~.index`
+ by one.
+
+ .. attribute:: index
+
+ ``int``, index of the last yielded element in the stream. If the stream
+ has ended, will give an index 1-past the stream
+ """
+ def __init__(self, stream, start=-1):
+ self.stream = iter(stream)
+ self.index = start
+ self.stopped = False
+ def __iter__(self):
+ return self
+ def next(self):
+ if self.stopped: raise StopIteration()
+ self.index += 1
+ val = next(self.stream, _ph)
+ if val is _ph:
+ self.stopped = True
+ raise StopIteration()
+ return val
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/setup.py b/setup.py
index a26b74e255d..4451bc1b710 100755
--- a/setup.py
+++ b/setup.py
@@ -116,6 +116,7 @@ setuptools.setup(
extras_require = {
'SSL' : ['pyopenssl'],
},
+ tests_require = ['unittest2'],
**py2exe_options()
)
From c9e0cfd64aa064df9a2544597bf77579ac4e08da Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Thu, 20 Sep 2012 12:25:45 +0200
Subject: [PATCH 004/171] [ADD] force linking to existing o2m being updated
bzr revid: xmo@openerp.com-20120920102545-30tkodb4s1dng5hp
---
openerp/addons/base/ir/ir_fields.py | 34 ++++++++++++++--
.../addons/test_impex/tests/test_load.py | 39 +++++++------------
2 files changed, 45 insertions(+), 28 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index f73067c9f6c..6b3898f3fdd 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -5,6 +5,22 @@ import warnings
from openerp.osv import orm, fields
from openerp.tools.translate import _
+REFERENCING_FIELDS = set([None, 'id', '.id'])
+def only_ref_fields(record):
+ return dict((k, v) for k, v in record.iteritems()
+ if k in REFERENCING_FIELDS)
+def exclude_ref_fields(record):
+ return dict((k, v) for k, v in record.iteritems()
+ if k not in REFERENCING_FIELDS)
+
+CREATE = lambda values: (0, False, values)
+UPDATE = lambda id, values: (1, id, values)
+DELETE = lambda id: (2, id, False)
+FORGET = lambda id: (3, id, False)
+LINK_TO = lambda id: (4, id, False)
+DELETE_ALL = lambda: (5, False, False)
+REPLACE_WITH = lambda ids: (6, False, ids)
+
class ConversionNotFound(ValueError): pass
class ir_fields_converter(orm.Model):
@@ -145,9 +161,8 @@ class ir_fields_converter(orm.Model):
:rtype: str
"""
# Can import by name_get, external id or database id
- allowed_fields = set([None, 'id', '.id'])
fieldset = set(record.iterkeys())
- if fieldset - allowed_fields:
+ if fieldset - REFERENCING_FIELDS:
raise ValueError(
_(u"Can not create Many-To-One records indirectly, import the field separately"))
if len(fieldset) > 1:
@@ -190,4 +205,17 @@ class ir_fields_converter(orm.Model):
return [(6, 0, ids)]
def _str_to_one2many(self, cr, uid, model, column, value, context=None):
- return value
+ commands = []
+ for subfield, record in zip((self._referencing_subfield(
+ only_ref_fields(record))
+ for record in value),
+ value):
+ id, subfield_type = self.db_id_for(
+ cr, uid, model, column, subfield, record[subfield], context=context)
+ writable = exclude_ref_fields(record)
+ if id:
+ commands.append(LINK_TO(id))
+ commands.append(UPDATE(id, writable))
+ else:
+ commands.append(CREATE(writable))
+ return commands
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index 80e5cfe9c8f..44b6c1a56df 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -869,10 +869,13 @@ class test_o2m(ImporterCase):
"invalid literal for int() with base 10: '%d,%d'" % (id1, id2))
def test_link(self):
- id1 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
+ """ O2M relating to an existing record (update) force a LINK_TO as well
+ """
+ O2M = self.registry('export.one2many.child')
+ id1 = O2M.create(self.cr, openerp.SUPERUSER_ID, {
'str': 'Bf', 'value': 109
})
- id2 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
+ id2 = O2M.create(self.cr, openerp.SUPERUSER_ID, {
'str': 'Me', 'value': 262
})
@@ -880,17 +883,14 @@ class test_o2m(ImporterCase):
['42', str(id1)],
['', str(id2)],
])
- self.assertEqual(len(ids), 2)
self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
- # No record values alongside id => o2m resolution skipped altogether,
- # creates 2 records => remove/don't import columns sideshow columns,
- # get completely different semantics
- b, b1 = self.browse()
+ [b] = self.browse()
self.assertEqual(b.const, 42)
- self.assertEqual(values(b.value), [])
- self.assertEqual(b1.const, 4)
- self.assertEqual(values(b1.value), [])
+ # automatically forces link between core record and o2ms
+ self.assertEqual(values(b.value), [109, 262])
+ self.assertEqual(values(b.value, field='parent_id'), [b, b])
def test_link_2(self):
O2M_c = self.registry('export.one2many.child')
@@ -905,24 +905,13 @@ class test_o2m(ImporterCase):
['42', str(id1), '1'],
['', str(id2), '2'],
])
- self.assertEqual(len(ids), 2)
self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
- (b,) = self.browse()
- # if an id (db or xid) is provided, expectations that objects are
- # *already* linked and emits UPDATE (1, id, {}).
- # Noid => CREATE (0, ?, {})
- # TODO: xid ignored aside from getting corresponding db id?
+ [b] = self.browse()
self.assertEqual(b.const, 42)
- self.assertEqual(values(b.value), [])
-
- # FIXME: updates somebody else's records?
- self.assertEqual(
- O2M_c.read(self.cr, openerp.SUPERUSER_ID, id1),
- {'id': id1, 'str': 'Bf', 'value': 1, 'parent_id': False})
- self.assertEqual(
- O2M_c.read(self.cr, openerp.SUPERUSER_ID, id2),
- {'id': id2, 'str': 'Me', 'value': 2, 'parent_id': False})
+ self.assertEqual(values(b.value), [1, 2])
+ self.assertEqual(values(b.value, field='parent_id'), [b, b])
class test_o2m_multiple(ImporterCase):
model_name = 'export.one2many.multiple'
From 8e841cd8f7603fc59be78b7d73283f65e4247840 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Thu, 20 Sep 2012 12:56:12 +0200
Subject: [PATCH 005/171] [FIX] non-linking o2m tests, corresponding code
bzr revid: xmo@openerp.com-20120920105612-03ifizt2iv08tdhz
---
openerp/addons/base/ir/ir_fields.py | 22 +++++---
openerp/tests/addons/test_impex/models.py | 6 +++
.../addons/test_impex/tests/test_load.py | 53 ++++++++-----------
3 files changed, 45 insertions(+), 36 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 6b3898f3fdd..44351229c26 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -206,16 +206,26 @@ class ir_fields_converter(orm.Model):
return [(6, 0, ids)]
def _str_to_one2many(self, cr, uid, model, column, value, context=None):
commands = []
- for subfield, record in zip((self._referencing_subfield(
- only_ref_fields(record))
- for record in value),
- value):
- id, subfield_type = self.db_id_for(
- cr, uid, model, column, subfield, record[subfield], context=context)
+
+ for record in value:
+ id = None
+ refs = only_ref_fields(record)
+ # there are ref fields in the record
+ if refs:
+ subfield = self._referencing_subfield(refs)
+ reference = record[subfield]
+ id, subfield_type = self.db_id_for(
+ cr, uid, model, column, subfield, reference, context=context)
+ if id is None:
+ raise ValueError(
+ _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'")
+ % {'field_type': subfield_type, 'value': reference})
+
writable = exclude_ref_fields(record)
if id:
commands.append(LINK_TO(id))
commands.append(UPDATE(id, writable))
else:
commands.append(CREATE(writable))
+
return commands
diff --git a/openerp/tests/addons/test_impex/models.py b/openerp/tests/addons/test_impex/models.py
index 455ea6b22f4..37894ccb78c 100644
--- a/openerp/tests/addons/test_impex/models.py
+++ b/openerp/tests/addons/test_impex/models.py
@@ -67,6 +67,12 @@ class One2ManyChild(orm.Model):
def name_get(self, cr, uid, ids, context=None):
return [(record.id, "%s:%s" % (self._name, record.value))
for record in self.browse(cr, uid, ids, context=context)]
+ def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100):
+ return (self.name_get(cr, user,
+ self.search(cr, user, [['value', operator, int(name.split(':')[1])]])
+ , context=context)
+ if isinstance(name, basestring) and name.split(':')[0] == self._name
+ else [])
class One2ManyMultiple(orm.Model):
_name = 'export.one2many.multiple'
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index 44b6c1a56df..25159dcd2ba 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -786,20 +786,21 @@ class test_o2m(ImporterCase):
model_name = 'export.one2many'
def test_name_get(self):
- # FIXME: bloody hell why can't this just name_create the record?
- self.assertRaises(
- IndexError,
- self.import_,
+ s = u'Java is a DSL for taking large XML files and converting them ' \
+ u'to stack traces'
+ ids, messages = self.import_(
['const', 'value'],
- [['5', u'Java is a DSL for taking large XML files'
- u' and converting them to stack traces']])
+ [['5', s]])
+ self.assertEqual(messages, [message(
+ u"No matching record found for name '%s' in field 'value'" % s)])
+ self.assertIs(ids, False)
def test_single(self):
ids, messages = self.import_(['const', 'value/value'], [
['5', '63']
])
- self.assertEqual(len(ids), 1)
self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
(b,) = self.browse()
self.assertEqual(b.const, 5)
@@ -810,8 +811,8 @@ class test_o2m(ImporterCase):
['5', '63'],
['6', '64'],
])
- self.assertEqual(len(ids), 2)
self.assertFalse(messages)
+ self.assertEqual(len(ids), 2)
b1, b2 = self.browse()
self.assertEqual(b1.const, 5)
@@ -826,8 +827,8 @@ class test_o2m(ImporterCase):
['', '65'],
['', '66'],
])
- self.assertEqual(len(ids), 4)
self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
(b,) = self.browse()
self.assertEqual(values(b.value), [63, 64, 65, 66])
@@ -839,8 +840,8 @@ class test_o2m(ImporterCase):
['the', '', '65'],
['rhythm', '', '66'],
])
- self.assertEqual(len(ids), 4)
self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
(b,) = self.browse()
self.assertEqual(values(b.value), [63, 64, 65, 66])
@@ -923,18 +924,12 @@ class test_o2m_multiple(ImporterCase):
['', '13', '23'],
['', '14', ''],
])
- self.assertEqual(len(ids), 4)
self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
# Oh yeah, that's the stuff
- (b, b1, b2) = self.browse()
- self.assertEqual(values(b.child1), [11])
- self.assertEqual(values(b.child2), [21])
-
- self.assertEqual(values(b1.child1), [12])
- self.assertEqual(values(b1.child2), [22])
-
- self.assertEqual(values(b2.child1), [13, 14])
- self.assertEqual(values(b2.child2), [23])
+ [b] = self.browse()
+ self.assertEqual(values(b.child1), [11, 12, 13, 14])
+ self.assertEqual(values(b.child2), [21, 22, 23])
def test_multi(self):
ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
@@ -945,13 +940,12 @@ class test_o2m_multiple(ImporterCase):
['', '', '22'],
['', '', '23'],
])
- self.assertEqual(len(ids), 6)
self.assertFalse(messages)
- # What the actual fuck?
- (b, b1) = self.browse()
+ self.assertEqual(len(ids), 1)
+
+ [b] = self.browse()
self.assertEqual(values(b.child1), [11, 12, 13, 14])
- self.assertEqual(values(b.child2), [21])
- self.assertEqual(values(b1.child2), [22, 23])
+ self.assertEqual(values(b.child2), [21, 22, 23])
def test_multi_fullsplit(self):
ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
@@ -963,14 +957,13 @@ class test_o2m_multiple(ImporterCase):
['', '', '22'],
['', '', '23'],
])
- self.assertEqual(len(ids), 7)
self.assertFalse(messages)
- # oh wow
- (b, b1) = self.browse()
+ self.assertEqual(len(ids), 1)
+
+ [b] = self.browse()
self.assertEqual(b.const, 5)
self.assertEqual(values(b.child1), [11, 12, 13, 14])
- self.assertEqual(b1.const, 36)
- self.assertEqual(values(b1.child2), [21, 22, 23])
+ self.assertEqual(values(b.child2), [21, 22, 23])
# function, related, reference: written to db as-is...
# => function uses @type for value coercion/conversion
From fdba99aaeb3998b6f1e76e69fc77bf45b0c73ee2 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Thu, 20 Sep 2012 13:09:14 +0200
Subject: [PATCH 006/171] [ADD] inline o2m LINK_TO (m2m-style)
bzr revid: xmo@openerp.com-20120920110914-hy2rtivhn9cs5wuc
---
openerp/addons/base/ir/ir_fields.py | 13 ++++++++--
.../addons/test_impex/tests/test_load.py | 24 ++++++++++---------
2 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 44351229c26..ae0d33298ca 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -204,10 +204,19 @@ class ir_fields_converter(orm.Model):
ids.append(id)
return [(6, 0, ids)]
- def _str_to_one2many(self, cr, uid, model, column, value, context=None):
+ def _str_to_one2many(self, cr, uid, model, column, records, context=None):
commands = []
- for record in value:
+ if len(records) == 1 and exclude_ref_fields(records[0]) == {}:
+ # only one row with only ref field, field=ref1,ref2,ref3 as in
+ # m2o/m2m
+ record = records[0]
+ subfield = self._referencing_subfield(record)
+ # transform [{subfield:ref1,ref2,ref3}] into
+ # [{subfield:ref1},{subfield:ref2},{subfield:ref3}]
+ records = ({subfield:item} for item in record[subfield].split(','))
+
+ for record in records:
id = None
refs = only_ref_fields(record)
# there are ref fields in the record
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index 25159dcd2ba..9ce0d5628ed 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -850,6 +850,8 @@ class test_o2m(ImporterCase):
'this is the rhythm'.split())
def test_link_inline(self):
+ """ m2m-style specification for o2ms
+ """
id1 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
'str': 'Bf', 'value': 109
})
@@ -857,17 +859,17 @@ class test_o2m(ImporterCase):
'str': 'Me', 'value': 262
})
- try:
- self.import_(['const', 'value/.id'], [
- ['42', '%d,%d' % (id1, id2)]
- ])
- self.fail("Should have raised a valueerror")
- except ValueError, e:
- # should be Exception(Database ID doesn't exist: export.one2many.child : $id1,$id2)
- self.assertIs(type(e), ValueError)
- self.assertEqual(
- e.args[0],
- "invalid literal for int() with base 10: '%d,%d'" % (id1, id2))
+ ids, messages = self.import_(['const', 'value/.id'], [
+ ['42', '%d,%d' % (id1, id2)]
+ ])
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
+
+ [b] = self.browse()
+ self.assertEqual(b.const, 42)
+ # automatically forces link between core record and o2ms
+ self.assertEqual(values(b.value), [109, 262])
+ self.assertEqual(values(b.value, field='parent_id'), [b, b])
def test_link(self):
""" O2M relating to an existing record (update) force a LINK_TO as well
From a9bc82c46dc007fa3bf0d479d6afab40530bb648 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Thu, 20 Sep 2012 17:04:43 +0200
Subject: [PATCH 007/171] [IMP] translation tests, translated acceptable values
for boolean fields
bzr revid: xmo@openerp.com-20120920150443-l9lna4bnkta7n2o8
---
openerp/addons/base/ir/ir_fields.py | 27 +++-
.../addons/test_impex/tests/test_load.py | 144 ++++++++----------
2 files changed, 90 insertions(+), 81 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index ae0d33298ca..10b80511c73 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import functools
import operator
+import itertools
import warnings
from openerp.osv import orm, fields
from openerp.tools.translate import _
@@ -55,7 +56,29 @@ class ir_fields_converter(orm.Model):
converter, cr, uid, model, column, context=context)
def _str_to_boolean(self, cr, uid, model, column, value, context=None):
- return value.lower() not in ('', '0', 'false', 'off')
+ # all translatables used for booleans
+ true, yes, false, no = _(u"true"), _(u"yes"), _(u"false"), _(u"no")
+ # potentially broken casefolding? What about locales?
+ trues = set(word.lower() for word in itertools.chain(
+ [u'1', u"true", u"yes"], # don't use potentially translated values
+ self._get_translations(cr, uid, ['code'], u"true", context=context),
+ self._get_translations(cr, uid, ['code'], u"yes", context=context),
+ ))
+ if value.lower() in trues: return True
+
+ # potentially broken casefolding? What about locales?
+ falses = set(word.lower() for word in itertools.chain(
+ [u'', u"0", u"false", u"no"],
+ self._get_translations(cr, uid, ['code'], u"false", context=context),
+ self._get_translations(cr, uid, ['code'], u"no", context=context),
+ ))
+ if value.lower() in falses: return False
+
+ warnings.warn(
+ _(u"Unknown value '%s' for boolean field '%%(field)s', assuming '%s'")
+ % (value, yes),
+ orm.ImportWarning)
+ return True
def _str_to_integer(self, cr, uid, model, column, value, context=None):
if not value: return False
@@ -86,7 +109,7 @@ class ir_fields_converter(orm.Model):
selection = selection(model, cr, uid)
for item, label in selection:
labels = self._get_translations(
- cr, uid, ('selection', 'model'), label, context=context)
+ cr, uid, ('selection', 'model', 'code'), label, context=context)
labels.append(label)
if value == unicode(item) or value in labels:
return item
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index 9ce0d5628ed..28957c29555 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -79,6 +79,27 @@ class ImporterCase(common.TransactionCase):
})
return '__test__.' + name
+ def add_translations(self, name, type, code, *tnx):
+ Lang = self.registry('res.lang')
+ if not Lang.search(self.cr, openerp.SUPERUSER_ID, [('code', '=', code)]):
+ Lang.create(self.cr, openerp.SUPERUSER_ID, {
+ 'name': code,
+ 'code': code,
+ 'translatable': True,
+ 'date_format': '%d.%m.%Y',
+ 'decimal_point': ',',
+ })
+ Translations = self.registry('ir.translation')
+ for source, value in tnx:
+ Translations.create(self.cr, openerp.SUPERUSER_ID, {
+ 'name': name,
+ 'lang': code,
+ 'type': type,
+ 'src': source,
+ 'value': value,
+ 'state': 'translated',
+ })
+
class test_ids_stuff(ImporterCase):
model_name = 'export.integer'
@@ -139,41 +160,39 @@ class test_boolean_field(ImporterCase):
], values(records))
def test_falses(self):
- ids, messages = self.import_(
- ['value'],
- [[u'0'], [u'off'],
- [u'false'], [u'FALSE'],
- [u'OFF'], [u''],
- ])
- self.assertEqual(len(ids), 6)
+ for lang, source, value in [('fr_FR', 'no', u'non'),
+ ('de_DE', 'no', u'nein'),
+ ('ru_RU', 'no', u'нет'),
+ ('nl_BE', 'false', u'vals'),
+ ('lt_LT', 'false', u'klaidingas')]:
+ self.add_translations('test_import.py', 'code', lang, (source, value))
+ falses = [[u'0'], [u'no'], [u'false'], [u'FALSE'], [u''],
+ [u'non'], # no, fr
+ [u'nein'], # no, de
+ [u'нет'], # no, ru
+ [u'vals'], # false, nl
+ [u'klaidingas'], # false, lt,
+ ]
+
+ ids, messages = self.import_(['value'], falses)
self.assertFalse(messages)
- self.assertEqual([
- False,
- False,
- False,
- False,
- False,
- False,
- ],
- values(self.read()))
+ self.assertEqual(len(ids), len(falses))
+ self.assertEqual([False] * len(falses), values(self.read()))
def test_trues(self):
- ids, messages = self.import_(
- ['value'],
- [['no'],
- ['None'],
- ['nil'],
- ['()'],
- ['f'],
- ['#f'],
- # Problem: OpenOffice (and probably excel) output localized booleans
- ['VRAI'],
+ trues = [['None'], ['nil'], ['()'], ['f'], ['#f'],
+ # Problem: OpenOffice (and probably excel) output localized booleans
+ ['VRAI'], ['ok'], ['true'], ['yes'], ['1'], ]
+ ids, messages = self.import_(['value'], trues)
+ self.assertEqual(len(ids), 10)
+ self.assertEqual(messages, [
+ message(u"Unknown value '%s' for boolean field 'value', assuming 'yes'" % v[0],
+ type='warning', from_=i, to_=i, record=i)
+ for i, v in enumerate(trues)
+ if v[0] != 'true' if v[0] != 'yes' if v[0] != '1'
])
- self.assertEqual(len(ids), 7)
- # FIXME: should warn for values which are not "true", "yes" or "1"
- self.assertFalse(messages)
self.assertEqual(
- [True] * 7,
+ [True] * 10,
values(self.read()))
class test_integer_field(ImporterCase):
@@ -399,9 +418,9 @@ class test_text(ImporterCase):
class test_selection(ImporterCase):
model_name = 'export.selection'
translations_fr = [
- ("Qux", "toto"),
- ("Bar", "titi"),
("Foo", "tete"),
+ ("Bar", "titi"),
+ ("Qux", "toto"),
]
def test_imported(self):
@@ -416,23 +435,8 @@ class test_selection(ImporterCase):
self.assertEqual([3, 2, 1, 2], values(self.read()))
def test_imported_translated(self):
- self.registry('res.lang').create(self.cr, openerp.SUPERUSER_ID, {
- 'name': u'Français',
- 'code': 'fr_FR',
- 'translatable': True,
- 'date_format': '%d.%m.%Y',
- 'decimal_point': ',',
- 'thousand_sep': ' ',
- })
- Translations = self.registry('ir.translation')
- for source, value in self.translations_fr:
- Translations.create(self.cr, openerp.SUPERUSER_ID, {
- 'name': 'export.selection,value',
- 'lang': 'fr_FR',
- 'type': 'selection',
- 'src': source,
- 'value': value
- })
+ self.add_translations(
+ 'export.selection,value', 'selection', 'fr_FR', *self.translations_fr)
ids, messages = self.import_(['value'], [
['toto'],
@@ -474,7 +478,7 @@ class test_selection_function(ImporterCase):
translations_fr = [
("Corge", "toto"),
("Grault", "titi"),
- ("Whee", "tete"),
+ ("Wheee", "tete"),
("Moog", "tutu"),
]
@@ -483,7 +487,7 @@ class test_selection_function(ImporterCase):
be good news) *and* serializes the selection function to reverse it:
import does not actually know that the selection field uses a function
"""
- # NOTE: conflict between a value and a label => ?
+ # NOTE: conflict between a value and a label => pick first
ids, messages = self.import_(['value'], [
['3'],
["Grault"],
@@ -497,38 +501,20 @@ class test_selection_function(ImporterCase):
def test_translated(self):
""" Expects output of selection function returns translated labels
"""
- self.registry('res.lang').create(self.cr, openerp.SUPERUSER_ID, {
- 'name': u'Français',
- 'code': 'fr_FR',
- 'translatable': True,
- 'date_format': '%d.%m.%Y',
- 'decimal_point': ',',
- 'thousand_sep': ' ',
- })
- Translations = self.registry('ir.translation')
- for source, value in self.translations_fr:
- Translations.create(self.cr, openerp.SUPERUSER_ID, {
- 'name': 'export.selection,value',
- 'lang': 'fr_FR',
- 'type': 'selection',
- 'src': source,
- 'value': value
- })
+ self.add_translations(
+ 'export.selection,value', 'selection', 'fr_FR', *self.translations_fr)
+
ids, messages = self.import_(['value'], [
- ['toto'],
+ ['titi'],
['tete'],
], context={'lang': 'fr_FR'})
- self.assertIs(ids, False)
- self.assertEqual(messages, [{
- 'type': 'error',
- 'rows': {'from': 1, 'to': 1},
- 'record': 1,
- 'field': 'value',
- 'message': "Value 'tete' not found in selection field 'value'",
- }])
- ids, messages = self.import_(['value'], [['Wheee']], context={'lang': 'fr_FR'})
- self.assertEqual(len(ids), 1)
self.assertFalse(messages)
+ self.assertEqual(len(ids), 2)
+ self.assertEqual(values(self.read()), ['1', '2'])
+
+ ids, messages = self.import_(['value'], [['Wheee']], context={'lang': 'fr_FR'})
+ self.assertFalse(messages)
+ self.assertEqual(len(ids), 1)
class test_m2o(ImporterCase):
model_name = 'export.many2one'
From b4421c8fba5a7208a0cf38708cfaa235d9bfa497 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 24 Sep 2012 12:14:04 +0200
Subject: [PATCH 008/171] [ADD] cache dict on the cursor, for request-local
repeated reads
bzr revid: xmo@openerp.com-20120924101404-cel6oy1akabbo7id
---
openerp/sql_db.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/openerp/sql_db.py b/openerp/sql_db.py
index 7b6f4469b8d..a6ebcd0300f 100644
--- a/openerp/sql_db.py
+++ b/openerp/sql_db.py
@@ -138,6 +138,16 @@ class Cursor(object):
sure you use psycopg2 v2.4.2 or newer if you use PostgreSQL 9.1 and
the performance hit is a concern for you.
+ .. attribute:: cache
+
+ Cache dictionary with a "request" (-ish) lifecycle, only lives as
+ long as the cursor itself does and proactively cleared when the
+ cursor is closed.
+
+ This cache should *only* be used to store repeatable reads as it
+ ignores rollbacks and savepoints, it should not be used to store
+ *any* data which may be modified during the life of the cursor.
+
"""
IN_MAX = 1000 # decent limit on size of IN queries - guideline = Oracle limit
@@ -182,6 +192,8 @@ class Cursor(object):
self._default_log_exceptions = True
+ self.cache = {}
+
def __del__(self):
if not self.__closed and not self._cnx.closed:
# Oops. 'self' has not been closed explicitly.
@@ -279,6 +291,8 @@ class Cursor(object):
if not self._obj:
return
+ del self.cache
+
if self.sql_log:
self.__closer = frame_codeinfo(currentframe(),3)
self.print_log()
From 449a86a51f62c2e3379fc649c55d89080c278fa4 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 24 Sep 2012 12:32:57 +0200
Subject: [PATCH 009/171] [IMP] cache boolean and selection translations for
the request (cursor) to avoid fetching them over and over again
bzr revid: xmo@openerp.com-20120924103257-1jgc3qhddzzi5c17
---
openerp/addons/base/ir/ir_fields.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 10b80511c73..73e748015a3 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -95,11 +95,20 @@ class ir_fields_converter(orm.Model):
return value or False
def _get_translations(self, cr, uid, types, src, context):
+ types = tuple(types)
+ # Cache translations so they don't have to be reloaded from scratch on
+ # every row of the file
+ tnx_cache = cr.cache.setdefault(self._name, {})
+ if tnx_cache.setdefault(types, {}) and src in tnx_cache[types]:
+ return tnx_cache[types][src]
+
Translations = self.pool['ir.translation']
tnx_ids = Translations.search(
cr, uid, [('type', 'in', types), ('src', '=', src)], context=context)
tnx = Translations.read(cr, uid, tnx_ids, ['value'], context=context)
- return map(operator.itemgetter('value'), tnx)
+ result = tnx_cache[types][src] = map(operator.itemgetter('value'), tnx)
+ return result
+
def _str_to_selection(self, cr, uid, model, column, value, context=None):
selection = column.selection
From 877e21ffdebeba412b7cb4db5fdf352adfac2ff2 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 24 Sep 2012 12:52:30 +0200
Subject: [PATCH 010/171] [IMP] return fields_get-style translated field
strings (if available) in user-readable warning and error messages from
import, rather than logical field names
bzr revid: xmo@openerp.com-20120924105230-1b7157xbruy2e5zr
---
openerp/osv/orm.py | 19 +++++++++++---
.../addons/test_impex/tests/test_load.py | 26 +++++++++----------
2 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index 57cc5823dd9..e58d6b76a76 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -1585,8 +1585,15 @@ class BaseModel(object):
:returns: a list of triplets of (id, xid, record)
:rtype: list((int|None, str|None, dict))
"""
+ if context is None: context = {}
Converter = self.pool['ir.fields.converter']
columns = dict((k, v.column) for k, v in self._all_columns.iteritems())
+ Translation = self.pool['ir.translation']
+ field_names = dict(
+ (f, (Translation._get_source(cr, uid, self._name + ',' + f, 'field',
+ context.get('lang', False) or 'en_US')
+ or column.string or f))
+ for f, column in columns.iteritems())
converters = dict(
(k, Converter.to_field(cr, uid, self, column, context=context))
for k, column in columns.iteritems())
@@ -1619,18 +1626,24 @@ class BaseModel(object):
for field, strvalue in record.iteritems():
if field in (None, 'id', '.id'): continue
- message_base = dict(extras, record=stream.index, field=field)
+ # In warnings and error messages, use translated string as
+ # field name
+ message_base = dict(
+ extras, record=stream.index, field=field_names[field])
with warnings.catch_warnings(record=True) as w:
try:
converted[field] = converters[field](strvalue)
+ # In warning and error returned, use logical field name
+ # as field so client can reverse
for warning in w:
- log(dict(message_base, type='warning',
+ log(dict(message_base, type='warning', field=field,
message=unicode(warning.message) % message_base))
except ValueError, e:
log(dict(message_base,
type='error',
- message=unicode(e) % message_base
+ field=field,
+ message=unicode(e) % message_base,
))
yield dbid, xid, converted, dict(extras, record=stream.index)
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index 28957c29555..cf95f5bb6c4 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -186,7 +186,7 @@ class test_boolean_field(ImporterCase):
ids, messages = self.import_(['value'], trues)
self.assertEqual(len(ids), 10)
self.assertEqual(messages, [
- message(u"Unknown value '%s' for boolean field 'value', assuming 'yes'" % v[0],
+ message(u"Unknown value '%s' for boolean field 'unknown', assuming 'yes'" % v[0],
type='warning', from_=i, to_=i, record=i)
for i, v in enumerate(trues)
if v[0] != 'true' if v[0] != 'yes' if v[0] != '1'
@@ -460,7 +460,7 @@ class test_selection(ImporterCase):
'rows': {'from': 0, 'to': 0},
'record': 0,
'field': 'value',
- 'message': "Value 'Baz' not found in selection field 'value'",
+ 'message': "Value 'Baz' not found in selection field 'unknown'",
}])
ids, messages = self.import_(['value'], [[42]])
@@ -470,7 +470,7 @@ class test_selection(ImporterCase):
'rows': {'from': 0, 'to': 0},
'record': 0,
'field': 'value',
- 'message': "Value '42' not found in selection field 'value'",
+ 'message': "Value '42' not found in selection field 'unknown'",
}])
class test_selection_function(ImporterCase):
@@ -583,7 +583,7 @@ class test_m2o(ImporterCase):
ids, messages = self.import_(['value'], [[name2]])
self.assertEqual(
messages,
- [message(u"Found multiple matches for field 'value' (2 matches)",
+ [message(u"Found multiple matches for field 'unknown' (2 matches)",
type='warning')])
self.assertEqual(len(ids), 1)
self.assertEqual([
@@ -607,7 +607,7 @@ class test_m2o(ImporterCase):
[integer_id1],
])
self.assertEqual(messages, [
- message(u"No matching record found for name '%s' in field 'value'" % id,
+ message(u"No matching record found for name '%s' in field 'unknown'" % id,
from_=index, to_=index, record=index)
for index, id in enumerate([integer_id1, integer_id2, integer_id1])])
self.assertIs(ids, False)
@@ -626,19 +626,19 @@ class test_m2o(ImporterCase):
ids, messages = self.import_(['value'], [['nameisnoexist:3']])
self.assertEqual(messages, [message(
u"No matching record found for name 'nameisnoexist:3' "
- u"in field 'value'")])
+ u"in field 'unknown'")])
self.assertIs(ids, False)
ids, messages = self.import_(['value/id'], [['noxidhere']])
self.assertEqual(messages, [message(
u"No matching record found for external id 'noxidhere' "
- u"in field 'value'")])
+ u"in field 'unknown'")])
self.assertIs(ids, False)
ids, messages = self.import_(['value/.id'], [['66']])
self.assertEqual(messages, [message(
u"No matching record found for database id '66' "
- u"in field 'value'")])
+ u"in field 'unknown'")])
self.assertIs(ids, False)
def test_fail_multiple(self):
@@ -646,7 +646,7 @@ class test_m2o(ImporterCase):
['value', 'value/id'],
[['somename', 'somexid']])
self.assertEqual(messages, [message(
- u"Ambiguous specification for field 'value', only provide one of "
+ u"Ambiguous specification for field 'unknown', only provide one of "
u"name, external id or database id")])
self.assertIs(ids, False)
@@ -690,7 +690,7 @@ class test_m2m(ImporterCase):
ids, messages = self.import_(['value/.id'], [['42']])
self.assertEqual(messages, [message(
u"No matching record found for database id '42' in field "
- u"'value'")])
+ u"'unknown'")])
self.assertIs(ids, False)
def test_xids(self):
@@ -716,7 +716,7 @@ class test_m2m(ImporterCase):
ids, messages = self.import_(['value/id'], [['noxidforthat']])
self.assertEqual(messages, [message(
u"No matching record found for external id 'noxidforthat' "
- u"in field 'value'")])
+ u"in field 'unknown'")])
self.assertIs(ids, False)
def test_names(self):
@@ -745,7 +745,7 @@ class test_m2m(ImporterCase):
ids, messages = self.import_(['value'], [['wherethem2mhavenonames']])
self.assertEqual(messages, [message(
u"No matching record found for name 'wherethem2mhavenonames' in "
- u"field 'value'")])
+ u"field 'unknown'")])
self.assertIs(ids, False)
def test_import_to_existing(self):
@@ -778,7 +778,7 @@ class test_o2m(ImporterCase):
['const', 'value'],
[['5', s]])
self.assertEqual(messages, [message(
- u"No matching record found for name '%s' in field 'value'" % s)])
+ u"No matching record found for name '%s' in field 'unknown'" % s)])
self.assertIs(ids, False)
def test_single(self):
From a9c2cfcdb91c79cc60de909a4e23bd9e9e5f9787 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 24 Sep 2012 16:57:50 +0200
Subject: [PATCH 011/171] [IMP] make help attribute available on all actions
bzr revid: xmo@openerp.com-20120924145750-n0gj4bww1d83h3fy
---
openerp/addons/base/ir/ir_actions.py | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py
index 383f78181e9..b14f4cd7e84 100644
--- a/openerp/addons/base/ir/ir_actions.py
+++ b/openerp/addons/base/ir/ir_actions.py
@@ -19,14 +19,11 @@
#
##############################################################################
-import ast
-import copy
import logging
import os
import re
import time
import tools
-from xml import dom
import netsvc
from osv import fields,osv
@@ -47,6 +44,9 @@ class actions(osv.osv):
'name': fields.char('Name', size=64, required=True),
'type': fields.char('Action Type', required=True, size=32,readonly=True),
'usage': fields.char('Action Usage', size=32),
+ 'help': fields.text('Action description',
+ help='Optional help text for the users with a description of the target view, such as its usage and purpose.',
+ translate=True),
}
_defaults = {
'usage': lambda *a: False,
@@ -107,6 +107,7 @@ class report_xml(osv.osv):
r['report_xsl'] and opj('addons',r['report_xsl']))
_name = 'ir.actions.report.xml'
+ _inherit = 'ir.actions.actions'
_table = 'ir_act_report_xml'
_sequence = 'ir_actions_id_seq'
_order = 'name'
@@ -155,6 +156,7 @@ report_xml()
class act_window(osv.osv):
_name = 'ir.actions.act_window'
_table = 'ir_act_window'
+ _inherit = 'ir.actions.actions'
_sequence = 'ir_actions_id_seq'
_order = 'name'
@@ -245,9 +247,6 @@ class act_window(osv.osv):
'filter': fields.boolean('Filter'),
'auto_search':fields.boolean('Auto Search'),
'search_view' : fields.function(_search_view, type='text', string='Search View'),
- 'help': fields.text('Action description',
- help='Optional help text for the users with a description of the target view, such as its usage and purpose.',
- translate=True),
'multi': fields.boolean('Action on Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view"),
}
@@ -331,6 +330,7 @@ act_wizard()
class act_url(osv.osv):
_name = 'ir.actions.url'
_table = 'ir_act_url'
+ _inherit = 'ir.actions.actions'
_sequence = 'ir_actions_id_seq'
_order = 'name'
_columns = {
@@ -432,6 +432,7 @@ class actions_server(osv.osv):
_name = 'ir.actions.server'
_table = 'ir_act_server'
+ _inherit = 'ir.actions.actions'
_sequence = 'ir_actions_id_seq'
_order = 'sequence,name'
_columns = {
From f143902d1afa345c8fad935a80a6b404a9a3cfb7 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 24 Sep 2012 17:04:17 +0200
Subject: [PATCH 012/171] [IMP] allow converters to add data to import
messages, formalize message keys
bzr revid: xmo@openerp.com-20120924150417-c2y7g7vdsfz66363
---
openerp/addons/base/ir/ir_fields.py | 33 +++++++--
openerp/osv/orm.py | 70 +++++++++++++++----
.../addons/test_impex/tests/test_load.py | 32 +++------
3 files changed, 94 insertions(+), 41 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 73e748015a3..2256542533b 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -38,6 +38,26 @@ class ir_fields_converter(orm.Model):
By default, tries to get a method on itself with a name matching the
pattern ``_$fromtype_$column._type`` and returns it.
+ Converter callables can either return a value to their caller or raise
+ ``ValueError``, which will be interpreted as a validation & conversion
+ failure.
+
+ ValueError can have either one or two parameters. The first parameter
+ is mandatory, **must** be a unicode string and will be used as the
+ user-visible message for the error (it should be translatable and
+ translated). It can contain a ``field`` named format placeholder so the
+ caller can inject the field's translated, user-facing name (@string).
+
+ The second parameter is optional and, if provided, must be a mapping.
+ This mapping will be merged into the error dictionary returned to the
+ client.
+
+ If a converter can perform its function but has to make assumptions
+ about the data, it can send a warning to the user through signalling
+ an :class:`~openerp.osv.orm.ImportWarning` (via ``warnings.warn``). The
+ handling of a warning at the upper levels is the same as
+ ``ValueError`` above.
+
:param cr: openerp cursor
:param uid: ID of user calling the converter
:param column: column object to generate a value for
@@ -74,10 +94,9 @@ class ir_fields_converter(orm.Model):
))
if value.lower() in falses: return False
- warnings.warn(
+ warnings.warn(orm.ImportWarning(
_(u"Unknown value '%s' for boolean field '%%(field)s', assuming '%s'")
- % (value, yes),
- orm.ImportWarning)
+ % (value, yes)))
return True
def _str_to_integer(self, cr, uid, model, column, value, context=None):
@@ -124,7 +143,9 @@ class ir_fields_converter(orm.Model):
return item
raise ValueError(
_(u"Value '%s' not found in selection field '%%(field)s'") % (
- value))
+ value), {
+ 'moreinfo': map(operator.itemgetter(1), selection)
+ })
def db_id_for(self, cr, uid, model, column, subfield, value, context=None):
@@ -174,9 +195,9 @@ class ir_fields_converter(orm.Model):
cr, uid, name=value, operator='=', context=context)
if ids:
if len(ids) > 1:
- warnings.warn(
+ warnings.warn(orm.ImportWarning(
_(u"Found multiple matches for field '%%(field)s' (%d matches)")
- % (len(ids)), orm.ImportWarning)
+ % (len(ids))))
id, _name = ids[0]
else:
raise Exception(u"Unknown sub-field '%s'" % subfield)
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index e58d6b76a76..98e24075311 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -1444,6 +1444,40 @@ class BaseModel(object):
def load(self, cr, uid, fields, data, context=None):
"""
+ Attempts to load the data matrix, and returns a list of ids (or
+ ``False`` if there was an error and no id could be generated) and a
+ list of messages.
+
+ Each message is a dictionary with the following keys:
+
+ ``type``
+ the type of message, either ``warning`` or ``error``. Any ``error``
+ message indicates the import failed and was rolled back.
+ ``message``
+ the message's actual text, which should be translated and can be
+ shown to the user directly
+ ``rows``
+ a dict with 2 keys ``from`` and ``to``, indicates the range of rows
+ in ``data`` which generated the message
+ ``record``
+ a single integer, for warnings the index of the record which
+ generated the message (can be obtained from a non-false ``ids``
+ result)
+ ``field``
+ the name of the (logical) OpenERP field for which the error or
+ warning was generated
+ ``moreinfo`` (optional)
+ A string, a list or a dict, leading to more information about the
+ warning.
+
+ * If ``moreinfo`` is a string, it is a supplementary warnings
+ message which should be hidden by default
+ * If ``moreinfo`` is a list, it provides a number of possible or
+ alternative values for the string
+ * If ``moreinfo`` is a dict, it is an OpenERP action descriptor
+ which can be executed to get more information about the issues
+ with the field. If present, the ``help`` key serves as a label
+ for the action (e.g. the text of the link).
:param cr: cursor for the request
:param int uid: ID of the user attempting the data import
@@ -1598,6 +1632,14 @@ class BaseModel(object):
(k, Converter.to_field(cr, uid, self, column, context=context))
for k, column in columns.iteritems())
+ def _log(base, field, exception):
+ type = 'warning' if isinstance(exception, Warning) else 'error'
+ record = dict(base, field=field, type=type,
+ message=unicode(exception.args[0]) % base)
+ if len(exception.args) > 1 and exception.args[1]:
+ record.update(exception.args[1])
+ log(record)
+
stream = CountingStream(records)
for record, extras in stream:
dbid = False
@@ -1630,21 +1672,23 @@ class BaseModel(object):
# field name
message_base = dict(
extras, record=stream.index, field=field_names[field])
- with warnings.catch_warnings(record=True) as w:
- try:
+ try:
+ with warnings.catch_warnings(record=True) as ws:
converted[field] = converters[field](strvalue)
- # In warning and error returned, use logical field name
- # as field so client can reverse
- for warning in w:
- log(dict(message_base, type='warning', field=field,
- message=unicode(warning.message) % message_base))
- except ValueError, e:
- log(dict(message_base,
- type='error',
- field=field,
- message=unicode(e) % message_base,
- ))
+ for warning in ws:
+ # bubble non-import warnings upward
+ if warning.category != ImportWarning:
+ warnings.warn(warning.message, warning.category)
+ continue
+ w = warning.message
+ if isinstance(w, basestring):
+ # wrap warning string in an ImportWarning for
+ # uniform handling
+ w = ImportWarning(w)
+ _log(message_base, field, w)
+ except ValueError, e:
+ _log(message_base, field, e)
yield dbid, xid, converted, dict(extras, record=stream.index)
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index cf95f5bb6c4..f97dafaaf39 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -5,14 +5,10 @@ import openerp
from openerp.tests import common
from openerp.tools.misc import mute_logger
-def message(msg, type='error', from_=0, to_=0, record=0, field='value'):
- return {
- 'type': type,
- 'rows': {'from': from_, 'to': to_},
- 'record': record,
- 'field': field,
- 'message': msg
- }
+def message(msg, type='error', from_=0, to_=0, record=0, field='value', **kwargs):
+ return dict(kwargs,
+ type=type, rows={'from': from_, 'to': to_}, record=record,
+ field=field, message=msg)
def error(row, message, record=None, **kwargs):
""" Failed import of the record ``record`` at line ``row``, with the error
@@ -455,23 +451,15 @@ class test_selection(ImporterCase):
def test_invalid(self):
ids, messages = self.import_(['value'], [['Baz']])
self.assertIs(ids, False)
- self.assertEqual(messages, [{
- 'type': 'error',
- 'rows': {'from': 0, 'to': 0},
- 'record': 0,
- 'field': 'value',
- 'message': "Value 'Baz' not found in selection field 'unknown'",
- }])
+ self.assertEqual(messages, [message(
+ u"Value 'Baz' not found in selection field 'unknown'",
+ moreinfo="Foo Bar Qux".split())])
ids, messages = self.import_(['value'], [[42]])
self.assertIs(ids, False)
- self.assertEqual(messages, [{
- 'type': 'error',
- 'rows': {'from': 0, 'to': 0},
- 'record': 0,
- 'field': 'value',
- 'message': "Value '42' not found in selection field 'unknown'",
- }])
+ self.assertEqual(messages, [message(
+ u"Value '42' not found in selection field 'unknown'",
+ moreinfo="Foo Bar Qux".split())])
class test_selection_function(ImporterCase):
model_name = 'export.selection.function'
From 9f2e7ba7ef86808ea5f10af178e7aeb939426323 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 24 Sep 2012 17:15:02 +0200
Subject: [PATCH 013/171] [IMP] return a dict from Model.load for easier future
extensibility (if needed) rather than a tuple.
also easier/cleaner to unpack on the JS side
bzr revid: xmo@openerp.com-20120924151502-4robe639ctpuvb94
---
openerp/osv/orm.py | 6 +-
.../addons/test_impex/tests/test_load.py | 378 +++++++++---------
2 files changed, 192 insertions(+), 192 deletions(-)
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index 98e24075311..b824be91b96 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -1486,7 +1486,7 @@ class BaseModel(object):
:param data: row-major matrix of data to import
:type data: list(list(str))
:param dict context:
- :returns:
+ :returns: {ids: list(int)|False, messages: [Message]}
"""
cr.execute('SAVEPOINT model_load')
messages = []
@@ -1516,8 +1516,8 @@ class BaseModel(object):
messages.append(dict(info, type="error", message=str(e)))
if any(message['type'] == 'error' for message in messages):
cr.execute('ROLLBACK TO SAVEPOINT model_load')
- return False, messages
- return ids, messages
+ ids = False
+ return {'ids': ids, 'messages': messages}
def _extract_records(self, cr, uid, fields_, data,
context=None, log=lambda a: None):
""" Generates record dicts from the data iterable.
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index f97dafaaf39..060b32c48f5 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -100,9 +100,9 @@ class test_ids_stuff(ImporterCase):
model_name = 'export.integer'
def test_create_with_id(self):
- ids, messages = self.import_(['.id', 'value'], [['42', '36']])
- self.assertIs(ids, False)
- self.assertEqual(messages, [{
+ result = self.import_(['.id', 'value'], [['42', '36']])
+ self.assertIs(result['ids'], False)
+ self.assertEqual(result['messages'], [{
'type': 'error',
'rows': {'from': 0, 'to': 0},
'record': 0,
@@ -110,9 +110,9 @@ class test_ids_stuff(ImporterCase):
'message': u"Unknown database identifier '42'",
}])
def test_create_with_xid(self):
- ids, messages = self.import_(['id', 'value'], [['somexmlid', '42']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['id', 'value'], [['somexmlid', '42']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual(
'somexmlid',
self.xid(self.browse()[0]))
@@ -123,9 +123,9 @@ class test_ids_stuff(ImporterCase):
36,
self.model.browse(self.cr, openerp.SUPERUSER_ID, id).value)
- ids, messages = self.import_(['.id', 'value'], [[str(id), '42']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['.id', 'value'], [[str(id), '42']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual(
[42], # updated value to imported
values(self.read()))
@@ -143,12 +143,12 @@ class test_boolean_field(ImporterCase):
def test_empty(self):
self.assertEqual(
self.import_(['value'], []),
- ([], []))
+ {'ids': [], 'messages': []})
def test_exported(self):
- ids, messages = self.import_(['value'], [['False'], ['True'], ])
- self.assertEqual(len(ids), 2)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['False'], ['True'], ])
+ self.assertEqual(len(result['ids']), 2)
+ self.assertFalse(result['messages'])
records = self.read()
self.assertEqual([
False,
@@ -170,18 +170,18 @@ class test_boolean_field(ImporterCase):
[u'klaidingas'], # false, lt,
]
- ids, messages = self.import_(['value'], falses)
- self.assertFalse(messages)
- self.assertEqual(len(ids), len(falses))
+ result = self.import_(['value'], falses)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), len(falses))
self.assertEqual([False] * len(falses), values(self.read()))
def test_trues(self):
trues = [['None'], ['nil'], ['()'], ['f'], ['#f'],
# Problem: OpenOffice (and probably excel) output localized booleans
['VRAI'], ['ok'], ['true'], ['yes'], ['1'], ]
- ids, messages = self.import_(['value'], trues)
- self.assertEqual(len(ids), 10)
- self.assertEqual(messages, [
+ result = self.import_(['value'], trues)
+ self.assertEqual(len(result['ids']), 10)
+ self.assertEqual(result['messages'], [
message(u"Unknown value '%s' for boolean field 'unknown', assuming 'yes'" % v[0],
type='warning', from_=i, to_=i, record=i)
for i, v in enumerate(trues)
@@ -197,69 +197,69 @@ class test_integer_field(ImporterCase):
def test_none(self):
self.assertEqual(
self.import_(['value'], []),
- ([], []))
+ {'ids': [], 'messages': []})
def test_empty(self):
- ids, messages = self.import_(['value'], [['']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual(
[False],
values(self.read()))
def test_zero(self):
- ids, messages = self.import_(['value'], [['0']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['0']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
- ids, messages = self.import_(['value'], [['-0']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['-0']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual([False, False], values(self.read()))
def test_positives(self):
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['1'],
['42'],
[str(2**31-1)],
['12345678']
])
- self.assertEqual(len(ids), 4)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 4)
+ self.assertFalse(result['messages'])
self.assertEqual([
1, 42, 2**31-1, 12345678
], values(self.read()))
def test_negatives(self):
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['-1'],
['-42'],
[str(-(2**31 - 1))],
[str(-(2**31))],
['-12345678']
])
- self.assertEqual(len(ids), 5)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 5)
+ self.assertFalse(result['messages'])
self.assertEqual([
-1, -42, -(2**31 - 1), -(2**31), -12345678
], values(self.read()))
@mute_logger('openerp.sql_db')
def test_out_of_range(self):
- ids, messages = self.import_(['value'], [[str(2**31)]])
- self.assertIs(ids, False)
- self.assertEqual(messages, [{
+ result = self.import_(['value'], [[str(2**31)]])
+ self.assertIs(result['ids'], False)
+ self.assertEqual(result['messages'], [{
'type': 'error',
'rows': {'from': 0, 'to': 0},
'record': 0,
'message': "integer out of range\n"
}])
- ids, messages = self.import_(['value'], [[str(-2**32)]])
- self.assertIs(ids, False)
- self.assertEqual(messages, [{
+ result = self.import_(['value'], [[str(-2**32)]])
+ self.assertIs(result['ids'], False)
+ self.assertEqual(result['messages'], [{
'type': 'error',
'rows': {'from': 0, 'to': 0},
'record': 0,
@@ -267,9 +267,9 @@ class test_integer_field(ImporterCase):
}])
def test_nonsense(self):
- ids, messages = self.import_(['value'], [['zorglub']])
- self.assertIs(ids, False)
- self.assertEqual(messages, [{
+ result = self.import_(['value'], [['zorglub']])
+ self.assertIs(result['ids'], False)
+ self.assertEqual(result['messages'], [{
'type': 'error',
'rows': {'from': 0, 'to': 0},
'record': 0,
@@ -282,29 +282,29 @@ class test_float_field(ImporterCase):
def test_none(self):
self.assertEqual(
self.import_(['value'], []),
- ([], []))
+ {'ids': [], 'messages': []})
def test_empty(self):
- ids, messages = self.import_(['value'], [['']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual(
[False],
values(self.read()))
def test_zero(self):
- ids, messages = self.import_(['value'], [['0']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['0']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
- ids, messages = self.import_(['value'], [['-0']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['-0']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual([False, False], values(self.read()))
def test_positives(self):
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['1'],
['42'],
[str(2**31-1)],
@@ -312,15 +312,15 @@ class test_float_field(ImporterCase):
[str(2**33)],
['0.000001'],
])
- self.assertEqual(len(ids), 6)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 6)
+ self.assertFalse(result['messages'])
self.assertEqual([
1, 42, 2**31-1, 12345678, 2.0**33, .000001
], values(self.read()))
def test_negatives(self):
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['-1'],
['-42'],
[str(-2**31 + 1)],
@@ -329,16 +329,16 @@ class test_float_field(ImporterCase):
[str(-2**33)],
['-0.000001'],
])
- self.assertEqual(len(ids), 7)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 7)
+ self.assertFalse(result['messages'])
self.assertEqual([
-1, -42, -(2**31 - 1), -(2**31), -12345678, -2.0**33, -.000001
], values(self.read()))
def test_nonsense(self):
- ids, messages = self.import_(['value'], [['foobar']])
- self.assertIs(ids, False)
- self.assertEqual(messages, [{
+ result = self.import_(['value'], [['foobar']])
+ self.assertIs(result['ids'], False)
+ self.assertEqual(result['messages'], [{
'type': 'error',
'rows': {'from': 0, 'to': 0},
'record': 0,
@@ -350,13 +350,13 @@ class test_string_field(ImporterCase):
model_name = 'export.string.bounded'
def test_empty(self):
- ids, messages = self.import_(['value'], [['']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual([False], values(self.read()))
def test_imported(self):
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
[u'foobar'],
[u'foobarbaz'],
[u'Með suð í eyrum við spilum endalaust'],
@@ -364,8 +364,8 @@ class test_string_field(ImporterCase):
u"someone he can't pound a nail with a banana doesn't much "
u"surprise him."]
])
- self.assertEqual(len(ids), 4)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 4)
+ self.assertFalse(result['messages'])
self.assertEqual([
u"foobar",
u"foobarbaz",
@@ -377,14 +377,14 @@ class test_unbound_string_field(ImporterCase):
model_name = 'export.string'
def test_imported(self):
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
[u'í dag viðrar vel til loftárása'],
# ackbar.jpg
[u"If they ask you about fun, you tell them – fun is a filthy"
u" parasite"]
])
- self.assertEqual(len(ids), 2)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 2)
+ self.assertFalse(result['messages'])
self.assertEqual([
u"í dag viðrar vel til loftárása",
u"If they ask you about fun, you tell them – fun is a filthy parasite"
@@ -394,9 +394,9 @@ class test_text(ImporterCase):
model_name = 'export.text'
def test_empty(self):
- ids, messages = self.import_(['value'], [['']])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['']])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual([False], values(self.read()))
def test_imported(self):
@@ -406,9 +406,9 @@ class test_text(ImporterCase):
u"snúninga 12 tommu vínylplötur (sem geta verið allt að 30 mín "
u"hvor hlið).\n\nBreiðskífur eru stundum tvöfaldar og eru þær þá"
u" gefnar út á tveimur geisladiskum eða tveimur vínylplötum.")
- ids, messages = self.import_(['value'], [[s]])
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [[s]])
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
self.assertEqual([s], values(self.read()))
class test_selection(ImporterCase):
@@ -420,44 +420,44 @@ class test_selection(ImporterCase):
]
def test_imported(self):
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['Qux'],
['Bar'],
['Foo'],
['2'],
])
- self.assertEqual(len(ids), 4)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 4)
+ self.assertFalse(result['messages'])
self.assertEqual([3, 2, 1, 2], values(self.read()))
def test_imported_translated(self):
self.add_translations(
'export.selection,value', 'selection', 'fr_FR', *self.translations_fr)
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['toto'],
['tete'],
['titi'],
], context={'lang': 'fr_FR'})
- self.assertEqual(len(ids), 3)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 3)
+ self.assertFalse(result['messages'])
self.assertEqual([3, 1, 2], values(self.read()))
- ids, messages = self.import_(['value'], [['Foo']], context={'lang': 'fr_FR'})
- self.assertEqual(len(ids), 1)
- self.assertFalse(messages)
+ result = self.import_(['value'], [['Foo']], context={'lang': 'fr_FR'})
+ self.assertEqual(len(result['ids']), 1)
+ self.assertFalse(result['messages'])
def test_invalid(self):
- ids, messages = self.import_(['value'], [['Baz']])
- self.assertIs(ids, False)
- self.assertEqual(messages, [message(
+ result = self.import_(['value'], [['Baz']])
+ self.assertIs(result['ids'], False)
+ self.assertEqual(result['messages'], [message(
u"Value 'Baz' not found in selection field 'unknown'",
moreinfo="Foo Bar Qux".split())])
- ids, messages = self.import_(['value'], [[42]])
- self.assertIs(ids, False)
- self.assertEqual(messages, [message(
+ result = self.import_(['value'], [[42]])
+ self.assertIs(result['ids'], False)
+ self.assertEqual(result['messages'], [message(
u"Value '42' not found in selection field 'unknown'",
moreinfo="Foo Bar Qux".split())])
@@ -476,12 +476,12 @@ class test_selection_function(ImporterCase):
import does not actually know that the selection field uses a function
"""
# NOTE: conflict between a value and a label => pick first
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['3'],
["Grault"],
])
- self.assertEqual(len(ids), 2)
- self.assertFalse(messages)
+ self.assertEqual(len(result['ids']), 2)
+ self.assertFalse(result['messages'])
self.assertEqual(
['3', '1'],
values(self.read()))
@@ -492,17 +492,17 @@ class test_selection_function(ImporterCase):
self.add_translations(
'export.selection,value', 'selection', 'fr_FR', *self.translations_fr)
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['titi'],
['tete'],
], context={'lang': 'fr_FR'})
- self.assertFalse(messages)
- self.assertEqual(len(ids), 2)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 2)
self.assertEqual(values(self.read()), ['1', '2'])
- ids, messages = self.import_(['value'], [['Wheee']], context={'lang': 'fr_FR'})
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ result = self.import_(['value'], [['Wheee']], context={'lang': 'fr_FR'})
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
class test_m2o(ImporterCase):
model_name = 'export.many2one'
@@ -519,14 +519,14 @@ class test_m2o(ImporterCase):
name2 = dict(self.registry('export.integer').name_get(
self.cr, openerp.SUPERUSER_ID,[integer_id2]))[integer_id2]
- ids , messages = self.import_(['value'], [
+ result = self.import_(['value'], [
# import by name_get
[name1],
[name1],
[name2],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 3)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 3)
# correct ids assigned to corresponding records
self.assertEqual([
(integer_id1, name1),
@@ -541,18 +541,18 @@ class test_m2o(ImporterCase):
xid = self.xid(ExportInteger.browse(
self.cr, openerp.SUPERUSER_ID, [integer_id])[0])
- ids, messages = self.import_(['value/id'], [[xid]])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ result = self.import_(['value/id'], [[xid]])
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
b = self.browse()
self.assertEqual(42, b[0].value.value)
def test_by_id(self):
integer_id = self.registry('export.integer').create(
self.cr, openerp.SUPERUSER_ID, {'value': 42})
- ids, messages = self.import_(['value/.id'], [[integer_id]])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ result = self.import_(['value/.id'], [[integer_id]])
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
b = self.browse()
self.assertEqual(42, b[0].value.value)
@@ -568,12 +568,12 @@ class test_m2o(ImporterCase):
# names should be the same
self.assertEqual(name1, name2)
- ids, messages = self.import_(['value'], [[name2]])
+ result = self.import_(['value'], [[name2]])
self.assertEqual(
- messages,
+ result['messages'],
[message(u"Found multiple matches for field 'unknown' (2 matches)",
type='warning')])
- self.assertEqual(len(ids), 1)
+ self.assertEqual(len(result['ids']), 1)
self.assertEqual([
(integer_id1, name1)
], values(self.read()))
@@ -588,55 +588,55 @@ class test_m2o(ImporterCase):
self.cr, openerp.SUPERUSER_ID, {'value': 36})
# Because name_search all the things. Fallback schmallback
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
# import by id, without specifying it
[integer_id1],
[integer_id2],
[integer_id1],
])
- self.assertEqual(messages, [
+ self.assertEqual(result['messages'], [
message(u"No matching record found for name '%s' in field 'unknown'" % id,
from_=index, to_=index, record=index)
for index, id in enumerate([integer_id1, integer_id2, integer_id1])])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
def test_sub_field(self):
""" Does not implicitly create the record, does not warn that you can't
import m2o subfields (at all)...
"""
- ids, messages = self.import_(['value/value'], [['42']])
- self.assertEqual(messages, [
+ result = self.import_(['value/value'], [['42']])
+ self.assertEqual(result['messages'], [
message(u"Can not create Many-To-One records indirectly, import "
u"the field separately")])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
def test_fail_noids(self):
- ids, messages = self.import_(['value'], [['nameisnoexist:3']])
- self.assertEqual(messages, [message(
+ result = self.import_(['value'], [['nameisnoexist:3']])
+ self.assertEqual(result['messages'], [message(
u"No matching record found for name 'nameisnoexist:3' "
u"in field 'unknown'")])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
- ids, messages = self.import_(['value/id'], [['noxidhere']])
- self.assertEqual(messages, [message(
+ result = self.import_(['value/id'], [['noxidhere']])
+ self.assertEqual(result['messages'], [message(
u"No matching record found for external id 'noxidhere' "
u"in field 'unknown'")])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
- ids, messages = self.import_(['value/.id'], [['66']])
- self.assertEqual(messages, [message(
+ result = self.import_(['value/.id'], [['66']])
+ self.assertEqual(result['messages'], [message(
u"No matching record found for database id '66' "
u"in field 'unknown'")])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
def test_fail_multiple(self):
- ids, messages = self.import_(
+ result = self.import_(
['value', 'value/id'],
[['somename', 'somexid']])
- self.assertEqual(messages, [message(
+ self.assertEqual(result['messages'], [message(
u"Ambiguous specification for field 'unknown', only provide one of "
u"name, external id or database id")])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
class test_m2m(ImporterCase):
model_name = 'export.many2many'
@@ -656,14 +656,14 @@ class test_m2m(ImporterCase):
id5 = self.registry('export.many2many.other').create(
self.cr, openerp.SUPERUSER_ID, {'value': 99, 'str': 'record4'})
- ids, messages = self.import_(['value/.id'], [
+ result = self.import_(['value/.id'], [
['%d,%d' % (id1, id2)],
['%d,%d,%d' % (id1, id3, id4)],
['%d,%d,%d' % (id1, id2, id3)],
['%d' % id5]
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 4)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 4)
ids = lambda records: [record.id for record in records]
@@ -675,11 +675,11 @@ class test_m2m(ImporterCase):
self.assertEqual(values(b[2].value), [3, 44, 84])
def test_noids(self):
- ids, messages = self.import_(['value/.id'], [['42']])
- self.assertEqual(messages, [message(
+ result = self.import_(['value/.id'], [['42']])
+ self.assertEqual(result['messages'], [message(
u"No matching record found for database id '42' in field "
u"'unknown'")])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
def test_xids(self):
M2O_o = self.registry('export.many2many.other')
@@ -689,23 +689,23 @@ class test_m2m(ImporterCase):
id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
records = M2O_o.browse(self.cr, openerp.SUPERUSER_ID, [id1, id2, id3, id4])
- ids, messages = self.import_(['value/id'], [
+ result = self.import_(['value/id'], [
['%s,%s' % (self.xid(records[0]), self.xid(records[1]))],
['%s' % self.xid(records[3])],
['%s,%s' % (self.xid(records[2]), self.xid(records[1]))],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 3)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 3)
b = self.browse()
self.assertEqual(values(b[0].value), [3, 44])
self.assertEqual(values(b[2].value), [44, 84])
def test_noxids(self):
- ids, messages = self.import_(['value/id'], [['noxidforthat']])
- self.assertEqual(messages, [message(
+ result = self.import_(['value/id'], [['noxidforthat']])
+ self.assertEqual(result['messages'], [message(
u"No matching record found for external id 'noxidforthat' "
u"in field 'unknown'")])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
def test_names(self):
M2O_o = self.registry('export.many2many.other')
@@ -717,24 +717,24 @@ class test_m2m(ImporterCase):
name = lambda record: dict(record.name_get())[record.id]
- ids, messages = self.import_(['value'], [
+ result = self.import_(['value'], [
['%s,%s' % (name(records[1]), name(records[2]))],
['%s,%s,%s' % (name(records[0]), name(records[1]), name(records[2]))],
['%s,%s' % (name(records[0]), name(records[3]))],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 3)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 3)
b = self.browse()
self.assertEqual(values(b[1].value), [3, 44, 84])
self.assertEqual(values(b[2].value), [3, 9])
def test_nonames(self):
- ids, messages = self.import_(['value'], [['wherethem2mhavenonames']])
- self.assertEqual(messages, [message(
+ result = self.import_(['value'], [['wherethem2mhavenonames']])
+ self.assertEqual(result['messages'], [message(
u"No matching record found for name 'wherethem2mhavenonames' in "
u"field 'unknown'")])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
def test_import_to_existing(self):
M2O_o = self.registry('export.many2many.other')
@@ -744,12 +744,12 @@ class test_m2m(ImporterCase):
id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
xid = 'myxid'
- ids, messages = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id1, id2)]])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
- ids, messages = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id3, id4)]])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ result = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id1, id2)]])
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
+ result = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id3, id4)]])
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
b = self.browse()
self.assertEqual(len(b), 1)
@@ -762,31 +762,31 @@ class test_o2m(ImporterCase):
def test_name_get(self):
s = u'Java is a DSL for taking large XML files and converting them ' \
u'to stack traces'
- ids, messages = self.import_(
+ result = self.import_(
['const', 'value'],
[['5', s]])
- self.assertEqual(messages, [message(
+ self.assertEqual(result['messages'], [message(
u"No matching record found for name '%s' in field 'unknown'" % s)])
- self.assertIs(ids, False)
+ self.assertIs(result['ids'], False)
def test_single(self):
- ids, messages = self.import_(['const', 'value/value'], [
+ result = self.import_(['const', 'value/value'], [
['5', '63']
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
(b,) = self.browse()
self.assertEqual(b.const, 5)
self.assertEqual(values(b.value), [63])
def test_multicore(self):
- ids, messages = self.import_(['const', 'value/value'], [
+ result = self.import_(['const', 'value/value'], [
['5', '63'],
['6', '64'],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 2)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 2)
b1, b2 = self.browse()
self.assertEqual(b1.const, 5)
@@ -795,27 +795,27 @@ class test_o2m(ImporterCase):
self.assertEqual(values(b2.value), [64])
def test_multisub(self):
- ids, messages = self.import_(['const', 'value/value'], [
+ result = self.import_(['const', 'value/value'], [
['5', '63'],
['', '64'],
['', '65'],
['', '66'],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
(b,) = self.browse()
self.assertEqual(values(b.value), [63, 64, 65, 66])
def test_multi_subfields(self):
- ids, messages = self.import_(['value/str', 'const', 'value/value'], [
+ result = self.import_(['value/str', 'const', 'value/value'], [
['this', '5', '63'],
['is', '', '64'],
['the', '', '65'],
['rhythm', '', '66'],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
(b,) = self.browse()
self.assertEqual(values(b.value), [63, 64, 65, 66])
@@ -833,11 +833,11 @@ class test_o2m(ImporterCase):
'str': 'Me', 'value': 262
})
- ids, messages = self.import_(['const', 'value/.id'], [
+ result = self.import_(['const', 'value/.id'], [
['42', '%d,%d' % (id1, id2)]
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
[b] = self.browse()
self.assertEqual(b.const, 42)
@@ -856,12 +856,12 @@ class test_o2m(ImporterCase):
'str': 'Me', 'value': 262
})
- ids, messages = self.import_(['const', 'value/.id'], [
+ result = self.import_(['const', 'value/.id'], [
['42', str(id1)],
['', str(id2)],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
[b] = self.browse()
self.assertEqual(b.const, 42)
@@ -878,12 +878,12 @@ class test_o2m(ImporterCase):
'str': 'Me', 'value': 262
})
- ids, messages = self.import_(['const', 'value/.id', 'value/value'], [
+ result = self.import_(['const', 'value/.id', 'value/value'], [
['42', str(id1), '1'],
['', str(id2), '2'],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
[b] = self.browse()
self.assertEqual(b.const, 42)
@@ -894,21 +894,21 @@ class test_o2m_multiple(ImporterCase):
model_name = 'export.one2many.multiple'
def test_multi_mixed(self):
- ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
+ result = self.import_(['const', 'child1/value', 'child2/value'], [
['5', '11', '21'],
['', '12', '22'],
['', '13', '23'],
['', '14', ''],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
# Oh yeah, that's the stuff
[b] = self.browse()
self.assertEqual(values(b.child1), [11, 12, 13, 14])
self.assertEqual(values(b.child2), [21, 22, 23])
def test_multi(self):
- ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
+ result = self.import_(['const', 'child1/value', 'child2/value'], [
['5', '11', '21'],
['', '12', ''],
['', '13', ''],
@@ -916,15 +916,15 @@ class test_o2m_multiple(ImporterCase):
['', '', '22'],
['', '', '23'],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
[b] = self.browse()
self.assertEqual(values(b.child1), [11, 12, 13, 14])
self.assertEqual(values(b.child2), [21, 22, 23])
def test_multi_fullsplit(self):
- ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
+ result = self.import_(['const', 'child1/value', 'child2/value'], [
['5', '11', ''],
['', '12', ''],
['', '13', ''],
@@ -933,8 +933,8 @@ class test_o2m_multiple(ImporterCase):
['', '', '22'],
['', '', '23'],
])
- self.assertFalse(messages)
- self.assertEqual(len(ids), 1)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
[b] = self.browse()
self.assertEqual(b.const, 5)
From e6c8f1739a70ba8c0252ed8ace839c30f7e794dc Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Tue, 25 Sep 2012 09:42:56 +0200
Subject: [PATCH 014/171] [ADD] 'more info' action to m2o, o2m and m2m linking
failures
bzr revid: xmo@openerp.com-20120925074256-18puerjbfo3om265
---
openerp/addons/base/ir/ir_fields.py | 31 +++++++-------
.../addons/test_impex/tests/test_load.py | 42 +++++++++----------
2 files changed, 38 insertions(+), 35 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 2256542533b..cec74e8976e 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -201,6 +201,21 @@ class ir_fields_converter(orm.Model):
id, _name = ids[0]
else:
raise Exception(u"Unknown sub-field '%s'" % subfield)
+
+ if id is None:
+ raise ValueError(
+ _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'")
+ % {'field_type': field_type, 'value': value}, {
+ 'moreinfo': {
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ 'res_model': column._obj,
+ 'view_mode': 'tree,form',
+ 'view_type': 'form',
+ 'views': [(False, 'tree', (False, 'form'))],
+ 'help': _(u"See all possible values")
+ }
+ })
return id, field_type
def _referencing_subfield(self, record):
@@ -235,12 +250,8 @@ class ir_fields_converter(orm.Model):
reference = record[subfield]
id, subfield_type = self.db_id_for(
cr, uid, model, column, subfield, reference, context=context)
-
- if id is None:
- raise ValueError(
- _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'")
- % {'field_type': subfield_type, 'value': reference})
return id
+
def _str_to_many2many(self, cr, uid, model, column, value, context=None):
[record] = value
@@ -250,13 +261,9 @@ class ir_fields_converter(orm.Model):
for reference in record[subfield].split(','):
id, subfield_type = self.db_id_for(
cr, uid, model, column, subfield, reference, context=context)
- if id is None:
- raise ValueError(
- _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'")
- % {'field_type': subfield_type, 'value': reference})
ids.append(id)
-
return [(6, 0, ids)]
+
def _str_to_one2many(self, cr, uid, model, column, records, context=None):
commands = []
@@ -278,10 +285,6 @@ class ir_fields_converter(orm.Model):
reference = record[subfield]
id, subfield_type = self.db_id_for(
cr, uid, model, column, subfield, reference, context=context)
- if id is None:
- raise ValueError(
- _(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'")
- % {'field_type': subfield_type, 'value': reference})
writable = exclude_ref_fields(record)
if id:
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index 060b32c48f5..f625ecb7043 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -9,18 +9,16 @@ def message(msg, type='error', from_=0, to_=0, record=0, field='value', **kwargs
return dict(kwargs,
type=type, rows={'from': from_, 'to': to_}, record=record,
field=field, message=msg)
-
-def error(row, message, record=None, **kwargs):
- """ Failed import of the record ``record`` at line ``row``, with the error
- message ``message``
-
- :param str message:
- :param dict record:
- """
- return (
- -1, dict(record or {}, **kwargs),
- "Line %d : %s" % (row, message),
- '')
+def moreaction(model):
+ return {
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ 'res_model': model,
+ 'view_mode': 'tree,form',
+ 'view_type': 'form',
+ 'views': [(False, 'tree', (False, 'form'))],
+ 'help': u"See all possible values"
+ }
def values(seq, field='value'):
return [item[field] for item in seq]
@@ -596,7 +594,8 @@ class test_m2o(ImporterCase):
])
self.assertEqual(result['messages'], [
message(u"No matching record found for name '%s' in field 'unknown'" % id,
- from_=index, to_=index, record=index)
+ from_=index, to_=index, record=index,
+ moreinfo=moreaction('export.integer'))
for index, id in enumerate([integer_id1, integer_id2, integer_id1])])
self.assertIs(result['ids'], False)
@@ -614,19 +613,19 @@ class test_m2o(ImporterCase):
result = self.import_(['value'], [['nameisnoexist:3']])
self.assertEqual(result['messages'], [message(
u"No matching record found for name 'nameisnoexist:3' "
- u"in field 'unknown'")])
+ u"in field 'unknown'", moreinfo=moreaction('export.integer'))])
self.assertIs(result['ids'], False)
result = self.import_(['value/id'], [['noxidhere']])
self.assertEqual(result['messages'], [message(
u"No matching record found for external id 'noxidhere' "
- u"in field 'unknown'")])
+ u"in field 'unknown'", moreinfo=moreaction('export.integer'))])
self.assertIs(result['ids'], False)
result = self.import_(['value/.id'], [['66']])
self.assertEqual(result['messages'], [message(
u"No matching record found for database id '66' "
- u"in field 'unknown'")])
+ u"in field 'unknown'", moreinfo=moreaction('export.integer'))])
self.assertIs(result['ids'], False)
def test_fail_multiple(self):
@@ -678,7 +677,7 @@ class test_m2m(ImporterCase):
result = self.import_(['value/.id'], [['42']])
self.assertEqual(result['messages'], [message(
u"No matching record found for database id '42' in field "
- u"'unknown'")])
+ u"'unknown'", moreinfo=moreaction('export.many2many.other'))])
self.assertIs(result['ids'], False)
def test_xids(self):
@@ -703,8 +702,8 @@ class test_m2m(ImporterCase):
def test_noxids(self):
result = self.import_(['value/id'], [['noxidforthat']])
self.assertEqual(result['messages'], [message(
- u"No matching record found for external id 'noxidforthat' "
- u"in field 'unknown'")])
+ u"No matching record found for external id 'noxidforthat' in field"
+ u" 'unknown'", moreinfo=moreaction('export.many2many.other'))])
self.assertIs(result['ids'], False)
def test_names(self):
@@ -733,7 +732,7 @@ class test_m2m(ImporterCase):
result = self.import_(['value'], [['wherethem2mhavenonames']])
self.assertEqual(result['messages'], [message(
u"No matching record found for name 'wherethem2mhavenonames' in "
- u"field 'unknown'")])
+ u"field 'unknown'", moreinfo=moreaction('export.many2many.other'))])
self.assertIs(result['ids'], False)
def test_import_to_existing(self):
@@ -766,7 +765,8 @@ class test_o2m(ImporterCase):
['const', 'value'],
[['5', s]])
self.assertEqual(result['messages'], [message(
- u"No matching record found for name '%s' in field 'unknown'" % s)])
+ u"No matching record found for name '%s' in field 'unknown'" % s,
+ moreinfo=moreaction('export.one2many.child'))])
self.assertIs(result['ids'], False)
def test_single(self):
From 359b4a44aa2d10cac6a0ce9bd623ac6b4e1a17d7 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Tue, 25 Sep 2012 12:02:32 +0200
Subject: [PATCH 015/171] [ADD] ability to convert postgres error messages to
human-readable ones
also convert 'violates not-null constraint' to something about fields being required
bzr revid: xmo@openerp.com-20120925100232-bfmxcxda65cki5kv
---
openerp/osv/orm.py | 31 ++++++++++++++++++-
openerp/tests/addons/test_impex/models.py | 1 +
.../addons/test_impex/tests/test_load.py | 15 +++++++++
3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index b824be91b96..25974760bdd 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -42,6 +42,7 @@
"""
import calendar
+import collections
import copy
import datetime
import itertools
@@ -1493,6 +1494,7 @@ class BaseModel(object):
fields = map(fix_import_export_id_paths, fields)
ModelData = self.pool['ir.model.data']
+ fg = self.fields_get(cr, uid, context=context)
mode = 'init'
current_module = ''
@@ -1509,11 +1511,16 @@ class BaseModel(object):
current_module, record, mode=mode, xml_id=xid,
noupdate=noupdate, res_id=id, context=context))
cr.execute('RELEASE SAVEPOINT model_load_save')
+ except psycopg2.Warning, e:
+ cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
+ messages.append(dict(info, type='warning', message=str(e)))
except psycopg2.Error, e:
# Failed to write, log to messages, rollback savepoint (to
# avoid broken transaction) and keep going
cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
- messages.append(dict(info, type="error", message=str(e)))
+ messages.append(dict(
+ info, type="error",
+ **PGERROR_TO_OE[e.pgcode](self, fg, info, e)))
if any(message['type'] == 'error' for message in messages):
cr.execute('ROLLBACK TO SAVEPOINT model_load')
ids = False
@@ -5390,4 +5397,26 @@ class ImportWarning(Warning):
""" Used to send warnings upwards the stack during the import process
"""
pass
+
+
+def convert_pgerror_23502(model, fields, info, e):
+ m = re.match(r'^null value in column "(?P\w+)" violates '
+ r'not-null constraint\n$',
+ str(e))
+ if not m or m.group('field') not in fields:
+ return {'message': unicode(e)}
+ field = fields[m.group('field')]
+ return {
+ 'message': _(u"Missing required value for the field '%(field)s'") % {
+ 'field': field['string']
+ },
+ 'field': m.group('field'),
+ }
+
+PGERROR_TO_OE = collections.defaultdict(
+ # shape of mapped converters
+ lambda: (lambda model, fvg, info, pgerror: {'message': unicode(pgerror)}), {
+ # not_null_violation
+ '23502': convert_pgerror_23502,
+})
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/openerp/tests/addons/test_impex/models.py b/openerp/tests/addons/test_impex/models.py
index 37894ccb78c..c56ddc649e2 100644
--- a/openerp/tests/addons/test_impex/models.py
+++ b/openerp/tests/addons/test_impex/models.py
@@ -17,6 +17,7 @@ models = [
('float', fields.float()),
('decimal', fields.float(digits=(16, 3))),
('string.bounded', fields.char('unknown', size=16)),
+ ('string.required', fields.char('unknown', size=None, required=True)),
('string', fields.char('unknown', size=None)),
('date', fields.date()),
('datetime', fields.datetime()),
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index f625ecb7043..eb777a57988 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -388,6 +388,21 @@ class test_unbound_string_field(ImporterCase):
u"If they ask you about fun, you tell them – fun is a filthy parasite"
], values(self.read()))
+class test_required_string_field(ImporterCase):
+ model_name = 'export.string.required'
+
+ def test_empty(self):
+ result = self.import_(['value'], [[]])
+ self.assertEqual(result['messages'], [message(
+ u"Missing required value for the field 'unknown'")])
+ self.assertIs(result['ids'], False)
+
+ def test_not_provided(self):
+ result = self.import_(['const'], [['12']])
+ self.assertEqual(result['messages'], [message(
+ u"Missing required value for the field 'unknown'")])
+ self.assertIs(result['ids'], False)
+
class test_text(ImporterCase):
model_name = 'export.text'
From d5c69fa87e9d17c92c00347af73fce53fb47dcd4 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Tue, 25 Sep 2012 15:59:55 +0200
Subject: [PATCH 016/171] [FIX] use lists instead of iterators in
BaseModel._extract_records
* although it does use an explicit external index, it turns out the
code is less complex
* the rewrapping of (many) iterators on top of one another ended up
blowing Python's stack during ``next`` calls, which Python does
*not* like
* added a 900-ish import test file to check for these things
bzr revid: xmo@openerp.com-20120925135955-oielhopegnefyctm
---
openerp/addons/base/ir/ir_fields.py | 5 +-
openerp/osv/orm.py | 53 +++++--------------
.../addons/test_impex/tests/test_load.py | 13 +++++
3 files changed, 30 insertions(+), 41 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index cec74e8976e..03d95fc67a6 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -69,7 +69,7 @@ class ir_fields_converter(orm.Model):
"""
# FIXME: return None
converter = getattr(
- self, '_%s_to_%s' % (fromtype.__name__, column._type))
+ self, '_%s_to_%s' % (fromtype.__name__, column._type), None)
if not converter: return None
return functools.partial(
@@ -113,6 +113,9 @@ class ir_fields_converter(orm.Model):
def _str_to_text(self, cr, uid, model, column, value, context=None):
return value or False
+ def _str_to_binary(self, cr, uid, model, column, value, context=None):
+ return value or False
+
def _get_translations(self, cr, uid, types, src, context):
types = tuple(types)
# Cache translations so they don't have to be reloaded from scratch on
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index 25974760bdd..eb7745b2f6e 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -1527,7 +1527,7 @@ class BaseModel(object):
return {'ids': ids, 'messages': messages}
def _extract_records(self, cr, uid, fields_, data,
context=None, log=lambda a: None):
- """ Generates record dicts from the data iterable.
+ """ Generates record dicts from the data sequence.
The result is a generator of dicts mapping field names to raw
(unconverted, unvalidated) values.
@@ -1562,12 +1562,11 @@ class BaseModel(object):
def only_o2m_values(row, f=get_nono2m_values, g=get_o2m_values):
return any(g(row)) and not any(f(row))
- rows = CountingStream(data)
+ index = 0
while True:
- row = next(rows, None)
- if row is None: return
- record_row_index = rows.index
+ if index >= len(data): return
+ row = data[index]
# copy non-relational fields to record dict
record = dict((field[0], value)
for field, value in itertools.izip(fields_, row)
@@ -1575,10 +1574,10 @@ class BaseModel(object):
# Get all following rows which have relational values attached to
# the current record (no non-relational values)
- # WARNING: replaces existing ``rows``
- record_span, _rows = span(only_o2m_values, rows)
+ record_span = itertools.takewhile(
+ only_o2m_values, itertools.islice(data, index + 1, None))
# stitch record row back on for relational fields
- record_span = itertools.chain([row], record_span)
+ record_span = list(itertools.chain([row], record_span))
for relfield in set(
field[0] for field in fields_
if is_relational(field[0])):
@@ -1586,8 +1585,6 @@ class BaseModel(object):
# FIXME: how to not use _obj without relying on fields_get?
Model = self.pool[column._obj]
- # copy stream to reuse for next relational field
- fieldrows, record_span = itertools.tee(record_span)
# get only cells for this sub-field, should be strictly
# non-empty, field path [None] is for name_get column
indices, subfields = zip(*((index, field[1:] or [None])
@@ -1596,26 +1593,17 @@ class BaseModel(object):
# return all rows which have at least one value for the
# subfields of relfield
- relfield_data = filter(any, map(itemgetter_tuple(indices), fieldrows))
+ relfield_data = filter(any, map(itemgetter_tuple(indices), record_span))
record[relfield] = [subrecord
for subrecord, _subinfo in Model._extract_records(
cr, uid, subfields, relfield_data,
context=context, log=log)]
- # Ensure full consumption of the span (and therefore advancement of
- # ``rows``) even if there are no relational fields. Needs two as
- # the code above stiched the row back on (so first call may only
- # get the stiched row without advancing the underlying operator row
- # itself)
- next(record_span, None)
- next(record_span, None)
- # old rows consumption (by iterating the span) should be done here,
- # at this point the old ``rows`` is 1 past `span` (either on the
- # next record row or past ``StopIteration``, so wrap new ``rows``
- # (``_rows``) in a counting stream indexed 1-before the old
- # ``rows``
- rows = CountingStream(_rows, rows.index - 1)
- yield record, {'rows': {'from': record_row_index,'to': rows.index}}
+ yield record, {'rows': {
+ 'from': index,
+ 'to': index + len(record_span) - 1
+ }}
+ index += len(record_span)
def _convert_records(self, cr, uid, records,
context=None, log=lambda a: None):
""" Converts records from the source iterable (recursive dicts of
@@ -5369,21 +5357,6 @@ class AbstractModel(BaseModel):
_auto = False # don't create any database backend for AbstractModels
_register = False # not visible in ORM registry, meant to be python-inherited only
-def span(predicate, iterable):
- """ Splits the iterable between the longest prefix of ``iterable`` whose
- elements satisfy ``predicate`` and the rest.
-
- If called with a list, equivalent to::
-
- takewhile(predicate, lst), dropwhile(predicate, lst)
-
- :param callable predicate:
- :param iterable:
- :rtype: (iterable, iterable)
- """
- it1, it2 = itertools.tee(iterable)
- return (itertools.takewhile(predicate, it1),
- itertools.dropwhile(predicate, it2))
def itemgetter_tuple(items):
""" Fixes itemgetter inconsistency (useful in some cases) of not returning
a tuple if len(items) == 1: always returns an n-tuple where n = len(items)
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index eb777a57988..72442963af5 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
+import json
+import pkgutil
+
import openerp.modules.registry
import openerp
@@ -956,5 +959,15 @@ class test_o2m_multiple(ImporterCase):
self.assertEqual(values(b.child1), [11, 12, 13, 14])
self.assertEqual(values(b.child2), [21, 22, 23])
+class test_realworld(common.TransactionCase):
+ def test_bigfile(self):
+ data = json.loads(pkgutil.get_data(self.__module__, 'contacts_big.json'))
+ result = self.registry('res.partner').load(
+ self.cr, openerp.SUPERUSER_ID,
+ ['name', 'mobile', 'email', 'image'],
+ data)
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), len(data))
+
# function, related, reference: written to db as-is...
# => function uses @type for value coercion/conversion
From e61dc509341ed2cd1222869048a81b2db209e21d Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Tue, 25 Sep 2012 17:59:15 +0200
Subject: [PATCH 017/171] [IMP] convert empty import fields to False values
without going through converters
simplifies the converter methods by avoiding redundant emptiness checks
bzr revid: xmo@openerp.com-20120925155915-82p2s6stpww37p5n
---
openerp/addons/base/ir/ir_fields.py | 8 +++-----
openerp/osv/orm.py | 4 +++-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 03d95fc67a6..621dd93d469 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -100,21 +100,19 @@ class ir_fields_converter(orm.Model):
return True
def _str_to_integer(self, cr, uid, model, column, value, context=None):
- if not value: return False
return int(value)
def _str_to_float(self, cr, uid, model, column, value, context=None):
- if not value: return False
return float(value)
def _str_to_char(self, cr, uid, model, column, value, context=None):
- return value or False
+ return value
def _str_to_text(self, cr, uid, model, column, value, context=None):
- return value or False
+ return value
def _str_to_binary(self, cr, uid, model, column, value, context=None):
- return value or False
+ return value
def _get_translations(self, cr, uid, types, src, context):
types = tuple(types)
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index eb7745b2f6e..81063deb180 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -68,7 +68,6 @@ from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
from query import Query
-from openerp import SUPERUSER_ID
_logger = logging.getLogger(__name__)
_schema = logging.getLogger(__name__ + '.schema')
@@ -1662,6 +1661,9 @@ class BaseModel(object):
for field, strvalue in record.iteritems():
if field in (None, 'id', '.id'): continue
+ if not strvalue:
+ converted[field] = False
+ continue
# In warnings and error messages, use translated string as
# field name
From a912bb31890a9d1d81f8b267e2ba2e0d0ca53dbe Mon Sep 17 00:00:00 2001
From: Saurang Suthar
Date: Wed, 26 Sep 2012 12:33:39 +0530
Subject: [PATCH 018/171] [IMP]openerp:rename the group Partner Manager ->
Contact Creation
bzr revid: ssu@tinyerp.com-20120926070339-sr9lv02l5632ml1t
---
openerp/addons/base/res/res_security.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/openerp/addons/base/res/res_security.xml b/openerp/addons/base/res/res_security.xml
index acec903c1a3..783243411ef 100644
--- a/openerp/addons/base/res/res_security.xml
+++ b/openerp/addons/base/res/res_security.xml
@@ -3,7 +3,7 @@
- Partner Manager
+ Contact Creation
CSV File:
From 84332d8aad36c92f91f21e9533974310f15481c6 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 1 Oct 2012 15:05:30 +0200
Subject: [PATCH 037/171] [FIX] type error when providing a non-integer for a
default database id
bzr revid: xmo@openerp.com-20121001130530-yf6pzuxdi3s09tji
---
openerp/addons/base/ir/ir_fields.py | 32 +++++++++++--------
openerp/osv/orm.py | 12 +++++--
.../addons/test_impex/tests/test_load.py | 10 ++++++
3 files changed, 38 insertions(+), 16 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 7a4c34c7f30..c7012525961 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -2,6 +2,7 @@
import functools
import operator
import itertools
+import psycopg2
from openerp.osv import orm, fields
from openerp.tools.translate import _
@@ -179,14 +180,27 @@ class ir_fields_converter(orm.Model):
if context is None: context = {}
id = None
warnings = []
+ extras = {'moreinfo': {
+ 'type': 'ir.actions.act_window', 'target': 'new',
+ 'res_model': column._obj, 'view_mode': 'tree,form',
+ 'view_type': 'form',
+ 'views': [(False, 'tree', (False, 'form'))],
+ 'help': _(u"See all possible values")
+ }}
RelatedModel = self.pool[column._obj]
if subfield == '.id':
field_type = _(u"database id")
try: tentative_id = int(value)
except ValueError: tentative_id = value
- if RelatedModel.search(cr, uid, [('id', '=', tentative_id)],
- context=context):
- id = tentative_id
+ try:
+ if RelatedModel.search(cr, uid, [('id', '=', tentative_id)],
+ context=context):
+ id = tentative_id
+ except psycopg2.DataError:
+ # type error
+ raise ValueError(
+ _(u"Invalid database id '%s' for the field '%%(field)s'") % value,
+ extras)
elif subfield == 'id':
field_type = _(u"external id")
if '.' in value:
@@ -217,17 +231,7 @@ class ir_fields_converter(orm.Model):
if id is None:
raise ValueError(
_(u"No matching record found for %(field_type)s '%(value)s' in field '%%(field)s'")
- % {'field_type': field_type, 'value': value}, {
- 'moreinfo': {
- 'type': 'ir.actions.act_window',
- 'target': 'new',
- 'res_model': column._obj,
- 'view_mode': 'tree,form',
- 'view_type': 'form',
- 'views': [(False, 'tree', (False, 'form'))],
- 'help': _(u"See all possible values")
- }
- })
+ % {'field_type': field_type, 'value': value}, extras)
return id, field_type, warnings
def _referencing_subfield(self, record):
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index da0c93762bc..9a25e621023 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -1335,7 +1335,15 @@ class BaseModel(object):
self._extract_records(cr, uid, fields, data,
context=context, log=messages.append),
context=context, log=messages.append):
- cr.execute('SAVEPOINT model_load_save')
+ try:
+ cr.execute('SAVEPOINT model_load_save')
+ except psycopg2.InternalError, e:
+ # broken transaction, exit and hope the source error was
+ # already logged
+ if not any(message['type'] == 'error' for message in messages):
+ messages.append(dict(info, type='error',message=
+ u"Unknown database error: '%s'" % e))
+ break
try:
ids.append(ModelData._update(cr, uid, self._name,
current_module, record, mode=mode, xml_id=xid,
@@ -1349,7 +1357,7 @@ class BaseModel(object):
# avoid broken transaction) and keep going
cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
messages.append(dict(
- info, type="error",
+ info, type='error',
**PGERROR_TO_OE[e.pgcode](self, fg, info, e)))
if any(message['type'] == 'error' for message in messages):
cr.execute('ROLLBACK TO SAVEPOINT model_load')
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index c141e62b65d..074b75a9fb3 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -619,6 +619,16 @@ class test_m2o(ImporterCase):
for index, id in enumerate([integer_id1, integer_id2, integer_id1])])
self.assertIs(result['ids'], False)
+ @mute_logger('openerp.sql_db')
+ def test_fail_id_mistype(self):
+ result = self.import_(['value/.id'], [["foo"]])
+
+ self.assertEqual(result['messages'], [
+ message(u"Invalid database id 'foo' for the field 'unknown'",
+ moreinfo=moreaction('export.integer'))
+ ])
+ self.assertIs(result['ids'], False)
+
def test_sub_field(self):
""" Does not implicitly create the record, does not warn that you can't
import m2o subfields (at all)...
From aed20ca5d7a19fb5497c65245f5a801723c2c91e Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 1 Oct 2012 15:43:30 +0200
Subject: [PATCH 038/171] [FIX] conversion and validation of date and datetime
field imports
bzr revid: xmo@openerp.com-20121001134330-za8hqctrghmw08i4
---
openerp/addons/base/ir/ir_fields.py | 24 +++++++--
.../addons/test_impex/tests/test_load.py | 49 ++++++++++++++++---
2 files changed, 61 insertions(+), 12 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index c7012525961..417fbc9b4db 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -3,8 +3,11 @@ import functools
import operator
import itertools
import psycopg2
+import time
from openerp.osv import orm, fields
from openerp.tools.translate import _
+from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT,\
+ DEFAULT_SERVER_DATETIME_FORMAT
REFERENCING_FIELDS = set([None, 'id', '.id'])
def only_ref_fields(record):
@@ -114,14 +117,25 @@ class ir_fields_converter(orm.Model):
_(u"'%s' does not seem to be a number for field '%%(field)s'")
% value)
- def _str_to_char(self, cr, uid, model, column, value, context=None):
+ def _str_id(self, cr, uid, model, column, value, context=None):
return value, []
+ _str_to_char = _str_to_text = _str_to_binary = _str_id
- def _str_to_text(self, cr, uid, model, column, value, context=None):
- return value, []
+ def _str_to_date(self, cr, uid, model, column, value, context=None):
+ try:
+ time.strptime(value, DEFAULT_SERVER_DATE_FORMAT)
+ return value, []
+ except ValueError:
+ raise ValueError(
+ _(u"'%s' does not seem to be a valid date for field '%%(field)s'") % value)
- def _str_to_binary(self, cr, uid, model, column, value, context=None):
- return value, []
+ def _str_to_datetime(self, cr, uid, model, column, value, context=None):
+ try:
+ time.strptime(value, DEFAULT_SERVER_DATETIME_FORMAT)
+ return value, []
+ except ValueError:
+ raise ValueError(
+ _(u"'%s' does not seem to be a valid datetime for field '%%(field)s'") % value)
def _get_translations(self, cr, uid, types, src, context):
types = tuple(types)
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index 074b75a9fb3..7657709d24a 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -339,13 +339,8 @@ class test_float_field(ImporterCase):
def test_nonsense(self):
result = self.import_(['value'], [['foobar']])
self.assertIs(result['ids'], False)
- self.assertEqual(result['messages'], [{
- 'type': 'error',
- 'rows': {'from': 0, 'to': 0},
- 'record': 0,
- 'field': 'value',
- 'message': u"'foobar' does not seem to be a number for field 'unknown'",
- }])
+ self.assertEqual(result['messages'], [
+ message(u"'foobar' does not seem to be a number for field 'unknown'")])
class test_string_field(ImporterCase):
model_name = 'export.string.bounded'
@@ -981,5 +976,45 @@ class test_realworld(common.TransactionCase):
self.assertFalse(result['messages'])
self.assertEqual(len(result['ids']), len(data))
+class test_date(ImporterCase):
+ model_name = 'export.date'
+
+ def test_empty(self):
+ self.assertEqual(
+ self.import_(['value'], []),
+ {'ids': [], 'messages': []})
+
+ def test_basic(self):
+ result = self.import_(['value'], [['2012-02-03']])
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
+
+ def test_invalid(self):
+ result = self.import_(['value'], [['not really a date']])
+ self.assertEqual(result['messages'], [
+ message(u"'not really a date' does not seem to be a valid date "
+ u"for field 'unknown'")])
+ self.assertIs(result['ids'], False)
+
+class test_datetime(ImporterCase):
+ model_name = 'export.datetime'
+
+ def test_empty(self):
+ self.assertEqual(
+ self.import_(['value'], []),
+ {'ids': [], 'messages': []})
+
+ def test_basic(self):
+ result = self.import_(['value'], [['2012-02-03 11:11:11']])
+ self.assertFalse(result['messages'])
+ self.assertEqual(len(result['ids']), 1)
+
+ def test_invalid(self):
+ result = self.import_(['value'], [['not really a datetime']])
+ self.assertEqual(result['messages'], [
+ message(u"'not really a datetime' does not seem to be a valid "
+ u"datetime for field 'unknown'")])
+ self.assertIs(result['ids'], False)
+
# function, related, reference: written to db as-is...
# => function uses @type for value coercion/conversion
From a7a8104623fa868e65265b54c826c0dd828c1663 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 1 Oct 2012 15:52:17 +0200
Subject: [PATCH 039/171] [IMP] base_import: typo in field name for row number
offset
bzr revid: xmo@openerp.com-20121001135217-0ao29ldft17d52ur
---
addons/base_import/static/src/js/import.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js
index 2a7e6f18d8a..80f72a14f5b 100644
--- a/addons/base_import/static/src/js/import.js
+++ b/addons/base_import/static/src/js/import.js
@@ -318,7 +318,7 @@ openerp.base_import = function (instance) {
// display 1-indexed.
var offset = 1;
// offset more if header
- if (this.import_options().header) { offset += 1; }
+ if (this.import_options().headers) { offset += 1; }
this.$el.addClass('oe_import_error');
this.$('.oe_import_error_report').html(
From 89be614ea3159be3879fbd4e0dd477a8d94e596c Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 1 Oct 2012 16:06:22 +0200
Subject: [PATCH 040/171] [ADD] base_import: info message when everything looks
ok after a validation
bzr revid: xmo@openerp.com-20121001140622-v63opfo97mmxf3sr
---
addons/base_import/static/src/css/import.css | 3 +++
addons/base_import/static/src/js/import.js | 6 ++++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/addons/base_import/static/src/css/import.css b/addons/base_import/static/src/css/import.css
index da61473fdba..25678cbe98a 100644
--- a/addons/base_import/static/src/css/import.css
+++ b/addons/base_import/static/src/css/import.css
@@ -31,6 +31,9 @@
.oe_import .oe_import_error_report ul .oe_import_report_warning {
background-color: #FEFFD9;
}
+.oe_import .oe_import_error_report ul .oe_import_report_info {
+ background-color: #d3ffd3;
+}
.oe_import .oe_import_noheaders {
color: #888;
diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js
index 80f72a14f5b..90995027021 100644
--- a/addons/base_import/static/src/js/import.js
+++ b/addons/base_import/static/src/js/import.js
@@ -311,8 +311,10 @@ openerp.base_import = function (instance) {
},
render_import_result: function (message) {
if (_.isEmpty(message)) {
- this.$el.removeClass('oe_import_error');
- return;
+ message.push({
+ type: 'info',
+ message: _t("Everything seems valid.")
+ });
}
// row indexes come back 0-indexed, spreadsheets
// display 1-indexed.
From 771fae90d7f1435eebe682a7dbfa49ac764de436 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Mon, 1 Oct 2012 16:22:27 +0200
Subject: [PATCH 041/171] [IMP] base_import: better warnings when the file
parsing has very likely failed
bzr revid: xmo@openerp.com-20121001142227-v1iypgjgfcq4pgo7
---
addons/base_import/static/src/js/import.js | 14 ++++++++++++--
addons/base_import/static/src/xml/import.xml | 3 ++-
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js
index 90995027021..0ea74e43755 100644
--- a/addons/base_import/static/src/js/import.js
+++ b/addons/base_import/static/src/js/import.js
@@ -171,14 +171,24 @@ openerp.base_import = function (instance) {
'oe_import_noheaders',
!this.$('input.oe_import_has_header').prop('checked'));
if (result.error) {
+ this.$('.oe_import_options').show();
this.$el.addClass('oe_import_preview_error oe_import_error');
this.$('.oe_import_error_report').html(
- QWeb.render('ImportView.preview.error', result));
+ QWeb.render('ImportView.preview.error', result))
+ .get(0).scrollIntoView();
return;
}
this.$el.addClass('oe_import_preview');
this.$('table').html(QWeb.render('ImportView.preview', result));
+ if (result.headers.length === 1) {
+ this.$('.oe_import_options').show();
+ this.render_import_result([{
+ type: 'warning',
+ message: _t("A single column was found in the file, this often means the file separator is incorrect")
+ }]);
+ }
+
var $fields = this.$('.oe_import_fields input');
this.render_fields_matches(result, $fields);
var data = this.generate_fields_completion(result);
@@ -365,7 +375,7 @@ openerp.base_import = function (instance) {
''
].join('')
},
- }));
+ })).get(0).scrollIntoView();
},
});
};
diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml
index 77c3d7d6ce5..e11cce26b80 100644
--- a/addons/base_import/static/src/xml/import.xml
+++ b/addons/base_import/static/src/xml/import.xml
@@ -82,7 +82,8 @@
- Import preview failed due to:
+ Import preview failed due to: . The issue is
+ usually an incorrect file encoding.
Here is the start of the file we could not import:
From a1d2dedaed9748d09e7bca21a0188cc8c625effc Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Tue, 2 Oct 2012 23:33:49 +0530
Subject: [PATCH 042/171] [IMP]: Use display_address() in company header.
bzr revid: atp@tinyerp.com-20121002180349-bxq8n10gfa1yea6g
---
openerp/addons/base/res/res_company.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py
index 5095cc8b1a4..81e757550ae 100644
--- a/openerp/addons/base/res/res_company.py
+++ b/openerp/addons/base/res/res_company.py
@@ -303,8 +303,7 @@ class res_company(osv.osv):
1.3cm %s 20cm %s
[[ company.rml_header1 ]]
[[ company.partner_id.name ]]
- [[ company.partner_id.street or '' ]]
- [[ company.partner_id.city or '' ]] - [[ company.partner_id.country_id and company.partner_id.country_id.name or '']]
+ [[ display_address(company.partner_id) or '' ]]
Phone:
[[ company.partner_id.phone or '' ]]
Mail:
@@ -328,8 +327,8 @@ class res_company(osv.osv):
"""
- _header_a4 = _header_main % ('23.0cm', '27.6cm', '27.7cm', '27.7cm', '27.8cm', '27.2cm', '26.8cm', '26.4cm', '26.0cm', '26.0cm', '25.6cm', '25.6cm', '25.5cm', '25.5cm')
- _header_letter = _header_main % ('21.3cm', '25.9cm', '26.0cm', '26.0cm', '26.1cm', '25.5cm', '25.1cm', '24.7cm', '24.3cm', '24.3cm', '23.9cm', '23.9cm', '23.8cm', '23.8cm')
+ _header_a4 = _header_main % ('23.0cm', '27.6cm', '27.7cm', '27.7cm', '27.8cm', '27.2cm', '26.8cm', '26.0cm', '26.0cm', '25.6cm', '25.6cm', '25.5cm', '25.5cm')
+ _header_letter = _header_main % ('21.3cm', '25.9cm', '26.0cm', '26.0cm', '26.1cm', '25.5cm', '25.1cm', '24.3cm', '24.3cm', '23.9cm', '23.9cm', '23.8cm', '23.8cm')
def onchange_paper_format(self, cr, uid, ids, paper_format, context=None):
if paper_format == 'us_letter':
From b9b19f61eab893ea27f16dcdf5c15621bf0c7636 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Wed, 3 Oct 2012 13:59:49 +0200
Subject: [PATCH 043/171] [FIX] if a selection label is empty, return the value
in a selection import message
bzr revid: xmo@openerp.com-20121003115949-sgsouhcmboascjbl
---
openerp/addons/base/ir/ir_fields.py | 3 ++-
openerp/tests/addons/test_impex/models.py | 2 +-
openerp/tests/addons/test_impex/tests/test_load.py | 4 ++--
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py
index 417fbc9b4db..65d4a786178 100644
--- a/openerp/addons/base/ir/ir_fields.py
+++ b/openerp/addons/base/ir/ir_fields.py
@@ -168,7 +168,8 @@ class ir_fields_converter(orm.Model):
raise ValueError(
_(u"Value '%s' not found in selection field '%%(field)s'") % (
value), {
- 'moreinfo': map(operator.itemgetter(1), selection)
+ 'moreinfo': [label or unicode(item) for item, label in selection
+ if label or item]
})
diff --git a/openerp/tests/addons/test_impex/models.py b/openerp/tests/addons/test_impex/models.py
index c56ddc649e2..3c85b56fff7 100644
--- a/openerp/tests/addons/test_impex/models.py
+++ b/openerp/tests/addons/test_impex/models.py
@@ -22,7 +22,7 @@ models = [
('date', fields.date()),
('datetime', fields.datetime()),
('text', fields.text()),
- ('selection', fields.selection([(1, "Foo"), (2, "Bar"), (3, "Qux")])),
+ ('selection', fields.selection([(1, "Foo"), (2, "Bar"), (3, "Qux"), (4, '')])),
('selection.function', fields.selection(selection_fn)),
# just relate to an integer
('many2one', fields.many2one('export.integer')),
diff --git a/openerp/tests/addons/test_impex/tests/test_load.py b/openerp/tests/addons/test_impex/tests/test_load.py
index 7657709d24a..18b26a16354 100644
--- a/openerp/tests/addons/test_impex/tests/test_load.py
+++ b/openerp/tests/addons/test_impex/tests/test_load.py
@@ -466,13 +466,13 @@ class test_selection(ImporterCase):
self.assertIs(result['ids'], False)
self.assertEqual(result['messages'], [message(
u"Value 'Baz' not found in selection field 'unknown'",
- moreinfo="Foo Bar Qux".split())])
+ moreinfo="Foo Bar Qux 4".split())])
result = self.import_(['value'], [[42]])
self.assertIs(result['ids'], False)
self.assertEqual(result['messages'], [message(
u"Value '42' not found in selection field 'unknown'",
- moreinfo="Foo Bar Qux".split())])
+ moreinfo="Foo Bar Qux 4".split())])
class test_selection_function(ImporterCase):
model_name = 'export.selection.function'
From f6544c801fa070403ce122d47c90644b50d8db58 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Wed, 3 Oct 2012 14:11:37 +0200
Subject: [PATCH 044/171] [IMP] make import into a full-scene client action
* Correctly handle back (via history_back)
* Disable buttons when no file has been loaded yet
* Highlight import when a validation has yield no message
bzr revid: xmo@openerp.com-20121003121137-xo7lu5m5y0s7gyo1
---
addons/base_import/static/src/js/import.js | 74 +++++++++++---------
addons/base_import/static/src/xml/import.xml | 10 +++
2 files changed, 50 insertions(+), 34 deletions(-)
diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js
index 0ea74e43755..dd8b3288de9 100644
--- a/addons/base_import/static/src/js/import.js
+++ b/addons/base_import/static/src/js/import.js
@@ -47,16 +47,23 @@ openerp.base_import = function (instance) {
this._super.apply(this, arguments);
if(add_button) {
this.$buttons.on('click', '.oe_list_button_import', function() {
- new instance.web.DataImport(self, self.dataset).open();
+ self.do_action({
+ type: 'ir.actions.client',
+ tag: 'import',
+ params: {
+ model: self.dataset.model
+ }
+ });
return false;
});
}
}
});
- instance.web.DataImport = instance.web.Dialog.extend({
+ instance.web.client_actions.add(
+ 'import', 'instance.web.DataImport');
+ instance.web.DataImport = instance.web.Widget.extend({
template: 'ImportView',
- dialog_title: _lt("Import Data"),
opts: [
{name: 'encoding', label: _lt("Encoding:"), value: 'utf-8'},
{name: 'separator', label: _lt("Separator:"), value: ','},
@@ -100,41 +107,34 @@ openerp.base_import = function (instance) {
];
});
this.do_action(_.extend(action, {target: 'new'}));
+ },
+ // buttons
+ 'click .oe_import_validate': 'import_dryrun',
+ 'click .oe_import_import': 'do_import',
+ 'click .oe_import_cancel': function (e) {
+ e.preventDefault();
+ this.exit();
}
},
- init: function (parent, dataset) {
- var self = this;
- this._super(parent, {
- buttons: [
- {text: _t("Validate"), click: self.proxy('import_dryrun'),
- 'class': 'oe_import_dialog_button'},
- {text: _t("Import"), click: self.proxy('do_import'),
- 'class': 'oe_import_dialog_button oe_highlight'}
- ]
- });
- this.res_model = parent.model;
+ init: function (parent, params) {
+ this._super.apply(this, arguments);
+ this.res_model = params.model;
// import object id
this.id = null;
this.Import = new instance.web.Model('base_import.import');
},
start: function () {
var self = this;
- return this.Import.call('create', [{
- 'res_model': this.res_model
- }]).then(function (id) {
- self.id = id;
- self.$('input[name=import_id]').val(id);
- });
- },
- open: function () {
- this._super.apply(this, arguments);
- this.$el.dialog('widget').find('.ui-dialog-buttonset')
- .append(_t(" or "))
- .append(
- $('')
- .click(this.proxy('close'))
- .append($('').text(_t("Cancel"))));
- return this;
+
+ return $.when(
+ this._super(),
+ this.Import.call('create', [{
+ 'res_model': this.res_model
+ }]).then(function (id) {
+ self.id = id;
+ self.$('input[name=import_id]').val(id);
+ })
+ )
},
import_options: function () {
@@ -151,6 +151,7 @@ openerp.base_import = function (instance) {
//- File & settings change section
file_update: function (e) {
+ this.$('.oe_import_button').prop('disabled', true);
if (!this.$('input.oe_import_file').val()) { return; }
this.$el.removeClass('oe_import_preview oe_import_error');
@@ -178,6 +179,7 @@ openerp.base_import = function (instance) {
.get(0).scrollIntoView();
return;
}
+ this.$('.oe_import_button').prop('disabled', false);
this.$el.addClass('oe_import_preview');
this.$('table').html(QWeb.render('ImportView.preview', result));
@@ -310,17 +312,21 @@ openerp.base_import = function (instance) {
return this.call_import({ dryrun: false }).then(function (message) {
if (!_.any(message, function (message) {
return message.type === 'error' })) {
- if (self.getParent().reload_content) {
- self.getParent().reload_content();
- }
- self.close();
+ self.exit();
return;
}
self.render_import_result(message);
});
},
+ exit: function () {
+ this.do_action({
+ type: 'ir.actions.client',
+ tag: 'history_back'
+ });
+ },
render_import_result: function (message) {
if (_.isEmpty(message)) {
+ this.$('.oe_import_import').addClass('oe_highlight');
message.push({
type: 'info',
message: _t("Everything seems valid.")
diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml
index e11cce26b80..aab9482ee81 100644
--- a/addons/base_import/static/src/xml/import.xml
+++ b/addons/base_import/static/src/xml/import.xml
@@ -2,6 +2,16 @@
@@ -401,7 +401,7 @@
-
+
diff --git a/addons/project_gtd/project_gtd_view.xml b/addons/project_gtd/project_gtd_view.xml
index fdb8ae8495c..a7026da8854 100644
--- a/addons/project_gtd/project_gtd_view.xml
+++ b/addons/project_gtd/project_gtd_view.xml
@@ -92,8 +92,8 @@
-
-
+
+
diff --git a/addons/project_gtd/wizard/project_gtd_fill_view.xml b/addons/project_gtd/wizard/project_gtd_fill_view.xml
index 8807c00a76b..626dfb699b8 100644
--- a/addons/project_gtd/wizard/project_gtd_fill_view.xml
+++ b/addons/project_gtd/wizard/project_gtd_fill_view.xml
@@ -8,7 +8,7 @@
-
+
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index 5505a6a88b5..0055deb8d3d 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -214,7 +214,7 @@
-
+
@@ -251,7 +251,7 @@
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, False, parent.date_order, False, parent.fiscal_position, True, context)"/>
+ groups="product.group_uom" options='{"no_open": True}'/>
From fe07dc2e6d67c32ebf6aab8e3e32e57f24886c28 Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Tue, 9 Oct 2012 16:51:13 +0200
Subject: [PATCH 121/171] [FIX] Fixed on_switch_mode tirggering.
bzr revid: vta@openerp.com-20121009145113-8sazhfrp3xaan5cq
---
addons/web/static/src/js/view_form.js | 9 ++++--
addons/web/static/src/js/views.js | 32 ++++++++-----------
addons/web_kanban/static/src/js/kanban.js | 4 +--
.../static/src/js/view_editor.js | 4 +--
4 files changed, 23 insertions(+), 26 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index db68b8d7a23..98fd83dadaf 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -3370,10 +3370,13 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
}
def.resolve();
});
- this.viewmanager.on('on_mode_switch',self,function(n_mode, b, c, d, e) {
+ this.viewmanager.on("on_mode_switch", self, function(n_mode, b, c, d, e) {
$.when(self.save_any_view()).then(function() {
- if(n_mode === "list")
- $.async_when().then(function() {self.reload_current_view();});
+ if (n_mode === "list") {
+ $.async_when().then(function() {
+ self.reload_current_view();
+ });
+ }
});
});
this.is_setted.then(function() {
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 18d7e9d5666..e18a3e361be 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -417,7 +417,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
this._super();
var self = this;
this.$el.find('.oe_view_manager_switch a').click(function() {
- self.on_mode_switch($(this).data('view-type'));
+ self.trigger('on_mode_switch', $(this).data('view-type'));
}).tipsy();
var views_ids = {};
_.each(this.views_src, function(view) {
@@ -439,16 +439,12 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
// If no default view defined, switch to the first one in sequence
var default_view = this.flags.default_view || this.views_src[0].view_type;
- return this.on_mode_switch(default_view);
+ this.on('on_mode_switch', self, function(view_type, no_store, view_options) {
+ self.switch_mode(view_type, no_store, view_options);
+ });
+ return this.trigger('on_mode_switch', default_view);
},
- /**
- * Asks the view manager to switch visualization mode.
- *
- * @param {String} view_type type of view to display
- * @param {Boolean} [no_store=false] don't store the view being switched to on the switch stack
- * @returns {jQuery.Deferred} new view loading promise
- */
- on_mode_switch: function(view_type, no_store, view_options) {
+ switch_mode: function(view_type, no_store, view_options) {
var self = this;
var view = this.views[view_type];
var view_promise;
@@ -552,7 +548,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
add_breadcrumb: function(on_reverse_breadcrumb) {
var self = this;
var views = [this.active_view || this.views_src[0].view_type];
- this.on('on_mode_switch',self,function(mode) {
+ this.on('on_mode_switch',self,function(mode) {
var last = views.slice(-1)[0];
if (mode !== last) {
if (mode !== 'form') {
@@ -568,7 +564,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
var view_to_select = views[index];
self.$el.show();
if (self.active_view !== view_to_select) {
- self.on_mode_switch(view_to_select);
+ self.trigger('on_mode_switch', view_to_select);
}
},
get_title: function() {
@@ -604,7 +600,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
* consist to switch to the asked view.
*/
switch_view: function(view_type, no_store, options) {
- return this.on_mode_switch(view_type, no_store, options);
+ return this.trigger('on_mode_switch', view_type, no_store, options);
},
/**
* Returns to the view preceding the caller view in this manager's
@@ -623,12 +619,12 @@ instance.web.ViewManager = instance.web.Widget.extend({
if (options.created && current_view === 'form' && previous_view === 'list') {
// APR special case: "If creation mode from list (and only from a list),
// after saving, go to page view (don't come back in list)"
- return this.on_mode_switch('form');
+ return this.trigger('on_mode_switch', 'form');
} else if (options.created && !previous_view && this.action && this.action.flags.default_view === 'form') {
// APR special case: "If creation from dashboard, we have no previous view
- return this.on_mode_switch('form');
+ return this.trigger('on_mode_switch', 'form');
}
- return this.on_mode_switch(previous_view, true);
+ return this.trigger('on_mode_switch', previous_view, true);
},
/**
* Sets up the current viewmanager's search view.
@@ -897,7 +893,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
}, action || {});
this.do_action(action);
},
- on_mode_switch: function (view_type, no_store, options) {
+ switch_mode: function (view_type, no_store, options) {
var self = this;
return $.when(this._super.apply(this, arguments)).then(function () {
@@ -932,7 +928,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
if (state.view_type && state.view_type !== this.active_view) {
defs.push(
this.views[this.active_view].deferred.pipe(function() {
- return self.on_mode_switch(state.view_type, true);
+ return self.trigger('on_mode_switch', state.view_type, true)
})
);
}
diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js
index 41cc366226f..dae3d7b214d 100644
--- a/addons/web_kanban/static/src/js/kanban.js
+++ b/addons/web_kanban/static/src/js/kanban.js
@@ -194,7 +194,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
});
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
- form.on_button_cancel.add_last(am.dialog.on_close);
+ form.on("on_button_cancel",self,am.dialog.on_close);
form.on_created.add_last(function(r) {
(new instance.web.DataSet(self, self.group_by_field.relation)).name_get([r.result]).then(function(new_record) {
am.dialog.on_close();
@@ -672,7 +672,7 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({
});
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
- form.on_button_cancel.add_last(am.dialog.on_close);
+ form.on("on_button_cancel",self,am.dialog.on_close);
form.on_saved.add_last(function() {
am.dialog.on_close();
self.view.do_reload();
diff --git a/addons/web_view_editor/static/src/js/view_editor.js b/addons/web_view_editor/static/src/js/view_editor.js
index e65f0ab5d38..f26e12a55d7 100644
--- a/addons/web_view_editor/static/src/js/view_editor.js
+++ b/addons/web_view_editor/static/src/js/view_editor.js
@@ -1014,9 +1014,7 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({
var action_manager = new instance.web.ActionManager(self);
$.when(action_manager.do_action(action)).then(function() {
var controller = action_manager.dialog_widget.views['form'].controller;
- controller.on_button_cancel.add_last(function(){
- action_manager.destroy()
- });
+ controller.on("on_button_cancel",self,action_manager.destroy);
controller.do_save.add_last(function(){
action_manager.destroy();
var value =controller.fields.name.get('value');
From 90fc4d66511634b11c95dfcb454eebe097486459 Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Tue, 9 Oct 2012 17:28:28 +0200
Subject: [PATCH 122/171] [IMP] use of literal_eval from ast instead of
const_eval from tools, as per Olivier recommendation
bzr revid: qdp-launchpad@openerp.com-20121009152828-3bdxpatkrl1qmyfi
---
openerp/osv/orm.py | 5 +++--
openerp/tools/safe_eval.py | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index 8bc5c386527..a6d192240a2 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -60,7 +60,8 @@ import openerp
import openerp.netsvc as netsvc
import openerp.tools as tools
from openerp.tools.config import config
-from openerp.tools.safe_eval import const_eval, safe_eval as eval
+from openerp.tools.safe_eval import safe_eval as eval
+from ast import literal_eval
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
from query import Query
@@ -1734,7 +1735,7 @@ class BaseModel(object):
transfer_field_to_modifiers(field, modifiers)
if node.get('options'):
try:
- node.set('options', simplejson.dumps(const_eval(node.get('options'))))
+ node.set('options', simplejson.dumps(literal_eval(node.get('options'))))
except Exception, msg:
raise except_orm('Invalide Python code in %s'%(node.get('options')), msg[0])
diff --git a/openerp/tools/safe_eval.py b/openerp/tools/safe_eval.py
index 6bc92e57465..601fd95200a 100644
--- a/openerp/tools/safe_eval.py
+++ b/openerp/tools/safe_eval.py
@@ -46,7 +46,7 @@ _ALLOWED_MODULES = ['_strptime', 'time']
_CONST_OPCODES = set(opmap[x] for x in [
'POP_TOP', 'ROT_TWO', 'ROT_THREE', 'ROT_FOUR', 'DUP_TOP', 'DUP_TOPX',
'POP_BLOCK','SETUP_LOOP', 'BUILD_LIST', 'BUILD_MAP', 'BUILD_TUPLE',
- 'LOAD_CONST', 'RETURN_VALUE', 'STORE_SUBSCR', 'STORE_MAP', 'LOAD_NAME'] if x in opmap)
+ 'LOAD_CONST', 'RETURN_VALUE', 'STORE_SUBSCR'] if x in opmap)
_EXPR_OPCODES = _CONST_OPCODES.union(set(opmap[x] for x in [
'UNARY_POSITIVE', 'UNARY_NEGATIVE', 'UNARY_NOT',
From e9d314646d310c1310fd405719cc1b518b00feaf Mon Sep 17 00:00:00 2001
From: Olivier Dony
Date: Tue, 9 Oct 2012 17:54:20 +0200
Subject: [PATCH 123/171] [FIX] mail.thread subclasses: convert body to
plaintext in message_new, as body is now HTML
Also disable the updating of the body when new messages
are received for project.issue records, because this
might discard important information that was manually
entered.
bzr revid: odo@openerp.com-20121009155420-72xvyhhiwd696upv
---
addons/crm/crm_lead.py | 5 ++++-
addons/crm_claim/crm_claim.py | 4 +++-
addons/crm_helpdesk/crm_helpdesk.py | 4 +++-
addons/hr_recruitment/hr_recruitment.py | 4 +++-
addons/project/project.py | 8 +++++---
addons/project_issue/project_issue.py | 6 ++++--
6 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index 7e33f397e8a..48c6491a7c3 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -26,6 +26,7 @@ from osv import fields, osv
import time
import tools
from tools.translate import _
+from tools import html2plaintext
from base.res.res_partner import format_address
@@ -812,9 +813,11 @@ class crm_lead(base_stage, format_address, osv.osv):
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
+
+ desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
- 'description': msg.get('body'),
+ 'description': desc,
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'user_id': False,
diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py
index cbf3ec9f13a..c88b2fe26af 100644
--- a/addons/crm_claim/crm_claim.py
+++ b/addons/crm_claim/crm_claim.py
@@ -26,6 +26,7 @@ from osv import fields, osv
import time
import tools
from tools.translate import _
+from tools import html2plaintext
CRM_CLAIM_PENDING_STATES = (
crm.AVAILABLE_STATES[2][0], # Cancelled
@@ -192,9 +193,10 @@ class crm_claim(base_stage, osv.osv):
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
+ desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
- 'description': msg.get('body'),
+ 'description': desc,
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
})
diff --git a/addons/crm_helpdesk/crm_helpdesk.py b/addons/crm_helpdesk/crm_helpdesk.py
index f36a3b72640..ceffd282aa8 100644
--- a/addons/crm_helpdesk/crm_helpdesk.py
+++ b/addons/crm_helpdesk/crm_helpdesk.py
@@ -25,6 +25,7 @@ from crm import crm
from osv import fields, osv
import tools
from tools.translate import _
+from tools import html2plaintext
CRM_HELPDESK_STATES = (
crm.AVAILABLE_STATES[2][0], # Cancelled
@@ -104,9 +105,10 @@ class crm_helpdesk(base_state, base_stage, osv.osv):
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
+ desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
- 'description': msg.get('body'),
+ 'description': desc,
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'user_id': False,
diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py
index 31959d7e9c7..ccfcae0d26e 100644
--- a/addons/hr_recruitment/hr_recruitment.py
+++ b/addons/hr_recruitment/hr_recruitment.py
@@ -26,6 +26,7 @@ from base_status.base_stage import base_stage
from datetime import datetime
from osv import fields, osv
from tools.translate import _
+from tools import html2plaintext
AVAILABLE_STATES = [
('draft', 'New'),
@@ -327,9 +328,10 @@ class hr_applicant(base_stage, osv.Model):
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
+ desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
- 'description': msg.get('body'),
+ 'description': desc,
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'user_id': False,
diff --git a/addons/project/project.py b/addons/project/project.py
index 98c385c0ce3..a47b582be77 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -19,12 +19,14 @@
#
##############################################################################
-from base_status.base_stage import base_stage
-from datetime import datetime, date
+import time
from lxml import etree
+from datetime import datetime, date
+
+import tools
+from base_status.base_stage import base_stage
from osv import fields, osv
from openerp.addons.resource.faces import task as Task
-import time
from tools.translate import _
from openerp import SUPERUSER_ID
diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py
index 2004e1310f0..9e434078d2f 100644
--- a/addons/project_issue/project_issue.py
+++ b/addons/project_issue/project_issue.py
@@ -27,6 +27,7 @@ from tools.translate import _
import binascii
import time
import tools
+from tools import html2plaintext
class project_issue_version(osv.osv):
_name = "project.issue.version"
@@ -462,9 +463,11 @@ class project_issue(base_stage, osv.osv):
if context is None: context = {}
context['state_to'] = 'draft'
+ desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
+
custom_values.update({
'name': msg.get('subject') or _("No Subject"),
- 'description': msg.get('body'),
+ 'description': desc,
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'user_id': False,
@@ -486,7 +489,6 @@ class project_issue(base_stage, osv.osv):
if update_vals is None: update_vals = {}
# Update doc values according to the message
- update_vals['description'] = msg.get('body', '')
if msg.get('priority'):
update_vals['priority'] = msg.get('priority')
# Parse 'body' to find values to update
From 49b102b54a860e655156fced1940ae6b913a7458 Mon Sep 17 00:00:00 2001
From: Launchpad Translations on behalf of openerp <>
Date: Wed, 10 Oct 2012 04:44:51 +0000
Subject: [PATCH 124/171] Launchpad automatic translations update.
bzr revid: launchpad_translations_on_behalf_of_openerp-20121010044451-x88fqu2rrhax9fq4
---
addons/account_analytic_default/i18n/hu.po | 13 +-
addons/account_budget/i18n/hu.po | 27 +-
addons/account_budget/i18n/lo.po | 32 +-
addons/hr_contract/i18n/mk.po | 271 +++++++
addons/hr_holidays/i18n/mk.po | 864 +++++++++++++++++++++
5 files changed, 1185 insertions(+), 22 deletions(-)
create mode 100644 addons/hr_contract/i18n/mk.po
create mode 100644 addons/hr_holidays/i18n/mk.po
diff --git a/addons/account_analytic_default/i18n/hu.po b/addons/account_analytic_default/i18n/hu.po
index 557aa2e66f5..8b863f51679 100644
--- a/addons/account_analytic_default/i18n/hu.po
+++ b/addons/account_analytic_default/i18n/hu.po
@@ -7,15 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-02-08 00:35+0000\n"
-"PO-Revision-Date: 2011-02-01 18:11+0000\n"
-"Last-Translator: NOVOTRADE RENDSZERHÁZ ( novotrade.hu ) "
-"\n"
+"PO-Revision-Date: 2012-10-09 13:58+0000\n"
+"Last-Translator: krnkris \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-08-28 06:22+0000\n"
-"X-Generator: Launchpad (build 15864)\n"
+"X-Launchpad-Export-Date: 2012-10-10 04:44+0000\n"
+"X-Generator: Launchpad (build 16112)\n"
#. module: account_analytic_default
#: help:account.analytic.default,partner_id:0
@@ -134,12 +133,14 @@ msgstr "Gyűjtőkód alapértelmezések"
#. module: account_analytic_default
#: sql_constraint:stock.picking:0
msgid "Reference must be unique per Company!"
-msgstr ""
+msgstr "Minden vállalkozáshoz egyedi hivatkozás kell!"
#. module: account_analytic_default
#: view:account.analytic.default:0
msgid "Analytical defaults whose end date is greater than today or None"
msgstr ""
+"A mai napnál későbbi lejáratú vagy nem létező dátumú elemzések "
+"alapértelmezései"
#. module: account_analytic_default
#: help:account.analytic.default,product_id:0
diff --git a/addons/account_budget/i18n/hu.po b/addons/account_budget/i18n/hu.po
index c48392c7c8a..35df6ac7dc9 100644
--- a/addons/account_budget/i18n/hu.po
+++ b/addons/account_budget/i18n/hu.po
@@ -7,15 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-02-08 00:35+0000\n"
-"PO-Revision-Date: 2011-01-30 16:38+0000\n"
-"Last-Translator: NOVOTRADE RENDSZERHÁZ ( novotrade.hu ) "
-"\n"
+"PO-Revision-Date: 2012-10-09 13:49+0000\n"
+"Last-Translator: krnkris \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-08-28 06:27+0000\n"
-"X-Generator: Launchpad (build 15864)\n"
+"X-Launchpad-Export-Date: 2012-10-10 04:44+0000\n"
+"X-Generator: Launchpad (build 16112)\n"
#. module: account_budget
#: field:crossovered.budget,creating_user_id:0
@@ -105,6 +104,7 @@ msgid "Percentage"
msgstr "Százalék"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:crossovered.budget.report:0
msgid "to"
msgstr "-"
@@ -138,21 +138,24 @@ msgstr ""
#: code:addons/account_budget/account_budget.py:119
#, python-format
msgid "The Budget '%s' has no accounts!"
-msgstr ""
+msgstr "A '%s' költségvetésnek nincs számlaszáma!"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "%"
msgstr "%"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Description"
msgstr "Leírás"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:crossovered.budget.report:0
msgid "Currency"
msgstr "Pénznem"
@@ -187,6 +190,7 @@ msgid "Planned Amount"
msgstr "Tervezett összeg"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Perc(%)"
@@ -199,6 +203,7 @@ msgid "Done"
msgstr "Kész"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Practical Amt"
@@ -259,7 +264,7 @@ msgstr "Üzleti terv"
#. module: account_budget
#: view:crossovered.budget:0
msgid "To Approve Budgets"
-msgstr ""
+msgstr "Költségvetés jóváhagyása"
#. module: account_budget
#: code:addons/account_budget/account_budget.py:119
@@ -333,6 +338,7 @@ msgid "Account Budget crossvered summary report"
msgstr "Üzleti terv összesítő kimutatás"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Theoretical Amt"
@@ -359,9 +365,10 @@ msgstr "Nyomtatás"
#: view:crossovered.budget:0
#: field:crossovered.budget.lines,theoritical_amount:0
msgid "Theoretical Amount"
-msgstr ""
+msgstr "Elméleti mennyiség"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: field:crossovered.budget.lines,analytic_account_id:0
#: model:ir.model,name:account_budget.model_account_analytic_account
msgid "Analytic Account"
@@ -373,6 +380,7 @@ msgid "Budget :"
msgstr "Üzleti terv :"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Planned Amt"
@@ -413,6 +421,7 @@ msgid "Error! You can not create recursive analytic accounts."
msgstr "Hiba! Nem hozhat létre rekurzív gyűjtőkódokat."
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Analysis from"
@@ -421,7 +430,7 @@ msgstr "Elemzési időszak"
#. module: account_budget
#: view:crossovered.budget:0
msgid "Draft Budgets"
-msgstr ""
+msgstr "Előzetes, tervezett költségvetés"
#, python-format
#~ msgid "The General Budget '%s' has no Accounts!"
diff --git a/addons/account_budget/i18n/lo.po b/addons/account_budget/i18n/lo.po
index daa39b8a6e6..cbc81b84000 100644
--- a/addons/account_budget/i18n/lo.po
+++ b/addons/account_budget/i18n/lo.po
@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME \n"
"POT-Creation-Date: 2012-02-08 00:35+0000\n"
-"PO-Revision-Date: 2011-01-19 15:50+0000\n"
+"PO-Revision-Date: 2012-10-09 16:05+0000\n"
"Last-Translator: Brice Muangkhot ສຸພາ ເມືອງໂຄຕ \n"
"Language-Team: Lao \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-08-28 06:27+0000\n"
-"X-Generator: Launchpad (build 15864)\n"
+"X-Launchpad-Export-Date: 2012-10-10 04:44+0000\n"
+"X-Generator: Launchpad (build 16112)\n"
#. module: account_budget
#: field:crossovered.budget,creating_user_id:0
@@ -31,7 +31,7 @@ msgstr "ຮັບຮູ້ເເລັວ"
#: model:ir.actions.act_window,name:account_budget.open_budget_post_form
#: model:ir.ui.menu,name:account_budget.menu_budget_post_form
msgid "Budgetary Positions"
-msgstr "ຈຸດງົບປະມານ"
+msgstr "ຕໍາແຫນ່ງງົບປະມານ"
#. module: account_budget
#: report:account.budget:0
@@ -105,6 +105,7 @@ msgid "Percentage"
msgstr "ເປີເຊັນ"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:crossovered.budget.report:0
msgid "to"
msgstr "ຫາ"
@@ -126,6 +127,14 @@ msgid ""
"revenue per analytic account and monitor its evolution based on the actuals "
"realised during that period."
msgstr ""
+"ງົບປະມານແມ່ນຄາດຄະເນລາຍໄດ້ຂອງບໍລິສັດຂອງທ່ານແລະຄ່າໃຊ້ຈ່າຍຄາດວ່າຈະສໍາລັບໄລຍະເວລາ"
+"ໃນອະນາຄົດໄດ້. ມີງົບປະມານ, "
+"ບໍລິສັດສາມາດລະມັດລະວັງເບິ່ງວິທີການເງິນຫຼາຍປານເຂົາເຈົ້າໄດ້ຖືກກິນໃນໄລຍະເວລາໃນໄລ"
+"ຍະໃດຫນຶ່ງ, ແລະສະວິທີທີ່ດີທີ່ສຸດເພື່ອແບ່ງມັນໃນບັນດາປະເພດຂອງລາຍການຕ່າງໆ. "
+"ໂດຍການຮັກສາຕິດຕາມບ່ອນທີ່ເງິນຂອງທ່ານດີ, ທ່ານອາດຈະມີຫນ້ອຍອາດຈະ overspend, "
+"ແລະອື່ນໆທີ່ອາດຈະຕອບສະຫນອງໄດ້ຕາມເປົ້າຫມາຍທາງດ້ານການເງິນຂອງທ່ານ. "
+"ຄາດງົບປະມານໂດຍ detailing ລາຍຮັບຄາດວ່າຈະຕໍ່ບັນຊີແຍກທາດແລະຕິດຕາມກວດກາຂອງຕົນ "
+"evolution ອີງຕາມຕົວຈິງໃນ realized ໃນໄລຍະນັ້ນ."
#. module: account_budget
#: code:addons/account_budget/account_budget.py:119
@@ -134,18 +143,21 @@ msgid "The Budget '%s' has no accounts!"
msgstr ""
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "%"
msgstr ""
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Description"
msgstr "ຄຳອະທິບາຍ"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:crossovered.budget.report:0
msgid "Currency"
msgstr "ເງິນຕາ"
@@ -170,7 +182,7 @@ msgstr "ເພື່ອຮັບຮູ້"
#. module: account_budget
#: view:crossovered.budget:0
msgid "Reset to Draft"
-msgstr ""
+msgstr "ປັບກັບຮ່າງ"
#. module: account_budget
#: view:account.budget.post:0
@@ -180,6 +192,7 @@ msgid "Planned Amount"
msgstr "ຈໍານວນຄາດໝາຍມ້ຽນ"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Perc(%)"
@@ -192,6 +205,7 @@ msgid "Done"
msgstr "ຈົບເເລັວ"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Practical Amt"
@@ -203,7 +217,7 @@ msgstr ""
#: view:crossovered.budget:0
#: field:crossovered.budget.lines,practical_amount:0
msgid "Practical Amount"
-msgstr ""
+msgstr "ຈໍານວນເງິນປະຕິບັດໄດ້"
#. module: account_budget
#: field:crossovered.budget,date_to:0
@@ -292,7 +306,7 @@ msgstr ""
#. module: account_budget
#: selection:crossovered.budget,state:0
msgid "Cancelled"
-msgstr ""
+msgstr "ຍົກເລີກ"
#. module: account_budget
#: view:crossovered.budget:0
@@ -326,6 +340,7 @@ msgid "Account Budget crossvered summary report"
msgstr ""
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Theoretical Amt"
@@ -355,6 +370,7 @@ msgid "Theoretical Amount"
msgstr ""
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: field:crossovered.budget.lines,analytic_account_id:0
#: model:ir.model,name:account_budget.model_account_analytic_account
msgid "Analytic Account"
@@ -366,6 +382,7 @@ msgid "Budget :"
msgstr "ງົບປະມານ"
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Planned Amt"
@@ -406,6 +423,7 @@ msgid "Error! You can not create recursive analytic accounts."
msgstr ""
#. module: account_budget
+#: report:account.analytic.account.budget:0
#: report:account.budget:0
#: report:crossovered.budget.report:0
msgid "Analysis from"
diff --git a/addons/hr_contract/i18n/mk.po b/addons/hr_contract/i18n/mk.po
new file mode 100644
index 00000000000..2a4011c9e0d
--- /dev/null
+++ b/addons/hr_contract/i18n/mk.po
@@ -0,0 +1,271 @@
+# Macedonian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-02-08 00:36+0000\n"
+"PO-Revision-Date: 2012-10-09 08:00+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Macedonian \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-10 04:44+0000\n"
+"X-Generator: Launchpad (build 16112)\n"
+
+#. module: hr_contract
+#: field:hr.contract,wage:0
+msgid "Wage"
+msgstr "Плата"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Information"
+msgstr "Информации"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Trial Period"
+msgstr "Пробен Период"
+
+#. module: hr_contract
+#: field:hr.contract,trial_date_start:0
+msgid "Trial Start Date"
+msgstr "Пробен Почетен Датум"
+
+#. module: hr_contract
+#: view:hr.employee:0
+msgid "Medical Examination"
+msgstr "Систематски Преглед"
+
+#. module: hr_contract
+#: field:hr.employee,vehicle:0
+msgid "Company Vehicle"
+msgstr "Службено Возило"
+
+#. module: hr_contract
+#: view:hr.employee:0
+msgid "Miscellaneous"
+msgstr "Разно"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Current"
+msgstr "Тековен"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Group By..."
+msgstr "Групирај По..."
+
+#. module: hr_contract
+#: field:hr.contract,department_id:0
+msgid "Department"
+msgstr "Сектор"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Overpassed"
+msgstr "Изминат"
+
+#. module: hr_contract
+#: view:hr.contract:0
+#: field:hr.contract,employee_id:0
+#: model:ir.model,name:hr_contract.model_hr_employee
+msgid "Employee"
+msgstr "Вработен"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Search Contract"
+msgstr "Пребарај Договор"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Contracts in progress"
+msgstr "Договори во тек"
+
+#. module: hr_contract
+#: field:hr.employee,vehicle_distance:0
+msgid "Home-Work Distance"
+msgstr "Дома-Работа Одалеченост"
+
+#. module: hr_contract
+#: view:hr.contract:0
+#: field:hr.employee,contract_ids:0
+#: model:ir.actions.act_window,name:hr_contract.act_hr_employee_2_hr_contract
+#: model:ir.actions.act_window,name:hr_contract.action_hr_contract
+#: model:ir.ui.menu,name:hr_contract.hr_menu_contract
+msgid "Contracts"
+msgstr "Договори"
+
+#. module: hr_contract
+#: view:hr.employee:0
+msgid "Personal Info"
+msgstr "Лични информации"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Contracts whose end date already passed"
+msgstr "Договори чии што краен рок е веќе поминат"
+
+#. module: hr_contract
+#: help:hr.employee,contract_id:0
+msgid "Latest contract of the employee"
+msgstr "Последен договор на вработениот"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Job"
+msgstr "Работно Место"
+
+#. module: hr_contract
+#: view:hr.contract:0
+#: field:hr.contract,advantages:0
+msgid "Advantages"
+msgstr "Придобивки"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Valid for"
+msgstr "Валиден за"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Work Permit"
+msgstr "Дозвола за Работа"
+
+#. module: hr_contract
+#: field:hr.employee,children:0
+msgid "Number of Children"
+msgstr "Број на Деца"
+
+#. module: hr_contract
+#: model:ir.actions.act_window,name:hr_contract.action_hr_contract_type
+#: model:ir.ui.menu,name:hr_contract.hr_menu_contract_type
+msgid "Contract Types"
+msgstr "Типови на Договор"
+
+#. module: hr_contract
+#: constraint:hr.employee:0
+msgid "Error ! You cannot create recursive Hierarchy of Employees."
+msgstr "Грешка! Не можете да креирате рекурзивна хиерархија на вработените."
+
+#. module: hr_contract
+#: field:hr.contract,date_end:0
+msgid "End Date"
+msgstr "Краен датум"
+
+#. module: hr_contract
+#: help:hr.contract,wage:0
+msgid "Basic Salary of the employee"
+msgstr "Основна Плата на вработениот"
+
+#. module: hr_contract
+#: field:hr.contract,name:0
+msgid "Contract Reference"
+msgstr "Референца"
+
+#. module: hr_contract
+#: help:hr.employee,vehicle_distance:0
+msgid "In kilometers"
+msgstr "во километри"
+
+#. module: hr_contract
+#: view:hr.contract:0
+#: field:hr.contract,notes:0
+msgid "Notes"
+msgstr "Забелешки"
+
+#. module: hr_contract
+#: field:hr.contract,permit_no:0
+msgid "Work Permit No"
+msgstr "Број на Дозвола за Работа"
+
+#. module: hr_contract
+#: view:hr.contract:0
+#: field:hr.employee,contract_id:0
+#: model:ir.model,name:hr_contract.model_hr_contract
+#: model:ir.ui.menu,name:hr_contract.next_id_56
+msgid "Contract"
+msgstr "Договор"
+
+#. module: hr_contract
+#: view:hr.contract:0
+#: field:hr.contract,type_id:0
+#: view:hr.contract.type:0
+#: field:hr.contract.type,name:0
+#: model:ir.model,name:hr_contract.model_hr_contract_type
+msgid "Contract Type"
+msgstr "Тип на Договор"
+
+#. module: hr_contract
+#: view:hr.contract:0
+#: field:hr.contract,working_hours:0
+msgid "Working Schedule"
+msgstr "Распоред за Работа"
+
+#. module: hr_contract
+#: view:hr.employee:0
+msgid "Job Info"
+msgstr "Информации за Работата"
+
+#. module: hr_contract
+#: field:hr.contract,visa_expire:0
+msgid "Visa Expire Date"
+msgstr "Виза Датум на Истекување"
+
+#. module: hr_contract
+#: field:hr.contract,job_id:0
+msgid "Job Title"
+msgstr "Звање"
+
+#. module: hr_contract
+#: field:hr.employee,manager:0
+msgid "Is a Manager"
+msgstr "Менаџер"
+
+#. module: hr_contract
+#: field:hr.contract,date_start:0
+msgid "Start Date"
+msgstr "Почетен датум"
+
+#. module: hr_contract
+#: constraint:hr.contract:0
+msgid "Error! contract start-date must be lower then contract end-date."
+msgstr ""
+"Грешка! Почетниот датум на договорот мора да биде помал од крајниот датум."
+
+#. module: hr_contract
+#: field:hr.contract,visa_no:0
+msgid "Visa No"
+msgstr "Број на Виза"
+
+#. module: hr_contract
+#: field:hr.employee,place_of_birth:0
+msgid "Place of Birth"
+msgstr "Место на раѓање"
+
+#. module: hr_contract
+#: view:hr.contract:0
+msgid "Duration"
+msgstr "Траење"
+
+#. module: hr_contract
+#: field:hr.employee,medic_exam:0
+msgid "Medical Examination Date"
+msgstr "Датум за Систематски Преглед"
+
+#. module: hr_contract
+#: field:hr.contract,trial_date_end:0
+msgid "Trial End Date"
+msgstr "Пробен Краен Датум"
+
+#. module: hr_contract
+#: view:hr.contract.type:0
+msgid "Search Contract Type"
+msgstr "Пребарај Тип на Договор"
diff --git a/addons/hr_holidays/i18n/mk.po b/addons/hr_holidays/i18n/mk.po
new file mode 100644
index 00000000000..2694317ebe9
--- /dev/null
+++ b/addons/hr_holidays/i18n/mk.po
@@ -0,0 +1,864 @@
+# Macedonian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-02-08 01:37+0100\n"
+"PO-Revision-Date: 2012-10-09 08:43+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Macedonian \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-10 04:44+0000\n"
+"X-Generator: Launchpad (build 16112)\n"
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Blue"
+msgstr "Сина"
+
+#. module: hr_holidays
+#: field:hr.holidays,holiday_type:0
+msgid "Allocation Type"
+msgstr "Тип на Алокација"
+
+#. module: hr_holidays
+#: selection:hr.employee,current_leave_state:0
+#: selection:hr.holidays,state:0
+msgid "Waiting Second Approval"
+msgstr "Се чека на второ одобрување"
+
+#. module: hr_holidays
+#: help:hr.holidays.status,remaining_leaves:0
+msgid "Maximum Leaves Allowed - Leaves Already Taken"
+msgstr "Мкасимален број на дозволени отсуства - Отсуствата се веќе земени"
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Leaves Management"
+msgstr "Менаџирање на Отсуства"
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Group By..."
+msgstr "Групирај По..."
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Allocation Mode"
+msgstr "Мод на Алокација"
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: field:hr.holidays,department_id:0
+msgid "Department"
+msgstr "Сектор"
+
+#. module: hr_holidays
+#: model:ir.actions.act_window,name:hr_holidays.request_approve_holidays
+msgid "Requests Approve"
+msgstr "Одобри Барања"
+
+#. module: hr_holidays
+#: selection:hr.employee,current_leave_state:0
+#: selection:hr.holidays,state:0
+msgid "Refused"
+msgstr "Одбиени"
+
+#. module: hr_holidays
+#: help:hr.holidays,category_id:0
+msgid "Category of Employee"
+msgstr "Категорија на Вработен"
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid " Month-1"
+msgstr " Месец-1"
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Brown"
+msgstr "Кафена"
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Remaining Days"
+msgstr "Останати Денови"
+
+#. module: hr_holidays
+#: selection:hr.holidays,holiday_type:0
+msgid "By Employee"
+msgstr "По Вработен"
+
+#. module: hr_holidays
+#: help:hr.holidays,employee_id:0
+msgid ""
+"Leave Manager can let this field empty if this leave request/allocation is "
+"for every employee"
+msgstr ""
+"Менаџерот за отсуства може да го остави ова поле празно ако барањето за "
+"отсуство/преместување е за секој вработен"
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Set to Draft"
+msgstr "Подеси на нацрт"
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Light Cyan"
+msgstr "Светла Цијан"
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Light Green"
+msgstr "Светло зелено"
+
+#. module: hr_holidays
+#: field:hr.employee,current_leave_id:0
+msgid "Current Leave Type"
+msgstr "Тековен Тип на Отсуство"
+
+#. module: hr_holidays
+#: model:ir.actions.act_window,help:hr_holidays.open_ask_holidays
+msgid ""
+"Leave requests can be recorded by employees and validated by their managers. "
+"Once a leave request is validated, it appears automatically in the agenda of "
+"the employee. You can define several allowance types (paid holidays, "
+"sickness, etc.) and manage allowances per type."
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.actions.report.xml,name:hr_holidays.report_holidays_summary
+msgid "Summary Of Leaves"
+msgstr "Збир на Отсуства"
+
+#. module: hr_holidays
+#: selection:hr.employee,current_leave_state:0
+#: view:hr.holidays:0
+#: selection:hr.holidays,state:0
+msgid "Approved"
+msgstr "Одобрено"
+
+#. module: hr_holidays
+#: field:hr.employee,last_login:0
+msgid "Latest Connection"
+msgstr "Последна Конекција"
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Refuse"
+msgstr "Одбиј"
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/hr_holidays.py:344
+#, python-format
+msgid ""
+"You cannot validate leaves for employee %s: too few remaining days (%s)."
+msgstr ""
+"Не можете да валидирате отсуства за вработениот %s: премалку преостанати "
+"денови (%s)."
+
+#. module: hr_holidays
+#: help:hr.holidays,state:0
+msgid ""
+"The state is set to 'Draft', when a holiday request is created. \n"
+"The state is 'Waiting Approval', when holiday request is confirmed by user. "
+" \n"
+"The state is 'Refused', when holiday request is refused by manager. "
+" \n"
+"The state is 'Approved', when holiday request is approved by manager."
+msgstr ""
+
+#. module: hr_holidays
+#: view:board.board:0
+#: model:ir.actions.act_window,name:hr_holidays.act_hr_employee_holiday_request
+#: model:ir.ui.menu,name:hr_holidays.menu_hr_reporting_holidays
+#: model:ir.ui.menu,name:hr_holidays.menu_open_ask_holidays
+msgid "Leaves"
+msgstr "Отсуства"
+
+#. module: hr_holidays
+#: model:ir.model,name:hr_holidays.model_hr_holidays
+msgid "Leave"
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.ui.menu,name:hr_holidays.menu_request_approve_holidays
+msgid "Leave Requests to Approve"
+msgstr "Барања за отсуства за одобрување"
+
+#. module: hr_holidays
+#: model:ir.ui.menu,name:hr_holidays.menu_account_central_journal
+msgid "Leaves by Department"
+msgstr "Отсуства по Сектор"
+
+#. module: hr_holidays
+#: selection:hr.employee,current_leave_state:0
+#: selection:hr.holidays,state:0
+msgid "Cancelled"
+msgstr "Откажано"
+
+#. module: hr_holidays
+#: help:hr.holidays,type:0
+msgid ""
+"Choose 'Leave Request' if someone wants to take an off-day. \n"
+"Choose 'Allocation Request' if you want to increase the number of leaves "
+"available for someone"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.employee,remaining_leaves:0
+msgid ""
+"Total number of legal leaves allocated to this employee, change this value "
+"to create allocation/leave requests."
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.status:0
+msgid "Validation"
+msgstr ""
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/hr_holidays.py:377
+#, python-format
+msgid "Warning !"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.status,color_name:0
+msgid "Color in Report"
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.model,name:hr_holidays.model_hr_holidays_summary_employee
+msgid "HR Holidays Summary Report By Employee"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays,manager_id:0
+msgid "This area is automatically filled by the user who validate the leave"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,holiday_status_id:0
+#: field:hr.holidays.remaining.leaves.user,leave_type:0
+#: view:hr.holidays.status:0
+#: field:hr.holidays.status,name:0
+#: field:hr.holidays.summary.dept,holiday_type:0
+#: model:ir.actions.act_window,name:hr_holidays.open_view_holiday_status
+#: model:ir.model,name:hr_holidays.model_hr_holidays_status
+#: model:ir.ui.menu,name:hr_holidays.menu_open_view_holiday_status
+msgid "Leave Type"
+msgstr ""
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/hr_holidays.py:199
+#: code:addons/hr_holidays/hr_holidays.py:344
+#, python-format
+msgid "Warning!"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Magenta"
+msgstr ""
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/wizard/hr_holidays_summary_department.py:44
+#, python-format
+msgid "You have to select at least 1 Department. And try again"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.summary.dept,holiday_type:0
+#: selection:hr.holidays.summary.employee,holiday_type:0
+msgid "Confirmed"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.summary.dept,date_from:0
+#: field:hr.holidays.summary.employee,date_from:0
+msgid "From"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Confirm"
+msgstr ""
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/hr_holidays.py:384
+#, python-format
+msgid "Leave Request for %s"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.status,remaining_leaves:0
+msgid "Remaining Leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: field:hr.holidays,state:0
+msgid "State"
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.model,name:hr_holidays.model_hr_holidays_remaining_leaves_user
+msgid "Total holidays by type"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.employee:0
+#: view:hr.holidays:0
+#: field:hr.holidays,employee_id:0
+#: field:hr.holidays.remaining.leaves.user,name:0
+#: model:ir.model,name:hr_holidays.model_hr_employee
+msgid "Employee"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.employee,current_leave_state:0
+#: selection:hr.holidays,state:0
+msgid "New"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Type"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Red"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.remaining.leaves.user:0
+msgid "Leaves by Type"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Light Salmon"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Wheat"
+msgstr ""
+
+#. module: hr_holidays
+#: constraint:resource.calendar.leaves:0
+msgid "Error! leave start-date must be lower then leave end-date."
+msgstr ""
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/hr_holidays.py:382
+#, python-format
+msgid "Allocation for %s"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: field:hr.holidays,number_of_days:0
+#: field:hr.holidays,number_of_days_temp:0
+msgid "Number of Days"
+msgstr ""
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/hr_holidays.py:377
+#, python-format
+msgid ""
+"The feature behind the field 'Remaining Legal Leaves' can only be used when "
+"there is only one leave type with the option 'Allow to Override Limit' "
+"unchecked. (%s Found). Otherwise, the update is ambiguous as we cannot "
+"decide on which leave type the update has to be done. \n"
+"You may prefer to use the classic menus 'Leave Requests' and 'Allocation "
+"Requests' located in 'Human Resources \\ Leaves' to manage the leave days of "
+"the employees if the configuration does not allow to use this field."
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.status:0
+msgid "Search Leave Type"
+msgstr ""
+
+#. module: hr_holidays
+#: sql_constraint:hr.holidays:0
+msgid "You have to select an employee or a category"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays.status,double_validation:0
+msgid ""
+"When selected, the Allocation/Leave Requests for this type require a second "
+"validation to be approved."
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.employee,current_leave_state:0
+#: selection:hr.holidays,state:0
+msgid "Waiting Approval"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.summary.employee,emp:0
+msgid "Employee(s)"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays.status,categ_id:0
+msgid ""
+"If you set a meeting type, OpenERP will create a meeting in the calendar "
+"once a leave is validated."
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,linked_request_ids:0
+msgid "Linked Requests"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,parent_id:0
+msgid "Parent"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Lavender"
+msgstr ""
+
+#. module: hr_holidays
+#: xsl:holidays.summary:0
+#: view:hr.holidays:0
+msgid "Month"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: model:ir.actions.act_window,name:hr_holidays.open_ask_holidays
+#: model:ir.ui.menu,name:hr_holidays.menu_open_ask_holidays_new
+msgid "Leave Requests"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.status,limit:0
+msgid "Allow to Override Limit"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.summary.employee:0
+#: model:ir.actions.act_window,name:hr_holidays.action_hr_holidays_summary_employee
+msgid "Employee's Holidays"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: field:hr.holidays,category_id:0
+msgid "Category"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays.status,max_leaves:0
+msgid ""
+"This value is given by the sum of all holidays requests with a positive "
+"value."
+msgstr ""
+
+#. module: hr_holidays
+#: view:board.board:0
+msgid "All Employee Leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Light Coral"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.summary.dept:0
+#: model:ir.actions.act_window,name:hr_holidays.action_hr_holidays_summary_dept
+msgid "Holidays by Department"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Black"
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.actions.act_window,name:hr_holidays.hr_holidays_leaves_assign_legal
+msgid "Allocate Leaves for Employees"
+msgstr ""
+
+#. module: hr_holidays
+#: field:resource.calendar.leaves,holiday_id:0
+msgid "Holiday"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,case_id:0
+#: field:hr.holidays.status,categ_id:0
+msgid "Meeting"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Ivory"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.summary.dept,holiday_type:0
+#: selection:hr.holidays.summary.employee,holiday_type:0
+msgid "Both Validated and Confirmed"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.status,leaves_taken:0
+msgid "Leaves Already Taken"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,user_id:0
+#: field:hr.holidays.remaining.leaves.user,user_id:0
+msgid "User"
+msgstr ""
+
+#. module: hr_holidays
+#: sql_constraint:hr.holidays:0
+msgid "The start date must be before the end date !"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.status,active:0
+msgid "Active"
+msgstr ""
+
+#. module: hr_holidays
+#: constraint:hr.employee:0
+msgid "Error ! You cannot create recursive Hierarchy of Employees."
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.employee:0
+#: field:hr.employee,remaining_leaves:0
+msgid "Remaining Legal Leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,manager_id:0
+msgid "First Approval"
+msgstr ""
+
+#. module: hr_holidays
+#: model:hr.holidays.status,name:hr_holidays.holiday_status_unpaid
+msgid "Unpaid"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: model:ir.actions.act_window,name:hr_holidays.open_company_allocation
+#: model:ir.ui.menu,name:hr_holidays.menu_open_company_allocation
+msgid "Leaves Summary"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Holidays during last month"
+msgstr ""
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/wizard/hr_holidays_summary_department.py:44
+#, python-format
+msgid "Error"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.employee:0
+msgid "Assign Leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Light Blue"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "My Department Leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.employee,current_leave_state:0
+msgid "Current Leave Status"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,type:0
+msgid "Request Type"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays.status,active:0
+msgid ""
+"If the active field is set to false, it will allow you to hide the leave "
+"type without removing it."
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.status:0
+msgid "Misc"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "General"
+msgstr ""
+
+#. module: hr_holidays
+#: model:hr.holidays.status,name:hr_holidays.holiday_status_comp
+msgid "Compensatory Days"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: field:hr.holidays,notes:0
+msgid "Reasons"
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.actions.act_window,name:hr_holidays.action_hr_available_holidays_report
+#: model:ir.ui.menu,name:hr_holidays.menu_hr_available_holidays_report_tree
+msgid "Leaves Analysis"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.summary.dept:0
+#: view:hr.holidays.summary.employee:0
+msgid "Cancel"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays.status,color_name:0
+msgid ""
+"This color will be used in the leaves summary located in Reporting\\Leaves "
+"by Departement"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: selection:hr.holidays.summary.dept,holiday_type:0
+#: selection:hr.holidays.summary.employee,holiday_type:0
+msgid "Validated"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: selection:hr.holidays,type:0
+msgid "Allocation Request"
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.model,name:hr_holidays.model_resource_calendar_leaves
+msgid "Leave Detail"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,double_validation:0
+#: field:hr.holidays.status,double_validation:0
+msgid "Apply Double Validation"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.summary.dept:0
+#: view:hr.holidays.summary.employee:0
+msgid "Print"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays.status:0
+msgid "Details"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: model:ir.actions.act_window,name:hr_holidays.action_hr_holidays_leaves_by_month
+msgid "My Leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays,holiday_type:0
+msgid "By Employee Category"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: selection:hr.holidays,type:0
+msgid "Leave Request"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,name:0
+msgid "Description"
+msgstr ""
+
+#. module: hr_holidays
+#: model:hr.holidays.status,name:hr_holidays.holiday_status_cl
+msgid "Legal Leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: sql_constraint:hr.holidays:0
+msgid "The number of days must be greater than 0 !"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays,holiday_type:0
+msgid ""
+"By Employee: Allocation/Request for individual Employee, By Employee "
+"Category: Allocation/Request for group of employees in category"
+msgstr ""
+
+#. module: hr_holidays
+#: code:addons/hr_holidays/hr_holidays.py:199
+#, python-format
+msgid "You cannot delete a leave which is not in draft state !"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Search Leave"
+msgstr "Пребарај Отсуство"
+
+#. module: hr_holidays
+#: field:hr.holidays.summary.employee,holiday_type:0
+msgid "Select Holiday Type"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.remaining.leaves.user,no_of_leaves:0
+msgid "Remaining leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.summary.dept,depts:0
+msgid "Department(s)"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,manager_id2:0
+msgid "Second Approval"
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays,date_to:0
+msgid "End Date"
+msgstr ""
+
+#. module: hr_holidays
+#: model:hr.holidays.status,name:hr_holidays.holiday_status_sl
+msgid "Sick Leaves"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays.status,limit:0
+msgid ""
+"If you select this checkbox, the system allows the employees to take more "
+"leaves than the available ones for this type."
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays.status,leaves_taken:0
+msgid ""
+"This value is given by the sum of all holidays requests with a negative "
+"value."
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Violet"
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.actions.act_window,help:hr_holidays.hr_holidays_leaves_assign_legal
+msgid ""
+"You can assign remaining Legal Leaves for each employee, OpenERP will "
+"automatically create and validate allocation requests."
+msgstr ""
+
+#. module: hr_holidays
+#: field:hr.holidays.status,max_leaves:0
+msgid "Maximum Allowed"
+msgstr ""
+
+#. module: hr_holidays
+#: help:hr.holidays,manager_id2:0
+msgid ""
+"This area is automaticly filled by the user who validate the leave with "
+"second level (If Leave type need second validation)"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Mode"
+msgstr ""
+
+#. module: hr_holidays
+#: model:ir.model,name:hr_holidays.model_hr_holidays_summary_dept
+msgid "HR Holidays Summary Report By Department"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Approve"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: field:hr.holidays,date_from:0
+msgid "Start Date"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+#: model:ir.actions.act_window,name:hr_holidays.open_allocation_holidays
+#: model:ir.ui.menu,name:hr_holidays.menu_open_allocation_holidays
+msgid "Allocation Requests"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Light Yellow"
+msgstr ""
+
+#. module: hr_holidays
+#: selection:hr.holidays.status,color_name:0
+msgid "Light Pink"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Manager"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "To Confirm"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "Year"
+msgstr ""
+
+#. module: hr_holidays
+#: view:hr.holidays:0
+msgid "To Approve"
+msgstr ""
From f7d5b5ff0aabd129cbb9c9c1278eab0c3ec361f2 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Wed, 10 Oct 2012 09:25:10 +0200
Subject: [PATCH 125/171] [FIX] mail: in function field mail_follower_ids,
support value False in setter
bzr revid: rco@openerp.com-20121010072510-aacyyj3csj720z8l
---
addons/mail/mail_thread.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py
index 529ee8c65cc..e6150640eb3 100644
--- a/addons/mail/mail_thread.py
+++ b/addons/mail/mail_thread.py
@@ -138,6 +138,8 @@ class mail_thread(osv.AbstractModel):
return res
def _set_followers(self, cr, uid, id, name, value, arg, context=None):
+ if not value:
+ return
partner_obj = self.pool.get('res.partner')
fol_obj = self.pool.get('mail.followers')
From 83c00b75ff7773916d8a1d6b7a8cc1087be3779d Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 11:37:00 +0200
Subject: [PATCH 126/171] [FIX] Fixed on_mode_switch.
bzr revid: vta@openerp.com-20121010093700-nz326tlux3v5olqj
---
addons/web_shortcuts/static/src/js/web_shortcuts.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/web_shortcuts/static/src/js/web_shortcuts.js b/addons/web_shortcuts/static/src/js/web_shortcuts.js
index 743f3fc73aa..c6d5a2f41fb 100644
--- a/addons/web_shortcuts/static/src/js/web_shortcuts.js
+++ b/addons/web_shortcuts/static/src/js/web_shortcuts.js
@@ -108,7 +108,7 @@ instance.web.UserMenu.include({
});
instance.web.ViewManagerAction.include({
- on_mode_switch: function (view_type, no_store) {
+ switch_mode: function (view_type, no_store) {
var self = this;
this._super.apply(this, arguments).then(function() {
self.shortcut_check(self.views[view_type]);
From 12c35d031dac08296e05bd4231994257e5247bbd Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 11:37:37 +0200
Subject: [PATCH 127/171] [FIX] Fixed on_mode_switch.
bzr revid: vta@openerp.com-20121010093737-0kheus1v0kdj5tk7
---
addons/web/static/src/js/view_form.js | 2 +-
addons/web/static/src/js/views.js | 24 +++++++++++------------
addons/web_kanban/static/src/js/kanban.js | 4 ++--
3 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 98fd83dadaf..7395011a5e7 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -3370,7 +3370,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
}
def.resolve();
});
- this.viewmanager.on("on_mode_switch", self, function(n_mode, b, c, d, e) {
+ this.viewmanager.on("switch_mode", self, function(n_mode, b, c, d, e) {
$.when(self.save_any_view()).then(function() {
if (n_mode === "list") {
$.async_when().then(function() {
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index e18a3e361be..f0df367c5e3 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -417,7 +417,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
this._super();
var self = this;
this.$el.find('.oe_view_manager_switch a').click(function() {
- self.trigger('on_mode_switch', $(this).data('view-type'));
+ self.trigger('switch_mode', $(this).data('view-type'));
}).tipsy();
var views_ids = {};
_.each(this.views_src, function(view) {
@@ -439,10 +439,8 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
// If no default view defined, switch to the first one in sequence
var default_view = this.flags.default_view || this.views_src[0].view_type;
- this.on('on_mode_switch', self, function(view_type, no_store, view_options) {
- self.switch_mode(view_type, no_store, view_options);
- });
- return this.trigger('on_mode_switch', default_view);
+ this.on('switch_mode', self, self.switch_mode);
+ return this.trigger('switch_mode', default_view);
},
switch_mode: function(view_type, no_store, view_options) {
var self = this;
@@ -548,7 +546,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
add_breadcrumb: function(on_reverse_breadcrumb) {
var self = this;
var views = [this.active_view || this.views_src[0].view_type];
- this.on('on_mode_switch',self,function(mode) {
+ this.on('switch_mode', self, function(mode) {
var last = views.slice(-1)[0];
if (mode !== last) {
if (mode !== 'form') {
@@ -564,7 +562,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
var view_to_select = views[index];
self.$el.show();
if (self.active_view !== view_to_select) {
- self.trigger('on_mode_switch', view_to_select);
+ self.trigger('switch_mode', view_to_select);
}
},
get_title: function() {
@@ -600,12 +598,12 @@ instance.web.ViewManager = instance.web.Widget.extend({
* consist to switch to the asked view.
*/
switch_view: function(view_type, no_store, options) {
- return this.trigger('on_mode_switch', view_type, no_store, options);
+ return this.trigger('switch_mode', view_type, no_store, options);
},
/**
* Returns to the view preceding the caller view in this manager's
* navigation history (the navigation history is appended to via
- * on_mode_switch)
+ * switch_mode)
*
* @param {Object} [options]
* @param {Boolean} [options.created=false] resource was created
@@ -619,12 +617,12 @@ instance.web.ViewManager = instance.web.Widget.extend({
if (options.created && current_view === 'form' && previous_view === 'list') {
// APR special case: "If creation mode from list (and only from a list),
// after saving, go to page view (don't come back in list)"
- return this.trigger('on_mode_switch', 'form');
+ return this.trigger('switch_mode', 'form');
} else if (options.created && !previous_view && this.action && this.action.flags.default_view === 'form') {
// APR special case: "If creation from dashboard, we have no previous view
- return this.trigger('on_mode_switch', 'form');
+ return this.trigger('switch_mode', 'form');
}
- return this.trigger('on_mode_switch', previous_view, true);
+ return this.trigger('switch_mode', previous_view, true);
},
/**
* Sets up the current viewmanager's search view.
@@ -928,7 +926,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
if (state.view_type && state.view_type !== this.active_view) {
defs.push(
this.views[this.active_view].deferred.pipe(function() {
- return self.trigger('on_mode_switch', state.view_type, true)
+ return self.trigger('switch_mode', state.view_type, true)
})
);
}
diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js
index dae3d7b214d..d95546dfe41 100644
--- a/addons/web_kanban/static/src/js/kanban.js
+++ b/addons/web_kanban/static/src/js/kanban.js
@@ -194,7 +194,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
});
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
- form.on("on_button_cancel",self,am.dialog.on_close);
+ form.on("on_button_cancel", self, am.dialog.on_close);
form.on_created.add_last(function(r) {
(new instance.web.DataSet(self, self.group_by_field.relation)).name_get([r.result]).then(function(new_record) {
am.dialog.on_close();
@@ -672,7 +672,7 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({
});
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
- form.on("on_button_cancel",self,am.dialog.on_close);
+ form.on("on_button_cancel", self, am.dialog.on_close);
form.on_saved.add_last(function() {
am.dialog.on_close();
self.view.do_reload();
From 9c71d984e6937cc598fc8da52bf353322acc03cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?=
Date: Wed, 10 Oct 2012 11:55:09 +0200
Subject: [PATCH 128/171] [IMP] Class instanciations throws an error when you
forgot to use the new operator
bzr revid: fva@openerp.com-20121010095509-ojvigsva4hblta7m
---
addons/web/static/src/js/corelib.js | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js
index ff193605033..21d593069e7 100644
--- a/addons/web/static/src/js/corelib.js
+++ b/addons/web/static/src/js/corelib.js
@@ -121,6 +121,10 @@ openerp.web.corelib = function(instance) {
// The dummy class constructor
function Class() {
+ if(this.constructor !== instance.web.Class){
+ throw new Error("You need a 'new' to instanciate an object");
+ return null;
+ }
// All construction is actually done in the init method
if (!initializing && this.init) {
var ret = this.init.apply(this, arguments);
From 31760fd2496a3287e10515a6e88cc5cd32f8db2c Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 12:02:18 +0200
Subject: [PATCH 129/171] [FIX] Fixed on_record_loaded.
bzr revid: vta@openerp.com-20121010100218-drvx420qtrjucom1
---
addons/board/static/src/js/dashboard.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/addons/board/static/src/js/dashboard.js b/addons/board/static/src/js/dashboard.js
index bba076e8594..2dbd9f5c9cc 100644
--- a/addons/board/static/src/js/dashboard.js
+++ b/addons/board/static/src/js/dashboard.js
@@ -25,8 +25,8 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
}).bind('sortstop', self.do_save_dashboard);
var old_title = this.__parentedParent.get('title');
- this.__parentedParent.on('record_load', this, function(){
- self.__parentedParent.set({ 'title' : old_title});
+ this.__parentedParent.on('load_record', self, function(){
+ self.__parentedParent.set({ 'title': old_title});
})
// Events
this.$el.find('.oe_dashboard_link_reset').click(this.on_reset);
@@ -173,7 +173,7 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
},
on_load_action: function(result, index, action_attrs) {
var self = this,
- action = result.result,
+ action = result,
view_mode = action_attrs.view_mode;
if (action_attrs.context && action_attrs.context['dashboard_merge_domains_contexts'] === false) {
From 40eceb20a384b56b1e1acad6750afa27521a8fa4 Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 12:02:33 +0200
Subject: [PATCH 130/171] [FIX] Fixed on_record_loaded.
bzr revid: vta@openerp.com-20121010100233-tulf3c1fvnt2s85e
---
addons/web/static/src/js/view_form.js | 31 ++++++++++++-------
.../web/static/src/js/view_list_editable.js | 7 ++---
addons/web_diagram/static/src/js/diagram.js | 6 ++--
addons/web_tests/static/src/js/web_tests.js | 6 ++--
4 files changed, 29 insertions(+), 21 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 43afe3a3bf1..6a9d1dcb3a4 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -126,7 +126,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
self.on("change:actual_mode", self, self.init_pager);
self.init_pager();
});
- self.on("record_load", self, self.on_record_loaded);
+ self.on("load_record", self, self.load_record);
instance.web.bus.on('clear_uncommitted_changes', this, function(e) {
if (!this.can_be_discarded()) {
e.preventDefault();
@@ -332,7 +332,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
fields.push('display_name');
return self.dataset.read_index(fields, {
context: { 'bin_size': true, 'future_display_name' : true }
- }).pipe(function(r){self.trigger('record_load',r)});
+ }).pipe(function(r) {
+ self.trigger('load_record', r);
+ });
});
}
return shown.pipe(function() {
@@ -355,7 +357,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
}
this._super();
},
- on_record_loaded: function(record) {
+ load_record: function(record) {
var self = this, set_values = [];
if (!record) {
this.set({ 'title' : undefined });
@@ -417,10 +419,11 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
var self = this;
var keys = _.keys(this.fields_view.fields);
if (keys.length) {
- return this.dataset.default_get(keys)
- .pipe(function(r){self.trigger('record_load',r)});
+ return this.dataset.default_get(keys).pipe(function(r) {
+ self.trigger('load_record', r);
+ });
}
- return self.trigger('record_load',{});
+ return self.trigger('load_record', {});
},
on_form_changed: function() {
this.trigger("view_content_has_changed");
@@ -754,7 +757,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.trigger('history_back');
} else {
this.to_view_mode();
- this.trigger('record_load',this.datarecord);
+ this.trigger('load_record', this.datarecord);
}
}
return false;
@@ -954,9 +957,15 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
} else {
var fields = _.keys(self.fields_view.fields);
fields.push('display_name');
- return self.dataset.read_index(fields, {
- context : { 'bin_size' : true, 'future_display_name' : true }
- }).pipe(function(r){self.trigger('record_load',r)});
+ return self.dataset.read_index(fields,
+ {
+ context: {
+ 'bin_size': true,
+ 'future_display_name': true
+ }
+ }).pipe(function(r) {
+ self.trigger('load_record', r);
+ });
}
});
},
@@ -3371,7 +3380,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
if (self.get("effective_readonly")) {
$(".oe_form_buttons", controller.$el).children().remove();
}
- controller.on("record_load", self, function(){
+ controller.on("load_record", self, function(){
once.resolve();
});
controller.on_pager_action.add_first(function() {
diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js
index 892221a347b..fe0f525fe3f 100644
--- a/addons/web/static/src/js/view_list_editable.js
+++ b/addons/web/static/src/js/view_list_editable.js
@@ -626,7 +626,7 @@ openerp.web.list_editable = function (instance) {
},
start: function () {
var self = this;
- var _super = this._super();
+ var _super = this._super();
this.form.embedded_view = this._validate_view(
this.delegate.edition_view(this));
var form_ready = this.form.appendTo(this.$el).then(
@@ -708,10 +708,9 @@ openerp.web.list_editable = function (instance) {
var self = this;
var form = self.form;
var loaded = record
- ? form.on_record_loaded(_.extend({}, record))
+ ? form.trigger('load_record', _.extend({}, record))
: form.load_defaults();
-
- return loaded.pipe(function () {
+ return $.when(loaded).pipe(function () {
return form.do_show({reload: false});
}).pipe(function () {
self.record = form.datarecord;
diff --git a/addons/web_diagram/static/src/js/diagram.js b/addons/web_diagram/static/src/js/diagram.js
index 3b9e81fdf6e..9fd74853c3c 100644
--- a/addons/web_diagram/static/src/js/diagram.js
+++ b/addons/web_diagram/static/src/js/diagram.js
@@ -246,7 +246,7 @@ instance.web.DiagramView = instance.web.View.extend({
var form_fields = [self.parent_field];
var form_controller = pop.view_form;
- form_controller.on("record_load", self, function(){
+ form_controller.on("load_record", self, function(){
_.each(form_fields, function(fld) {
if (!(fld in form_controller.fields)) { return; }
var field = form_controller.fields[fld];
@@ -280,7 +280,7 @@ instance.web.DiagramView = instance.web.View.extend({
var form_controller = pop.view_form;
var form_fields = [this.parent_field];
- form_controller.on("record_load", self, function(){
+ form_controller.on("load_record", self, function(){
_.each(form_fields, function(fld) {
if (!(fld in form_controller.fields)) { return; }
var field = form_controller.fields[fld];
@@ -340,7 +340,7 @@ instance.web.DiagramView = instance.web.View.extend({
var form_controller = pop.view_form;
- form_controller.on("record_load", self, function(){
+ form_controller.on("load_record", self, function(){
form_controller.fields[self.connectors.attrs.source].set_value(node_source_id);
form_controller.fields[self.connectors.attrs.source].dirty = true;
form_controller.fields[self.connectors.attrs.destination].set_value(node_dest_id);
diff --git a/addons/web_tests/static/src/js/web_tests.js b/addons/web_tests/static/src/js/web_tests.js
index 8c146644372..bc7d16913fb 100644
--- a/addons/web_tests/static/src/js/web_tests.js
+++ b/addons/web_tests/static/src/js/web_tests.js
@@ -23,14 +23,14 @@ openerp.web_tests = function (instance) {
on_everything_loaded: function (slice) {
var records = slice[0].records;
if (!records.length) {
- this.form.trigger("record_load",{});
+ this.form.trigger("load_record", {});
return;
}
- this.form.trigger("record_load", records[0])
+ this.form.trigger("load_record", records[0]);
_(records.slice(1)).each(function (record, index) {
this.dataset.index = index+1;
this.form.reposition($('').appendTo(this.$el));
- this.form.trigger("record_load", record)
+ this.form.trigger("load_record", record);
}, this);
}
});
From 5f8c1b4907f7bf448fc37eda679398153c6a6772 Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 12:08:32 +0200
Subject: [PATCH 131/171] [REV] revert revision 7730 that will be pushed to
trunk via another branch (a dedicated one)
bzr revid: qdp-launchpad@openerp.com-20121010100832-asu2rj6j7x5328f0
---
addons/account/account_bank_statement.py | 5 ++---
addons/account/account_view.xml | 9 ++++++---
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py
index 549363ce269..8b2a9aff257 100644
--- a/addons/account/account_bank_statement.py
+++ b/addons/account/account_bank_statement.py
@@ -461,10 +461,9 @@ class account_bank_statement(osv.osv):
return {}
balance_start = self._compute_balance_end_real(cr, uid, journal_id, context=context)
- journal_data = self.pool.get('account.journal').read(cr, uid, journal_id, ['company_id', 'currency'], context=context)
+ journal_data = self.pool.get('account.journal').read(cr, uid, journal_id, ['company_id'], context=context)
company_id = journal_data['company_id']
- currency_id = journal_data['currency'] or self.pool.get('res.company').browse(cr, uid, company_id[0], context=context).currency_id.id
- return {'value': {'balance_start': balance_start, 'company_id': company_id, 'currency': currency_id}}
+ return {'value': {'balance_start': balance_start, 'company_id': company_id}}
def unlink(self, cr, uid, ids, context=None):
stat = self.read(cr, uid, ids, ['state'], context=context)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index d2680a8456f..1c40bebba52 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -633,10 +633,13 @@
-
-
-
+
+
+
+
+
+
From bbbc6a304dca2b58aef7e47e2bba9e155de160f9 Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 12:12:00 +0200
Subject: [PATCH 132/171] [FIX] Fixed event name on_write_complete.
bzr revid: vta@openerp.com-20121010101200-1lwcqae44bb88ffa
---
addons/process/static/src/js/process.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/process/static/src/js/process.js b/addons/process/static/src/js/process.js
index c593c1569fc..386a9653c02 100644
--- a/addons/process/static/src/js/process.js
+++ b/addons/process/static/src/js/process.js
@@ -239,7 +239,7 @@ instance.web.ViewManager.include({
title: _t('Process')
});
var form_controller = pop.view_form;
- pop.on('on_write_complete', self, self.initialize_process_view);
+ pop.on('write_completed', self, self.initialize_process_view);
}
});
};
From a8bf5bfbab84fdc278a9481a493b44adbaf0676c Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 12:12:46 +0200
Subject: [PATCH 133/171] [FIX] Fixed event name on_write_complete.
bzr revid: vta@openerp.com-20121010101246-1ht2npz6l75ah06e
---
addons/web/static/src/js/view_form.js | 6 +++---
addons/web_gantt/static/src/js/gantt.js | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index d635ab7e640..1478ae6e4ac 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -2982,7 +2982,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
title: _t("Open: ") + self.string
}
);
- pop.on('on_write_complete', self, function(){
+ pop.on('write_completed', self, function(){
self.display_value = {};
self.render_value();
self.focus();
@@ -4134,7 +4134,7 @@ instance.web.form.Many2ManyListView = instance.web.ListView.extend(/** @lends in
title: _t("Open: ") + this.m2m_field.string,
readonly: this.getParent().get("effective_readonly")
});
- pop.on('on_write_complete', self, self.reload_content);
+ pop.on('write_completed', self, self.reload_content);
}
});
@@ -4382,7 +4382,7 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
this.dataset.write_function = function(id, data, options, sup) {
var fct = self.options.write_function || sup;
return fct.call(this, id, data, options).then(function() {
- self.trigger('on_write_complete');
+ self.trigger('write_completed');
});
};
this.dataset.parent_view = this.options.parent_view;
diff --git a/addons/web_gantt/static/src/js/gantt.js b/addons/web_gantt/static/src/js/gantt.js
index 0d600712d4a..66d699c2cde 100644
--- a/addons/web_gantt/static/src/js/gantt.js
+++ b/addons/web_gantt/static/src/js/gantt.js
@@ -211,7 +211,7 @@ instance.web_gantt.GanttView = instance.web.View.extend({
on_task_display: function(task) {
var self = this;
var pop = new instance.web.form.FormOpenPopup(self);
- pop.on('on_write_complete',self,self.reload);
+ pop.on('write_completed',self,self.reload);
pop.show_element(
self.dataset.model,
task.id,
From 4dd9a0529e79eccb7670a180c5d88fad144fa4c9 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Wed, 10 Oct 2012 12:18:36 +0200
Subject: [PATCH 134/171] [ADD] reload file button next to the file input, as
webkit browsers and MSIE don't trigger change when a file input is re-set to
thee same file
Using other events (e.g. 'click') is not kosher as the event is
triggered long before the file is picked, the alternative is to use
the File API and regularly check the file in the input to see if it's
been altered (by storing a crc) and re-pushing it if the hash is
different. Of course this has other issues (risks catching the file
mid-edition...)
A third alternative is, once a file has been uploaded, to clear and
re-insert the corresponding file input. This means the file input will
*always* be empty
bzr revid: xmo@openerp.com-20121010101836-qtqmcc5n5zblgmcp
---
addons/base_import/static/src/css/import.css | 19 +++++++++++++++++++
addons/base_import/static/src/js/import.js | 3 ++-
addons/base_import/static/src/xml/import.xml | 1 +
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/addons/base_import/static/src/css/import.css b/addons/base_import/static/src/css/import.css
index 21e598ff707..3b4daf815e5 100644
--- a/addons/base_import/static/src/css/import.css
+++ b/addons/base_import/static/src/css/import.css
@@ -60,3 +60,22 @@
.oe_import_selector li {
margin: 0; padding: 0;
}
+
+.oe_import .oe_import_file_reload {
+ font-size: 1px;
+ letter-spacing: -1px;
+ color: transparent;
+ font-weight: normal;
+ position: relative;
+ padding: 0;
+ height: 19px;
+ width: 20px;
+}
+.oe_import .oe_import_file_reload:before {
+ font: 26px "mnmliconsRegular";
+ content: "Q";
+ color: #4C4C4C;
+ position: absolute;
+ top: -6px;
+ left: 2px;
+}
diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js
index 5980eb2384c..0a60fe18ffb 100644
--- a/addons/base_import/static/src/js/import.js
+++ b/addons/base_import/static/src/js/import.js
@@ -73,7 +73,8 @@ openerp.base_import = function (instance) {
],
events: {
// 'change .oe_import_grid input': 'import_dryrun',
- 'change input.oe_import_file': 'loaded_file',
+ 'change .oe_import_file': 'loaded_file',
+ 'click .oe_import_file_reload': 'loaded_file',
'change input.oe_import_has_header, .oe_import_options input': 'settings_changed',
'click a.oe_import_toggle': function (e) {
e.preventDefault();
diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml
index adca0579f8f..902478468e1 100644
--- a/addons/base_import/static/src/xml/import.xml
+++ b/addons/base_import/static/src/xml/import.xml
@@ -24,6 +24,7 @@
CSV File:
+ Reload File
File Format Options…
From f4f3d6fa153bc3bb446cf841fc3844614f5103dc Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 12:42:20 +0200
Subject: [PATCH 135/171] [REF] code review by odo
bzr revid: qdp-launchpad@openerp.com-20121010104220-nqi6c12ua7tnaejt
---
openerp/osv/orm.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py
index a6d192240a2..4f717e69dad 100644
--- a/openerp/osv/orm.py
+++ b/openerp/osv/orm.py
@@ -1733,11 +1733,13 @@ class BaseModel(object):
field = model_fields.get(node.get('name'))
if field:
transfer_field_to_modifiers(field, modifiers)
+ #evaluate the options as python code, but send it as json to the client
if node.get('options'):
try:
node.set('options', simplejson.dumps(literal_eval(node.get('options'))))
- except Exception, msg:
- raise except_orm('Invalide Python code in %s'%(node.get('options')), msg[0])
+ except Exception, e:
+ _logger.exception('Invalid `options´ attribute, should be a valid python expression: %r', node.get('options'))
+ raise except_orm('Invalid options', 'Invalid options: %r %s' % (node.get('options'), e))
elif node.tag in ('form', 'tree'):
result = self.view_header_get(cr, user, False, node.tag, context)
From 21dcc15a2ca38725d963fd16f57f5c9f4b1c5afe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?=
Date: Wed, 10 Oct 2012 12:44:33 +0200
Subject: [PATCH 136/171] [FIX] previous 'forgot now' error message was a bit
crappy
bzr revid: fva@openerp.com-20121010104433-cb03lb11fi15qrzd
---
addons/web/static/src/js/corelib.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js
index 21d593069e7..7a9af79b4fb 100644
--- a/addons/web/static/src/js/corelib.js
+++ b/addons/web/static/src/js/corelib.js
@@ -122,7 +122,7 @@ openerp.web.corelib = function(instance) {
// The dummy class constructor
function Class() {
if(this.constructor !== instance.web.Class){
- throw new Error("You need a 'new' to instanciate an object");
+ throw new Error("You can only instanciate objects with the 'new' operator");
return null;
}
// All construction is actually done in the init method
From e2d3d617a96e416751c15e42d3fbebedfdc7e00c Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 12:49:52 +0200
Subject: [PATCH 137/171] [IMP] account: added monetary widget on invoices form
view
bzr revid: qdp-launchpad@openerp.com-20121010104952-jxy17zagby2jp0w2
---
addons/account/account_invoice_view.xml | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml
index 8421409d4ce..8516fcd96ae 100644
--- a/addons/account/account_invoice_view.xml
+++ b/addons/account/account_invoice_view.xml
@@ -211,17 +211,17 @@
@@ -368,16 +368,16 @@
From 7c6e893a3952b206ba6f8e6301336ceced1b3f38 Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 12:56:19 +0200
Subject: [PATCH 138/171] [IMP] account: added monetary widget on
account.move.line and cash registers
bzr revid: qdp-launchpad@openerp.com-20121010105619-fk13ba9ex0f0ihpv
---
addons/account/account_view.xml | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 3391158696a..d98b53ebbbd 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1127,8 +1127,8 @@
-
-
+
+
@@ -1174,8 +1174,8 @@
-
-
+
+
@@ -2564,7 +2564,7 @@ action = pool.get('res.config').next(cr, uid, [], context)
-
+
@@ -2626,12 +2626,12 @@ action = pool.get('res.config').next(cr, uid, [], context)
-
-
-
+
+
+
-
+
From 1bb568d22e4fa493f3fa388928f47af09e24d90a Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 13:12:05 +0200
Subject: [PATCH 139/171] [IMP] sale, sale_margin: added monetary widget on
sale order form view
bzr revid: qdp-launchpad@openerp.com-20121010111205-eokyh1haa69tgrfl
---
addons/sale/sale.py | 10 ++++++++--
addons/sale/sale_view.xml | 7 ++++---
addons/sale_margin/sale_margin_view.xml | 2 +-
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index ed7a2835425..9ba6c43a588 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -201,6 +201,7 @@ class sale_order(osv.osv):
help="""This field controls how invoice and delivery operations are synchronized.
- With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""),
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order."),
+ 'currency_id': fields.related('pricelist_id', 'currency_id', type="many2one", relation="res.currency", readonly=True, required=True),
'project_id': fields.many2one('account.analytic.account', 'Contract/Analytic Account', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order."),
'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
@@ -264,13 +265,18 @@ class sale_order(osv.osv):
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context=None):
- if (not pricelist_id) or (not order_lines):
+ if not pricelist_id:
return {}
+ value = {
+ 'currency_id': self.pool.get('product.pricelist').browse(cr, uid, pricelist_id, context=context).currency_id.id
+ }
+ if not order_lines:
+ return {'value': value}
warning = {
'title': _('Pricelist Warning!'),
'message' : _('If you change the pricelist of this order (and eventually the currency), prices of existing order lines will not be updated.')
}
- return {'warning': warning}
+ return {'warning': warning, 'value': value}
def onchange_partner_id(self, cr, uid, ids, part):
if not part:
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index a9ebca876a9..8b89e8047cb 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -184,6 +184,7 @@
+
@@ -261,14 +262,14 @@
diff --git a/addons/sale_margin/sale_margin_view.xml b/addons/sale_margin/sale_margin_view.xml
index 69f49bd48ea..6aa34bae26c 100644
--- a/addons/sale_margin/sale_margin_view.xml
+++ b/addons/sale_margin/sale_margin_view.xml
@@ -11,7 +11,7 @@
-
+
From 42b2412782ea665217fb3652665c762ca45ef054 Mon Sep 17 00:00:00 2001
From: Antonin Bourguignon
Date: Wed, 10 Oct 2012 13:15:38 +0200
Subject: [PATCH 140/171] [REV] revert the previous 'bugfix' which is not a
bugfix; removing a bugged feature doesn't fix anything also remove
whitespaces
bzr revid: abo@openerp.com-20121010111538-03xm67fpc3tljfd4
---
addons/project/report/project_cumulative.xml | 26 +++++++++++---------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml
index dc556be22e7..75bfe3b8879 100644
--- a/addons/project/report/project_cumulative.xml
+++ b/addons/project/report/project_cumulative.xml
@@ -18,10 +18,12 @@
+
project.task.history.cumulative.graph
project.task.history.cumulative
+
@@ -36,16 +38,18 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
@@ -56,12 +60,12 @@
form
graph,tree
-
+
{"search_default_open":1, "search_default_this_month": 1}
+ parent="base.menu_project_report"/>
From 9fa829ebcad8a0bcd68617f9553ebe24b66747c5 Mon Sep 17 00:00:00 2001
From: Antonin Bourguignon
Date: Wed, 10 Oct 2012 13:16:49 +0200
Subject: [PATCH 141/171] [FIX] replace the related field with a m2o field and
adapt the requet in init() method
bzr revid: abo@openerp.com-20121010111649-11p1h305w6j7dwqf
---
addons/project/project.py | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/addons/project/project.py b/addons/project/project.py
index 6b02a018293..1bdbd34c575 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -1099,7 +1099,7 @@ class task(base_stage, osv.osv):
task_record = self.browse(cr, uid, task_id, context=context)
if task_record.project_id:
project_follower_ids = [follower.id for follower in task_record.project_id.message_follower_ids]
- self.message_subscribe(cr, uid, [task_id], project_follower_ids,
+ self.message_subscribe(cr, uid, [task_id], project_follower_ids,
context=context)
self._store_history(cr, uid, [task_id], context=context)
self.create_send_note(cr, uid, [task_id], context=context)
@@ -1353,16 +1353,15 @@ class project_project(osv.osv):
'use_tasks': True
}
-
-#
-# Tasks History, used for cumulative flow charts (Lean/Agile)
-#
-
class project_task_history(osv.osv):
+ """
+ Tasks History, used for cumulative flow charts (Lean/Agile)
+ """
_name = 'project.task.history'
_description = 'History of Tasks'
_rec_name = 'task_id'
_log_access = False
+
def _get_date(self, cr, uid, ids, name, arg, context=None):
result = {}
for history in self.browse(cr, uid, ids, context=context):
@@ -1414,35 +1413,38 @@ class project_task_history(osv.osv):
'date': fields.date.context_today,
}
-
class project_task_history_cumulative(osv.osv):
_name = 'project.task.history.cumulative'
_table = 'project_task_history_cumulative'
_inherit = 'project.task.history'
_auto = False
+
_columns = {
'end_date': fields.date('End Date'),
- 'project_id': fields.related('task_id', 'project_id', string='Project', type='many2one', relation='project.project')
+ 'project_id': fields.many2one('project.project', 'Project'),
}
+
def init(self, cr):
cr.execute(""" CREATE OR REPLACE VIEW project_task_history_cumulative AS (
SELECT
- history.date::varchar||'-'||history.history_id::varchar as id,
- history.date as end_date,
+ history.date::varchar||'-'||history.history_id::varchar AS id,
+ history.date AS end_date,
*
FROM (
SELECT
- id as history_id,
- date+generate_series(0, CAST((coalesce(end_date,DATE 'tomorrow')::date - date)AS integer)-1) as date,
- task_id, type_id, user_id, kanban_state, state,
- greatest(remaining_hours,1) as remaining_hours, greatest(planned_hours,1) as planned_hours
+ h.id AS history_id,
+ h.date+generate_series(0, CAST((coalesce(h.end_date, DATE 'tomorrow')::date - h.date) AS integer)-1) AS date,
+ h.task_id, h.type_id, h.user_id, h.kanban_state, h.state,
+ greatest(h.remaining_hours, 1) AS remaining_hours, greatest(h.planned_hours, 1) AS planned_hours,
+ t.project_id
FROM
- project_task_history
- ) as history
+ project_task_history AS h
+ JOIN project_task AS t ON (h.task_id = t.id)
+
+ ) AS history
)
""")
-
class project_category(osv.osv):
""" Category of project's task (or issue) """
_name = "project.category"
From 155680a15871af3f06abaa461c7e531c1f2adc8d Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 13:20:13 +0200
Subject: [PATCH 142/171] [IMP] purchase: added monetary widget on purchase
order form view
bzr revid: qdp-launchpad@openerp.com-20121010112013-d6z1iq6hpjgdle63
---
addons/purchase/purchase.py | 6 ++++++
addons/purchase/purchase_view.xml | 9 +++++----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index d654078a055..c0516d09de3 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -166,6 +166,7 @@ class purchase_order(osv.osv):
'warehouse_id': fields.many2one('stock.warehouse', 'Destination Warehouse', states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]}),
'location_id': fields.many2one('stock.location', 'Destination', required=True, domain=[('usage','<>','view')]),
'pricelist_id':fields.many2one('product.pricelist', 'Pricelist', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]}, help="The pricelist sets the currency used for this purchase order. It also computes the supplier price for the selected products/quantities."),
+ 'currency_id': fields.related('pricelist_id', 'currency_id', type="many2one", relation="res.currency", readonly=True, required=True),
'state': fields.selection(STATE_SELECTION, 'Status', readonly=True, help="The state of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' state. Then the order has to be confirmed by the user, the state switch to 'Confirmed'. Then the supplier must confirm the order to change the state to 'Approved'. When the purchase order is paid and received, the state becomes 'Done'. If a cancel action occurs in the invoice or in the reception of goods, the state becomes in exception.", select=True),
'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'approved':[('readonly',True)],'done':[('readonly',True)]}),
'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
@@ -246,6 +247,11 @@ class purchase_order(osv.osv):
def button_dummy(self, cr, uid, ids, context=None):
return True
+ def onchange_pricelist(self, cr, uid, ids, pricelist_id, context=None):
+ if not pricelist_id:
+ return {}
+ return {'value': {'currency_id': self.pool.get('product.pricelist').browse(cr, uid, pricelist_id, context=context).currency_id.id}}
+
def onchange_dest_address_id(self, cr, uid, ids, address_id):
if not address_id:
return {}
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index bfff06f5eaf..446c17578cb 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -223,7 +223,8 @@
-
+
+
@@ -249,14 +250,14 @@
From 550d7905b55423cc8b7d3931cc1ff23a46b14cd5 Mon Sep 17 00:00:00 2001
From: Antonin Bourguignon
Date: Wed, 10 Oct 2012 13:25:53 +0200
Subject: [PATCH 143/171] [FIX] domain in view
bzr revid: abo@openerp.com-20121010112553-no3nhdvaj5kun1a8
---
addons/project/report/project_cumulative.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml
index 75bfe3b8879..c30c91fe6c0 100644
--- a/addons/project/report/project_cumulative.xml
+++ b/addons/project/report/project_cumulative.xml
@@ -49,7 +49,7 @@
-
+
From f8a29989c8d921732956f9ba7f81a69b048056de Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Wed, 10 Oct 2012 13:27:31 +0200
Subject: [PATCH 144/171] [IMP] base_import: simplify styling of looks button
bzr revid: xmo@openerp.com-20121010112731-flw3bkijm229mr53
---
addons/base_import/static/src/css/import.css | 19 -------------------
addons/base_import/static/src/xml/import.xml | 4 +++-
2 files changed, 3 insertions(+), 20 deletions(-)
diff --git a/addons/base_import/static/src/css/import.css b/addons/base_import/static/src/css/import.css
index 3b4daf815e5..21e598ff707 100644
--- a/addons/base_import/static/src/css/import.css
+++ b/addons/base_import/static/src/css/import.css
@@ -60,22 +60,3 @@
.oe_import_selector li {
margin: 0; padding: 0;
}
-
-.oe_import .oe_import_file_reload {
- font-size: 1px;
- letter-spacing: -1px;
- color: transparent;
- font-weight: normal;
- position: relative;
- padding: 0;
- height: 19px;
- width: 20px;
-}
-.oe_import .oe_import_file_reload:before {
- font: 26px "mnmliconsRegular";
- content: "Q";
- color: #4C4C4C;
- position: absolute;
- top: -6px;
- left: 2px;
-}
diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml
index 902478468e1..1c57c40c9db 100644
--- a/addons/base_import/static/src/xml/import.xml
+++ b/addons/base_import/static/src/xml/import.xml
@@ -24,7 +24,9 @@
CSV File:
- Reload File
+
+
+
File Format Options…
From 4c7f416dd4b2689a38a6be14a4bcaeeb44583ca7 Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Wed, 10 Oct 2012 13:30:25 +0200
Subject: [PATCH 145/171] [FIX] switch_view
bzr revid: al@openerp.com-20121010113025-qpz12d28uob7hab9
---
addons/web/static/src/js/view_form.js | 2 +-
addons/web/static/src/js/views.js | 35 +++++++++++----------------
2 files changed, 15 insertions(+), 22 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 1478ae6e4ac..9315ce15d1a 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -3565,7 +3565,7 @@ instance.web.form.One2ManyViewManager = instance.web.ViewManager.extend({
});
this.__ignore_blur = false;
},
- switch_view: function(mode, unused) {
+ do_switch_view: function(mode, unused) {
if (mode !== 'form') {
return this._super(mode, unused);
}
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 0474e43bee3..f985e5f6dc8 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -417,7 +417,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
this._super();
var self = this;
this.$el.find('.oe_view_manager_switch a').click(function() {
- self.trigger('switch_mode', $(this).data('view-type'));
+ self.switch_mode($(this).data('view-type'));
}).tipsy();
var views_ids = {};
_.each(this.views_src, function(view) {
@@ -439,8 +439,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
// If no default view defined, switch to the first one in sequence
var default_view = this.flags.default_view || this.views_src[0].view_type;
- this.on('switch_mode', self, self.switch_mode);
- return this.trigger('switch_mode', default_view);
+ return this.switch_mode(default_view);
},
switch_mode: function(view_type, no_store, view_options) {
var self = this;
@@ -448,9 +447,9 @@ instance.web.ViewManager = instance.web.Widget.extend({
var view_promise;
var form = this.views['form'];
if (!view || (form && form.controller && !form.controller.can_be_discarded())) {
+ self.trigger('switch_mode', view_type, no_store, view_options);
return $.Deferred().reject();
}
-
if (!no_store) {
this.views_history.push(view_type);
}
@@ -468,13 +467,12 @@ instance.web.ViewManager = instance.web.Widget.extend({
this.searchview[(view.controller.searchable === false || this.searchview.hidden) ? 'hide' : 'show']();
}
- this.$el
- .find('.oe_view_manager_switch a').parent().removeClass('active');
+ this.$el.find('.oe_view_manager_switch a').parent().removeClass('active');
this.$el
.find('.oe_view_manager_switch a').filter('[data-view-type="' + view_type + '"]')
.parent().addClass('active');
- return $.when(view_promise).then(function () {
+ r = $.when(view_promise).then(function () {
_.each(_.keys(self.views), function(view_name) {
var controller = self.views[view_name].controller;
if (controller) {
@@ -495,7 +493,9 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
}
});
+ self.trigger('switch_mode', view_type, no_store, view_options);
});
+ return r;
},
do_create_view: function(view_type) {
// Lazy loading of views
@@ -524,7 +524,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
if (view.embedded_view) {
controller.set_embedded_view(view.embedded_view);
}
- controller.do_switch_view.add_last(_.bind(this.switch_view, this));
+ controller.on('switch_mode', self, this.switch_mode);
controller.do_prev_view.add_last(this.on_prev_view);
var container = this.$el.find(".oe_view_manager_view_" + view_type);
@@ -562,7 +562,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
var view_to_select = views[index];
self.$el.show();
if (self.active_view !== view_to_select) {
- self.trigger('switch_mode', view_to_select);
+ self.switch_mode(view_to_select);
}
},
get_title: function() {
@@ -592,14 +592,6 @@ instance.web.ViewManager = instance.web.Widget.extend({
on_reverse_breadcrumb: on_reverse_breadcrumb,
});
},
- /**
- * Method used internally when a view asks to switch view. This method is meant
- * to be extended by child classes to change the default behavior, which simply
- * consist to switch to the asked view.
- */
- switch_view: function(view_type, no_store, options) {
- return this.trigger('switch_mode', view_type, no_store, options);
- },
/**
* Returns to the view preceding the caller view in this manager's
* navigation history (the navigation history is appended to via
@@ -617,12 +609,12 @@ instance.web.ViewManager = instance.web.Widget.extend({
if (options.created && current_view === 'form' && previous_view === 'list') {
// APR special case: "If creation mode from list (and only from a list),
// after saving, go to page view (don't come back in list)"
- return this.trigger('switch_mode', 'form');
+ return this.switch_mode('form');
} else if (options.created && !previous_view && this.action && this.action.flags.default_view === 'form') {
// APR special case: "If creation from dashboard, we have no previous view
- return this.trigger('switch_mode', 'form');
+ return this.switch_mode('form');
}
- return this.trigger('switch_mode', previous_view, true);
+ return this.switch_mode(previous_view, true);
},
/**
* Sets up the current viewmanager's search view.
@@ -926,7 +918,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
if (state.view_type && state.view_type !== this.active_view) {
defs.push(
this.views[this.active_view].deferred.pipe(function() {
- return self.trigger('switch_mode', state.view_type, true)
+ return self.switch_mode(state.view_type, true);
})
);
}
@@ -1265,6 +1257,7 @@ instance.web.View = instance.web.Widget.extend({
* @param {String} view view type to switch to
*/
do_switch_view: function(view) {
+ this.trigger('switch_mode',view);
},
/**
* Cancels the switch to the current view, switches to the previous one
From a28d4b75bc779e3506331f4bedeeccb0a81d7121 Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 13:31:47 +0200
Subject: [PATCH 146/171] [IMP] account_voucher: added monetary widget on
customer/supplier payment form view
bzr revid: qdp-launchpad@openerp.com-20121010113147-8yxjj1kdx3j1i2ma
---
.../voucher_payment_receipt_view.xml | 44 ++++++++-----------
1 file changed, 19 insertions(+), 25 deletions(-)
diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml
index 78b76e5c9b7..e1a48c6c535 100644
--- a/addons/account_voucher/voucher_payment_receipt_view.xml
+++ b/addons/account_voucher/voucher_payment_receipt_view.xml
@@ -136,11 +136,8 @@
-
-
-
-
-
+
+
-
+
-
-
-
-
-
+
+
-
+
-
+
-
-
-
-
-
-
+
+
-
+
-
+
Date: Wed, 10 Oct 2012 13:40:07 +0200
Subject: [PATCH 147/171] [FIX] Fixed on_button_cancel.
bzr revid: vta@openerp.com-20121010114007-3cw3qlxu2zwt1k0s
---
addons/web/static/src/js/view_form.js | 9 +++++----
addons/web_kanban/static/src/js/kanban.js | 4 ++--
addons/web_view_editor/static/src/js/view_editor.js | 2 +-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index b41039361c0..b2faa93889e 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -172,10 +172,10 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
} else {
this.$el.find('.oe_form_buttons').replaceWith(this.$buttons);
}
- this.$buttons.on('click','.oe_form_button_create',this.on_button_create);
- this.$buttons.on('click','.oe_form_button_edit',this.on_button_edit);
- this.$buttons.on('click','.oe_form_button_save',this.on_button_save);
- this.$buttons.on('click','.oe_form_button_cancel',this.on_button_cancel);
+ this.$buttons.on('click', '.oe_form_button_create', this.on_button_create);
+ this.$buttons.on('click', '.oe_form_button_edit', this.on_button_edit);
+ this.$buttons.on('click', '.oe_form_button_save', this.on_button_save);
+ this.$buttons.on('click', '.oe_form_button_cancel', this.on_button_cancel);
this.$sidebar = this.options.$sidebar || this.$el.find('.oe_form_sidebar');
if (!this.sidebar && this.options.$sidebar) {
@@ -755,6 +755,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.on_record_loaded(this.datarecord);
}
}
+ this.trigger('on_button_cancel');
return false;
},
on_button_new: function() {
diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js
index dae3d7b214d..d95546dfe41 100644
--- a/addons/web_kanban/static/src/js/kanban.js
+++ b/addons/web_kanban/static/src/js/kanban.js
@@ -194,7 +194,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
});
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
- form.on("on_button_cancel",self,am.dialog.on_close);
+ form.on("on_button_cancel", self, am.dialog.on_close);
form.on_created.add_last(function(r) {
(new instance.web.DataSet(self, self.group_by_field.relation)).name_get([r.result]).then(function(new_record) {
am.dialog.on_close();
@@ -672,7 +672,7 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({
});
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
- form.on("on_button_cancel",self,am.dialog.on_close);
+ form.on("on_button_cancel", self, am.dialog.on_close);
form.on_saved.add_last(function() {
am.dialog.on_close();
self.view.do_reload();
diff --git a/addons/web_view_editor/static/src/js/view_editor.js b/addons/web_view_editor/static/src/js/view_editor.js
index b3a4f0dcfac..40d333afa0f 100644
--- a/addons/web_view_editor/static/src/js/view_editor.js
+++ b/addons/web_view_editor/static/src/js/view_editor.js
@@ -1014,7 +1014,7 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({
var action_manager = new instance.web.ActionManager(self);
$.when(action_manager.do_action(action)).then(function() {
var controller = action_manager.dialog_widget.views['form'].controller;
- controller.on("on_button_cancel",self,function(){
+ controller.on("on_button_cancel", self, function(){
action_manager.destroy();
});
controller.do_save.add_last(function(){
From f486bf1c9f7f4908e667576c45f07146c459e599 Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Wed, 10 Oct 2012 14:08:49 +0200
Subject: [PATCH 148/171] [FIX] o2m switch_view
bzr revid: al@openerp.com-20121010120849-8qekbmy570zozicn
---
addons/web/static/src/js/view_form.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 4bdc122b690..a095ab129c1 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -3566,7 +3566,7 @@ instance.web.form.One2ManyViewManager = instance.web.ViewManager.extend({
});
this.__ignore_blur = false;
},
- do_switch_view: function(mode, unused) {
+ switch_mode: function(mode, unused) {
if (mode !== 'form') {
return this._super(mode, unused);
}
@@ -4204,7 +4204,7 @@ instance.web.form.FieldMany2ManyKanban = instance.web.form.AbstractField.extend(
self.initial_is_loaded.resolve();
loaded.resolve();
});
- this.kanban_view.do_switch_view.add_last(_.bind(this.open_popup, this));
+ this.kanban_view.on('switch_mode', this, this.open_popup);
$.async_when().then(function () {
self.kanban_view.appendTo(self.$el);
});
From 9acd1e6bf3400ff945e39f7eefc01a4efefd42ae Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 14:09:17 +0200
Subject: [PATCH 149/171] [FIX] Fixed on_created.
bzr revid: vta@openerp.com-20121010120917-8aah2jrats09jaol
---
addons/web/static/src/js/view_form.js | 10 +++++-----
addons/web_calendar/static/src/js/calendar.js | 2 +-
addons/web_kanban/static/src/js/kanban.js | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 366b2e7a9e9..dc5721208e5 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -131,7 +131,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
e.preventDefault();
}
});
- self.on('on_rec_create', self, self.on_created);
+ self.on('record_created', self, self.update_dataset);
},
destroy: function() {
_.each(this.get_widgets(), function(w) {
@@ -779,7 +779,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
var def = $.Deferred();
$.when(this.has_been_loaded).then(function() {
self.dataset.call('copy', [self.datarecord.id, {}, self.dataset.context]).then(function(new_id) {
- return self.trigger('on_rec_create',{ result : new_id });
+ return self.trigger('record_created', { result : new_id });
}).then(function() {
return self.to_edit_mode();
}).then(function() {
@@ -860,7 +860,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
if (!self.datarecord.id) {
// Creation save
save_deferral = self.dataset.create(values).pipe(function(r) {
- return self.trigger('on_rec_create', r, prepend_on_create);
+ return self.trigger('record_created', r, prepend_on_create);
}, null);
} else if (_.isEmpty(values) && ! self.force_dirty) {
// Not dirty, noop save
@@ -919,7 +919,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
* @param {Boolean} [prepend_on_create=false] adds the newly created record
* at the beginning of the dataset instead of the end
*/
- on_created: function(r, prepend_on_create) {
+ update_dataset: function(r, prepend_on_create) {
if (!r) {
// should not happen in the server, but may happen for internal purpose
return $.Deferred().reject();
@@ -1629,7 +1629,7 @@ instance.web.form.FormDialog = instance.web.Dialog.extend({
pager: false
});
this.form.appendTo(this.$el);
- this.form.on('on_rec_create', self, this.on_form_dialog_saved);
+ this.form.on('record_created', self, this.on_form_dialog_saved);
this.form.on_saved.add_last(this.on_form_dialog_saved);
return this;
},
diff --git a/addons/web_calendar/static/src/js/calendar.js b/addons/web_calendar/static/src/js/calendar.js
index 35cac441b35..5e04743b8a9 100644
--- a/addons/web_calendar/static/src/js/calendar.js
+++ b/addons/web_calendar/static/src/js/calendar.js
@@ -458,7 +458,7 @@ instance.web_calendar.CalendarFormDialog = instance.web.Dialog.extend({
pager: false
});
var def = this.form.appendTo(this.$el);
- this.form.on('on_rec_create', self, this.on_form_dialog_saved);
+ this.form.on('record_created', self, this.on_form_dialog_saved);
this.form.on_saved.add_last(this.on_form_dialog_saved);
this.form.on_button_cancel = function() {
self.close();
diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js
index 45f5c98bf51..332f4e8d037 100644
--- a/addons/web_kanban/static/src/js/kanban.js
+++ b/addons/web_kanban/static/src/js/kanban.js
@@ -195,8 +195,8 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
form.on_button_cancel.add_last(am.dialog.on_close);
- form.on('on_rec_create', self, function(r) {
- (new instance.web.DataSet(self, self.group_by_field.relation)).name_get([r.result]).then(function(new_record) {
+ form.on('record_created', self, function(r) {
+ (new instance.web.DataSet(self, self.group_by_field.relation)).name_get([r]).then(function(new_record) {
am.dialog.on_close();
var domain = self.dataset.domain.slice(0);
domain.push([self.group_by, '=', new_record[0][0]]);
From 94e4c0750eceb46351d642c67e9e7b8b04cc50c6 Mon Sep 17 00:00:00 2001
From: Fabien Meghazi
Date: Wed, 10 Oct 2012 14:19:19 +0200
Subject: [PATCH 150/171] [IMP] auth_oauth2: log provider error
bzr revid: fme@openerp.com-20121010121919-cefodm7vzat5z321
---
addons/auth_oauth/controllers/main.py | 2 +-
addons/auth_oauth/res_users.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py
index ae01df5f6f7..7baac5d67c4 100644
--- a/addons/auth_oauth/controllers/main.py
+++ b/addons/auth_oauth/controllers/main.py
@@ -43,7 +43,7 @@ class OAuthController(openerpweb.Controller):
url = "/#action=login&oauth_error=1"
except Exception,e:
# signup error
- _logger.exception('oops')
+ _logger.exception("OAuth2: %s" % str(e))
url = "/#action=login&oauth_error=2"
return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, url)
diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py
index fd26e89c2e3..124c46d687c 100644
--- a/addons/auth_oauth/res_users.py
+++ b/addons/auth_oauth/res_users.py
@@ -41,7 +41,7 @@ class res_users(osv.Model):
validation = self.auth_oauth_rpc(cr, uid, p.validation_endpoint, access_token)
if validation.get("error"):
- raise openerp.exceptions.AccessDenied
+ raise Exception(validation['error'])
if p.data_endpoint:
data = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)
validation.update(data)
From aa4791450f7c7b7b1ff1027a807754206eb5fa84 Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 14:20:08 +0200
Subject: [PATCH 151/171] [FIX] account_voucher: wrong accounting entry for
supplier payment in foreign currency
lp bug: https://launchpad.net/bugs/1007487 fixed
bzr revid: qdp-launchpad@openerp.com-20121010122008-sb3tgrccik1968ga
---
addons/account_voucher/account_voucher.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index 423026251c2..f97f3f6af3c 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -1070,7 +1070,8 @@ class account_voucher(osv.osv):
if line.amount == line.amount_unreconciled:
if not line.move_line_id.amount_residual:
raise osv.except_osv(_('Wrong bank statement line'),_("You have to delete the bank statement line which the payment was reconciled to manually. Please check the payment of the partner %s by the amount of %s.")%(line.voucher_id.partner_id.name, line.voucher_id.amount))
- currency_rate_difference = line.move_line_id.amount_residual - amount
+ sign = voucher_brw.type in ('payment', 'purchase') and -1 or 1
+ currency_rate_difference = sign * (line.move_line_id.amount_residual - amount)
else:
currency_rate_difference = 0.0
move_line = {
From 3195c02971280355bf47135cb97979a60e1d432a Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 14:33:51 +0200
Subject: [PATCH 152/171] [FIX] Fixed on_created.
bzr revid: vta@openerp.com-20121010123351-gq8mr73z5avh79nd
---
addons/web/static/src/js/view_form.js | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index dc5721208e5..009de5a6211 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -131,7 +131,6 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
e.preventDefault();
}
});
- self.on('record_created', self, self.update_dataset);
},
destroy: function() {
_.each(this.get_widgets(), function(w) {
@@ -779,7 +778,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
var def = $.Deferred();
$.when(this.has_been_loaded).then(function() {
self.dataset.call('copy', [self.datarecord.id, {}, self.dataset.context]).then(function(new_id) {
- return self.trigger('record_created', { result : new_id });
+ return self.record_created({ result : new_id });
}).then(function() {
return self.to_edit_mode();
}).then(function() {
@@ -860,7 +859,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
if (!self.datarecord.id) {
// Creation save
save_deferral = self.dataset.create(values).pipe(function(r) {
- return self.trigger('record_created', r, prepend_on_create);
+ return self.record_created(r, prepend_on_create);
}, null);
} else if (_.isEmpty(values) && ! self.force_dirty) {
// Not dirty, noop save
@@ -919,9 +918,11 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
* @param {Boolean} [prepend_on_create=false] adds the newly created record
* at the beginning of the dataset instead of the end
*/
- update_dataset: function(r, prepend_on_create) {
+ record_created: function(r, prepend_on_create) {
+ var self = this;
if (!r) {
// should not happen in the server, but may happen for internal purpose
+ this.trigger('record_created', r);
return $.Deferred().reject();
} else {
this.datarecord.id = r;
@@ -935,9 +936,10 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.do_update_pager();
if (this.sidebar) {
this.sidebar.do_attachement_update(this.dataset, this.datarecord.id);
- }
+ }
//openerp.log("The record has been created with id #" + this.datarecord.id);
return $.when(this.reload()).pipe(function () {
+ self.trigger('record_created', r);
return _.extend(r, {created: true});
});
}
From b70d0dab52d3cbbb49d88ae2e9cc5e72f222cbc2 Mon Sep 17 00:00:00 2001
From: Xavier Morel
Date: Wed, 10 Oct 2012 14:38:27 +0200
Subject: [PATCH 153/171] [FIX] cases where options dict is decoded as unicode
strings on windows: csv.reader kwargs *must* be strings
bzr revid: xmo@openerp.com-20121010123827-x76udyurqzgnqebg
---
addons/base_import/models.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/base_import/models.py b/addons/base_import/models.py
index 16bb52d5856..996dbf7964d 100644
--- a/addons/base_import/models.py
+++ b/addons/base_import/models.py
@@ -128,8 +128,8 @@ class ir_import(orm.TransientModel):
"""
csv_iterator = csv.reader(
StringIO(record.file),
- quotechar=options['quoting'],
- delimiter=options['separator'])
+ quotechar=str(options['quoting']),
+ delimiter=str(options['separator']))
csv_nonempty = itertools.ifilter(None, csv_iterator)
# TODO: guess encoding with chardet? Or https://github.com/aadsm/jschardet
encoding = options.get('encoding', 'utf-8')
From 5cae4f05bf5a304b8ad7be3717cf0178180e4142 Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 14:46:26 +0200
Subject: [PATCH 154/171] [IMP] hr_expense: added monetary widget on expense
form view
bzr revid: qdp-launchpad@openerp.com-20121010124626-gw4inlqinqptubup
---
addons/hr_expense/hr_expense_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml
index 67d629eee6a..44853cee4f0 100644
--- a/addons/hr_expense/hr_expense_view.xml
+++ b/addons/hr_expense/hr_expense_view.xml
@@ -124,7 +124,7 @@
From 6ef264339c0870b7aee543f2c3fefeab7decc03c Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 14:52:12 +0200
Subject: [PATCH 155/171] [FIX] Fixed conflicts in kanban.js. Thanks to VME.
bzr revid: vta@openerp.com-20121010125212-oy5m304knbifad52
---
addons/web_kanban/static/src/js/kanban.js | 5 -----
1 file changed, 5 deletions(-)
diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js
index b786441cfc3..9176666e218 100644
--- a/addons/web_kanban/static/src/js/kanban.js
+++ b/addons/web_kanban/static/src/js/kanban.js
@@ -672,13 +672,8 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({
});
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
-<<<<<<< TREE
form.on("on_button_cancel", self, am.dialog.on_close);
form.on_saved.add_last(function() {
-=======
- form.on_button_cancel.add_last(am.dialog.on_close);
- form.on('on_saved', self, function() {
->>>>>>> MERGE-SOURCE
am.dialog.on_close();
self.view.do_reload();
});
From 7162a6255041642117c8e164eba59c7658ec9d73 Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 14:52:31 +0200
Subject: [PATCH 156/171] [IMP] account_asset: added monetary widget on asset
form view
bzr revid: qdp-launchpad@openerp.com-20121010125231-q3pmc65m5ujz2anr
---
addons/account_asset/account_asset_view.xml | 34 ++++++++++-----------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/addons/account_asset/account_asset_view.xml b/addons/account_asset/account_asset_view.xml
index 3fab306863c..520ee733e73 100644
--- a/addons/account_asset/account_asset_view.xml
+++ b/addons/account_asset/account_asset_view.xml
@@ -106,27 +106,27 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
From 7796ecaccf787b1a2f6833ff8c68fa1cfeec2d55 Mon Sep 17 00:00:00 2001
From: Fabien Meghazi
Date: Wed, 10 Oct 2012 14:55:45 +0200
Subject: [PATCH 157/171] [FIX] auth_oauth calling refactored method
bzr revid: fme@openerp.com-20121010125545-kolr1xcmgvtt1ouc
---
addons/auth_oauth/res_users.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py
index 124c46d687c..bdbe4128efb 100644
--- a/addons/auth_oauth/res_users.py
+++ b/addons/auth_oauth/res_users.py
@@ -66,7 +66,7 @@ class res_users(osv.Model):
'oauth_access_token': access_token,
'active': True,
}
- self.auth_signup_create(cr, uid, new_user)
+ self._signup_create_user(cr, uid, new_user)
credentials = (cr.dbname, email, access_token)
return credentials
From 94ac244a221866f246542dac82a344a9df82c3a6 Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 15:20:49 +0200
Subject: [PATCH 158/171] [FIX] Fixed on_saved.
bzr revid: vta@openerp.com-20121010132049-uuqru2c0k81s3o90
---
addons/web/static/src/js/view_form.js | 10 ++++++----
addons/web_calendar/static/src/js/calendar.js | 2 +-
addons/web_kanban/static/src/js/kanban.js | 2 +-
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index ce2e1ac5689..719c7146d45 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -131,7 +131,6 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
e.preventDefault();
}
});
- self.on("on_rec_save", self, self.on_saved);
},
destroy: function() {
_.each(this.get_widgets(), function(w) {
@@ -869,7 +868,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
self.force_dirty = false;
// Write save
save_deferral = self.dataset.write(self.datarecord.id, values, {}).pipe(function(r) {
- return self.trigger('on_rec_save', r);
+ return self.record_saved(r);
}, null);
}
return save_deferral;
@@ -896,12 +895,15 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
*
* @param {Object} r result of the write function.
*/
- on_saved: function(r) {
+ record_saved: function(r) {
+ var self = this;
if (!r) {
// should not happen in the server, but may happen for internal purpose
+ this.trigger('record_saved', r);
return $.Deferred().reject();
} else {
return $.when(this.reload()).pipe(function () {
+ self.trigger('record_saved', r);
return r;
});
}
@@ -1629,7 +1631,7 @@ instance.web.form.FormDialog = instance.web.Dialog.extend({
});
this.form.appendTo(this.$el);
this.form.on_created.add_last(this.on_form_dialog_saved);
- this.form.on('on_rec_save', this, this.on_form_dialog_saved);
+ this.form.on('record_saved', this, this.on_form_dialog_saved);
return this;
},
select_id: function(id) {
diff --git a/addons/web_calendar/static/src/js/calendar.js b/addons/web_calendar/static/src/js/calendar.js
index 37c49462b59..9042cf74003 100644
--- a/addons/web_calendar/static/src/js/calendar.js
+++ b/addons/web_calendar/static/src/js/calendar.js
@@ -459,7 +459,7 @@ instance.web_calendar.CalendarFormDialog = instance.web.Dialog.extend({
});
var def = this.form.appendTo(this.$el);
this.form.on_created.add_last(this.on_form_dialog_saved);
- this.form.on('on_rec_save', self, this.on_form_dialog_saved);
+ this.form.on('record_saved', self, this.on_form_dialog_saved);
this.form.on_button_cancel = function() {
self.close();
}
diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js
index 438b1f7cb14..ab742628bd0 100644
--- a/addons/web_kanban/static/src/js/kanban.js
+++ b/addons/web_kanban/static/src/js/kanban.js
@@ -673,7 +673,7 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({
var am = instance.webclient.action_manager;
var form = am.dialog_widget.views.form.controller;
form.on_button_cancel.add_last(am.dialog.on_close);
- form.on('on_rec_save', self, function() {
+ form.on('record_saved', self, function() {
am.dialog.on_close();
self.view.do_reload();
});
From cb89d2d842e5e40b4cbbdf17d94f3f7c2041914a Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 15:53:59 +0200
Subject: [PATCH 159/171] [FIX] account_voucher: wrong accounting entry for
supplier payment in foreign currency
lp bug: https://launchpad.net/bugs/1007487 fixed
bzr revid: qdp-launchpad@openerp.com-20121010135359-0h0cxeyvk8lrtzni
---
addons/account_voucher/account_voucher.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index 423026251c2..f97f3f6af3c 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -1070,7 +1070,8 @@ class account_voucher(osv.osv):
if line.amount == line.amount_unreconciled:
if not line.move_line_id.amount_residual:
raise osv.except_osv(_('Wrong bank statement line'),_("You have to delete the bank statement line which the payment was reconciled to manually. Please check the payment of the partner %s by the amount of %s.")%(line.voucher_id.partner_id.name, line.voucher_id.amount))
- currency_rate_difference = line.move_line_id.amount_residual - amount
+ sign = voucher_brw.type in ('payment', 'purchase') and -1 or 1
+ currency_rate_difference = sign * (line.move_line_id.amount_residual - amount)
else:
currency_rate_difference = 0.0
move_line = {
From ec5b3b7e64b3479e2647c6283404e12aa1db3f94 Mon Sep 17 00:00:00 2001
From: "Quentin (OpenERP)"
Date: Wed, 10 Oct 2012 15:54:14 +0200
Subject: [PATCH 160/171] [FIX] project: fixed error introduced in revision
7741
bzr revid: qdp-launchpad@openerp.com-20121010135414-q7hp9mu752j3z3rk
---
addons/project/project_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index b81db3c4b57..03c0ee2440b 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -103,7 +103,7 @@
-
+
From 4436d11ad733ee0e08bf8c9fe18ed413e6740241 Mon Sep 17 00:00:00 2001
From: Christophe Simonis
Date: Wed, 10 Oct 2012 16:01:04 +0200
Subject: [PATCH 161/171] [FIX] auth_oauth: add unique constraint on
(oauth_provide_id,oauth_uid) + do not try to create user if signup is not
installed
bzr revid: chs@openerp.com-20121010140104-4amqblnbu0es753x
---
addons/auth_oauth/res_users.py | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py
index bdbe4128efb..9c1f88bd7f4 100644
--- a/addons/auth_oauth/res_users.py
+++ b/addons/auth_oauth/res_users.py
@@ -15,13 +15,17 @@ class res_users(osv.Model):
_inherit = 'res.users'
_columns = {
- 'oauth_provider_id': fields.many2one('auth.oauth.provider','OAuth Provider'),
+ 'oauth_provider_id': fields.many2one('auth.oauth.provider', 'OAuth Provider'),
'oauth_uid': fields.char('OAuth User ID', help="Oauth Provider user_id"),
- 'oauth_access_token': fields.char('OAuth Token', readonly=True),
+ 'oauth_access_token': fields.char('OAuth Access Token', readonly=True),
}
+ _sql_constraints = [
+ ('uniq_users_oauth_provider_oauht_uid', 'unique(auth_provider_id, auth_uid)', 'OAuth UID must be unique per provider'),
+ ]
+
def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
- params = urllib.urlencode({ 'access_token': access_token })
+ params = urllib.urlencode({'access_token': access_token})
if urlparse.urlparse(endpoint)[4]:
url = endpoint + '&' + params
else:
@@ -48,15 +52,19 @@ class res_users(osv.Model):
# required
oauth_uid = validation['user_id']
if not oauth_uid:
- raise openerp.exceptions.AccessDenied
+ raise openerp.exceptions.AccessDenied()
email = validation.get('email', 'provider_%d_user_%d' % (p.id, oauth_uid))
# optional
name = validation.get('name', email)
- res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)])
+ res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid), ('oauth_provider_id', '=', provider)])
if res:
- self.write(cr, uid, res[0], { 'oauth_access_token': access_token })
+ assert len(res) == 1
+ self.write(cr, uid, res[0], {'oauth_access_token': access_token})
else:
- # New user
+ # New user if signup module available
+ if not hasattr(self, '_signup_create_user'):
+ raise openerp.exceptions.AccessDenied()
+
new_user = {
'name': name,
'login': email,
@@ -66,7 +74,9 @@ class res_users(osv.Model):
'oauth_access_token': access_token,
'active': True,
}
+ # TODO pass signup token to allow attach new user to right partner
self._signup_create_user(cr, uid, new_user)
+
credentials = (cr.dbname, email, access_token)
return credentials
@@ -74,7 +84,7 @@ class res_users(osv.Model):
try:
return super(res_users, self).check_credentials(cr, uid, password)
except openerp.exceptions.AccessDenied:
- res = self.search(cr, SUPERUSER_ID, [('id','=',uid),('oauth_access_token','=',password)])
+ res = self.search(cr, SUPERUSER_ID, [('id', '=', uid), ('oauth_access_token', '=', password)])
if not res:
raise
From 6b509ab8eae0808a272a8d5f145854e7e60b2c5c Mon Sep 17 00:00:00 2001
From: "vta vta@openerp.com" <>
Date: Wed, 10 Oct 2012 16:36:07 +0200
Subject: [PATCH 162/171] [FIX] on_unlink.
bzr revid: vta@openerp.com-20121010143607-nv3lhmy8r27m1ls9
---
addons/web/static/src/js/data.js | 8 +++-----
addons/web/static/src/js/view_form.js | 4 ++--
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js
index 79f909c0908..ce85e0ac43f 100644
--- a/addons/web/static/src/js/data.js
+++ b/addons/web/static/src/js/data.js
@@ -575,6 +575,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
* @param {Number|String} ids identifier of the record to delete
*/
unlink: function(ids) {
+ this.trigger('unlink', ids);
return this._model.call('unlink', [ids], {context: this._model.context()});
},
/**
@@ -694,7 +695,6 @@ instance.web.DataSetStatic = instance.web.DataSet.extend({
this._super(parent, model, context);
// all local records
this.ids = ids || [];
- self.on("on_rec_unlink", self, self.on_unlink);
},
read_slice: function (fields, options) {
options = options || {};
@@ -713,12 +713,10 @@ instance.web.DataSetStatic = instance.web.DataSet.extend({
}
},
unlink: function(ids) {
- this.trigger('on_rec_unlink', ids);
+ this.set_ids(_.without.apply(null, [this.ids].concat(ids)));
+ this.trigger('unlink', ids);
return $.Deferred().resolve({result: true});
},
- on_unlink: function(ids) {
- this.set_ids(_.without.apply(null, [this.ids].concat(ids)));
- }
});
instance.web.DataSetSearch = instance.web.DataSet.extend({
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 0266af3d40e..549a3154ff1 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -3998,7 +3998,7 @@ instance.web.form.FieldMany2Many = instance.web.form.AbstractField.extend({
this.dataset = new instance.web.form.Many2ManyDataSet(this, this.field.relation);
this.dataset.m2m = this;
- this.dataset.on('on_rec_unlink', self, function(ids) {
+ this.dataset.on('unlink', self, function(ids) {
self.dataset_changed();
});
@@ -4131,7 +4131,7 @@ instance.web.form.FieldMany2ManyKanban = instance.web.form.AbstractField.extend(
this.dataset = new instance.web.form.Many2ManyDataSet(this, this.field.relation);
this.dataset.m2m = this;
- this.dataset.on('on_rec_unlink', self, function(ids) {
+ this.dataset.on('unlink', self, function(ids) {
self.dataset_changed();
});
From 818fd9f67f9e416f130998293b0e466eb3659c0d Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Wed, 10 Oct 2012 19:24:18 +0200
Subject: [PATCH 163/171] remove standalone
bzr revid: al@openerp.com-20121010172418-27stgsd4w71cbxv4
---
addons/web/common/__init__.py | 1 -
addons/web/common/http.py | 101 ++------
addons/web/common/openerplib/__init__.py | 32 ---
addons/web/common/openerplib/dates.py | 97 -------
addons/web/common/openerplib/main.py | 311 -----------------------
addons/web/common/release.py | 10 -
addons/web/common/session.py | 144 +++++------
addons/web/controllers/main.py | 18 +-
8 files changed, 109 insertions(+), 605 deletions(-)
delete mode 100644 addons/web/common/openerplib/__init__.py
delete mode 100644 addons/web/common/openerplib/dates.py
delete mode 100644 addons/web/common/openerplib/main.py
delete mode 100644 addons/web/common/release.py
diff --git a/addons/web/common/__init__.py b/addons/web/common/__init__.py
index 4060be2f87e..d8fb717bb83 100644
--- a/addons/web/common/__init__.py
+++ b/addons/web/common/__init__.py
@@ -1,6 +1,5 @@
#!/usr/bin/python
from . import http
from . import nonliterals
-from . import release
from . import session
from . import xml2json
diff --git a/addons/web/common/http.py b/addons/web/common/http.py
index 3b9fdf302f3..d9524f31c54 100644
--- a/addons/web/common/http.py
+++ b/addons/web/common/http.py
@@ -6,15 +6,18 @@ import ast
import cgi
import contextlib
import functools
+import getpass
import logging
import mimetypes
import os
import pprint
import sys
+import tempfile
import threading
import time
import traceback
import urllib
+import urlparse
import uuid
import xmlrpclib
@@ -26,10 +29,10 @@ import werkzeug.utils
import werkzeug.wrappers
import werkzeug.wsgi
-from . import nonliterals
-from . import session
-from . import openerplib
-import urlparse
+import openerp
+
+import nonliterals
+import session
__all__ = ['Root', 'jsonrequest', 'httprequest', 'Controller',
'WebRequest', 'JsonRequest', 'HttpRequest']
@@ -46,7 +49,6 @@ class WebRequest(object):
:param request: a wrapped werkzeug Request object
:type request: :class:`werkzeug.wrappers.BaseRequest`
- :param config: configuration object
.. attribute:: httprequest
@@ -58,10 +60,6 @@ class WebRequest(object):
a :class:`~collections.Mapping` holding the HTTP session data for the
current http session
- .. attribute:: config
-
- config parameter provided to the request object
-
.. attribute:: params
:class:`~collections.Mapping` of request parameters, not generally
@@ -85,11 +83,10 @@ class WebRequest(object):
``bool``, indicates whether the debug mode is active on the client
"""
- def __init__(self, request, config):
+ def __init__(self, request):
self.httprequest = request
self.httpresponse = None
self.httpsession = request.session
- self.config = config
def init(self, params):
self.params = dict(params)
@@ -98,7 +95,6 @@ class WebRequest(object):
self.session = self.httpsession.get(self.session_id)
if not self.session:
self.httpsession[self.session_id] = self.session = session.OpenERPSession()
- self.session.config = self.config
self.context = self.params.pop('context', None)
self.debug = self.params.pop('debug', False) != False
@@ -180,7 +176,7 @@ class JsonRequest(WebRequest):
_logger.debug("--> %s.%s\n%s", controller.__class__.__name__, method.__name__, pprint.pformat(self.jsonrequest))
response['id'] = self.jsonrequest.get('id')
response["result"] = method(controller, self, **self.params)
- except openerplib.AuthenticationError:
+ except session.AuthenticationError:
error = {
'code': 100,
'message': "OpenERP Session Invalid",
@@ -238,8 +234,8 @@ def jsonrequest(f):
beforehand)
"""
@functools.wraps(f)
- def json_handler(controller, request, config):
- return JsonRequest(request, config).dispatch(controller, f)
+ def json_handler(controller, request):
+ return JsonRequest(request).dispatch(controller, f)
json_handler.exposed = True
return json_handler
@@ -325,8 +321,8 @@ def httprequest(f):
and ``debug`` keys (which are stripped out beforehand)
"""
@functools.wraps(f)
- def http_handler(controller, request, config):
- return HttpRequest(request, config).dispatch(controller, f)
+ def http_handler(controller, request):
+ return HttpRequest(request).dispatch(controller, f)
http_handler.exposed = True
return http_handler
@@ -425,6 +421,7 @@ def session_context(request, storage_path, session_cookie='httpsessionid'):
mimetypes.add_type('application/font-woff', '.woff')
mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
mimetypes.add_type('application/x-font-ttf', '.ttf')
+
class DisableCacheMiddleware(object):
def __init__(self, app):
self.app = app
@@ -449,45 +446,23 @@ class DisableCacheMiddleware(object):
class Root(object):
"""Root WSGI application for the OpenERP Web Client.
-
- :param options: mandatory initialization options object, must provide
- the following attributes:
-
- ``server_host`` (``str``)
- hostname of the OpenERP server to dispatch RPC to
- ``server_port`` (``int``)
- RPC port of the OpenERP server
- ``serve_static`` (``bool | None``)
- whether this application should serve the various
- addons's static files
- ``storage_path`` (``str``)
- filesystem path where HTTP session data will be stored
- ``dbfilter`` (``str``)
- only used in case the list of databases is requested
- by the server, will be filtered by this pattern
"""
- def __init__(self, options):
- self.config = options
-
- if not hasattr(self.config, 'connector'):
- if self.config.backend == 'local':
- self.config.connector = session.LocalConnector()
- else:
- self.config.connector = openerplib.get_connector(
- hostname=self.config.server_host, port=self.config.server_port)
-
+ def __init__(self):
self.httpsession_cookie = 'httpsessionid'
self.addons = {}
static_dirs = self._load_addons()
- if options.serve_static:
- app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs)
- self.dispatch = DisableCacheMiddleware(app)
+ app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs)
+ self.dispatch = DisableCacheMiddleware(app)
- if options.session_storage:
- if not os.path.exists(options.session_storage):
- os.mkdir(options.session_storage, 0700)
- self.session_storage = options.session_storage
+ try:
+ username = getpass.getuser()
+ except Exception:
+ username = "unknown"
+ self.session_storage = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
+
+ if not os.path.exists(self.session_storage):
+ os.mkdir(self.session_storage, 0700)
_logger.debug('HTTP sessions stored in: %s', self.session_storage)
def __call__(self, environ, start_response):
@@ -512,7 +487,7 @@ class Root(object):
response = werkzeug.exceptions.NotFound()
else:
with session_context(request, self.session_storage, self.httpsession_cookie) as session:
- result = handler( request, self.config)
+ result = handler( request)
if isinstance(result, basestring):
headers=[('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', len(result))]
@@ -531,7 +506,7 @@ class Root(object):
static URLs to the corresponding directories
"""
statics = {}
- for addons_path in self.config.addons_path:
+ for addons_path in openerp.modules.module.ad_paths:
for module in os.listdir(addons_path):
if module not in addons_module:
manifest_path = os.path.join(addons_path, module, '__openerp__.py')
@@ -579,28 +554,8 @@ class Root(object):
ps = '/'
return None
-class Options(object):
- pass
-
def wsgi_postload():
- import openerp
- import tempfile
- import getpass
- _logger.info("embedded mode")
- o = Options()
- o.dbfilter = openerp.tools.config['dbfilter']
- o.server_wide_modules = openerp.conf.server_wide_modules or ['web']
- try:
- username = getpass.getuser()
- except Exception:
- username = "unknown"
- o.session_storage = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
- o.addons_path = openerp.modules.module.ad_paths
- o.serve_static = True
- o.backend = 'local'
-
- app = Root(o)
- openerp.wsgi.register_wsgi_handler(app)
+ openerp.wsgi.register_wsgi_handler(Root())
# vim:et:ts=4:sw=4:
diff --git a/addons/web/common/openerplib/__init__.py b/addons/web/common/openerplib/__init__.py
deleted file mode 100644
index 44701ec22fe..00000000000
--- a/addons/web/common/openerplib/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# Copyright (C) Stephane Wirtel
-# Copyright (C) 2011 Nicolas Vanhoren
-# Copyright (C) 2011 OpenERP s.a. ().
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-##############################################################################
-
-from .main import *
-
diff --git a/addons/web/common/openerplib/dates.py b/addons/web/common/openerplib/dates.py
deleted file mode 100644
index 6d4fa9e2f63..00000000000
--- a/addons/web/common/openerplib/dates.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# Copyright (C) Stephane Wirtel
-# Copyright (C) 2011 Nicolas Vanhoren
-# Copyright (C) 2011 OpenERP s.a. ().
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-##############################################################################
-
-import datetime
-
-DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
-DEFAULT_SERVER_TIME_FORMAT = "%H:%M:%S"
-DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % (
- DEFAULT_SERVER_DATE_FORMAT,
- DEFAULT_SERVER_TIME_FORMAT)
-
-def str_to_datetime(str):
- """
- Converts a string to a datetime object using OpenERP's
- datetime string format (exemple: '2011-12-01 15:12:35').
-
- No timezone information is added, the datetime is a naive instance, but
- according to OpenERP 6.1 specification the timezone is always UTC.
- """
- if not str:
- return str
- return datetime.datetime.strptime(str, DEFAULT_SERVER_DATETIME_FORMAT)
-
-def str_to_date(str):
- """
- Converts a string to a date object using OpenERP's
- date string format (exemple: '2011-12-01').
- """
- if not str:
- return str
- return datetime.datetime.strptime(str, DEFAULT_SERVER_DATE_FORMAT).date()
-
-def str_to_time(str):
- """
- Converts a string to a time object using OpenERP's
- time string format (exemple: '15:12:35').
- """
- if not str:
- return str
- return datetime.datetime.strptime(str, DEFAULT_SERVER_TIME_FORMAT).time()
-
-def datetime_to_str(obj):
- """
- Converts a datetime object to a string using OpenERP's
- datetime string format (exemple: '2011-12-01 15:12:35').
-
- The datetime instance should not have an attached timezone and be in UTC.
- """
- if not obj:
- return False
- return obj.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
-
-def date_to_str(obj):
- """
- Converts a date object to a string using OpenERP's
- date string format (exemple: '2011-12-01').
- """
- if not obj:
- return False
- return obj.strftime(DEFAULT_SERVER_DATE_FORMAT)
-
-def time_to_str(obj):
- """
- Converts a time object to a string using OpenERP's
- time string format (exemple: '15:12:35').
- """
- if not obj:
- return False
- return obj.strftime(DEFAULT_SERVER_TIME_FORMAT)
-
diff --git a/addons/web/common/openerplib/main.py b/addons/web/common/openerplib/main.py
deleted file mode 100644
index 93c2d1da69d..00000000000
--- a/addons/web/common/openerplib/main.py
+++ /dev/null
@@ -1,311 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# Copyright (C) Stephane Wirtel
-# Copyright (C) 2011 Nicolas Vanhoren
-# Copyright (C) 2011 OpenERP s.a. ().
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-##############################################################################
-
-"""
-OpenERP Client Library
-
-Home page: http://pypi.python.org/pypi/openerp-client-lib
-Code repository: https://code.launchpad.net/~niv-openerp/openerp-client-lib/trunk
-"""
-
-import xmlrpclib
-import logging
-
-_logger = logging.getLogger(__name__)
-
-def _getChildLogger(logger, subname):
- return logging.getLogger(logger.name + "." + subname)
-
-class Connector(object):
- """
- The base abstract class representing a connection to an OpenERP Server.
- """
-
- __logger = _getChildLogger(_logger, 'connector')
-
- def get_service(self, service_name):
- """
- Returns a Service instance to allow easy manipulation of one of the services offered by the remote server.
-
- :param service_name: The name of the service.
- """
- return Service(self, service_name)
-
-class XmlRPCConnector(Connector):
- """
- A type of connector that uses the XMLRPC protocol.
- """
- PROTOCOL = 'xmlrpc'
-
- __logger = _getChildLogger(_logger, 'connector.xmlrpc')
-
- def __init__(self, hostname, port=8069):
- """
- Initialize by specifying the hostname and the port.
- :param hostname: The hostname of the computer holding the instance of OpenERP.
- :param port: The port used by the OpenERP instance for XMLRPC (default to 8069).
- """
- self.url = 'http://%s:%d/xmlrpc' % (hostname, port)
-
- def send(self, service_name, method, *args):
- url = '%s/%s' % (self.url, service_name)
- service = xmlrpclib.ServerProxy(url)
- return getattr(service, method)(*args)
-
-class XmlRPCSConnector(XmlRPCConnector):
- """
- A type of connector that uses the secured XMLRPC protocol.
- """
- PROTOCOL = 'xmlrpcs'
-
- __logger = _getChildLogger(_logger, 'connector.xmlrpcs')
-
- def __init__(self, hostname, port=8069):
- super(XmlRPCSConnector, self).__init__(hostname, port)
- self.url = 'https://%s:%d/xmlrpc' % (hostname, port)
-
-class Service(object):
- """
- A class to execute RPC calls on a specific service of the remote server.
- """
- def __init__(self, connector, service_name):
- """
- :param connector: A valid Connector instance.
- :param service_name: The name of the service on the remote server.
- """
- self.connector = connector
- self.service_name = service_name
- self.__logger = _getChildLogger(_getChildLogger(_logger, 'service'),service_name or "")
-
- def __getattr__(self, method):
- """
- :param method: The name of the method to execute on the service.
- """
- self.__logger.debug('method: %r', method)
- def proxy(*args):
- """
- :param args: A list of values for the method
- """
- self.__logger.debug('args: %r', args)
- result = self.connector.send(self.service_name, method, *args)
- self.__logger.debug('result: %r', result)
- return result
- return proxy
-
-class Connection(object):
- """
- A class to represent a connection with authentication to an OpenERP Server.
- It also provides utility methods to interact with the server more easily.
- """
- __logger = _getChildLogger(_logger, 'connection')
-
- def __init__(self, connector,
- database=None,
- login=None,
- password=None,
- user_id=None):
- """
- Initialize with login information. The login information is facultative to allow specifying
- it after the initialization of this object.
-
- :param connector: A valid Connector instance to send messages to the remote server.
- :param database: The name of the database to work on.
- :param login: The login of the user.
- :param password: The password of the user.
- :param user_id: The user id is a number identifying the user. This is only useful if you
- already know it, in most cases you don't need to specify it.
- """
- self.connector = connector
-
- self.set_login_info(database, login, password, user_id)
- self.user_context = None
-
- def set_login_info(self, database, login, password, user_id=None):
- """
- Set login information after the initialisation of this object.
-
- :param connector: A valid Connector instance to send messages to the remote server.
- :param database: The name of the database to work on.
- :param login: The login of the user.
- :param password: The password of the user.
- :param user_id: The user id is a number identifying the user. This is only useful if you
- already know it, in most cases you don't need to specify it.
- """
- self.database, self.login, self.password = database, login, password
-
- self.user_id = user_id
-
- def check_login(self, force=True):
- """
- Checks that the login information is valid. Throws an AuthenticationError if the
- authentication fails.
-
- :param force: Force to re-check even if this Connection was already validated previously.
- Default to True.
- """
- if self.user_id and not force:
- return
-
- if not self.database or not self.login or self.password is None:
- raise AuthenticationError("Credentials not provided")
-
- # TODO use authenticate instead of login
- self.user_id = self.get_service("common").login(self.database, self.login, self.password)
- if not self.user_id:
- raise AuthenticationError("Authentication failure")
- self.__logger.debug("Authenticated with user id %s", self.user_id)
-
- def get_user_context(self):
- """
- Query the default context of the user.
- """
- if not self.user_context:
- self.user_context = self.get_model('res.users').context_get()
- return self.user_context
-
- def get_model(self, model_name):
- """
- Returns a Model instance to allow easy remote manipulation of an OpenERP model.
-
- :param model_name: The name of the model.
- """
- return Model(self, model_name)
-
- def get_service(self, service_name):
- """
- Returns a Service instance to allow easy manipulation of one of the services offered by the remote server.
- Please note this Connection instance does not need to have valid authentication information since authentication
- is only necessary for the "object" service that handles models.
-
- :param service_name: The name of the service.
- """
- return self.connector.get_service(service_name)
-
-class AuthenticationError(Exception):
- """
- An error thrown when an authentication to an OpenERP server failed.
- """
- pass
-
-class Model(object):
- """
- Useful class to dialog with one of the models provided by an OpenERP server.
- An instance of this class depends on a Connection instance with valid authentication information.
- """
-
- def __init__(self, connection, model_name):
- """
- :param connection: A valid Connection instance with correct authentication information.
- :param model_name: The name of the model.
- """
- self.connection = connection
- self.model_name = model_name
- self.__logger = _getChildLogger(_getChildLogger(_logger, 'object'), model_name or "")
-
- def __getattr__(self, method):
- """
- Provides proxy methods that will forward calls to the model on the remote OpenERP server.
-
- :param method: The method for the linked model (search, read, write, unlink, create, ...)
- """
- def proxy(*args, **kw):
- """
- :param args: A list of values for the method
- """
- self.connection.check_login(False)
- self.__logger.debug(args)
- result = self.connection.get_service('object').execute_kw(
- self.connection.database,
- self.connection.user_id,
- self.connection.password,
- self.model_name,
- method,
- args, kw)
- if method == "read":
- if isinstance(result, list) and len(result) > 0 and "id" in result[0]:
- index = {}
- for r in result:
- index[r['id']] = r
- result = [index[x] for x in args[0] if x in index]
- self.__logger.debug('result: %r', result)
- return result
- return proxy
-
- def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, context=None):
- """
- A shortcut method to combine a search() and a read().
-
- :param domain: The domain for the search.
- :param fields: The fields to extract (can be None or [] to extract all fields).
- :param offset: The offset for the rows to read.
- :param limit: The maximum number of rows to read.
- :param order: The order to class the rows.
- :param context: The context.
- :return: A list of dictionaries containing all the specified fields.
- """
- record_ids = self.search(domain or [], offset, limit or False, order or False, context or {})
- if not record_ids: return []
- records = self.read(record_ids, fields or [], context or {})
- return records
-
-def get_connector(hostname=None, protocol="xmlrpc", port="auto"):
- """
- A shortcut method to easily create a connector to a remote server using XMLRPC.
-
- :param hostname: The hostname to the remote server.
- :param protocol: The name of the protocol, must be "xmlrpc" or "xmlrpcs".
- :param port: The number of the port. Defaults to auto.
- """
- if port == 'auto':
- port = 8069
- if protocol == "xmlrpc":
- return XmlRPCConnector(hostname, port)
- elif protocol == "xmlrpcs":
- return XmlRPCSConnector(hostname, port)
- else:
- raise ValueError("You must choose xmlrpc or xmlrpcs")
-
-def get_connection(hostname=None, protocol="xmlrpc", port='auto', database=None,
- login=None, password=None, user_id=None):
- """
- A shortcut method to easily create a connection to a remote OpenERP server.
-
- :param hostname: The hostname to the remote server.
- :param protocol: The name of the protocol, must be "xmlrpc" or "xmlrpcs".
- :param port: The number of the port. Defaults to auto.
- :param connector: A valid Connector instance to send messages to the remote server.
- :param database: The name of the database to work on.
- :param login: The login of the user.
- :param password: The password of the user.
- :param user_id: The user id is a number identifying the user. This is only useful if you
- already know it, in most cases you don't need to specify it.
- """
- return Connection(get_connector(hostname, protocol, port), database, login, password, user_id)
-
diff --git a/addons/web/common/release.py b/addons/web/common/release.py
deleted file mode 100644
index b9dafd330d0..00000000000
--- a/addons/web/common/release.py
+++ /dev/null
@@ -1,10 +0,0 @@
-name = 'openerp-web'
-version = '7.0alpha'
-description = "OpenERP Web"
-long_description = "OpenERP Web is the web interface of OpenERP, an Open Source Business Application Suite"
-author = "OpenERP SA"
-author_email = "info@openerp.com"
-support_email = 'support@openerp.com'
-url = "http://www.openerp.com/"
-download_url = ''
-license = "AGPL"
diff --git a/addons/web/common/session.py b/addons/web/common/session.py
index 45bbb32f64c..e57d3da5b45 100644
--- a/addons/web/common/session.py
+++ b/addons/web/common/session.py
@@ -4,70 +4,58 @@ import babel
import dateutil.relativedelta
import logging
import time
+import traceback
import sys
+import xmlrpclib
-import openerplib
+import openerp
-from . import nonliterals
+import nonliterals
_logger = logging.getLogger(__name__)
-#----------------------------------------------------------
-# openerplib local connector
-#----------------------------------------------------------
-class LibException(Exception):
- """ Base of all client lib exceptions """
- def __init__(self,code=None,message=None):
- self.code = code
- self.message = message
-
-class ApplicationError(LibException):
- """ maps to code: 1, server side: Exception or openerp.exceptions.DeferredException"""
-
-class Warning(LibException):
- """ maps to code: 2, server side: openerp.exceptions.Warning"""
-
-class AccessError(LibException):
- """ maps to code: 3, server side: openerp.exceptions.AccessError"""
-
-class AccessDenied(LibException):
- """ maps to code: 4, server side: openerp.exceptions.AccessDenied"""
-
-class LocalConnector(openerplib.Connector):
- """
- A type of connector that uses the XMLRPC protocol.
- """
- PROTOCOL = 'local'
-
- def __init__(self):
- pass
-
- def send(self, service_name, method, *args):
- import openerp
- import traceback
- import xmlrpclib
- code_string = "warning -- %s\n\n%s"
- try:
- return openerp.netsvc.dispatch_rpc(service_name, method, args)
- except openerp.osv.osv.except_osv, e:
- # TODO change the except to raise LibException instead of their emulated xmlrpc fault
- raise xmlrpclib.Fault(code_string % (e.name, e.value), '')
- except openerp.exceptions.Warning, e:
- raise xmlrpclib.Fault(code_string % ("Warning", e), '')
- except openerp.exceptions.AccessError, e:
- raise xmlrpclib.Fault(code_string % ("AccessError", e), '')
- except openerp.exceptions.AccessDenied, e:
- raise xmlrpclib.Fault('AccessDenied', str(e))
- except openerp.exceptions.DeferredException, e:
- formatted_info = "".join(traceback.format_exception(*e.traceback))
- raise xmlrpclib.Fault(openerp.tools.ustr(e.message), formatted_info)
- except Exception, e:
- formatted_info = "".join(traceback.format_exception(*(sys.exc_info())))
- raise xmlrpclib.Fault(openerp.tools.exception_to_unicode(e), formatted_info)
-
#----------------------------------------------------------
# OpenERPSession RPC openerp backend access
#----------------------------------------------------------
+class AuthenticationError(Exception):
+ pass
+
+class Service(object):
+ def __init__(self, session, service_name):
+ self.session = session
+ self.service_name = service_name
+
+ def __getattr__(self, method):
+ def proxy_method(*args):
+ result = self.session.send(self.service_name, method, *args)
+ return result
+ return proxy_method
+
+class Model(object):
+ def __init__(self, session, model):
+ self.session = session
+ self.model = model
+ self.proxy = self.session.proxy('object')
+
+ def __getattr__(self, method):
+ def proxy(*args, **kw):
+ result = self.proxy.execute_kw(self.session._db, self.session._uid, self.session._password, self.model, method, args, kw)
+ # reorder read
+ if method == "read":
+ if isinstance(result, list) and len(result) > 0 and "id" in result[0]:
+ index = {}
+ for r in result:
+ index[r['id']] = r
+ result = [index[x] for x in args[0] if x in index]
+ return result
+ return proxy
+
+ def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, context=None):
+ record_ids = self.search(domain or [], offset, limit or False, order or False, context or {})
+ if not record_ids: return []
+ records = self.read(record_ids, fields or [], context or {})
+ return records
+
class OpenERPSession(object):
"""
An OpenERP RPC session, a given user can own multiple such sessions
@@ -87,7 +75,6 @@ class OpenERPSession(object):
"""
def __init__(self):
self._creation_time = time.time()
- self.config = None
self._db = False
self._uid = False
self._login = False
@@ -98,19 +85,27 @@ class OpenERPSession(object):
self.domains_store = {}
self.jsonp_requests = {} # FIXME use a LRU
- def __getstate__(self):
- state = dict(self.__dict__)
- if "config" in state:
- del state['config']
- return state
-
- def build_connection(self):
- conn = openerplib.Connection(self.config.connector, database=self._db, login=self._login,
- user_id=self._uid, password=self._password)
- return conn
+ def send(self, service_name, method, *args):
+ code_string = "warning -- %s\n\n%s"
+ try:
+ return openerp.netsvc.dispatch_rpc(service_name, method, args)
+ except openerp.osv.osv.except_osv, e:
+ raise xmlrpclib.Fault(code_string % (e.name, e.value), '')
+ except openerp.exceptions.Warning, e:
+ raise xmlrpclib.Fault(code_string % ("Warning", e), '')
+ except openerp.exceptions.AccessError, e:
+ raise xmlrpclib.Fault(code_string % ("AccessError", e), '')
+ except openerp.exceptions.AccessDenied, e:
+ raise xmlrpclib.Fault('AccessDenied', str(e))
+ except openerp.exceptions.DeferredException, e:
+ formatted_info = "".join(traceback.format_exception(*e.traceback))
+ raise xmlrpclib.Fault(openerp.tools.ustr(e.message), formatted_info)
+ except Exception, e:
+ formatted_info = "".join(traceback.format_exception(*(sys.exc_info())))
+ raise xmlrpclib.Fault(openerp.tools.exception_to_unicode(e), formatted_info)
def proxy(self, service):
- return self.build_connection().get_service(service)
+ return Service(self, service)
def bind(self, db, uid, login, password):
self._db = db
@@ -119,7 +114,6 @@ class OpenERPSession(object):
self._password = password
def authenticate(self, db, login, password, env=None):
- # TODO use the openerplib API once it exposes authenticate()
uid = self.proxy('common').authenticate(db, login, password, env)
self.bind(db, uid, login, password)
@@ -130,7 +124,12 @@ class OpenERPSession(object):
"""
Ensures this session is valid (logged into the openerp server)
"""
- self.build_connection().check_login(force)
+ if self._uid and not force:
+ return
+ # TODO use authenticate instead of login
+ uid = self.proxy("common").login(self._db, self._login, self._password)
+ if not uid:
+ raise AuthenticationError("Authentication failure")
def ensure_valid(self):
if self._uid:
@@ -141,7 +140,7 @@ class OpenERPSession(object):
def execute(self, model, func, *l, **d):
self.assert_valid()
- model = self.build_connection().get_model(model)
+ model = self.model(model)
r = getattr(model, func)(*l, **d)
return r
@@ -157,7 +156,8 @@ class OpenERPSession(object):
:type model: str
:rtype: a model object
"""
- return self.build_connection().get_model(model)
+
+ return Model(self, model)
def get_context(self):
""" Re-initializes the current user's session context (based on
@@ -167,7 +167,7 @@ class OpenERPSession(object):
:returns: the new context
"""
assert self._uid, "The user needs to be logged-in to initialize his context"
- self.context = self.build_connection().get_user_context() or {}
+ self.context = self.model('res.users').context_get() or {}
self.context['uid'] = self._uid
self._fix_lang(self.context)
return self.context
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 85e9bc076be..94e84168139 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -27,6 +27,8 @@ try:
except ImportError:
xlwt = None
+import openerp
+
from .. import common
openerpweb = common.http
@@ -135,7 +137,7 @@ def db_list(req):
dbs = proxy.list()
h = req.httprequest.environ['HTTP_HOST'].split(':')[0]
d = h.split('.')[0]
- r = req.config.dbfilter.replace('%h', h).replace('%d', d)
+ r = openerp.tools.config['dbfilter'].replace('%h', h).replace('%d', d)
dbs = [i for i in dbs if re.match(r, i)]
return dbs
@@ -227,11 +229,12 @@ def module_installed_bypass_session(dbname):
return sorted_modules
def module_boot(req):
- return [m for m in req.config.server_wide_modules if m in openerpweb.addons_manifest]
+ server_wide_modules = openerp.conf.server_wide_modules or ['web']
+ return [m for m in server_wide_modules if m in openerpweb.addons_manifest]
# TODO the following will be enabled once we separate the module code and translation loading
serverside = []
dbside = []
- for i in req.config.server_wide_modules:
+ for i in server_wide_modules:
if i in openerpweb.addons_manifest:
serverside.append(i)
# if only one db load every module at boot
@@ -507,7 +510,7 @@ def parse_domain(domain, session):
:param domain: the domain to parse, if the domain is not a string it
is assumed to be a literal domain and is returned as-is
:param session: Current OpenERP session
- :type session: openerpweb.openerpweb.OpenERPSession
+ :type session: openerpweb.OpenERPSession
"""
if not isinstance(domain, basestring):
return domain
@@ -524,7 +527,7 @@ def parse_context(context, session):
:param context: the context to parse, if the context is not a string it
is assumed to be a literal domain and is returned as-is
:param session: Current OpenERP session
- :type session: openerpweb.openerpweb.OpenERPSession
+ :type session: openerpweb.OpenERPSession
"""
if not isinstance(context, basestring):
return context
@@ -612,7 +615,6 @@ class Home(openerpweb.Controller):
def login(self, req, db, login, key):
return login_and_redirect(req, db, login, key)
-
class WebClient(openerpweb.Controller):
_cp_path = "/web/webclient"
@@ -746,7 +748,7 @@ class WebClient(openerpweb.Controller):
@openerpweb.jsonrequest
def version_info(self, req):
return {
- "version": common.release.version
+ "version": openerp.release.version
}
class Proxy(openerpweb.Controller):
@@ -862,12 +864,10 @@ class Session(openerpweb.Controller):
@openerpweb.jsonrequest
def authenticate(self, req, db, login, password, base_location=None):
wsgienv = req.httprequest.environ
- release = common.release
env = dict(
base_location=base_location,
HTTP_HOST=wsgienv['HTTP_HOST'],
REMOTE_ADDR=wsgienv['REMOTE_ADDR'],
- user_agent="%s / %s" % (release.name, release.version),
)
req.session.authenticate(db, login, password, env)
From ae6ff0764b709880c458c54a850594db8eed795a Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Wed, 10 Oct 2012 22:37:53 +0200
Subject: [PATCH 164/171] web remove common, fix imports
bzr revid: al@openerp.com-20121010203753-azrcz3k2kd44ni24
---
addons/web/__init__.py | 4 +-
addons/web/common/__init__.py | 5 ---
addons/web/common/xml2json.py | 26 ------------
addons/web/controllers/main.py | 59 ++++++++++++++++++--------
addons/web/{common => }/http.py | 12 ++----
addons/web/{common => }/nonliterals.py | 0
addons/web/{common => }/session.py | 0
addons/web_diagram/controllers/main.py | 15 ++-----
addons/web_graph/controllers/graph.py | 13 ++----
9 files changed, 55 insertions(+), 79 deletions(-)
delete mode 100644 addons/web/common/__init__.py
delete mode 100644 addons/web/common/xml2json.py
rename addons/web/{common => }/http.py (98%)
rename addons/web/{common => }/nonliterals.py (100%)
rename addons/web/{common => }/session.py (100%)
diff --git a/addons/web/__init__.py b/addons/web/__init__.py
index c4337b37d2c..3b447ce748d 100644
--- a/addons/web/__init__.py
+++ b/addons/web/__init__.py
@@ -1,4 +1,4 @@
-import common
+import http
import controllers
-wsgi_postload = common.http.wsgi_postload
+wsgi_postload = http.wsgi_postload
diff --git a/addons/web/common/__init__.py b/addons/web/common/__init__.py
deleted file mode 100644
index d8fb717bb83..00000000000
--- a/addons/web/common/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/python
-from . import http
-from . import nonliterals
-from . import session
-from . import xml2json
diff --git a/addons/web/common/xml2json.py b/addons/web/common/xml2json.py
deleted file mode 100644
index df3aad67fa5..00000000000
--- a/addons/web/common/xml2json.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# xml2json-direct
-# Simple and straightforward XML-to-JSON converter in Python
-# New BSD Licensed
-#
-# URL: http://code.google.com/p/xml2json-direct/
-
-def from_elementtree(el, preserve_whitespaces=False):
- res = {}
- if el.tag[0] == "{":
- ns, name = el.tag.rsplit("}", 1)
- res["tag"] = name
- res["namespace"] = ns[1:]
- else:
- res["tag"] = el.tag
- res["attrs"] = {}
- for k, v in el.items():
- res["attrs"][k] = v
- kids = []
- if el.text and (preserve_whitespaces or el.text.strip() != ''):
- kids.append(el.text)
- for kid in el:
- kids.append(from_elementtree(kid, preserve_whitespaces))
- if kid.tail and (preserve_whitespaces or kid.tail.strip() != ''):
- kids.append(kid.tail)
- res["children"] = kids
- return res
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 94e84168139..72ffd9567f6 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -29,8 +29,9 @@ except ImportError:
import openerp
-from .. import common
-openerpweb = common.http
+from .. import http
+from .. import nonliterals
+openerpweb = http
#----------------------------------------------------------
# OpenERP Web helpers
@@ -505,7 +506,7 @@ def fix_view_modes(action):
def parse_domain(domain, session):
""" Parses an arbitrary string containing a domain, transforms it
- to either a literal domain or a :class:`common.nonliterals.Domain`
+ to either a literal domain or a :class:`nonliterals.Domain`
:param domain: the domain to parse, if the domain is not a string it
is assumed to be a literal domain and is returned as-is
@@ -518,11 +519,11 @@ def parse_domain(domain, session):
return ast.literal_eval(domain)
except ValueError:
# not a literal
- return common.nonliterals.Domain(session, domain)
+ return nonliterals.Domain(session, domain)
def parse_context(context, session):
""" Parses an arbitrary string containing a context, transforms it
- to either a literal context or a :class:`common.nonliterals.Context`
+ to either a literal context or a :class:`nonliterals.Context`
:param context: the context to parse, if the context is not a string it
is assumed to be a literal domain and is returned as-is
@@ -534,8 +535,7 @@ def parse_context(context, session):
try:
return ast.literal_eval(context)
except ValueError:
- return common.nonliterals.Context(session, context)
-
+ return nonliterals.Context(session, context)
def _local_web_translations(trans_file):
messages = []
@@ -549,6 +549,31 @@ def _local_web_translations(trans_file):
messages.append({'id': x.id, 'string': x.string})
return messages
+def from_elementtree(el, preserve_whitespaces=False):
+ """ xml2json-direct
+ Simple and straightforward XML-to-JSON converter in Python
+ New BSD Licensed
+ http://code.google.com/p/xml2json-direct/
+ """
+ res = {}
+ if el.tag[0] == "{":
+ ns, name = el.tag.rsplit("}", 1)
+ res["tag"] = name
+ res["namespace"] = ns[1:]
+ else:
+ res["tag"] = el.tag
+ res["attrs"] = {}
+ for k, v in el.items():
+ res["attrs"][k] = v
+ kids = []
+ if el.text and (preserve_whitespaces or el.text.strip() != ''):
+ kids.append(el.text)
+ for kid in el:
+ kids.append(from_elementtree(kid, preserve_whitespaces))
+ if kid.tail and (preserve_whitespaces or kid.tail.strip() != ''):
+ kids.append(kid.tail)
+ res["children"] = kids
+ return res
#----------------------------------------------------------
# OpenERP Web web Controllers
@@ -942,8 +967,8 @@ class Session(openerpweb.Controller):
no group by should be performed)
"""
context, domain = eval_context_and_domain(req.session,
- common.nonliterals.CompoundContext(*(contexts or [])),
- common.nonliterals.CompoundDomain(*(domains or [])))
+ nonliterals.CompoundContext(*(contexts or [])),
+ nonliterals.CompoundDomain(*(domains or [])))
group_by_sequence = []
for candidate in (group_by_seq or []):
@@ -1165,14 +1190,14 @@ class DataSet(openerpweb.Controller):
def _call_kw(self, req, model, method, args, kwargs):
for i in xrange(len(args)):
- if isinstance(args[i], common.nonliterals.BaseContext):
+ if isinstance(args[i], nonliterals.BaseContext):
args[i] = req.session.eval_context(args[i])
- elif isinstance(args[i], common.nonliterals.BaseDomain):
+ elif isinstance(args[i], nonliterals.BaseDomain):
args[i] = req.session.eval_domain(args[i])
for k in kwargs.keys():
- if isinstance(kwargs[k], common.nonliterals.BaseContext):
+ if isinstance(kwargs[k], nonliterals.BaseContext):
kwargs[k] = req.session.eval_context(kwargs[k])
- elif isinstance(kwargs[k], common.nonliterals.BaseDomain):
+ elif isinstance(kwargs[k], nonliterals.BaseDomain):
kwargs[k] = req.session.eval_domain(kwargs[k])
# Temporary implements future display_name special field for model#read()
@@ -1303,7 +1328,7 @@ class View(openerpweb.Controller):
xml = self.transform_view(arch, session, evaluation_context)
else:
xml = ElementTree.fromstring(arch)
- fvg['arch'] = common.xml2json.from_elementtree(xml, preserve_whitespaces)
+ fvg['arch'] = from_elementtree(xml, preserve_whitespaces)
if 'id' in fvg['fields']:
# Special case for id's
@@ -1436,12 +1461,12 @@ class SearchView(View):
try:
parsed_context = parse_context(filter["context"], req.session)
filter["context"] = (parsed_context
- if not isinstance(parsed_context, common.nonliterals.BaseContext)
+ if not isinstance(parsed_context, nonliterals.BaseContext)
else req.session.eval_context(parsed_context))
parsed_domain = parse_domain(filter["domain"], req.session)
filter["domain"] = (parsed_domain
- if not isinstance(parsed_domain, common.nonliterals.BaseDomain)
+ if not isinstance(parsed_domain, nonliterals.BaseDomain)
else req.session.eval_domain(parsed_domain))
except Exception:
logger.exception("Failed to parse custom filter %s in %s",
@@ -1932,7 +1957,7 @@ class Reports(View):
report_srv = req.session.proxy("report")
context = req.session.eval_context(
- common.nonliterals.CompoundContext(
+ nonliterals.CompoundContext(
req.context or {}, action[ "context"]))
report_data = {}
diff --git a/addons/web/common/http.py b/addons/web/http.py
similarity index 98%
rename from addons/web/common/http.py
rename to addons/web/http.py
index d9524f31c54..65630768737 100644
--- a/addons/web/common/http.py
+++ b/addons/web/http.py
@@ -34,13 +34,10 @@ import openerp
import nonliterals
import session
-__all__ = ['Root', 'jsonrequest', 'httprequest', 'Controller',
- 'WebRequest', 'JsonRequest', 'HttpRequest']
-
_logger = logging.getLogger(__name__)
#----------------------------------------------------------
-# OpenERP Web RequestHandler
+# RequestHandler
#----------------------------------------------------------
class WebRequest(object):
""" Parent class for all OpenERP Web request types, mostly deals with
@@ -327,7 +324,7 @@ def httprequest(f):
return http_handler
#----------------------------------------------------------
-# OpenERP Web Controller registration with a metaclass
+# Controller registration with a metaclass
#----------------------------------------------------------
addons_module = {}
addons_manifest = {}
@@ -344,7 +341,7 @@ class Controller(object):
__metaclass__ = ControllerType
#----------------------------------------------------------
-# OpenERP Web Session context manager
+# Session context manager
#----------------------------------------------------------
STORES = {}
@@ -415,7 +412,7 @@ def session_context(request, storage_path, session_cookie='httpsessionid'):
session_store.save(request.session)
#----------------------------------------------------------
-# OpenERP Web WSGI Application
+# WSGI Application
#----------------------------------------------------------
# Add potentially missing (older ubuntu) font mime types
mimetypes.add_type('application/font-woff', '.woff')
@@ -557,5 +554,4 @@ class Root(object):
def wsgi_postload():
openerp.wsgi.register_wsgi_handler(Root())
-
# vim:et:ts=4:sw=4:
diff --git a/addons/web/common/nonliterals.py b/addons/web/nonliterals.py
similarity index 100%
rename from addons/web/common/nonliterals.py
rename to addons/web/nonliterals.py
diff --git a/addons/web/common/session.py b/addons/web/session.py
similarity index 100%
rename from addons/web/common/session.py
rename to addons/web/session.py
diff --git a/addons/web_diagram/controllers/main.py b/addons/web_diagram/controllers/main.py
index e3d626ad48b..6af1f91adc0 100644
--- a/addons/web_diagram/controllers/main.py
+++ b/addons/web_diagram/controllers/main.py
@@ -1,21 +1,14 @@
-try:
- # embedded
- import openerp.addons.web.common.http as openerpweb
- from openerp.addons.web.controllers.main import View
-except ImportError:
- # standalone
- import web.common.http as openerpweb
- from web.controllers.main import View
+import openerp
-class DiagramView(View):
+class DiagramView(openerp.addons.web.controllers.main.View):
_cp_path = "/web_diagram/diagram"
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def load(self, req, model, view_id):
fields_view = self.fields_view_get(req, model, view_id, 'diagram')
return {'fields_view': fields_view}
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def get_diagram_info(self, req, id, model, node, connector,
src_node, des_node, label, **kw):
diff --git a/addons/web_graph/controllers/graph.py b/addons/web_graph/controllers/graph.py
index e5c15898155..21ec7d6e973 100644
--- a/addons/web_graph/controllers/graph.py
+++ b/addons/web_graph/controllers/graph.py
@@ -1,19 +1,12 @@
# -*- coding: utf-8 -*-
-try:
- # embedded
- import openerp.addons.web.common.http as openerpweb
- from openerp.addons.web.controllers.main import View
-except ImportError:
- # standalone
- import web.common.http as openerpweb
- from web.controllers.main import View
+import openerp
from lxml import etree
-class GraphView(View):
+class GraphView(openerp.addons.web.controllers.main.View):
_cp_path = '/web_graph/graph'
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def data_get(self, req, model=None, domain=[], context={}, group_by=[], view_id=False, orientation=False, stacked=False, mode="bar", **kwargs):
obj = req.session.model(model)
From 84a7523a631db1af67dadfd1e83fd6164c18b6a2 Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Wed, 10 Oct 2012 22:46:17 +0200
Subject: [PATCH 165/171] [IMP] remove standalone web client, fix imports
bzr revid: al@openerp.com-20121010204617-ah29rz616xo7i2dr
---
addons/auth_oauth/controllers/main.py | 15 +++---
addons/auth_openid/controllers/main.py | 23 ++++-----
.../auth_reset_password/controllers/main.py | 14 +++---
addons/auth_signup/controllers/main.py | 21 ++++----
addons/base_import/controllers.py | 9 ++--
addons/board/controllers.py | 15 ++----
addons/point_of_sale/controllers/main.py | 48 +++++++++----------
addons/web_linkedin/web_linkedin.py | 13 ++---
addons/web_shortcuts/controllers/main.py | 13 ++---
9 files changed, 70 insertions(+), 101 deletions(-)
diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py
index 7baac5d67c4..26016f3f0a1 100644
--- a/addons/auth_oauth/controllers/main.py
+++ b/addons/auth_oauth/controllers/main.py
@@ -4,28 +4,25 @@ import simplejson
import werkzeug.urls
import werkzeug.utils
-import openerp.modules.registry
-import openerp.addons.web.controllers.main
-import openerp.addons.web.common.http as openerpweb
-from openerp import SUPERUSER_ID
+import openerp
_logger = logging.getLogger(__name__)
-class OAuthController(openerpweb.Controller):
+class OAuthController(openerp.addons.web.http.Controller):
_cp_path = '/auth_oauth'
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def list_providers(self, req, dbname):
try:
registry = openerp.modules.registry.RegistryManager.get(dbname)
with registry.cursor() as cr:
providers = registry.get('auth.oauth.provider')
- l = providers.read(cr, SUPERUSER_ID, providers.search(cr, SUPERUSER_ID, [('enabled','=',True)]))
+ l = providers.read(cr, openerp.SUPERUSER_ID, providers.search(cr, openerp.SUPERUSER_ID, [('enabled','=',True)]))
except Exception:
l = []
return l
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def signin(self, req, **kw):
state = simplejson.loads(kw['state'])
dbname = state['d']
@@ -34,7 +31,7 @@ class OAuthController(openerpweb.Controller):
with registry.cursor() as cr:
try:
u = registry.get('res.users')
- credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw)
+ credentials = u.auth_oauth(cr, openerp.SUPERUSER_ID, provider, kw)
cr.commit()
return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials)
except AttributeError:
diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py
index ebcaab4bf25..7ee562d4d29 100644
--- a/addons/auth_openid/controllers/main.py
+++ b/addons/auth_openid/controllers/main.py
@@ -23,24 +23,21 @@ import logging
import os
import tempfile
import urllib
-from openerp import SUPERUSER_ID
import werkzeug.urls
import werkzeug.exceptions
-from openerp.modules.registry import RegistryManager
-from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect
-try:
- import openerp.addons.web.common.http as openerpweb
-except ImportError:
- import web.common.http as openerpweb # noqa
-
from openid import oidutil
from openid.store import filestore
from openid.consumer import consumer
from openid.cryptutil import randomString
from openid.extensions import ax, sreg
+import openerp
+from openerp import SUPERUSER_ID
+from openerp.modules.registry import RegistryManager
+from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect
+
from .. import utils
_logger = logging.getLogger(__name__)
@@ -70,7 +67,7 @@ class GoogleAppsAwareConsumer(consumer.GenericConsumer):
return super(GoogleAppsAwareConsumer, self).complete(message, endpoint, return_to)
-class OpenIDController(openerpweb.Controller):
+class OpenIDController(openerp.addons.web.http.Controller):
_cp_path = '/auth_openid/login'
_store = filestore.FileOpenIDStore(_storedir)
@@ -118,7 +115,7 @@ class OpenIDController(openerpweb.Controller):
def _get_realm(self, req):
return req.httprequest.host_url
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def verify_direct(self, req, db, url):
result = self._verify(req, db, url)
if 'error' in result:
@@ -127,7 +124,7 @@ class OpenIDController(openerpweb.Controller):
return werkzeug.utils.redirect(result['value'])
return result['value']
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def verify(self, req, db, url):
return self._verify(req, db, url)
@@ -157,7 +154,7 @@ class OpenIDController(openerpweb.Controller):
form_html = request.htmlMarkup(realm, redirect_to)
return {'action': 'post', 'value': form_html, 'session_id': req.session_id}
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def process(self, req, **kw):
session = getattr(req.session, 'openid_session', None)
if not session:
@@ -225,7 +222,7 @@ class OpenIDController(openerpweb.Controller):
return set_cookie_and_redirect(req, '/#action=login&loginerror=1')
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def status(self, req):
session = getattr(req.session, 'openid_session', {})
return {'status': session.get('status'), 'message': session.get('message')}
diff --git a/addons/auth_reset_password/controllers/main.py b/addons/auth_reset_password/controllers/main.py
index 5185a65c3ce..639945cfc09 100644
--- a/addons/auth_reset_password/controllers/main.py
+++ b/addons/auth_reset_password/controllers/main.py
@@ -18,20 +18,20 @@
# along with this program. If not, see
#
##############################################################################
-
-from openerp import SUPERUSER_ID
-from openerp.modules.registry import RegistryManager
-import openerp.addons.web.common.http as openerpweb
+import logging
import werkzeug
-import logging
+import openerp
+from openerp import SUPERUSER_ID
+from openerp.modules.registry import RegistryManager
+
_logger = logging.getLogger(__name__)
-class Controller(openerpweb.Controller):
+class Controller(openerp.addons.web.http.Controller):
_cp_path = '/auth_reset_password'
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def reset_password(self, req, dbname, login):
""" retrieve user, and perform reset password """
url = '/'
diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
index 56e5e910212..cf72e581049 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -18,31 +18,30 @@
# along with this program. If not, see
#
##############################################################################
-
-from openerp import SUPERUSER_ID
-from openerp.modules.registry import RegistryManager
-from openerp.addons.web.controllers.main import login_and_redirect
-import openerp.addons.web.common.http as openerpweb
+import logging
import werkzeug
-import logging
+import openerp
+from openerp.modules.registry import RegistryManager
+from openerp.addons.web.controllers.main import login_and_redirect
+
_logger = logging.getLogger(__name__)
-class Controller(openerpweb.Controller):
+class Controller(openerp.addons.web.http.Controller):
_cp_path = '/auth_signup'
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def retrieve(self, req, dbname, token):
""" retrieve the user info (name, login or email) corresponding to a signup token """
registry = RegistryManager.get(dbname)
user_info = None
with registry.cursor() as cr:
res_partner = registry.get('res.partner')
- user_info = res_partner.signup_retrieve_info(cr, SUPERUSER_ID, token)
+ user_info = res_partner.signup_retrieve_info(cr, openerp.SUPERUSER_ID, token)
return user_info
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def signup(self, req, dbname, token, name, login, password):
""" sign up a user (new or existing), and log it in """
url = '/'
@@ -51,7 +50,7 @@ class Controller(openerpweb.Controller):
try:
res_users = registry.get('res.users')
values = {'name': name, 'login': login, 'password': password}
- credentials = res_users.signup(cr, SUPERUSER_ID, values, token)
+ credentials = res_users.signup(cr, openerp.SUPERUSER_ID, values, token)
cr.commit()
return login_and_redirect(req, *credentials)
except Exception as e:
diff --git a/addons/base_import/controllers.py b/addons/base_import/controllers.py
index 85ff993e92e..c831ffd229d 100644
--- a/addons/base_import/controllers.py
+++ b/addons/base_import/controllers.py
@@ -1,15 +1,12 @@
# -*- coding: utf-8 -*-
import simplejson
-try:
- import openerp.addons.web.common.http as openerpweb
-except ImportError:
- import web.common.http as openerpweb
+import openerp
-class ImportController(openerpweb.Controller):
+class ImportController(openerp.addons.web.http.Controller):
_cp_path = '/base_import'
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def set_file(self, req, file, import_id, jsonp='callback'):
import_id = int(import_id)
diff --git a/addons/board/controllers.py b/addons/board/controllers.py
index 53845c96095..81557f64fa3 100644
--- a/addons/board/controllers.py
+++ b/addons/board/controllers.py
@@ -1,19 +1,14 @@
# -*- coding: utf-8 -*-
from xml.etree import ElementTree
-try:
- import openerp.addons.web.common.http as openerpweb
- from openerp.addons.web.common import nonliterals
- from openerp.addons.web.controllers.main import load_actions_from_ir_values
-except ImportError:
- import web.common.http as openerpweb # noqa
- from web.common import nonliterals # noqa
- from web.controllers.main import load_actions_from_ir_values # noqa
+import openerp
+from openerp.addons.web import nonliterals
+from openerp.addons.web.controllers.main import load_actions_from_ir_values
-class Board(openerpweb.Controller):
+class Board(openerp.addons.web.http.Controller):
_cp_path = '/board'
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def add_to_dashboard(self, req, menu_id, action_id, context_to_save, domain, view_mode, name=''):
# FIXME move this method to board.board model
to_eval = nonliterals.CompoundContext(context_to_save)
diff --git a/addons/point_of_sale/controllers/main.py b/addons/point_of_sale/controllers/main.py
index 3d80fd53e24..b189c8f204a 100644
--- a/addons/point_of_sale/controllers/main.py
+++ b/addons/point_of_sale/controllers/main.py
@@ -4,16 +4,12 @@ import simplejson
import os
import openerp
-try:
- import openerp.addons.web.common.http as openerpweb
- from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template
-except ImportError:
- import web.common.http as openerpweb
+from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template
-class PointOfSaleController(openerpweb.Controller):
+class PointOfSaleController(openerp.addons.web.http.Controller):
_cp_path = '/pos'
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def app(self, req, s_action=None, **kw):
js = "\n ".join('' % i for i in manifest_list(req, None, 'js'))
css = "\n ".join(' ' % i for i in manifest_list(req, None, 'css'))
@@ -29,7 +25,7 @@ class PointOfSaleController(openerpweb.Controller):
}
return r
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def manifest(self, req, **kwargs):
""" This generates a HTML5 cache manifest files that preloads the categories and products thumbnails
and other ressources necessary for the point of sale to work offline """
@@ -66,12 +62,12 @@ class PointOfSaleController(openerpweb.Controller):
return m
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def dispatch(self, request, iface, **kwargs):
method = 'iface_%s' % iface
return getattr(self, method)(request, **kwargs)
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def scan_item_success(self, request, ean):
"""
A product has been scanned with success
@@ -79,7 +75,7 @@ class PointOfSaleController(openerpweb.Controller):
print 'scan_item_success: ' + str(ean)
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def scan_item_error_unrecognized(self, request, ean):
"""
A product has been scanned without success
@@ -87,7 +83,7 @@ class PointOfSaleController(openerpweb.Controller):
print 'scan_item_error_unrecognized: ' + str(ean)
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def help_needed(self, request):
"""
The user wants an help (ex: light is on)
@@ -95,7 +91,7 @@ class PointOfSaleController(openerpweb.Controller):
print "help_needed"
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def help_canceled(self, request):
"""
The user stops the help request
@@ -103,22 +99,22 @@ class PointOfSaleController(openerpweb.Controller):
print "help_canceled"
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def weighting_start(self, request):
print "weighting_start"
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def weighting_read_kg(self, request):
print "weighting_read_kg"
return 0.0
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def weighting_end(self, request):
print "weighting_end"
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def payment_request(self, request, price):
"""
The PoS will activate the method payment
@@ -126,47 +122,47 @@ class PointOfSaleController(openerpweb.Controller):
print "payment_request: price:"+str(price)
return 'ok'
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def payment_status(self, request):
print "payment_status"
return { 'status':'waiting' }
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def payment_cancel(self, request):
print "payment_cancel"
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def transaction_start(self, request):
print 'transaction_start'
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def transaction_end(self, request):
print 'transaction_end'
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def cashier_mode_activated(self, request):
print 'cashier_mode_activated'
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def cashier_mode_deactivated(self, request):
print 'cashier_mode_deactivated'
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def open_cashbox(self, request):
print 'open_cashbox'
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def print_receipt(self, request, receipt):
print 'print_receipt' + str(receipt)
return
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def print_pdf_invoice(self, request, pdfinvoice):
print 'print_pdf_invoice' + str(pdfinvoice)
return
diff --git a/addons/web_linkedin/web_linkedin.py b/addons/web_linkedin/web_linkedin.py
index ea94329f8b1..71865c7fcc1 100644
--- a/addons/web_linkedin/web_linkedin.py
+++ b/addons/web_linkedin/web_linkedin.py
@@ -19,21 +19,16 @@
#
##############################################################################
-try:
- # embedded
- import openerp.addons.web.common.http as openerpweb
-except ImportError:
- # standalone
- import web.common.http as openerpweb
-
import base64
import urllib2
+
+import openerp
from osv import osv, fields
-class Binary(openerpweb.Controller):
+class Binary(openerp.addons.web.http.Controller):
_cp_path = "/web_linkedin/binary"
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def url2binary(self, req,url):
bfile = urllib2.urlopen(url)
return base64.b64encode(bfile.read())
diff --git a/addons/web_shortcuts/controllers/main.py b/addons/web_shortcuts/controllers/main.py
index 23f4bbd3fbe..2cdf232ac0f 100644
--- a/addons/web_shortcuts/controllers/main.py
+++ b/addons/web_shortcuts/controllers/main.py
@@ -1,16 +1,9 @@
-try:
- # embedded
- import openerp.addons.web.common.http as openerpweb
- import openerp.addons.web.controllers.main as webmain
-except ImportError:
- # standalone
- import web.common.http as openerpweb
- import web.controllers.main as webmain
+import openerp
-class Shortcuts(openerpweb.Controller):
+class Shortcuts(openerp.addons.web.http.Controller):
_cp_path = "/web/shortcuts"
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def list(self, req):
return req.session.model('ir.ui.view_sc').get_sc(
req.session._uid, "ir.ui.menu", req.session.eval_context(req.context))
From 0dbd9b603aa389b6c40ab1a072fc96808c249d89 Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Wed, 10 Oct 2012 22:48:29 +0200
Subject: [PATCH 166/171] [IMP] remove standalone web client, fix logging
bzr revid: al@openerp.com-20121010204829-5vamumz9lhxpsgob
---
openerp/netsvc.py | 3 +--
openerp/tools/config.py | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/openerp/netsvc.py b/openerp/netsvc.py
index c1a31602262..e2e435a746f 100644
--- a/openerp/netsvc.py
+++ b/openerp/netsvc.py
@@ -192,8 +192,7 @@ def init_logger():
default_config = [
'openerp.netsvc.rpc.request:INFO',
'openerp.netsvc.rpc.response:INFO',
- 'openerp.addons.web.common.http:INFO',
- 'openerp.addons.web.common.openerplib:INFO',
+ 'openerp.addons.web.http:INFO',
'openerp.sql_db:INFO',
':INFO',
]
diff --git a/openerp/tools/config.py b/openerp/tools/config.py
index 18b442221c9..56f1e5c7b83 100644
--- a/openerp/tools/config.py
+++ b/openerp/tools/config.py
@@ -182,7 +182,7 @@ class configmanager(object):
group.add_option('--log-handler', action="append", default=[':INFO'], my_default=[':INFO'], metavar="PREFIX:LEVEL", help='setup a handler at LEVEL for a given PREFIX. An empty PREFIX indicates the root logger. This option can be repeated. Example: "openerp.orm:DEBUG" or "werkzeug:CRITICAL" (default: ":INFO")')
group.add_option('--log-request', action="append_const", dest="log_handler", const="openerp.netsvc.rpc.request:DEBUG", help='shortcut for --log-handler=openerp.netsvc.rpc.request:DEBUG')
group.add_option('--log-response', action="append_const", dest="log_handler", const="openerp.netsvc.rpc.response:DEBUG", help='shortcut for --log-handler=openerp.netsvc.rpc.response:DEBUG')
- group.add_option('--log-web', action="append_const", dest="log_handler", const="openerp.addons.web.common.http:DEBUG", help='shortcut for --log-handler=openerp.addons.web.common.http:DEBUG')
+ group.add_option('--log-web', action="append_const", dest="log_handler", const="openerp.addons.web.http:DEBUG", help='shortcut for --log-handler=openerp.addons.web.http:DEBUG')
group.add_option('--log-sql', action="append_const", dest="log_handler", const="openerp.sql_db:DEBUG", help='shortcut for --log-handler=openerp.sql_db:DEBUG')
# For backward-compatibility, map the old log levels to something
# quite close.
From a7891a99bb7fada087a96a91125dcaf0d3f66965 Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Wed, 10 Oct 2012 23:23:52 +0200
Subject: [PATCH 167/171] [MERGE] trunk-export_terminology-mdi manually
bzr revid: al@openerp.com-20121010212352-ulfyar0j2x2w2jbo
---
addons/web/static/src/js/view_form.js | 2 +-
addons/web/static/src/xml/base.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index c8b3667b334..2b4569eea3f 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -3827,7 +3827,7 @@ instance.web.form.One2ManyList = instance.web.ListView.List.extend({
colspan: columns,
'class': 'oe_form_field_one2many_list_row_add'
}).append(
- $('', {href: '#'}).text(_t("Add a row"))
+ $(' ', {href: '#'}).text(_t("Add an item"))
.mousedown(function () {
// FIXME: needs to be an official API somehow
if (self.view.editor.is_editing()) {
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 544fc0b8061..a09897862f6 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1537,7 +1537,7 @@
Export Type:
- Import Compatible Export
+ Import-Compatible Export
Export all Data
From b1b8447a6b7afe9a78a42a0cdcee58384690fd09 Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Thu, 11 Oct 2012 02:02:17 +0200
Subject: [PATCH 168/171] [FIX] login always set params for potential
redirection
bzr revid: al@openerp.com-20121011000217-ck3xsquoain1z8ja
---
addons/web/static/src/js/chrome.js | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index 80693d26e46..ffec074a975 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -1016,15 +1016,13 @@ instance.web.WebClient = instance.web.Client.extend({
},
show_login: function() {
this.toggle_bars(false);
-
+
+ var state = $.bbq.getState(true);
var action = {
'type': 'ir.actions.client',
- 'tag': 'login'
+ 'tag': 'login',
+ 'params': state
};
- var state = $.bbq.getState(true);
- if (state.action === "login") {
- action.params = state;
- }
this.action_manager.do_action(action);
this.action_manager.inner_widget.on('login_successful', this, function() {
From 462eccb10d3f3c4c374ad6c305c89dcc5eb57cdf Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Thu, 11 Oct 2012 02:05:34 +0200
Subject: [PATCH 169/171] [FIX] auth_signup pass on the state
bzr revid: al@openerp.com-20121011000534-w3wa7m3mh1znylde
---
addons/auth_signup/controllers/main.py | 4 ++--
addons/auth_signup/res_users.py | 12 ++++--------
addons/auth_signup/static/src/js/auth_signup.js | 1 +
3 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
index cf72e581049..54dcc5b4362 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -42,7 +42,7 @@ class Controller(openerp.addons.web.http.Controller):
return user_info
@openerp.addons.web.http.httprequest
- def signup(self, req, dbname, token, name, login, password):
+ def signup(self, req, dbname, token, name, login, password, state=''):
""" sign up a user (new or existing), and log it in """
url = '/'
registry = RegistryManager.get(dbname)
@@ -52,7 +52,7 @@ class Controller(openerp.addons.web.http.Controller):
values = {'name': name, 'login': login, 'password': password}
credentials = res_users.signup(cr, openerp.SUPERUSER_ID, values, token)
cr.commit()
- return login_and_redirect(req, *credentials)
+ return login_and_redirect(req, *credentials, redirect_url='/#%s'%state)
except Exception as e:
# signup error
_logger.exception('error when signup')
diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py
index 7b663bd0e33..59196c4da87 100644
--- a/addons/auth_signup/res_users.py
+++ b/addons/auth_signup/res_users.py
@@ -18,6 +18,10 @@
# along with this program. If not, see
#
##############################################################################
+import random
+import time
+import urllib
+import urlparse
import openerp
from openerp.osv import osv, fields
@@ -25,11 +29,6 @@ from openerp import SUPERUSER_ID
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval
-import time
-import random
-import urllib
-import urlparse
-
def random_token():
# the token has an entropy of about 120 bits (6 bits/char * 20 chars)
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
@@ -38,7 +37,6 @@ def random_token():
def now():
return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
-
class res_partner(osv.Model):
_inherit = 'res.partner'
@@ -132,8 +130,6 @@ class res_partner(osv.Model):
res['email'] = partner.email or ''
return res
-
-
class res_users(osv.Model):
_inherit = 'res.users'
diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js
index 509fafa35cc..0974b73292d 100644
--- a/addons/auth_signup/static/src/js/auth_signup.js
+++ b/addons/auth_signup/static/src/js/auth_signup.js
@@ -90,6 +90,7 @@ openerp.auth_signup = function(instance) {
name: name,
login: login,
password: password,
+ state: $.param(this.params)
};
var url = "/auth_signup/signup?" + $.param(params);
window.location = url;
From f44ea704fe562dc346b280c6f546e5bc8d630387 Mon Sep 17 00:00:00 2001
From: Antony Lesuisse
Date: Thu, 11 Oct 2012 02:37:29 +0200
Subject: [PATCH 170/171] [IMP] CrashManager use event dispatcher and cleanups
bzr revid: al@openerp.com-20121011003729-jjbh5se1cpsachvm
---
addons/web/static/src/js/chrome.js | 20 ++++++++++----------
addons/web/static/src/js/corelib.js | 9 ++++-----
addons/web/static/src/js/view_form.js | 10 +++-------
3 files changed, 17 insertions(+), 22 deletions(-)
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index ffec074a975..b605f4ad4e1 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -181,7 +181,7 @@ instance.web.Dialog = instance.web.Widget.extend({
});
instance.web.CrashManager = instance.web.CallbackEnabled.extend({
- on_rpc_error: function(error) {
+ rpc_error: function(error) {
if (error.data.fault_code) {
var split = ("" + error.data.fault_code).split('\n')[0].split(' -- ');
if (split.length > 1) {
@@ -190,12 +190,12 @@ instance.web.CrashManager = instance.web.CallbackEnabled.extend({
}
}
if (error.code === 200 && error.type) {
- this.on_managed_error(error);
+ this.show_warning(error);
} else {
- this.on_traceback(error);
+ this.show_error(error);
}
},
- on_managed_error: function(error) {
+ show_warning: function(error) {
instance.web.dialog($('' + QWeb.render('CrashManager.warning', {error: error}) + '
'), {
title: "OpenERP " + _.str.capitalize(error.type),
buttons: [
@@ -203,7 +203,7 @@ instance.web.CrashManager = instance.web.CallbackEnabled.extend({
]
});
},
- on_traceback: function(error) {
+ show_error: function(error) {
var self = this;
var buttons = {};
buttons[_t("Ok")] = function() {
@@ -219,8 +219,8 @@ instance.web.CrashManager = instance.web.CallbackEnabled.extend({
}).open();
dialog.$el.html(QWeb.render('CrashManager.error', {session: instance.session, error: error}));
},
- on_javascript_exception: function(exception) {
- this.on_traceback({
+ show_message: function(exception) {
+ this.show_error({
type: _t("Client Error"),
message: exception,
data: {debug: ""}
@@ -236,7 +236,7 @@ instance.web.Loading = instance.web.Widget.extend({
this.blocked_ui = false;
this.session.on("request", this, this.request_call);
this.session.on("response", this, this.response_call);
- this.session.on("error", this, this.response_call);
+ this.session.on("response_failed", this, this.response_call);
},
destroy: function() {
this.on_rpc_event(-this.count);
@@ -957,7 +957,7 @@ instance.web.Client = instance.web.Widget.extend({
show_common: function() {
var self = this;
this.crashmanager = new instance.web.CrashManager();
- instance.session.on_rpc_error.add(this.crashmanager.on_rpc_error);
+ instance.session.on('error', this.crashmanager, this.crashmanager.rpc_error);
self.notification = new instance.web.Notification(this);
self.notification.appendTo(self.$el);
self.loading = new instance.web.Loading(self);
@@ -1007,7 +1007,7 @@ instance.web.WebClient = instance.web.Client.extend({
var self = this;
this._super();
window.onerror = function (message, file, line) {
- self.crashmanager.on_traceback({
+ self.crashmanager.show_error({
type: _t("Client Error"),
message: message,
data: {debug: file + ':' + line}
diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js
index 7a9af79b4fb..b5fbacc7927 100644
--- a/addons/web/static/src/js/corelib.js
+++ b/addons/web/static/src/js/corelib.js
@@ -980,7 +980,8 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
triggers: {
'request': 'Request sent',
'response': 'Response received',
- 'error': 'HTTP Error response or timeout received',
+ 'response_failed': 'HTTP Error response or timeout received',
+ 'error': 'The received response is an JSON-RPC error',
},
/**
* @constructs instance.web.JsonRPC
@@ -1336,7 +1337,7 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
}
},
function(jqXHR, textStatus, errorThrown) {
- self.trigger('error');
+ self.trigger('response_failed', jqXHR);
var error = {
code: -32098,
message: "XmlHttpRequestError " + errorThrown,
@@ -1348,7 +1349,7 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
deferred.fail(function() {
deferred.fail(function(error, event) {
if (!event.isDefaultPrevented()) {
- self.on_rpc_error(error, event);
+ self.trigger('error', error, event);
}
});
});
@@ -1434,8 +1435,6 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
return deferred;
}
},
- on_rpc_error: function(error) {
- },
get_url: function (file) {
return this.prefix + file;
},
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 2b4569eea3f..afb5e258c0b 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -615,7 +615,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
return self.on_processed_onchange(response, processed);
} catch(e) {
console.error(e);
- instance.webclient.crashmanager.on_javascript_exception(e);
+ instance.webclient.crashmanager.show_message(e);
return $.Deferred().reject();
}
});
@@ -650,7 +650,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
return $.Deferred().resolve();
} catch(e) {
console.error(e);
- instance.webclient.crashmanager.on_javascript_exception(e);
+ instance.webclient.crashmanager.show_message(e);
return $.Deferred().reject();
}
},
@@ -3316,11 +3316,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
var views = [];
_.each(modes, function(mode) {
if (! _.include(["list", "tree", "graph", "kanban"], mode)) {
- try {
- throw new Error(_.str.sprintf("View type '%s' is not supported in One2Many.", mode));
- } catch(e) {
- instance.webclient.crashmanager.on_javascript_exception(e)
- }
+ throw new Error(_.str.sprintf("View type '%s' is not supported in One2Many.", mode));
}
var view = {
view_id: false,
From fc94df2af5146d2780da3b07bf1fad78e6831889 Mon Sep 17 00:00:00 2001
From: Launchpad Translations on behalf of openerp <>
Date: Thu, 11 Oct 2012 05:00:45 +0000
Subject: [PATCH 171/171] Launchpad automatic translations update.
bzr revid: launchpad_translations_on_behalf_of_openerp-20121011050045-qe3vhe34wrjw1xb8
---
addons/hr_payroll/i18n/es_MX.po | 2302 ++++++++++----------------
addons/l10n_in_hr_payroll/i18n/bn.po | 926 +----------
addons/l10n_in_hr_payroll/i18n/gu.po | 926 +----------
addons/l10n_in_hr_payroll/i18n/hi.po | 926 +----------
addons/l10n_in_hr_payroll/i18n/ta.po | 926 +----------
addons/l10n_in_hr_payroll/i18n/te.po | 926 +----------
6 files changed, 861 insertions(+), 6071 deletions(-)
diff --git a/addons/hr_payroll/i18n/es_MX.po b/addons/hr_payroll/i18n/es_MX.po
index a0f4837d947..24b8d615a63 100644
--- a/addons/hr_payroll/i18n/es_MX.po
+++ b/addons/hr_payroll/i18n/es_MX.po
@@ -1,1759 +1,1119 @@
-# Spanish translation for openobject-addons
-# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
+# Spanish (Mexico) translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
-# FIRST AUTHOR , 2010.
+# FIRST AUTHOR , 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME \n"
-"POT-Creation-Date: 2011-01-11 11:15+0000\n"
-"PO-Revision-Date: 2011-01-18 11:08+0000\n"
-"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
-"\n"
-"Language-Team: Spanish \n"
+"POT-Creation-Date: 2012-02-08 01:37+0100\n"
+"PO-Revision-Date: 2012-10-10 21:29+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Spanish (Mexico) \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2011-09-05 05:46+0000\n"
-"X-Generator: Launchpad (build 13830)\n"
+"X-Launchpad-Export-Date: 2012-10-11 05:00+0000\n"
+"X-Generator: Launchpad (build 16118)\n"
#. module: hr_payroll
-#: report:employees.salary:0
-msgid "E-mail Address"
-msgstr "Dirección de correo electrónico"
+#: field:hr.payslip.line,condition_select:0
+#: field:hr.salary.rule,condition_select:0
+msgid "Condition Based on"
+msgstr ""
#. module: hr_payroll
-#: view:hr.allounce.deduction.categoty:0
-msgid "Based"
-msgstr "Basado"
+#: selection:hr.contract,schedule_pay:0
+msgid "Monthly"
+msgstr ""
#. module: hr_payroll
-#: field:hr.contract,net:0
-#: field:hr.employee,net:0
-#: field:hr.payroll.register,net:0
-#: field:hr.payslip,net:0
-#: report:salary.structure:0
-msgid "Net Salary"
-msgstr "Salario neto"
+#: view:hr.payslip:0 field:hr.payslip,line_ids:0
+#: model:ir.actions.act_window,name:hr_payroll.act_contribution_reg_payslip_lines
+msgid "Payslip Lines"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip.line:0
+#: model:ir.model,name:hr_payroll.model_hr_salary_rule_category
+#: report:paylip.details:0
+msgid "Salary Rule Category"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.salary.rule.category,parent_id:0
+msgid ""
+"Linking a salary category to its parent is used only for the reporting "
+"purpose."
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0 view:hr.payslip.line:0 view:hr.salary.rule:0
+msgid "Group By..."
+msgstr ""
#. module: hr_payroll
#: view:hr.payslip:0
-msgid "Recompute Sheet"
-msgstr "Recalcular plantilla"
+msgid "States"
+msgstr ""
#. module: hr_payroll
-#: report:employees.salary:0
-msgid "Employees Salary Details"
-msgstr "Detalles salario de los empleados"
+#: field:hr.payslip.line,input_ids:0 view:hr.salary.rule:0
+#: field:hr.salary.rule,input_ids:0
+msgid "Inputs"
+msgstr ""
#. module: hr_payroll
-#: report:employees.salary:0
-msgid "Allowances with Basic:"
-msgstr "Primas con base:"
+#: field:hr.payslip.line,parent_rule_id:0
+#: field:hr.salary.rule,parent_rule_id:0
+msgid "Parent Salary Rule"
+msgstr ""
#. module: hr_payroll
-#: report:employees.salary:0
-#: report:salary.structure:0
-msgid "Department"
-msgstr "Departamento"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-msgid "Deductions:"
-msgstr "Deducciones:"
-
-#. module: hr_payroll
-#: field:company.contribution,gratuity:0
-msgid "Use for Gratuity ?"
-msgstr "¿Uso de propina?"
-
-#. module: hr_payroll
-#: field:hr.contract,working_days_per_week:0
-#: field:hr.payslip,working_days:0
-#: report:payslip.pdf:0
-msgid "Working Days"
-msgstr "Días de trabajo"
-
-#. module: hr_payroll
-#: selection:hr.allounce.deduction.categoty,type:0
-#: selection:hr.payslip.line,type:0
-msgid "Loan"
-msgstr "Préstamo"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "Salary Payment Register"
-msgstr "Registro de pago de nómina"
-
-#. module: hr_payroll
-#: field:hr.employee,slip_ids:0
-#: view:hr.payroll.register:0
-#: field:hr.payroll.register,line_ids:0
+#: field:hr.employee,slip_ids:0 view:hr.payslip:0 view:hr.payslip.run:0
+#: field:hr.payslip.run,slip_ids:0
#: model:ir.actions.act_window,name:hr_payroll.act_hr_employee_payslip_list
msgid "Payslips"
-msgstr "Nóminas"
-
-#. module: hr_payroll
-#: model:ir.actions.report.xml,name:hr_payroll.year_salary_report
-msgid "Year Salary Report"
-msgstr "Informe anual de salarios"
-
-#. module: hr_payroll
-#: selection:hr.payroll.register,state:0
-#: selection:hr.payslip,state:0
-msgid "Paid Salary"
-msgstr "Nómina pagada"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "("
-msgstr "("
-
-#. module: hr_payroll
-#: field:company.contribution,company_id:0
-#: field:hr.allounce.deduction.categoty,company_id:0
-#: field:hr.contibution.register,company_id:0
-#: field:hr.holidays.status,company_id:0
-#: field:hr.payroll.advice,company_id:0
-#: field:hr.payroll.register,company_id:0
-#: field:hr.payroll.structure,company_id:0
-#: field:hr.payslip,company_id:0
-msgid "Company"
-msgstr "Compañía"
-
-#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "The Manager"
-msgstr "El responsable"
-
-#. module: hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Letter Details"
-msgstr "Detalles de la carta"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-#: report:payslip.pdf:0
-msgid ","
-msgstr ","
-
-#. module: hr_payroll
-#: view:hr.payroll.advice:0
-#: view:hr.payroll.register:0
-#: view:hr.payslip:0
-msgid "Set to Draft"
-msgstr "Cambiar a borrador"
-
-#. module: hr_payroll
-#: code:addons/hr_payroll/hr_payroll.py:180
-#: code:addons/hr_payroll/hr_payroll.py:195
-#: code:addons/hr_payroll/hr_payroll.py:285
-#: code:addons/hr_payroll/hr_payroll.py:835
-#: code:addons/hr_payroll/hr_payroll.py:1111
-#: code:addons/hr_payroll/hr_payroll.py:1126
-#: code:addons/hr_payroll/hr_payroll.py:1410
-#, python-format
-msgid "Variable Error: %s "
-msgstr "Error variable: %s "
-
-#. module: hr_payroll
-#: view:hr.passport:0
-msgid "Expire"
-msgstr "Vencimiento"
-
-#. module: hr_payroll
-#: selection:hr.holidays.status,type:0
-msgid "Half-Pay Holiday"
-msgstr "Vacaciones con media paga"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-#: field:hr.payslip,other_pay:0
-msgid "Others"
-msgstr "Otros"
-
-#. module: hr_payroll
-#: field:hr.payslip.line,slip_id:0
-#: model:ir.model,name:hr_payroll.model_hr_payslip
-#: report:payslip.pdf:0
-msgid "Pay Slip"
-msgstr "Nómina"
-
-#. module: hr_payroll
-#: report:salary.structure:0
-msgid "Contract Detail:"
-msgstr "Detalles del contrato:"
-
-#. module: hr_payroll
-#: field:hr.payslip,igross:0
-#: field:hr.payslip,inet:0
-msgid "Calculaton Field"
-msgstr "Campo de cálculo"
-
-#. module: hr_payroll
-#: help:hr.payroll.advice,bank_id:0
-#: help:hr.payroll.register,bank_id:0
-msgid "Select the Bank Address from whcih the salary is going to be paid"
-msgstr "Seleccione la dirección del banco de donde se pagará la nómina."
-
-#. module: hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice.line,advice_id:0
-msgid "Bank Advice"
-msgstr "Aviso bancario"
-
-#. module: hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:hr.payroll.register,state:0
-#: selection:hr.payslip,state:0
-msgid "Reject"
-msgstr "Rechazado"
-
-#. module: hr_payroll
-#: selection:hr.allounce.deduction.categoty,type:0
-#: selection:hr.payslip.line,type:0
-msgid "Leaves"
-msgstr "Ausencias"
-
-#. module: hr_payroll
-#: field:hr.contibution.register.line,register_id:0
-#: view:hr.payslip:0
-#: field:hr.payslip,register_id:0
-#: report:payslip.pdf:0
-msgid "Register"
-msgstr "Registro"
-
-#. module: hr_payroll
-#: constraint:hr.employee:0
-msgid ""
-"Error ! You cannot select a department for which the employee is the manager."
msgstr ""
-"¡Error! No puede seleccionar un departamento que tenga el empleado como "
-"responsable."
#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Total Deductions"
-msgstr "Total deducciones"
+#: field:hr.payroll.structure,parent_id:0
+#: field:hr.salary.rule.category,parent_id:0
+msgid "Parent"
+msgstr ""
#. module: hr_payroll
-#: field:company.contribution.line,value:0
-#: field:hr.payslip.line.line,value:0
-msgid "Value"
-msgstr "Valor"
+#: report:paylip.details:0 report:payslip:0
+msgid "("
+msgstr ""
#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "Name of the Employee"
-msgstr "Nombre del empleado"
+#: field:hr.contribution.register,company_id:0
+#: field:hr.payroll.structure,company_id:0 field:hr.payslip,company_id:0
+#: field:hr.payslip.line,company_id:0 field:hr.salary.rule,company_id:0
+#: field:hr.salary.rule.category,company_id:0
+msgid "Company"
+msgstr ""
#. module: hr_payroll
-#: view:hr.contibution.register:0
-msgid "Register Lines"
-msgstr "Líneas de registro"
+#: view:hr.payslip:0
+msgid "Done Slip"
+msgstr ""
+
+#. module: hr_payroll
+#: report:paylip.details:0 report:payslip:0
+msgid ","
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0 view:hr.payslip.run:0
+msgid "Set to Draft"
+msgstr ""
+
+#. module: hr_payroll
+#: model:ir.model,name:hr_payroll.model_hr_salary_rule
+msgid "hr.salary.rule"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip,payslip_run_id:0
+#: model:ir.model,name:hr_payroll.model_hr_payslip_run
+msgid "Payslip Batches"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip.employees:0
+msgid ""
+"This wizard will generate payslips for all selected employee(s) based on the "
+"dates and credit note specified on Payslips Run."
+msgstr ""
+
+#. module: hr_payroll
+#: report:contribution.register.lines:0 report:paylip.details:0
+#: report:payslip:0
+msgid "Quantity/Rate"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.input,payslip_id:0 field:hr.payslip.line,slip_id:0
+#: field:hr.payslip.worked_days,payslip_id:0
+#: model:ir.model,name:hr_payroll.model_hr_payslip report:payslip:0
+msgid "Pay Slip"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip.employees:0
+msgid "Generate"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.payslip.line,amount_percentage_base:0
+#: help:hr.salary.rule,amount_percentage_base:0
+msgid "result will be affected to a variable"
+msgstr ""
+
+#. module: hr_payroll
+#: report:contribution.register.lines:0
+msgid "Total:"
+msgstr ""
+
+#. module: hr_payroll
+#: model:ir.actions.act_window,name:hr_payroll.act_children_salary_rules
+msgid "All Children Rules"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0 view:hr.salary.rule:0
+msgid "Input Data"
+msgstr ""
+
+#. module: hr_payroll
+#: constraint:hr.payslip:0
+msgid "Payslip 'Date From' must be before 'Date To'."
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0 view:hr.salary.rule.category:0
+msgid "Notes"
+msgstr ""
#. module: hr_payroll
#: view:hr.payslip:0
msgid "Salary Computation"
-msgstr "Cálculo de la nómina"
-
-#. module: hr_payroll
-#: field:hr.payroll.advice.line,amount:0
-#: report:payroll.advice:0
-#: report:salary.structure:0
-msgid "Amount"
-msgstr "Importe"
-
-#. module: hr_payroll
-#: code:addons/hr_payroll/hr_payroll.py:1225
-#, python-format
-msgid "Please check configuration of %s, payroll head is missing"
msgstr ""
-"Por favor, compruebe la configuración de %s, falta la cabecera de la nómina"
#. module: hr_payroll
-#: selection:company.contribution,amount_type:0
-msgid "Percentage"
-msgstr "Porcentaje"
+#: report:contribution.register.lines:0 field:hr.payslip.input,amount:0
+#: field:hr.payslip.line,amount:0 report:paylip.details:0 report:payslip:0
+msgid "Amount"
+msgstr ""
#. module: hr_payroll
-#: view:company.contribution:0
-#: view:hr.allounce.deduction.categoty:0
-msgid "Other Information"
-msgstr "Otra información"
-
-#. module: hr_payroll
-#: field:hr.passport,country_id:0
-msgid "Country of Issue"
-msgstr "País de emisión"
-
-#. module: hr_payroll
-#: field:hr.contibution.register.line,emp_deduction:0
-msgid "Employee Deduction"
-msgstr "Deducción del empleado"
-
-#. module: hr_payroll
-#: selection:hr.allounce.deduction.categoty,type:0
-#: selection:hr.payslip.line,type:0
-msgid "Other Deduction"
-msgstr "Otras deducciones"
-
-#. module: hr_payroll
-#: selection:hr.holidays.status,type:0
-msgid "Paid Holiday"
-msgstr "Vacaciones pagada"
-
-#. module: hr_payroll
-#: view:company.contribution:0
-#: view:hr.allounce.deduction.categoty:0
-#: view:hr.passport:0
-#: view:hr.payslip:0
-msgid "Group By..."
-msgstr "Agrupar por..."
-
-#. module: hr_payroll
-#: field:hr.passport,date_expire:0
-msgid "Passport Expire Date"
-msgstr "Fecha expiración pasaporte"
-
-#. module: hr_payroll
-#: selection:hr.holidays.status,type:0
-msgid "Un-Paid Holiday"
-msgstr "Vacaciones no pagadas"
-
-#. module: hr_payroll
-#: view:hr.passport:0
-msgid "Valid From"
-msgstr "Válido desde"
-
-#. module: hr_payroll
-#: help:hr.payslip,igross:0
-#: help:hr.payslip,inet:0
-msgid ""
-"Calculation field used for internal calculation, do not place this on form"
-msgstr "Campo usado en cálculos internos, no lo coloque en un formulario."
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Amount (in words) :"
-msgstr "Importe (en palabras):"
-
-#. module: hr_payroll
-#: field:hr.holidays.status,type:0
-msgid "Payment"
-msgstr "Pago"
-
-#. module: hr_payroll
-#: view:hr.payroll.structure:0
-#: view:hr.payslip:0
-#: field:hr.payslip,line_ids:0
-#: view:hr.payslip.line:0
+#: view:hr.payslip:0 view:hr.payslip.line:0
#: model:ir.model,name:hr_payroll.model_hr_payslip_line
msgid "Payslip Line"
-msgstr "Línea de nómina"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Identification No"
-msgstr "Nº identificación"
-
-#. module: hr_payroll
-#: view:hr.allounce.deduction.categoty:0
-#: field:hr.allounce.deduction.categoty,base:0
-msgid "Based on"
-msgstr "Basado en"
-
-#. module: hr_payroll
-#: selection:hr.payroll.register,state:0
-#: selection:hr.payslip,state:0
-msgid "Wating for Verification"
-msgstr "Esperando verificación"
-
-#. module: hr_payroll
-#: model:ir.module.module,shortdesc:hr_payroll.module_meta_information
-msgid "Human Resource Payroll"
-msgstr "Nóminas de recursos humanos"
-
-#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "Total:"
-msgstr "Total:"
-
-#. module: hr_payroll
-#: view:hr.payslip:0
-msgid "Posted"
-msgstr "Fijado"
-
-#. module: hr_payroll
-#: model:ir.module.module,description:hr_payroll.module_meta_information
-msgid ""
-"Generic Payroll system\n"
-" * Employee Details\n"
-" * Employee Contracts\n"
-" * Passport based Contract\n"
-" * Allowances / Deductions\n"
-" * Allow to configure Basic / Grows / Net Salary\n"
-" * Employee Payslip\n"
-" * Monthly Payroll Register\n"
-" * Integrated with Holiday Management\n"
-" "
msgstr ""
-"Sistema de nóminas genérico\n"
-" * Detalles de empleado\n"
-" * Contratos de empleado\n"
-" * Contratos basados en pasaportes\n"
-" * Complementos/deducciones\n"
-" * Permite configurar salario base/bruto/neto\n"
-" * Nómina de empleado\n"
-" * Registro mensual de nóminas\n"
-" * Integrado con la gestión de vacaciones\n"
-" "
#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_holidays_status
-msgid "Leave Type"
-msgstr "Tipo de ausencia"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "Date :"
-msgstr "Fecha :"
-
-#. module: hr_payroll
-#: field:hr.payslip.line,total:0
-msgid "Sub Total"
-msgstr "Subtotal"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Payments -"
-msgstr "Pagos -"
-
-#. module: hr_payroll
-#: field:hr.contract,visa_no:0
-msgid "Visa No"
-msgstr "Número de Visa"
-
-#. module: hr_payroll
-#: field:company.contribution.line,from_val:0
-#: report:employees.salary:0
-#: field:hr.payslip.line.line,from_val:0
-#: report:year.salary:0
-msgid "From"
-msgstr "Desde"
-
-#. module: hr_payroll
-#: field:hr.payroll.advice.line,bysal:0
-#: report:payroll.advice:0
-msgid "By Salary"
-msgstr "Por salario"
-
-#. module: hr_payroll
-#: field:hr.payroll.employees.detail,date_to:0
-#: field:hr.payroll.year.salary,date_to:0
-#: report:salary.structure:0
-msgid "End Date"
-msgstr "Fecha final"
-
-#. module: hr_payroll
-#: model:ir.actions.report.xml,name:hr_payroll.salary_payslip
-msgid "Employee PaySlip"
-msgstr "Nómina del empleado"
-
-#. module: hr_payroll
-#: field:hr.payslip,leaves:0
-msgid "Leave Deductions"
-msgstr "Deducciones por ausencia"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-#: report:payroll.advice:0
-msgid "Authorised Signature"
-msgstr "Firma autorizada"
-
-#. module: hr_payroll
-#: selection:hr.payslip.line,amount_type:0
-msgid "Function Value"
-msgstr "Valor de función"
-
-#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_contibution_register_line
-msgid "Contribution Register Line"
-msgstr "Línea de registro de contribución"
-
-#. module: hr_payroll
-#: report:salary.structure:0
-msgid "Notes:"
-msgstr "Notas:"
-
-#. module: hr_payroll
-#: field:hr.payroll.advice,state:0
-#: field:hr.payroll.register,state:0
-#: field:hr.payslip,state:0
-msgid "State"
-msgstr "Estado"
-
-#. module: hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Paymeny Lines"
-msgstr "Líneas de pago"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Other Lines"
-msgstr "Otras líneas"
-
-#. module: hr_payroll
-#: view:company.contribution:0
-#: view:hr.allounce.deduction.categoty:0
-#: view:hr.payroll.structure:0
#: view:hr.payslip:0
-#: view:hr.payslip.line:0
-msgid "Function Arguments"
-msgstr "Argumentos de la función"
+msgid "Other Information"
+msgstr ""
#. module: hr_payroll
-#: model:ir.actions.act_window,name:hr_payroll.action_hr_company_contribution_tree
-#: model:ir.ui.menu,name:hr_payroll.menu_hr_company_contribution_tree
-msgid "Company Contributions"
-msgstr "Contribuciones de la compañía"
+#: help:hr.payslip.line,amount_select:0 help:hr.salary.rule,amount_select:0
+msgid "The computation method for the rule amount."
+msgstr ""
#. module: hr_payroll
-#: field:hr.contibution.register.line,employee_id:0
-#: field:hr.passport,employee_id:0
-#: field:hr.payroll.advice.line,employee_id:0
-#: field:hr.payslip,employee_id:0
-#: field:hr.payslip.line,employee_id:0
+#: view:payslip.lines.contribution.register:0
+msgid "Contribution Register's Payslip Lines"
+msgstr ""
+
+#. module: hr_payroll
+#: code:addons/hr_payroll/wizard/hr_payroll_payslips_by_employees.py:52
+#, python-format
+msgid "Warning !"
+msgstr ""
+
+#. module: hr_payroll
+#: report:paylip.details:0
+msgid "Details by Salary Rule Category:"
+msgstr ""
+
+#. module: hr_payroll
+#: report:paylip.details:0 report:payslip:0
+msgid "Note"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payroll.structure,code:0 field:hr.payslip,number:0
+#: report:paylip.details:0 report:payslip:0
+msgid "Reference"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0
+msgid "Draft Slip"
+msgstr ""
+
+#. module: hr_payroll
+#: code:addons/hr_payroll/hr_payroll.py:422
+#, python-format
+msgid "Normal Working Days paid at 100%"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.line,condition_range_max:0
+#: field:hr.salary.rule,condition_range_max:0
+msgid "Maximum Range"
+msgstr ""
+
+#. module: hr_payroll
+#: report:paylip.details:0 report:payslip:0
+msgid "Identification No"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip,struct_id:0
+msgid "Structure"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.employee,total_wage:0
+msgid "Sum of all current contract's wage of employee."
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0
+msgid "Total Working Days"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.payslip.line,code:0 help:hr.salary.rule,code:0
+msgid ""
+"The code of salary rules can be used as reference in computation of other "
+"rules. In that case, it is case sensitive."
+msgstr ""
+
+#. module: hr_payroll
+#: selection:hr.contract,schedule_pay:0
+msgid "Weekly"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.line,rate:0
+msgid "Rate (%)"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0
+msgid "Confirm"
+msgstr ""
+
+#. module: hr_payroll
+#: model:ir.actions.report.xml,name:hr_payroll.payslip_report
+msgid "Employee PaySlip"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.payslip.line,condition_range_max:0
+#: help:hr.salary.rule,condition_range_max:0
+msgid "The maximum amount, applied for this rule."
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.payslip.line,condition_python:0
+#: help:hr.salary.rule,condition_python:0
+msgid ""
+"Applied this rule for calculation if condition is true. You can specify "
+"condition like basic > 1000."
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip.employees:0
+msgid "Payslips by Employees"
+msgstr ""
+
+#. module: hr_payroll
+#: selection:hr.contract,schedule_pay:0
+msgid "Quarterly"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip,state:0 field:hr.payslip.run,state:0
+msgid "State"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.salary.rule,quantity:0
+msgid ""
+"It is used in computation for percentage and fixed amount.For e.g. A rule "
+"for Meal Voucher having fixed amount of 1€ per worked day can have its "
+"quantity defined in expression like worked_days.WORK100.number_of_days."
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.salary.rule:0
+msgid "Search Salary Rule"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip,employee_id:0 field:hr.payslip.line,employee_id:0
#: model:ir.model,name:hr_payroll.model_hr_employee
msgid "Employee"
-msgstr "Empleado"
+msgstr ""
#. module: hr_payroll
-#: field:hr.payslip.line,base:0
-msgid "Formula"
-msgstr "Fórmula"
+#: selection:hr.contract,schedule_pay:0
+msgid "Semi-annually"
+msgstr ""
#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_payroll_advice_line
-msgid "Bank Advice Lines"
-msgstr "Líneas de notificación bancaria"
+#: view:hr.salary.rule:0
+msgid "Children Definition"
+msgstr ""
#. module: hr_payroll
-#: view:company.contribution:0
-#: view:hr.allounce.deduction.categoty:0
-#: field:hr.allounce.deduction.categoty,type:0
-#: field:hr.payslip.line,type:0
-#: report:salary.structure:0
-msgid "Type"
-msgstr "Tipo"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
+#: report:paylip.details:0 report:payslip:0
msgid "Email"
-msgstr "Correo electrónico"
+msgstr ""
#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "#"
-msgstr "#"
+#: view:hr.payslip.run:0
+msgid "Search Payslip Batches"
+msgstr ""
#. module: hr_payroll
-#: code:addons/hr_payroll/hr_payroll.py:469
-#: code:addons/hr_payroll/hr_payroll.py:1225
-#, python-format
-msgid "Error !"
-msgstr "¡ Error !"
+#: field:hr.payslip.line,amount_percentage_base:0
+#: field:hr.salary.rule,amount_percentage_base:0
+msgid "Percentage based on"
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.register:0
-#: view:hr.payslip:0
-msgid "Verify Sheet"
-msgstr "Comprobar hoja"
+#: help:hr.payslip.line,amount_percentage:0
+#: help:hr.salary.rule,amount_percentage:0
+msgid "For example, enter 50.0 to apply a percentage of 50%"
+msgstr ""
#. module: hr_payroll
-#: help:hr.contract,working_days_per_week:0
-msgid "No of Working days / week for an employee"
-msgstr "Número de días/semanas trabajados para un empleado."
+#: field:hr.payslip,paid:0
+msgid "Made Payment Order ? "
+msgstr ""
+
+#. module: hr_payroll
+#: report:contribution.register.lines:0
+msgid "PaySlip Lines by Contribution Register"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.payslip,state:0
+msgid ""
+"* When the payslip is created the state is 'Draft'. \n"
+"* If the payslip is under verification, the state is 'Waiting'. "
+"\n"
+"* If the payslip is confirmed then state is set to 'Done'. \n"
+"* When user cancel payslip the state is 'Rejected'."
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.worked_days,number_of_days:0
+msgid "Number of Days"
+msgstr ""
#. module: hr_payroll
-#: selection:hr.payroll.register,state:0
#: selection:hr.payslip,state:0
-msgid "New Slip"
-msgstr "Nuevo justificante"
+msgid "Rejected"
+msgstr ""
#. module: hr_payroll
-#: field:hr.payslip,basic:0
-msgid "Net Basic"
-msgstr "Base neta"
+#: view:hr.payroll.structure:0 field:hr.payroll.structure,rule_ids:0
+#: view:hr.salary.rule:0
+#: model:ir.actions.act_window,name:hr_payroll.action_salary_rule_form
+#: model:ir.ui.menu,name:hr_payroll.menu_action_hr_salary_rule_form
+msgid "Salary Rules"
+msgstr ""
#. module: hr_payroll
-#: field:hr.contract,gross:0
-#: field:hr.employee,gross:0
-#: field:hr.payroll.register,grows:0
-#: field:hr.payslip,grows:0
-#: report:salary.structure:0
-msgid "Gross Salary"
-msgstr "Salario bruto"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Total Earnings"
-msgstr "Ingresos totales"
-
-#. module: hr_payroll
-#: model:ir.actions.act_window,name:hr_payroll.action_hr_payroll_employees_detail
-#: model:ir.ui.menu,name:hr_payroll.menu_hr_payroll_employees_detail
-msgid "Employee Salary Statement"
-msgstr "Declaración salario del empleado"
-
-#. module: hr_payroll
-#: selection:hr.allounce.deduction.categoty,type:0
-#: selection:hr.payslip.line,type:0
-msgid "Other Payment"
-msgstr "Otros pagos"
-
-#. module: hr_payroll
-#: field:hr.employee,advantages_net:0
-#: report:payslip.pdf:0
-#: report:salary.structure:0
-msgid "Deductions"
-msgstr "Deducciones"
-
-#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "C/D"
-msgstr "C/D"
-
-#. module: hr_payroll
-#: field:hr.contract,permit_no:0
-msgid "Work Permit No"
-msgstr "Nº permiso trabajo"
-
-#. module: hr_payroll
-#: field:hr.payroll.advice,line_ids:0
-msgid "Employee Salary"
-msgstr "Salario empleado"
-
-#. module: hr_payroll
-#: field:hr.payroll.advice,chaque_nos:0
-msgid "Chaque Nos"
-msgstr "Cada uno de nuestros"
-
-#. module: hr_payroll
-#: field:hr.contibution.register,monthly_total_by_emp:0
-msgid "Total By Employee"
-msgstr "Total por empleado"
-
-#. module: hr_payroll
-#: view:company.contribution:0
-#: selection:company.contribution,amount_type:0
-#: selection:company.contribution.line,amount_type:0
-#: selection:hr.payslip.line,amount_type:0
-#: selection:hr.payslip.line.line,amount_type:0
-msgid "Fixed Amount"
-msgstr "Importe fijo"
-
-#. module: hr_payroll
-#: field:company.contribution.line,to_val:0
-#: report:employees.salary:0
-#: field:hr.payslip.line.line,to_val:0
-#: report:year.salary:0
-msgid "To"
-msgstr "Para"
-
-#. module: hr_payroll
-#: code:addons/hr_payroll/hr_payroll.py:180
-#: code:addons/hr_payroll/hr_payroll.py:195
-#: code:addons/hr_payroll/hr_payroll.py:285
-#: code:addons/hr_payroll/hr_payroll.py:835
-#: code:addons/hr_payroll/hr_payroll.py:1111
-#: code:addons/hr_payroll/hr_payroll.py:1126
-#: code:addons/hr_payroll/hr_payroll.py:1410
+#: code:addons/hr_payroll/hr_payroll.py:337
#, python-format
-msgid "Variable Error !"
-msgstr "¡Error de variable!"
+msgid "Refund: "
+msgstr ""
#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_payroll_employees_detail
-msgid "hr.payroll.employees.detail"
-msgstr "rrhh.nomina.empleados.detalle"
+#: model:ir.model,name:hr_payroll.model_payslip_lines_contribution_register
+msgid "PaySlip Lines by Contribution Registers"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0 selection:hr.payslip,state:0 view:hr.payslip.run:0
+msgid "Done"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.line,appears_on_payslip:0
+#: field:hr.salary.rule,appears_on_payslip:0
+msgid "Appears on Payslip"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.line,amount_fix:0
+#: selection:hr.payslip.line,amount_select:0 field:hr.salary.rule,amount_fix:0
+#: selection:hr.salary.rule,amount_select:0
+msgid "Fixed Amount"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.payslip.line,active:0 help:hr.salary.rule,active:0
+msgid ""
+"If the active field is set to false, it will allow you to hide the salary "
+"rule without removing it."
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.register:0
#: view:hr.payslip:0
-msgid "Pay Salary"
-msgstr "Pagar nómina"
+msgid "Worked Days & Inputs"
+msgstr ""
#. module: hr_payroll
-#: field:hr.payroll.advice.line,name:0
-msgid "Bank Account A/C"
-msgstr "Cuenta bancaria"
+#: field:hr.payslip,details_by_salary_rule_category:0
+msgid "Details by Salary Rule Category"
+msgstr ""
#. module: hr_payroll
-#: view:hr.contibution.register:0
-msgid "Contribution Lines"
-msgstr "Líneas de contribución"
+#: model:ir.actions.act_window,name:hr_payroll.action_payslip_lines_contribution_register
+msgid "PaySlip Lines"
+msgstr ""
#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "For the month of"
-msgstr "Para el mes de"
+#: help:hr.payslip.line,register_id:0 help:hr.salary.rule,register_id:0
+msgid "Eventual third party involved in the salary payment of the employees."
+msgstr ""
#. module: hr_payroll
-#: view:hr.allounce.deduction.categoty:0
-#: selection:hr.allounce.deduction.categoty,type:0
-#: field:hr.payroll.register,deduction:0
-#: report:hr.payroll.register.sheet:0
-#: field:hr.payslip,deduction:0
-#: selection:hr.payslip.line,type:0
-msgid "Deduction"
-msgstr "Deducción"
+#: field:hr.payslip.worked_days,number_of_hours:0
+msgid "Number of Hours"
+msgstr ""
#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_payroll_advice
-msgid "Bank Advice Note"
-msgstr "Observación aviso bancario"
+#: view:hr.payslip:0
+msgid "PaySlip Batch"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.line,condition_range_min:0
+#: field:hr.salary.rule,condition_range_min:0
+msgid "Minimum Range"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.line,child_ids:0 field:hr.salary.rule,child_ids:0
+msgid "Child Salary Rule"
+msgstr ""
+
+#. module: hr_payroll
+#: report:contribution.register.lines:0 field:hr.payslip,date_to:0
+#: field:hr.payslip.run,date_end:0 report:paylip.details:0 report:payslip:0
+#: field:payslip.lines.contribution.register,date_to:0
+msgid "Date To"
+msgstr ""
+
+#. module: hr_payroll
+#: selection:hr.payslip.line,condition_select:0
+#: selection:hr.salary.rule,condition_select:0
+msgid "Range"
+msgstr ""
+
+#. module: hr_payroll
+#: model:ir.actions.act_window,name:hr_payroll.action_view_hr_payroll_structure_tree
+#: model:ir.ui.menu,name:hr_payroll.menu_hr_payroll_structure_tree
+msgid "Salary Structures Hierarchy"
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.register:0
#: view:hr.payslip:0
msgid "Payslip"
-msgstr "Nómina"
+msgstr ""
#. module: hr_payroll
#: constraint:hr.contract:0
msgid "Error! contract start-date must be lower then contract end-date."
msgstr ""
-"¡Error! La fecha de inicio de contrato debe ser menor que la fecha de "
-"finalización."
#. module: hr_payroll
-#: selection:hr.allounce.deduction.categoty,type:0
-#: selection:hr.payslip.line,type:0
-msgid "Loan Installment"
-msgstr "Entrega anticipo"
+#: view:hr.contract:0
+msgid "Payslip Info"
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.register:0
-msgid "Complete HR Checking"
-msgstr "Comprobación RH completa"
+#: model:ir.actions.act_window,name:hr_payroll.act_payslip_lines
+msgid "Payslip Computation Details"
+msgstr ""
#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "Yours Sincerely"
-msgstr "Atentamente"
+#: code:addons/hr_payroll/hr_payroll.py:872
+#, python-format
+msgid "Wrong python code defined for salary rule %s (%s) "
+msgstr ""
#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "SI. No."
-msgstr "Nº SS"
+#: model:ir.model,name:hr_payroll.model_hr_payslip_input
+msgid "Payslip Input"
+msgstr ""
#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Net Amount"
-msgstr "Importe neto"
+#: view:hr.salary.rule.category:0
+#: model:ir.actions.act_window,name:hr_payroll.action_hr_salary_rule_category
+#: model:ir.ui.menu,name:hr_payroll.menu_hr_salary_rule_category
+msgid "Salary Rule Categories"
+msgstr ""
#. module: hr_payroll
-#: report:salary.structure:0
-msgid "Salary Structure:"
-msgstr "Estructura salarial:"
+#: help:hr.payslip.input,contract_id:0
+#: help:hr.payslip.worked_days,contract_id:0
+msgid "The contract for which applied this input"
+msgstr ""
#. module: hr_payroll
-#: model:ir.actions.report.xml,name:hr_payroll.year_employees_detail
-msgid "Employees Salary Detail"
-msgstr "Detalle salario empleado"
+#: view:hr.salary.rule:0
+msgid "Computation"
+msgstr ""
#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_payslip_line_line
-msgid "Function Line"
-msgstr "Línea de función"
+#: help:hr.payslip.input,amount:0
+msgid ""
+"It is used in computation. For e.g. A rule for sales having 1% commission of "
+"basic salary for per product can defined in expression like result = "
+"inputs.SALEURO.amount * contract.wage*0.01."
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.advice:0
-#: selection:hr.payroll.advice,state:0
-#: selection:hr.payroll.register,state:0
-#: selection:hr.payslip,state:0
-msgid "Confirm Sheet"
-msgstr "Hoja de confirmación"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-msgid "Others:"
-msgstr "Otros:"
-
-#. module: hr_payroll
-#: view:company.contribution:0
-#: selection:company.contribution,amount_type:0
-msgid "Function Calculation"
-msgstr "Función de cálculo"
-
-#. module: hr_payroll
-#: field:hr.payslip,worked_days:0
-#: report:payslip.pdf:0
-msgid "Worked Day"
-msgstr "Días trabajados"
-
-#. module: hr_payroll
-#: field:hr.contibution.register,monthly_total_by_comp:0
-msgid "Total By Company"
-msgstr "Total por compañía"
-
-#. module: hr_payroll
-#: field:hr.payroll.advice.line,flag:0
-msgid "D/C"
-msgstr "D/C"
-
-#. module: hr_payroll
-#: view:hr.passport:0
-msgid "Country & Address"
-msgstr "País y Dirección"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-msgid "Employee Code"
-msgstr "Código de empleado"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Basic Salary – Leaves"
-msgstr "Salario base - Ausencias"
-
-#. module: hr_payroll
-#: field:company.contribution,amount_type:0
-#: field:company.contribution.line,amount_type:0
-#: field:hr.payslip.line,amount_type:0
-#: field:hr.payslip.line.line,amount_type:0
-#: report:salary.structure:0
+#: view:hr.payslip.line:0 field:hr.payslip.line,amount_select:0
+#: field:hr.salary.rule,amount_select:0
msgid "Amount Type"
-msgstr "Tipo de importe"
+msgstr ""
#. module: hr_payroll
-#: view:company.contribution:0
-#: field:hr.payslip.line,category_id:0
+#: field:hr.payslip.line,category_id:0 view:hr.salary.rule:0
+#: field:hr.salary.rule,category_id:0
msgid "Category"
-msgstr "Categoría"
+msgstr ""
#. module: hr_payroll
-#: view:company.contribution:0
-#: view:hr.allounce.deduction.categoty:0
-#: field:hr.payslip.line,company_contrib:0
-#: model:ir.model,name:hr_payroll.model_company_contribution
-msgid "Company Contribution"
-msgstr "Contribución compañía"
+#: help:hr.payslip.run,credit_note:0
+msgid ""
+"If its checked, indicates that all payslips generated from here are refund "
+"payslips."
+msgstr ""
#. module: hr_payroll
-#: field:company.contribution,category_id:0
-msgid "Heads"
-msgstr "Cabeceras"
+#: model:ir.actions.act_window,name:hr_payroll.action_view_hr_payroll_structure_list_form
+#: model:ir.ui.menu,name:hr_payroll.menu_hr_payroll_structure_view
+msgid "Salary Structures"
+msgstr ""
#. module: hr_payroll
-#: model:ir.actions.report.xml,name:hr_payroll.year_payroll_register
-msgid "Print Statement"
-msgstr "Imprimir declaración"
+#: view:hr.payslip.run:0
+msgid "Draft Payslip Batches"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip:0 selection:hr.payslip,state:0 view:hr.payslip.run:0
+#: selection:hr.payslip.run,state:0
+msgid "Draft"
+msgstr ""
+
+#. module: hr_payroll
+#: report:contribution.register.lines:0 field:hr.payslip,date_from:0
+#: field:hr.payslip.run,date_start:0 report:paylip.details:0 report:payslip:0
+#: field:payslip.lines.contribution.register,date_from:0
+msgid "Date From"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip.run:0
+msgid "Done Payslip Batches"
+msgstr ""
+
+#. module: hr_payroll
+#: report:paylip.details:0
+msgid "Payslip Lines by Contribution Register:"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.salary.rule:0
+msgid "Conditions"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.line,amount_percentage:0
+#: selection:hr.payslip.line,amount_select:0
+#: field:hr.salary.rule,amount_percentage:0
+#: selection:hr.salary.rule,amount_select:0
+msgid "Percentage (%)"
+msgstr ""
#. module: hr_payroll
#: view:hr.payslip:0
-msgid "Draft"
-msgstr "Borrador"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Earnings"
-msgstr "Ingresos"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-#: report:salary.structure:0
-msgid "Basic"
-msgstr "Básico"
-
-#. module: hr_payroll
-#: model:ir.actions.act_window,name:hr_payroll.action_hr_passport_tree
-msgid "All Passports"
-msgstr "Todos los pasaportes"
-
-#. module: hr_payroll
-#: model:ir.actions.act_window,name:hr_payroll.action_hr_payroll_year_salary
-#: model:ir.ui.menu,name:hr_payroll.menu_wizard_print_year_salary
-msgid "Salary Register"
-msgstr "Registro salarial"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-#: report:hr.payroll.register.sheet:0
-msgid "Employee Name"
-msgstr "Nombre del empleado"
-
-#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_passport
-msgid "Passport Detail"
-msgstr "Detalle pasaporte"
-
-#. module: hr_payroll
-#: selection:hr.payslip.line,amount_type:0
-msgid "Percentage (%)"
-msgstr "Porcentaje (%)"
-
-#. module: hr_payroll
-#: field:hr.payroll.advice,register_id:0
-#: view:hr.payroll.register:0
-#: model:ir.actions.act_window,name:hr_payroll.action_view_hr_payroll_register_form
-#: model:ir.model,name:hr_payroll.model_hr_payroll_register
-#: model:ir.ui.menu,name:hr_payroll.hr_menu_payroll_register
-msgid "Payroll Register"
-msgstr "Registro de nóminas"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-#: report:payroll.advice:0
-msgid "For"
-msgstr "Para"
-
-#. module: hr_payroll
-#: field:hr.passport,contracts_ids:0
-msgid "Contracts"
-msgstr "Contratos"
+msgid "Worked Day"
+msgstr ""
#. module: hr_payroll
#: view:hr.payroll.structure:0
msgid "Employee Function"
-msgstr "Función del empleado"
+msgstr ""
#. module: hr_payroll
-#: view:hr.payslip:0
-msgid "Paid"
-msgstr "Pagado"
-
-#. module: hr_payroll
-#: view:hr.payslip:0
-msgid "Approve Sheet"
-msgstr "Aprobar hoja"
-
-#. module: hr_payroll
-#: field:hr.payslip,paid:0
-msgid "Paid ? "
-msgstr "¿Pagado? "
-
-#. module: hr_payroll
-#: view:hr.holidays.status:0
-msgid "Validation"
-msgstr "Validación"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-msgid "Title"
-msgstr "Título"
-
-#. module: hr_payroll
-#: view:company.contribution:0
-msgid "Search Company Contribution"
-msgstr "Buscar contribución de la compañía"
-
-#. module: hr_payroll
-#: field:hr.allounce.deduction.categoty,user_id:0
-msgid "User"
-msgstr "Usuario"
-
-#. module: hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Payment Lines"
-msgstr "Líneas de pago"
+#: field:hr.payslip,credit_note:0 field:hr.payslip.run,credit_note:0
+msgid "Credit Note"
+msgstr ""
#. module: hr_payroll
#: view:hr.payslip:0
msgid "Compute Sheet"
-msgstr "Calcular hoja"
+msgstr ""
#. module: hr_payroll
-#: field:company.contribution,active:0
-#: field:hr.payroll.register,active:0
+#: field:hr.payslip.line,active:0 field:hr.salary.rule,active:0
msgid "Active"
-msgstr "Activo"
+msgstr ""
#. module: hr_payroll
-#: help:hr.allounce.deduction.categoty,condition:0
-msgid "Applied this head for calculation if condition is true"
-msgstr "Aplicar este encabezado en el cálculo si la condición es verdadera"
-
-#. module: hr_payroll
-#: report:year.salary:0
-msgid "Yearly Salary Details"
-msgstr "Detalles del salario anual"
+#: view:hr.salary.rule:0
+msgid "Child Rules"
+msgstr ""
#. module: hr_payroll
#: constraint:hr.employee:0
msgid "Error ! You cannot create recursive Hierarchy of Employees."
-msgstr "¡Error! No se puede crear una jerarquía recursiva de empleados."
+msgstr ""
#. module: hr_payroll
-#: field:hr.allounce.deduction.categoty,condition:0
-msgid "Condition"
-msgstr "Condición"
+#: model:ir.actions.report.xml,name:hr_payroll.payslip_details_report
+msgid "PaySlip Details"
+msgstr ""
#. module: hr_payroll
-#: selection:hr.payroll.register,state:0
-#: selection:hr.payslip,state:0
-msgid "Wating for HR Verification"
-msgstr "Esperando verificación de RRHH"
+#: help:hr.payslip.line,condition_range_min:0
+#: help:hr.salary.rule,condition_range_min:0
+msgid "The minimum amount, applied for this rule."
+msgstr ""
#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "Payment Advice:"
-msgstr "Aviso de pago:"
+#: selection:hr.payslip.line,condition_select:0
+#: selection:hr.salary.rule,condition_select:0
+msgid "Python Expression"
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.register:0
-msgid "Compute"
-msgstr "Calcular"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-#: field:hr.payslip,deg_id:0
-#: report:payslip.pdf:0
-#: report:salary.structure:0
+#: report:paylip.details:0 report:payslip:0
msgid "Designation"
-msgstr "Designación"
+msgstr ""
#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "HR Manager"
-msgstr "Responsable de RRHH"
+#: code:addons/hr_payroll/wizard/hr_payroll_payslips_by_employees.py:52
+#, python-format
+msgid "You must select employee(s) to generate payslip(s)"
+msgstr ""
#. module: hr_payroll
-#: field:hr.contract,basic:0
-#: field:hr.employee,basic:0
-#: field:hr.payslip,basic_before_leaves:0
-#: report:payslip.pdf:0
-msgid "Basic Salary"
-msgstr "Salario base"
-
-#. module: hr_payroll
-#: field:hr.allounce.deduction.categoty,code:0
-msgid "Category Code"
-msgstr "Código categoría"
-
-#. module: hr_payroll
-#: view:hr.payroll.register:0
-msgid "Salary Information"
-msgstr "Información del salario"
-
-#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_allounce_deduction_categoty
-#: model:ir.model,name:hr_payroll.model_hr_allounce_deduction_categoty_line
-msgid "Allowance Deduction Categoty"
-msgstr "Categoría prima/deducción"
+#: code:addons/hr_payroll/hr_payroll.py:861
+#, python-format
+msgid "Wrong quantity defined for salary rule %s (%s)"
+msgstr ""
#. module: hr_payroll
#: view:hr.payslip:0
msgid "Companies"
-msgstr "Compañías"
+msgstr ""
#. module: hr_payroll
-#: report:payslip.pdf:0
+#: report:paylip.details:0 report:payslip:0
msgid "Authorized Signature"
-msgstr "Firma autorizada"
+msgstr ""
#. module: hr_payroll
-#: field:hr.payslip,contract_id:0
+#: field:hr.payslip,contract_id:0 field:hr.payslip.input,contract_id:0
+#: field:hr.payslip.line,contract_id:0
+#: field:hr.payslip.worked_days,contract_id:0
#: model:ir.model,name:hr_payroll.model_hr_contract
msgid "Contract"
-msgstr "Contrato"
+msgstr ""
#. module: hr_payroll
-#: selection:hr.payroll.advice,state:0
-msgid "Draft Sheet"
-msgstr "Hoja borrador"
+#: report:paylip.details:0 report:payslip:0
+msgid "Credit"
+msgstr ""
#. module: hr_payroll
-#: selection:hr.payroll.year.salary,salary_on:0
-msgid "Next Month Date"
-msgstr "Fecha próximo mes"
+#: field:hr.contract,schedule_pay:0
+msgid "Scheduled Pay"
+msgstr ""
#. module: hr_payroll
-#: field:hr.contibution.register.line,date:0
-#: field:hr.payroll.advice,date:0
-#: field:hr.payroll.register,date:0
-#: field:hr.payslip,date:0
-msgid "Date"
-msgstr "Fecha"
+#: code:addons/hr_payroll/hr_payroll.py:861
+#: code:addons/hr_payroll/hr_payroll.py:866
+#: code:addons/hr_payroll/hr_payroll.py:872
+#: code:addons/hr_payroll/hr_payroll.py:889
+#: code:addons/hr_payroll/hr_payroll.py:895
+#, python-format
+msgid "Error"
+msgstr ""
#. module: hr_payroll
-#: field:hr.contract,visa_expire:0
-msgid "Visa Expire Date"
-msgstr "Fecha expiración visado"
+#: field:hr.payslip.line,condition_python:0
+#: field:hr.salary.rule,condition_python:0
+msgid "Python Condition"
+msgstr ""
#. module: hr_payroll
-#: view:hr.passport:0
-msgid "Search Passport"
-msgstr "Buscar pasaporte"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-#: report:salary.structure:0
-msgid "Phone No."
-msgstr "Nº Teléfono"
-
-#. module: hr_payroll
-#: field:company.contribution,contribute_per:0
-#: field:company.contribution.line,contribution_id:0
-#: view:hr.allounce.deduction.categoty:0
-#: view:hr.contibution.register:0
-#: view:hr.contibution.register.line:0
+#: view:hr.contribution.register:0
msgid "Contribution"
-msgstr "Contribución"
+msgstr ""
#. module: hr_payroll
-#: field:hr.allounce.deduction.categoty,state:0
-msgid "Label"
-msgstr "Etiqueta"
+#: code:addons/hr_payroll/hr_payroll.py:347
+#, python-format
+msgid "Refund Payslip"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.rule.input,input_id:0
+#: model:ir.model,name:hr_payroll.model_hr_rule_input
+msgid "Salary Rule Input"
+msgstr ""
+
+#. module: hr_payroll
+#: code:addons/hr_payroll/hr_payroll.py:895
+#, python-format
+msgid "Wrong python condition defined for salary rule %s (%s)"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.payslip.line,quantity:0 field:hr.salary.rule,quantity:0
+msgid "Quantity"
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.structure:0
#: view:hr.payslip:0
-#: view:hr.payslip.line:0
+msgid "Refund"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.salary.rule:0
msgid "Company Contribution"
-msgstr "Contribución compañía"
+msgstr ""
#. module: hr_payroll
-#: report:employees.salary:0
-#: report:salary.structure:0
-msgid "Other No."
-msgstr "Otro Nº"
-
-#. module: hr_payroll
-#: field:company.contribution,code:0
-#: field:hr.contibution.register.line,code:0
-#: field:hr.holidays.status,code:0
-#: field:hr.payroll.structure,code:0
-#: field:hr.payslip.line,code:0
-#: report:payslip.pdf:0
-#: report:salary.structure:0
+#: report:contribution.register.lines:0 field:hr.payslip.input,code:0
+#: field:hr.payslip.line,code:0 field:hr.payslip.worked_days,code:0
+#: field:hr.rule.input,code:0 field:hr.salary.rule,code:0
+#: field:hr.salary.rule.category,code:0 report:paylip.details:0
+#: report:payslip:0
msgid "Code"
-msgstr "Código"
-
-#. module: hr_payroll
-#: model:ir.actions.act_window,name:hr_payroll.action_view_hr_bank_advice_tree
-#: model:ir.ui.menu,name:hr_payroll.hr_menu_payment_advice
-msgid "Payment Advice"
-msgstr "Aviso de pago"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "Number :"
-msgstr "Número :"
-
-#. module: hr_payroll
-#: help:hr.allounce.deduction.categoty,base:0
-msgid ""
-"This will use to computer the % fields values, in general its on basic, but "
-"You can use all heads code field in small letter as a variable name i.e. "
-"hra, ma, lta, etc...., also you can use, static varible basic"
msgstr ""
-"Esto se utiliza para calcular los valores de los campos %, en general en su "
-"base, pero puede utilizar todas las cabeceras de los campos de código en "
-"letra pequeña como un nombre de variable, por ejemplo hra, ma, lta, etc., "
-"también puede utilizar variable estática básica."
#. module: hr_payroll
-#: view:hr.payslip:0
-msgid "Computation Overview"
-msgstr "Resumen del cálculo"
+#: field:hr.payslip.line,amount_python_compute:0
+#: selection:hr.payslip.line,amount_select:0
+#: field:hr.salary.rule,amount_python_compute:0
+#: selection:hr.salary.rule,amount_select:0
+msgid "Python Code"
+msgstr ""
#. module: hr_payroll
-#: field:hr.payroll.year.salary,salary_on:0
-msgid "Salary On"
-msgstr "Salario sobre"
+#: field:hr.payslip.input,sequence:0 field:hr.payslip.line,sequence:0
+#: field:hr.payslip.worked_days,sequence:0 field:hr.salary.rule,sequence:0
+msgid "Sequence"
+msgstr ""
#. module: hr_payroll
-#: field:hr.payroll.advice,number:0
-#: field:hr.payroll.register,number:0
-#: field:hr.payslip,number:0
-msgid "Number"
-msgstr "Número"
+#: report:contribution.register.lines:0 report:paylip.details:0
+msgid "Register Name"
+msgstr ""
#. module: hr_payroll
-#: field:hr.contract,struct_id:0
-#: field:hr.employee,line_ids:0
-#: view:hr.payroll.structure:0
-#: field:hr.payroll.structure,line_ids:0
-#: view:hr.payslip:0
+#: view:hr.salary.rule:0
+msgid "General"
+msgstr ""
+
+#. module: hr_payroll
+#: code:addons/hr_payroll/hr_payroll.py:664
+#, python-format
+msgid "Salary Slip of %s for %s"
+msgstr ""
+
+#. module: hr_payroll
+#: model:ir.model,name:hr_payroll.model_hr_payslip_employees
+msgid "Generate payslips for all selected employees"
+msgstr ""
+
+#. module: hr_payroll
+#: field:hr.contract,struct_id:0 view:hr.payroll.structure:0 view:hr.payslip:0
#: view:hr.payslip.line:0
-#: model:ir.actions.act_window,name:hr_payroll.action_view_hr_employee_grade_form
-#: model:ir.actions.report.xml,name:hr_payroll.salary_structure_register
#: model:ir.model,name:hr_payroll.model_hr_payroll_structure
-#: model:ir.ui.menu,name:hr_payroll.menu_hr_employee_function
msgid "Salary Structure"
-msgstr "Estructura salarial"
-
-#. module: hr_payroll
-#: field:hr.contibution.register,register_line_ids:0
-msgid "Register Line"
-msgstr "Línea registro"
-
-#. module: hr_payroll
-#: view:hr.payroll.register:0
-#: view:hr.payslip:0
-msgid "Cancel"
-msgstr "Cancelar"
-
-#. module: hr_payroll
-#: view:hr.payroll.employees.detail:0
-#: view:hr.payroll.year.salary:0
-msgid "Close"
-msgstr "Cerrar"
-
-#. module: hr_payroll
-#: field:hr.payslip.line,amount:0
-msgid "Amount / Percentage"
-msgstr "Importe / Porcentaje"
-
-#. module: hr_payroll
-#: field:hr.employee,advantages_gross:0
-#: report:hr.payroll.register.sheet:0
-#: report:salary.structure:0
-msgid "Allowances"
-msgstr "Primas"
-
-#. module: hr_payroll
-#: selection:hr.payroll.year.salary,salary_on:0
-msgid "Current Month Date"
-msgstr "Fecha mes actual"
-
-#. module: hr_payroll
-#: report:salary.structure:0
-msgid "Salary"
-msgstr "Salario"
-
-#. module: hr_payroll
-#: field:hr.contract,passport_id:0
-#: field:hr.passport,name:0
-msgid "Passport No"
-msgstr "Número de pasaporte"
-
-#. module: hr_payroll
-#: view:hr.passport:0
-msgid "Passport"
-msgstr "Pasaporte"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "Total Salary"
-msgstr "Salario total"
-
-#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "for period"
-msgstr "por periodo"
-
-#. module: hr_payroll
-#: field:hr.holidays.status,head_id:0
-msgid "Payroll Head"
-msgstr "Cabecera nómina"
-
-#. module: hr_payroll
-#: field:company.contribution,register_id:0
-#: model:ir.actions.act_window,name:hr_payroll.action_contibution_register_form
-#: model:ir.model,name:hr_payroll.model_hr_contibution_register
-#: model:ir.ui.menu,name:hr_payroll.menu_action_hr_contibution_register_form
-msgid "Contribution Register"
-msgstr "Registro de contribución"
-
-#. module: hr_payroll
-#: report:salary.structure:0
-msgid "E-mail"
-msgstr "Correo electrónico"
-
-#. module: hr_payroll
-#: view:hr.allounce.deduction.categoty:0
-#: model:ir.actions.act_window,name:hr_payroll.hr_allounce_deduction_tree
-#: model:ir.ui.menu,name:hr_payroll.menu_hr_allounce_deduction_tree
-msgid "Salary Heads"
-msgstr "Cabeceras salario"
-
-#. module: hr_payroll
-#: view:hr.payroll.employees.detail:0
-#: view:hr.payroll.year.salary:0
-msgid "Print Report"
-msgstr "Imprimir informe"
-
-#. module: hr_payroll
-#: field:company.contribution,line_ids:0
-#: view:hr.payroll.structure:0
-#: view:hr.payslip:0
-#: view:hr.payslip.line:0
-#: field:hr.payslip.line,line_ids:0
-msgid "Calculations"
-msgstr "Cálculos"
-
-#. module: hr_payroll
-#: help:company.contribution,contribute_per:0
-msgid ""
-"Define Company contribution ratio 1.00=100% contribution, If Employee "
-"Contribute 5% then company will and here 0.50 defined then company will "
-"contribute 50% on employee 5% contribution"
msgstr ""
-"Define el ratio de contribución de la compañía 1,00=100% de la contribución. "
-"Si el empleado contribuye con el 5%, entonces si aquí la compañía tiene un "
-"ratio de 0.50, la compañía contribuirá con el 50% del 5% de la contribución "
-"del empleado."
#. module: hr_payroll
-#: view:hr.payslip:0
-msgid "Other Informations"
-msgstr "Otra información"
+#: field:hr.contribution.register,register_line_ids:0
+msgid "Register Line"
+msgstr ""
#. module: hr_payroll
-#: view:hr.contibution.register:0
-msgid "Month"
-msgstr "Mes"
+#: view:hr.payslip:0 view:hr.payslip.employees:0
+#: view:payslip.lines.contribution.register:0
+msgid "Cancel"
+msgstr ""
#. module: hr_payroll
-#: view:hr.passport:0
-msgid "Issue"
-msgstr "Incidencia"
+#: view:hr.payslip.run:0 selection:hr.payslip.run,state:0
+msgid "Close"
+msgstr ""
#. module: hr_payroll
-#: view:hr.allounce.deduction.categoty:0
-msgid "Dynamic Computation"
-msgstr "Cálculo Dinámico"
+#: help:hr.payslip,struct_id:0
+msgid ""
+"Defines the rules that have to be applied to this payslip, accordingly to "
+"the contract chosen. If you let empty the field contract, this field isn't "
+"mandatory anymore and thus the rules applied will be all the rules set on "
+"the structure of all contracts of the employee valid for the chosen period"
+msgstr ""
#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Basic Salary without Leave:"
-msgstr "Salario base sin ausencias:"
+#: field:hr.payroll.structure,children_ids:0
+#: field:hr.salary.rule.category,children_ids:0
+msgid "Children"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.payslip,credit_note:0
+msgid "Indicates this payslip has a refund of another"
+msgstr ""
+
+#. module: hr_payroll
+#: selection:hr.contract,schedule_pay:0
+msgid "Bi-monthly"
+msgstr ""
+
+#. module: hr_payroll
+#: report:paylip.details:0
+msgid "Pay Slip Details"
+msgstr ""
+
+#. module: hr_payroll
+#: model:ir.actions.act_window,name:hr_payroll.action_view_hr_payslip_form
+#: model:ir.ui.menu,name:hr_payroll.menu_department_tree
+msgid "Employee Payslips"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip.line:0 field:hr.payslip.line,register_id:0
+#: field:hr.salary.rule,register_id:0
+#: model:ir.model,name:hr_payroll.model_hr_contribution_register
+msgid "Contribution Register"
+msgstr ""
+
+#. module: hr_payroll
+#: view:payslip.lines.contribution.register:0
+msgid "Print"
+msgstr ""
+
+#. module: hr_payroll
+#: model:ir.actions.act_window,help:hr_payroll.action_contribution_register_form
+msgid ""
+"A contribution register is a third party involved in the salary payment of "
+"the employees. It can be the social security, the estate or anyone that "
+"collect or inject money on payslips."
+msgstr ""
+
+#. module: hr_payroll
+#: code:addons/hr_payroll/hr_payroll.py:889
+#, python-format
+msgid "Wrong range condition defined for salary rule %s (%s)"
+msgstr ""
#. module: hr_payroll
-#: view:company.contribution:0
-#: view:hr.allounce.deduction.categoty:0
-#: view:hr.payroll.structure:0
-#: view:hr.payslip:0
#: view:hr.payslip.line:0
-#: field:hr.payslip.line,function_id:0
-msgid "Function"
-msgstr "Función"
+msgid "Calculations"
+msgstr ""
#. module: hr_payroll
#: view:hr.payslip:0
-msgid "States"
-msgstr "Estados"
+msgid "Worked Days"
+msgstr ""
#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "Dear Sir/Madam,"
-msgstr "Apreciado Sr./Sra.,"
-
-#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_allounce_deduction_categoty
-msgid "Allowance Deduction Heads"
-msgstr "Cabeceras prima/deducción"
-
-#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "Gross Sal."
-msgstr "Sal. bruto"
-
-#. module: hr_payroll
-#: view:company.contribution:0
-#: field:company.contribution,note:0
-#: view:hr.allounce.deduction.categoty:0
-#: field:hr.allounce.deduction.categoty,note:0
-#: view:hr.contibution.register:0
-#: field:hr.contibution.register,note:0
-#: view:hr.passport:0
-#: field:hr.passport,note:0
-#: field:hr.payroll.advice,note:0
-#: field:hr.payroll.register,note:0
-#: view:hr.payroll.structure:0
-#: field:hr.payroll.structure,note:0
#: view:hr.payslip:0
-#: field:hr.payslip,note:0
-#: view:hr.payslip.line:0
-#: field:hr.payslip.line,note:0
+msgid "Search Payslips"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip.run:0
+#: model:ir.actions.act_window,name:hr_payroll.action_hr_payslip_run_tree
+#: model:ir.ui.menu,name:hr_payroll.menu_hr_payslip_run
+msgid "Payslips Batches"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.contribution.register:0 field:hr.contribution.register,note:0
+#: field:hr.payroll.structure,note:0 field:hr.payslip,name:0
+#: field:hr.payslip,note:0 field:hr.payslip.input,name:0
+#: view:hr.payslip.line:0 field:hr.payslip.line,note:0
+#: field:hr.payslip.worked_days,name:0 field:hr.rule.input,name:0
+#: view:hr.salary.rule:0 field:hr.salary.rule,note:0
+#: field:hr.salary.rule.category,note:0
msgid "Description"
-msgstr "Descripción"
+msgstr ""
#. module: hr_payroll
-#: field:hr.payroll.employees.detail,date_from:0
-#: field:hr.payroll.year.salary,date_from:0
-#: report:salary.structure:0
-msgid "Start Date"
-msgstr "Fecha inicio"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Deduction -"
-msgstr "Deducción -"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
+#: report:paylip.details:0 report:payslip:0
msgid ")"
-msgstr ")"
+msgstr ""
#. module: hr_payroll
-#: view:hr.contibution.register:0
+#: view:hr.contribution.register:0
+#: model:ir.actions.act_window,name:hr_payroll.action_contribution_register_form
+#: model:ir.ui.menu,name:hr_payroll.menu_action_hr_contribution_register_form
msgid "Contribution Registers"
-msgstr "Registros de contribución"
+msgstr ""
#. module: hr_payroll
#: model:ir.ui.menu,name:hr_payroll.menu_hr_payroll_reporting
#: model:ir.ui.menu,name:hr_payroll.menu_hr_root_payroll
#: model:ir.ui.menu,name:hr_payroll.payroll_configure
msgid "Payroll"
-msgstr "Nómina"
+msgstr ""
#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_contract_wage_type
-msgid "Wage Type"
-msgstr "Tipo de salario"
+#: model:ir.actions.report.xml,name:hr_payroll.contribution_register
+msgid "PaySlip Lines By Conribution Register"
+msgstr ""
#. module: hr_payroll
-#: report:hr.payroll.register.sheet:0
-msgid "Net Sal."
-msgstr "Sal. neto"
-
-#. module: hr_payroll
-#: sql_constraint:hr.passport:0
-msgid "The Passport No must be unique !"
-msgstr "¡El número de pasaporte debe ser único!"
-
-#. module: hr_payroll
-#: field:hr.allounce.deduction.categoty,name:0
-msgid "Category Name"
-msgstr "Nombre categoría"
-
-#. module: hr_payroll
-#: model:ir.model,name:hr_payroll.model_hr_payroll_year_salary
-msgid "hr.payroll.year.salary"
-msgstr "hr.nómina.año.salario"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-#: field:hr.passport,address_id:0
-#: report:payslip.pdf:0
-#: report:salary.structure:0
-msgid "Address"
-msgstr "Dirección"
-
-#. module: hr_payroll
-#: field:hr.payslip.line.line,slipline_id:0
-msgid "Slip Line"
-msgstr "Línea justificante"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Number of Leaves"
-msgstr "Número de hojas"
-
-#. module: hr_payroll
-#: report:employees.salary:0
-#: field:hr.payroll.advice,bank_id:0
-#: field:hr.payroll.register,bank_id:0
-#: report:salary.structure:0
-msgid "Bank"
-msgstr "Banco"
-
-#. module: hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Cancel Sheet"
-msgstr "Cancelar hoja"
-
-#. module: hr_payroll
-#: selection:hr.allounce.deduction.categoty,type:0
-#: selection:hr.payslip.line,type:0
-msgid "Advance"
-msgstr "Adelanto"
-
-#. module: hr_payroll
-#: report:salary.structure:0
-msgid "Special Allowances and Deductions For Employee:"
-msgstr "Primas y deducciones especiales por empleado:"
-
-#. module: hr_payroll
-#: field:company.contribution,name:0
-#: field:company.contribution.line,name:0
-#: field:hr.contibution.register,name:0
-#: field:hr.contibution.register.line,name:0
-#: field:hr.payroll.advice,name:0
-#: field:hr.payroll.register,name:0
-#: field:hr.payroll.structure,name:0
-#: field:hr.payslip,name:0
-#: field:hr.payslip.line,name:0
-#: field:hr.payslip.line.line,name:0
-#: report:payslip.pdf:0
-#: report:salary.structure:0
-#: report:year.salary:0
-msgid "Name"
-msgstr "Nombre"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Leaved Deduction"
-msgstr "Hojas de deducción"
-
-#. module: hr_payroll
-#: view:hr.passport:0
-msgid "Country"
-msgstr "País"
-
-#. module: hr_payroll
-#: view:hr.passport:0
-#: view:hr.payroll.employees.detail:0
-#: field:hr.payroll.employees.detail,employee_ids:0
-#: view:hr.payroll.year.salary:0
-#: field:hr.payroll.year.salary,employee_ids:0
-#: view:hr.payslip:0
-msgid "Employees"
-msgstr "Empleados"
-
-#. module: hr_payroll
-#: report:payroll.advice:0
-msgid "Bank Account"
-msgstr "Cuenta bancaria"
-
-#. module: hr_payroll
-#: help:company.contribution,register_id:0
-msgid "Contribution register based on company"
-msgstr "Registro de contribución basado en la empresa"
-
-#. module: hr_payroll
-#: help:hr.allounce.deduction.categoty,sequence:0
-msgid "Use to arrange calculation sequence"
-msgstr "Se utiliza para organizar la secuencia de cálculo"
-
-#. module: hr_payroll
-#: field:hr.payslip,total_pay:0
-msgid "Total Payment"
-msgstr "Pago total"
-
-#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Leave Deductions Line:"
-msgstr "Línea de deducciones por ausencias:"
-
-#. module: hr_payroll
-#: selection:hr.payroll.register,state:0
#: selection:hr.payslip,state:0
-msgid "Wating for Account Verification"
-msgstr "Esperando por verificación de la cuenta"
+msgid "Waiting"
+msgstr ""
#. module: hr_payroll
-#: field:hr.contibution.register.line,comp_deduction:0
-msgid "Company Deduction"
-msgstr "Deducción de la Compañía"
+#: report:paylip.details:0 report:payslip:0
+msgid "Address"
+msgstr ""
#. module: hr_payroll
-#: view:hr.holidays.status:0
-msgid "Payroll Configurtion"
-msgstr "Configuración nómina"
-
-#. module: hr_payroll
-#: code:addons/hr_payroll/hr_payroll.py:469
+#: code:addons/hr_payroll/hr_payroll.py:866
#, python-format
-msgid "Please define bank account for the %s employee"
-msgstr "Por favor, defina la cuenta bancaria para el empleado %s"
+msgid "Wrong percentage base or quantity defined for salary rule %s (%s)"
+msgstr ""
#. module: hr_payroll
-#: field:hr.passport,date_issue:0
-msgid "Passport Issue Date"
-msgstr "Fecha de emisión del pasaporte"
+#: field:hr.payslip,worked_days_line_ids:0
+#: model:ir.model,name:hr_payroll.model_hr_payslip_worked_days
+msgid "Payslip Worked Days"
+msgstr ""
#. module: hr_payroll
-#: view:hr.allounce.deduction.categoty:0
-#: selection:hr.allounce.deduction.categoty,type:0
-#: field:hr.payroll.register,allounce:0
-#: field:hr.payslip,allounce:0
-#: selection:hr.payslip.line,type:0
-msgid "Allowance"
-msgstr "Prima"
+#: view:hr.salary.rule.category:0
+msgid "Salary Categories"
+msgstr ""
#. module: hr_payroll
-#: field:hr.payslip,holiday_days:0
-msgid "No of Leaves"
-msgstr "N º de hojas"
+#: report:contribution.register.lines:0 field:hr.contribution.register,name:0
+#: field:hr.payroll.structure,name:0 field:hr.payslip.line,name:0
+#: field:hr.payslip.run,name:0 field:hr.salary.rule,name:0
+#: field:hr.salary.rule.category,name:0 report:paylip.details:0
+#: report:payslip:0
+msgid "Name"
+msgstr ""
#. module: hr_payroll
-#: field:hr.employee,otherid:0
-msgid "Other Id"
-msgstr "Otro id"
+#: view:hr.payroll.structure:0
+msgid "Payroll Structures"
+msgstr ""
#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Bank Details"
-msgstr "Detalles bancarios"
+#: view:hr.payslip:0 view:hr.payslip.employees:0
+#: field:hr.payslip.employees,employee_ids:0 view:hr.payslip.line:0
+msgid "Employees"
+msgstr ""
#. module: hr_payroll
-#: report:payslip.pdf:0
-msgid "Slip ID"
-msgstr "ID justificante"
+#: report:paylip.details:0 report:payslip:0
+msgid "Bank Account"
+msgstr ""
#. module: hr_payroll
-#: field:company.contribution.line,sequence:0
-#: field:hr.allounce.deduction.categoty,sequence:0
-#: field:hr.payslip.line,sequence:0
-#: field:hr.payslip.line.line,sequence:0
-msgid "Sequence"
-msgstr "Secuencia"
+#: help:hr.payslip.line,sequence:0 help:hr.salary.rule,sequence:0
+msgid "Use to arrange calculation sequence"
+msgstr ""
#. module: hr_payroll
-#: model:ir.actions.act_window,name:hr_payroll.action_view_hr_payslip_form
-#: model:ir.ui.menu,name:hr_payroll.menu_department_tree
-msgid "Employee Payslip"
-msgstr "Nómina de los empleados"
+#: help:hr.payslip.line,condition_range:0
+#: help:hr.salary.rule,condition_range:0
+msgid ""
+"This will be used to compute the % fields values; in general it is on basic, "
+"but you can also use categories code fields in lowercase as a variable names "
+"(hra, ma, lta, etc.) and the variable basic."
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Letter Content"
-msgstr "Contenido carta"
+#: selection:hr.contract,schedule_pay:0
+msgid "Annually"
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.employees.detail:0
-#: view:hr.payroll.year.salary:0
-msgid "Year Salary"
-msgstr "Salario anual"
+#: field:hr.payslip,input_line_ids:0
+msgid "Payslip Inputs"
+msgstr ""
#. module: hr_payroll
-#: view:hr.payroll.register:0
-msgid "Allowance / Deduction"
-msgstr "Prima / Deducción"
+#: field:hr.payslip.line,salary_rule_id:0
+msgid "Rule"
+msgstr ""
#. module: hr_payroll
-#: model:ir.actions.report.xml,name:hr_payroll.payroll_advice
-msgid "Bank Payment Advice"
-msgstr "Aviso de pago del banco"
+#: model:ir.actions.act_window,name:hr_payroll.action_hr_salary_rule_category_tree_view
+#: model:ir.ui.menu,name:hr_payroll.menu_hr_salary_rule_category_tree_view
+msgid "Salary Rule Categories Hierarchy"
+msgstr ""
+
+#. module: hr_payroll
+#: report:contribution.register.lines:0 field:hr.payslip.line,total:0
+#: report:paylip.details:0 report:payslip:0
+msgid "Total"
+msgstr ""
+
+#. module: hr_payroll
+#: help:hr.payslip.line,appears_on_payslip:0
+#: help:hr.salary.rule,appears_on_payslip:0
+msgid "Used for the display of rule on payslip"
+msgstr ""
+
+#. module: hr_payroll
+#: view:hr.payslip.line:0
+msgid "Search Payslip Lines"
+msgstr ""
#. module: hr_payroll
#: view:hr.payslip:0
-msgid "Search Payslips"
-msgstr "Buscar nóminas"
+msgid "Details By Salary Rule Category"
+msgstr ""
#. module: hr_payroll
-#: report:employees.salary:0
-#: field:hr.contibution.register.line,total:0
-#: report:year.salary:0
-msgid "Total"
-msgstr "Total"
+#: help:hr.payslip.input,code:0 help:hr.payslip.worked_days,code:0
+#: help:hr.rule.input,code:0
+msgid "The code that can be used in the salary rules"
+msgstr ""
#. module: hr_payroll
-#: view:company.contribution:0
-#: view:hr.allounce.deduction.categoty:0
-#: field:hr.allounce.deduction.categoty,contribute_ids:0
-msgid "Contributions"
-msgstr "Contribuciones"
+#: view:hr.payslip.run:0
+#: model:ir.actions.act_window,name:hr_payroll.action_hr_payslip_by_employees
+msgid "Generate Payslips"
+msgstr ""
-#~ msgid "Categoty Code"
-#~ msgstr "Código de categoría"
+#. module: hr_payroll
+#: selection:hr.contract,schedule_pay:0
+msgid "Bi-weekly"
+msgstr ""
-#~ msgid "Categoty Name"
-#~ msgstr "Nombre categoría"
+#. module: hr_payroll
+#: field:hr.employee,total_wage:0
+msgid "Total Basic Salary"
+msgstr ""
-#~ msgid "Invalid model name in the action definition."
-#~ msgstr "Nombre del modelo inválido en la definición de acción."
+#. module: hr_payroll
+#: selection:hr.payslip.line,condition_select:0
+#: selection:hr.salary.rule,condition_select:0
+msgid "Always True"
+msgstr ""
-#~ msgid "Analytic Account for Salary Analysis"
-#~ msgstr "Cuenta analítica para análisis de nóminas"
+#. module: hr_payroll
+#: report:contribution.register.lines:0
+msgid "PaySlip Name"
+msgstr ""
-#~ msgid "Employee No"
-#~ msgstr "Núm. trabajador"
-
-#~ msgid "Employee Payable Account"
-#~ msgstr "Cuenta a pagar del trabajador"
-
-#~ msgid "Account"
-#~ msgstr "Cuenta"
-
-#, python-format
-#~ msgid "Warning !"
-#~ msgstr "¡ Aviso !"
-
-#~ msgid "Payment From"
-#~ msgstr "Pago desde"
-
-#~ msgid "Keep empty to use the period of the validation(Payslip) date."
-#~ msgstr ""
-#~ "Deje en blanco para usar el período de la fecha de validación de la nómina"
-
-#~ msgid "Analytic Account"
-#~ msgstr "Cuenta analítica"
-
-#~ msgid "Force Period"
-#~ msgstr "Forzar período"
-
-#~ msgid "Accounting Information"
-#~ msgstr "Información contable"
-
-#, python-format
-#~ msgid "Integrity Error !"
-#~ msgstr "¡Error de integridad!"
-
-#~ msgid "Miscelleanous"
-#~ msgstr "Misceláneos"
-
-#~ msgid "Error! You can not create recursive analytic accounts."
-#~ msgstr "¡Error! No puede crear cuentas analíticas recursivas."
-
-#~ msgid "Account Lines"
-#~ msgstr "Movimientos"
-
-#~ msgid "Accounting Informations"
-#~ msgstr "Información contable"
-
-#~ msgid "Print"
-#~ msgstr "Imprimir"
-
-#~ msgid "Invalid XML for View Architecture!"
-#~ msgstr "¡XML inválido para la definición de la vista!"
-
-#~ msgid "Accounting Lines"
-#~ msgstr "Movimientos contables"
-
-#~ msgid "Bank Journal"
-#~ msgstr "Diario bancario"
-
-#~ msgid "Expense"
-#~ msgstr "Gastos"
-
-#~ msgid "Payment Entries"
-#~ msgstr "Asientos de pago"
-
-#~ msgid "Salary Account"
-#~ msgstr "Cuenta de nómina"
-
-#~ msgid "Employee Contract"
-#~ msgstr "Contrato de trabajador"
-
-#~ msgid ""
-#~ "The Object name must start with x_ and not contain any special character !"
-#~ msgstr ""
-#~ "¡El nombre del objeto debe empezar con x_ y no contener ningún carácter "
-#~ "especial!"
-
-#~ msgid "General Account"
-#~ msgstr "Cuenta general"
-
-#~ msgid "Process"
-#~ msgstr "Proceso"
-
-#~ msgid "Employee Account"
-#~ msgstr "Cuenta trabajador"
-
-#~ msgid "General Information"
-#~ msgstr "Información general"
-
-#~ msgid "Accounting Details"
-#~ msgstr "Detalles de contabilidad"
-
-#~ msgid "Account Information"
-#~ msgstr "Información de la cuenta"
-
-#~ msgid "Generalities"
-#~ msgstr "Generalidades"
-
-#~ msgid "Contract Duration"
-#~ msgstr "Duración del contrato"
-
-#~ msgid "Notes"
-#~ msgstr "Notas"
-
-#~ msgid "Fiscal Year"
-#~ msgstr "Ejercicio fiscal"
+#. module: hr_payroll
+#: field:hr.payslip.line,condition_range:0
+#: field:hr.salary.rule,condition_range:0
+msgid "Range Based on"
+msgstr ""
diff --git a/addons/l10n_in_hr_payroll/i18n/bn.po b/addons/l10n_in_hr_payroll/i18n/bn.po
index ea9fcfd7bb3..0fd88c3813e 100644
--- a/addons/l10n_in_hr_payroll/i18n/bn.po
+++ b/addons/l10n_in_hr_payroll/i18n/bn.po
@@ -6,928 +6,14 @@ msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0alpha\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-17 06:46+0000\n"
-"PO-Revision-Date: 2012-08-17 06:46+0000\n"
-"Last-Translator: <>\n"
+"POT-Creation-Date: 2012-09-10 09:14+0000\n"
+"PO-Revision-Date: 2012-10-10 12:31+0000\n"
+"Last-Translator: Fabien (Open ERP) \n"
"Language-Team: Bengali \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
-"Plural-Forms: \n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-11 05:00+0000\n"
+"X-Generator: Launchpad (build 16118)\n"
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "E-mail Address"
-msgstr ""
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,employee_bank_no:0
-msgid "Employee Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in draft state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Title"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Payment Advice from"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_yearly_salary_detail
-msgid "Hr Salary Employee By Category Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employees Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Allowances with Basic:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Department"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Deductions:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "A/C no."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,driver_salay:0
-msgid "Driver Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_yearly_salary_detail
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.yearly_salary
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_yearly_salary_detail
-msgid "Yearly Salary by Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.act_hr_emp_payslip_list
-msgid "Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "March"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "("
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,company_id:0
-#: field:hr.payroll.advice.line,company_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,company_id:0
-msgid "Company"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "The Manager"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Letter Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ","
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Set to Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,number_of_year:0
-msgid "Total years of work experience"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "to"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Total :"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payslip.run,available_advice:0
-msgid "Made Payment Advice?"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Advices which are paid using NEFT transfer"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,tds:0
-msgid "Amount for Tax Deduction at Source"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip
-msgid "Pay Slip"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,day:0
-msgid "Day"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Month of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.payslip:0
-msgid "Payslip 'Date From' must be before 'Date To'."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,batch_id:0
-msgid "Batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Other Information"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Cancelled"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "For"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Details by Salary Rule Category:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,voluntary_provident_fund:0
-msgid "VPF computed as percentage(%)"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,number:0
-#: report:paylip.details.in:0
-msgid "Reference"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Group By..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,medical_insurance:0
-msgid "Medical Insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Identification No"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Confirmed"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,bysal:0
-#: field:payment.advice.report,bysal:0
-#: report:payroll.advice:0
-msgid "By Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Confirm"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,chaque_nos:0
-#: field:payment.advice.report,cheque_nos:0
-msgid "Cheque Numbers"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:res.company:0
-msgid "Error! You can not create recursive companies."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_salary_employee_month
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.hr_salary_employee_bymonth
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_salary_employee_month
-msgid "Yearly Salary by Head"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#, python-format
-msgid "You can not confirm Payment advice without advice lines."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,state:0
-#: field:payment.advice.report,state:0
-msgid "State"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Yours Sincerely"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,medical_insurance:0
-msgid "Deduction towards company provided medical insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice_line
-msgid "Bank Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Email"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payslip.run,available_advice:0
-msgid "If this box is checked which means that Payment Advice exists for current batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Error !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Print"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip_run
-msgid "Payslip Batches"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,debit_credit:0
-#: report:payroll.advice:0
-msgid "C/D"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.employee.bymonth:0
-msgid "Yearly Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payroll_advice
-msgid "Print Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,line_ids:0
-msgid "Employee Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "July"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Configuration"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_view_hr_bank_advice_tree
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.hr_menu_payment_advice
-msgid "Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_payment_advice_report_all
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_reporting_payment_advice
-#: view:payment.advice.report:0
-msgid "Advices Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "This wizard will print report which displays employees break-up of Net Head for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc:0
-msgid "IFSC"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,tds:0
-msgid "TDS"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,join_date:0
-msgid "Join Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.contract:0
-msgid "Error! Contract start-date must be less than contract end-date."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:res.company,dearness_allowance:0
-msgid "Dearness Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "August"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Deduction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Search Payment advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "SI. No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in confirm state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "December"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Sheet"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,month:0
-msgid "Month"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Non Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "or"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_salary_employee_month
-msgid "Hr Salary Employee By Month Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,category_id:0
-msgid "Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#, python-format
-msgid "Payment advice already exists for %s, 'Set to Draft' to create a new advice."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "To Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,number_of_year:0
-msgid "No. of Years of Service"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Note"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Salary Rule Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: selection:hr.payroll.advice,state:0
-#: view:payment.advice.report:0
-#: selection:payment.advice.report,state:0
-msgid "Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,voluntary_provident_fund:0
-msgid "Voluntary Provident Fund"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_payment_advice_report
-msgid "Payment Advice Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Status"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,city_type:0
-msgid "Type of City"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:res.company,dearness_allowance:0
-msgid "Check this box if your company provide Dearness Allowance to employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc_code:0
-#: field:payment.advice.report,ifsc_code:0
-#: report:payroll.advice:0
-msgid "IFSC Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "June"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,nbr:0
-msgid "# Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payslip_details_report
-msgid "PaySlip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,date:0
-#: field:payment.advice.report,date:0
-msgid "Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "November"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Extended Filters..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,help:l10n_in_hr_payroll.action_payment_advice_report_all
-msgid "This report performs analysis on Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "October"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Designation"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "January"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "Pay Head Employee Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_res_company
-msgid "Companies"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:payroll.advice:0
-msgid "Authorized Signature"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_contract
-msgid "Contract"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice.line:0
-msgid "Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "To,"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,driver_salay:0
-msgid "Check this box if you provide allowance for driver"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice.line,advice_id:0
-#: field:hr.payslip,advice_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice
-msgid "Bank Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Other No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Draft Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,neft:0
-msgid "Check this box if your company use online transfer for salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,number:0
-msgid "Number"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "September"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Cancel"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Day of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.employee:0
-msgid "Error! You cannot create recursive hierarchy of Employee(s)."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "This wizard will print report which display a pay head employee breakup for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Payslip Batches ready to be Adviced"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Pay Slip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Total Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,employee_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_employee
-#: view:payment.advice.report:0
-#: field:payment.advice.report,employee_id:0
-msgid "Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Compute Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,join_date:0
-msgid "Joining date of employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Dear Sir/Madam,"
-msgstr "Dear Sir/Madam,"
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,note:0
-msgid "Description"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ")"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Payroll"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "NEFT"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Address"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,bank_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,bank_id:0
-#: report:payroll.advice:0
-#: report:salary.detail.byyear:0
-msgid "Bank"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,end_date:0
-#: field:yearly.salary.detail,date_to:0
-msgid "End Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "February"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: sql_constraint:res.company:0
-msgid "The company name must be unique !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,name:0
-#: report:paylip.details.in:0
-#: field:payment.advice.report,name:0
-#: report:salary.employee.bymonth:0
-msgid "Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: field:hr.salary.employee.month,employee_ids:0
-#: view:yearly.salary.detail:0
-#: field:yearly.salary.detail,employee_ids:0
-msgid "Employees"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "April"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Name of the Employe"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Please define bank account for the %s employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,start_date:0
-#: field:yearly.salary.detail,date_from:0
-msgid "Start Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,bank_id:0
-msgid "Select the Bank from which the salary is going to be paid"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "Employee Pay Head Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Phone No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Credit"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,name:0
-#: report:payroll.advice:0
-msgid "Bank Account No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,date:0
-msgid "Advice Date is used to search Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "May"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Create Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,year:0
-msgid "Year"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,neft:0
-#: field:payment.advice.report,neft:0
-msgid "NEFT Transaction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "Total"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "form period"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Year of Payment Advices"
-msgstr ""
\ No newline at end of file
diff --git a/addons/l10n_in_hr_payroll/i18n/gu.po b/addons/l10n_in_hr_payroll/i18n/gu.po
index 2c321b13191..844c492e28b 100644
--- a/addons/l10n_in_hr_payroll/i18n/gu.po
+++ b/addons/l10n_in_hr_payroll/i18n/gu.po
@@ -6,928 +6,14 @@ msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0alpha\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-17 06:46+0000\n"
-"PO-Revision-Date: 2012-08-17 06:46+0000\n"
-"Last-Translator: <>\n"
+"POT-Creation-Date: 2012-09-10 09:14+0000\n"
+"PO-Revision-Date: 2012-10-10 12:31+0000\n"
+"Last-Translator: Fabien (Open ERP) \n"
"Language-Team: Gujarati \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
-"Plural-Forms: \n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-11 05:00+0000\n"
+"X-Generator: Launchpad (build 16118)\n"
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "E-mail Address"
-msgstr ""
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,employee_bank_no:0
-msgid "Employee Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in draft state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Title"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Payment Advice from"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_yearly_salary_detail
-msgid "Hr Salary Employee By Category Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employees Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Allowances with Basic:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Department"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Deductions:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "A/C no."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,driver_salay:0
-msgid "Driver Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_yearly_salary_detail
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.yearly_salary
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_yearly_salary_detail
-msgid "Yearly Salary by Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.act_hr_emp_payslip_list
-msgid "Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "March"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "("
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,company_id:0
-#: field:hr.payroll.advice.line,company_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,company_id:0
-msgid "Company"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "The Manager"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Letter Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ","
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Set to Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,number_of_year:0
-msgid "Total years of work experience"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "to"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Total :"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payslip.run,available_advice:0
-msgid "Made Payment Advice?"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Advices which are paid using NEFT transfer"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,tds:0
-msgid "Amount for Tax Deduction at Source"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip
-msgid "Pay Slip"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,day:0
-msgid "Day"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Month of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.payslip:0
-msgid "Payslip 'Date From' must be before 'Date To'."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,batch_id:0
-msgid "Batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Other Information"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Cancelled"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "For"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Details by Salary Rule Category:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,voluntary_provident_fund:0
-msgid "VPF computed as percentage(%)"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,number:0
-#: report:paylip.details.in:0
-msgid "Reference"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Group By..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,medical_insurance:0
-msgid "Medical Insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Identification No"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Confirmed"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,bysal:0
-#: field:payment.advice.report,bysal:0
-#: report:payroll.advice:0
-msgid "By Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Confirm"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,chaque_nos:0
-#: field:payment.advice.report,cheque_nos:0
-msgid "Cheque Numbers"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:res.company:0
-msgid "Error! You can not create recursive companies."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_salary_employee_month
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.hr_salary_employee_bymonth
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_salary_employee_month
-msgid "Yearly Salary by Head"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#, python-format
-msgid "You can not confirm Payment advice without advice lines."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,state:0
-#: field:payment.advice.report,state:0
-msgid "State"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Yours Sincerely"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,medical_insurance:0
-msgid "Deduction towards company provided medical insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice_line
-msgid "Bank Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Email"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payslip.run,available_advice:0
-msgid "If this box is checked which means that Payment Advice exists for current batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Error !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Print"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip_run
-msgid "Payslip Batches"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,debit_credit:0
-#: report:payroll.advice:0
-msgid "C/D"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.employee.bymonth:0
-msgid "Yearly Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payroll_advice
-msgid "Print Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,line_ids:0
-msgid "Employee Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "July"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Configuration"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_view_hr_bank_advice_tree
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.hr_menu_payment_advice
-msgid "Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_payment_advice_report_all
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_reporting_payment_advice
-#: view:payment.advice.report:0
-msgid "Advices Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "This wizard will print report which displays employees break-up of Net Head for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc:0
-msgid "IFSC"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,tds:0
-msgid "TDS"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,join_date:0
-msgid "Join Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.contract:0
-msgid "Error! Contract start-date must be less than contract end-date."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:res.company,dearness_allowance:0
-msgid "Dearness Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "August"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Deduction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Search Payment advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "SI. No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in confirm state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "December"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Sheet"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,month:0
-msgid "Month"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Non Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "or"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_salary_employee_month
-msgid "Hr Salary Employee By Month Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,category_id:0
-msgid "Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#, python-format
-msgid "Payment advice already exists for %s, 'Set to Draft' to create a new advice."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "To Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,number_of_year:0
-msgid "No. of Years of Service"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Note"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Salary Rule Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: selection:hr.payroll.advice,state:0
-#: view:payment.advice.report:0
-#: selection:payment.advice.report,state:0
-msgid "Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,voluntary_provident_fund:0
-msgid "Voluntary Provident Fund"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_payment_advice_report
-msgid "Payment Advice Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Status"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,city_type:0
-msgid "Type of City"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:res.company,dearness_allowance:0
-msgid "Check this box if your company provide Dearness Allowance to employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc_code:0
-#: field:payment.advice.report,ifsc_code:0
-#: report:payroll.advice:0
-msgid "IFSC Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "June"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,nbr:0
-msgid "# Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payslip_details_report
-msgid "PaySlip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,date:0
-#: field:payment.advice.report,date:0
-msgid "Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "November"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Extended Filters..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,help:l10n_in_hr_payroll.action_payment_advice_report_all
-msgid "This report performs analysis on Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "October"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Designation"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "January"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "Pay Head Employee Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_res_company
-msgid "Companies"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:payroll.advice:0
-msgid "Authorized Signature"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_contract
-msgid "Contract"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice.line:0
-msgid "Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "To,"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,driver_salay:0
-msgid "Check this box if you provide allowance for driver"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice.line,advice_id:0
-#: field:hr.payslip,advice_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice
-msgid "Bank Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Other No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Draft Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,neft:0
-msgid "Check this box if your company use online transfer for salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,number:0
-msgid "Number"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "September"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Cancel"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Day of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.employee:0
-msgid "Error! You cannot create recursive hierarchy of Employee(s)."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "This wizard will print report which display a pay head employee breakup for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Payslip Batches ready to be Adviced"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Pay Slip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Total Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,employee_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_employee
-#: view:payment.advice.report:0
-#: field:payment.advice.report,employee_id:0
-msgid "Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Compute Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,join_date:0
-msgid "Joining date of employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Dear Sir/Madam,"
-msgstr "Dear Sir/Madam,"
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,note:0
-msgid "Description"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ")"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Payroll"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "NEFT"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Address"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,bank_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,bank_id:0
-#: report:payroll.advice:0
-#: report:salary.detail.byyear:0
-msgid "Bank"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,end_date:0
-#: field:yearly.salary.detail,date_to:0
-msgid "End Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "February"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: sql_constraint:res.company:0
-msgid "The company name must be unique !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,name:0
-#: report:paylip.details.in:0
-#: field:payment.advice.report,name:0
-#: report:salary.employee.bymonth:0
-msgid "Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: field:hr.salary.employee.month,employee_ids:0
-#: view:yearly.salary.detail:0
-#: field:yearly.salary.detail,employee_ids:0
-msgid "Employees"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "April"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Name of the Employe"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Please define bank account for the %s employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,start_date:0
-#: field:yearly.salary.detail,date_from:0
-msgid "Start Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,bank_id:0
-msgid "Select the Bank from which the salary is going to be paid"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "Employee Pay Head Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Phone No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Credit"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,name:0
-#: report:payroll.advice:0
-msgid "Bank Account No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,date:0
-msgid "Advice Date is used to search Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "May"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Create Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,year:0
-msgid "Year"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,neft:0
-#: field:payment.advice.report,neft:0
-msgid "NEFT Transaction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "Total"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "form period"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Year of Payment Advices"
-msgstr ""
\ No newline at end of file
diff --git a/addons/l10n_in_hr_payroll/i18n/hi.po b/addons/l10n_in_hr_payroll/i18n/hi.po
index d7cc9dc1519..b13e24e05f9 100644
--- a/addons/l10n_in_hr_payroll/i18n/hi.po
+++ b/addons/l10n_in_hr_payroll/i18n/hi.po
@@ -6,928 +6,14 @@ msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0alpha\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-17 06:46+0000\n"
-"PO-Revision-Date: 2012-08-17 06:46+0000\n"
-"Last-Translator: <>\n"
+"POT-Creation-Date: 2012-09-10 09:14+0000\n"
+"PO-Revision-Date: 2012-10-10 12:31+0000\n"
+"Last-Translator: Fabien (Open ERP) \n"
"Language-Team: Hindi \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
-"Plural-Forms: \n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-11 05:00+0000\n"
+"X-Generator: Launchpad (build 16118)\n"
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "E-mail Address"
-msgstr ""
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,employee_bank_no:0
-msgid "Employee Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in draft state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Title"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Payment Advice from"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_yearly_salary_detail
-msgid "Hr Salary Employee By Category Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employees Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Allowances with Basic:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Department"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Deductions:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "A/C no."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,driver_salay:0
-msgid "Driver Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_yearly_salary_detail
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.yearly_salary
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_yearly_salary_detail
-msgid "Yearly Salary by Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.act_hr_emp_payslip_list
-msgid "Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "March"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "("
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,company_id:0
-#: field:hr.payroll.advice.line,company_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,company_id:0
-msgid "Company"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "The Manager"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Letter Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ","
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Set to Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,number_of_year:0
-msgid "Total years of work experience"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "to"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Total :"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payslip.run,available_advice:0
-msgid "Made Payment Advice?"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Advices which are paid using NEFT transfer"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,tds:0
-msgid "Amount for Tax Deduction at Source"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip
-msgid "Pay Slip"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,day:0
-msgid "Day"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Month of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.payslip:0
-msgid "Payslip 'Date From' must be before 'Date To'."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,batch_id:0
-msgid "Batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Other Information"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Cancelled"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "For"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Details by Salary Rule Category:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,voluntary_provident_fund:0
-msgid "VPF computed as percentage(%)"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,number:0
-#: report:paylip.details.in:0
-msgid "Reference"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Group By..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,medical_insurance:0
-msgid "Medical Insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Identification No"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Confirmed"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,bysal:0
-#: field:payment.advice.report,bysal:0
-#: report:payroll.advice:0
-msgid "By Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Confirm"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,chaque_nos:0
-#: field:payment.advice.report,cheque_nos:0
-msgid "Cheque Numbers"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:res.company:0
-msgid "Error! You can not create recursive companies."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_salary_employee_month
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.hr_salary_employee_bymonth
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_salary_employee_month
-msgid "Yearly Salary by Head"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#, python-format
-msgid "You can not confirm Payment advice without advice lines."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,state:0
-#: field:payment.advice.report,state:0
-msgid "State"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Yours Sincerely"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,medical_insurance:0
-msgid "Deduction towards company provided medical insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice_line
-msgid "Bank Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Email"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payslip.run,available_advice:0
-msgid "If this box is checked which means that Payment Advice exists for current batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Error !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Print"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip_run
-msgid "Payslip Batches"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,debit_credit:0
-#: report:payroll.advice:0
-msgid "C/D"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.employee.bymonth:0
-msgid "Yearly Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payroll_advice
-msgid "Print Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,line_ids:0
-msgid "Employee Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "July"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Configuration"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_view_hr_bank_advice_tree
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.hr_menu_payment_advice
-msgid "Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_payment_advice_report_all
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_reporting_payment_advice
-#: view:payment.advice.report:0
-msgid "Advices Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "This wizard will print report which displays employees break-up of Net Head for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc:0
-msgid "IFSC"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,tds:0
-msgid "TDS"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,join_date:0
-msgid "Join Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.contract:0
-msgid "Error! Contract start-date must be less than contract end-date."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:res.company,dearness_allowance:0
-msgid "Dearness Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "August"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Deduction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Search Payment advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "SI. No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in confirm state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "December"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Sheet"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,month:0
-msgid "Month"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Non Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "or"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_salary_employee_month
-msgid "Hr Salary Employee By Month Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,category_id:0
-msgid "Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#, python-format
-msgid "Payment advice already exists for %s, 'Set to Draft' to create a new advice."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "To Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,number_of_year:0
-msgid "No. of Years of Service"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Note"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Salary Rule Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: selection:hr.payroll.advice,state:0
-#: view:payment.advice.report:0
-#: selection:payment.advice.report,state:0
-msgid "Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,voluntary_provident_fund:0
-msgid "Voluntary Provident Fund"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_payment_advice_report
-msgid "Payment Advice Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Status"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,city_type:0
-msgid "Type of City"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:res.company,dearness_allowance:0
-msgid "Check this box if your company provide Dearness Allowance to employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc_code:0
-#: field:payment.advice.report,ifsc_code:0
-#: report:payroll.advice:0
-msgid "IFSC Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "June"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,nbr:0
-msgid "# Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payslip_details_report
-msgid "PaySlip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,date:0
-#: field:payment.advice.report,date:0
-msgid "Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "November"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Extended Filters..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,help:l10n_in_hr_payroll.action_payment_advice_report_all
-msgid "This report performs analysis on Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "October"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Designation"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "January"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "Pay Head Employee Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_res_company
-msgid "Companies"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:payroll.advice:0
-msgid "Authorized Signature"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_contract
-msgid "Contract"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice.line:0
-msgid "Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "To,"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,driver_salay:0
-msgid "Check this box if you provide allowance for driver"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice.line,advice_id:0
-#: field:hr.payslip,advice_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice
-msgid "Bank Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Other No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Draft Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,neft:0
-msgid "Check this box if your company use online transfer for salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,number:0
-msgid "Number"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "September"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Cancel"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Day of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.employee:0
-msgid "Error! You cannot create recursive hierarchy of Employee(s)."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "This wizard will print report which display a pay head employee breakup for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Payslip Batches ready to be Adviced"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Pay Slip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Total Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,employee_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_employee
-#: view:payment.advice.report:0
-#: field:payment.advice.report,employee_id:0
-msgid "Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Compute Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,join_date:0
-msgid "Joining date of employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Dear Sir/Madam,"
-msgstr "Dear Sir/Madam,"
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,note:0
-msgid "Description"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ")"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Payroll"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "NEFT"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Address"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,bank_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,bank_id:0
-#: report:payroll.advice:0
-#: report:salary.detail.byyear:0
-msgid "Bank"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,end_date:0
-#: field:yearly.salary.detail,date_to:0
-msgid "End Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "February"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: sql_constraint:res.company:0
-msgid "The company name must be unique !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,name:0
-#: report:paylip.details.in:0
-#: field:payment.advice.report,name:0
-#: report:salary.employee.bymonth:0
-msgid "Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: field:hr.salary.employee.month,employee_ids:0
-#: view:yearly.salary.detail:0
-#: field:yearly.salary.detail,employee_ids:0
-msgid "Employees"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "April"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Name of the Employe"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Please define bank account for the %s employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,start_date:0
-#: field:yearly.salary.detail,date_from:0
-msgid "Start Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,bank_id:0
-msgid "Select the Bank from which the salary is going to be paid"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "Employee Pay Head Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Phone No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Credit"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,name:0
-#: report:payroll.advice:0
-msgid "Bank Account No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,date:0
-msgid "Advice Date is used to search Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "May"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Create Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,year:0
-msgid "Year"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,neft:0
-#: field:payment.advice.report,neft:0
-msgid "NEFT Transaction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "Total"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "form period"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Year of Payment Advices"
-msgstr ""
\ No newline at end of file
diff --git a/addons/l10n_in_hr_payroll/i18n/ta.po b/addons/l10n_in_hr_payroll/i18n/ta.po
index 98d00c76a33..dbe0e244bee 100644
--- a/addons/l10n_in_hr_payroll/i18n/ta.po
+++ b/addons/l10n_in_hr_payroll/i18n/ta.po
@@ -6,928 +6,14 @@ msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0alpha\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-17 06:46+0000\n"
-"PO-Revision-Date: 2012-08-17 06:46+0000\n"
-"Last-Translator: <>\n"
+"POT-Creation-Date: 2012-09-10 09:14+0000\n"
+"PO-Revision-Date: 2012-10-10 12:31+0000\n"
+"Last-Translator: Fabien (Open ERP) \n"
"Language-Team: Tamil \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
-"Plural-Forms: \n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-11 05:00+0000\n"
+"X-Generator: Launchpad (build 16118)\n"
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "E-mail Address"
-msgstr ""
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,employee_bank_no:0
-msgid "Employee Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in draft state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Title"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Payment Advice from"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_yearly_salary_detail
-msgid "Hr Salary Employee By Category Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employees Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Allowances with Basic:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Department"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Deductions:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "A/C no."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,driver_salay:0
-msgid "Driver Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_yearly_salary_detail
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.yearly_salary
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_yearly_salary_detail
-msgid "Yearly Salary by Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.act_hr_emp_payslip_list
-msgid "Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "March"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "("
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,company_id:0
-#: field:hr.payroll.advice.line,company_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,company_id:0
-msgid "Company"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "The Manager"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Letter Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ","
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Set to Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,number_of_year:0
-msgid "Total years of work experience"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "to"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Total :"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payslip.run,available_advice:0
-msgid "Made Payment Advice?"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Advices which are paid using NEFT transfer"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,tds:0
-msgid "Amount for Tax Deduction at Source"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip
-msgid "Pay Slip"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,day:0
-msgid "Day"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Month of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.payslip:0
-msgid "Payslip 'Date From' must be before 'Date To'."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,batch_id:0
-msgid "Batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Other Information"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Cancelled"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "For"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Details by Salary Rule Category:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,voluntary_provident_fund:0
-msgid "VPF computed as percentage(%)"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,number:0
-#: report:paylip.details.in:0
-msgid "Reference"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Group By..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,medical_insurance:0
-msgid "Medical Insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Identification No"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Confirmed"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,bysal:0
-#: field:payment.advice.report,bysal:0
-#: report:payroll.advice:0
-msgid "By Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Confirm"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,chaque_nos:0
-#: field:payment.advice.report,cheque_nos:0
-msgid "Cheque Numbers"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:res.company:0
-msgid "Error! You can not create recursive companies."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_salary_employee_month
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.hr_salary_employee_bymonth
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_salary_employee_month
-msgid "Yearly Salary by Head"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#, python-format
-msgid "You can not confirm Payment advice without advice lines."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,state:0
-#: field:payment.advice.report,state:0
-msgid "State"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Yours Sincerely"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,medical_insurance:0
-msgid "Deduction towards company provided medical insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice_line
-msgid "Bank Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Email"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payslip.run,available_advice:0
-msgid "If this box is checked which means that Payment Advice exists for current batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Error !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Print"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip_run
-msgid "Payslip Batches"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,debit_credit:0
-#: report:payroll.advice:0
-msgid "C/D"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.employee.bymonth:0
-msgid "Yearly Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payroll_advice
-msgid "Print Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,line_ids:0
-msgid "Employee Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "July"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Configuration"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_view_hr_bank_advice_tree
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.hr_menu_payment_advice
-msgid "Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_payment_advice_report_all
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_reporting_payment_advice
-#: view:payment.advice.report:0
-msgid "Advices Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "This wizard will print report which displays employees break-up of Net Head for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc:0
-msgid "IFSC"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,tds:0
-msgid "TDS"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,join_date:0
-msgid "Join Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.contract:0
-msgid "Error! Contract start-date must be less than contract end-date."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:res.company,dearness_allowance:0
-msgid "Dearness Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "August"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Deduction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Search Payment advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "SI. No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in confirm state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "December"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Sheet"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,month:0
-msgid "Month"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Non Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "or"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_salary_employee_month
-msgid "Hr Salary Employee By Month Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,category_id:0
-msgid "Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#, python-format
-msgid "Payment advice already exists for %s, 'Set to Draft' to create a new advice."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "To Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,number_of_year:0
-msgid "No. of Years of Service"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Note"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Salary Rule Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: selection:hr.payroll.advice,state:0
-#: view:payment.advice.report:0
-#: selection:payment.advice.report,state:0
-msgid "Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,voluntary_provident_fund:0
-msgid "Voluntary Provident Fund"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_payment_advice_report
-msgid "Payment Advice Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Status"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,city_type:0
-msgid "Type of City"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:res.company,dearness_allowance:0
-msgid "Check this box if your company provide Dearness Allowance to employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc_code:0
-#: field:payment.advice.report,ifsc_code:0
-#: report:payroll.advice:0
-msgid "IFSC Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "June"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,nbr:0
-msgid "# Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payslip_details_report
-msgid "PaySlip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,date:0
-#: field:payment.advice.report,date:0
-msgid "Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "November"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Extended Filters..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,help:l10n_in_hr_payroll.action_payment_advice_report_all
-msgid "This report performs analysis on Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "October"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Designation"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "January"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "Pay Head Employee Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_res_company
-msgid "Companies"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:payroll.advice:0
-msgid "Authorized Signature"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_contract
-msgid "Contract"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice.line:0
-msgid "Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "To,"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,driver_salay:0
-msgid "Check this box if you provide allowance for driver"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice.line,advice_id:0
-#: field:hr.payslip,advice_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice
-msgid "Bank Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Other No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Draft Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,neft:0
-msgid "Check this box if your company use online transfer for salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,number:0
-msgid "Number"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "September"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Cancel"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Day of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.employee:0
-msgid "Error! You cannot create recursive hierarchy of Employee(s)."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "This wizard will print report which display a pay head employee breakup for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Payslip Batches ready to be Adviced"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Pay Slip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Total Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,employee_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_employee
-#: view:payment.advice.report:0
-#: field:payment.advice.report,employee_id:0
-msgid "Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Compute Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,join_date:0
-msgid "Joining date of employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Dear Sir/Madam,"
-msgstr "Dear Sir/Madam,"
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,note:0
-msgid "Description"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ")"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Payroll"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "NEFT"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Address"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,bank_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,bank_id:0
-#: report:payroll.advice:0
-#: report:salary.detail.byyear:0
-msgid "Bank"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,end_date:0
-#: field:yearly.salary.detail,date_to:0
-msgid "End Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "February"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: sql_constraint:res.company:0
-msgid "The company name must be unique !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,name:0
-#: report:paylip.details.in:0
-#: field:payment.advice.report,name:0
-#: report:salary.employee.bymonth:0
-msgid "Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: field:hr.salary.employee.month,employee_ids:0
-#: view:yearly.salary.detail:0
-#: field:yearly.salary.detail,employee_ids:0
-msgid "Employees"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "April"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Name of the Employe"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Please define bank account for the %s employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,start_date:0
-#: field:yearly.salary.detail,date_from:0
-msgid "Start Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,bank_id:0
-msgid "Select the Bank from which the salary is going to be paid"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "Employee Pay Head Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Phone No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Credit"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,name:0
-#: report:payroll.advice:0
-msgid "Bank Account No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,date:0
-msgid "Advice Date is used to search Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "May"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Create Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,year:0
-msgid "Year"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,neft:0
-#: field:payment.advice.report,neft:0
-msgid "NEFT Transaction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "Total"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "form period"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Year of Payment Advices"
-msgstr ""
\ No newline at end of file
diff --git a/addons/l10n_in_hr_payroll/i18n/te.po b/addons/l10n_in_hr_payroll/i18n/te.po
index 0c6f6127c4d..47ea35552f8 100644
--- a/addons/l10n_in_hr_payroll/i18n/te.po
+++ b/addons/l10n_in_hr_payroll/i18n/te.po
@@ -6,928 +6,14 @@ msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0alpha\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-17 06:46+0000\n"
-"PO-Revision-Date: 2012-08-17 06:46+0000\n"
-"Last-Translator: <>\n"
+"POT-Creation-Date: 2012-09-10 09:14+0000\n"
+"PO-Revision-Date: 2012-10-10 12:31+0000\n"
+"Last-Translator: Fabien (Open ERP) \n"
"Language-Team: Telugu \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
-"Plural-Forms: \n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-11 05:00+0000\n"
+"X-Generator: Launchpad (build 16118)\n"
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "E-mail Address"
-msgstr ""
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,employee_bank_no:0
-msgid "Employee Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in draft state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Title"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Payment Advice from"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_yearly_salary_detail
-msgid "Hr Salary Employee By Category Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employees Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Allowances with Basic:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Department"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Deductions:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "A/C no."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,driver_salay:0
-msgid "Driver Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_yearly_salary_detail
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.yearly_salary
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_yearly_salary_detail
-msgid "Yearly Salary by Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.act_hr_emp_payslip_list
-msgid "Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "March"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "("
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,company_id:0
-#: field:hr.payroll.advice.line,company_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,company_id:0
-msgid "Company"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "The Manager"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Letter Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ","
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Set to Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,number_of_year:0
-msgid "Total years of work experience"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "to"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Total :"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payslip.run,available_advice:0
-msgid "Made Payment Advice?"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Advices which are paid using NEFT transfer"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,tds:0
-msgid "Amount for Tax Deduction at Source"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip
-msgid "Pay Slip"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,day:0
-msgid "Day"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Month of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.payslip:0
-msgid "Payslip 'Date From' must be before 'Date To'."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,batch_id:0
-msgid "Batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Other Information"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Cancelled"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "For"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Details by Salary Rule Category:"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,voluntary_provident_fund:0
-msgid "VPF computed as percentage(%)"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,number:0
-#: report:paylip.details.in:0
-msgid "Reference"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Group By..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,medical_insurance:0
-msgid "Medical Insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Identification No"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.payroll.advice,state:0
-#: selection:payment.advice.report,state:0
-msgid "Confirmed"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,bysal:0
-#: field:payment.advice.report,bysal:0
-#: report:payroll.advice:0
-msgid "By Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Confirm"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,chaque_nos:0
-#: field:payment.advice.report,cheque_nos:0
-msgid "Cheque Numbers"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:res.company:0
-msgid "Error! You can not create recursive companies."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_salary_employee_month
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.hr_salary_employee_bymonth
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_salary_employee_month
-msgid "Yearly Salary by Head"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#, python-format
-msgid "You can not confirm Payment advice without advice lines."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,state:0
-#: field:payment.advice.report,state:0
-msgid "State"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Yours Sincerely"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,medical_insurance:0
-msgid "Deduction towards company provided medical insurance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice_line
-msgid "Bank Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Email"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payslip.run,available_advice:0
-msgid "If this box is checked which means that Payment Advice exists for current batch"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:184
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Error !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Print"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payslip_run
-msgid "Payslip Batches"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,debit_credit:0
-#: report:payroll.advice:0
-msgid "C/D"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.employee.bymonth:0
-msgid "Yearly Salary Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payroll_advice
-msgid "Print Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,line_ids:0
-msgid "Employee Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "July"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Configuration"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_view_hr_bank_advice_tree
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.hr_menu_payment_advice
-msgid "Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,name:l10n_in_hr_payroll.action_payment_advice_report_all
-#: model:ir.ui.menu,name:l10n_in_hr_payroll.menu_reporting_payment_advice
-#: view:payment.advice.report:0
-msgid "Advices Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "This wizard will print report which displays employees break-up of Net Head for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc:0
-msgid "IFSC"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,tds:0
-msgid "TDS"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,join_date:0
-msgid "Join Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.contract:0
-msgid "Error! Contract start-date must be less than contract end-date."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:res.company,dearness_allowance:0
-msgid "Dearness Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "August"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Deduction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Search Payment advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "SI. No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Payment Advices which are in confirm state"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "December"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Confirm Sheet"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,month:0
-msgid "Month"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Non Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "or"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_salary_employee_month
-msgid "Hr Salary Employee By Month Report"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,category_id:0
-msgid "Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:240
-#, python-format
-msgid "Payment advice already exists for %s, 'Set to Draft' to create a new advice."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "To Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.employee,number_of_year:0
-msgid "No. of Years of Service"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Note"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Salary Rule Category"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: selection:hr.payroll.advice,state:0
-#: view:payment.advice.report:0
-#: selection:payment.advice.report,state:0
-msgid "Draft"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Date From"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,voluntary_provident_fund:0
-msgid "Voluntary Provident Fund"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Employee Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_payment_advice_report
-msgid "Payment Advice Analysis"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:payment.advice.report:0
-msgid "Status"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.contract,city_type:0
-msgid "Type of City"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:res.company,dearness_allowance:0
-msgid "Check this box if your company provide Dearness Allowance to employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,ifsc_code:0
-#: field:payment.advice.report,ifsc_code:0
-#: report:payroll.advice:0
-msgid "IFSC Code"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "June"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,nbr:0
-msgid "# Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.report.xml,name:l10n_in_hr_payroll.payslip_details_report
-msgid "PaySlip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Payment Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,date:0
-#: field:payment.advice.report,date:0
-msgid "Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "November"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Extended Filters..."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.actions.act_window,help:l10n_in_hr_payroll.action_payment_advice_report_all
-msgid "This report performs analysis on Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "October"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Designation"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "January"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "Pay Head Employee Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_res_company
-msgid "Companies"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:payroll.advice:0
-msgid "Authorized Signature"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_contract
-msgid "Contract"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice.line:0
-msgid "Advice Lines"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "To,"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.contract,driver_salay:0
-msgid "Check this box if you provide allowance for driver"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice.line,advice_id:0
-#: field:hr.payslip,advice_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_payroll_advice
-msgid "Bank Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Other No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Draft Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,neft:0
-msgid "Check this box if your company use online transfer for salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "To"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:payment.advice.report,number:0
-msgid "Number"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "September"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: view:hr.salary.employee.month:0
-#: view:yearly.salary.detail:0
-msgid "Cancel"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Day of Payment Advices"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: constraint:hr.employee:0
-msgid "Error! You cannot create recursive hierarchy of Employee(s)."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:yearly.salary.detail:0
-msgid "This wizard will print report which display a pay head employee breakup for a specified dates."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Payslip Batches ready to be Adviced"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Pay Slip Details"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Total Salary"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,employee_id:0
-#: model:ir.model,name:l10n_in_hr_payroll.model_hr_employee
-#: view:payment.advice.report:0
-#: field:payment.advice.report,employee_id:0
-msgid "Employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-msgid "Compute Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.employee,join_date:0
-msgid "Joining date of employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Dear Sir/Madam,"
-msgstr "Dear Sir/Madam,"
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,note:0
-msgid "Description"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid ")"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:res.company:0
-msgid "Payroll"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "NEFT"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-msgid "Address"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,bank_id:0
-#: view:payment.advice.report:0
-#: field:payment.advice.report,bank_id:0
-#: report:payroll.advice:0
-#: report:salary.detail.byyear:0
-msgid "Bank"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,end_date:0
-#: field:yearly.salary.detail,date_to:0
-msgid "End Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "February"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: sql_constraint:res.company:0
-msgid "The company name must be unique !"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payroll.advice:0
-#: field:hr.payroll.advice,name:0
-#: report:paylip.details.in:0
-#: field:payment.advice.report,name:0
-#: report:salary.employee.bymonth:0
-msgid "Name"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:hr.contract,city_type:0
-msgid "Metro"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-#: field:hr.salary.employee.month,employee_ids:0
-#: view:yearly.salary.detail:0
-#: field:yearly.salary.detail,employee_ids:0
-msgid "Employees"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Bank Account"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "April"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "Name of the Employe"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:158
-#: code:addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py:257
-#, python-format
-msgid "Please define bank account for the %s employee"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.salary.employee.month,start_date:0
-#: field:yearly.salary.detail,date_from:0
-msgid "Start Date"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.contract:0
-msgid "Allowance"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,bank_id:0
-msgid "Select the Bank from which the salary is going to be paid"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.salary.employee.month:0
-msgid "Employee Pay Head Breakup"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:salary.detail.byyear:0
-msgid "Phone No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-msgid "Credit"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice.line,name:0
-#: report:payroll.advice:0
-msgid "Bank Account No."
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: help:hr.payroll.advice,date:0
-msgid "Advice Date is used to search Payslips"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: selection:payment.advice.report,month:0
-msgid "May"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:hr.payslip.run:0
-msgid "Create Advice"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-#: field:payment.advice.report,year:0
-msgid "Year"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: field:hr.payroll.advice,neft:0
-#: field:payment.advice.report,neft:0
-msgid "NEFT Transaction"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:paylip.details.in:0
-#: report:salary.detail.byyear:0
-#: report:salary.employee.bymonth:0
-msgid "Total"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: report:payroll.advice:0
-msgid "form period"
-msgstr ""
-
-#. module: l10n_in_hr_payroll
-#: view:payment.advice.report:0
-msgid "Year of Payment Advices"
-msgstr ""
\ No newline at end of file