def test_0040_import_configurable_product(self): """Test the import of a configurable product using magento data """ category_obj = POOL.get('product.category') product_obj = POOL.get('product.product') website_obj = POOL.get('magento.instance.website') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_instance': self.instance_id1, 'magento_website': self.website_id1, }) website = website_obj.browse( txn.cursor, txn.user, self.website_id1, txn.context ) if settings.MOCK: category_data = load_json('categories', '17') else: with magento.Category(*settings.ARGS) as category_api: category_tree = category_api.tree( website.magento_root_category_id ) category_data = category_api.info( category_tree['children'][0]['category_id'] ) category_obj.create_using_magento_data( txn.cursor, txn.user, category_data, context=context ) magento_store_id = website.stores[0].store_views[0].magento_id if settings.MOCK: product_data = load_json('products', '135') else: with magento.Product(*settings.ARGS) as product_api: product_list = product_api.list( store_view=magento_store_id ) for product in product_list: if product['type'] == 'configurable': product_data = product_api.info( product=product['product_id'], store_view=magento_store_id ) break product = product_obj.find_or_create_using_magento_data( txn.cursor, txn.user, product_data, context ) self.assertTrue( str(product.categ_id.magento_ids[0].magento_id) in product_data['categories'] ) self.assertEqual( product.magento_product_type, product_data['type'] )
def import_product(self, sku): """ Import specific product for this magento channel Downstream implementation for channel.import_product """ Product = Pool().get('product.product') if self.source != 'magento': return super(Channel, self).import_product(sku) product = Product.find_using_magento_sku(sku) if not product: # if product is not found get the info from magento and # delegate to create_using_magento_data with magento.Product( self.magento_url, self.magento_api_user, self.magento_api_key ) as product_api: product_data = product_api.info(sku) product = Product.create_using_magento_data(product_data) return product
def test_0070_import_downloadable_product(self): """Test the import of a downloadable product using magento data """ product_obj = POOL.get('product.product') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_instance': self.instance_id1, 'magento_website': self.website_id1, }) if settings.MOCK: product_data = load_json('products', '170') else: with magento.Product(*settings.ARGS) as product_api: product_list = product_api.list() for product in product_list: if product['type'] == 'downloadable': product_data = product_api.info( product=product['product_id'], ) break product = product_obj.find_or_create_using_magento_data( txn.cursor, txn.user, product_data, context ) self.assertEqual( product.magento_product_type, product_data['type'] ) self.assertEqual( product.categ_id.name, 'Unclassified Magento Products' )
def find_or_create_using_magento_id(cls, magento_id): """ Find or create a product template using magento ID. This method looks for an existing template using the magento ID provided. If found, it returns the template found, else creates a new one and returns that :param magento_id: Product ID from Magento :returns: Active record of Product Created """ Website = Pool().get('magento.instance.website') product_template = cls.find_using_magento_id(magento_id) if not product_template: # if product is not found get the info from magento and # delegate to create_using_magento_data website = Website(Transaction().context.get('magento_website')) instance = website.instance with magento.Product( instance.url, instance.api_user, instance.api_key ) as product_api: product_data = product_api.info(magento_id) product_template = cls.create_using_magento_data(product_data) return product_template
def find_or_create_using_magento_id(self, cursor, user, magento_id, context): """ Find or create product using magento_id :param cursor: Database cursor :param user: ID of current user :param magento_id: Product ID from magento :param context: Application context :returns: Browse record of product found/created """ website_obj = self.pool.get('magento.instance.website') product = self.find_using_magento_id(cursor, user, magento_id, context) if not product: # If product is not found, get the info from magento and delegate # to create_using_magento_data website = website_obj.browse(cursor, user, context['magento_website'], context=context) instance = website.instance with magento.Product(instance.url, instance.api_user, instance.api_key) as product_api: product_data = product_api.info(magento_id) product = self.create_using_magento_data(cursor, user, product_data, context) return product
def update_from_magento(self, cursor, user, product, context=None): """Update product using magento ID for that product :param cursor: Database cursor :param user: ID of current user :param product: Browse record of product to be updated :param context: Application context :returns: Browse record of product updated """ website_obj = self.pool.get('magento.instance.website') magento_product_obj = self.pool.get('magento.website.product') website = website_obj.browse(cursor, user, context['magento_website'], context=context) instance = website.instance with magento.Product(instance.url, instance.api_user, instance.api_key) as product_api: magento_product_id, = magento_product_obj.search( cursor, user, [ ('product', '=', product.id), ('website', '=', website.id), ], context=context) magento_product = magento_product_obj.browse(cursor, user, magento_product_id, context=context) product_data = product_api.info(magento_product.magento_id) return self.update_from_magento_using_data(cursor, user, product, product_data, context)
def update_from_magento(self): """ Update product using magento ID for that product :returns: Active record of product updated """ Channel = Pool().get('sale.channel') SaleChannelListing = Pool().get('product.product.channel_listing') channel = Channel.get_current_magento_channel() with magento.Product( channel.magento_url, channel.magento_api_user, channel.magento_api_key ) as product_api: channel_listing, = SaleChannelListing.search([ ('product', '=', self.id), ('channel', '=', channel.id), ]) product_data = product_api.info( channel_listing.product_identifier, identifierType="productID" ) return self.update_from_magento_using_data(product_data)
def updateProduct(sku, data): """ Atualiza um produto existente no Magento """ item = None with magento.Product(api.url, api.user, api.passwd) as productApi: item = productApi.update(product=sku, data=data, identifierType="sku") return item
def productInfo(sku): """ Tras as informações do produto pelo sku """ with magento.Product(api.url, api.user, api.passwd) as productApi: product = productApi.info(product=sku, identifierType='sku') return product
def export_to_magento(self, category): """Export the current product to the magento category corresponding to the given `category` under the current website in context :param category: Active record of category to which the product has to be exported :return: Active record of product """ Website = Pool().get('magento.instance.website') WebsiteProductTemplate = Pool().get('magento.website.template') if not category.magento_ids: self.raise_user_error( 'invalid_category', (category.complete_name,) ) if self.magento_ids: self.raise_user_error( 'invalid_product', (self.name,) ) if not self.products[0].code: self.raise_user_error( 'missing_product_code', (self.name,) ) website = Website(Transaction().context['magento_website']) instance = website.instance with magento.Product( instance.url, instance.api_user, instance.api_key ) as product_api: # We create only simple products on magento with the default # attribute set # TODO: We have to call the method from core API extension # because the method for catalog create from core API does not seem # to work. This should ideally be from core API rather than # extension magento_id = product_api.call( 'ol_catalog_product.create', [ 'simple', int(Transaction().context['magento_attribute_set']), self.products[0].code, self.get_product_values_for_export_to_magento( [category], [website] ) ] ) WebsiteProductTemplate.create([{ 'magento_id': magento_id, 'website': website.id, 'template': self.id, }]) self.write([self], { 'magento_product_type': 'simple' }) return self
def createProduct(sku, ptype, attrSet, product): """ Cadastra um novo produto no Magento """ with magento.Product(api.url, api.user, api.passwd) as productApi: new_item = productApi.create(product_type=ptype, attribute_set_id=attrSet, sku=sku, data=product) return new_item
def export_to_magento(self, category): """Export the current product to the magento category corresponding to the given `category` under the current magento_channel in context :param category: Active record of category to which the product has to be exported :return: Active record of product """ Channel = Pool().get('sale.channel') SaleChannelListing = Pool().get('product.product.channel_listing') channel = Channel.get_current_magento_channel() if not category.magento_ids: self.raise_user_error('invalid_category', (category.complete_name, )) listing = SaleChannelListing.search([ ('channel', '=', channel.id), ('product', '=', self.id), ]) if listing: self.raise_user_error('invalid_product', (self.name, )) if not self.products[0].code: self.raise_user_error('missing_product_code', (self.name, )) with magento.Product(channel.magento_url, channel.magento_api_user, channel.magento_api_key) as product_api: # We create only simple products on magento with the default # attribute set # TODO: We have to call the method from core API extension # because the method for catalog create from core API does not seem # to work. This should ideally be from core API rather than # extension magento_id = product_api.call('ol_catalog_product.create', [ 'simple', int(Transaction().context['magento_attribute_set']), self.products[0].code, self.get_product_values_for_export_to_magento([category], [channel]) ]) SaleChannelListing.create([{ 'product_identifier': str(magento_id), 'channel': channel.id, 'product': self.id, 'magento_product_type': 'simple', }]) return self
def import_product(self, sku, product_data=None): """ Import specific product for this magento channel Downstream implementation for channel.import_product """ Product = Pool().get('product.product') Listing = Pool().get('product.product.channel_listing') if self.source != 'magento': return super(Channel, self).import_product(sku, product_data) if not sku: # SKU is required can not continue return # Sanitize SKU sku = sku.strip() products = Product.search([ ('code', '=', sku), ]) listings = Listing.search([('product.code', '=', sku), ('channel', '=', self)]) if not products or not listings: # Either way we need the product data from magento. Make that # dreaded API call. with magento.Product(self.magento_url, self.magento_api_user, self.magento_api_key) as product_api: product_data = product_api.info(sku, identifierType="sku") # XXX: sanitize product_data, sometimes product sku may # contain trailing spaces product_data['sku'] = product_data['sku'].strip() # Create a product since there is no match for an existing # product with the SKU. if not products: product = Product.create_from(self, product_data) else: product, = products if not listings: Listing.create_from(self, product_data) else: product = products[0] return product
def test_0030_import_product_wo_categories(self): """Test the import of a product using magento data which does not have any categories associated """ product_obj = POOL.get('product.product') website_obj = POOL.get('magento.instance.website') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_instance': self.instance_id1, 'magento_website': self.website_id1, }) website = website_obj.browse( txn.cursor, txn.user, self.website_id1, txn.context ) store_view_magento_id = website.stores[0].store_views[0].magento_id if settings.MOCK: product_data = load_json('products', '17-wo-category') else: with magento.Product(*settings.ARGS) as product_api: product_list = product_api.list( store_view=store_view_magento_id ) for product in product_list: if not product.get('category_ids'): product_data = product_api.info( product=product['product_id'], store_view=store_view_magento_id ) break product = product_obj.find_or_create_using_magento_data( txn.cursor, txn.user, product_data, context ) self.assertEqual( product.magento_product_type, product_data['type'] ) self.assertEqual(product.name, product_data['name']) self.assertEqual( product.categ_id.name, 'Unclassified Magento Products' )
def updateProductList(products): """ Atualiza os produtos no Site a partir de uma lista de produtos """ items = [] erros = [] with magento.Product(api.url, api.user, api.passwd) as productApi: for p in products: try: item = productApi.update(product=p['sku'], data=p['data'], identifierType="sku") items.append(item) except Exception as e: erro = {'item': p['sku'], 'erro': str(e)} erros.append(erro) return items, erros
def productList(filtro=None): """ Tras um lista com todos os produtos do site e se algum filtro for passado tras a lista de acordo com as especificações do filtro. Exemplo Filtro ---------------- filtro = { 'special_to_date': { 'gteq': '2018-07-24' } } produto = productList(filtro=filtro) """ with magento.Product(api.url, api.user, api.passwd) as productApi: products = productApi.list(filters=filtro, store_view=1) return products
def import_products(self, website): """ Imports products for the current instance :param website: Active record of website """ Product = Pool().get('product.template') instance = website.instance Transaction().set_context({ 'magento_instance': instance.id, 'magento_website': website.id }) with magento.Product( instance.url, instance.api_user, instance.api_key ) as product_api: magento_products = [] products = [] # Products are linked to websites. But the magento api filters # the products based on store views. The products available on # website are always available on all of its store views. # So we get one store view for each website in current instance. magento_products.extend( product_api.list( store_view=website.stores[0].store_views[0].magento_id ) ) for magento_product in magento_products: products.append( Product.find_or_create_using_magento_id( magento_product['product_id'] ) ) return map(int, products)
def import_products(self): """ Import products for this magento channel Downstream implementation for channel.import_products """ if self.source != 'magento': return super(Channel, self).import_products() self.import_category_tree() with Transaction().set_context({'current_channel': self.id}): with magento.Product(self.magento_url, self.magento_api_user, self.magento_api_key) as product_api: # TODO: Implement pagination and import each product as async # task magento_products = product_api.list() products = [] for magento_product in magento_products: products.append(self.import_product( magento_product['sku'])) return products
def update_from_magento(self): """ Update product using magento ID for that product :returns: Active record of product updated """ Website = Pool().get('magento.instance.website') MagentoProductTemplate = Pool().get('magento.website.template') website = Website(Transaction().context.get('magento_website')) instance = website.instance with magento.Product( instance.url, instance.api_user, instance.api_key ) as product_api: magento_product_template, = MagentoProductTemplate.search([ ('template', '=', self.id), ('website', '=', website.id), ]) product_data = product_api.info( magento_product_template.magento_id ) return self.update_from_magento_using_data(product_data)
def export_to_magento(self, cursor, user, product, category, context): """Export the given `product` to the magento category corresponding to the given `category` under the current website in context :param cursor: Database cursor :param user: ID of current user :param product: Browserecord of product to be exported :param category: Browserecord of category to which the product has to be exported :param context: Application context :return: Browserecord of product """ website_obj = self.pool.get('magento.instance.website') website_product_obj = self.pool.get('magento.website.product') if not product.default_code: raise osv.except_osv( _('Invalid Product!'), _('Product %s has a missing code.') % product.name, ) website = website_obj.browse(cursor, user, context['magento_website'], context=context) instance = website.instance with magento.Product(instance.url, instance.api_user, instance.api_key) as product_api: web_product_ids = website_product_obj.search( cursor, user, [('product', '=', product.id), ('website', '=', context['magento_website'])]) if web_product_ids: magento_id = website_product_obj.browse( cursor, user, web_product_ids[0]).magento_id product_api.call('ol_catalog_product.update', [ magento_id, self.get_product_values_for_export_to_magento( product, [category], [website], context) ]) else: magento_id = product_api.call('ol_catalog_product.create', [ 'simple', int(context['magento_attribute_set']), product.default_code, self.get_product_values_for_export_to_magento( product, [category], [website], context) ]) web_magento_ids = website_product_obj.search( cursor, user, [('magento_id', '=', magento_id), ('website', '=', context['magento_website'])]) if not web_magento_ids: website_product_obj.create( cursor, user, { 'magento_id': magento_id, 'website': context['magento_website'], 'product': product.id, }, context=context) self.write(cursor, user, product.id, {'magento_product_type': 'simple'}, context=context) return product
def export_to_magento(self, cursor, user, product, category, context): """Export the given `product` to the magento category corresponding to the given `category` under the current website in context :param cursor: Database cursor :param user: ID of current user :param product: Browserecord of product to be exported :param category: Browserecord of category to which the product has to be exported :param context: Application context :return: Browserecord of product """ website_obj = self.pool.get('magento.instance.website') website_product_obj = self.pool.get('magento.website.product') if not category.magento_ids: raise osv.except_osv( _('Invalid Category!'), _('Category %s must have a magento category associated') % category.complete_name, ) if product.magento_ids: raise osv.except_osv( _('Invalid Product!'), _('Product %s already has a magento product associated') % product.name, ) if not product.default_code: raise osv.except_osv( _('Invalid Product!'), _('Product %s has a missing code.') % product.name, ) website = website_obj.browse(cursor, user, context['magento_website'], context=context) instance = website.instance with magento.Product(instance.url, instance.api_user, instance.api_key) as product_api: # We create only simple products on magento with the default # attribute set # TODO: We have to call the method from core API extension # because the method for catalog create from core API does not seem # to work. This should ideally be from core API rather than # extension magento_id = product_api.call('ol_catalog_product.create', [ 'simple', int(context['magento_attribute_set']), product.default_code, self.get_product_values_for_export_to_magento( product, [category], [website], context) ]) website_product_obj.create( cursor, user, { 'magento_id': magento_id, 'website': context['magento_website'], 'product': product.id, }, context=context) self.write(cursor, user, product.id, {'magento_product_type': 'simple'}, context=context) return product
def test_0103_update_product_using_magento_id(self): """Check if the product gets updated """ product_obj = POOL.get('product.product') category_obj = POOL.get('product.category') website_obj = POOL.get('magento.instance.website') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_instance': self.instance_id1, 'magento_website': self.website_id1, 'magento_store': self.store_id, }) website = website_obj.browse( txn.cursor, txn.user, self.website_id1, txn.context ) if settings.MOCK: category_data = load_json('categories', '17') else: with magento.Category(*settings.ARGS) as category_api: category_tree = category_api.tree( website.magento_root_category_id ) category_data = category_api.info( category_tree['children'][0]['category_id'] ) category_obj.create_using_magento_data( txn.cursor, txn.user, category_data, context=context ) if settings.MOCK: product_data = load_json('products', '135001') else: with magento.Product(*settings.ARGS) as product_api: product_list = product_api.list() product_data = product_api.info( product=product_list[0]['product_id'], ) product = product_obj.find_or_create_using_magento_data( txn.cursor, txn.user, product_data, context ) product_before_updation = product_obj.read( txn.cursor, txn.user, product.id, [], context=txn.context ) if settings.MOCK: with patch('magento.Product', mock_product_api(), create=True): product = product_obj.update_from_magento( txn.cursor, txn.user, product, context ) else: product_data['name'] = 'Updated-product' product_data['default_code'] = 'Updated-sku' product_data['description'] = 'Updated-description' product = product_obj.update_from_magento( txn.cursor, txn.user, product, context ) product_after_updation = product_obj.read( txn.cursor, txn.user, product.id, [], context=txn.context ) self.assertEqual( product_before_updation['id'], product_after_updation['id'] ) self.assertNotEqual( product_before_updation['name'], product_after_updation['name'] ) self.assertNotEqual( product_before_updation['default_code'], product_after_updation['default_code'] ) self.assertNotEqual( product_before_updation['description'], product_after_updation['description'] )
def test_0090_tier_prices(self): """Checks the function field on product price tiers """ product_obj = POOL.get('product.product') store_obj = POOL.get('magento.website.store') category_obj = POOL.get('product.category') pricelist_item_obj = POOL.get('product.pricelist.item') product_price_tier = POOL.get('product.price_tier') website_obj = POOL.get('magento.instance.website') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_instance': self.instance_id1, 'magento_website': self.website_id1, 'magento_store': self.store_id, }) store = store_obj.browse( txn.cursor, txn.user, self.store_id, context=context ) website = website_obj.browse( txn.cursor, txn.user, self.website_id1, txn.context ) if settings.MOCK: category_data = load_json('categories', '17') else: with magento.Category(*settings.ARGS) as category_api: category_tree = category_api.tree( website.magento_root_category_id ) category_data = category_api.info( category_tree['children'][0]['category_id'] ) category_obj.create_using_magento_data( txn.cursor, txn.user, category_data, context=context ) magento_store_id = website.stores[0].store_views[0].magento_id if settings.MOCK: product_data = load_json('products', '135') else: with magento.Product(*settings.ARGS) as product_api: product_list = product_api.list( store_view=magento_store_id ) product_data = product_api.info( product=product_list[0]['product_id'], store_view=magento_store_id ) product = product_obj.find_or_create_using_magento_data( txn.cursor, txn.user, product_data, context ) pricelist_item_obj.create(txn.cursor, txn.user, { 'name': 'Test line', 'price_version_id': store.shop.pricelist_id.version_id[0].id, 'product_id': product.id, 'min_quantity': 10, 'base': 1, 'price_surcharge': -5, }, context=context) tier_id = product_price_tier.create(txn.cursor, txn.user, { 'product': product.id, 'quantity': 10, }, context) tier = product_price_tier.browse( txn.cursor, txn.user, tier_id, context ) self.assertEqual(product.lst_price - 5, tier.price)
def test_0080_export_product_stock_information(self): """ This test checks if the method to call for updation of product stock info does not break anywhere in between. This method does not check the API calls """ product_obj = POOL.get('product.product') website_obj = POOL.get('magento.instance.website') category_obj = POOL.get('product.category') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_instance': self.instance_id1, 'magento_website': self.website_id1, }) website = website_obj.browse( txn.cursor, txn.user, self.website_id1, txn.context ) if settings.MOCK: category_data = load_json('categories', '17') else: with magento.Category(*settings.ARGS) as category_api: category_tree = category_api.tree( website.magento_root_category_id ) category_data = category_api.info( category_tree['children'][0]['category_id'] ) category_obj.create_using_magento_data( txn.cursor, txn.user, category_data, context=context ) magento_store_id = website.stores[0].store_views[0].magento_id if settings.MOCK: product_data = load_json('products', '135') else: with magento.Product(*settings.ARGS) as product_api: product_list = product_api.list( store_view=magento_store_id ) product_data = product_api.info( product=product_list[0]['product_id'], store_view=magento_store_id ) product_obj.find_or_create_using_magento_data( txn.cursor, txn.user, product_data, context ) website = website_obj.browse( txn.cursor, txn.user, self.website_id1, context ) with patch( 'magento.Inventory', mock_inventory_api(), create=True ): website_obj.export_inventory_to_magento( txn.cursor, txn.user, website, context )
def test_0020_import_simple_product(self): """Test the import of simple product using magento data """ category_obj = POOL.get('product.category') product_obj = POOL.get('product.product') magento_product_obj = POOL.get('magento.website.product') website_obj = POOL.get('magento.instance.website') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_instance': self.instance_id1, 'magento_website': self.website_id1, }) website = website_obj.browse( txn.cursor, txn.user, self.website_id1, txn.context ) if settings.MOCK: category_data = load_json('categories', '8') else: with magento.Category(*settings.ARGS) as category_api: category_tree = category_api.tree( website.magento_root_category_id ) category_data = category_api.info( category_tree['children'][0]['category_id'] ) category_obj.create_using_magento_data( txn.cursor, txn.user, category_data, context=context ) products_before_import = product_obj.search( txn.cursor, txn.user, [], context=context, count=True ) magento_store_id = website.stores[0].store_views[0].magento_id if settings.MOCK: product_data = load_json('products', '17') else: with magento.Product(*settings.ARGS) as product_api: product_list = product_api.list( store_view=magento_store_id ) for product in product_list: if product['type'] == 'simple': product_data = product_api.info( product=product['product_id'], ) break product = product_obj.find_or_create_using_magento_data( txn.cursor, txn.user, product_data, context ) self.assertTrue( str(product.categ_id.magento_ids[0].magento_id) in product_data['categories'] ) self.assertEqual( product.magento_product_type, product_data['type'] ) self.assertEqual(product.name, product_data['name']) products_after_import = product_obj.search( txn.cursor, txn.user, [], context=context, count=True ) self.assertTrue(products_after_import > products_before_import) self.assertEqual( product, product_obj.find_using_magento_data( txn.cursor, txn.user, product_data, context ) ) # Make sure the categs created only in website1 and not in # website2 self.assertTrue( magento_product_obj.search(txn.cursor, txn.user, [ ('website', '=', self.website_id1) ], count=True) > 0 ) self.assertTrue( magento_product_obj.search(txn.cursor, txn.user, [ ('website', '=', self.website_id2) ], count=True) == 0 )