No Description

QueueMgr.cpp 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. #include "StdAfx.h"
  2. #include "QueueMgr.h"
  3. #include "Queue.h"
  4. #include "AgentOffice.h"
  5. #include "IncomingCall.h"
  6. #include "Agent.h"
  7. #include <map>
  8. CQueueMgr::CQueueMgr(void)
  9. {
  10. }
  11. CQueueMgr::~CQueueMgr(void)
  12. {
  13. __freeQueues();
  14. }
  15. /*****************************************************************
  16. **【函数名称】 __getQueue
  17. **【函数功能】 获取指定来电队列
  18. **【参数】
  19. **【返回值】
  20. ****************************************************************/
  21. CQueue* CQueueMgr::__getQueue(UINT QueueNo, bool NewWhenNull /*= false*/ )
  22. {
  23. for(int i = 0; i < m_QueueArray.GetCount(); ++i)
  24. {
  25. CQueue* pQueue = m_QueueArray[i];
  26. ASSERT(pQueue != NULL);
  27. if(pQueue->no() == QueueNo)
  28. return pQueue;
  29. }
  30. if(NewWhenNull)
  31. {
  32. CQueue* pQueue = new CQueue(QueueNo);
  33. m_QueueArray.Add(pQueue);
  34. return pQueue;
  35. }
  36. return NULL;
  37. }
  38. /*****************************************************************
  39. **【函数名称】 __freeQueues
  40. **【函数功能】 释放所有来电队列
  41. **【参数】
  42. **【返回值】
  43. ****************************************************************/
  44. void CQueueMgr::__freeQueues( void )
  45. {
  46. for(int i = 0; i < m_QueueArray.GetCount(); ++i)
  47. {
  48. CQueue* pQueue = m_QueueArray[i];
  49. ASSERT(pQueue != NULL);
  50. pQueue->clear();
  51. delete pQueue;
  52. pQueue = NULL;
  53. }
  54. m_QueueArray.RemoveAll();
  55. }
  56. /*****************************************************************
  57. **【函数名称】 onQueueAsking
  58. **【函数功能】 IVR请求座席命令响应
  59. **【参数】 pCmd: PDU命令内容
  60. pAgentOffice: 关联的座席管理类
  61. **【返回值】
  62. ****************************************************************/
  63. void CQueueMgr::onQueueAsking( CPduEntity* pCmd )
  64. {
  65. UINT QueueNo = pCmd->GetDataUInt(4);
  66. CQueue* pQueue = __getQueue(QueueNo, true);
  67. ASSERT(pQueue != NULL);
  68. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "{CQueueMgr}: 来电请求排队, Index = %d, CallID = %lu, Group = %lu, VipLevel = %d, CallerNum = %s",
  69. pCmd->GetDataInt(1),
  70. pCmd->GetDataULong(2),
  71. QueueNo,
  72. pCmd->GetDataInt(5),
  73. pCmd->GetDataString(6));
  74. pQueue->onQueueRequest(pCmd);
  75. }
  76. /*****************************************************************
  77. **【函数名称】 onQueueCancel
  78. **【函数功能】 IVR继续请求排队命令响应
  79. **【参数】 pCmd: PDU命令内容
  80. pAgentOffice: 关联的座席管理类
  81. **【返回值】
  82. ****************************************************************/
  83. void CQueueMgr::onQueueCancel( CPduEntity* pCmd )
  84. {
  85. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "{CQueueMgr}: 来电取消排队, Index = %d, CallId = %lu",
  86. pCmd->GetDataInt(1),
  87. pCmd->GetDataULong(2));
  88. for(int i = 0; i < m_QueueArray.GetCount(); ++i)
  89. {
  90. if(m_QueueArray[i]->onQueueCancel(pCmd))
  91. return;
  92. }
  93. }
  94. /*****************************************************************
  95. **【函数名称】 onQueueContinue
  96. **【函数功能】 IVR继续请求排队命令响应
  97. **【参数】 pCmd: 命令内容
  98. pAgentOffice: 关联的座席管理类
  99. **【返回值】
  100. ****************************************************************/
  101. void CQueueMgr::onQueueContinue( CPduEntity* pCmd )
  102. {
  103. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "{CQueueMgr}: 来电继续排队, Index = %d, CallId = %lu, CallerNum = %s",
  104. pCmd->GetDataInt(1),
  105. pCmd->GetDataULong(2),
  106. pCmd->GetDataString(4));
  107. for(int i = 0; i < m_QueueArray.GetCount(); ++i)
  108. {
  109. if(m_QueueArray[i]->onQueueContinue(pCmd))
  110. return;
  111. }
  112. }
  113. /*****************************************************************
  114. **【函数名称】 onQueuePause
  115. **【函数功能】 IVR暂停排队命令响应
  116. **【参数】 pCmd: PDU命令内容
  117. pAgentOffice: 关联的座席管理类
  118. **【返回值】
  119. ****************************************************************/
  120. void CQueueMgr::onQueuePause( CPduEntity* pCmd )
  121. {
  122. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "{Queue}: 来电暂停排队, Index = %d", pCmd->GetDataInt(0));
  123. for(int i = 0; i < m_QueueArray.GetCount(); ++i)
  124. {
  125. if(m_QueueArray[i]->onQueuePause(pCmd))
  126. return;
  127. }
  128. }
  129. void CQueueMgr::onUpdateCallIndex()
  130. {
  131. CString callIndex;
  132. for (int i = 0; i < m_QueueArray.GetCount(); ++i)
  133. {
  134. auto pQueue = m_QueueArray[i];
  135. callIndex += pQueue->callIndex();
  136. }
  137. pushCallIndex(callIndex.GetBuffer(0));
  138. callIndex.ReleaseBuffer();
  139. }
  140. bool CQueueMgr::GetFreeAgent(int GroupNo, UINT& AgentId, UINT& ExtenId)
  141. {
  142. CQueue* pQueue = __getQueue(GroupNo);
  143. if (pQueue)
  144. {
  145. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "[%s][%d]", __FUNCTION__, __LINE__);
  146. CAgent *pAgent = pQueue->GetFreeAgentForLoop();
  147. if (pAgent != NULL)
  148. {
  149. AgentId = pAgent->id();
  150. ExtenId = pAgent->assoExten();
  151. return true;
  152. }
  153. }
  154. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "[%s][%d]", __FUNCTION__, __LINE__);
  155. return false;
  156. }
  157. /*****************************************************************
  158. **【函数名称】 callCount
  159. **【函数功能】 读取等待排队的来电数量
  160. **【参数】
  161. **【返回值】
  162. ****************************************************************/
  163. UINT CQueueMgr::callCount( void )
  164. {
  165. UINT Count = 0;
  166. for(int i = 0; i < m_QueueArray.GetCount(); ++i)
  167. {
  168. Count += m_QueueArray[i]->callCount();
  169. }
  170. return Count;
  171. }
  172. /*****************************************************************
  173. **【函数名称】 callCount
  174. **【函数功能】 读取等待排队的来电数量
  175. **【参数】
  176. **【返回值】
  177. ****************************************************************/
  178. UINT CQueueMgr::callCount( UINT QueueNo )
  179. {
  180. CQueue* pQueue = __getQueue(QueueNo);
  181. if(pQueue != NULL)
  182. return pQueue->callCount();
  183. else
  184. return 0;
  185. }
  186. CString CQueueMgr::waitCount()
  187. {
  188. CString str;
  189. /*
  190. for (int i = 0; i < m_QueueArray.GetCount(); ++i)
  191. {
  192. str.Format("%d|%d#%s", m_QueueArray[i]->no(), m_QueueArray[i]->callCount(),str);
  193. }
  194. */
  195. // 2022-09-02 利用 m_queryCount去重
  196. m_QueryCount.clear();
  197. for (int i = 0; i < m_QueueArray.GetCount(); ++i)
  198. {
  199. m_QueryCount[m_QueueArray[i]->no()] = m_QueueArray[i]->callCount();
  200. }
  201. std::stringstream ss;
  202. auto it = m_QueryCount.begin();
  203. while (it != m_QueryCount.end())
  204. {
  205. ss << it->first << "|" << it->second << "#";
  206. ++it;
  207. }
  208. str.Format("%s", ss.str().c_str());
  209. return str;
  210. }
  211. UINT CQueueMgr::talkIngCount(UINT QueueNo)
  212. {
  213. CQueue* pQueue = __getQueue(QueueNo);
  214. if (pQueue != NULL)
  215. return pQueue->talkIngAgentCount();
  216. else
  217. return 0;
  218. }
  219. /*****************************************************************
  220. **【函数名称】 clear
  221. **【函数功能】 释放资源
  222. **【参数】
  223. **【返回值】
  224. ****************************************************************/
  225. void CQueueMgr::clear( void )
  226. {
  227. __freeQueues();
  228. }
  229. /*****************************************************************
  230. **【函数名称】 getCallInfo
  231. **【函数功能】 获取指定呼叫的相关信息用于UI展现
  232. **【参数】
  233. **【返回值】
  234. ****************************************************************/
  235. bool CQueueMgr::getCallInfo( Call2Show& Info )
  236. {
  237. for(int i = 0; i < m_QueueArray.GetCount(); ++i)
  238. {
  239. if(m_QueueArray[i]->getCallInfo(Info))
  240. return true;
  241. }
  242. return false;
  243. }
  244. /*****************************************************************
  245. **【函数名称】 addAgent
  246. **【函数功能】 添加座席
  247. **【参数】
  248. **【返回值】
  249. ****************************************************************/
  250. void CQueueMgr::addAgent( CAgent* pAgent )
  251. {
  252. ASSERT(pAgent != NULL);
  253. UINT GroupNo = 0;
  254. TCHAR AgentGroup[AGENT_GROUP_BUF_LEN] = { 0 };
  255. lstrcpy(AgentGroup, pAgent->group());
  256. AgentGroupNoList& GrouNoList = pAgent->groupNoList();
  257. TCHAR* lpNext = NULL;
  258. TCHAR* lpToken = strtok_s(AgentGroup, AGENT_GROUP_SPLIT_FLAG, &lpNext);
  259. while(lpToken != NULL)
  260. {
  261. sscanf_s(lpToken, "%u", &GroupNo);
  262. CQueue* pQueue = __getQueue(GroupNo, true);
  263. ASSERT(pQueue != NULL);
  264. GrouNoList.AddTail(GroupNo);
  265. pQueue->addAgent(pAgent);
  266. lpToken = strtok_s(NULL, AGENT_GROUP_SPLIT_FLAG, &lpNext);
  267. }
  268. }
  269. /*****************************************************************
  270. **【函数名称】 delAgent
  271. **【函数功能】 删除座席
  272. **【参数】
  273. **【返回值】
  274. ****************************************************************/
  275. void CQueueMgr::delAgent( CAgent* pAgent, bool isClear)
  276. {
  277. AgentGroupNoList& GrouNoList = pAgent->groupNoList();
  278. POSITION Pos = GrouNoList.GetHeadPosition();
  279. while(Pos != NULL)
  280. {
  281. UINT GroupNo = GrouNoList.GetNext(Pos);
  282. CQueue* pQueue = __getQueue(GroupNo);
  283. if(pQueue != NULL)
  284. pQueue->delAgent(pAgent,!isClear); // 2022-09-13 如果isclear是真,是cti断开造成,就传递false,不保存更新在线坐席信息
  285. }
  286. }
  287. /*****************************************************************
  288. **【函数名称】 onAgentFree
  289. **【函数功能】 座席的处理函数
  290. **【参数】
  291. **【返回值】
  292. ****************************************************************/
  293. void CQueueMgr::onAgentFree( CAgent* pAgent )
  294. {
  295. CQueue* pQueueDst = NULL;
  296. UINT CallCountMax = 0;
  297. AgentGroupNoList& GrouNoList = pAgent->groupNoList();
  298. // 查找排队呼叫最多的队列
  299. POSITION Pos = GrouNoList.GetHeadPosition();
  300. while(Pos != NULL)
  301. {
  302. UINT GroupNo = GrouNoList.GetNext(Pos);
  303. CQueue* pQueue = __getQueue(GroupNo);
  304. ASSERT(pQueue != NULL);
  305. UINT CallCout = pQueue->callCount();
  306. if(CallCout > CallCountMax)
  307. {
  308. pQueueDst = pQueue;
  309. CallCountMax = CallCout;
  310. }
  311. }
  312. if(CallCountMax > 0)
  313. pQueueDst->distributeAgent();
  314. }