| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- #include "StdAfx.h"
- #include "IvrFlow.h"
- #include "CellBase.h"
- #include "FlowTemplate.h"
- #include "MsgCenter.h"
- #include "NetworkIvr.h"
- #include "CellTimer.h"
- #include "IvrCore.h"
- IMPLEMENT_DYNAMIC(CIvrFlow, CWnd)
- CIvrFlow::CIvrFlow(int Id) : m_Id(Id), m_State(IVR_FLOW_STATE_FREE), m_IsHangUp(false), m_IsNetLinkUp(false), m_AssoCallId(0), m_pFlowTemplate(NULL), m_pCurrentCell(NULL)
- {
- CreateEx(0, AfxRegisterWndClass(CS_GLOBALCLASS), "", 0, 0, 0, 0, 0, 0, 0);
- }
- CIvrFlow::~CIvrFlow(void)
- {
- __release();
- DestroyWindow();
- }
- BEGIN_MESSAGE_MAP(CIvrFlow, CWnd)
- ON_WM_TIMER()
- END_MESSAGE_MAP()
- /*****************************************************************
- **【函数名称】 __release
- **【函数功能】 释放资源
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIvrFlow::__release( void )
- {
- if(m_pCurrentCell != NULL)
- __deleteCurrentCell();
- m_VarTable.RemoveAll();
- }
- /*****************************************************************
- **【函数名称】 __clearFlow
- **【函数功能】 流程结束时对流程进行清理
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIvrFlow::__clearFlow( void )
- {
- m_AssoCallId = 0;
- m_IsHangUp = false;
- m_State = IVR_FLOW_STATE_FREE;
- __release();
- CMsgCenter::GetInstance().pushMsg(IVR_MSG_FLOW_STATE_UPDAET, reinterpret_cast<const PARAM>(m_Id));
- CMsgCenter::GetInstance().pushMsg(IVR_MSG_FLOW_CELL_UPDATE, reinterpret_cast<const PARAM>(m_Id));
- if(m_IsNetLinkUp && m_pFlowTemplate != NULL && m_pFlowTemplate->type() == FLOW_AUTO)
- start();
- }
- /*****************************************************************
- **【函数名称】 __onTimerTimeOut
- **【函数功能】 流程节点最大执行时间超时处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIvrFlow::__onTimerTimeOut( void )
- {
- ASSERT(m_pCurrentCell != NULL);
- ASSERT(m_pFlowTemplate != NULL);
- // by 屏蔽流程释放的命令
- //if(m_pFlowTemplate->type() != FLOW_SUB) // 执行子流程时不上报流程结束
- //{
- // CPduEntity cmdFlowEnd(PDU_CMD_IVR_END);
- // cmdFlowEnd.SetDataInt(1, m_Id);
- // CNetworkIvr::GetInstance().send(cmdFlowEnd);
- //}
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{FLow}: 节点[%s]超过最大执行时间, 流程[%d]将被释放"), m_pCurrentCell->name(), m_Id);
- // by 屏蔽掉清除掉Flow的函数
- //__clearFlow();
- }
- /*****************************************************************
- **【函数名称】 __onNextCellNull
- **【函数功能】 当下个节点为空的处理
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIvrFlow::__onNextCellNull( int NullCellPos )
- {
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{FLow}: 查找节点[%d]失败, 流程[%d]将被释放"), NullCellPos, m_Id);
- CPduEntity CmdHangUp(PDU_CMD_IVR_HANGUP);
- CmdHangUp.SetDataInt(1, m_Id);
- CNetworkIvr::GetInstance().send(CmdHangUp);
- __clearFlow();
- }
- /*****************************************************************
- **【函数名称】 __deleteCurrentCell
- **【函数功能】 删除当前节点
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIvrFlow::__deleteCurrentCell( void )
- {
- ASSERT(m_pCurrentCell != NULL);
- if(m_pCurrentCell->maxWaitingTime() > 0)
- KillTimer((long)m_pCurrentCell);
- delete m_pCurrentCell;
- m_pCurrentCell = NULL;
- }
- /*****************************************************************
- **【函数名称】 start
- **【函数功能】 开始执行流程
- **【参数】 pFlowTemp: 流程模板
- **【返回值】 下一个节点编号
- ****************************************************************/
- int CIvrFlow::start( CFlowTemplate* pFlowTemp /*= NULL*/, int StartPos/* = 1*/ )
- {
- if(pFlowTemp != NULL)
- m_pFlowTemplate = pFlowTemp;
- if(m_pFlowTemplate == NULL)
- {
- ASSERT(FALSE);
- return CELL_OP_ERROR;
- }
- CString CellName = "";
- switch(m_pFlowTemplate->type())
- {
- case FLOW_NORMAL:
- case FLOW_SUB:
- CellName = CELL_NAME_START;
- break;
- case FLOW_AUTO:
- CellName = CELL_NAME_TIMER;
- break;
- }
- int Pos = m_pFlowTemplate->getCellPos(CellName);
- if(Pos < 1)
- {
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Flow}: 执行流程[%d]时未找到起始节点, Template = %s"), m_Id, m_pFlowTemplate->name());
- return CELL_OP_ERROR;
- }
- Pos = (StartPos == 1) ? Pos : StartPos;
- m_State = IVR_FLOW_STATE_RUN;
- CMsgCenter::GetInstance().pushMsg(IVR_MSG_FLOW_STATE_UPDAET, reinterpret_cast<const PARAM>(m_Id));
- // 如果是自动流程,但是还未连接至CTI则等待,直到连至CTI后执行
- if(m_pFlowTemplate->type() == FLOW_AUTO && !m_IsNetLinkUp)
- {
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Flow}: 自动流程[%d]挂起, 等候与CTI连接, Template = %s"), m_Id, m_pFlowTemplate->name());
- return CELL_OP_WAIT_FOR;
- }
- return next(Pos);
- }
- /*****************************************************************
- **【函数名称】 next
- **【函数功能】 执行流程下一结点
- **【参数】 NextPos:下一结点编号
- **【返回值】 后一个节点编号
- ****************************************************************/
- int CIvrFlow::next( int NextPos )
- {
- ASSERT(m_pFlowTemplate != NULL);
- if(m_pFlowTemplate == NULL)
- {
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Flow}: 执行流程[%d]后续节点时,流程模板为空"), m_Id);
- return CELL_OP_ERROR;
- }
- int NextCellPos = NextPos;
- m_pCurrentCell = m_pFlowTemplate->findCell(NextCellPos);
- //by 2019-9-6 将播放工号的时间调整至摘机之后
- if(m_pCurrentCell == NULL)
- {
- __onNextCellNull(NextCellPos);
- return NextCellPos;
- }
- while(m_pCurrentCell != NULL)
- {
- m_pCurrentCell->assoIvrFlow() = this;
- CMsgCenter::GetInstance().pushMsg(IVR_MSG_FLOW_CELL_UPDATE, reinterpret_cast<const PARAM>(m_Id));
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]开始执行节点[%s]"), m_Id, m_pCurrentCell->name());
- //by 2019-9-6 将播放工号的时间调整至摘机之后
- CString n_CellNextName = m_pCurrentCell->name();
- if (n_CellNextName == CELL_NAME_HOLD_ON)
- {
- //主动向ACD发送请求座席状态的消息,如果添加主动返回消息估计会产生问题
- CPduEntity cmdhold(PDU_CMD_IVR_TURN_HOLDON);
- //cmdhold.SetDataInt(1, /*m_pCurrentCell->assoIvrFlow()->id()*/1017);
- cmdhold.SetDataULong(2, m_pCurrentCell->assoIvrFlow()->assoCallId());
- CNetworkIvr::GetInstance().send(cmdhold);
- }
- NextCellPos = m_pCurrentCell->operate();
- if(NextCellPos > 0)
- {
- __deleteCurrentCell();
- m_pCurrentCell = m_pFlowTemplate->findCell(NextCellPos);
- if(m_pCurrentCell == NULL)
- {
- __onNextCellNull(NextCellPos);
- break;
- }
- }
- else if(NextCellPos == CELL_OP_END)
- {
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]执行模板[%s]结束"), m_Id, m_pFlowTemplate->name());
- __clearFlow();
- break;
- }
- else if(NextCellPos == CELL_OP_WAIT_FOR)
- {
- if(m_pCurrentCell->maxWaitingTime() > 0)
- SetTimer(reinterpret_cast<long>(m_pCurrentCell), m_pCurrentCell->maxWaitingTime() * 1000, NULL);
- break;
- }
- else if(NextCellPos == CELL_OP_ERROR)
- {
- CPduEntity cmdIVREnd(PDU_CMD_IVR_END);
- cmdIVREnd.SetDataInt(1, m_Id);
- if(!CNetworkIvr::GetInstance().send(cmdIVREnd))
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]执行节点[%s]时发生异常, 且通知Cti失败, 流程将被释放"), m_Id, m_pCurrentCell->name());
- else
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]执行节点[%s]时发生异常, 已成功通知Cti, 流程将被释放"), m_Id, m_pCurrentCell->name());
- __clearFlow();
- break;
- }
- else if(NextCellPos == CELL_OP_SEND_ERROR)
- {
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]执行节点[%s]时, 向Cti传送数据失败, 流程将被释放"), m_Id, m_pCurrentCell->name());
- __clearFlow();
- break;
- }
- }
- return NextCellPos;
- }
- /*****************************************************************
- **【函数名称】 procPdu
- **【函数功能】 处理PDU消息
- **【参数】 pPduEntity:PDU消息
- **【返回值】 下一个节点编号
- ****************************************************************/
- //2019-09-11 颐和随访
- int CIvrFlow::procPdu( CPduEntity* pPduEntity )
- {
- ASSERT(pPduEntity != NULL);
- bool HangupFlag = false;
- if(pPduEntity->GetCmdType() == PDU_CMD_CTI_IVR_HANGUP && !pPduEntity->GetIsExecReturn())
- HangupFlag = true;
- if(m_pCurrentCell != NULL)
- {
- int NextCellPos = m_pCurrentCell->onOpResultReturn(pPduEntity);
- if(HangupFlag)
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]收到挂机消息, 流程当前节点为[%s], Note = %s, 下一节点[%d]"),
- m_Id, m_pCurrentCell->name(), m_pCurrentCell->note(), NextCellPos);
- else
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]收到节点操作的返回结果, 流程当前节点为[%s], Note = %s, 下一节点[%d]"),
- m_Id, m_pCurrentCell->name(), m_pCurrentCell->note(), NextCellPos);
- //2019-09-11 颐和随访转分机成功时
-
- if(NextCellPos > 0) // NextCellPos为可用的下一结点编号
- {
- __deleteCurrentCell();
- return next(NextCellPos);
- }
- else if(NextCellPos == CELL_OP_WAIT_FOR)
- {
- if(HangupFlag) m_IsHangUp = true;
-
- return CELL_OP_WAIT_FOR;
- }
- else if(NextCellPos == CELL_OP_END)
- {
- ASSERT(FALSE);
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]执行模板[%s]结束"), m_Id, m_pFlowTemplate->name());
- __clearFlow();
- return CELL_OP_END;
- }
- else // CELL_OP_ERROR或者CELL_OP_SEND_ERROR的情况
- {
- __clearFlow();
- return CELL_OP_ERROR;
- }
- }
- else
- {
- if(HangupFlag)
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]收到挂机消息, 但是当前执行节点为空, 流程将被释放"), m_Id);
- else
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]收到节点操作的返回结果, 但是执行节点却为空, 流程将被释放"), m_Id);
- //__clearFlow();
- return CELL_OP_ERROR;
- }
- }
- /*****************************************************************
- **【函数名称】 onNetLinkUpdated
- **【函数功能】 响应网络链接成功或断开事件
- **【参数】 IsConnect:网络链接成功或断开
- **【返回值】
- ****************************************************************/
- void CIvrFlow::onNetLinkUpdated( bool IsConnect )
- {
- m_IsNetLinkUp = IsConnect;
- if(!IsConnect)
- {
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 网络中断流程[%d]将被释放"), m_Id);
- __clearFlow();
- }
- else
- {
- if(m_pFlowTemplate != NULL && m_pFlowTemplate->type() == FLOW_AUTO)
- {
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 网络连接成功自动流程[%d]将启动"), m_Id);
- start();
- }
- }
- }
- /*****************************************************************
- **【函数名称】 addVar
- **【函数功能】 添加系统变量
- **【参数】 VarName: 变量名称
- VarValue: 变量值
- **【返回值】
- ****************************************************************/
- void CIvrFlow::addVar( const CString& VarName, const CString& VarValue )
- {
- m_VarTable.SetAt(VarName, VarValue);
- }
- /*****************************************************************
- **【函数名称】 findVarValue
- **【函数功能】 查找系统变量
- **【参数】 VarName:变量名称
- VarValue:变量值
- **【返回值】 true:查找到,false:未查找到
- ****************************************************************/
- bool CIvrFlow::findVarValue( const CString& VarName, CString& VarValue )
- {
- if(m_VarTable.Lookup(VarName, VarValue))
- return true;
- else
- return false;
- }
- /*****************************************************************
- **【函数名称】 replaceVar
- **【函数功能】 根据流程中的变量对指定字符串进行替换
- **【参数】 Src: 要进行替换的字符串
- Dst: 替换完成的字符串
- **【返回值】 成功true,失败false
- ****************************************************************/
- bool CIvrFlow::replaceVar( const CString& Src, CString& Dst )
- {
- Dst = Src;
- int Begin = 0;
- while( (Begin = Dst.Find(VAR_REF_START_FLAG, Begin)) != -1)
- {
- int End = Dst.Find(VAR_REF_END_FLAG, Begin);
- if(End != -1 && (End - Begin) > 2) // 可以取其中的变量
- {
- CString ValName = Dst.Mid(Begin + 2, End - Begin - 2);
- CString ValValue = _T("");
- // 将变量替换为具体值
- if( findVarValue(ValName, ValValue))
- Dst.Replace((VAR_REF_START_FLAG + ValName + VAR_REF_END_FLAG), ValValue);
- else
- return false;
- } // end if
- else
- {
- return false;
- }
- } // end while
- return true;
- }
- /*****************************************************************
- **【函数名称】 copyVar
- **【函数功能】 复制目标流程的系统变量
- **【参数】 DestFlow:目标流程
- **【返回值】
- ****************************************************************/
- void CIvrFlow::copyVar( CIvrFlow& DestFlow )
- {
- const VarTable::CPair* pPair = DestFlow.m_VarTable.PGetFirstAssoc();
- while(pPair != NULL)
- {
- m_VarTable.SetAt(pPair->key, pPair->value);
- DestFlow.m_VarTable.PGetNextAssoc(pPair);
- }
- }
- /*****************************************************************
- **【函数名称】 setFlowInfo
- **【函数功能】 保存流程信息
- **【参数】 CallId: 呼叫标识
- TrunkId: 外线Id
- CallerNum:主叫号码
- CalleeNum: 被叫号码
- **【返回值】
- ****************************************************************/
- void CIvrFlow::setFlowInfo( ULONG CallId, UINT TrunkId, const CString& CallerNum, const CString& CalleeNum )
- {
- m_AssoCallId = CallId;
- // 给系统变量呼叫标识赋值
- CString Data = "";
- Data.Format(_T("%lu"), CallId);
- addVar(SYSTEM_VAR_CALLID, Data);
- // 给系统变量外线号赋值
- Data.Format(_T("%u"), TrunkId);
- addVar(SYSTEM_VAR_OUTLINEID, Data);
- // 给系统变量主叫号码赋值
- addVar(SYSTEM_VAR_CALLER, CallerNum);
- // 给系统变量被叫号码赋值
- addVar(SYSTEM_VAR_CALLEE, CalleeNum);
- }
- /*****************************************************************
- **【函数名称】 setFlowInfo
- **【函数功能】 保存流程信息
- **【参数】 CallId: 呼叫标识
- TrunkId: 外线Id
- TaskId: 预测任务ID
- OpType: 操作类型
- CallerNum:主叫号码
- CalleeNum: 被叫号码
- **【返回值】
- ****************************************************************/
- void CIvrFlow::setFlowInfo( ULONG CallId, UINT TrunkId, int TaskId, UINT OpType, const CString& CallerNum, const CString& CalleeNum )
- {
- setFlowInfo(CallId, TrunkId, CallerNum, CalleeNum);
- CString Data;
- Data.Format(_T("%d"), TaskId);
- addVar(SYSTEM_VAR_PRE_CALL_ID, Data);
- Data.Format(_T("%u"), OpType);
- addVar(SYSTEM_VAR_PRE_CALL_TYPE, Data);
- }
- /*****************************************************************
- **【函数名称】 setFlowAssoData
- **【函数功能】 设置流程随路数据
- **【参数】 AssoData: 随路数据
- **【返回值】
- ****************************************************************/
- void CIvrFlow::setFlowAssoData( CString AssoData )
- {
- CString DataInfo = "";
- CString DataName = "";
- CString DataValue = "";
- while(!AssoData.IsEmpty())
- {
- int nIndex = AssoData.Find("|");
- if(nIndex == -1)
- {
- DataInfo = AssoData;
- AssoData.Empty();
- }
- else
- {
- DataInfo = AssoData.Left(nIndex);
- AssoData = AssoData.Right(AssoData.GetLength() - nIndex - 1);
- }
- // 解析单个随路数据
- int Falg = DataInfo.Find(":");
- if(Falg == -1)
- continue;
- // 获取变量名
- DataName = DataInfo.Left(Falg);
- if(DataName.IsEmpty())
- continue;
- // 获取变量值
- DataValue = DataInfo.Right(DataInfo.GetLength() - Falg - 1);
- // 添加进随路数据
- this->addVar(DataName, DataValue);
- }
- }
- /*****************************************************************
- **【函数名称】 OnTimer
- **【函数功能】 定时器响应函数
- **【参数】 nIDEvent: 定时器ID
- **【返回值】
- ****************************************************************/
- void CIvrFlow::OnTimer( UINT_PTR nIDEvent )
- {
- KillTimer(nIDEvent);
-
- if(m_pCurrentCell != NULL && nIDEvent == reinterpret_cast<long>(m_pCurrentCell))
- __onTimerTimeOut();
-
- CWnd::OnTimer(nIDEvent);
- }
- /*****************************************************************
- **【函数名称】 onTimeUp
- **【函数功能】 定时器节点时间到
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIvrFlow::onTimerTimeUp( int NextPos )
- {
- if(m_pCurrentCell->name() == CELL_NAME_TIMER)
- {
- __deleteCurrentCell();
- next(NextPos);
- }
- }
|