Two Days of Innovation and Insights at Enterprise Connect 2024: A Personal Overview

I was saddened that I could only do 2 days at EC24, but those 2 days were jam-packed. Here’s recap of what I saw and some thoughts on the some specific vendor announcements I got a chance to hear on the stage and see on the expo floor.

Overall Recap

This year brought a nice change to some of the main stage sessions with both vendors and customers sharing the stage. This added a nice dynamic to the conversation and helped balance some things out. In one of the sessions while all the vendors were saying single vendor is best a customer said the total opposite. The flip side of this is that some times the stage looked like a public school classroom with the number of people on stage. There were too many panelist and not enough time to really dive deeper into any one topic. Maybe break up the sessions to separate topics to avoid this.

It was interesting to hear that large orgs have task forces convened around how AI could be applied to their business. Sounds like use cases are brought to them and they assess the merits of using AI and put together a plan. While this all sounds like a great idea, instead of jumping head first and sprinkling AI on everything, I do wonder how much education and knowledge these tasks forces actually have. Is AI consulting a thing now? I suspect it is.

Burnout was a bigger talking point than the crunch on the potential employee pool size. While no one outright said that jobs will be eliminated, the reality is that they will. If you can reduce workload by a percentage, then there’s no reason why you couldn’t reduce your workforce by a similar amount. While we talk about cross skilling and shifting agents to do other tasks, I wonder how much that really happens. I suspect it might be easier to just hire for the new role than try to train up. Of course this is not universal, but if even half of these AI promises come through we will see a large number of agent seats evacuated. The burnout message didn’t seem aligned with what I project how AI will impact employment in the next 5-10 years.

AI dominated every session I attended and while I understand why it really felt like the same use cases over and over again. While I am sure it’s hard to come up with truly revolutionary use cases it does feel very repetitive seeing the same use case over and over again from all the vendors. It was also interesting to not see Edify be an exhibitor I wonder if this is a signal to how they are doing business wise, anyone know?

Vendor Specific Recap:

Microsoft

Live Keynote Recap: https://www.linkedin.com/posts/dmacias_enterpriseconnect-activity-7178398994623078400-YD-c?utm_source=share&utm_medium=member_desktop

I was expecting MS to open the floor with Copilot, then go into the demos with more Copilot, and finally bring it home with Copilot. However, this was not the case. The first part of their keynote was focused on hybrid work, which is a message that Cisco has been carrying for a few years.  Intelligent recap for phone calls was very cool and then being able to have Copilot use other assets and share outputs from the conversation with others was very cool. The voice isolation demo was a bit rough. I wonder if this is because MS has to do it all on software (Teams) while Cisco demos this on hardware.

The new to me Teams Queue App was of most interest to me. This is the greatest thread to every CCaaS provider out there. The introduction of the Queues App is the first clear signal of a native contact center like feature and while the person who gave me the demo of this feature said 3 times that “this is not a call center”, it sure smelled like a call center to me. Having an agent and supervisor view, ability to queue voicemails, ability to monitor agents and take over calls, and access to raw data make this feature very compelling and a no brainier to deploy if you want to keep everything on Teams. If I was a vendor that has bolted on contact center functionality on top of Teams I would be worried. Now, I really don’t think we’re going to see a full fledged contact center from MS next year, but I do think in the next 5 years they will finally be there and would have done it incrementally anchoring everything around Teams.

Cisco

Live Keynote Recap: https://www.linkedin.com/posts/dmacias_entepriseconnect-activity-7178417256744329217-WOUg?utm_source=share&utm_medium=member_desktop

