def lambda_handler(event, context):
    logger.info("event: %s" % json.dumps(event))

    event_record = event['Records'][0]
    bucket = event_record['s3']['bucket']['name']
    logger.info("bucket: %s" % bucket)
    key = urllib.parse.unquote(event_record['s3']['object']['key'])
    logger.info("key: %s" % key)
    data = s3.get_object(Bucket=bucket, Key=key)["Body"].read().decode()

    runtime_region = os.environ['AWS_REGION']

    sf = Salesforce()

    for record in csv.DictReader(data.split("\n")):
        queue_record = prepare_queue_record(record, event_record['eventTime'])
        ac_record_id = "%s%s%s" % (
            queue_record[pnamespace + 'AC_Object_Name__c'],
            queue_record[pnamespace + 'StartInterval__c'], runtime_region
        )  # Add AWS region into recordID for multi-instance setup
        #logger.info("sfIntervalAgent ac_record_id: %s" % ac_record_id)
        #logger.info("sfIntervalAgent record: %s" % queue_record)
        # logger.info("sfIntervalAgent record: %s" % agent_record)
        sf.update_by_external(pnamespace + "AC_HistoricalQueueMetrics__c",
                              pnamespace + 'AC_Record_Id__c', ac_record_id,
                              queue_record)

    logger.info("done")
Beispiel #2
0
def lambda_handler(event, context):

  logger.info("Logging Start sfIntervalAgent")
  logger.info("sfIntervalAgent event: %s" % json.dumps(event))

  event_record = event['Records'][0]
  bucket = event_record['s3']['bucket']['name']
  logger.info("bucket: %s" % bucket)
  key = urllib.parse.unquote(event_record['s3']['object']['key'])
  logger.info("key: %s" % key)
  data = s3.get_object(Bucket=bucket, Key=key)["Body"].read().decode()
  logger.info("sfIntervalAgent data: %s" % data)
  sf = Salesforce()


  for record in csv.DictReader(data.split("\n")):
    logger.info("sfIntervalAgent record: %s" % record)
    #sf.create(pnamespace + "AC_AgentPerformance__c", prepare_agent_record(record, event_record['eventTime']))
    agent_record = prepare_agent_record(record, event_record['eventTime'])
    #logger.info("AC_Object_Name__c: %s" % agent_record[pnamespace + 'AC_Object_Name__c'])
    #logger.info("StartInterval__c: %s" % agent_record[pnamespace + 'StartInterval__c'])
    ac_record_id = "%s%s" % (agent_record[pnamespace + 'AC_Object_Name__c'], agent_record[pnamespace + 'StartInterval__c'])
    #logger.info("sfIntervalAgent ac_record_id: %s" % ac_record_id)
    #logger.info("sfIntervalAgent record: %s" % agent_record)
    #logger.info("sfIntervalAgent record: %s" % agent_record)
    sf.update_by_external(pnamespace + "AC_AgentPerformance__c", pnamespace + 'AC_Record_Id__c',ac_record_id, agent_record)

  logger.info("done")
