def test_agent_post_first(self): token = self.get_token() session_id = 'agent_fist_session_id' chat_data = dict(session_id=session_id, content="agent message", channels=[str(self.sc.id)], token=token, type='chat', is_inbound=False, actor_id=self.agent_profile.id) resp = self.client.post('/api/v2.0/events', data=json.dumps(chat_data), content_type='application/json', base_url='https://localhost') self.assertEqual(resp.status_code, 200) # the first event belog to untracked agent, lets check that events = Event.objects()[:] self.assertEqual(len(events), 1) event = events[0] actor_num = unpack_event_id(event.id)[0] self.assertEqual(actor_num, 0) self.assertEqual(event.actor.first_name, self.agent_profile.first_name) self.assertEqual(event.actor.id, self.agent_profile.id) self.assertEqual(event.actor.actor_num, self.agent_profile.actor_num) chat_data = dict(session_id=session_id, content="customer message", channels=[str(self.sc.id)], token=token, type='chat', is_inbound=True, actor_id=str(self.customer_profile.id)) resp = self.client.post('/api/v2.0/events', data=json.dumps(chat_data), content_type='application/json', base_url='https://localhost') self.assertEqual(resp.status_code, 200) # after customer event was fired, the first event should # has right id with particular customer_profile encoded in id value events = Event.objects()[:] self.assertEqual(len(events), 2) event = events[0] self.assertEqual(event.is_inbound, False) self.assertEqual(event.actor.first_name, self.agent_profile.first_name) self.assertEqual(event.actor.id, self.agent_profile.id) self.assertEqual(event.actor.actor_num, self.agent_profile.actor_num) actor_num = unpack_event_id(event.id)[0] self.assertEqual(self.customer_profile.actor_num, actor_num)
class NBACase(BaseCase): def setUp(self): super(NBACase, self).setUp() setup_customer_schema(self.user) setup_agent_schema(self.user) self.customer_data = dict( first_name='Sujan', last_name='Shakya', age=30, account_id=str(self.account.id), location='Nepal', sex='M', account_balance=1000, last_call_intent=['buy a house'], num_calls=10, seniority='mediocre', ) self.customer = create_customer(**self.customer_data) agent_data = dict( first_name='Dipa', last_name='Shakya', age=29, location='Banepa', sex='F', account_id=str(self.account.id), skillset={ 'ethics': .9, 'temper': .5, 'memory': .5, }, occupancy=.9, products=['sell a house'], english_fluency='advanced', seniority='expert', ) self.agent = create_agent(**agent_data) self.action = Action.objects.create(account_id=self.account.id, name="Got a question? Chat Now!", tags=[], channels=[]) self.event = Event(actor_id=self.customer.id, is_inbound=True, assigned_tags=[], _native_id='1') self.event.save()
def test_conversation(self): ''' Generate an evenet sequence as a conversation and make sure it has customers and agents. ''' CustomerProfile = self.account.get_customer_profile_class() AgentProfile = self.account.get_customer_profile_class() events = self._create_event_sequence(length=7, brand_involved=True) # TODO: Figure out why it is necessary to convert these to strings. It appears to be the same # class but a direct comparison with isinstance does not work. Could be a limitation of the # dynamic class structure. self.assertTrue( str(type(events[0].actor)) == str(CustomerProfile), "%s %s is not instance of %s" % (type(events[0].actor), events[0].actor, CustomerProfile)) self.assertEqual(Event.objects(is_inbound=True).count(), 4) self.assertEqual(Event.objects(is_inbound=False).count(), 3)
def test_customer_events(self): events = self._create_event_sequence(length=3) for event in events: self.assertTrue(event.actor_id, self.customer.id) events = [x for x in Event.objects()] # self.assertEqual(len(events), 3) for e in events: unpacked_actor_num, unpacked_created_at = unpack_event_id(e.id) self.assertEqual(e.actor.actor_num, unpacked_actor_num) self.assertEqual(e.created_at, unpacked_created_at)
def construct_feature_space(self, event, features_metadata=None): actor_num, _ = unpack_event_id(event.id) id_lower_bound = pack_event_id(actor_num, utc(event._created - timedelta(seconds=self.lookback_window))) id_upper_bound = pack_event_id(actor_num, utc(event._created)) event_sequence = Event.objects(id__lte=id_upper_bound, id__gte=id_lower_bound)[:] vector_space = [] for event in event_sequence: event_vector = self.vectorize(event, features_metadata) if event_vector is not None: vector_space.append(event_vector) return vector_space
def customer_events(user): customer_data = request.json id_lower_bound = customer_data['event_first_id'] id_upper_bound = customer_data['event_last_id'] CustomerProfile = user.account.get_customer_profile_class() AgentProfile = user.account.get_agent_profile_class() results = [] for each in Event.objects(id__lte=long(id_upper_bound), id__gte=long(id_lower_bound)): result = each.to_dict() if each.is_inbound: result['user'] = CustomerProfile.objects.get(actor_counter=each.customer_id).to_dict() else: result['user'] = AgentProfile.objects.get(each.actor_id).to_dict() results.append(result) return jsonify(ok=True, list=results)
def test_event_linking(self): ''' Load dynamic events and have them link together in a sequence''' from solariat.utils.timeslot import utc, now from solariat_bottle.db.post.twitter import TwitterPost from solariat_bottle.db.post.facebook import FacebookPost from solariat_bottle.db.channel.facebook import FacebookChannel from solariat_bottle.db.channel.twitter import TwitterChannel from solariat_bottle.tasks import create_post start = utc(now()) one_sec = timedelta(seconds=1) account = setup_account(samples.sample2) # Get the customer for whom we expect the events to be linked. CustomerProfile = account.get_customer_profile_class() customer = CustomerProfile.objects.get(customer_id='c_1') self.assertEqual(customer.first_name, 'Jane') channels = [c.id for c in Channel.objects(account=account)] # Should be 5 events in all self.assertEqual(Event.objects.count(), 5) events = Event.objects(channels__in=channels)[:] self.assertEqual(len(events), 5) # lets check event linking with other entities tw_channel = TwitterChannel.objects.create_by_user( self.user, title='TestTWChannel', type='twitter') fb_channel = FacebookChannel.objects.create_by_user( self.user, title='TestFBChannel', type='facebook') # link twitter post to dynamic customer profile c_1 tw_post_data = { 'channels': [tw_channel.id], 'content': "hi! I'd like to order new bike", 'user_profile': { 'user_id': 'c_1', # link to CustomerProfile with id=c_1 'name': 'Jane Tw', }, 'twitter': { 'id': '80001000', } } # link twitter post to dynamic customer profile c_2 fb_post_data = { 'channels': [fb_channel.id], 'content': 'I love fb', 'user_profile': { 'user_id': 'c_2', # link event to CustomerProfile id=c_2 'name': 'John FB', }, 'facebook': { 'facebook_post_id': '1234-1234', } } tw_post = create_post(self.user, sync=True, **tw_post_data) fb_post = create_post(self.user, sync=True, **fb_post_data) end = now() + one_sec # because of added padding while created event_id, # we could reach next second self.assertEqual(Event.objects.count(), 7) # check linking: request sequences by 2 different customers customer.reload() customer2 = CustomerProfile.objects.get('c_2') c1_events = list(Event.objects.range_query(start, end, customer)) c2_events = list(Event.objects.range_query(start, end, customer2)) # import ipdb; ipdb.set_trace() self.assertEqual(len(c1_events), 4) self.assertEqual({e.platform for e in c1_events}, {'ET1', 'ET2', TwitterPost.platform}) self.assertEqual(len(c2_events), 3) self.assertEqual({e.platform for e in c2_events}, {'ET2', FacebookPost.platform}) tw_profile = customer.linked_profiles[0] fb_profile = customer2.linked_profiles[0] self.assertEqual(tw_profile.native_id, tw_post_data['user_profile']['user_id']) self.assertEqual(fb_profile.native_id, fb_post_data['user_profile']['user_id']) # new non-dynamic post which doesn't has corresponding id for customer profile create_post(self.user, sync=True, **{ 'channels': [tw_channel.id], 'content': "another twitter post", 'user_profile': { 'user_id': 'new_customer', 'name': 'New Twitter', }, 'twitter': { 'id': '80003874', } }) end = now() + one_sec # because of added padding while created event_id, # we could reach next second # we must still have 4 posts (with 1 twitter post) by c_1 customer self.assertEqual(Event.objects.range_query_count(start, end, customer), 4) # check for new customer created with twitter linked profile new_customer = CustomerProfile.objects.get('new_customer') self.assertIsNotNone(new_customer) self.assertIsInstance(new_customer.linked_profiles[0], TwitterPost.PROFILE_CLASS) # check we can find our last twitter event in range query new_customer_events = Event.objects.range_query_count(start, end, new_customer) self.assertEqual(new_customer_events, 1) # Cleanup remove_account(samples.sample2)