The items that stood out were dropped call detection and summarization. Not sure if this is based on conversation context or PSTN signaling. It was also interesting to see Cisco talking about going beyond LLMs to what they called real time media model (RTMM). In short, giving AI other dimensions to make decisions. Their noise suppression demo was much better’s than Microsoft’s, but their noise was being produced by toys which had repetitive audio which might be much easier to filter out as well as the fact that they own the hardware which could allow for better suppression all around. Finally, Cisco still has some of the most attractive hardware out there. Their designs are just slick and the release of the 9800 (https://www.webex.com/us/en/devices/phone-series/cisco-phone-9800-series.html) phone continues that trend.

Zoom

I was not there for the Zoom keynote, but I did sit down on one of the expo sessions and went to the floor to bug them about what all they were releasing. First, VM transcription feature was pretty cool. The ability to automatically crate tasks from the content and have the system automatically bring certain VMs to the top for immediate attention. One feature I had not seen before and I believe is new is email routing, which is something none of the other big players are doing natively. Finally, licensing seems very straightforward and easy to understand… looking at your MS.

2020 Cisco Forums Profile

It’s nice to be recognized

I got a nice surprise in my inbox today. An email from Cisco letting me know that I was the first ever winner of the English Community Developer of the Month. Per Cisco the Community Spotlight Awards:

… recognizes members whose significant contributions designate leadership and commitment to their peers within their respective communities, including the Cisco Learning Network (CLN) and Cisco Community. Spotlight Awards Program is designed to recognize and thank individuals who help make our communities the premier online destination for Cisco enthusiasts.

I get a cool badge to show off too.

2020 Cisco Forums Profile

2020 Cisco Forums Profile

You can find current and past winners here or try to spot me in the picture below.

Current Spotlight Winners

Current Spotlight Winners

Looking back through my blog posts in 2008 I talked about getting my first star due to my contributions in the Cisco NetPro forums and how happy I was about it. In that blog I have a picture of my profile showing a total of 103 posts made with 8 questions resolved. That number, 12 years later, has ballooned to 3030 posts and 208 solutions.

I encourage anyone starting out or a seasoned veteran to contribute in the various Cisco Communities it’s a great way to network with your Cisco peers and try to tackle some very interesting technical problems while you procrastinate from your not as interesting technical problems.

~david

Cisco Finesse Desktop Tabs for Supervisors

This came up on this thread and figured I would post something about it is an easy mistake. The Finesse layout is devided into an Agent and Supervisor section. So adding a tab to the top of the default layout will only add it to the Agent view. You can tell the layouts apart by the following tags:

<layout>
    <role>Agent</role>
    <page>

</layout>

or

<layout>
    <role>Supervisor</role>
    <page>
</layout>

~david

Add Connection Profiles to Cisco AnyConnect Secure Mobility Client

I enjoy the new VPN client, it’s small and fast, however I hated that you can’t save profiles in the drop down list like you could in the traditional VPN client.

VPNNoProfile

This has been bothering for a long time and kept finding conflicting information on if this was possible or not. Finally got it to work.

VPNProfiles

This is for version 3.1x and Windows 7 let me know if this works for your version and OS.

  • Create a preferences.xml file in C:\ProgramData\Cisco\Cisco AnyConnect Secure Mobility Client\Profile\
  • Use this format

<?xml version="1.0" encoding="UTF-8"?>

<AnyConnectProfile xmlns="http://schemas.xmlsoap.org/encoding/">
<ServerList>
     <HostEntry>
          <User>dclouduser</User>
          <SecondUser></SecondUser>
          <ClientCertificateThumbprint></ClientCertificateThumbprint>
          <ServerCertificateThumbprint></ServerCertificateThumbprint>
          <HostName>dCloud</HostName>
          <HostAddress>dcloud-rtp-anyconnect.cisco.com</HostAddress>
          <Domain></Domain>
          <Group>ssl_url</Group>
          <ProxyHost></ProxyHost>
          <ProxyPort></ProxyPort>
          <SDITokenType>none</SDITokenType>
          <ControllablePreferences>
          <LocalLanAccess>true</LocalLanAccess></ControllablePreferences>
     </HostEntry>

     <HostEntry>
          <User>dmacias</User>
          <SecondUser></SecondUser>
          <ClientCertificateThumbprint></ClientCertificateThumbprint>
          <ServerCertificateThumbprint></ServerCertificateThumbprint>
          <HostName>Speech-Soft</HostName>
          <HostAddress>vpn.dmacias.com</HostAddress>
          <Domain></Domain>
          <Group>ssl_url</Group>
          <ProxyHost></ProxyHost>
          <ProxyPort></ProxyPort>
          <SDITokenType>none</SDITokenType>
          <ControllablePreferences>
          <LocalLanAccess>true</LocalLanAccess></ControllablePreferences>
     </HostEntry>
</ServerList>

</AnyConnectProfile>

  • Save the file.
  • Restart the connectivity client.
  • Enjoy

~david

EDIT 01/18/2017: This also works with Cisco AnyConnect 4.x!

Cisco CUIC Creating Value Lists and Collections

This one should be pretty simple, but figure I would add it here for posterity’s sake.  I wanted to setup a real time Value List of all the call types, then break down my Value List into smaller Collections for each specific type of call type.

First step is to log in to CUIC and got to Value Lists and click on Create.

Untitled

The Value List Query:

SELECT Call_Type.CallTypeID AS ID, Call_Type.EnterpriseName AS VALUE FROM Call_Type (nolock) 
Order by Call_Type.EnterpriseName

The Collection Query:

SELECT Call_Type.CallTypeID AS ID, Call_Type.EnterpriseName AS VALUE FROM Call_Type (nolock) 
WHERE Call_Type.CustomerDefinitionID = (SELECT User_Group.CustomerDefinitionID FROM User_Group (nolock) 
WHERE UPPER(User_Group.UserGroupName) = UPPER(<COLLECTIONIDENTIFIER>)) OR (SELECT COUNT(User_Group.CustomerDefinitionID) 
FROM User_Group (nolock) WHERE UPPER(User_Group.UserGroupName) = UPPER(<COLLECTIONIDENTIFIER>)) = 0 ORDER BY Call_Type.EnterpriseName ASC

Validate your query and save.

Second, click on your Value List and click on Collections.

Untitled1

Notice the Collection Type of Wildcard which allows your create a wildcard which references all your call types.  This could be French* or CustomerService*.  Hit Save, Populate Values, and confirm the values to ensure the collection has the call types you’re looking for.

~dmacias

Cisco CUIC Real Time Agent Report with Not Ready Reason Code

I had my first exposure to CUIC last week and was glad to finally see this product and get to play with it.  For the most part it looks just like CUIS, except for the whole appliance model.  The UI is a little more streamlined, but what I remember from CUIS, it’s all there.  Now, one big change is that with CUIC, reports are cut down to a standard set (20 if I remember correctly) as opposed to the dozens of reports available through WebView.  This created some initial confusion as you try to familiarize yourself with what kind of data the new reports have.  Perhaps the best feature is the ability to remove columns from reports and just display the data you want to see.

One report which comes up all the time is an agent real time report showing the agent’s current not ready reason code.  I have an SQL query I use to get this data myself, but now that CUIC is supposed to make it easier to create your own reports, I wanted to give it a shot and create my very first custom report.

First, let’s start with the SQL query which joins the real time agent states as well as reason code tables.

   1:  SELECT [awdb].[dbo].[t_Agent_Real_Time].[SkillTargetID]
   2:          ,[awdb].[dbo].[t_Agent].[EnterpriseName]
   3:        ,[DateTime]
   4:        ,[SkillGroupSkillTargetID]
   5:        ,[ServiceSkillTargetID]
   6:        ,[AgentState]
   7:        ,'Agent State' =
   8:              CASE
   9:                    WHEN [AgentState] = 2 THEN 'Not Ready'
  10:                    WHEN [AgentState] = 3 THEN 'Ready'
  11:                    WHEN [AgentState] = 4 THEN 'Talking'
  12:                    WHEN [AgentState] = 5 THEN 'Wrap Up'
  13:              END
  14:        ,[awdb].[dbo].[t_Agent_Real_Time].[ReasonCode]
  15:        ,[awdb].[dbo].[t_Reason_Code].[ReasonText]
  16:        ,[Extension]
  17:        ,[DateTimeLastStateChange]
  18:    FROM [awdb].[dbo].[t_Agent_Real_Time] 
  19:    JOIN [awdb].[dbo].[t_Reason_Code] ON ([awdb].[dbo].[t_Agent_Real_Time].[ReasonCode]=[awdb].[dbo].[t_Reason_Code].[ReasonCode])
  20:    JOIN [awdb].[dbo].[t_Agent] ON [awdb].[dbo].[t_Agent_Real_Time].[SkillTargetID] = [awdb].[dbo].[t_Agent].[SkillTargetID]
  21:  GO

Now, don’t judge me on a) the poor SQL writing skills or b) my affinity to spacing.  It’s important to understand what the above query is doing to ensure you know where your reason codes are coming from.

