Example #1
0
    def _map_direct(self, record, from_attr, to_attr):
        """ Apply the ``direct`` mappings.

        :param record: record to convert from a source to a target
        :param from_attr: name of the source attribute or a callable
        :type from_attr: callable | str
        :param to_attr: name of the target attribute
        :type to_attr: str
        """
        if callable(from_attr):
            return from_attr(self, record, to_attr)

        value = record[from_attr]
        if not value:
            return False

        # Backward compatibility: when a field is a relation, and a modifier is
        # not used, we assume that the relation model is a binding.
        # Use an explicit modifier external_to_m2o in the 'direct' mappings to
        # change that.
        field = self.model._fields[to_attr]
        if field.type == 'many2one':
            mapping_func = external_to_m2o(from_attr)
            value = mapping_func(self, record, to_attr)
        return value
Example #2
0
class AddressImportMapper(Component):
    _name = 'prestashop.address.mappper'
    _inherit = 'prestashop.import.mapper'
    _apply_on = 'prestashop.address'

    direct = [
        ('address1', 'street'),
        ('address2', 'street2'),
        ('city', 'city'),
        ('other', 'comment'),
        ('phone', 'phone'),
        ('phone_mobile', 'mobile'),
        ('postcode', 'zip'),
        ('date_add', 'date_add'),
        ('date_upd', 'date_upd'),
        (external_to_m2o('id_customer'), 'prestashop_partner_id'),
    ]

    @mapping
    def backend_id(self, record):
        return {'backend_id': self.backend_record.id}

    @mapping
    def parent_id(self, record):
        binder = self.binder_for('prestashop.res.partner')
        parent = binder.to_internal(record['id_customer'], unwrap=True)
        return {'parent_id': parent.id}

    @mapping
    def name(self, record):
        parts = [record['firstname'], record['lastname']]
        if record['alias']:
            parts.append('(%s)' % record['alias'])
        name = ' '.join(p.strip() for p in parts if p.strip())
        return {'name': name}

    @mapping
    def customer(self, record):
        return {'customer': True}

    @mapping
    def country(self, record):
        if record.get('id_country'):
            binder = self.binder_for('prestashop.res.country')
            country = binder.to_internal(record['id_country'], unwrap=True)
            return {'country_id': country.id}
        return {}

    @mapping
    def company_id(self, record):
        return {'company_id': self.backend_record.company_id.id}

    @only_create
    @mapping
    def type(self, record):
        # do not set 'contact', otherwise the address fields are shared with
        # the parent
        return {'type': 'other'}
Example #3
0
class RancherServiceImportMapper(Component):
    _name = 'rancher.import.mapper.service'
    _inherit = 'rancher.import.mapper'
    _apply_on = 'rancher.service'

    direct = [('name', 'name'),
              ('description', 'description'),
              ('state', 'state'),
              ('scale', 'scale_max'),
              ('healthState', 'state_health'),
              ('scale', 'scale_current'),
              (external_to_m2o('accountId', 'rancher.environment'),
               'environment_id'),
              (external_to_m2o('stackId', 'rancher.stack'),
               'stack_id'),
              ]

    config_serialized = config_serialized
class RancherInstanceImportMapper(Component):
    _name = 'rancher.import.mapper.instance'
    _inherit = 'rancher.import.mapper'
    _apply_on = 'rancher.instance'

    direct = [
        ('name', 'name'),
        ('description', 'description'),
        ('state', 'state'),
        ('healthState', 'state_health'),
        (external_to_m2o('accountId',
                         'rancher.environment'), 'environment_id'),
        (external_to_m2o('hostId', 'rancher.host'), 'host_id'),
    ]

    @mapping
    def service_and_stack_id(self, record):
        if not record.get('serviceIds'):
            return
        service = self.env['rancher.service'].search([
            ('backend_id', '=', self.backend_record.id),
            ('external_id', '=', record['serviceIds'][0])
        ])
        if service:
            return {
                'service_id': service.odoo_id.id,
                'stack_id': service.stack_id.id,
            }

    @mapping
    def mount_ids(self, record):
        binder = self.binder_for('rancher.volume')
        mounts = [(5, 0, 0)]
        for mount in record['mounts'] or []:
            volume = binder.to_internal(mount.volumeId, unwrap=True)
            values = {
                'volume_id': volume.id,
                'path': mount.path,
                'is_read_only': mount.permission == 'ro',
            }
            mounts.append((0, 0, values))
        return {'mount_ids': mounts}
