#include "StdAfx.h" #include "CallDetail.h" #include "ICdr.h" #include "LineHolder.h" #include "LogicLine.h" #include "CdrConference.h" #include "CdrExtCallIn.h" #include "CdrExtCallOut.h" #include "CdrFax.h" #include "Record.h" #include "CdrInstead.h" #include "CdrIvrCallOut.h" #include "CdrTransfer.h" #include "CdrTrunkCallIn.h" #include "StatisticsMgr.h" CCallDetail::CCallDetail(ULONG CallId) : m_CallId(CallId), m_ActionId(0), m_FinalExt(0), m_GrubExt(0), m_PostProcessing(false) { } CCallDetail::~CCallDetail(void) { } /***************************************************************** **【函数名称】 __createCdr **【函数功能】 创建呼叫明细记录 **【参数】 **【返回值】 *****************************************************************/ ICdr* CCallDetail::__createCdr( REP_EVENT Event, UINT HostLine ) { // 添加一个明细记录 ICdr* pCdr = NULL; switch (Event) { case REP_EVENT_TRUNK_CALL_IN: // 中继呼入 { pCdr = new CCdrTrunkCallIn(m_CallId, ++m_ActionId, HostLine); } break; case REP_EVENT_EXT_CALL_OUT: // 坐席呼出 { pCdr = new CCdrExtCallOut(m_CallId, ++m_ActionId, HostLine); } break; case REP_EVENT_EXT_CALL_IN: // 坐席呼入 { //如果操作ID不递增,在坐席接听超时再次重复转坐席时 //会出现数据库插入数据错误(主键重复) pCdr = new CCdrExtCallIn(m_CallId, ++m_ActionId, HostLine); } break; case REP_EVENT_IVR_CALL_OUT: // IVR自动外呼 { pCdr = new CCdrIvrCallOut(m_CallId, ++m_ActionId, HostLine); } break; case REP_EVENT_TRANSFER: // 转移 { pCdr = new CCdrTransfer(m_CallId, ++m_ActionId, HostLine); } break; case REP_EVENT_CONFERENCE: // 会议 { pCdr = new CCdrConference(m_CallId, ++m_ActionId, HostLine); } break; case REP_EVENT_INSTEAD: // 代接 { pCdr = new CCdrInstead(m_CallId, ++m_ActionId, HostLine); } break; case REP_EVENT_FAX_BEGIN: // 收/发传真开始 { // 收发传真时的ActionID,未严格按照坐席操作时序分配,默认与上一个操作同步 // 如需严格控制ActionID赋值的正确性,需要建立操作关联 // 其实收发传真表记录ActionID没什么用,有CallID和HostLine即可 pCdr = new CCdrFax(m_CallId, m_ActionId, HostLine); } break; default: break; } // end switch // 返回表对象指针 ASSERT(pCdr != NULL); return pCdr; } /***************************************************************** **【函数名称】 end **【函数功能】 结束呼叫统计过程 **【参数】 **【返回值】 *****************************************************************/ void CCallDetail::end( void ) { ICdr* pCdr = NULL; POSITION pos = m_CdrList.GetHeadPosition(); // 本呼叫中的统计记录全部提交数据, 然后销毁表实体 while (pos != NULL) { pCdr = m_CdrList.GetNext(pos); // 写入数据 ASSERT(pCdr != NULL); pCdr->toSql(); // 销毁表实体 delete pCdr; pCdr = NULL; } // end while } /***************************************************************** **【函数名称】 onCallDetail **【函数功能】 统计事件响应 **【参数】 CallId CallID Event 统计事件 HostLine 主控线路 lpParam 统计信息 **【返回值】 *****************************************************************/ void CCallDetail::onCallDetail( ULONG CallId, REP_EVENT Event, UINT HostLine, void* lpParam ) { // 是否需要添加新表 if (Event <= REP_EVENT_TURN_IVR) { ICdr* pCdr = __createCdr(Event, HostLine); m_CdrList.AddTail(pCdr); pCdr->onCallDetail(Event, HostLine, lpParam); } else { // by 这里解决关于中继表缺少的内线通话状态下的数据 2020/1/8 // 统计事件分发 POSITION pos = m_CdrList.GetHeadPosition(); ICdr* pCdr = NULL; while (pos != NULL) { pCdr = m_CdrList.GetNext(pos); pCdr->onCallDetail(Event, HostLine, lpParam); } // end while } // 根据事件判断是否需要进行话后处理 switch(Event) { case REP_EVENT_TRUNK_CALL_IN: // 外线呼入 m_PostProcessing = true; break; case REP_EVENT_EXT_CALL_OUT: // 坐席外呼 { T_EvtExtCallOut* tEvent = (T_EvtExtCallOut*)lpParam; if (tEvent->nPeerLineType == 1) m_PostProcessing = true; } break; case REP_EVENT_TRANSFER: // 转移或者协商转移 { T_EvtTransfer* tEvent = (T_EvtTransfer*)lpParam; if (tEvent->nPeerLineType == 1) m_PostProcessing = true; } break; case REP_EVENT_CONFERENCE: m_PostProcessing = false; break; // 在转座席状态发生改变的情况下更新接通的时间 by 2020/1/8 // 在分机呼入状态下更新中继入表中的分机号以及工号 // 开始的工号 case REP_EVENT_TURN_AGENT: { CLogicLine* pLine = CLineHolder::GetInstance().getLogicLine(HostLine); T_EvtStateChanged repInfo; repInfo.nLineState = INNER_STATE_TALKING; repInfo.nAgentId = pLine->getAgentNum(); CStatisticsMgr::GetInstance().onCallDetail(m_CallId, REP_EVENT_STATE_CHANGED, HostLine, &repInfo); CString RectrunkFile = ""; CString RecFile = ""; RectrunkFile = CRecord::GetInstance().recordTrunk(pLine,RecFile); // 需要向座席发送录音消息 // 统计 REP_EVENT_REC_BEGIN T_EvtRecBegin repRecInfo; memset(&repRecInfo, 0, sizeof(repRecInfo)); lstrcpy(repRecInfo.szFileName, RectrunkFile); UINT lineTemp = pLine->lineId(); lineTemp--; CStatisticsMgr::GetInstance().onCallDetail(m_CallId, REP_EVENT_REC_BEGIN, lineTemp, &repRecInfo); } break; case REP_EVENT_STATE_CHANGED: // 线路变化事件 { T_EvtStateChanged* tEvtState = (T_EvtStateChanged*)lpParam; if (tEvtState->nLineState == INNER_STATE_TALKING) { CLogicLine* pLine = CLineHolder::GetInstance().getLogicLine(HostLine); if (pLine->opType() == PDU_CMD_AGENT_MONI_LISTEN) // 监听线路不进行话后处理 { } else if (pLine->opType() == PDU_CMD_AGENT_MONI_INTERCEPT) // 强截 { m_GrubExt = HostLine; } else { m_HostLineSet.insert(HostLine); } } else if (tEvtState->nLineState == INNER_STATE_FREE) { if (m_HostLineSet.size() == 1) { m_FinalExt = m_PostProcessing ? *m_HostLineSet.begin() : 0; } if (m_GrubExt == HostLine) { m_FinalExt = m_PostProcessing ? m_GrubExt : 0; // 设置强截的话后处理 m_GrubExt = 0; } m_HostLineSet.erase(HostLine); } } break; default: break; } }