Second, you will need to create a new report definition based on the stock Agent Real Time report definition.  You will need to extract the SQL of the report query shown below.

SELECT Agent.EnterpriseName, full_name=(Person.LastName + ‘, ‘ + Person.FirstName) , Skill_Group.EnterpriseName as SkillName, Agent.SkillTargetID, Agent_Real_Time.DateTime, Datepart(yy, Agent_Real_Time.DateTime) as Year, Datepart(mm, Agent_Real_Time.DateTime) as Month, Datepart(ww, Agent_Real_Time.DateTime) as Week, Datepart(dy, Agent_Real_Time.DateTime) as DOY, Datepart(dw, Agent_Real_Time.DateTime) as DOW, CONVERT(char(10),Agent_Real_Time.DateTime,101) as DATE, Agent_Real_Time.SkillGroupSkillTargetID, ServiceName = Service.EnterpriseName, Media = Media_Routing_Domain.EnterpriseName, CASE Agent_Real_Time.AgentState WHEN 0 THEN ‘Logged Out’ WHEN 1 THEN ‘Logged On’ WHEN 2 THEN ‘Not Ready’ WHEN 3 THEN ‘Ready’ WHEN 4 THEN ‘Talking’ WHEN 5 THEN ‘Work Not Ready’ WHEN 6 THEN ‘Work Ready’ WHEN 7 THEN ‘Busy Other’ WHEN 8 THEN ‘Reserved’ WHEN 9 THEN ‘Unknown’ WHEN 10 THEN ‘Hold’ WHEN 11 THEN ‘Active’ WHEN 12 THEN ‘Paused’ WHEN 13 THEN ‘Interrupted’ WHEN 14 THEN ‘Not Active’ ELSE CONVERT(VARCHAR, Agent_Real_Time.AgentState) END AgentState, CASE Agent_Real_Time.PhoneType When 0 THEN ‘Not Mobile’ WHEN 1 THEN ‘Call By Call’ WHEN 2 THEN ‘Nailed Connection’ Else ‘Not Applicable’ END phonetypetext, remotephonenumber = Agent_Real_Time.RemotePhoneNumber, ReasonCode = CASE WHEN Agent_Real_Time.ReasonCode = 0 THEN ‘NONE’ ELSE CONVERT(VARCHAR, Agent_Real_Time.ReasonCode) END , Agent_Real_Time.Extension, Agent_Real_Time.DateTimeLastStateChange, Agent_Real_Time.DateTimeLogin, CASE WHEN RequestedSupervisorAssist = 1 THEN ‘Yes’ ELSE ‘No’ END RequestedSupervisorAssist, CASE Agent_Real_Time.Destination WHEN 1 THEN ‘ACD’ WHEN 2 THEN ‘Direct’ WHEN 3 THEN ‘Auto Out’ WHEN 4 THEN ‘Reserve’ WHEN 5 THEN ‘Preview’ ELSE ‘Not Applicable’ END Destination, CASE Agent_Real_Time.Direction WHEN 1 THEN ‘In’ WHEN 2 THEN ‘Out’ WHEN 3 THEN ‘Other’ ELSE ‘Not Applicable’ END Direction, CASE WHEN Agent_Real_Time.OnHold = 1 THEN ‘Yes’ ELSE ‘No’ END OnHold, Agent_Real_Time.NetworkTargetID, Agent_Real_Time.AgentStatus, Agent_Real_Time.CustomerPhoneNumber, Agent_Real_Time.CustomerAccountNumber, Agent_Real_Time.CampaignID, Agent_Real_Time.QueryRuleID, Duration = DATEDIFF(ss, Agent_Real_Time.DateTimeLastStateChange, CASE WHEN (DATEDIFF(ss, Agent_Real_Time.DateTimeLastStateChange, (SELECT NowTime from Controller_Time (nolock))) <= 0 ) THEN Agent_Real_Time.DateTimeLastStateChange ELSE(SELECT NowTime FROM Controller_Time (nolock)) END), CASE WHEN Agent_Real_Time.Routable = 1 THEN ‘Yes’ ELSE ‘No’ END RoutableText,Agent_Real_Time.DateTimeLastModeChange, Agent_Real_Time.CallInProgress, Agent_Real_Time.MaxTasks, CASE WHEN Agent_Real_Time.AvailableInMRD = 0 THEN ‘No’ WHEN Agent_Real_Time.AvailableInMRD = 1 THEN ‘Yes_ICM’ WHEN Agent_Real_Time.AvailableInMRD = 2 THEN ‘Yes_APP’ ELSE ‘No’ END AvailInMRDText, Agent_Real_Time.DateTimeTaskLevelChange, Agent_Real_Time.RouterCallsQueueNow, Agent_Real_Time.RouterLongestCallQ FROM Agent (nolock), Person (nolock), Media_Routing_Domain (nolock), Agent_Real_Time (nolock) LEFT JOIN Service (nolock) ON Agent_Real_Time.ServiceSkillTargetID = Service.SkillTargetID, Skill_Group WHERE ( Agent_Real_Time.SkillGroupSkillTargetID = Skill_Group.SkillTargetID) and Agent.PersonID=Person.PersonID and Media_Routing_Domain.MRDomainID = Agent_Real_Time.MRDomainID and ( Agent.SkillTargetID = Agent_Real_Time.SkillTargetID ) UNION SELECT Agent.EnterpriseName, full_name=(Person.LastName + ‘, ‘ + Person.FirstName) , convert(varchar,’Not Applicable’), Agent_Real_Time.SkillTargetID, Agent_Real_Time.DateTime, Datepart(yy, Agent_Real_Time.DateTime) as Year, Datepart(mm, Agent_Real_Time.DateTime) as Month, Datepart(ww, Agent_Real_Time.DateTime) as Week, Datepart(dy, Agent_Real_Time.DateTime) as DOY, Datepart(dw, Agent_Real_Time.DateTime) as DOW, CONVERT(char(10),Agent_Real_Time.DateTime,101) as DATE, Agent_Real_Time.SkillGroupSkillTargetID, ServiceName = Service.EnterpriseName, Media=Media_Routing_Domain.EnterpriseName, CASE Agent_Real_Time.AgentState WHEN 0 THEN ‘Logged Out’ WHEN 1 THEN ‘Logged On’ WHEN 2 THEN ‘Not Ready’ WHEN 3 THEN ‘Ready’ WHEN 4 THEN ‘Talking’ WHEN 5 THEN ‘Work Not Ready’ WHEN 6 THEN ‘Work Ready’ WHEN 7 THEN ‘Busy Other’ WHEN 8 THEN ‘Reserved’ WHEN 9 THEN ‘Unknown’ WHEN 10 THEN ‘Hold’ WHEN 11 THEN ‘Active’ WHEN 12 THEN ‘Paused’ WHEN 13 THEN ‘Interrupted’ WHEN 14 THEN ‘Not Active’ ELSE CONVERT(VARCHAR, Agent_Real_Time.AgentState) END AgentState, CASE Agent_Real_Time.PhoneType When 0 THEN ‘Not Mobile’WHEN 1 THEN ‘Call By Call’ WHEN 2 THEN ‘Nailed Connection’ Else ‘Not Applicable’ END phonetypetext, remotephonenumber = Agent_Real_Time.RemotePhoneNumber, ReasonCode = CASE WHEN Agent_Real_Time.ReasonCode = 0 THEN ‘NONE’ ELSE CONVERT(VARCHAR, Agent_Real_Time.ReasonCode) END , Agent_Real_Time.Extension, Agent_Real_Time.DateTimeLastStateChange, Agent_Real_Time.DateTimeLogin, CASE WHEN RequestedSupervisorAssist = 1 THEN ‘Yes’ ELSE ‘No’ END RequestedSupervisorAssist, CASE Agent_Real_Time.Destination WHEN 1 THEN ‘ACD’ WHEN 2 THEN ‘Direct’ WHEN 3 THEN ‘Auto Out’ WHEN 4 THEN ‘Reserve’ WHEN 5 THEN ‘Preview’ ELSE ‘Not Applicable’ END Destination, CASE Agent_Real_Time.Direction WHEN 1 THEN ‘In’ WHEN 2 THEN ‘Out’ WHEN 3 THEN ‘Other’ ELSE ‘Not Applicable’ END Direction, CASE WHEN Agent_Real_Time.OnHold = 1 THEN ‘Yes’ ELSE ‘No’ END OnHold, Agent_Real_Time.NetworkTargetID, Agent_Real_Time.AgentStatus, Agent_Real_Time.CustomerPhoneNumber, Agent_Real_Time.CustomerAccountNumber, Agent_Real_Time.CampaignID, Agent_Real_Time.QueryRuleID, Duration=DATEDIFF(ss, Agent_Real_Time.DateTimeLastStateChange, CASE WHEN (DATEDIFF(ss, Agent_Real_Time.DateTimeLastStateChange, (SELECT NowTime from Controller_Time (nolock))) <= 0 ) THEN Agent_Real_Time.DateTimeLastStateChange ELSE (SELECT NowTime FROM Controller_Time (nolock)) END), CASE WHEN Agent_Real_Time.Routable = 1 THEN ‘Yes’ ELSE ‘No’ END RoutableText , Agent_Real_Time.DateTimeLastModeChange, Agent_Real_Time.CallInProgress, Agent_Real_Time.MaxTasks, CASE WHEN Agent_Real_Time.AvailableInMRD = 0 THEN ‘No’ WHEN Agent_Real_Time.AvailableInMRD = 1 THEN ‘Yes_ICM’ WHEN Agent_Real_Time.AvailableInMRD = 2 THEN ‘Yes_APP’ ELSE ‘No’ END AvailInMRDText, Agent_Real_Time.DateTimeTaskLevelChange, Agent_Real_Time.RouterCallsQueueNow, Agent_Real_Time.RouterLongestCallQ FROM Agent (nolock), Person (nolock), Media_Routing_Domain (nolock), Agent_Real_Time (nolock) LEFT JOIN Service (nolock) ON Agent_Real_Time.ServiceSkillTargetID = Service.SkillTargetID WHERE ((Agent_Real_Time.SkillGroupSkillTargetID = 0) OR (Agent_Real_Time.SkillGroupSkillTargetID IS NULL)) and Agent.PersonID=Person.PersonID and Media_Routing_Domain.MRDomainID = Agent_Real_Time.MRDomainID and ( Agent.SkillTargetID = Agent_Real_Time.SkillTargetID )