Beispiel #3
0
def ac_queue_metrics(queue_id_name_dict, queue_ids, instance_id):
    try:

        logger.info("Start ac_queue_metrics")
        logger.info(f"Queues : {queue_ids}")
        next_token = 'NoToken'

        queuemetics_max_result = os.environ[
            'AMAZON_CONNECT_QUEUEMETRICS_MAX_RESULT']
        current_metrics = [
            {
                'Name': 'AGENTS_ONLINE',
                'Unit': 'COUNT'
            },
            {
                'Name': 'AGENTS_AVAILABLE',
                'Unit': 'COUNT'
            },
            {
                'Name': 'AGENTS_ON_CALL',
                'Unit': 'COUNT'
            },
            {
                'Name': 'AGENTS_STAFFED',
                'Unit': 'COUNT'
            },
            {
                'Name': 'AGENTS_AFTER_CONTACT_WORK',
                'Unit': 'COUNT'
            },
            {
                'Name': 'AGENTS_NON_PRODUCTIVE',
                'Unit': 'COUNT'
            },
            {
                'Name': 'AGENTS_ERROR',
                'Unit': 'COUNT'
            },
            {
                'Name': 'CONTACTS_IN_QUEUE',
                'Unit': 'COUNT'
            },
            {
                'Name': 'OLDEST_CONTACT_AGE',
                'Unit': 'SECONDS'
            },
            {
                'Name': 'CONTACTS_SCHEDULED',
                'Unit': 'COUNT'
            },
        ]

        while len(next_token) != 0:
            if next_token == 'NoToken':
                logger.info("Call QueueMetric : without no token")
                currentMetrics_data = connect.get_current_metric_data(
                    InstanceId=instance_id,
                    Filters={
                        'Channels': ['VOICE'],
                        'Queues': queue_ids
                    },
                    Groupings=['QUEUE'],
                    CurrentMetrics=current_metrics,
                    MaxResults=int(queuemetics_max_result))
            else:
                logger.info("Call QueueMetric : with token")
                currentMetrics_data = connect.get_current_metric_data(
                    InstanceId=instance_id,
                    Filters={
                        'Channels': ['VOICE'],
                        'Queues': queue_ids
                    },
                    Groupings=['QUEUE'],
                    CurrentMetrics=current_metrics,
                    MaxResults=int(queuemetics_max_result),
                    NextToken=next_token)
            logger.info(f"currentMetrics_data: {currentMetrics_data}")

            if 'NextToken' in currentMetrics_data.keys():
                next_token = currentMetrics_data['NextToken']
                logger.info(f"NextToken: {next_token}")
            else:
                next_token = ''
                logger.info("NextToke key is Not present")

            if 'MetricResults' in currentMetrics_data.keys():
                metricresults_data = currentMetrics_data['MetricResults']
                logger.info(f"metricresults_data: {metricresults_data}")
            else:
                metricresults_data = []
                logger.info("MetricResults key is Not present")

            i = 0

            sf = Salesforce()
            sf.sign_in()

            if len(metricresults_data) != 0:
                while i < len(metricresults_data):
                    queue_metics_data_dict = {}
                    data = metricresults_data[i]
                    logger.info('*********')
                    logger.info(f'Data : {i} ***  {data}')
                    if 'Dimensions' in data.keys():
                        dimensions_data = data['Dimensions']
                        if 'Queue' in dimensions_data.keys():
                            queue_data = dimensions_data['Queue']
                            queue_metics_data_dict['queue_id'] = queue_data[
                                'Id']
                            queue_metics_data_dict['queue_arn'] = queue_data[
                                'Arn']
                            logger.info(f"queue id : {queue_data['Id']}")
                            logger.info(f"queue ARN : {queue_data['Arn']}")
                            logger.info('*********')
                            logger.info('*********')

                    if 'Collections' in data.keys():
                        collections_data = data['Collections']
                        logger.info(
                            f'collections_data : {i} ***  {collections_data}')
                        j = 0
                        while j < len(collections_data):
                            logger.info(f"J : {j}")
                            metrics_data = collections_data[j]
                            logger.info(metrics_data)

                            if 'Metric' in metrics_data.keys():
                                metric_data = metrics_data['Metric']
                                if metric_data[
                                        'Name'] == 'AGENTS_ONLINE' and 'Value' in metrics_data.keys(
                                        ):
                                    agent_online = int(metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'agent_online'] = agent_online
                                elif metric_data[
                                        'Name'] == 'AGENTS_AVAILABLE' and 'Value' in metrics_data.keys(
                                        ):
                                    agent_available = int(
                                        metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'agent_available'] = agent_available
                                elif metric_data[
                                        'Name'] == 'AGENTS_ON_CALL' and 'Value' in metrics_data.keys(
                                        ):
                                    agent_on_call = int(metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'agent_on_call'] = agent_on_call
                                elif metric_data[
                                        'Name'] == 'AGENTS_STAFFED' and 'Value' in metrics_data.keys(
                                        ):
                                    agent_staffed = int(metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'agent_staffed'] = agent_staffed
                                elif metric_data[
                                        'Name'] == 'AGENTS_AFTER_CONTACT_WORK' and 'Value' in metrics_data.keys(
                                        ):
                                    agent_awc = int(metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'agent_awc'] = agent_awc
                                elif metric_data[
                                        'Name'] == 'AGENTS_NON_PRODUCTIVE' and 'Value' in metrics_data.keys(
                                        ):
                                    agent_non_productive = int(
                                        metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'agent_non_productive'] = agent_non_productive
                                elif metric_data[
                                        'Name'] == 'AGENTS_ERROR' and 'Value' in metrics_data.keys(
                                        ):
                                    agent_error = int(metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'agent_error'] = agent_error
                                elif metric_data[
                                        'Name'] == 'CONTACTS_IN_QUEUE' and 'Value' in metrics_data.keys(
                                        ):
                                    contacts_in_queue = int(
                                        metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'contacts_in_queue'] = contacts_in_queue
                                elif metric_data[
                                        'Name'] == 'OLDEST_CONTACT_AGE' and 'Value' in metrics_data.keys(
                                        ):
                                    oldest_contact_age = int(
                                        metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'oldest_contact_age'] = oldest_contact_age
                                elif metric_data[
                                        'Name'] == 'CONTACTS_SCHEDULED' and 'Value' in metrics_data.keys(
                                        ):
                                    contacts_scheduled = int(
                                        metrics_data['Value'])
                                    queue_metics_data_dict[
                                        'contacts_scheduled'] = contacts_scheduled
                            j = j + 1
                        sObjectData = prepare_record(queue_id_name_dict,
                                                     queue_metics_data_dict)
                        sf.update_by_external(
                            objectnamespace + "AC_QueueMetrics__c",
                            objectnamespace + 'Queue_Id__c',
                            queue_metics_data_dict['queue_id'], sObjectData)
                        i = i + 1

            logger.info("End ac_queue_metrics method")

    except Exception as e:
        raise e
