class AddressImportMapper(ImportMapper): _model_name = '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'), (backend_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_odoo(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_odoo(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'}
class ProductCategoryMapper(ImportMapper): _model_name = 'prestashop.product.category' direct = [('position', 'sequence'), ('description', 'description'), ('link_rewrite', 'link_rewrite'), ('meta_description', 'meta_description'), ('meta_keywords', 'meta_keywords'), ('meta_title', 'meta_title'), (backend_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_odoo( 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']}
class ShopImportMapper(ImportMapper): _model_name = 'prestashop.shop' direct = [ ('name', 'name'), (backend_to_m2o('id_shop_group'), 'shop_group_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 warehouse_id(self, record): return {'warehouse_id': self.backend_record.warehouse_id.id} @mapping def opener_id(self, record): return {'odoo_id': self.backend_record.warehouse_id.id}
class MyMapper(ImportMapper): _model_name = 'res.partner' direct = [(backend_to_m2o('country'), 'country_id')]
class PartnerImportMapper(ImportMapper): _model_name = 'prestashop.res.partner' direct = [ ('date_add', 'date_add'), ('date_upd', 'date_upd'), ('email', 'email'), ('newsletter', 'newsletter'), ('company', 'company'), ('active', 'active'), ('note', 'comment'), (backend_to_m2o('id_shop_group'), 'shop_group_id'), (backend_to_m2o('id_shop'), 'shop_id'), (backend_to_m2o('id_default_group'), 'default_category_id'), ] @mapping def pricelist(self, record): binder = self.binder_for('prestashop.groups.pricelist') pricelist = binder.to_odoo(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_odoo(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 backend_id(self, record): return {'backend_id': self.backend_record.id} @mapping def lang(self, record): binder = self.binder_for('prestashop.res.lang') erp_lang = None if record.get('id_lang'): erp_lang = binder.to_odoo(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}
class TemplateMapper(ImportMapper): _model_name = 'prestashop.product.template' direct = [ ('weight', 'weight'), ('wholesale_price', 'wholesale_price'), ('wholesale_price', 'standard_price'), (backend_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.unit_for(GenericAdapter, '_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 """ product = self.env['product.template'].search( [('default_code', '=', record['reference'])], limit=1) if product: return {'odoo_id': product.id} def _template_code_exists(self, code): model = self.session.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_odoo( 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_odoo( 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_odoo( record['id_tax_rules_group'], unwrap=True, ) return tax_group.tax_ids @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'} @mapping def extras_features(self, record): mapper = self.unit_for(FeaturesProductImportMapper) return mapper.map_record(record).values(**self.options) @mapping def extras_manufacturer(self, record): mapper = self.unit_for(ManufacturerProductImportMapper) return mapper.map_record(record).values(**self.options)