Third, modify the SQL query.  Also, it helps a lot to actually arrange the above query and break it down section by section.

 

   1:   
   2:  SELECT 
   3:                  Agent.EnterpriseName, 
   4:                  full_name=(Person.LastName + ', ' + Person.FirstName), 
   5:                  Skill_Group.EnterpriseName as SkillName, 
   6:                  Agent.SkillTargetID, 
   7:                  Agent_Real_Time.DateTime, 
   8:                  Datepart(yy, Agent_Real_Time.DateTime) as Year, 
   9:                  Datepart(mm, Agent_Real_Time.DateTime) as Month, 
  10:                  Datepart(ww, Agent_Real_Time.DateTime) as Week, 
  11:                  Datepart(dy, Agent_Real_Time.DateTime) as DOY, 
  12:                  Datepart(dw, Agent_Real_Time.DateTime) as DOW, 
  13:                  CONVERT(char(10),Agent_Real_Time.DateTime,101) as DATE, Agent_Real_Time.SkillGroupSkillTargetID, 
  14:                  ServiceName = Service.EnterpriseName, 
  15:                  Media = Media_Routing_Domain.EnterpriseName, 
  16:                  CASE Agent_Real_Time.AgentState  
  17:                                  WHEN 0 THEN 'Logged Out' 
  18:                                  WHEN 1 THEN 'Logged On' 
  19:                                  WHEN 2 THEN 'Not Ready' 
  20:                                  WHEN 3 THEN 'Ready' 
  21:                                  WHEN 4 THEN 'Talking' 
  22:                                  WHEN 5 THEN 'Work Not Ready' 
  23:                                  WHEN 6 THEN 'Work Ready' 
  24:                                  WHEN 7 THEN 'Busy Other' 
  25:                                  WHEN 8 THEN 'Reserved'  
  26:                                  WHEN 9 THEN 'Unknown' 
  27:                                  WHEN 10 THEN 'Hold' 
  28:                                  WHEN 11 THEN 'Active'  
  29:                                  WHEN 12 THEN 'Paused' 
  30:                                  WHEN 13 THEN 'Interrupted' 
  31:                                  WHEN 14 THEN 'Not Active' 
  32:                                  ELSE CONVERT(VARCHAR, Agent_Real_Time.AgentState) 
  33:                  END AgentState, 
  34:                  CASE Agent_Real_Time.PhoneType 
  35:                                  When 0 THEN 'Not Mobile' 
  36:                                  WHEN 1 THEN 'Call By Call' 
  37:                                  WHEN 2 THEN 'Nailed Connection' 
  38:                                  Else 'Not Applicable' 
  39:                  END phonetypetext, 
  40:                  remotephonenumber = Agent_Real_Time.RemotePhoneNumber, 
  41:                  ReasonCode = CASE 
  42:                                  WHEN Agent_Real_Time.ReasonCode = 0 
  43:                                  THEN 'NONE' 
  44:                                  ELSE CONVERT(VARCHAR, Agent_Real_Time.ReasonCode) 
  45:                                  END , 
  46:                  Reason_Code.ReasonText,
  47:                  Agent_Real_Time.Extension, 
  48:                  Agent_Real_Time.DateTimeLastStateChange, 
  49:                  Agent_Real_Time.DateTimeLogin, 
  50:                  CASE 
  51:                                  WHEN RequestedSupervisorAssist = 1 THEN 'Yes' ELSE 'No' 
  52:                  END RequestedSupervisorAssist, 
  53:                  CASE Agent_Real_Time.Destination 
  54:                                  WHEN 1 THEN 'ACD' 
  55:                                  WHEN 2 THEN 'Direct' 
  56:                                  WHEN 3 THEN 'Auto Out' 
  57:                                  WHEN 4 THEN 'Reserve' 
  58:                                  WHEN 5 THEN 'Preview' 
  59:                                  ELSE 'Not Applicable' 
  60:                  END Destination, 
  61:                  CASE  Agent_Real_Time.Direction 
  62:                                  WHEN 1 THEN 'In' 
  63:                                  WHEN 2 THEN 'Out' 
  64:                                  WHEN 3 THEN 'Other' 
  65:                                  ELSE 'Not Applicable' 
  66:                  END Direction, 
  67:                  CASE 
  68:                                  WHEN Agent_Real_Time.OnHold = 1 THEN 'Yes' 
  69:                                  ELSE 'No' 
  70:                  END OnHold, 
  71:                  Agent_Real_Time.NetworkTargetID, 
  72:                  Agent_Real_Time.AgentStatus, 
  73:                  Agent_Real_Time.CustomerPhoneNumber, 
  74:                  Agent_Real_Time.CustomerAccountNumber, 
  75:                  Agent_Real_Time.CampaignID, 
  76:                  Agent_Real_Time.QueryRuleID, 
  77:                  Duration = DATEDIFF(ss, Agent_Real_Time.DateTimeLastStateChange, 
  78:                  CASE 
  79:                                  WHEN (DATEDIFF(ss, Agent_Real_Time.DateTimeLastStateChange, (SELECT NowTime from Controller_Time (nolock))) <= 0 ) 
  80:                                  THEN Agent_Real_Time.DateTimeLastStateChange 
  81:                                  ELSE(SELECT NowTime FROM Controller_Time (nolock)) 
  82:                  END), 
  83:                  CASE 
  84:                                  WHEN Agent_Real_Time.Routable = 1 
  85:                                  THEN 'Yes' ELSE 'No' 
  86:                  END RoutableText, 
  87:                  Agent_Real_Time.DateTimeLastModeChange, 
  88:                  Agent_Real_Time.CallInProgress, 
  89:                  Agent_Real_Time.MaxTasks, 
  90:                  CASE 
  91:                                  WHEN Agent_Real_Time.AvailableInMRD = 0 THEN 'No' 
  92:                                  WHEN Agent_Real_Time.AvailableInMRD = 1 THEN 'Yes_ICM' 
  93:                                  WHEN Agent_Real_Time.AvailableInMRD = 2 THEN 'Yes_APP' 
  94:                                  ELSE 'No' 
  95:                  END AvailInMRDText, 
  96:                  Agent_Real_Time.DateTimeTaskLevelChange, 
  97:                  Agent_Real_Time.RouterCallsQueueNow, 
  98:                  Agent_Real_Time.RouterLongestCallQ 
  99:  FROM 
 100:                  Agent (nolock), 
 101:                  Person (nolock), 
 102:                  Media_Routing_Domain (nolock), 
 103:                  Agent_Real_Time (nolock) LEFT JOIN Service (nolock) ON Agent_Real_Time.ServiceSkillTargetID = Service.SkillTargetID 
 104:                  JOIN Reason_Code ON Agent_Real_Time.ReasonCode = Reason_Code.ReasonCode,
 105:                  Skill_Group
 106:  WHERE ( Agent_Real_Time.SkillGroupSkillTargetID = Skill_Group.SkillTargetID) 
 107:                  and Agent.PersonID=Person.PersonID 
 108:                  and Media_Routing_Domain.MRDomainID = Agent_Real_Time.MRDomainID 
 109:                  and ( Agent.SkillTargetID = Agent_Real_Time.SkillTargetID ) 
 110:  UNION SELECT 
 111:                  Agent.EnterpriseName, 
 112:                  full_name=(Person.LastName + ', ' + Person.FirstName) , 
 113:                  convert(varchar,'Not Applicable'), 
 114:                  Agent_Real_Time.SkillTargetID, 
 115:                  Agent_Real_Time.DateTime, 
 116:                  Datepart(yy, Agent_Real_Time.DateTime) as Year, 
 117:                  Datepart(mm, Agent_Real_Time.DateTime) as Month, 
 118:                  Datepart(ww, Agent_Real_Time.DateTime) as Week, 
 119:                  Datepart(dy, Agent_Real_Time.DateTime) as DOY, 
 120:                  Datepart(dw, Agent_Real_Time.DateTime) as DOW, 
 121:                  CONVERT(char(10),Agent_Real_Time.DateTime,101) as DATE, 
 122:                  Agent_Real_Time.SkillGroupSkillTargetID, 
 123:                  ServiceName = Service.EnterpriseName, 
 124:                  Media=Media_Routing_Domain.EnterpriseName, 
 125:                  CASE 
 126:                                  Agent_Real_Time.AgentState 
 127:                                  WHEN 0 THEN 'Logged Out' 
 128:                                  WHEN 1 THEN 'Logged On' 
 129:                                  WHEN 2 THEN 'Not Ready' 
 130:                                  WHEN 3 THEN 'Ready' 
 131:                                  WHEN 4 THEN 'Talking' 
 132:                                  WHEN 5 THEN 'Work Not Ready' 
 133:                                  WHEN 6 THEN 'Work Ready' 
 134:                                  WHEN 7 THEN 'Busy Other' 
 135:                                  WHEN 8 THEN 'Reserved'  
 136:                                  WHEN 9 THEN 'Unknown' 
 137:                                  WHEN 10 THEN 'Hold' 
 138:                                  WHEN 11 THEN 'Active'  
 139:                                  WHEN 12 THEN 'Paused' 
 140:                                  WHEN 13 THEN 'Interrupted' 
 141:                                  WHEN 14 THEN 'Not Active' 
 142:                                  ELSE CONVERT(VARCHAR, Agent_Real_Time.AgentState) 
 143:                  END AgentState, 
 144:                  CASE 
 145:                                  Agent_Real_Time.PhoneType 
 146:                                  When 0 THEN 'Not Mobile'
 147:                                  WHEN 1 THEN 'Call By Call' 
 148:                                  WHEN 2 THEN 'Nailed Connection' 
 149:                                  Else 'Not Applicable' 
 150:                  END phonetypetext, 
 151:                  remotephonenumber = Agent_Real_Time.RemotePhoneNumber, 
 152:                  ReasonCode = 
 153:                  CASE 
 154:                                  WHEN Agent_Real_Time.ReasonCode = 0 THEN 'NONE' 
 155:                                  ELSE CONVERT(VARCHAR, Agent_Real_Time.ReasonCode) 
 156:                  END , 
 157:                  Reason_Code.ReasonText,
 158:                  Agent_Real_Time.Extension, 
 159:                  Agent_Real_Time.DateTimeLastStateChange, 
 160:                  Agent_Real_Time.DateTimeLogin, 
 161:                  CASE 
 162:                                  WHEN RequestedSupervisorAssist = 1 THEN 'Yes' 
 163:                                  ELSE 'No' 
 164:                  END RequestedSupervisorAssist, 
 165:                  CASE 
 166:                                  Agent_Real_Time.Destination 
 167:                                  WHEN 1 THEN 'ACD' 
 168:                                  WHEN 2 THEN 'Direct' 
 169:                                  WHEN 3 THEN 'Auto Out' 
 170:                                  WHEN 4 THEN 'Reserve' 
 171:                                  WHEN 5 THEN 'Preview' 
 172:                                  ELSE 'Not Applicable' 
 173:                  END Destination, 
 174:                  CASE  
 175:                                  Agent_Real_Time.Direction 
 176:                                  WHEN 1 THEN 'In' 
 177:                                  WHEN 2 THEN 'Out' 
 178:                                  WHEN 3 THEN 'Other' 
 179:                                  ELSE 'Not Applicable' 
 180:                  END Direction, 
 181:                  CASE 
 182:                                  WHEN Agent_Real_Time.OnHold = 1 THEN 'Yes' 
 183:                                  ELSE 'No' 
 184:                  END OnHold, 
 185:                  Agent_Real_Time.NetworkTargetID, 
 186:                  Agent_Real_Time.AgentStatus, 
 187:                  Agent_Real_Time.CustomerPhoneNumber, 
 188:                  Agent_Real_Time.CustomerAccountNumber, 
 189:                  Agent_Real_Time.CampaignID, 
 190:                  Agent_Real_Time.QueryRuleID, 
 191:                  Duration=DATEDIFF(ss, Agent_Real_Time.DateTimeLastStateChange, 
 192:                  CASE 
 193:                                  WHEN (DATEDIFF(ss, Agent_Real_Time.DateTimeLastStateChange, 
 194:                                  (SELECT NowTime from Controller_Time (nolock)))  <= 0 ) 
 195:                                  THEN Agent_Real_Time.DateTimeLastStateChange    
 196:                                  ELSE (SELECT NowTime FROM Controller_Time (nolock)) 
 197:                  END), 
 198:                  CASE 
 199:                                  WHEN Agent_Real_Time.Routable = 1 THEN 'Yes' 
 200:                                  ELSE 'No' 
 201:                  END RoutableText , 
 202:                  Agent_Real_Time.DateTimeLastModeChange, 
 203:                  Agent_Real_Time.CallInProgress, 
 204:                  Agent_Real_Time.MaxTasks, 
 205:                  CASE 
 206:                                  WHEN Agent_Real_Time.AvailableInMRD = 0 THEN 'No' 
 207:                                  WHEN Agent_Real_Time.AvailableInMRD = 1 THEN 'Yes_ICM' 
 208:                                  WHEN Agent_Real_Time.AvailableInMRD = 2 THEN 'Yes_APP' 
 209:                                  ELSE 'No' 
 210:                  END AvailInMRDText, 
 211:                  Agent_Real_Time.DateTimeTaskLevelChange, 
 212:                  Agent_Real_Time.RouterCallsQueueNow, 
 213:                  Agent_Real_Time.RouterLongestCallQ 
 214:                  FROM   
 215:                                  Agent (nolock), 
 216:                                  Person (nolock), 
 217:                                  Media_Routing_Domain (nolock), 
 218:                                  Agent_Real_Time (nolock) LEFT JOIN Service (nolock) ON Agent_Real_Time.ServiceSkillTargetID = Service.SkillTargetID
 219:                                  JOIN Reason_Code ON Agent_Real_Time.ReasonCode = Reason_Code.ReasonCode
 220:                  WHERE 
 221:                                  ((Agent_Real_Time.SkillGroupSkillTargetID = 0) OR (Agent_Real_Time.SkillGroupSkillTargetID IS NULL)) 
 222:                                  and Agent.PersonID=Person.PersonID
 223:                                  and Media_Routing_Domain.MRDomainID = Agent_Real_Time.MRDomainID 
 224:                                  and ( Agent.SkillTargetID = Agent_Real_Time.SkillTargetID )