class RancherStackImportMapper(Component):
    _name = 'rancher.import.mapper.stack'
    _inherit = 'rancher.import.mapper'
    _apply_on = 'rancher.stack'

    direct = [
        ('name', 'name'),
        ('description', 'description'),
        ('state', 'state'),
        ('healthState', 'state_health'),
        (external_to_m2o('accountId',
                         'rancher.environment'), 'environment_id'),
    ]
class RancherVolumeImportMapper(Component):
    _name = 'rancher.import.mapper.volume'
    _inherit = 'rancher.import.mapper'
    _apply_on = 'rancher.volume'

    direct = [
        ('name', 'name'),
        ('externalId', 'external_name'),
        ('state', 'state'),
        ('accessMode', 'access_mode'),
        ('driver', 'driver'),
        ('isHostPath', 'is_host_path'),
        ('kind', 'type'),
        ('size_mb', 'capacity'),
        (external_to_m2o('accountId',
                         'rancher.environment'), 'environment_id'),
        (external_to_m2o('hostId', 'rancher.host'), 'host_id'),
    ]

    @mapping
    def capacity_uom_id(self, _):
        mib = self.env.ref('product_uom_technology.product_uom_gib')
        return {'capacity_uom_id': mib.id}
class ProductCategoryMapper(Component):
    _name = 'prestashop.product.category.import.mapper'
    _inherit = 'prestashop.import.mapper'
    _apply_on = 'prestashop.product.category'

    _model_name = 'prestashop.product.category'

    direct = [
        ('description', 'description'),
        ('link_rewrite', 'link_rewrite'),
        ('meta_description', 'meta_description'),
        ('meta_keywords', 'meta_keywords'),
        ('meta_title', 'meta_title'),
        (external_to_m2o('id_shop_default'), 'default_shop_id'),
        ('active', 'active'),
        ('position', 'position')
    ]

    @mapping
    def name(self, record):
        if record['name'] is None:
            return {'name': ''}
        return {'name': record['name']}

#     @mapping
#     def backend_id(self, record):
#         return {'backend_id': self.backend_record.id}

    @mapping
    def parent_id(self, record):
        if record['id_parent'] == '0':
            return {}
        category = self.binder_for('prestashop.product.category').to_internal(
            record['id_parent'], unwrap=True)
        return {
            'parent_id': category.id,
        }

    @mapping
    def data_add(self, record):
        if record['date_add'] == '0000-00-00 00:00:00':
            return {'date_add': datetime.datetime.now()}
        return {'date_add': record['date_add']}

    @mapping
    def data_upd(self, record):
        if record['date_upd'] == '0000-00-00 00:00:00':
            return {'date_upd': datetime.datetime.now()}
        return {'date_upd': record['date_upd']}
Example #8
0
class ShopImportMapper(Component):
    _name = 'prestashop.shop.mapper'
    _inherit = 'prestashop.import.mapper'
    _apply_on = 'prestashop.shop'

    direct = [
        ('name', 'name'),
        (external_to_m2o('id_shop_group'), 'shop_group_id'),
    ]

    @mapping
    def backend_id(self, record):
        return {'backend_id': self.backend_record.id}

    @mapping
    def opener_id(self, record):
        return {'odoo_id': self.backend_record.warehouse_id.id}
