Code Overview¶
Some simple code examples.
Trigger and listen an event¶
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
@api.multi
def action_invoice_paid(self):
res = super(AccountInvoice, self).action_invoice_paid()
for record in self:
self._event('on_invoice_paid').notify(record)
return res
from odoo.addons.component.core import Component
class MyEventListener(Component):
_name = 'my.event.listener'
_inherit = 'base.event.listener'
def on_invoice_paid(self, record):
_logger.info('invoice %s has been paid!', record.name)
Ref: Events
Delay an Asynchronous Job¶
from odoo.addons.queue_job.job import job
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
@job
@api.multi
def export_payment(self):
self.ensure_one()
_logger.info("I'm exporting the payment for %s", self.name)
@api.multi
def action_invoice_paid(self):
res = super(AccountInvoice, self).action_invoice_paid()
for record in self:
record.with_delay(priority=5).export_payment()
return res
Ref: Queue
Work with components¶
This is a highly simplified version of a micro-connector, without using events or jobs, for the sake of the example.
from odoo.addons.component.core import AbstractComponent
class MagentoBackend(models.Model):
_name = 'magento.backend'
_description = 'Magento Backend'
_inherit = 'connector.backend'
location = fields.Char(string='Location', required=True)
username = fields.Char(string='Username')
password = fields.Char(string='Password')
def import_partner(self, external_id):
with self.work_on(model_name='magento.res.partner') as work:
importer = work.component(usage='record.importer')
# returns an instance of PartnerImporter, which has been
# found with:the collection name (magento.backend, the model,
# and the usage).
importer.run(partner_id)
# the next 2 components are abstract and are used by inheritance
# by the others
class BaseMagentoConnectorComponent(AbstractComponent):
# same inheritance than Odoo models
_name = 'base.magento.connector'
_inherit = 'base.connector'
# subscribe to:
_collection = 'magento.backend'
# the collection will be inherited to the components below,
# because they inherit from this component
class GenericAdapter(AbstractComponent):
# same inheritance than Odoo models
_name = 'magento.adapter'
_inherit = ['base.backend.adapter', 'base.magento.connector']
# usage is used for lookups of components
_usage = 'backend.adapter'
_magento_model = None
def _call(self, *args, **kwargs):
location = self.backend_record.location
# use client API
def read(self, fields=None):
""" Search records according to some criterias
and returns a list of ids
:rtype: list
"""
return self._call('%s.info' % self._magento_model, fields)
# these are the components we need for our synchronization
class PartnerAdapter(Component):
_name = 'magento.partner.adapter'
_inherit = 'magento.adapter'
_apply_on = ['magento.res.partner']
_magento_model = 'customer'
class PartnerMapper(Component):
_name = 'magento.partner.import.mapper'
_inherit = 'magento.import.mapper' # parent component omitted for brevity
_apply_on = ['magento.res.partner']
_usage = 'import.mapper'
class PartnerBinder(Component):
_name = 'magento.partner.binder'
_inherit = 'magento.binder' # parent component omitted for brevity
_apply_on = ['magento.res.partner']
_usage = 'binder'
class PartnerImporter(Component):
_name = 'magento.partner.importer'
_inherit = 'magento.importer' # parent component omitted for brevity
_apply_on = ['magento.res.partner']
_usage = 'record.importer'
def run(self, external_id):
# get the components we need for the sync
# this one knows how to speak to magento
backend_adapter = self.component(usage='backend.adapter')
# this one knows how to convert magento data to odoo data
mapper = self.component(usage='import.mapper')
# this one knows how to link magento/odoo records
binder = self.component(usage='binder')
# read external data from magento
external_data = backend_adapter.read(external_id)
# convert to odoo data
internal_data = mapper.map_record(external_data).values()
# find if the magento id already exists in odoo
binding = binder.to_internal(external_id)
if binding:
# if yes, we update it
binding.write(internal_data)
else:
# or we create it
binding = self.model.create(internal_data)
# finally, we bind both, so the next time we import
# the record, we'll update the same record instead of
# creating a new one
binder.bind(external_id, binding)
Ref: Components