Note line 46 and 104 where the join is made to retrieve the reason text.  Also note that you need to duplicate these lines in the Union Select statement.

Finally, create a new report definition, create a new report based off the definition, and test.  This posts assumes that you know at least the very basics around CUIC.  It doesn’t hurt to know some SQL, personally I know enough to be dangerous, but touch it so seldom that I’m no expert.

Hope this helps others out there as this is a pretty common report and a lot of customer ask for it.

~david

David gets a gold star (Cisco Support Community)!

I like to contribute a lot to Cisco’s NetPro Forums, now called Cisco Support Community.  I’ve been a member since 2005 and love the community since everyone seems to help everyone out a lot.  For this particular reason I feel inclined to give back as much as possible.  That being said, when you post a reply posters can give you points for how good your response was or how much it helped them.  So, that’s one way to get some recognition if you’re actually being helpful.

That being said, there are different levels based on how many points you’ve been awarded.  Just recently I reached the gold start level by surpassing 750 points.  While I still have a long way to go to catch some of the top contributors who are in the 10s of thousands of points, it does feel nice to hit a small milestone.

image

~dmacias

David get’s a silver badge

I try to stay involved with Cisco’s forum as to try to give back to the community a bit as well as trying to get some knowledge from the masses.  While I’m not a know it all it’s nice to have a little bit of recognition.  Last week i went from Bronze to Silver, which based on points others award you for the answers you provide. :-)

