'write(vals)
Updates all records in the current set with the provided values.
:param dict vals: fields to update and the value to set on them e.g::
{\'foo\': 1, \'bar\': "Qux"}
will set the field ``foo`` to ``1`` and the field ``bar`` to
``"Qux"`` if those are valid (otherwise it will trigger an error).
:raise AccessError: * if user has no write rights on the requested object
* if user tries to bypass access rules for write on the requested object
:raise ValidateError: if user tries to enter invalid value for a field that is not in selection
:raise UserError: if a loop would be created in a hierarchy of objects a result of the operation (such as setting an object as its own parent)
* For numeric fields (:class:`~odoo.fields.Integer`,
:class:`~odoo.fields.Float`) the value should be of the
corresponding type
* For :class:`~odoo.fields.Boolean`, the value should be a
:class:`python:bool`
* For :class:`~odoo.fields.Selection`, the value should match the
selection values (generally :class:`python:str`, sometimes
:class:`python:int`)
* For :class:`~odoo.fields.Many2one`, the value should be the
database identifier of the record to set
* Other non-relational fields use a string for value
.. danger::
for historical and compatibility reasons,
:class:`~odoo.fields.Date` and
:class:`~odoo.fields.Datetime` fields use strings as values
(written and read) rather than :class:`~python:datetime.date` or
:class:`~python:datetime.datetime`. These date strings are
UTC-only and formatted according to
:const:`odoo.tools.misc.DEFAULT_SERVER_DATE_FORMAT` and
:const:`odoo.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT`
* .. _openerp/models/relationals/format:
:class:`~odoo.fields.One2many` and
:class:`~odoo.fields.Many2many` use a special "commands" format to
manipulate the set of records stored in/associated with the field.
This format is a list of triplets executed sequentially, where each
triplet is a command to execute on the set of records. Not all
commands apply in all situations. Possible commands are:
``(0, _, values)``
adds a new record created from the provided ``value`` dict.
``(1, id, values)``
updates an existing record of id ``id`` with the values in
``values``. Can not be used in :meth:`~.create`.
``(2, id, _)``
removes the record of id ``id`` from the set, then deletes it
(from the database). Can not be used in :meth:`~.create`.
``(3, id, _)``
removes the record of id ``id`` from the set, but does not
delete it. Can not be used on
:class:`~odoo.fields.One2many`. Can not be used in
:meth:`~.create`.
``(4, id, _)``
adds an existing record of id ``id`` to the set. Can not be
used on :class:`~odoo.fields.One2many`.
``(5, _, _)``
removes all records from the set, equivalent to using the
command ``3`` on every record explicitly. Can not be used on
:class:`~odoo.fields.One2many`. Can not be used in
:meth:`~.create`.
``(6, _, ids)``
replaces all existing records in the set by the ``ids`` list,
equivalent to using the command ``5`` followed by a command
``4`` for each ``id`` in ``ids``.
.. note:: Values marked as ``_`` in the list above are ignored and
can be anything, generally ``0`` or ``False``.'

@api.multi
def write(self, vals):

    if (not self):
        return True
    self._check_concurrency()
    self.check_access_rights('write')
    for field in itertools.chain(MAGIC_COLUMNS, ('parent_left', 'parent_right')):
        vals.pop(field, None)
    (old_vals, new_vals, unknown) = ({}, {}, [])
    for (key, val) in vals.iteritems():
        field = self._fields.get(key)
        if field:
            if (field.store or field.inherited):
                old_vals[key] = val
            if (field.inverse and (not field.inherited)):
                new_vals[key] = val
        else:
            unknown.append(key)
    if unknown:
        _logger.warning('%s.write()    with    unknown    fields:    %s', self._name, ',    '.join(sorted(unknown)))
    protected_fields = map(self._fields.get, new_vals)
    with self.env.protecting(protected_fields, self):
        if old_vals:
            self._write(old_vals)
        if new_vals:
            self.modified((set(new_vals) - set(old_vals)))
            for record in self:
                record._cache.update(record._convert_to_cache(new_vals, update=True))
            for key in new_vals:
                self._fields[key].determine_inverse(self)
            self.modified((set(new_vals) - set(old_vals)))
            self._validate_fields((set(new_vals) - set(old_vals)))
            if (self.env.recompute and self._context.get('recompute', True)):
                self.recompute()
    return True
