Hi, everyone!
Might someone take a look at this and spot my mistake?
What this is, is SAP's example preferred agent IVR customized to check a list of queues instead of checking just one or every queue:
# coding=latin-1
from __future__ import with_statement
import VER
VER.VER(__file__, """
Company: SAP
Filename: PreferredAgentCustomizer.py
Description: Custom method(s) for finding a preferred agent for the call.
Created: 08.04.2014
Modified: -
""", '1.0.0.0')
from Env import *
from ICustomize import *
from CEMODBC import ODBCConnection
from SBTools import AGENT, QUEUE
from Tools import TRIM_SQL, makefilter
class PreferredAgentCustomizer(ICustomize): # ======================================================================== def __init__(self, AppConf): # Call the base class constructor ICustomize.__init__(self, AppConf) # ======================================================================== def FindPreferredAgent(self, params): """ Find a preferred agent for current call. <params> is a dictionary containing the parameters passed in from the application, plus a reference to the application's state machine, available with key "SM". Parameters: MonitoringHistoryDSN : string : Monitoring History database connection string ANumber : string : Alternative a-number to be used in search - if not given, SM.CALL["ANumber"] is used by default QueueID : string : Only search previous contacts from this queue (optional) MaxContactAge : int : Maximum age (in seconds) for the previous contact - if not given, a value corresponding 30 days is used by default Returns: Extension number of the preferred agent, or None if the agent was not found. """ try: SM = params['SM'] dsn = params['MonitoringHistoryDSN'] if not SM: raise RuntimeError('Invalid value for mandatory parameter [SM]: [%s]' % SM) number = params.get('ANumber', SM.CALL['ANumber']) queueIDs = params.get('QueueID') queueIDs = queueIDs.split() maxAge = params.get('MaxContactAge', 60 * 60 * 24 * 30) if not dsn: # We need Monitoring History database connection string in order to continue raise RuntimeError('Invalid value for mandatory parameter [MonitoringHistoryDSN]: [%s]' % dsn) # Perform rudimentary caller number validation number = makefilter('0123456789')(None, number) if not (len(number) >= 3 and number != 'CLIR'): WRN('PreferredAgentCustomizer.FindPreferredAgent : Cannot search using caller number [%s]' % number) else: if queueIDs: # Validate the given queue identifier for queue in queueIDs: raise RuntimeError('%s' % queue) exists = QUEUE.FIND(queue, None, None) if not exists: raise RuntimeError('Queue with identifier [%s] not found' % queue) # Replace possible queue extension number with queue GUID # queueID = queue['GUID'] # Try resolving the user GUID of the agent who most recently answered the call from <number> userGUID = self._DoFindAgent(dsn, number, maxAge, queueIDs) if userGUID: # Validate the user GUID against CEM's agent store agent = AGENT.FIND(userGUID, 'USER_GUID', None) if agent: # The agent is still known by CEM: return her extension number result = agent.NUMBER else: # The agent (user) has probably been deleted from the system... WRN('PreferredAgentCustomizer.FindPreferredAgent : User [%s] not found' % userGUID) except Exception, err: EXC('PreferredAgentCustomizer.FindPreferredAgent : %s' % str(err)) return 'ERROR' SAFE('PreferredAgentCustomizer.FindPreferredAgent : OK') return ('OK', result)
# ======================================================================== c_SQL = \ TRIM_SQL(""" SELECT TOP 1 [Value1] AS [UserGUID] FROM [TAContactLog] cl WITH(NOLOCK) INNER JOIN [TAContactLogDetail] cld WITH(NOLOCK) ON cld.[ContactLogGUID] = cl.[GUID] WHERE cl.[Source] LIKE ? AND cl.[QueueGUID] <> ? %s AND cld.[Event] = 'ConnectedToOper' AND cld.[TimeStamp] >= DATEADD(ss, ?, GETUTCDATE()) ORDER BY cl.[TimeStamp] DESC""") def _DoFindAgent( self, monitoringHistoryDSN, callerNumber, maxSecondsSinceLastContact, queueIDs, ): """ Perform the agent search in Monitoring History database. Note that direct calls are excluded from the search -- in order to include them, remove the first AND condition from the query and the corresponding parameter value (Env.c_OperDirectName) from the statement parameter list. """ result = None if len(callerNumber) > 8: # Search using last 8 characters callerNumber = '%%%s' % callerNumber[-8:] if maxSecondsSinceLastContact > 0: maxSecondsSinceLastContact = -maxSecondsSinceLastContact # Connect to database connection = ODBCConnection(GUID(), self.m_E, monitoringHistoryDSN) # Prepare the SQL statement and run the query query = self.c_SQL % (" AND cl.[QueueGUID] IN (") for queue in queueIDs: query = self.c_SQL % (("'%s'," % queue if queue else '')) query = query[:-1] query = self.c_SQL % (")") parameters = (callerNumber, Env.c_OperDirectName, maxSecondsSinceLastContact) resultset = connection.execute(query, parameters) if resultset is not None and len(resultset): result = resultset['UserGUID'] return result
I've not yet tested if it works (so there might be logic errors), since every time I activate it I'm greeted with the following error:
12:51:15.577 (03672/RelThr:POLL_ChangeTrack) ERR> [EXC] : ImportCustomizer : Exception : '5F75F7DC-FFA2-4991-B652-909A9CCC0CF7'
12:51:15.577 (03672/RelThr:POLL_ChangeTrack) ERR> <type 'exceptions.KeyError'> : 'PreferredAgentCustomizer_queues'
12:51:15.577 (03672/RelThr:POLL_ChangeTrack) ERR> File: .\ConfMultiAppl.py (3359) Func: ImportCustomizer <None>
This seems to indicate that some dictionary is missing the key that is currently being requested. Which dictionary - I have no idea ![]()
I'm also quite stuck since I'm currently having a hard time thinking outside the box.
So, once again, could anyone take a look at this with a different angle and point out what causes the KeyError?
Best wishes,
Jaanus