From 37664ea9a29dc8804dfc3c07ea1dc6a0bb37b787 Mon Sep 17 00:00:00 2001 From: Pierrick Brun Date: Tue, 10 Oct 2017 10:04:10 +0200 Subject: [PATCH] [WIP] add configurable inheritage --- connector_magento/models/product/importer.py | 37 +++++++++++ connector_magento_configurable/README.rst | 37 +++++++++++ connector_magento_configurable/__init__.py | 2 + .../__manifest__.py | 17 +++++ .../models/__init__.py | 4 ++ .../models/configurable.py | 54 ++++++++++++++++ .../models/inherits.py | 52 +++++++++++++++ .../models/product_attribute/__init__.py | 3 + .../models/product_attribute/common.py | 64 +++++++++++++++++++ .../models/product_attribute/importer.py | 59 +++++++++++++++++ .../security/ir.model.access.csv | 3 + .../views/magento_backend_views.xml | 24 +++++++ 12 files changed, 356 insertions(+) create mode 100644 connector_magento_configurable/README.rst create mode 100644 connector_magento_configurable/__init__.py create mode 100644 connector_magento_configurable/__manifest__.py create mode 100644 connector_magento_configurable/models/__init__.py create mode 100644 connector_magento_configurable/models/configurable.py create mode 100644 connector_magento_configurable/models/inherits.py create mode 100644 connector_magento_configurable/models/product_attribute/__init__.py create mode 100644 connector_magento_configurable/models/product_attribute/common.py create mode 100644 connector_magento_configurable/models/product_attribute/importer.py create mode 100644 connector_magento_configurable/security/ir.model.access.csv create mode 100644 connector_magento_configurable/views/magento_backend_views.xml diff --git a/connector_magento/models/product/importer.py b/connector_magento/models/product/importer.py index 937605337..3887087f3 100644 --- a/connector_magento/models/product/importer.py +++ b/connector_magento/models/product/importer.py @@ -118,6 +118,43 @@ def run(self, external_id, binding): self._write_image_data(binding, binary, image_data) +# class ConfigurableImporter(Component): +# """ Can be inherited to change the way the configurable products are +# imported. +# +# called at the end of the import of a product. +# +# By default, the configurable products are imported as simple products, the +# configurable product is skipped and his children are imported separately. +# +# If you want to create a custom importer for the configurables, you have to +# inherit the Component:: +# +# class ConfigurableImporter(Component): +# _inherit = 'magento.product.configurable.importer' +# +# And to bypass the _must_skip:: +# +# class ProductImporter(Component): +# _inherit = 'magento.product.product.importer' +# +# def _must_skip(self): +# res = super(ProductImporter, self)._must_skip() +# if self.magento_record['type_id'] != 'configurable': +# return res +# """ +# _name = 'magento.product.configurable.importer' +# _inherit = 'magento.importer' +# _apply_on = ['magento.product.product'] +# _usage = 'product.configurable.importer' +# +# def run(self, binding, magento_record): +# """ import the configurable information about a product. +# +# :param magento_record: product information from Magento +# """ + + # TODO: not needed, use inheritance class BundleImporter(Component): """ Can be inherited to change the way the bundle products are diff --git a/connector_magento_configurable/README.rst b/connector_magento_configurable/README.rst new file mode 100644 index 000000000..281eee12d --- /dev/null +++ b/connector_magento_configurable/README.rst @@ -0,0 +1,37 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +==================================================== +Magento Connector - Configurable Product +==================================================== + +This modules aims to create configurable products as Product templates and +linked ProductProduct and not flat ProductProduct + +Installation +============ + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + + +Maintainer +---------- + diff --git a/connector_magento_configurable/__init__.py b/connector_magento_configurable/__init__.py new file mode 100644 index 000000000..a0fdc10fe --- /dev/null +++ b/connector_magento_configurable/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import models diff --git a/connector_magento_configurable/__manifest__.py b/connector_magento_configurable/__manifest__.py new file mode 100644 index 000000000..c11409e0b --- /dev/null +++ b/connector_magento_configurable/__manifest__.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +{'name': 'Magento Connector - Configurable', + 'version': '10.0.1.0.0', + 'author': 'Akretion, Odoo Community Association (OCA)', + 'license': 'AGPL-3', + 'category': 'Hidden', + 'depends': ['connector_magento'], + 'data': [ + # 'security/ir.model.access.csv', + 'views/magento_backend_views.xml', + ], + 'installable': True, + 'auto_install': True, + } diff --git a/connector_magento_configurable/models/__init__.py b/connector_magento_configurable/models/__init__.py new file mode 100644 index 000000000..cd7e040a9 --- /dev/null +++ b/connector_magento_configurable/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +from . import configurable +from . import inherits +from . import product_attribute diff --git a/connector_magento_configurable/models/configurable.py b/connector_magento_configurable/models/configurable.py new file mode 100644 index 000000000..f54ed775d --- /dev/null +++ b/connector_magento_configurable/models/configurable.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +import logging + +from odoo import models + +from odoo.addons.component.core import Component + +_logger = logging.getLogger(__name__) + + +class ConfigurableBatchImporter(Component): + """ Import the Configurable Products. + + For every Configurable Product not yet converted from flat + to templated product, creates a job + """ + _name = 'magento.product.configurable.batch.importer' + _inherit = 'magento.delayed.batch.importer' + _apply_on = ['magento.product.configurable'] + + def run(self, filters=None): + """ Run the synchronization """ + # from_date = filters.pop('from_date', None) + # to_date = filters.pop('to_date', None) + internal_ids = self.env['magento.product.product'].search( + [('product_type', '=', 'configurable')] + ) + _logger.info('search for configurable products %s returned %s', + filters, internal_ids) + for internal_id in internal_ids: + self._import_record(internal_id) + + +class ConfigurableImporter(Component): + _name = 'magento.product.configurable.importer' + _inherit = 'magento.importer' + _apply_on = ['magento.product.configurable'] + + def run(self, magento_record, force=False): + filters = {'sku': magento_record.default_code} + self.env['magento.product.attribute'].import_batch( + self.backend_record, + filters, + ) + + +class MagentoProductConfigurable(models.Model): + _name = 'magento.product.configurable' + _inherit = 'magento.binding' + _inherits = {'product.product': 'odoo_id'} + _description = 'Magento Product Configurable' diff --git a/connector_magento_configurable/models/inherits.py b/connector_magento_configurable/models/inherits.py new file mode 100644 index 000000000..464594098 --- /dev/null +++ b/connector_magento_configurable/models/inherits.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import models, fields, api + +from odoo.addons.component.core import Component + + +class MagentoBackend(models.Model): + _inherit = 'magento.backend' + + import_configurables_from_date = fields.Datetime( + string='Import configurables from date', + ) + + @api.multi + def import_product_configurable(self): + self._import_from_date('magento.product.configurable', + 'import_configurables_from_date') + return True + + @api.model + def _scheduler_import_product_configurable(self, domain=None): + self._magento_backend('import_product_configurable', domain=domain) + + +class ProductImporter(Component): + _inherit = 'magento.product.product.importer' + + """ + Returns None if the product_type is configurable + So that it is not skipped + """ + def _must_skip(self): + res = super(ProductImporter, self)._must_skip() + if self.magento_record['type_id'] != 'configurable': + return res + + +class MagentoProductProduct(models.Model): + _inherit = 'magento.product.product' + + transformed_at = fields.Date( + 'Transformed At (from simple to templated product)' + ) + + +class MagentoConfigurableModelBinder(Component): + _name = 'magento.configurable.binder' + _inherit = 'magento.binder' + _apply_on = ['magento.product.attribute'] diff --git a/connector_magento_configurable/models/product_attribute/__init__.py b/connector_magento_configurable/models/product_attribute/__init__.py new file mode 100644 index 000000000..9d854de96 --- /dev/null +++ b/connector_magento_configurable/models/product_attribute/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +from . import common +from . import importer diff --git a/connector_magento_configurable/models/product_attribute/common.py b/connector_magento_configurable/models/product_attribute/common.py new file mode 100644 index 000000000..6e7978443 --- /dev/null +++ b/connector_magento_configurable/models/product_attribute/common.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +import xmlrpclib +from odoo import models, fields +from odoo.addons.connector.exception import IDMissingInBackend +from odoo.addons.component.core import Component + +_logger = logging.getLogger(__name__) + + +class MagentoProductAttribute(models.Model): + _name = 'magento.product.attribute' + _inherit = 'magento.binding' + _inherits = {'product.attribute': 'odoo_id'} + _description = 'Magento Product Attribute' + + odoo_id = fields.Many2one( + comodel_name='product.attribute', + string='Product Attribute', + required=True, + ondelete='cascade') + + +class ProductAttribute(models.Model): + _inherit = 'product.attribute' + + magento_bind_ids = fields.One2many( + comodel_name='magento.product.attribute', + inverse_name='odoo_id', + string="Magento Bindings", + ) + + +class ProductAttributeAdapter(Component): + _name = 'magento.product.attribute.adapter' + _inherit = 'magento.adapter' + _apply_on = 'magento.product.attribute' + + _magento_model = 'ol_catalog_product_link' + _admin_path = '/{model}/index/' + + def _call(self, method, arguments): + try: + return super(ProductAttributeAdapter, self)._call( + method, + arguments) + except xmlrpclib.Fault as err: + # 101 is the error in the Magento API + # when the attribute does not exist + if err.faultCode == 101: + raise IDMissingInBackend + else: + raise + + def list_attributes(self, sku, storeview_id=None, attributes=None): + """ Returns the information of a record + + :rtype: dict + """ + return self._call('%s.listSuperAttributes' % self._magento_model, + [sku, storeview_id, attributes]) diff --git a/connector_magento_configurable/models/product_attribute/importer.py b/connector_magento_configurable/models/product_attribute/importer.py new file mode 100644 index 000000000..8062d53b5 --- /dev/null +++ b/connector_magento_configurable/models/product_attribute/importer.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo.addons.component.core import Component +from odoo.addons.connector.components.mapper import mapping + + +class ProductAttributeBatchImporter(Component): + """ Import the Magento Product Attributes. + + For every product attribute in the list, a delayed job is created. + A priority is set on the jobs according to their level to rise the + chance to have the top level attributes imported first. + """ + _name = 'magento.product.attribute.batch.importer' + _inherit = 'magento.delayed.batch.importer' + _apply_on = ['magento.product.attribute'] + + def _import_record(self, external_id, job_options=None): + """ Delay a job for the import """ + super(ProductAttributeBatchImporter, self)._import_record( + external_id, job_options=job_options + ) + + def run(self, filters=None): + """ Run the synchronization """ + sku = filters['sku'] + updated_attributes = self.backend_adapter.list_attributes(sku) + for attribute in updated_attributes: + self._import_record(attribute) + + +class ProductAttributeImporter(Component): + _name = 'magento.product.attribute.importer' + _inherit = 'magento.importer' + _apply_on = ['magento.product.attribute'] + + def _get_magento_data(self, storeview_id=None): + """ + In this case, the external_id contains all the object to insert + """ + return self.external_id + + +class ProductAttributeImportMapper(Component): + _name = 'magento.product.attribute.import.mapper' + _inherit = 'magento.import.mapper' + _apply_on = 'magento.product.attribute' + + direct = [ + ('attribute_code', 'name'), + ('attribute_id', 'external_id'), + ('store_label', 'display_name'), + ] + + @mapping + def backend_id(self, record): + return {'backend_id': self.backend_record.id} diff --git a/connector_magento_configurable/security/ir.model.access.csv b/connector_magento_configurable/security/ir.model.access.csv new file mode 100644 index 000000000..06d0dbda6 --- /dev/null +++ b/connector_magento_configurable/security/ir.model.access.csv @@ -0,0 +1,3 @@ +"access_magento_product_attribute","magento_product_attribute connector manager","model_magento_product_attribute","connector.group_connector_manager",1,1,1,1 +"access_magento_product_attribute_user","magento_product_attribute user","model_magento_product_attribute","sales_team.group_sale_salesman",1,0,0,0 +"access_magento_product_attribute_sale_manager","magento_product_attribute sale manager","model_magento_product_attribute","sales_team.group_sale_manager",1,1,1,1 diff --git a/connector_magento_configurable/views/magento_backend_views.xml b/connector_magento_configurable/views/magento_backend_views.xml new file mode 100644 index 000000000..741c92b81 --- /dev/null +++ b/connector_magento_configurable/views/magento_backend_views.xml @@ -0,0 +1,24 @@ + + + + + magento.backend + + + + +
+
+