#include "StdAfx.h" #include "Agent.h" #include "Config.h" #include "SLogic.h" #include "AcdCore.h" #include "MsgCenter.h" #include "NetworkAcd.h" CAgent::CAgent(UINT a_AgentID, UINT a_ExtID, LPCTSTR a_GroupID, UINT a_AgentType, UINT a_PostProcessingTime) { // 网络属性 CNetworkAcd::GetInstance().getAgentLinkInfo(a_AgentID, m_AgentIp, m_AgentPort); // 基本属性 m_AgentID = a_AgentID; m_Exten = a_ExtID; m_GroupID = a_GroupID; m_AgentType = (AGENT_TYPE)a_AgentType; m_State = AGENT_STATE_UNKNOWN; m_AssoExtState = INNER_STATE_FREE; m_IsRepose = false; // 业务属性 m_AnswerCount = 0; m_ReposeCount = 0; m_TimeFree = 0; m_TimeRepos = 0; m_TimeTalk = 0; m_TimePostProcessing = (a_PostProcessingTime == 0) ? CConfig::postProcessingTime() : a_PostProcessingTime; // 定时器初始化 m_PollTimer.SetTimedEvent(this, &CAgent::__onTimerPoll); m_PollTimer.Start(1000); // 通知统计模块座席签入 __reportLogin(); // 添加消息可供视图刷新 CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (const PARAM)m_AgentID); } CAgent::~CAgent(void) { m_PollTimer.StopSafely(); m_AgentTimer.StopSafely(); } /***************************************************************** **【函数名称】 __reportLogin **【函数功能】 签出统计通知 **【参数】 **【返回值】 ****************************************************************/ void CAgent::__reportLogin() { // 通知统计模块 REP_EVENT_LOGIN T_EvtLogIn repLogin = { 0 }; repLogin.nAgentID = m_AgentID; repLogin.nExtID = m_Exten; repLogin.nAgentType = m_AgentType; lstrcpy(repLogin.szGroup, m_GroupID); lstrcpy(repLogin.szAgentIP, m_AgentIp); CSLogic::GetInstance().onSEvent(m_AgentID, REP_EVENT_LOGIN, &repLogin); } /***************************************************************** **【函数名称】 __reportLogout **【函数功能】 签出统计通知 **【参数】 HostAgent: 签出当前座席的主控座席 **【返回值】 ****************************************************************/ void CAgent::__reportLogout( const UINT HostAgent ) { if(m_State == AGENT_STATE_REPOSE ) __onStatusUpdate(AGENT_STATE_REPOSE, false); if( m_State == AGENT_STATE_POST_PROCESSING ) __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false); // 通知统计模块 REP_EVENT_LOGOUT T_EvtLogout repLogout = { 0 }; repLogout.nLogoutHost = HostAgent; repLogout.nTimeFree = m_TimeFree; repLogout.nTimeRepose = m_TimeRepos; repLogout.nTimeTalk = m_TimeTalk; repLogout.nAnswerCount = m_AnswerCount; repLogout.nReposeCount = m_ReposeCount; CSLogic::GetInstance().onSEvent(m_AgentID, REP_EVENT_LOGOUT, &repLogout); } /***************************************************************** **【函数名称】 __onStatusUpdate **【函数功能】 座席状态变更通知 **【参数】 **【返回值】 ****************************************************************/ void CAgent::__onStatusUpdate( AGENT_STATE State, bool StartFlag ) { T_EvtStatus EvtStatus; EvtStatus.State = State; EvtStatus.StartFlag = StartFlag; CSLogic::GetInstance().onSEvent(m_AgentID, REP_EVENT_STATE, &EvtStatus); } /***************************************************************** **【函数名称】 __reportStatus **【函数功能】 通知各方座席当前状态 **【参数】 **【返回值】 ****************************************************************/ void CAgent::__reportStatus( void ) { // 通知OCX座席当前状态 CPduEntity Cmd(PDU_CMD_ACD_AGENT_STATE); Cmd.SetDataUInt(0, m_Exten); Cmd.SetDataUInt(1, m_AgentID); Cmd.SetDataUInt(2, m_State); CNetworkAcd::GetInstance().send2Agent(m_AgentID, &Cmd); // 添加消息可供视图刷新 CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (PARAM)m_AgentID); } /***************************************************************** **【函数名称】 __onTimerPoll **【函数功能】 轮询定时器处理 **【参数】 **【返回值】 ****************************************************************/ void CAgent::__onTimerPoll( void ) { if(m_State == AGENT_STATE_FREE) m_TimeFree++; else if(m_State == AGENT_STATE_BUSY) m_TimeTalk++; if(m_IsRepose) m_TimeRepos++; } /***************************************************************** **【函数名称】 __onTimerPostProcessing **【函数功能】 话后处理时长定时器处理 **【参数】 **【返回值】 ****************************************************************/ void CAgent::__onTimerPostProcessing( void ) { if(m_State == AGENT_STATE_POST_PROCESSING) { setState(AGENT_STATE_FREE); } } /***************************************************************** **【函数名称】 __onTimerLock **【函数功能】 座席被锁定超时处理 **【参数】 **【返回值】 ****************************************************************/ void CAgent::__onTimerLock( void ) { if(m_State == AGENT_STATE_REQUESTED) { setState(AGENT_STATE_FREE, true); } } /***************************************************************** **【函数名称】 __setTimer **【函数功能】 设立定时器 **【参数】 **【返回值 ****************************************************************/ void CAgent::__setTimer( UINT TimmerId, UINT Elapse ) { if(TimmerId == TIMER_POST_PROCESSING) { m_AgentTimer.StopSafely(); m_AgentTimer.SetTimedEvent(this, &CAgent::__onTimerPostProcessing); m_AgentTimer.Start(Elapse, false, true, WT_EXECUTEDEFAULT); } else if(TimmerId == TIMER_LOCK_PERIOD) { m_AgentTimer.StopSafely(); m_AgentTimer.SetTimedEvent(this, &CAgent::__onTimerLock); m_AgentTimer.Start(Elapse, false, true, WT_EXECUTEDEFAULT); } else { ASSERT(FALSE); } } /***************************************************************** **【函数名称】 __killTimer **【函数功能】 删除定时器 **【参数】 **【返回值 ****************************************************************/ void CAgent::__killTimer( UINT TimmerId ) { m_AgentTimer.Stop(); } /***************************************************************** **【函数名称】 release **【函数功能】 清理资源 **【参数】 HostAgent: 主控制坐席工号 **【返回值】 ****************************************************************/ void CAgent::release( UINT HostAgent ) { m_PollTimer.StopSafely(); m_AgentTimer.StopSafely(); // 设置状态为注销 setState(AGENT_STATE_LOGOUT); // 通知统计模块 REP_EVENT_LOGOUT __reportLogout(HostAgent); // 关闭Agent端SOCKET连接 CNetworkAcd::GetInstance().shutDownAgentLink(m_AgentID); // 添加消息可供视图刷新 CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_LOGOUT, (const PARAM)m_AgentID); } /***************************************************************** **【函数名称】 setState **【函数功能】 设置座席状态 **【参数】 a_AgentState:座席当前逻辑状态 **【返回值】 ****************************************************************/ BOOL CAgent::setState( AGENT_STATE a_AgentState, bool IsForce/* = false*/ ) { CSingleLock Locker(&m_Cs4Lock, TRUE); switch(a_AgentState) { case AGENT_STATE_BUSY: // 通话 { switch(m_State) { case AGENT_STATE_BUSY: return TRUE; break; case AGENT_STATE_REQUESTED: __killTimer(TIMER_LOCK_PERIOD); break; case AGENT_STATE_POST_PROCESSING: { __killTimer(TIMER_POST_PROCESSING); __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false); } break; case AGENT_STATE_REPOSE: { m_IsRepose = false; __onStatusUpdate(AGENT_STATE_REPOSE, false); } break; case AGENT_STATE_LOGOUT: return FALSE; break; } __onStatusUpdate(AGENT_STATE_BUSY, true); m_State = AGENT_STATE_BUSY; } break; case AGENT_STATE_REPOSE: // 小休 { switch(m_State) { case AGENT_STATE_REPOSE: return TRUE; break; case AGENT_STATE_POST_PROCESSING: { __killTimer(TIMER_POST_PROCESSING); __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false); } break; case AGENT_STATE_BUSY: case AGENT_STATE_LOGOUT: case AGENT_STATE_REQUESTED: return FALSE; break; } m_ReposeCount++; m_IsRepose = true; m_State = AGENT_STATE_REPOSE; // 统计小休开始 __onStatusUpdate(AGENT_STATE_REPOSE, true); } break; case AGENT_STATE_POST_PROCESSING: // 话后处理 { switch(m_State) { case AGENT_STATE_POST_PROCESSING: return TRUE; break; case AGENT_STATE_BUSY: __onStatusUpdate(AGENT_STATE_BUSY, false); break; case AGENT_STATE_FREE: case AGENT_STATE_REPOSE: case AGENT_STATE_REQUESTED: case AGENT_STATE_LOGOUT: return FALSE; break; } // 统计话后处理开始 __onStatusUpdate(AGENT_STATE_POST_PROCESSING, true); m_State = AGENT_STATE_POST_PROCESSING; if (m_TimePostProcessing > 0) __setTimer(TIMER_POST_PROCESSING, m_TimePostProcessing * 1000); // 启动话后处理定时器 } break; case AGENT_STATE_FREE: // 空闲 { switch(m_State) { case AGENT_STATE_FREE: return TRUE; break; case AGENT_STATE_BUSY: { if(IsForce) __onStatusUpdate(AGENT_STATE_BUSY, false); else return FALSE; } break; case AGENT_STATE_POST_PROCESSING: { __killTimer(TIMER_POST_PROCESSING); __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false); } break; case AGENT_STATE_REPOSE: { __onStatusUpdate(AGENT_STATE_REPOSE, false); m_IsRepose = false; } break; case AGENT_STATE_REQUESTED: { if(IsForce) __killTimer(TIMER_LOCK_PERIOD); else return FALSE; } break; case AGENT_STATE_LOGOUT: return FALSE; break; } m_State = m_IsRepose ? AGENT_STATE_REPOSE : AGENT_STATE_FREE; } break; case AGENT_STATE_REQUESTED: // 被请求 { ASSERT(m_State == AGENT_STATE_FREE); switch(m_State) { case AGENT_STATE_REQUESTED: case AGENT_STATE_BUSY: case AGENT_STATE_REPOSE: case AGENT_STATE_POST_PROCESSING: case AGENT_STATE_LOGOUT: return FALSE; break; } __setTimer(TIMER_LOCK_PERIOD, CConfig::agentLockedPeriod() * 1000); // 被请求超时处理定时器 m_State = AGENT_STATE_REQUESTED; } break; default: { switch(m_State) { case AGENT_STATE_BUSY: __onStatusUpdate(AGENT_STATE_BUSY, false); break; case AGENT_STATE_POST_PROCESSING: { __killTimer(TIMER_POST_PROCESSING); __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false); } break; case AGENT_STATE_REPOSE: { m_IsRepose = false; __onStatusUpdate(AGENT_STATE_REPOSE, false); } break; case AGENT_STATE_REQUESTED: __killTimer(TIMER_LOCK_PERIOD); break; } m_State = a_AgentState; } break; } // end switch // 通知座席当前状态变化 __reportStatus(); return TRUE; } /***************************************************************** **【函数名称】 onAssoExtStatusUpdated **【函数功能】 关联分机状态更新的处理函数 **【参数】 a_ExtState:分机当前状态 Param:附加参数 **【返回值】 ****************************************************************/ void CAgent::onAssoExtStatusUpdated( INNER_STATE a_ExtState, PARAM Param /*= NULL*/ ) { CPduEntity * pCmd = (CPduEntity *)Param; m_AssoExtState = a_ExtState; switch(a_ExtState) { case INNER_STATE_ALERTING: { // 来电振铃时解除请求锁定等状态 if(m_State == AGENT_STATE_POST_PROCESSING || m_State == AGENT_STATE_REPOSE || m_State == AGENT_STATE_REQUESTED) setState(AGENT_STATE_FREE, true); } break; case INNER_STATE_RING_BACK: { if(m_State == AGENT_STATE_POST_PROCESSING || m_State == AGENT_STATE_REPOSE || m_State == AGENT_STATE_REQUESTED) setState(AGENT_STATE_FREE, true); } break; case INNER_STATE_TALKING: { if(pCmd == NULL || pCmd->GetDataUInt(10) != PDU_CMD_AGENT_MONI_REPLACE) // 如果是代接操作则不记录应答次数 m_AnswerCount++; // 累计应答计数 setState(AGENT_STATE_BUSY, true); } break; case INNER_STATE_FREE: { if(m_State == AGENT_STATE_BUSY) { ASSERT(pCmd != NULL); // 关联线路为非内线,最后通话分机为当前分机,则需要进行话后处理 if(pCmd != NULL && pCmd->GetDataUInt(7) != DEV_RES_TYPE_EXT && pCmd->GetDataUInt(9) == m_Exten) setState(AGENT_STATE_POST_PROCESSING); else setState(AGENT_STATE_FREE, true); } else if(m_State == AGENT_STATE_UNKNOWN || m_State == AGENT_STATE_REQUESTED) setState(AGENT_STATE_FREE, true); } break; default: { if(m_State == AGENT_STATE_UNKNOWN) setState(AGENT_STATE_FREE); } break; } } /***************************************************************** **【函数名称】 lock **【函数功能】 锁定座席 **【参数】 **【返回值】 ****************************************************************/ BOOL CAgent::lock( void ) { if(isFree()) return setState(AGENT_STATE_REQUESTED); else return FALSE; }