Beispiel #4
0
def create_ctr_record(ctr):
    objectnamespace = os.environ['SF_ADAPTER_NAMESPACE']

    if not objectnamespace or objectnamespace == '-':
        logger.info("SF_ADAPTER_NAMESPACE is empty")
        objectnamespace = ''
    else:
        objectnamespace = objectnamespace + "__"

    sf_request = {}

    sf_request[objectnamespace + 'AWSAccountId__c'] = ctr['AWSAccountId']

    if ctr['Agent']:
        sf_request[objectnamespace + 'AfterContactWorkDuration__c'] = ctr[
            'Agent']['AfterContactWorkDuration']
        sf_request[objectnamespace + 'AfterContactWorkEndTimestamp__c'] = ctr[
            'Agent']['AfterContactWorkEndTimestamp']
        sf_request[objectnamespace +
                   'AfterContactWorkStartTimestamp__c'] = ctr['Agent'][
                       'AfterContactWorkStartTimestamp']
        sf_request[objectnamespace +
                   'AfterContactWorkStartTimestamp__c'] = ctr['Agent'][
                       'AfterContactWorkStartTimestamp']
        sf_request[objectnamespace +
                   'AgentConnectedToAgentTimestamp__c'] = ctr['Agent'][
                       'ConnectedToAgentTimestamp']
        sf_request[objectnamespace + 'AgentInteractionDuration__c'] = ctr[
            'Agent']['AgentInteractionDuration']
        sf_request[objectnamespace + 'AgentCustomerHoldDuration__c'] = ctr[
            'Agent']['CustomerHoldDuration']
        sf_request[objectnamespace + 'AgentHierarchyGroup__c'] = json.dumps(
            ctr['Agent']['HierarchyGroups'])
        sf_request[objectnamespace + 'AgentLongestHoldDuration__c'] = ctr[
            'Agent']['LongestHoldDuration']
        sf_request[objectnamespace +
                   'AgentNumberOfHolds__c'] = ctr['Agent']['NumberOfHolds']
        sf_request[objectnamespace +
                   'AgentUsername__c'] = ctr['Agent']['Username']

        if ctr['Agent']['RoutingProfile']:
            sf_request[objectnamespace + 'AgentRoutingProfileARN__c'] = ctr[
                'Agent']['RoutingProfile']['ARN']
            sf_request[objectnamespace + 'AgentRoutingProfileName__c'] = ctr[
                'Agent']['RoutingProfile']['Name']

    sf_request[objectnamespace +
               'AgentConnectionAttempts__c'] = ctr['AgentConnectionAttempts']
    sf_request[objectnamespace + 'Attributes__c'] = json.dumps(
        ctr['Attributes'])
    sf_request[objectnamespace + 'Channel__c'] = ctr['Channel']

    # Customer Data
    if ctr['CustomerEndpoint']:
        sf_request[
            objectnamespace +
            'CustomerEndpointAddress__c'] = ctr['CustomerEndpoint']['Address']

    sf_request[objectnamespace +
               'InitiationTimestamp__c'] = ctr['InitiationTimestamp']
    sf_request[objectnamespace +
               'InitialContactId__c'] = ctr['InitialContactId']
    sf_request[objectnamespace +
               'Initiation_Method__c'] = ctr['InitiationMethod']
    sf_request[objectnamespace +
               'InitiationTimestamp__c'] = ctr['InitiationTimestamp']
    sf_request[objectnamespace + 'InstanceARN__c'] = ctr['InstanceARN']
    sf_request[objectnamespace +
               'LastUpdateTimestamp__c'] = ctr['LastUpdateTimestamp']
    sf_request[objectnamespace + 'NextContactId__c'] = ctr['NextContactId']
    sf_request[objectnamespace +
               'PreviousContactId__c'] = ctr['PreviousContactId']

    # Queue
    if ctr['Queue']:
        sf_request[objectnamespace + 'QueueARN__c'] = ctr['Queue']['ARN']
        sf_request[
            objectnamespace +
            'QueueDequeueTimestamp__c'] = ctr['Queue']['DequeueTimestamp']
        sf_request[objectnamespace +
                   'QueueDuration__c'] = ctr['Queue']['Duration']
        sf_request[
            objectnamespace +
            'QueueEnqueueTimestamp__c'] = ctr['Queue']['EnqueueTimestamp']
        sf_request[objectnamespace + 'QueueName__c'] = ctr['Queue']['Name']

    # Recording
    if ctr['Recording']:
        sf_request[objectnamespace +
                   'RecordingLocation__c'] = ctr['Recording']['Location']
        sf_request[objectnamespace +
                   'RecordingStatus__c'] = ctr['Recording']['Status']
        sf_request[
            objectnamespace +
            'RecordingDeletionReason__c'] = ctr['Recording']['DeletionReason']

    # System End Data
    if ctr['SystemEndpoint']:
        sf_request[
            objectnamespace +
            'SystemEndpointAddress__c'] = ctr['SystemEndpoint']['Address']

    # Transfer Data
    if ctr['TransferredToEndpoint']:
        sf_request[objectnamespace + 'TransferredToEndpoint__c'] = ctr[
            'TransferredToEndpoint']['Address']

    if ctr['TransferCompletedTimestamp']:
        sf_request[objectnamespace + 'TransferCompletedTimestamp__c'] = ctr[
            'TransferCompletedTimestamp']

    logger.info(f'Record : {sf_request}')

    sf = Salesforce()
    sf.update_by_external(objectnamespace + "AC_ContactTraceRecord__c",
                          objectnamespace + 'ContactId__c', ctr['ContactId'],
                          sf_request)

    logger.info(f'Record Created Successfully')