class RancherApplicationVersionImportMapper(Component):
    _name = 'rancher.import.mapper.application.version'
    _inherit = 'rancher.import.mapper'
    _apply_on = 'rancher.application.version'

    direct = [('version', 'name'),
              (external_to_m2o('templateId', 'rancher.application'),
               'application_id'),
              ]

    @mapping
    @only_create
    def file_ids(self, record):
        files = []
        for name, data in (record['files'] or {}).items():
            file_values = {
                'datas': base64.b64encode(data.encode('utf-8')),
                'datas_fname': name,
                'name': name,
                'type': 'binary',
                'mimetype': 'text/plain',
            }
            files.append((0, 0, file_values))
        return {'file_ids': files}

    @mapping
    def option_ids(self, record):
        options = [(5, 0, 0)]
        for question in record['questions'] or []:
            option_values = {
                'name': question['variable'],
                'description': question['description'],
                'display_name': question['label'],
                'is_required': question['required'],
                'value_default': question['default'],
            }
            options.append((0, 0, option_values))
        return {'option_ids': options}

    @mapping
    def external_id(self, record):
        return {
            'external_id': 'catalog://%s' % record['id'],
        }
Example #10
0
class TemplateMapper(Component):
    _name = 'prestashop.product.template.mapper'
    _inherit = 'prestashop.import.mapper'
    _apply_on = 'prestashop.product.template'

    direct = [
        ('weight', 'weight'),
        ('wholesale_price', 'wholesale_price'),
        ('wholesale_price', 'standard_price'),
        (external_to_m2o('id_shop_default'), 'default_shop_id'),
        ('link_rewrite', 'link_rewrite'),
        ('reference', 'reference'),
        ('available_for_order', 'available_for_order'),
        ('on_sale', 'on_sale'),
    ]

    def _apply_taxes(self, tax, price):
        if self.backend_record.taxes_included == tax.price_include:
            return price
        factor_tax = tax.price_include and (1 + tax.amount / 100) or 1.0
        if self.backend_record.taxes_included:
            if not tax.price_include:
                return price / factor_tax
        else:
            if tax.price_include:
                return price * factor_tax

    @mapping
    def list_price(self, record):
        price = 0.0
        tax = self._get_tax_ids(record)
        if record['price'] != '':
            price = float(record['price'])
        price = self._apply_taxes(tax, price)
        return {'list_price': price}

    @mapping
    def tags_to_text(self, record):
        associations = record.get('associations', {})
        tags = associations.get('tags', {}).get(
            self.backend_record.get_version_ps_key('tag'), [])
        tag_adapter = self.component(usage='backend.adapter',
                                     model_name='_prestashop_product_tag')
        if not isinstance(tags, list):
            tags = [tags]
        if tags:
            ps_tags = tag_adapter.search(
                filters={
                    'filter[id]': '[%s]' % '|'.join(x['id'] for x in tags),
                    'display': '[name]'
                })
            if ps_tags:
                return {'tags': ','.join(x['name'] for x in ps_tags)}

    @mapping
    def name(self, record):
        if record['name']:
            return {'name': record['name']}
        return {'name': 'noname'}

    @mapping
    def date_add(self, record):
        if record['date_add'] == '0000-00-00 00:00:00':
            return {'date_add': datetime.datetime.now()}
        return {'date_add': record['date_add']}

    @mapping
    def date_upd(self, record):
        if record['date_upd'] == '0000-00-00 00:00:00':
            return {'date_upd': datetime.datetime.now()}
        return {'date_upd': record['date_upd']}

    def has_combinations(self, record):
        associations = record.get('associations', {})
        combinations = associations.get('combinations', {}).get(
            self.backend_record.get_version_ps_key('combinations'))
        return len(combinations or '') != 0

    @only_create
    @mapping
    def odoo_id(self, record):
        """ Will bind the product to an existing one with the same code """
        if self.backend_record.matching_product_template:
            if self.has_combinations(record):
                # Browse combinations for matching products and find if there
                # is a potential template to be matched
                template = self.env['product.template']
                associations = record.get('associations', {})
                combinations = associations.get('combinations', {}).get(
                    self.backend_record.get_version_ps_key('combinations'))
                if len(combinations) == 1:
                    # Defensive mode when product have no combinations, force
                    # the list mode
                    combinations = [combinations]
                for prod in combinations:
                    backend_adapter = self.component(
                        usage='backend.adapter',
                        model_name='prestashop.product.combination')
                    variant = backend_adapter.read(int(prod['id']))
                    code = variant.get(self.backend_record.matching_product_ch)
                    if not code and self.backend_record.matching_product_ch == 'barcode':
                        code = variant.get('ean13')
                    if code:
                        if self.backend_record.matching_product_ch == 'reference':
                            product = self.env['product.product'].search([
                                ('default_code', '=', code)
                            ])
                            if len(product) > 1:
                                raise ValidationError(
                                    _('Error! Multiple products found with '
                                      'combinations reference %s. Maybe consider to '
                                      'update you datas') % code)
                            template |= product.product_tmpl_id
                        if self.backend_record.matching_product_ch == 'barcode':
                            product = self.env['product.product'].search([
                                ('barcode', '=', code)
                            ])
                            if len(product) > 1:
                                raise ValidationError(
                                    _('Error! Multiple products found with '
                                      'combinations reference %s. Maybe consider to '
                                      'update you datas') % code)
                            template |= product.product_tmpl_id
                _logger.debug('template %s' % template)
                if len(template) == 1:
                    return {'odoo_id': template.id}
                if len(template) > 1:
                    raise ValidationError(
                        _('Error! Multiple templates are found with '
                          'combinations reference. Maybe consider to change '
                          'matching option'))
            else:
                code = record.get(self.backend_record.matching_product_ch)
                if not code and self.backend_record.matching_product_ch == 'barcode':
                    code = record.get('ean13')
                if code:
                    if self.backend_record.matching_product_ch == 'reference':
                        if self._template_code_exists(code):
                            product = self.env['product.template'].search(
                                [('default_code', '=', code)], limit=1)
                            if product:
                                return {'odoo_id': product.id}

                    if self.backend_record.matching_product_ch == 'barcode':
                        product = self.env['product.template'].search(
                            [('barcode', '=', code)], limit=1)
                        if product:
                            return {'odoo_id': product.id}
        return {}

    def _template_code_exists(self, code):
        model = self.env['product.template']
        template_ids = model.search([
            ('default_code', '=', code),
            ('company_id', '=', self.backend_record.company_id.id),
        ],
                                    limit=1)
        return len(template_ids) > 0

    @mapping
    def default_code(self, record):
        if self.has_combinations(record):
            return {}
        code = record.get('reference')
        if not code:
            code = "backend_%d_product_%s" % (self.backend_record.id,
                                              record['id'])
        if not self._template_code_exists(code):
            return {'default_code': code}
        i = 1
        current_code = '%s_%d' % (code, i)
        while self._template_code_exists(current_code):
            i += 1
            current_code = '%s_%d' % (code, i)
        return {'default_code': current_code}

    def clear_html_field(self, content):
        html = html2text.HTML2Text()
        html.ignore_images = True
        html.ignore_links = True
        return html.handle(content)

    @staticmethod
    def sanitize_html(content):
        content = BeautifulSoup(content, 'html.parser')
        # Prestashop adds both 'lang="fr-ch"' and 'xml:lang="fr-ch"'
        # but Odoo tries to parse the xml for the translation and fails
        # due to the unknow namespace
        for child in content.find_all(lambda tag: tag.has_attr('xml:lang')):
            del child['xml:lang']
        return content.prettify()

    @mapping
    def descriptions(self, record):
        return {
            'description':
            self.clear_html_field(record.get('description_short', '')),
            'description_html':
            self.sanitize_html(record.get('description', '')),
            'description_short_html':
            self.sanitize_html(record.get('description_short', '')),
        }

    @mapping
    def active(self, record):
        return {'always_available': bool(int(record['active']))}

    @mapping
    def sale_ok(self, record):
        # if this product has combinations, we do not want to sell this
        # product, but its combinations (so sale_ok = False in that case).
        return {'sale_ok': True}

    @mapping
    def purchase_ok(self, record):
        return {'purchase_ok': True}

    @mapping
    def categ_ids(self, record):
        categories = record['associations'].get('categories', {}).get(
            self.backend_record.get_version_ps_key('category'), [])
        if not isinstance(categories, list):
            categories = [categories]
        product_categories = self.env['product.category'].browse()
        binder = self.binder_for('prestashop.product.category')
        for ps_category in categories:
            product_categories |= binder.to_internal(
                ps_category['id'],
                unwrap=True,
            )
        return {'categ_ids': [(6, 0, product_categories.ids)]}

    @mapping
    def default_category_id(self, record):
        if not int(record['id_category_default']):
            return
        binder = self.binder_for('prestashop.product.category')
        category = binder.to_internal(
            record['id_category_default'],
            unwrap=True,
        )
        if category:
            return {'prestashop_default_category_id': category.id}

    @mapping
    def backend_id(self, record):
        return {'backend_id': self.backend_record.id}

    @mapping
    def company_id(self, record):
        return {'company_id': self.backend_record.company_id.id}

    @mapping
    def barcode(self, record):
        if self.has_combinations(record):
            return {}
        barcode = record.get('barcode') or record.get('ean13')
        if barcode in ['', '0']:
            return {}
        if self.env['barcode.nomenclature'].check_ean(barcode):
            return {'barcode': barcode}
        return {}

    def _get_tax_ids(self, record):
        # if record['id_tax_rules_group'] == '0':
        #     return {}
        binder = self.binder_for('prestashop.account.tax.group')
        tax_group = binder.to_internal(
            record['id_tax_rules_group'],
            unwrap=True,
        )
        return tax_group.tax_ids

    # TOREVIEW: Tax rules group is not the same that odoo tax groups
    # @mapping
    # def taxes_id(self, record):
    #     taxes = self._get_tax_ids(record)
    #     return {'taxes_id': [(6, 0, taxes.ids)]}

    @mapping
    def type(self, record):
        # If the product has combinations, this main product is not a real
        # product. So it is set to a 'service' kind of product. Should better
        # be a 'virtual' product... but it does not exist...
        # The same if the product is a virtual one in prestashop.
        if record['type']['value'] and record['type']['value'] == 'virtual':
            return {"type": 'service'}
        return {"type": 'product'}
