MiddleWares_YiHe 郑州颐和医院随访系统中间件

CallDetail.cpp 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include "StdAfx.h"
  2. #include "CallDetail.h"
  3. #include "ICdr.h"
  4. #include "LineHolder.h"
  5. #include "LogicLine.h"
  6. #include "CdrConference.h"
  7. #include "CdrExtCallIn.h"
  8. #include "CdrExtCallOut.h"
  9. #include "CdrFax.h"
  10. #include "Record.h"
  11. #include "CdrInstead.h"
  12. #include "CdrIvrCallOut.h"
  13. #include "CdrTransfer.h"
  14. #include "CdrTrunkCallIn.h"
  15. #include "StatisticsMgr.h"
  16. CCallDetail::CCallDetail(ULONG CallId) : m_CallId(CallId), m_ActionId(0), m_FinalExt(0), m_GrubExt(0), m_PostProcessing(false)
  17. {
  18. }
  19. CCallDetail::~CCallDetail(void)
  20. {
  21. }
  22. /*****************************************************************
  23. **【函数名称】 __createCdr
  24. **【函数功能】 创建呼叫明细记录
  25. **【参数】
  26. **【返回值】
  27. *****************************************************************/
  28. ICdr* CCallDetail::__createCdr( REP_EVENT Event, UINT HostLine )
  29. {
  30. // 添加一个明细记录
  31. ICdr* pCdr = NULL;
  32. switch (Event)
  33. {
  34. case REP_EVENT_TRUNK_CALL_IN: // 中继呼入
  35. {
  36. pCdr = new CCdrTrunkCallIn(m_CallId, ++m_ActionId, HostLine);
  37. }
  38. break;
  39. case REP_EVENT_EXT_CALL_OUT: // 坐席呼出
  40. {
  41. pCdr = new CCdrExtCallOut(m_CallId, ++m_ActionId, HostLine);
  42. }
  43. break;
  44. case REP_EVENT_EXT_CALL_IN: // 坐席呼入
  45. {
  46. //如果操作ID不递增,在坐席接听超时再次重复转坐席时
  47. //会出现数据库插入数据错误(主键重复)
  48. pCdr = new CCdrExtCallIn(m_CallId, ++m_ActionId, HostLine);
  49. }
  50. break;
  51. case REP_EVENT_IVR_CALL_OUT: // IVR自动外呼
  52. {
  53. pCdr = new CCdrIvrCallOut(m_CallId, ++m_ActionId, HostLine);
  54. }
  55. break;
  56. case REP_EVENT_TRANSFER: // 转移
  57. {
  58. pCdr = new CCdrTransfer(m_CallId, ++m_ActionId, HostLine);
  59. }
  60. break;
  61. case REP_EVENT_CONFERENCE: // 会议
  62. {
  63. pCdr = new CCdrConference(m_CallId, ++m_ActionId, HostLine);
  64. }
  65. break;
  66. case REP_EVENT_INSTEAD: // 代接
  67. {
  68. pCdr = new CCdrInstead(m_CallId, ++m_ActionId, HostLine);
  69. }
  70. break;
  71. case REP_EVENT_FAX_BEGIN: // 收/发传真开始
  72. {
  73. // 收发传真时的ActionID,未严格按照坐席操作时序分配,默认与上一个操作同步
  74. // 如需严格控制ActionID赋值的正确性,需要建立操作关联
  75. // 其实收发传真表记录ActionID没什么用,有CallID和HostLine即可
  76. pCdr = new CCdrFax(m_CallId, m_ActionId, HostLine);
  77. }
  78. break;
  79. default:
  80. break;
  81. } // end switch
  82. // 返回表对象指针
  83. ASSERT(pCdr != NULL);
  84. return pCdr;
  85. }
  86. /*****************************************************************
  87. **【函数名称】 end
  88. **【函数功能】 结束呼叫统计过程
  89. **【参数】
  90. **【返回值】
  91. *****************************************************************/
  92. void CCallDetail::end( void )
  93. {
  94. ICdr* pCdr = NULL;
  95. POSITION pos = m_CdrList.GetHeadPosition();
  96. // 本呼叫中的统计记录全部提交数据, 然后销毁表实体
  97. while (pos != NULL)
  98. {
  99. pCdr = m_CdrList.GetNext(pos);
  100. // 写入数据
  101. ASSERT(pCdr != NULL);
  102. pCdr->toSql();
  103. // 销毁表实体
  104. delete pCdr;
  105. pCdr = NULL;
  106. } // end while
  107. }
  108. /*****************************************************************
  109. **【函数名称】 onCallDetail
  110. **【函数功能】 统计事件响应
  111. **【参数】 CallId CallID
  112. Event 统计事件
  113. HostLine 主控线路
  114. lpParam 统计信息
  115. **【返回值】
  116. *****************************************************************/
  117. void CCallDetail::onCallDetail( ULONG CallId, REP_EVENT Event, UINT HostLine, void* lpParam )
  118. {
  119. // 是否需要添加新表
  120. if (Event <= REP_EVENT_TURN_IVR)
  121. {
  122. ICdr* pCdr = __createCdr(Event, HostLine);
  123. m_CdrList.AddTail(pCdr);
  124. pCdr->onCallDetail(Event, HostLine, lpParam);
  125. }
  126. else
  127. {
  128. // by 这里解决关于中继表缺少的内线通话状态下的数据 2020/1/8
  129. // 统计事件分发
  130. POSITION pos = m_CdrList.GetHeadPosition();
  131. ICdr* pCdr = NULL;
  132. while (pos != NULL)
  133. {
  134. pCdr = m_CdrList.GetNext(pos);
  135. pCdr->onCallDetail(Event, HostLine, lpParam);
  136. } // end while
  137. }
  138. // 根据事件判断是否需要进行话后处理
  139. switch(Event)
  140. {
  141. case REP_EVENT_TRUNK_CALL_IN: // 外线呼入
  142. m_PostProcessing = true;
  143. break;
  144. case REP_EVENT_EXT_CALL_OUT: // 坐席外呼
  145. {
  146. T_EvtExtCallOut* tEvent = (T_EvtExtCallOut*)lpParam;
  147. if (tEvent->nPeerLineType == 1)
  148. m_PostProcessing = true;
  149. }
  150. break;
  151. case REP_EVENT_TRANSFER: // 转移或者协商转移
  152. {
  153. T_EvtTransfer* tEvent = (T_EvtTransfer*)lpParam;
  154. if (tEvent->nPeerLineType == 1)
  155. m_PostProcessing = true;
  156. }
  157. break;
  158. case REP_EVENT_CONFERENCE:
  159. m_PostProcessing = false;
  160. break;
  161. // 在转座席状态发生改变的情况下更新接通的时间 by 2020/1/8
  162. // 在分机呼入状态下更新中继入表中的分机号以及工号
  163. // 开始的工号
  164. case REP_EVENT_TURN_AGENT:
  165. {
  166. CLogicLine* pLine = CLineHolder::GetInstance().getLogicLine(HostLine);
  167. T_EvtStateChanged repInfo;
  168. repInfo.nLineState = INNER_STATE_TALKING;
  169. repInfo.nAgentId = pLine->getAgentNum();
  170. CStatisticsMgr::GetInstance().onCallDetail(m_CallId, REP_EVENT_STATE_CHANGED, HostLine, &repInfo);
  171. CString RectrunkFile = "";
  172. CString RecFile = "";
  173. RectrunkFile = CRecord::GetInstance().recordTrunk(pLine,RecFile);
  174. // 需要向座席发送录音消息
  175. // 统计 REP_EVENT_REC_BEGIN
  176. T_EvtRecBegin repRecInfo;
  177. memset(&repRecInfo, 0, sizeof(repRecInfo));
  178. lstrcpy(repRecInfo.szFileName, RectrunkFile);
  179. UINT lineTemp = pLine->lineId();
  180. lineTemp--;
  181. CStatisticsMgr::GetInstance().onCallDetail(m_CallId, REP_EVENT_REC_BEGIN, lineTemp, &repRecInfo);
  182. }
  183. break;
  184. case REP_EVENT_STATE_CHANGED: // 线路变化事件
  185. {
  186. T_EvtStateChanged* tEvtState = (T_EvtStateChanged*)lpParam;
  187. if (tEvtState->nLineState == INNER_STATE_TALKING)
  188. {
  189. CLogicLine* pLine = CLineHolder::GetInstance().getLogicLine(HostLine);
  190. if (pLine->opType() == PDU_CMD_AGENT_MONI_LISTEN) // 监听线路不进行话后处理
  191. {
  192. }
  193. else if (pLine->opType() == PDU_CMD_AGENT_MONI_INTERCEPT) // 强截
  194. {
  195. m_GrubExt = HostLine;
  196. }
  197. else
  198. {
  199. m_HostLineSet.insert(HostLine);
  200. }
  201. }
  202. else if (tEvtState->nLineState == INNER_STATE_FREE)
  203. {
  204. if (m_HostLineSet.size() == 1)
  205. {
  206. m_FinalExt = m_PostProcessing ? *m_HostLineSet.begin() : 0;
  207. }
  208. if (m_GrubExt == HostLine)
  209. {
  210. m_FinalExt = m_PostProcessing ? m_GrubExt : 0; // 设置强截的话后处理
  211. m_GrubExt = 0;
  212. }
  213. m_HostLineSet.erase(HostLine);
  214. }
  215. }
  216. break;
  217. default:
  218. break;
  219. }
  220. }