Skip to content

Commit

Permalink
[WIP] add configurable inheritage
Browse files Browse the repository at this point in the history
- import product attribute OK

- import product attributes values OK

- import product attribute lines OK

- change product template OK

TODO :
- remove useless product templates
- unit tests
  • Loading branch information
PierrickBrun committed Oct 19, 2017
1 parent f02affb commit 8663e37
Show file tree
Hide file tree
Showing 18 changed files with 683 additions and 0 deletions.
37 changes: 37 additions & 0 deletions connector_magento/models/product/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 37 additions & 0 deletions connector_magento_configurable/README.rst
Original file line number Diff line number Diff line change
@@ -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
<https://github.com/OCA/connector-magento/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 <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.

Contributors
------------


Maintainer
----------

2 changes: 2 additions & 0 deletions connector_magento_configurable/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import models
17 changes: 17 additions & 0 deletions connector_magento_configurable/__manifest__.py
Original file line number Diff line number Diff line change
@@ -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,
}
6 changes: 6 additions & 0 deletions connector_magento_configurable/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from . import configurable
from . import inherits
from . import product_attribute
from . import product_attribute_value
from . import product_attribute_line
58 changes: 58 additions & 0 deletions connector_magento_configurable/models/configurable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# -*- 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, record, force=False):
filters = {'record': record}
self.env['magento.product.attribute'].import_batch(
self.backend_record,
filters,
)
self.env['magento.product.attribute.line'].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'
56 changes: 56 additions & 0 deletions connector_magento_configurable/models/inherits.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# -*- 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',
'magento.product.attribute.value',
'magento.product.attribute.line',
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import common
from . import importer
65 changes: 65 additions & 0 deletions connector_magento_configurable/models/product_attribute/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -*- 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 list of the super attributes and their possible values
from a specific configurable product
:rtype: dict
"""
return self._call('%s.listSuperAttributes' % self._magento_model,
[sku, storeview_id, attributes])
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# -*- 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.
"""
_name = 'magento.product.attribute.batch.importer'
_inherit = 'magento.delayed.batch.importer'
_apply_on = ['magento.product.attribute']

def run(self, filters=None):
""" Run the synchronization """
record = filters['record']
updated_attributes = self.backend_adapter.list_attributes(
record.default_code)
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 magento_record already contains all the data to insert,
no need to make a xmlrpc call
"""
return self.magento_record

def _after_import(self, binding):
self.env['magento.product.attribute.value'].import_batch(
self.backend_record,
{
'values': self.magento_record['values'],
'attribute_id': self.magento_record['attribute_id'],
}
)

def run(self, magento_record, force=False):
self.magento_record = magento_record
super(ProductAttributeImporter, self).run(
magento_record['attribute_id'],
force,
)


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}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import common
from . import importer
Loading

0 comments on commit 8663e37

Please sign in to comment.