Example #11
0
        class MyMapper(Component):
            _name = "my.mapper"
            _inherit = "base.import.mapper"
            _apply_on = "res.partner"

            direct = [(external_to_m2o("country"), "country_id")]
Example #12
0
        class MyMapper(Component):
            _name = 'my.mapper'
            _inherit = 'base.import.mapper'
            _apply_on = 'res.partner'

            direct = [(external_to_m2o('country'), 'country_id')]
Example #13
0
class PartnerImportMapper(Component):
    _name = 'prestashop.res.partner.mapper'
    _inherit = 'prestashop.import.mapper'
    _apply_on = 'prestashop.res.partner'

    direct = [
        ('date_add', 'date_add'),
        ('date_upd', 'date_upd'),
        ('email', 'email'),
        ('newsletter', 'newsletter'),
        ('company', 'company'),
        ('active', 'active'),
        ('note', 'comment'),
        (external_to_m2o('id_shop_group'), 'shop_group_id'),
        (external_to_m2o('id_shop'), 'shop_id'),
        (external_to_m2o('id_default_group'), 'default_category_id'),
    ]

    @mapping
    def backend_id(self, record):
        return {'backend_id': self.backend_record.id}

    @mapping
    def pricelist(self, record):
        binder = self.binder_for('prestashop.groups.pricelist')
        pricelist = binder.to_internal(record['id_default_group'], unwrap=True)
        if not pricelist:
            return {}
        return {'property_product_pricelist': pricelist.id}

    @mapping
    def birthday(self, record):
        if record['birthday'] in ['0000-00-00', '']:
            return {}
        return {'birthday': record['birthday']}

    @mapping
    def name(self, record):
        parts = [record['firstname'], record['lastname']]
        name = ' '.join(p.strip() for p in parts if p.strip())
        return {'name': name}

    @mapping
    def groups(self, record):
        groups = record.get('associations', {}).get('groups', {}).get(
            self.backend_record.get_version_ps_key('group'), [])
        if not isinstance(groups, list):
            groups = [groups]
        model_name = 'prestashop.res.partner.category'
        partner_category_bindings = self.env[model_name].browse()
        binder = self.binder_for(model_name)
        for group in groups:
            partner_category_bindings |= binder.to_internal(group['id'])

        result = {
            'group_ids': [(6, 0, partner_category_bindings.ids)],
            'category_id':
            [(4, b.odoo_id.id) for b in partner_category_bindings]
        }
        return result

    @mapping
    def lang(self, record):
        binder = self.binder_for('prestashop.res.lang')
        erp_lang = None
        if record.get('id_lang'):
            erp_lang = binder.to_internal(record['id_lang'])
        if not erp_lang:
            erp_lang = self.env.ref('base.lang_en')
        return {'lang': erp_lang.code}

    @mapping
    def customer(self, record):
        return {'customer': True}

    @mapping
    def is_company(self, record):
        # This is sad because we _have_ to have a company partner if we want to
        # store multiple adresses... but... well... we have customers who want
        # to be billed at home and be delivered at work... (...)...
        return {'is_company': True}

    @mapping
    def company_id(self, record):
        return {'company_id': self.backend_record.company_id.id}

    @mapping
    def backend_id(self, record):
        return {'backend_id': self.backend_record.id}