class SalesforceTest(unittest.TestCase):
    def setUp(self):
        self.version = "v5"
        self.consumer_key = "consumer_key"
        self.consumer_secret = "consumer_secret"
        self.username = "******"
        self.password = "******"
        self.access_token = "access_token"

        self.sf = Salesforce(self.version, self.consumer_key,
                             self.consumer_secret, self.username,
                             self.password)

    def test_sign_in(self):
        data = {
            'access_token': self.access_token,
            'instance_url': 'https://instanceid.salesforce.com'
        }
        resp = unittest.mock.Mock()
        resp.json.return_value = data
        self.sf.request = unittest.mock.Mock()
        self.sf.request.post.return_value = resp

        self.sf.sign_in()

        self.assertEqual(data['access_token'], self.sf.access_token)
        self.assertEqual(data['instance_url'], self.sf.host)
        self.sf.request.post.called_once()
        _, kwargs = self.sf.request.post.call_args
        self.assertTrue("client_id" in kwargs['params'])
        self.assertEqual(self.consumer_key, kwargs['params']['client_id'])
        self.assertTrue("client_secret" in kwargs['params'])
        self.assertEqual(self.consumer_secret,
                         kwargs['params']['client_secret'])
        self.assertTrue("username" in kwargs['params'])
        self.assertEqual(self.username, kwargs['params']['username'])
        self.assertTrue(self.password in kwargs['params'])
        self.assertEqual(self.password, kwargs['params']['password'])
        self.assertTrue('Authorization' in self.sf.headers)
        self.assertTrue(
            self.sf.access_token in self.sf.headers['Authorization'])
        self.assertTrue("Content-Type" in self.sf.headers)
        self.assertEqual("application/json", self.sf.headers["Content-Type"])

    def test_query(self):
        self.sf.headers = {
            'Authorization': 'Bearer %s' % self.access_token,
            'Content-Type': 'application/json'
        }
        self.sf.host = "https://instancid.salesforce.com"
        data_original = {
            "done":
            True,
            "totalSize":
            2,
            "records": [{
                "attributes": {
                    "type":
                    "Account",
                    "url":
                    "/services/data/v20.0/sobjects/Account/001D000000IRFmaIAH"
                },
                "Name": "Test 1"
            }, {
                "attributes": {
                    "type":
                    "Account",
                    "url":
                    "/services/data/v20.0/sobjects/Account/001D000000IomazIAB"
                },
                "Name": "Test 2"
            }]
        }
        resp = unittest.mock.Mock()
        resp.json.return_value = data_original
        self.sf.request.get = unittest.mock.Mock(return_value=resp)

        query = "SELECT Name FROM Account"
        data = self.sf.query(query)

        self.assertEqual(data_original['records'], data)
        _, kwargs = self.sf.request.get.call_args
        self.assertEqual(
            self.sf.host + "/services/data/" + self.version + "/query",
            kwargs['url'])
        self.assertTrue('params' in kwargs)
        self.assertEqual(query, kwargs['params']['q'])

    def test_search(self):
        self.sf.headers = {
            'Authorization': 'Bearer %s' % self.access_token,
            'Content-Type': 'application/json'
        }
        self.sf.host = "https://instancid.salesforce.com"
        data_original = {
            "searchRecords": [{
                "attributes": {
                    "type":
                    "Account",
                    "url":
                    "/services/data/v35.0/sobjects/Account/001D000000IqhSLIAZ"
                },
                "Id": "001D000000IqhSLIAZ",
            }, {
                "attributes": {
                    "type":
                    "Account",
                    "url":
                    "/services/data/v35.0/sobjects/Account/001D000000IomazIAB"
                },
                "Id": "001D000000IomazIAB"
            }]
        }
        resp = unittest.mock.Mock()
        resp.json.return_value = data_original
        self.sf.request.get = unittest.mock.Mock(return_value=resp)

        query = "FIND Acme"
        data = self.sf.search(query)

        self.assertEqual(data_original['searchRecords'], data)
        _, kwargs = self.sf.request.get.call_args
        self.assertEqual(
            self.sf.host + "/services/data/" + self.version + "/search",
            kwargs['url'])
        self.assertTrue('params' in kwargs)
        self.assertEqual(query, kwargs['params']['q'])

    def test_update(self):
        self.sf.headers = {
            'Authorization': 'Bearer %s' % self.access_token,
            'Content-Type': 'application/json'
        }
        self.sf.host = "https://instancid.salesforce.com"
        self.sf.request = unittest.mock.Mock(return_value=(None, None))

        sobject = "Case"
        data = {'Name': 'Pete'}
        sojb_id = "abc"
        self.sf.update(sobject, sojb_id, data)

        _, kwargs = self.sf.request.patch.call_args
        self.assertEqual(self.sf.host + "/services/data/v5/sobjects/Case/abc",
                         kwargs['url'])
        self.assertEqual(data, kwargs['data'])
        self.assertEqual(self.sf.headers, kwargs['headers'])

    def test_update_by_external(self):
        self.sf.headers = {
            'Authorization': 'Bearer %s' % self.access_token,
            'Content-Type': 'application/json'
        }
        self.sf.host = "https://instancid.salesforce.com"
        self.sf.request = unittest.mock.Mock(return_value=None)

        sobject = "Case"
        sfield = "call_id__c"
        data = {'Name': 'Pete'}
        sojb_id = "abc"
        self.sf.update_by_external(sobject, sfield, sojb_id, data)

        _, kwargs = self.sf.request.patch.call_args
        self.assertEqual(
            self.sf.host + "/services/data/v5/sobjects/Case/call_id__c/abc",
            kwargs['url'])
        self.assertEqual(data, kwargs['data'])
        self.assertEqual(self.sf.headers, kwargs['headers'])

    def test_create(self):
        self.sf.headers = {
            'Authorization': 'Bearer %s' % self.access_token,
            'Content-Type': 'application/json'
        }
        self.sf.host = "https://instancid.salesforce.com"
        resp_data = {"id": "001D000000IqhSLIAZ", "errors": [], "success": True}
        resp = unittest.mock.Mock()
        resp.json.return_value = resp_data
        self.sf.request.post = unittest.mock.Mock(return_value=resp)

        sobj = "Account"
        data = {'Name': 'Pete'}
        new_id = self.sf.create(sobj, data)

        self.assertEqual(resp_data['id'], new_id)
        _, kwargs = self.sf.request.post.call_args
        self.assertTrue('url' in kwargs)
        self.assertEqual(self.sf.host + "/services/data/v5/sobjects/Account",
                         kwargs['url'])
        self.assertTrue('data' in kwargs)
        self.assertEqual(data, kwargs['data'])
        self.assertEqual(self.sf.headers, kwargs['headers'])

    def test_delete(self):
        self.sf.headers = {
            'Authorization': 'Bearer %s' % self.access_token,
            'Content-Type': 'application/json'
        }
        self.sf.host = "https://instancid.salesforce.com"
        resp = unittest.mock.Mock()
        resp.json.return_value = "create_data"
        self.sf.request.delete = unittest.mock.Mock(return_value=resp)

        sobj = "Account"
        sobj_id = "abc"
        self.sf.delete(sobj, sobj_id)

        _, kwargs = self.sf.request.delete.call_args
        self.assertTrue('url' in kwargs)
        self.assertEqual(
            self.sf.host + "/services/data/v5/sobjects/Account/abc",
            kwargs['url'])
        self.assertEqual(self.sf.headers, kwargs['headers'])

    def test_set_production(self):
        current_login_host = self.sf.login_host
        self.sf.set_production()

        self.assertNotEqual(current_login_host, self.sf.login_host)

    @unittest.skip("Configuration required")
    def test_end_to_end(self):
        import os
        import sf_config
        import uuid
        sf = Salesforce(version=os.environ["SF_VERSION"],
                        consumer_key=os.environ["SF_CONSUMER_KEY"],
                        consumer_secret=os.environ["SF_CONSUMER_SECRET"],
                        username=os.environ["SF_USERNAME"],
                        password=os.environ["SF_PASSWORD"])
        sf.sign_in()
        name = str(uuid.uuid4())
        sf.create("Account", {'Name': name})
        acc = sf.query("SELECT Id FROM Account WHERE Name='%s'" % name)[0]
        sf.update("Account",
                  sobj_id=acc['Id'],
                  data={"Description": "hello world"})
        sf.delete("Account", acc['Id'])