Source code for connector.components.binder

# -*- coding: utf-8 -*-
# Copyright 2013-2017 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

"""
Binders
=======

Binders are components that know how to find the external ID for an
Odoo ID, how to find the Odoo ID for an external ID and how to
create the binding between them.

"""

from odoo import fields, models, tools
from odoo.addons.component.core import AbstractComponent


[docs]class Binder(AbstractComponent): """ For one record of a model, capable to find an external or internal id, or create the binding (link) between them This is a default implementation that can be inherited or reimplemented in the connectors. This implementation assumes that binding models are ``_inherits`` of the models they are binding. """ _name = 'base.binder' _inherit = 'base.connector' _usage = 'binder' _external_field = 'external_id' # override in sub-classes _backend_field = 'backend_id' # override in sub-classes _odoo_field = 'odoo_id' # override in sub-classes _sync_date_field = 'sync_date' # override in sub-classes
[docs] def to_internal(self, external_id, unwrap=False): """ Give the Odoo recordset for an external ID :param external_id: external ID for which we want the Odoo ID :param unwrap: if True, returns the normal record else return the binding record :return: a recordset, depending on the value of unwrap, or an empty recordset if the external_id is not mapped :rtype: recordset """ bindings = self.model.with_context(active_test=False).search( [(self._external_field, '=', tools.ustr(external_id)), (self._backend_field, '=', self.backend_record.id)] ) if not bindings: if unwrap: return self.model.browse()[self._odoo_field] return self.model.browse() bindings.ensure_one() if unwrap: bindings = bindings[self._odoo_field] return bindings
[docs] def to_external(self, binding, wrap=False): """ Give the external ID for an Odoo binding ID :param binding: Odoo binding for which we want the external id :param wrap: if True, binding is a normal record, the method will search the corresponding binding and return the external id of the binding :return: external ID of the record """ if isinstance(binding, models.BaseModel): binding.ensure_one() else: binding = self.model.browse(binding) if wrap: binding = self.model.with_context(active_test=False).search( [(self._odoo_field, '=', binding.id), (self._backend_field, '=', self.backend_record.id), ] ) if not binding: return None binding.ensure_one() return binding[self._external_field] return binding[self._external_field]
[docs] def bind(self, external_id, binding): """ Create the link between an external ID and an Odoo ID :param external_id: external id to bind :param binding: Odoo record to bind :type binding: int """ # Prevent False, None, or "", but not 0 assert (external_id or external_id is 0) and binding, ( "external_id or binding missing, " "got: %s, %s" % (external_id, binding) ) # avoid to trigger the export when we modify the `external_id` now_fmt = fields.Datetime.now() if isinstance(binding, models.BaseModel): binding.ensure_one() else: binding = self.model.browse(binding) binding.with_context(connector_no_export=True).write( {self._external_field: tools.ustr(external_id), self._sync_date_field: now_fmt, })
[docs] def unwrap_binding(self, binding): """ For a binding record, gives the normal record. Example: when called with a ``magento.product.product`` id, it will return the corresponding ``product.product`` id. :param browse: when True, returns a browse_record instance rather than an ID """ if isinstance(binding, models.BaseModel): binding.ensure_one() else: binding = self.model.browse(binding) return binding[self._odoo_field]
[docs] def unwrap_model(self): """ For a binding model, gives the normal model. Example: when called on a binder for ``magento.product.product``, it will return ``product.product``. """ try: column = self.model._fields[self._odoo_field] except KeyError: raise ValueError( 'Cannot unwrap model %s, because it has no %s fields' % (self.model._name, self._odoo_field)) return column.comodel_name