中间件底层,websocket

Agent.cpp 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. #include "StdAfx.h"
  2. #include "Agent.h"
  3. #include "Config.h"
  4. #include "SLogic.h"
  5. #include "AcdCore.h"
  6. #include "MsgCenter.h"
  7. #include "NetworkAcd.h"
  8. #include "Exten.h"
  9. #include "YamlConfig.h"
  10. CAgent::CAgent(UINT a_AgentID, UINT a_ExtID, LPCTSTR a_GroupID, UINT a_AgentType, UINT a_PostProcessingTime)
  11. {
  12. // 网络属性
  13. //::GetInstance().getAgentLinkInfo(a_AgentID, m_AgentIp, m_AgentPort);
  14. // 基本属性
  15. m_AgentID = a_AgentID;
  16. m_Exten = a_ExtID;
  17. m_GroupID = a_GroupID;
  18. m_AgentType = (AGENT_TYPE)a_AgentType;
  19. m_State = AGENT_STATE_UNKNOWN;
  20. m_AssoExtState = INNER_STATE_FREE;
  21. m_IsRepose = false;
  22. m_bFirstQueue = true;
  23. // 业务属性
  24. m_AnswerCount = 0;
  25. m_ReposeCount = 0;
  26. m_TimeFree = 0;
  27. m_TimeRepos = 0;
  28. m_TimeTalk = 0;
  29. m_TypePostProcessing = CConfig::postProcessingType(); //2020-03-02 话后处理类型
  30. m_TimePostProcessing = (a_PostProcessingTime == 0) ? CConfig::postProcessingTime() : a_PostProcessingTime;
  31. /*******************2019-12-19**********************/
  32. m_AnswerCountOld = 0;
  33. m_ReposeCountOld = 0;
  34. m_TimeFreeOld = 0;
  35. m_TimeReposOld = 0;
  36. m_TimeTalkOld = 0;
  37. CString curDay;
  38. CTime tm;
  39. tm = CTime::GetCurrentTime();
  40. curDay = tm.Format("%Y-%m-%d ");
  41. CString startTime, endTime;
  42. startTime = "00:00";
  43. endTime = "23:59";
  44. startTime = curDay + startTime;
  45. endTime = curDay + endTime;
  46. YamlConfig* fig = YamlConfig::GetInstance();
  47. if (fig->GetIsUsed())
  48. {
  49. map<string, string> m_Times = fig->GetTimeMap();
  50. if (m_Times.size() > 0)
  51. {
  52. map<string, string>::iterator it = m_Times.begin();
  53. while (it != m_Times.end())
  54. {
  55. CTime ts = YamlConfig::timestr((curDay.GetString() + it->first).c_str()); // 开始时间
  56. CTime te = YamlConfig::timestr((curDay.GetString() + it->second).c_str()); // 结束时间
  57. if (ts > te) // 如果开始时间大于结束时间,则结束时间为第二天的时间
  58. te = te + CTimeSpan(1, 0, 0, 0);
  59. if (tm > ts && tm < te) // 当前时间在该时间段内则使用该考核时间段
  60. {
  61. startTime = ts.Format("%Y-%m-%d %H:%M");
  62. endTime = te.Format("%Y-%m-%d %H:%M");
  63. cout << startTime << "**" << endTime << endl;
  64. break;
  65. }
  66. cout << startTime << "遍历" << endTime << endl;
  67. ++it;
  68. }
  69. }
  70. CString sql;
  71. sql.Format("SELECT sum([FreeTimes])[FreeTimes],sum([ReposeTimes])[ReposeTimes] ,sum([TalkTimes])[TalkTimes] ,sum([ReposeNum])[ReposeNum],sum([AnswerNum])[AnswerNum] "
  72. "FROM [dbo].[rep_agent_detail] where AgentId = %d and TimeLogin between '%s' and '%s'", a_AgentID, startTime, endTime);
  73. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "初始化座席信息sql:%s", sql);
  74. IOtlConnection* pConn = IOtlConnection::getInstance();
  75. IOtlRecordset* record = pConn->QueryRecords(sql);
  76. if (record != NULL)
  77. {
  78. if (!record->IsEOF())
  79. {
  80. record->MoveNextRow();
  81. m_AnswerCountOld = record->GetValueInt("AnswerNum");
  82. m_ReposeCountOld = record->GetValueInt("ReposeNum");
  83. m_TimeFreeOld = record->GetValueInt("FreeTimes");
  84. m_TimeReposOld = record->GetValueInt("ReposeTimes");
  85. m_TimeTalkOld = record->GetValueInt("TalkTimes");
  86. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "初始化座席业务信息:AnswerNum = %d,ReposeNum = %d,FreeTimes = %d,ReposeTimes = %d,TalkTimes = %d", m_AnswerCountOld, m_ReposeCountOld, m_TimeFreeOld, m_TimeReposOld, m_TimeTalkOld);
  87. }
  88. }
  89. IOtlRecordset::DestroyInstance(record); // 释放记录集
  90. }
  91. /*************************************************/
  92. // 定时器初始化
  93. m_PollTimer.SetTimedEvent(this, &CAgent::__onTimerPoll);
  94. m_PollTimer.Start(1000);
  95. // 通知统计模块座席签入
  96. __reportLogin();
  97. // 添加消息可供视图刷新
  98. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (const PARAM)m_AgentID);
  99. }
  100. //CAgent::CAgent(UINT a_AgentID, UINT a_ExtID, LPCTSTR a_GroupID, UINT a_AgentType, const CAgentProperty& AgentProperty)
  101. //{
  102. // // 网络属性
  103. // CNetworkAcd::GetInstance().getAgentLinkInfo(a_AgentID, m_AgentIp, m_AgentPort);
  104. //
  105. // // 基本属性
  106. // m_AgentID = a_AgentID;
  107. // m_Exten = a_ExtID;
  108. // m_GroupID = a_GroupID;
  109. // m_AgentType = (AGENT_TYPE)a_AgentType;
  110. // m_State = AGENT_STATE_UNKNOWN;
  111. // m_AssoExtState = INNER_STATE_FREE;
  112. // m_IsRepose = false;
  113. //
  114. // // 业务属性
  115. // m_AnswerCount = AgentProperty.m_AnswerCount;
  116. // m_ReposeCount = AgentProperty.m_ReposeCount;
  117. // m_TimeFree = AgentProperty.m_TimeFree;
  118. // m_TimeRepos = AgentProperty.m_TimeRepos;
  119. // m_TimeTalk = AgentProperty.m_TimeTalk;
  120. // m_TimePostProcessing = (AgentProperty.m_TimePostProcessing == 0) ? CConfig::postProcessingTime() : AgentProperty.m_TimePostProcessing;
  121. //
  122. // // 定时器初始化
  123. // m_PollTimer.SetTimedEvent(this, &CAgent::__onTimerPoll);
  124. // m_PollTimer.Start(1000);
  125. // // 通知统计模块座席签入
  126. // __reportLogin();
  127. //
  128. // // 添加消息可供视图刷新
  129. // CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (const PARAM)m_AgentID);
  130. //}
  131. CAgent::~CAgent(void)
  132. {
  133. m_PollTimer.StopSafely();
  134. m_AgentTimer.StopSafely();
  135. }
  136. /*****************************************************************
  137. **【函数名称】 __reportLogin
  138. **【函数功能】 签出统计通知
  139. **【参数】
  140. **【返回值】
  141. ****************************************************************/
  142. void CAgent::__reportLogin()
  143. {
  144. // 通知统计模块 REP_EVENT_LOGIN
  145. T_EvtLogIn repLogin = { 0 };
  146. repLogin.nAgentID = m_AgentID;
  147. repLogin.nExtID = m_Exten;
  148. repLogin.nAgentType = m_AgentType;
  149. lstrcpy(repLogin.szGroup, m_GroupID);
  150. lstrcpy(repLogin.szAgentIP, m_AgentIp);
  151. CSLogic::GetInstance().onSEvent(m_AgentID, m_Exten, REP_EVENT_LOGIN, &repLogin, m_GroupID); // 2021-11-10 签入时传递组号;
  152. }
  153. /*****************************************************************
  154. **【函数名称】 __reportLogout
  155. **【函数功能】 签出统计通知
  156. **【参数】 HostAgent: 签出当前座席的主控座席
  157. **【返回值】
  158. ****************************************************************/
  159. void CAgent::__reportLogout(const UINT HostAgent)
  160. {
  161. if (m_State == AGENT_STATE_REPOSE)
  162. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  163. if (m_State == AGENT_STATE_POST_PROCESSING)
  164. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  165. if (m_State == AGENT_STATE_FREE)
  166. __onStatusUpdate(AGENT_STATE_FREE, false);
  167. // 通知统计模块 REP_EVENT_LOGOUT
  168. T_EvtLogout repLogout = { 0 };
  169. repLogout.nLogoutHost = HostAgent;
  170. repLogout.nTimeFree = m_TimeFree;
  171. repLogout.nTimeRepose = m_TimeRepos;
  172. repLogout.nTimeTalk = m_TimeTalk;
  173. repLogout.nAnswerCount = m_AnswerCount;
  174. repLogout.nReposeCount = m_ReposeCount;
  175. CSLogic::GetInstance().onSEvent(m_AgentID, m_Exten, REP_EVENT_LOGOUT, &repLogout);
  176. }
  177. /*****************************************************************
  178. **【函数名称】 __onStatusUpdate
  179. **【函数功能】 座席状态变更通知
  180. **【参数】
  181. **【返回值】
  182. ****************************************************************/
  183. void CAgent::__onStatusUpdate(AGENT_STATE State, bool StartFlag)
  184. {
  185. T_EvtStatus EvtStatus;
  186. EvtStatus.State = State;
  187. EvtStatus.StartFlag = StartFlag;
  188. CSLogic::GetInstance().onSEvent(m_AgentID, m_Exten, REP_EVENT_STATE, &EvtStatus);
  189. }
  190. /*****************************************************************
  191. **【函数名称】 __reportStatus
  192. **【函数功能】 通知各方座席当前状态
  193. **【参数】
  194. **【返回值】
  195. ****************************************************************/
  196. void CAgent::__reportStatus(void)
  197. {
  198. // 通知OCX座席当前状态
  199. CPduEntity Cmd(PDU_CMD_ACD_AGENT_STATE);
  200. Cmd.SetDataUInt(0, m_Exten);
  201. Cmd.SetDataUInt(1, m_AgentID);
  202. Cmd.SetDataUInt(2, m_State);
  203. //CNetworkAcd::GetInstance().send2Agent(m_AgentID, &Cmd);
  204. CNetworkAcd::GetInstance().send2Server(&Cmd);
  205. // 添加消息可供视图刷新
  206. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (PARAM)m_AgentID);
  207. }
  208. /*****************************************************************
  209. **【函数名称】 __reportStatus
  210. **【函数功能】 通知各方座席当前状态
  211. **【参数】
  212. **【返回值】
  213. ych 2018.5.17
  214. ****************************************************************
  215. void CAgent::__reportStatus(void)
  216. {
  217. CExten* pExten = CAcdCore::GetInstance().getExtenCtrl().getExten(m_Exten); // 获取指定分机
  218. if (pExten == NULL)
  219. {
  220. // 显示日志 ych 2018.5.17
  221. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_ERROR, _T("{CAgent::__reportStatus}: pExten指针为NULL"));
  222. return;
  223. }
  224. if (m_AgentID !=0 && m_AgentID == pExten->assoAgent())
  225. {
  226. CPduEntity Cmd(PDU_CMD_CTI_LINE_STATE);
  227. Cmd.SetDataUInt(0, pExten->GetID());
  228. Cmd.SetDataUInt(1, pExten->GetState());
  229. Cmd.SetDataULong(2, pExten->GetCallId());
  230. Cmd.SetDataUInt(3, pExten->GetAssoAgent());
  231. Cmd.SetDataString(4, pExten->GetCallerNum());
  232. Cmd.SetDataString(5, pExten->GetCalleeNum());
  233. Cmd.SetDataString(6, pExten->GetDataBind());
  234. Cmd.SetDataUInt(7, pExten->GetPeerLineType());
  235. Cmd.SetDataUInt(8, pExten->GetInfoEx());
  236. Cmd.SetDataUInt(9, pExten->GetFinalExt());
  237. Cmd.SetDataUInt(10, pExten->GetOpType());
  238. Cmd.SetDataUInt(11, 0);
  239. Cmd.SetDataUInt(12, m_State);
  240. //CNetworkAcd::GetInstance().send2Agent(m_AssoAgent, &Cmd);
  241. CNetworkAcd::GetInstance().send2Server(&Cmd);
  242. // 显示日志 ych 2018.5.17
  243. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CAgent::__reportStatus}: 返回线路及座席状态"));
  244. // 添加消息可供视图刷新
  245. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (PARAM)m_AgentID);
  246. }
  247. }*/
  248. /*****************************************************************
  249. **【函数名称】 __onTimerPoll
  250. **【函数功能】 轮询定时器处理
  251. **【参数】
  252. **【返回值】
  253. ****************************************************************/
  254. void CAgent::__onTimerPoll(void)
  255. {
  256. if (m_State == AGENT_STATE_FREE)
  257. m_TimeFree++;
  258. else if (m_State == AGENT_STATE_BUSY)
  259. m_TimeTalk++;
  260. if (m_IsRepose)
  261. m_TimeRepos++;
  262. }
  263. /*****************************************************************
  264. **【函数名称】 __onTimerPostProcessing
  265. **【函数功能】 话后处理时长定时器处理
  266. **【参数】
  267. **【返回值】
  268. ****************************************************************/
  269. void CAgent::__onTimerPostProcessing(void)
  270. {
  271. if (m_State == AGENT_STATE_POST_PROCESSING)
  272. {
  273. //setState(AGENT_STATE_FREE);
  274. setFreeForAgentCall(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  275. }
  276. }
  277. /*****************************************************************
  278. **【函数名称】 __onTimerLock
  279. **【函数功能】 座席被锁定超时处理
  280. **【参数】
  281. **【返回值】
  282. ****************************************************************/
  283. void CAgent::__onTimerLock(void)
  284. {
  285. if (m_State == AGENT_STATE_REQUESTED)
  286. {
  287. //setState(AGENT_STATE_FREE, true);
  288. setFreeForAgentCall(true); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  289. }
  290. }
  291. /*****************************************************************
  292. **【函数名称】 __setTimer
  293. **【函数功能】 设立定时器
  294. **【参数】
  295. **【返回值
  296. ****************************************************************/
  297. void CAgent::__setTimer(UINT TimmerId, UINT Elapse)
  298. {
  299. if (TimmerId == TIMER_POST_PROCESSING)
  300. {
  301. m_AgentTimer.StopSafely();
  302. m_AgentTimer.SetTimedEvent(this, &CAgent::__onTimerPostProcessing);
  303. m_AgentTimer.Start(Elapse, false, true, WT_EXECUTEDEFAULT);
  304. }
  305. else if (TimmerId == TIMER_LOCK_PERIOD)
  306. {
  307. m_AgentTimer.StopSafely();
  308. m_AgentTimer.SetTimedEvent(this, &CAgent::__onTimerLock);
  309. m_AgentTimer.Start(Elapse, false, true, WT_EXECUTEDEFAULT);
  310. }
  311. else
  312. {
  313. ASSERT(FALSE);
  314. }
  315. }
  316. /*****************************************************************
  317. **【函数名称】 __killTimer
  318. **【函数功能】 删除定时器
  319. **【参数】
  320. **【返回值
  321. ****************************************************************/
  322. void CAgent::__killTimer(UINT TimmerId)
  323. {
  324. m_AgentTimer.Stop();
  325. }
  326. /*****************************************************************
  327. **【函数名称】 release
  328. **【函数功能】 清理资源
  329. **【参数】 HostAgent: 主控制坐席工号
  330. **【返回值】
  331. ****************************************************************/
  332. void CAgent::release(UINT HostAgent)
  333. {
  334. m_PollTimer.StopSafely();
  335. m_AgentTimer.StopSafely();
  336. // 设置状态为注销
  337. setState(AGENT_STATE_LOGOUT);
  338. // 通知统计模块 REP_EVENT_LOGOUT
  339. __reportLogout(HostAgent);
  340. // 关闭Agent端SOCKET连接
  341. //CNetworkAcd::GetInstance().shutDownAgentLink(m_AgentID);
  342. // 添加消息可供视图刷新
  343. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_LOGOUT, (const PARAM)m_AgentID);
  344. }
  345. /*****************************************************************
  346. **【函数名称】 setState
  347. **【函数功能】 设置座席状态
  348. **【参数】 a_AgentState:座席当前逻辑状态
  349. **【返回值】
  350. ****************************************************************/
  351. BOOL CAgent::setState(AGENT_STATE a_AgentState, bool IsForce/* = false*/)
  352. {
  353. switch (a_AgentState)
  354. {
  355. case AGENT_STATE_BUSY: // 通话
  356. {
  357. switch (m_State)
  358. {
  359. case AGENT_STATE_BUSY:
  360. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  361. return TRUE;
  362. break;
  363. case AGENT_STATE_REQUESTED:
  364. __killTimer(TIMER_LOCK_PERIOD);
  365. break;
  366. case AGENT_STATE_POST_PROCESSING:
  367. {
  368. __killTimer(TIMER_POST_PROCESSING);
  369. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  370. }
  371. break;
  372. case AGENT_STATE_REPOSE:
  373. {
  374. m_IsRepose = false;
  375. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  376. }
  377. break;
  378. case AGENT_STATE_LOGOUT:
  379. return FALSE;
  380. break;
  381. }
  382. __onStatusUpdate(AGENT_STATE_BUSY, true);
  383. m_State = AGENT_STATE_BUSY;
  384. }
  385. break;
  386. case AGENT_STATE_REPOSE: // 小休
  387. {
  388. switch (m_State)
  389. {
  390. case AGENT_STATE_REPOSE:
  391. m_IsRepose = true; // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  392. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  393. return TRUE;
  394. break;
  395. case AGENT_STATE_POST_PROCESSING:
  396. {
  397. __killTimer(TIMER_POST_PROCESSING);
  398. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  399. }
  400. break;
  401. case AGENT_STATE_BUSY:
  402. case AGENT_STATE_LOGOUT:
  403. case AGENT_STATE_REQUESTED:
  404. return FALSE;
  405. break;
  406. case AGENT_STATE_FREE: // 2021-11-22 保存坐席空闲状态结束
  407. __onStatusUpdate(AGENT_STATE_FREE, false);
  408. break;
  409. }
  410. m_ReposeCount++;
  411. m_IsRepose = true;
  412. m_State = AGENT_STATE_REPOSE;
  413. // 统计小休开始
  414. __onStatusUpdate(AGENT_STATE_REPOSE, true);
  415. }
  416. break;
  417. case AGENT_STATE_POST_PROCESSING: // 话后处理
  418. {
  419. // 电话挂断后重新计算空闲时长 2020-03-05
  420. YamlConfig* fig = YamlConfig::GetInstance();
  421. if (!fig->GetIsUsed()&&fig->GetIsResetFreeTime())
  422. {
  423. m_TimeFree = 0;
  424. }
  425. //
  426. switch (m_State)
  427. {
  428. case AGENT_STATE_POST_PROCESSING:
  429. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  430. return TRUE;
  431. break;
  432. case AGENT_STATE_BUSY:
  433. __onStatusUpdate(AGENT_STATE_BUSY, false);
  434. break;
  435. case AGENT_STATE_FREE:
  436. case AGENT_STATE_REPOSE:
  437. case AGENT_STATE_REQUESTED:
  438. case AGENT_STATE_LOGOUT:
  439. return FALSE;
  440. break;
  441. }
  442. // 统计话后处理开始
  443. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, true);
  444. m_State = AGENT_STATE_POST_PROCESSING;
  445. //if (m_TimePostProcessing > 0)
  446. // __setTimer(TIMER_POST_PROCESSING, m_TimePostProcessing * 1000); // 启动话后处理定时器
  447. if (m_TimePostProcessing > 0 && m_TypePostProcessing==0) // 2020-03-02
  448. __setTimer(TIMER_POST_PROCESSING, m_TimePostProcessing * 1000); // 启动话后处理定时器
  449. }
  450. break;
  451. case AGENT_STATE_FREE: // 空闲
  452. {
  453. switch (m_State)
  454. {
  455. case AGENT_STATE_FREE:
  456. m_IsRepose = false; // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  457. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  458. return TRUE;
  459. break;
  460. case AGENT_STATE_BUSY:
  461. {
  462. if (IsForce)
  463. __onStatusUpdate(AGENT_STATE_BUSY, false);
  464. else
  465. return FALSE;
  466. }
  467. break;
  468. case AGENT_STATE_POST_PROCESSING:
  469. {
  470. __killTimer(TIMER_POST_PROCESSING);
  471. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  472. }
  473. break;
  474. case AGENT_STATE_REPOSE:
  475. {
  476. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  477. __onStatusUpdate(AGENT_STATE_FREE, true); // 2021 - 11 - 22 保存坐席空闲状态开始
  478. m_IsRepose = false;
  479. }
  480. break;
  481. case AGENT_STATE_REQUESTED:
  482. {
  483. if (IsForce)
  484. __killTimer(TIMER_LOCK_PERIOD);
  485. else
  486. return FALSE;
  487. }
  488. break;
  489. case AGENT_STATE_LOGOUT:
  490. return FALSE;
  491. break;
  492. }
  493. m_State = m_IsRepose ? AGENT_STATE_REPOSE : AGENT_STATE_FREE;
  494. }
  495. break;
  496. case AGENT_STATE_REQUESTED: // 被请求
  497. {
  498. ASSERT(m_State == AGENT_STATE_FREE);
  499. switch (m_State)
  500. {
  501. case AGENT_STATE_REQUESTED:
  502. case AGENT_STATE_BUSY:
  503. case AGENT_STATE_REPOSE:
  504. case AGENT_STATE_POST_PROCESSING:
  505. case AGENT_STATE_LOGOUT:
  506. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  507. return FALSE;
  508. break;
  509. }
  510. if (AGENT_STATE_FREE == m_State)
  511. __onStatusUpdate(AGENT_STATE_FREE, false); // 2021-11-22 添加保存坐席空闲->被请求,空闲结束
  512. __setTimer(TIMER_LOCK_PERIOD, CConfig::agentLockedPeriod() * 1000); // 被请求超时处理定时器
  513. m_State = AGENT_STATE_REQUESTED;
  514. __onStatusUpdate(AGENT_STATE_REQUESTED, true); // 2021-11-22 添加保存坐席被请求开始,外线呼入锁定坐席
  515. }
  516. break;
  517. default:
  518. {
  519. switch (m_State)
  520. {
  521. case AGENT_STATE_BUSY:
  522. __onStatusUpdate(AGENT_STATE_BUSY, false);
  523. break;
  524. case AGENT_STATE_POST_PROCESSING:
  525. {
  526. __killTimer(TIMER_POST_PROCESSING);
  527. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  528. }
  529. break;
  530. case AGENT_STATE_REPOSE:
  531. {
  532. m_IsRepose = false;
  533. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  534. }
  535. break;
  536. case AGENT_STATE_REQUESTED:
  537. //__killTimer(TIMER_LOCK_PERIOD);
  538. if (a_AgentState != AGENT_STATE_LOGOUT) // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  539. {
  540. __killTimer(TIMER_LOCK_PERIOD);
  541. }
  542. else // 被请求或者座席锁定签出失败
  543. {
  544. if (!IsForce) // 如果强制签出时,返回true
  545. return FALSE;
  546. }
  547. break;
  548. }
  549. m_State = a_AgentState;
  550. }
  551. break;
  552. } // end switch
  553. // 通知座席当前状态变化
  554. __reportStatus();
  555. __onStatusUpdate(m_State, true);
  556. return TRUE;
  557. }
  558. bool CAgent::sendState(AGENT_STATE a_AgentState)
  559. {
  560. switch (a_AgentState)
  561. {
  562. case AGENT_STATE_FREE: // 空闲
  563. {
  564. if (m_IsRepose)
  565. {
  566. m_State = AGENT_STATE_REPOSE;
  567. }
  568. __reportStatus();
  569. }
  570. case AGENT_STATE_REPOSE: // 小休
  571. {
  572. __onStatusUpdate(AGENT_STATE_REQUESTED, false);
  573. __onStatusUpdate(m_State, true);
  574. __reportStatus();
  575. }
  576. break;
  577. }
  578. return false;
  579. }
  580. BOOL CAgent::setFreeForAgentCall(bool IsForce)
  581. {
  582. switch (m_State)
  583. {
  584. case AGENT_STATE_FREE:
  585. return TRUE;
  586. break;
  587. case AGENT_STATE_BUSY:
  588. {
  589. if (IsForce)
  590. {
  591. __onStatusUpdate(AGENT_STATE_BUSY, false);
  592. }
  593. else
  594. return FALSE;
  595. }
  596. break;
  597. case AGENT_STATE_POST_PROCESSING:
  598. {
  599. __killTimer(TIMER_POST_PROCESSING);
  600. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  601. }
  602. break;
  603. case AGENT_STATE_REPOSE:
  604. {
  605. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  606. //m_IsRepose = false;
  607. }
  608. break;
  609. case AGENT_STATE_REQUESTED:
  610. {
  611. if (IsForce)
  612. {
  613. __killTimer(TIMER_LOCK_PERIOD);
  614. __onStatusUpdate(AGENT_STATE_REQUESTED, false); // 2021-1-22 保存坐席状态,被请求结束
  615. }
  616. else
  617. return FALSE;
  618. }
  619. break;
  620. case AGENT_STATE_LOGOUT:
  621. return FALSE;
  622. break;
  623. }
  624. // 2021-11-22
  625. AGENT_STATE state = m_State;
  626. // 2021-11-19 添加if条件 小休情况下,通话后仍为小休 2022-06-23 添加状态为被请求(外呼时,被叫拒接),由通话中改为通话中或被请求为真
  627. if (m_IsRepose &&IsForce && (m_State == AGENT_STATE_BUSY || m_State == AGENT_STATE_REQUESTED))
  628. m_State = AGENT_STATE_REPOSE;
  629. else
  630. m_State = AGENT_STATE_FREE;
  631. if (IsForce && ((m_State == AGENT_STATE_FREE && state != AGENT_STATE_FREE) || (m_State == AGENT_STATE_REPOSE && state != AGENT_STATE_REPOSE)) && (state == AGENT_STATE_REQUESTED && state == AGENT_STATE_BUSY)) // 2021-11-22 添加保存坐席通话结束后的状态(闲/忙)开始 (被请求不处理(锁定超时))
  632. {
  633. __onStatusUpdate(m_State, true); // 2021-11-22 添加保存坐席通话结束后的状态(闲/忙)开始
  634. }
  635. //if (m_IsRepose == false) //2021-11-23 小休状态下外呼后向前端推送小休的坐席状态
  636. if ((m_IsRepose == false && (m_AssoExtState!= INNER_STATE_RING_BACK|| m_AssoExtState != INNER_STATE_ALERTING)) || state == AGENT_STATE_BUSY)
  637. {
  638. __reportStatus();
  639. }
  640. return TRUE;
  641. }
  642. BOOL CAgent::setRequestedForAgentCall(bool IsForce)
  643. {
  644. ASSERT(m_State == AGENT_STATE_FREE);
  645. switch (m_State)
  646. {
  647. case AGENT_STATE_REQUESTED:
  648. case AGENT_STATE_BUSY:
  649. case AGENT_STATE_REPOSE:
  650. case AGENT_STATE_POST_PROCESSING:
  651. case AGENT_STATE_LOGOUT:
  652. return FALSE;
  653. break;
  654. }
  655. __onStatusUpdate(AGENT_STATE_FREE, false); // 2021-11-22 添加保存坐席空闲结束,变为被请求
  656. __setTimer(TIMER_LOCK_PERIOD, CConfig::agentLockedPeriod() * 1000); // 被请求超时处理定时器
  657. m_State = AGENT_STATE_REQUESTED;
  658. __onStatusUpdate(AGENT_STATE_REQUESTED, true); // 2021-11-22 添加保存坐席被请求开始,系统外呼锁定当前坐席
  659. if (m_IsRepose == false)
  660. __reportStatus();
  661. return TRUE;
  662. }
  663. BOOL CAgent::setBusyForAgentCall(bool IsForce)
  664. {
  665. if (IsForce && (m_State == AGENT_STATE_FREE || m_State == AGENT_STATE_REPOSE)) // 2021-11-22 添加保存坐席通话结束后的状态(闲/忙)结束
  666. {
  667. __onStatusUpdate(m_State, false); // 2021-11-22 添加保存坐席通话结束后的状态(闲/忙)结束
  668. }
  669. switch (m_State)
  670. {
  671. case AGENT_STATE_BUSY:
  672. return TRUE;
  673. break;
  674. case AGENT_STATE_REQUESTED:
  675. __killTimer(TIMER_LOCK_PERIOD);
  676. break;
  677. case AGENT_STATE_POST_PROCESSING:
  678. {
  679. __killTimer(TIMER_POST_PROCESSING);
  680. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  681. }
  682. break;
  683. case AGENT_STATE_REPOSE:
  684. {
  685. //m_IsRepose = false;
  686. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  687. }
  688. break;
  689. case AGENT_STATE_LOGOUT:
  690. return FALSE;
  691. break;
  692. }
  693. __onStatusUpdate(AGENT_STATE_BUSY, true);
  694. m_State = AGENT_STATE_BUSY;
  695. if (m_IsRepose == false)
  696. __reportStatus();
  697. return TRUE;
  698. }
  699. BOOL CAgent::setProcessingForAgentCall(bool IsForce)
  700. {
  701. switch (m_State)
  702. {
  703. case AGENT_STATE_POST_PROCESSING:
  704. return TRUE;
  705. break;
  706. case AGENT_STATE_BUSY:
  707. __onStatusUpdate(AGENT_STATE_BUSY, false);
  708. break;
  709. case AGENT_STATE_FREE:
  710. case AGENT_STATE_REPOSE:
  711. case AGENT_STATE_REQUESTED:
  712. case AGENT_STATE_LOGOUT:
  713. return FALSE;
  714. break;
  715. }
  716. // 统计话后处理开始
  717. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, true);
  718. m_State = AGENT_STATE_POST_PROCESSING;
  719. if (m_TimePostProcessing > 0)
  720. __setTimer(TIMER_POST_PROCESSING, m_TimePostProcessing * 1000); // 启动话后处理定时器
  721. //if (m_IsRepose == false) // 2022-02-24 置忙下的外呼后,话后处理状态,因此屏蔽 取消置忙标识
  722. m_IsRepose = false;
  723. __reportStatus();
  724. return TRUE;
  725. }
  726. /*****************************************************************
  727. **【函数名称】 onAssoExtStatusUpdated
  728. **【函数功能】 关联分机状态更新的处理函数
  729. **【参数】 a_ExtState:分机当前状态
  730. Param:附加参数
  731. **【返回值】
  732. ****************************************************************/
  733. void CAgent::onAssoExtStatusUpdated(INNER_STATE a_ExtState, PARAM Param /*= NULL*/)
  734. {
  735. CPduEntity * pCmd = (CPduEntity *)Param;
  736. m_AssoExtState = a_ExtState;
  737. switch (a_ExtState)
  738. {
  739. case INNER_STATE_ALERTING:
  740. {
  741. if (m_State == AGENT_STATE_POST_PROCESSING || m_State == AGENT_STATE_REPOSE /*|| m_State == AGENT_STATE_REQUESTED*/)
  742. setFreeForAgentCall(true);
  743. //setState(AGENT_STATE_FREE, true);
  744. }
  745. break;
  746. case INNER_STATE_RING_BACK:
  747. {
  748. if (m_State == AGENT_STATE_POST_PROCESSING || m_State == AGENT_STATE_REPOSE /*|| m_State == AGENT_STATE_REQUESTED*/) //2021-11-24 外呼被请求多了个空闲推送
  749. setFreeForAgentCall(true);
  750. //setState(AGENT_STATE_FREE, true);
  751. }
  752. break;
  753. case INNER_STATE_TALKING:
  754. {
  755. if (pCmd == NULL || pCmd->GetDataUInt(10) != PDU_CMD_AGENT_MONI_REPLACE) // 如果是代接操作则不记录应答次数
  756. m_AnswerCount++; // 累计应答计数
  757. //setState(AGENT_STATE_BUSY, true);
  758. setBusyForAgentCall(true);
  759. }
  760. break;
  761. case INNER_STATE_FREE:
  762. {
  763. if (m_State == AGENT_STATE_BUSY)
  764. {
  765. ASSERT(pCmd != NULL);
  766. setProcessingForAgentCall();
  767. /* 2022-02-28 通话中变空闲,状态为话后处理
  768. // 关联线路为非内线,最后通话分机为当前分机,则需要进行话后处理
  769. if (pCmd != NULL && pCmd->GetDataUInt(7) != DEV_RES_TYPE_EXT && (pCmd->GetDataUInt(9) == m_Exten || pCmd->GetDataUInt(12) == 1)) // 2022-01-05 pdu-12 为是否在会议,在会议时最后应答分机不等于当前分机,也弹出
  770. //setState(AGENT_STATE_POST_PROCESSING);
  771. setProcessingForAgentCall();
  772. else
  773. //setState(AGENT_STATE_FREE, true);
  774. setFreeForAgentCall(true);
  775. */
  776. }
  777. else if (m_State == AGENT_STATE_UNKNOWN || m_State == AGENT_STATE_REQUESTED)
  778. //setState(AGENT_STATE_FREE, true);
  779. setFreeForAgentCall(true);
  780. /*
  781. else if (m_State == AGENT_STATE_FREE &&!m_IsRepose) // 2022-01-07 话机外呼失败,空闲变空闲,增加坐席状态回复空闲
  782. sendState(AGENT_STATE_FREE);
  783. else if (m_State == AGENT_STATE_FREE && m_IsRepose) // 2022-07-07 置忙情况下话机外呼后,发送话机忙
  784. sendState(AGENT_STATE_REPOSE);
  785. else if(m_State == AGENT_STATE_REPOSE) // 2022-07-07 小休状态下外呼失败后,向坐席发送小休状态
  786. sendState(AGENT_STATE_REPOSE);
  787. */
  788. else if(m_State == AGENT_STATE_FREE|| m_State == AGENT_STATE_REPOSE)
  789. sendState(m_State);
  790. }
  791. break;
  792. default:
  793. {
  794. if (m_State == AGENT_STATE_UNKNOWN)
  795. setState(AGENT_STATE_FREE);
  796. }
  797. break;
  798. }
  799. }
  800. /*****************************************************************
  801. **【函数名称】 lock
  802. **【函数功能】 锁定座席
  803. **【参数】
  804. **【返回值】
  805. ****************************************************************/
  806. BOOL CAgent::lock(void)
  807. {
  808. if (isFree())
  809. return setState(AGENT_STATE_REQUESTED);
  810. else
  811. return FALSE;
  812. }
  813. BOOL CAgent::lockForCall(void)
  814. {
  815. if (isFreeForCall())
  816. return setRequestedForAgentCall();
  817. //return setState(AGENT_STATE_REQUESTED);
  818. else
  819. return FALSE;
  820. }
  821. void CAgent::GetAgentProperty(CAgentProperty& AgentProperty)
  822. {
  823. AgentProperty.m_AnswerCount = m_AnswerCount;
  824. AgentProperty.m_ReposeCount = m_ReposeCount;
  825. AgentProperty.m_TimeFree = m_TimeFree;
  826. AgentProperty.m_TimePostProcessing = m_TimePostProcessing;
  827. AgentProperty.m_TimeRepos = m_TimeRepos;
  828. AgentProperty.m_TimeTalk = m_TimeTalk;
  829. }
  830. bool CAgent::queueJump()
  831. {
  832. if (m_bFirstQueue) {
  833. m_bFirstQueue = false;
  834. return true;
  835. }
  836. else
  837. {
  838. return false;
  839. }
  840. }