Example #14
0
class RancherHostImportMapper(Component):
    _name = 'rancher.import.mapper.host'
    _inherit = 'rancher.import.mapper'
    _apply_on = 'rancher.host'

    direct = [
        ('hostname', 'name'),
        ('description', 'description'),
        ('state', 'state'),
        (external_to_m2o('accountId',
                         'rancher.environment'), 'environment_id'),
    ]

    @mapping
    def cpu_metric_id(self, record):
        cpu_info = record['info'].cpuInfo
        mhz = self.env.ref('product_uom_technology.product_uom_mhz')
        metric = self.env['infrastructure.metric.cpu'].create({
            'name':
            cpu_info.modelName,
            'load_one':
            cpu_info.loadAvg[0],
            'load_five':
            cpu_info.loadAvg[1],
            'load_fifteen':
            cpu_info.loadAvg[2],
            'core_count':
            cpu_info.count,
            'frequency':
            cpu_info.mhz,
            'frequency_uom_id':
            mhz.id,
            'core_metric_ids': [(0, 0, {
                'percent_use': p
            }) for p in cpu_info.cpuCoresPercentages],
        })
        return {'cpu_metric_id': metric.id}

    @mapping
    def memory_metric_id(self, record):
        memory_info = record['info'].memoryInfo
        mib = self.env.ref('product_uom_technology.product_uom_mib')
        metric = self.env['infrastructure.metric.memory'].create({
            'memory_free':
            memory_info.memFree,
            'memory_cache':
            memory_info.cached,
            'memory_buffer':
            memory_info.buffers,
            'memory_total':
            memory_info.memTotal,
            'memory_available':
            memory_info.memAvailable,
            'memory_used':
            memory_info.memTotal - memory_info.memFree,
            'swap_cache':
            memory_info.swapCached,
            'swap_free':
            memory_info.swapfree,
            'swap_total':
            memory_info.swaptotal,
            'uom_id':
            mib.id,
        })
        return {'memory_metric_id': metric.id}

    @mapping
    def operating_system_id(self, record):
        regex = re.compile(r'(?P<name>.+?) (?P<version>\d+\.\d+.*)')
        matches = regex.search(record['info'].osInfo.operatingSystem)
        software = self.env['infrastructure.software.version'].get_or_create(
            name=matches.group('name').strip(),
            version=matches.group('version').strip(),
            type='os',
        )
        return {'operating_system_id': software.id}

    @mapping
    def kernel_id(self, record):
        software = self.env['infrastructure.software.version'].get_or_create(
            name='Linux',
            version=record['info'].osInfo.kernelVersion,
            type='kernel',
        )
        return {'kernel_id': software.id}

    @mapping
    def virtualization_id(self, record):
        regex = re.compile(
            r'(?P<name>.+?) (v(ersion)? ?)?(?P<version>\d+\.\d+.*)', )
        matches = regex.search(record['info'].osInfo.dockerVersion)
        software = self.env['infrastructure.software.version'].get_or_create(
            name=matches.group('name').strip(),
            version=matches.group('version').strip(),
            type='virtualization',
        )
        return {'virtualization_id': software.id}

    @mapping
    def label_ids(self, record):
        labels = self.env['infrastructure.option']
        for name, value in record['labels'].items():
            labels += labels.get_or_create(name, value)
        return {'label_ids': [(6, 0, labels.ids)]}