Queue Conversation with the longest duration Assistance

Yeah I am stuck at the moment.

This is the query that I am using currently.

{
 "interval": "2022-06-08T23:00:00.000Z/2022-06-09T23:00:00.000Z",
 "order": "desc",
 "orderBy": "conversationStart",
 "paging": {
  "pageSize": 25,
  "pageNumber": 1
 },
 "segmentFilters": [
  {
   "type": "and",
   "predicates": [
    {
     "type": "dimension",
     "dimension": "queueId",
     "operator": "matches",
     "value": "e1a1b5ff-6ad9-4547-a407-b16e229b4c82"
    },
    {
     "type": "dimension",
     "dimension": "purpose",
     "operator": "matches",
     "value": "acd"
    }
   ]
  }
 ],
 "conversationFilters": [
  {
   "type": "and",
   "predicates": [
    {
     "type": "dimension",
     "dimension": "conversationEnd",
     "operator": "notExists",
     "value": null
    }
   ]
  }
 ]
}

Don't forget the segmentEnd predicate.

What are you stuck on?

Thank you very much!!! This seams to do the trick

{
 "interval": "2022-06-08T23:00:00.000Z/2022-06-09T23:00:00.000Z",
 "order": "desc",
 "orderBy": "conversationStart",
 "paging": {
  "pageSize": 25,
  "pageNumber": 1
 },
 "segmentFilters": [
  {
   "type": "and",
   "predicates": [
    {
     "type": "dimension",
     "dimension": "queueId",
     "operator": "matches",
     "value": "e1a1b5ff-6ad9-4547-a407-b16e229b4c82"
    },
    {
     "type": "dimension",
     "dimension": "purpose",
     "operator": "matches",
     "value": "acd"
    },
    {
     "type": "dimension",
     "dimension": "segmentEnd",
     "operator": "notExists",
     "value": null
    }
   ]
  }
 ],
 "conversationFilters": [
  {
   "type": "and",
   "predicates": [
    {
     "type": "dimension",
     "dimension": "conversationEnd",
     "operator": "notExists",
     "value": null
    }
   ]
  }
 ]
}

I will continue with the flow and expressions and see how I get on.

I assume that I would need to have an out for conversationStart and then use an expression to calculate the duration?

would you be able to help me with the mapping by any chance>

This is failing

{
  "translationMap": {
    "totalHits": "$.totalHits",
    "conversationStart": "$.conversationStart"
  },
  "translationMapDefaults": {},
  "successTemplate": "{\n   \"calls\": ${conversationStart}\n}"
}

Oh, I didn't catch that you were doing this for a data action. I'm not sure if you can do this purely in Architect. I don't work with JSONPath expressions or Architect much; let me tag in some other folks.

thank you very much. Appreciate it. I have the same post in the data action category, however, no replies except for one stating that I should also post it here in the analytics and reporting category. I should have mentioned in the initial post, thanks again.

Hello,

Using Conversation Details Query:
POST /api/v2/analytics/conversations/details/query

If you are looking for the oldest conversations (when conversation started), which are currently in queue, you have to use an:
"order": "asc",
"orderBy": "conversationStart",

If you only need to retrieve the oldest conversation, which is currently in queue, you could limit the results to 1 with:
"paging": {
"pageSize": "1",
"pageNumber": 1
},

I would also recommend to use a filter on mediaType (as you mention "calls") - so that it only looks at the oldest voice conversations (if your Queueu manages multiple media types).

Conversation Details Query example for the 25 oldest conversations, currently in queue:

{
 "interval": "YOUR_INTERVAL",
 "order": "asc",
 "orderBy": "conversationStart",
 "paging": {
  "pageSize": "25",
  "pageNumber": 1
 },
 "segmentFilters": [
  {
   "type": "and",
   "predicates": [
    {
     "type": "dimension",
     "dimension": "queueId",
     "operator": "matches",
     "value": "YOUR_QUEUE_ID"
    },
    {
     "type": "dimension",
     "dimension": "purpose",
     "operator": "matches",
     "value": "acd"
    },
    {
     "type": "dimension",
     "dimension": "segmentEnd",
     "operator": "notExists",
     "value": null
    },
    {
     "type": "dimension",
     "dimension": "mediaType",
     "operator": "matches",
     "value": "voice"
    }
   ]
  }
 ],
 "conversationFilters": [
  {
   "type": "or",
   "predicates": [
    {
     "type": "dimension",
     "dimension": "conversationEnd",
     "operator": "notExists",
     "value": null
    }
   ]
  }
 ]
}

Data Action Contract and Configuration - oldestTimes and oldestConversations output parameter as arrays:

