def find_or_create_using_magento_increment_id(cls, order_increment_id): """ This method tries to find the sale with the order increment ID first and if not found it will fetch the info from magento and create a new sale with the data from magento using create_using_magento_data :param order_increment_id: Order increment ID from magento :type order_increment_id: string :returns: Active record of sale order created/found """ Channel = Pool().get('sale.channel') channel = Channel.get_current_magento_channel() sale = cls.find_using_magento_increment_id(order_increment_id) if not sale: with magento.Order(channel.magento_url, channel.magento_api_user, channel.magento_api_key) as order_api: order_data = order_api.info(order_increment_id) sale = cls.create_using_magento_data(order_data) return sale
def export_order_status_to_magento(self): """ Export order status to magento. :return: Active record of sale """ if not self.magento_id: return self channel = self.channel channel.validate_magento_channel() increment_id = self.reference.split(channel.magento_order_prefix)[1] # This try except is placed because magento might not accept this # order status change due to its workflow constraints. # TODO: Find a better way to do it try: with magento.Order(channel.magento_url, channel.magento_api_user, channel.magento_api_key) as order_api: if self.state == 'cancel': order_api.cancel(increment_id) elif self.state == 'done': # TODO: update shipping and invoice order_api.addcomment(increment_id, 'complete') except xmlrpclib.Fault, exception: if exception.faultCode == 103: return self
def export_order_status_to_magento(self, cursor, user, sale, context): """ Export order status to magento. :param cursor: Database cursor :param user: ID of current user :param sale: Browse record of sale :param context: Application context :return: Browse record of sale """ if not sale.magento_id: return sale instance = sale.magento_instance if sale.state == 'cancel': increment_id = sale.name.split(instance.order_prefix)[1] # This try except is placed because magento might not accept this # order status change due to its workflow constraints. # TODO: Find a better way to do it try: with magento.Order(instance.url, instance.api_user, instance.api_key) as order_api: order_api.cancel(increment_id) except xmlrpclib.Fault, f: if f.faultCode == 103: return sale
def update_order_status(self): "Downstream implementation of order_status update" Sale = Pool().get('sale.sale') if self.source != 'magento': return super(Channel, self).update_order_status() sales = Sale.search([ ('channel', '=', self.id), ('state', 'in', ('confirmed', 'processing')), ]) order_ids = [sale.reference for sale in sales] for order_ids_batch in batch(order_ids, 50): with magento.Order(self.magento_url, self.magento_api_user, self.magento_api_key) as order_api: orders_data = order_api.info_multi(order_ids_batch) for i, order_data in enumerate(orders_data): if order_data.get('isFault'): if order_data['faultCode'] == '100': # 100: Requested order not exists. # TODO: Remove order from channel or add some # exception. pass logger.warning( "Order %s: %s %s" % (order_ids_batch[i], order_data['faultCode'], order_data['faultMessage'])) continue sale, = Sale.search([('reference', '=', order_data['increment_id'])]) sale.update_order_status_from_magento(order_data=order_data)
def find_or_create_using_magento_increment_id(self, cursor, user, order_increment_id, context): """ Finds or create sale order using magento ID :param cursor: Database cursor :param user: ID of current user :param order_increment_id: Order increment ID from magento :type order_increment_id: string :param context: Application context :returns: Browse record of sale order created/found """ instance_obj = self.pool.get('magento.instance') sale = self.find_using_magento_increment_id(cursor, user, order_increment_id, context) if not sale: instance = instance_obj.browse(cursor, user, context['magento_instance'], context=context) with magento.Order(instance.url, instance.api_user, instance.api_key) as order_api: order_data = order_api.info(order_increment_id) sale = self.create_using_magento_data(cursor, user, order_data, context) return sale
def update_order_status_from_magento(self): """Update order status from magento. :TODO: this only handles complete orders of magento. Should handle other states too? """ Shipment = Pool().get('stock.shipment.out') with magento.Order(self.channel.magento_url, self.channel.magento_api_user, self.channel.magento_api_key) as order_api: order_data = order_api.info(self.reference) if order_data['status'] == 'complete': # Order is completed on magento, process shipments and # invoices. for shipment in self.shipments: if shipment.state == 'draft': Shipment.wait([shipment]) if shipment.state == 'waiting': Shipment.assign([shipment]) if shipment.state == 'assigned': Shipment.pack([shipment]) if shipment.state == 'packed': Shipment.done([shipment])
def test0010_create_partner(self): """ Tests if customers imported from magento is created as partners in openerp """ partner_obj = POOL.get('res.partner') magento_partner_obj = POOL.get('magento.website.partner') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_website': self.website_id1, 'magento_store_view': self.store_view_id, }) if settings.MOCK: customer_data = load_json('customers', '1') else: with magento.Order(*settings.ARGS) as order_api: orders = order_api.list() order_data = order_api.info(orders[0]['increment_id']) with magento.Customer(*settings.ARGS) as customer_api: if order_data.get('customer_id'): customer_data = customer_api.info( order_data['customer_id'] ) else: customer_data = { 'firstname': order_data['customer_firstname'], 'lastname': order_data['customer_lastname'], 'email': order_data['customer_email'], 'magento_id': 0 } partners_before_import = magento_partner_obj.search( txn.cursor, txn.user, [], context=context ) # Create partner partner = partner_obj.find_or_create( txn.cursor, txn.user, customer_data, context ) self.assert_(partner) self.assertTrue( partner_obj.search( txn.cursor, txn.user, [ ('email', '=', customer_data['email']) ], context=context ) ) partners_after_import = magento_partner_obj.search( txn.cursor, txn.user, [], context=context ) self.assertTrue(partners_after_import > partners_before_import)
def import_orders(self): """ Downstream implementation of channel.import_orders :return: List of active record of sale imported """ if self.source != 'magento': return super(Channel, self).import_orders() new_sales = [] with Transaction().set_context({'current_channel': self.id}): order_states = self.get_order_states_to_import() order_states_to_import_in = map(lambda state: state.code, order_states) with magento.Order(self.magento_url, self.magento_api_user, self.magento_api_key) as order_api: # Filter orders with date and store_id using list() # then get info of each order using info() # and call find_or_create_using_magento_data on sale filter = { 'store_id': { '=': self.magento_store_id }, 'state': { 'in': order_states_to_import_in }, } if self.last_order_import_time: last_order_import_time = \ self.last_order_import_time.replace( microsecond=0 ) filter.update({ 'updated_at': { 'gteq': last_order_import_time.isoformat(' ') }, }) self.write([self], {'last_order_import_time': datetime.utcnow()}) page = 1 has_next = True orders_summaries = [] while has_next: # XXX: Pagination is only available in # magento extension >= 1.6.1 api_res = order_api.search(filters=filter, limit=3000, page=page) has_next = api_res['hasNext'] page += 1 orders_summaries.extend(api_res['items']) for order_summary in orders_summaries: new_sales.append(self.import_order(order_summary)) return new_sales
def import_order_from_store_view(self): """ Imports sale from store view :return: List of active record of sale imported """ Sale = Pool().get('sale.sale') MagentoOrderState = Pool().get('magento.order_state') new_sales = [] instance = self.instance with Transaction().set_context({ 'magento_instance': instance.id, 'magento_website': self.website.id, 'magento_store_view': self.id, }): order_states = MagentoOrderState.search([ ('instance', '=', instance.id), ('use_for_import', '=', True) ]) order_states_to_import_in = map(lambda state: state.code, order_states) if not order_states_to_import_in: self.raise_user_error("states_not_found") with magento.Order(instance.url, instance.api_user, instance.api_key) as order_api: # Filter orders with date and store_id using list() # then get info of each order using info() # and call find_or_create_using_magento_data on sale filter = { 'store_id': { '=': self.magento_id }, 'state': { 'in': order_states_to_import_in }, } if self.last_order_import_time: filter.update({ 'updated_at': { 'gteq': self.last_order_import_time }, }) self.write([self], {'last_order_import_time': datetime.utcnow()}) orders = order_api.list(filter) for order in orders: new_sales.append( Sale.find_or_create_using_magento_data( order_api.info(order['increment_id']))) return new_sales
def import_order(self, order_info): "Downstream implementation to import sale order from magento" if self.source != 'magento': return super(Channel, self).import_order(order_info) Sale = Pool().get('sale.sale') sale = Sale.find_using_magento_data(order_info) if sale: return sale with Transaction().set_context({'current_channel': self.id}): with magento.Order(self.magento_url, self.magento_api_user, self.magento_api_key) as order_api: order_data = order_api.info(order_info['increment_id']) return Sale.create_using_magento_data(order_data)
def import_orders_from_store_view(self, cursor, user, store_view, context): """ Imports orders from store view :param cursor: Database cursor :param user: ID of current user :param store_view: browse record of store_view :param context: dictionary of application context data :return: list of sale ids """ sale_obj = self.pool.get('sale.order') magento_state_obj = self.pool.get('magento.order_state') instance = store_view.instance if context: new_context = deepcopy(context) else: new_context = {} new_context.update({ 'magento_instance': instance.id, 'magento_website': store_view.website.id, 'magento_store_view': store_view.id, }) new_sales = [] order_states = magento_state_obj.search( cursor, user, [('instance', '=', instance.id), ('use_for_import', '=', True)]) order_states_to_import_in = [ state.code for state in magento_state_obj.browse( cursor, user, order_states, context=context) ] if not order_states_to_import_in: raise osv.except_osv( _('Order States Not Found!'), _('No order states found for importing orders! ' 'Please configure the order states on magento instance')) with magento.Order(instance.url, instance.api_user, instance.api_key) as order_api: # Filter orders with date and store_id using list() # then get info of each order using info() # and call find_or_create_using_magento_data on sale filter = { 'store_id': { '=': store_view.magento_id }, 'state': { 'in': order_states_to_import_in }, } if store_view.last_order_import_time: filter.update({ 'updated_at': { 'gteq': store_view.last_order_import_time }, }) self.write(cursor, user, [store_view.id], { 'last_order_import_time': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) }, context=context) orders = order_api.list(filter) for order in orders: new_sales.append( sale_obj.find_or_create_using_magento_data( cursor, user, order_api.info(order['increment_id']), new_context)) return new_sales
def reimport(self, cr, uid, ids, context): """ In this method we can Re-import the sale order from magento, which is in exception state. """ if not context: context = {} sale_obj = self.pool.get('sale.order') store_view_ids = self.pool.get('magento.store.store_view').search( cr, uid, [], context=context) store_view_obj = self.pool.get('magento.store.store_view').browse( cr, uid, store_view_ids[0], context=context) magento_state_obj = self.pool.get('magento.order_state') store_view = store_view_obj instance = store_view.instance order_states = magento_state_obj.search( cr, uid, [('instance', '=', instance.id), ('use_for_import', '=', True)]) order_states_to_import_in = [ state.code for state in magento_state_obj.browse( cr, uid, order_states, context=context) ] context.update({ 'magento_instance': instance.id, 'magento_website': store_view.website.id, 'magento_store_view': store_view.id, }) with magento.Order(instance.url, instance.api_user, instance.api_key) as order_api: new_sales = [] mag_order_ids = [] #sale_order_ids = self.search(cr, uid, [('model_nm','=','sale.order')]) data = self.read(cr, uid, ids, ['exce_id'], context) for item in data: mag_order_ids.append(item.get('exce_id')) filter = { 'store_id': { '=': store_view.magento_id }, 'state': { 'in': order_states_to_import_in }, 'increment_id': { 'in': mag_order_ids }, } orders = order_api.list(filter) for order in orders: reimport_id = self.search( cr, uid, [('exce_id', '=', order['increment_id'])], context=context) try: new_sales.append( sale_obj.find_or_create_using_magento_data( cr, uid, order_api.info(order['increment_id']), context)) vals = { 'exce_id': order['increment_id'], 'state': 'done', } self.write(cr, uid, reimport_id, vals, context=context) except Exception, e: vals = { 'data': e, } self.write(cr, uid, reimport_id, vals, context=context)
def test0020_create_partner_for_same_website(self): """ Tests that partners should be unique in a website """ partner_obj = POOL.get('res.partner') magento_partner_obj = POOL.get('magento.website.partner') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_website': self.website_id1, 'magento_store_view': self.store_view_id, }) initial_partners = magento_partner_obj.search( txn.cursor, txn.user, [], context=context ) if settings.MOCK: customer_data = load_json('customers', '1') else: with magento.Order(*settings.ARGS) as order_api: orders = order_api.list() order_data = order_api.info(orders[0]['increment_id']) with magento.Customer(*settings.ARGS) as customer_api: if order_data.get('customer_id'): customer_data = customer_api.info( order_data['customer_id'] ) else: customer_data = { 'firstname': order_data['customer_firstname'], 'lastname': order_data['customer_lastname'], 'email': order_data['customer_email'], 'magento_id': 0 } partner = partner_obj.find_or_create( txn.cursor, txn.user, customer_data, context ) self.assert_(partner) self.assertTrue( partner_obj.search( txn.cursor, txn.user, [ ('email', '=', customer_data['email']) ], context=context ) ) partners = magento_partner_obj.search( txn.cursor, txn.user, [], context=context ) self.assertEqual(len(partners), len(initial_partners) + 1) # Create partner with same magento_id and website_id it will not # create new one partner_obj.find_or_create( txn.cursor, txn.user, customer_data, context ) partners = magento_partner_obj.search( txn.cursor, txn.user, [], context=context ) self.assertEqual(len(partners), len(initial_partners) + 1) # Create partner with different website context.update({ 'magento_website': self.website_id2 }) partner = partner_obj.find_or_create( txn.cursor, txn.user, customer_data, context ) self.assert_(partner) partners = magento_partner_obj.search( txn.cursor, txn.user, [], context=context ) self.assertEqual(len(partners), len(initial_partners) + 2) # Create partner with different magento_id context.update({ 'magento_website': self.website_id1 }) if settings.MOCK: customer_data = load_json('customers', '2') else: with magento.Order(*settings.ARGS) as order_api: orders = order_api.list() with magento.Customer(*settings.ARGS) as customer_api: for order in orders: if order.get('customer_id'): # Search for different cusotmer if order_data['customer_id'] == \ order['customer_id']: continue customer_data = customer_api.info( order['customer_id'] ) else: customer_data = { 'firstname': order['customer_firstname'], 'lastname': order['customer_lastname'], 'email': order['customer_email'], 'magento_id': 0 } self.assertFalse( partner_obj.search( txn.cursor, txn.user, [ ('email', '=', customer_data['email']) ], context=context ) ) partner = partner_obj.find_or_create( txn.cursor, txn.user, customer_data, context ) self.assert_(partner) self.assertTrue( partner_obj.search( txn.cursor, txn.user, [ ('email', '=', customer_data['email']) ], context=context ) ) partners = magento_partner_obj.search( txn.cursor, txn.user, [], context=context ) self.assertEqual(len(partners), len(initial_partners) + 3)
def test0040_match_address(self): """ Tests if address matching works as expected """ partner_obj = POOL.get('res.partner') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_website': self.website_id1, 'magento_store_view': self.store_view_id, }) if settings.MOCK: customer_data = load_json('customers', '1') address_data = load_json('addresses', '1') address_data2 = load_json('addresses', '1b') address_data3 = load_json('addresses', '1c') address_data4 = load_json('addresses', '1d') address_data5 = load_json('addresses', '1e') else: with magento.Order(*settings.ARGS) as order_api: orders = [ order_api.info(order['increment_id']) for order in order_api.list() ] order_data = orders[0] with magento.Customer(*settings.ARGS) as customer_api: if order_data.get('customer_id'): customer_data = customer_api.info( order_data['customer_id'] ) else: customer_data = { 'firstname': order_data['customer_firstname'], 'lastname': order_data['customer_lastname'], 'email': order_data['customer_email'], 'magento_id': 0 } address_data = order_data['billing_address'] for order in orders: # Search for address with different country if order['billing_address']['country_id'] != \ address_data['country_id']: address_data2 = order['billing_address'] # Search for address with different state if order['billing_address']['region'] != \ address_data['region']: address_data3 = order['billing_address'] # Search for address with different telephone if order['billing_address']['telephone'] != \ address_data['telephone']: address_data4 = order['billing_address'] # Search for address with different street if order['billing_address']['street'] != \ address_data['street']: address_data5 = order['billing_address'] # Create partner partner = partner_obj.find_or_create( txn.cursor, txn.user, customer_data, context ) address = partner_obj.\ find_or_create_address_as_partner_using_magento_data( txn.cursor, txn.user, address_data, partner, context ) # Same address imported again self.assertTrue( partner_obj.match_address_with_magento_data( txn.cursor, txn.user, address, address_data ) ) # Exactly similar address imported again self.assertTrue( partner_obj.match_address_with_magento_data( txn.cursor, txn.user, address, address_data ) ) # Similar with different country self.assertFalse( partner_obj.match_address_with_magento_data( txn.cursor, txn.user, address, address_data2 ) ) # Similar with different state self.assertFalse( partner_obj.match_address_with_magento_data( txn.cursor, txn.user, address, address_data3 ) ) # Similar with different telephone self.assertFalse( partner_obj.match_address_with_magento_data( txn.cursor, txn.user, address, address_data4 ) ) # Similar with different street self.assertFalse( partner_obj.match_address_with_magento_data( txn.cursor, txn.user, address, address_data5 ) )
def test0030_create_address(self): """ Tests if address creation works as expected """ partner_obj = POOL.get('res.partner') with Transaction().start(DB_NAME, USER, CONTEXT) as txn: self.setup_defaults(txn) context = deepcopy(CONTEXT) context.update({ 'magento_website': self.website_id1, 'magento_store_view': self.store_view_id, }) if settings.MOCK: customer_data = load_json('customers', '1') address_data = load_json('addresses', '1') else: with magento.Order(*settings.ARGS) as order_api: orders = order_api.list() order_data = order_api.info(orders[0]['increment_id']) with magento.Customer(*settings.ARGS) as customer_api: if order_data.get('customer_id'): customer_data = customer_api.info( order_data['customer_id'] ) else: customer_data = { 'firstname': order_data['customer_firstname'], 'lastname': order_data['customer_lastname'], 'email': order_data['customer_email'], 'magento_id': 0 } address_data = order_data['billing_address'] # Create partner partner = partner_obj.find_or_create( txn.cursor, txn.user, customer_data, context ) partners_before_address = partner_obj.search( txn.cursor, txn.user, [], context=context, count=True ) address_partner = partner_obj.\ find_or_create_address_as_partner_using_magento_data( txn.cursor, txn.user, address_data, partner, context ) partners_after_address = partner_obj.search( txn.cursor, txn.user, [], context=context, count=True ) self.assertTrue(partners_after_address > partners_before_address) self.assertEqual( address_partner.name, ' '.join( [address_data['firstname'], address_data['lastname']] ) )