141 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
# -*- 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
 | 
						|
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
    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
 | 
						|
 | 
						|
    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]
 | 
						|
 | 
						|
    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,
 | 
						|
             })
 | 
						|
 | 
						|
    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]
 | 
						|
 | 
						|
    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
 |