BadgesI have a long way to go before getting those 25k points… wonder if I could turn them in for cool Cisco gear?

~david

Frustrations with Cisco’s ICM Script Editor

So, I’ve been working with ICM scripts for what feels like ages, but in reality is more like 5 years. In the last 2 years though I spend more time scripting than anything else… well except documentation, but that’s another story.

Regardless, here are a few frustrations I constantly face when using ICM script editor.

1. No find and replace. This should be very easy to do and would help greatly, specially when working with CVP and you need to modify a VXML URL or when you’re working with formulas which need to be updated to include some new variable.

2. Copy and paste does not respect the fact that you’ve specified the Snap to Grid option. Yes, copy and paste rocks when you need to write a bunch of scripts which are similar, however, having to remember to snap your recently pasted script to the grid is a pain in the butt and I often forget it.

3. Call Tracer. Personally, I would like to see the call tracer as an independent window which can be sent to the back ground. If you’re working with a very small screen, you have to move the tracer around while looking at your script. In addition, the windows can be so much bigger by default. Can’t they just auto-size? See below.

ICM Script Editor Call Tracer

4. Formula Editor. Is there really no better way to display the formulas being written? Some of my formulas are pretty long which require that I writ them on TextPad first then move them to Script Editor. This allows me to lay them out a little better, specifically when trying to make sure I have enough parenthesis. For example, the formula below shows up like this:

(((ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerTo5,0))+(ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerTo5,0))+(ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerHalf,0))+(ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerHalf,0))+(ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerToday,0)))/((2*((ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerTo5,0))/(ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerTo5,1)))+(2*((ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerHalf,0))/(ValidValue(CallType._Sales_Q_International.AvgSpeedAnswerHalf,1))))+1))*
CallType._Sales_Q_International.RouterCallsQNow)>60

Surely, there’s a better way to display this.

One thing I miss about Genesys is their slick UIs and Cisco knows nothing about UIs. Hope to see some changes in the future, but I wouldn’t bet on it.

~dmacias