#include "StdAfx.h" #include "LogicLineExt.h" #include "CallSession.h" #include "SessionHolder.h" #include "StatisticsMgr.h" #include "NetworkCti.h" #include "CtiCore.h" #include "TaskMgr.h" CLogicLineExt::CLogicLineExt(UINT ResId) : CLogicLine(ResId), m_AgentId(0), m_FinalExt(0), m_AssoLineType(0), m_HoldRecordFile(_T("")) { m_LineStatus = INNER_STATE_FREE; } CLogicLineExt::~CLogicLineExt(void) { } /***************************************************************** **【函数名称】 __telephoneNumBelongsTo **【函数功能】 获取归属地信息 **【参数】 Number: 来电号码 BelongsTo:输出参数,归属地 **【返回值】 ****************************************************************/ void CLogicLineExt::__telephoneNumBelongsTo(const CString& Number, CString& BelongsTo) { // 去掉出局号码进行查询归属地 // Number= Number.Right(Number.GetLength()-1); //屏蔽出局号,该行代码在测试环境中使用 CString SqlFunc = _T("charindex"); // MS SQL SERVER 字符串匹配函数 if (DB_MySQL == IOtlConnection::getInstance()->GetDatabaseType()) SqlFunc = _T("locate"); // MYSQL 字符串匹配函数 CString SQL; SQL.Format("select * from conf_phone where %s(rtrim(number),'%s') in (1,2)", SqlFunc, Number); IOtlRecordset* pRD = IOtlConnection::getInstance()->QueryRecords(SQL); if (NULL == pRD) //判断空值 return; if (pRD->IsEOF()) { IOtlRecordset::DestroyInstance(pRD); // 释放记录集 return; } CString Province = _T(""); CString City = _T(""); CString Type = _T(""); while (!pRD->IsEOF()) { pRD->MoveNextRow(); Province = pRD->GetValueStr(_T("Province")); City = pRD->GetValueStr(_T("City")); Type = pRD->GetValueStr(_T("Type")); } IOtlRecordset::DestroyInstance(pRD); // 释放记录集 BelongsTo = Province.Trim() + _T("-") + City.Trim() + _T("-") + Type.Trim(); } /***************************************************************** **【函数名称】 resetLine **【函数功能】 线路重置 **【参数】 **【返回值】 ****************************************************************/ void CLogicLineExt::resetLine() { // 清除线路信息 m_FinalExt = 0; m_AssoLineType = 0; m_HoldRecordFile = ""; CLogicLine::resetLine(); } /***************************************************************** **【函数名称】 pushLineData2ACD **【函数功能】 将线路数据发送给ACD **【参数】 **【返回值】 ****************************************************************/ void CLogicLineExt::pushLineData2ACD() { // 通过会话获取线路信息 CString Data = _T(""); CString TrunkNum = _T(""); CCallSession* pSession = CSessionHolder::GetInstance().findSession(m_CallId); if (pSession != NULL) { // 获取随路数据 Data = pSession->data(); // 获取对端线路类型 CLogicLine* pAssoLine = pSession->getAssoLine(this); if (pAssoLine != NULL) { TrunkNum = pAssoLine->calleeNum(); m_AssoLineType = pAssoLine->type(); //2018.5.19分机外线判定 if (m_AssoLineType == DEV_RES_TYPE_VOIP) { m_AssoLineType = pAssoLine->typeExtTrunk(); } // ych // 2019-9-12 bwj 满意度,分机挂机时不能挂断外线,故屏蔽掉 if (m_LineStatus == INNER_STATE_FREE) { #ifdef ISNEEDMYD CPduEntity CmdTurnIvr(PDU_CMD_CTI_IVR_TURNIVR); CmdTurnIvr.SetDataULong(2, pAssoLine->callId()); // CallId CmdTurnIvr.SetDataString(3, pAssoLine->callerNum()); // 主叫 CmdTurnIvr.SetDataString(4, pAssoLine->calleeNum()); // 被叫 CmdTurnIvr.SetDataUInt(5, pAssoLine->lineId()); // 外线Id CmdTurnIvr.SetDataUInt(6, 0); // 分机Id CmdTurnIvr.SetDataUInt(7, 0); // IVr节点号 CmdTurnIvr.SetDataString(8, "MYD"); // Ivr文件名 CmdTurnIvr.SetDataString(9, ""); // 随路数据 CmdTurnIvr.SetDataBool(10, false); // 是否返回 BOOL bRet = CNetworkCti::GetInstance().send2IVR(CmdTurnIvr); // 发送IVR失败,转IVR失败,外线挂机 if (!bRet) { LineOpParam pLineOpParam; memset(&pLineOpParam, 0, sizeof(pLineOpParam)); CCtiCore::GetInstance().getDevLink().exec((long)this, LINE_OP_HANG_UP, pAssoLine->lineId(), &pLineOpParam); } #else ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Line}: 当前会话[%d]线路数:%d"), m_CallId, pSession->lineCount()); //if (pSession->lineCount() == 2 && m_AssoLineType == DEV_RES_TYPE_TRUNK) // 对端线路是外线 //{ // CCtiCore::GetInstance().getDevLink().exec((long)-1, LINE_OP_HANG_UP, pAssoLine->lineId(), NULL); // ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Line}: 座席分机挂机,挂断关联中继线路")); //} #endif // ISNEEDMYD } } } // 发送线路状态变化信息到ACD CPduEntity Cmd(PDU_CMD_CTI_LINE_STATE); Cmd.SetDataUInt(0, m_LineId); Cmd.SetDataUInt(1, m_LineStatus); Cmd.SetDataULong(2, (m_CallId == 0 ? m_HoldCallId : m_CallId)); Cmd.SetDataUInt(3, m_AgentId); Cmd.SetDataString(4, m_CallerNum); Cmd.SetDataString(5, m_CalleeNum); Cmd.SetDataString(6, Data); Cmd.SetDataUInt(7, m_AssoLineType); //if (m_LineStatus == INNER_STATE_ALERTING) //分机振铃事件才送归属地 //{ // CString NumberBelongsTo = _T(""); // __telephoneNumBelongsTo(m_CallerNum, NumberBelongsTo); // ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Line}: 坐席线路来电振铃,来电归属地:%s"), NumberBelongsTo); // Cmd.SetDataString(8, NumberBelongsTo); //} Cmd.SetDataUInt(9, m_FinalExt); Cmd.SetDataUInt(10, m_CurrentOpType); // 传入当前线路操作类型 Cmd.SetDataInt(11, m_ActionID); Cmd.SetDataUInt(12, m_IsMeeting); // 2020-01-05 坐席状态,标记是否再会议 Cmd.SetDataString(13, TrunkNum); // 中继号 CNetworkCti::GetInstance().send2ACD(Cmd); } /***************************************************************** **【函数名称】 pushRecord2ACD **【函数功能】 将录音数据发送给ACD **【参数】 **【返回值】 ****************************************************************/ void CLogicLineExt::pushRecord2ACD() { // 向ACD发送录音文件名 CPduEntity Pdu(PDU_CMD_CTI_RECORD); Pdu.SetDataUInt(0, m_LineId); Pdu.SetDataULong(1, m_CallId); Pdu.SetDataString(2, m_RecordFile); CNetworkCti::GetInstance().send2ACD(Pdu); // 显示日志 ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("CTI->AGENT, PDU = [线路录音信息], Exten = %d, Agent = %d, RecordFile = %s"), m_LineId, m_AgentId, m_RecordFile); } /***************************************************************** **【函数名称】 onLineStatusUpdated **【函数功能】 处理线路状态变化 **【参数】 EvtInfo: 线路资源状态 **【返回值】 ****************************************************************/ void CLogicLineExt::onLineStatusUpdated(const EventResStatus &EvtInfo) { if (m_LineStatus == EvtInfo.nState) return; // 保持处理 if (m_HoldCallId == 0 && (EvtInfo.nState & HELD_STATE_MASK) == INNER_STATE_HELD) { m_HoldCallId = m_CallId; m_CallId = 0; m_HoldRecordFile = m_RecordFile; } // 接回处理 if (m_HoldCallId != 0 && (EvtInfo.nState & HELD_STATE_MASK) != INNER_STATE_HELD) { m_CallId = m_HoldCallId; m_HoldCallId = 0; m_RecordFile = m_HoldRecordFile; } // 保存线路信息 m_LineStatus = EvtInfo.nState; m_CallerNum = EvtInfo.szCallerNum; m_CalleeNum = EvtInfo.szCalleeNum; ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LogicLineExt}: 线路状态, LineId = %lu,State=%d,CallId=%lu,Caller=%s,Callee=%s"), m_LineId, m_LineStatus, m_CallId, m_CallerNum, m_CalleeNum); // 统计线路状态变化 _reportLineStatus(); //获取内线呼入类型 m_FinalExt = CStatisticsMgr::GetInstance().getFinalExt(m_CallId); // 发送线路状态变化信息到ACD(只有分机线路) pushLineData2ACD(); // 通知会话状态变化,保持会话(m_nHoldCallId)不再通知 CSessionHolder::GetInstance().onLineStatusUpdated(this); if (m_CallId == 0 && m_LineStatus== INNER_STATE_FREE) // 2022-01-06 设备外呼一个不存在的号码,callid为0,之前不会清除绑定的操作 { resetLine(); } }