{
  "config": {
    "request": {
      "requestUrlTemplate": "/api/v2/analytics/conversations/details/query",
      "requestType": "POST",
      "headers": {
        "Content-Type": "application/json"
      },
      "requestTemplate": "{\n    \"interval\": \"${input.interval}\",\n    \"order\": \"asc\",\n    \"orderBy\": \"conversationStart\",\n    \"paging\": {\n        \"pageSize\": \"25\",\n        \"pageNumber\": 1\n    },\n    \"segmentFilters\": [\n        {\n            \"type\": \"and\",\n            \"predicates\": [\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"queueId\",\n                    \"operator\": \"matches\",\n                    \"value\": \"${input.queueId}\"\n                },\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"purpose\",\n                    \"operator\": \"matches\",\n                    \"value\": \"acd\"\n                },\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"segmentEnd\",\n                    \"operator\": \"notExists\",\n                    \"value\": null\n                },\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"mediaType\",\n                    \"operator\": \"matches\",\n                    \"value\": \"voice\"\n                }\n            ]\n        }\n    ],\n    \"conversationFilters\": [\n        {\n            \"type\": \"or\",\n            \"predicates\": [\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"conversationEnd\",\n                    \"operator\": \"notExists\",\n                    \"value\": null\n                }\n            ]\n        }\n    ]\n}"
    },
    "response": {
      "translationMap": {
        "nbHits": "$.totalHits",
        "timeStartArray": "$.conversations[*].conversationStart",
        "convIdArray": "$.conversations[*].conversationId"
      },
      "translationMapDefaults": {
        "nbHits": "0",
        "timeStartArray": "[]",
        "convIdArray": "[]"
      },
      "successTemplate": "{ \"nbWaiting\": ${nbHits}, \"oldestTimes\": ${timeStartArray}, \"oldestConversations\": ${convIdArray} }"
    }
  },
  "contract": {
    "input": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "interval": {
            "type": "string"
          },
          "queueId": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    },
    "output": {
      "successSchema": {
        "type": "object",
        "properties": {
          "nbWaiting": {
            "type": "integer"
          },
          "oldestTimes": {
            "type": "array",
            "items": {
              "title": "Item 1",
              "type": "string"
            }
          },
          "oldestConversations": {
            "type": "array",
            "items": {
              "title": "Item 1",
              "type": "string"
            }
          }
        },
        "additionalProperties": true
      }
    }
  }
}

Conversation Details Query for the oldest conversation, currently in queue (only one returned)

Data Action Contract and Configuration - oldestTime and oldestConversation output parameter as strings:

{
  "config": {
    "request": {
      "requestUrlTemplate": "/api/v2/analytics/conversations/details/query",
      "requestType": "POST",
      "headers": {
        "Content-Type": "application/json"
      },
      "requestTemplate": "{\n    \"interval\": \"${input.interval}\",\n    \"order\": \"asc\",\n    \"orderBy\": \"conversationStart\",\n    \"paging\": {\n        \"pageSize\": \"1\",\n        \"pageNumber\": 1\n    },\n    \"segmentFilters\": [\n        {\n            \"type\": \"and\",\n            \"predicates\": [\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"queueId\",\n                    \"operator\": \"matches\",\n                    \"value\": \"${input.queueId}\"\n                },\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"purpose\",\n                    \"operator\": \"matches\",\n                    \"value\": \"acd\"\n                },\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"segmentEnd\",\n                    \"operator\": \"notExists\",\n                    \"value\": null\n                },\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"mediaType\",\n                    \"operator\": \"matches\",\n                    \"value\": \"voice\"\n                }\n            ]\n        }\n    ],\n    \"conversationFilters\": [\n        {\n            \"type\": \"or\",\n            \"predicates\": [\n                {\n                    \"type\": \"dimension\",\n                    \"dimension\": \"conversationEnd\",\n                    \"operator\": \"notExists\",\n                    \"value\": null\n                }\n            ]\n        }\n    ]\n}"
    },
    "response": {
      "translationMap": {
        "nbHits": "$.totalHits",
        "timeStart": "$.conversations[0].conversationStart",
        "convId": "$.conversations[0].conversationId"
      },
      "translationMapDefaults": {
        "nbHits": "0",
        "timeStart": "\"\"",
        "convId": "\"\""
      },
      "successTemplate": "{ \"nbWaiting\": ${nbHits}, \"oldestTime\": ${timeStart}, \"oldestConversation\": ${convId} }"
    }
  },
  "contract": {
    "input": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "interval": {
            "type": "string"
          },
          "queueId": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    },
    "output": {
      "successSchema": {
        "type": "object",
        "properties": {
          "nbWaiting": {
            "type": "integer"
          },
          "oldestTime": {
            "type": "string"
          },
          "oldestConversation": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    }
  }
}

Using Queue Observation Query:
POST /api/v2/analytics/queues/observations/query

You could also use a Queue Observation Query, if you are interested in the longest time in Queue.
What I mean is that:
A customer (Customer 1) calls; the call is put into a Queue for 3 mn; the customer is connected to an Agent.
A second customer (Customer 2) calls; the call is put into a Queue.
While Customer 2 is waiting in the Queue, the Agent transfers Customer 1 back to the Queue.

With the Conversation Details Query from above, you would capture Customer 1 as the oldest call.
With the Queue Observation Query, you can capture Customer 2 as the oldest call in this Queue.

Note that the query response will include a list of ongoing observations with up to 50 oldest and up to 50 newest observations.

Here is an example of Data Action only getting the oldest observation.
To retrieve multiples, the approach may be different than the one I have used for Conversation Details Query above. In theory, the Observation Query could retrieve up to 100 values. I have never tried in Architect if that would be a problem for a Collection of Strings.

Queue Observation Query example:

{
    "filter": {
       "type": "and",
       "predicates": [
          {
      "type": "dimension",
      "dimension": "queueId",
      "operator": "matches",
      "value": "YOUR_QUEUE_ID"
     },
     {
      "type": "dimension",
      "dimension": "mediaType",
      "operator": "matches",
      "value": "chat"
     }
       ]
    },
    "metrics": ["oWaiting"],
    "detailMetrics": ["oWaiting"]
}

Data Action Contract and Configuration:

{
  "config": {
    "request": {
      "requestUrlTemplate": "/api/v2/analytics/queues/observations/query",
      "requestType": "POST",
      "headers": {
        "Content-Type": "application/json"
      },
      "requestTemplate": "{\n    \"filter\": {\n        \"type\": \"and\",\n        \"predicates\": [\n            {\n                \"type\": \"dimension\",\n                \"dimension\": \"queueId\",\n                \"operator\": \"matches\",\n                \"value\": \"${input.queueId}\"\n            },\n            {\n                \"type\": \"dimension\",\n                \"dimension\": \"mediaType\",\n                \"operator\": \"matches\",\n                \"value\": \"voice\"\n            }\n        ]\n    },\n    \"metrics\": [\n        \"oWaiting\"\n    ],\n    \"detailMetrics\": [\n        \"oWaiting\"\n    ]\n}"
    },
    "response": {
      "translationMap": {
        "nbHits": "$.results[0].data[0].stats.count",
        "timeQueued": "$.results[0].data[0].observations[0].observationDate",
        "convId": "$.results[0].data[0].observations[0].conversationId"
      },
      "translationMapDefaults": {
        "nbHits": "0",
        "timeQueued": "\"\"",
        "convId": "\"\""
      },
      "successTemplate": "{ \"nbWaiting\": ${nbHits}, \"oldestTime\": ${timeQueued}, \"oldestConversation\": ${convId} }"
    }
  },
  "contract": {
    "input": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "queueId": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    },
    "output": {
      "successSchema": {
        "type": "object",
        "properties": {
          "nbWaiting": {
            "type": "integer"
          },
          "oldestTime": {
            "type": "string"
          },
          "oldestConversation": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    }
  }
}

Regards,

1 Like

HI Jerome,

Thank you very much, this is exactly what I needed.

Thanks again.

Chris Carr

The only issue I am having is that I cannot use DateTimeDiff() with strings in my expression.

I believe you can use the ToDateTime function to convert a date time string to a DateTime typed variable.

Thanks Tim, I did give that a try before my post:
image

In that screenshot, it appears you're converting from a string to datetime, but then trying to assign it to a boolean variable. As the error indicates, a datetime is not able to be cast to a value of true or false. You should either change the value of that variable to datetime or provide an expression that evaluates to a boolean.

Thanks Tim, I am not too sure how to get the time difference so that I can make a decision based on how long the oldest call has been waiting in the queue but I am having a go now.

I am a bit stuck. I have got the data action working as per @Jerome.Saint-Marc assistance. Are you able to assist me in creating the expression that will make a decision if the call is longer than 5 mins for example?

What part are you having trouble with? What have you tried so far?

Not sure if this is the correct way but I am currently using substring so that I can get the year, month, day, hour, min, seconds from the oldestTime output and insert them in individual variables to try use them in the DateTimeDiff() function.

Hi @tim.smith

Apologies, but do you know how to convert the output from "2022-06-13T21:35:43.272Z" to the following format 2022, 6, 1, 7, 17, 14, 821000?

Thank you.

Hello,

After your "Call Data Action", on the Success output, you should add a "Decision" block to check if you have calls waiting or not.
If not (Task.callsWaiting equal to 0), the Task.oldestTime would be an empty string - max duration = 0.

Regarding the test on duration:

You can use an "Update Data" block, and add an update statement with a variable of type Duration (e.g. Task.OldestDuration). For this statement, define the value as an expression: DateTimeDiff(GetCurrentDateTimeUtc(), ToDateTime(Task.oldestTime))

You can then use a "Decision" block to compare this to the duration you want - using an Expression like the following to check if the duration is greater than 5 minutes: Task.OldestDuration > MakeDuration(0,0,5,0)
MakeDuration -> day, hour, minute, second

Regards,

1 Like