Sin descripción

Agent.cpp 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  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. CNetworkAcd::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. CSingleLock Locker(&m_Cs4Lock, TRUE);
  354. switch (a_AgentState)
  355. {
  356. case AGENT_STATE_BUSY: // 通话
  357. {
  358. switch (m_State)
  359. {
  360. case AGENT_STATE_BUSY:
  361. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  362. return TRUE;
  363. break;
  364. case AGENT_STATE_REQUESTED:
  365. __killTimer(TIMER_LOCK_PERIOD);
  366. break;
  367. case AGENT_STATE_POST_PROCESSING:
  368. {
  369. __killTimer(TIMER_POST_PROCESSING);
  370. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  371. }
  372. break;
  373. case AGENT_STATE_REPOSE:
  374. {
  375. m_IsRepose = false;
  376. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  377. }
  378. break;
  379. case AGENT_STATE_LOGOUT:
  380. return FALSE;
  381. break;
  382. }
  383. __onStatusUpdate(AGENT_STATE_BUSY, true);
  384. m_State = AGENT_STATE_BUSY;
  385. }
  386. break;
  387. case AGENT_STATE_REPOSE: // 小休
  388. {
  389. switch (m_State)
  390. {
  391. case AGENT_STATE_REPOSE:
  392. m_IsRepose = true; // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  393. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  394. return TRUE;
  395. break;
  396. case AGENT_STATE_POST_PROCESSING:
  397. {
  398. __killTimer(TIMER_POST_PROCESSING);
  399. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  400. }
  401. break;
  402. case AGENT_STATE_BUSY:
  403. case AGENT_STATE_LOGOUT:
  404. case AGENT_STATE_REQUESTED:
  405. return FALSE;
  406. break;
  407. case AGENT_STATE_FREE: // 2021-11-22 保存坐席空闲状态结束
  408. __onStatusUpdate(AGENT_STATE_FREE, false);
  409. break;
  410. }
  411. m_ReposeCount++;
  412. m_IsRepose = true;
  413. m_State = AGENT_STATE_REPOSE;
  414. // 统计小休开始
  415. __onStatusUpdate(AGENT_STATE_REPOSE, true);
  416. }
  417. break;
  418. case AGENT_STATE_POST_PROCESSING: // 话后处理
  419. {
  420. // 电话挂断后重新计算空闲时长 2020-03-05
  421. YamlConfig* fig = YamlConfig::GetInstance();
  422. if (!fig->GetIsUsed()&&fig->GetIsResetFreeTime())
  423. {
  424. m_TimeFree = 0;
  425. }
  426. //
  427. switch (m_State)
  428. {
  429. case AGENT_STATE_POST_PROCESSING:
  430. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  431. return TRUE;
  432. break;
  433. case AGENT_STATE_BUSY:
  434. __onStatusUpdate(AGENT_STATE_BUSY, false);
  435. break;
  436. case AGENT_STATE_FREE:
  437. case AGENT_STATE_REPOSE:
  438. case AGENT_STATE_REQUESTED:
  439. case AGENT_STATE_LOGOUT:
  440. return FALSE;
  441. break;
  442. }
  443. // 统计话后处理开始
  444. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, true);
  445. m_State = AGENT_STATE_POST_PROCESSING;
  446. //if (m_TimePostProcessing > 0)
  447. // __setTimer(TIMER_POST_PROCESSING, m_TimePostProcessing * 1000); // 启动话后处理定时器
  448. if (m_TimePostProcessing > 0 && m_TypePostProcessing==0) // 2020-03-02
  449. __setTimer(TIMER_POST_PROCESSING, m_TimePostProcessing * 1000); // 启动话后处理定时器
  450. }
  451. break;
  452. case AGENT_STATE_FREE: // 空闲
  453. {
  454. switch (m_State)
  455. {
  456. case AGENT_STATE_FREE:
  457. m_IsRepose = false; // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  458. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  459. return TRUE;
  460. break;
  461. case AGENT_STATE_BUSY:
  462. {
  463. if (IsForce)
  464. __onStatusUpdate(AGENT_STATE_BUSY, false);
  465. else
  466. return FALSE;
  467. }
  468. break;
  469. case AGENT_STATE_POST_PROCESSING:
  470. {
  471. __killTimer(TIMER_POST_PROCESSING);
  472. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  473. }
  474. break;
  475. case AGENT_STATE_REPOSE:
  476. {
  477. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  478. __onStatusUpdate(AGENT_STATE_FREE, true); // 2021 - 11 - 22 保存坐席空闲状态开始
  479. m_IsRepose = false;
  480. }
  481. break;
  482. case AGENT_STATE_REQUESTED:
  483. {
  484. if (IsForce)
  485. __killTimer(TIMER_LOCK_PERIOD);
  486. else
  487. return FALSE;
  488. }
  489. break;
  490. case AGENT_STATE_LOGOUT:
  491. return FALSE;
  492. break;
  493. }
  494. m_State = m_IsRepose ? AGENT_STATE_REPOSE : AGENT_STATE_FREE;
  495. }
  496. break;
  497. case AGENT_STATE_REQUESTED: // 被请求
  498. {
  499. ASSERT(m_State == AGENT_STATE_FREE);
  500. switch (m_State)
  501. {
  502. case AGENT_STATE_REQUESTED:
  503. case AGENT_STATE_BUSY:
  504. case AGENT_STATE_REPOSE:
  505. case AGENT_STATE_POST_PROCESSING:
  506. case AGENT_STATE_LOGOUT:
  507. __reportStatus(); // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  508. return FALSE;
  509. break;
  510. }
  511. if (AGENT_STATE_FREE == m_State)
  512. __onStatusUpdate(AGENT_STATE_FREE, false); // 2021-11-22 添加保存坐席空闲->被请求,空闲结束
  513. __setTimer(TIMER_LOCK_PERIOD, CConfig::agentLockedPeriod() * 1000); // 被请求超时处理定时器
  514. m_State = AGENT_STATE_REQUESTED;
  515. __onStatusUpdate(AGENT_STATE_REQUESTED, true); // 2021-11-22 添加保存坐席被请求开始,外线呼入锁定坐席
  516. }
  517. break;
  518. default:
  519. {
  520. switch (m_State)
  521. {
  522. case AGENT_STATE_BUSY:
  523. __onStatusUpdate(AGENT_STATE_BUSY, false);
  524. break;
  525. case AGENT_STATE_POST_PROCESSING:
  526. {
  527. __killTimer(TIMER_POST_PROCESSING);
  528. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  529. }
  530. break;
  531. case AGENT_STATE_REPOSE:
  532. {
  533. m_IsRepose = false;
  534. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  535. }
  536. break;
  537. case AGENT_STATE_REQUESTED:
  538. //__killTimer(TIMER_LOCK_PERIOD);
  539. if (a_AgentState != AGENT_STATE_LOGOUT) // 2020-04-03 根据安图修改 座席置忙外呼后座席设置置忙
  540. {
  541. __killTimer(TIMER_LOCK_PERIOD);
  542. }
  543. else // 被请求或者座席锁定签出失败
  544. {
  545. if (!IsForce) // 如果强制签出时,返回true
  546. return FALSE;
  547. }
  548. break;
  549. }
  550. m_State = a_AgentState;
  551. }
  552. break;
  553. } // end switch
  554. // 通知座席当前状态变化
  555. __reportStatus();
  556. __onStatusUpdate(m_State, true);
  557. return TRUE;
  558. }
  559. bool CAgent::sendState(AGENT_STATE a_AgentState)
  560. {
  561. switch (a_AgentState)
  562. {
  563. case AGENT_STATE_FREE: // 空闲
  564. {
  565. if (m_IsRepose)
  566. {
  567. m_State = AGENT_STATE_REPOSE;
  568. }
  569. __reportStatus();
  570. }
  571. case AGENT_STATE_REPOSE: // 小休
  572. {
  573. __onStatusUpdate(AGENT_STATE_REQUESTED, false);
  574. __onStatusUpdate(m_State, true);
  575. __reportStatus();
  576. }
  577. break;
  578. }
  579. return false;
  580. }
  581. BOOL CAgent::setFreeForAgentCall(bool IsForce)
  582. {
  583. switch (m_State)
  584. {
  585. case AGENT_STATE_FREE:
  586. return TRUE;
  587. break;
  588. case AGENT_STATE_BUSY:
  589. {
  590. if (IsForce)
  591. {
  592. __onStatusUpdate(AGENT_STATE_BUSY, false);
  593. }
  594. else
  595. return FALSE;
  596. }
  597. break;
  598. case AGENT_STATE_POST_PROCESSING:
  599. {
  600. __killTimer(TIMER_POST_PROCESSING);
  601. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  602. }
  603. break;
  604. case AGENT_STATE_REPOSE:
  605. {
  606. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  607. //m_IsRepose = false;
  608. }
  609. break;
  610. case AGENT_STATE_REQUESTED:
  611. {
  612. if (IsForce)
  613. {
  614. __killTimer(TIMER_LOCK_PERIOD);
  615. __onStatusUpdate(AGENT_STATE_REQUESTED, false); // 2021-1-22 保存坐席状态,被请求结束
  616. }
  617. else
  618. return FALSE;
  619. }
  620. break;
  621. case AGENT_STATE_LOGOUT:
  622. return FALSE;
  623. break;
  624. }
  625. // 2021-11-22
  626. AGENT_STATE state = m_State;
  627. // 2021-11-19 添加if条件 小休情况下,通话后仍为小休 2022-06-23 添加状态为被请求(外呼时,被叫拒接),由通话中改为通话中或被请求为真
  628. if (m_IsRepose &&IsForce && (m_State == AGENT_STATE_BUSY || m_State == AGENT_STATE_REQUESTED))
  629. m_State = AGENT_STATE_REPOSE;
  630. else
  631. m_State = AGENT_STATE_FREE;
  632. 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 添加保存坐席通话结束后的状态(闲/忙)开始 (被请求不处理(锁定超时))
  633. {
  634. __onStatusUpdate(m_State, true); // 2021-11-22 添加保存坐席通话结束后的状态(闲/忙)开始
  635. }
  636. //if (m_IsRepose == false) //2021-11-23 小休状态下外呼后向前端推送小休的坐席状态
  637. if ((m_IsRepose == false && (m_AssoExtState!= INNER_STATE_RING_BACK|| m_AssoExtState != INNER_STATE_ALERTING)) || state == AGENT_STATE_BUSY)
  638. {
  639. __reportStatus();
  640. }
  641. return TRUE;
  642. }
  643. BOOL CAgent::setRequestedForAgentCall(bool IsForce)
  644. {
  645. ASSERT(m_State == AGENT_STATE_FREE);
  646. switch (m_State)
  647. {
  648. case AGENT_STATE_REQUESTED:
  649. case AGENT_STATE_BUSY:
  650. case AGENT_STATE_REPOSE:
  651. case AGENT_STATE_POST_PROCESSING:
  652. case AGENT_STATE_LOGOUT:
  653. return FALSE;
  654. break;
  655. }
  656. __onStatusUpdate(AGENT_STATE_FREE, false); // 2021-11-22 添加保存坐席空闲结束,变为被请求
  657. __setTimer(TIMER_LOCK_PERIOD, CConfig::agentLockedPeriod() * 1000); // 被请求超时处理定时器
  658. m_State = AGENT_STATE_REQUESTED;
  659. __onStatusUpdate(AGENT_STATE_REQUESTED, true); // 2021-11-22 添加保存坐席被请求开始,系统外呼锁定当前坐席
  660. if (m_IsRepose == false)
  661. __reportStatus();
  662. return TRUE;
  663. }
  664. BOOL CAgent::setBusyForAgentCall(bool IsForce)
  665. {
  666. if (IsForce && (m_State == AGENT_STATE_FREE || m_State == AGENT_STATE_REPOSE)) // 2021-11-22 添加保存坐席通话结束后的状态(闲/忙)结束
  667. {
  668. __onStatusUpdate(m_State, false); // 2021-11-22 添加保存坐席通话结束后的状态(闲/忙)结束
  669. }
  670. switch (m_State)
  671. {
  672. case AGENT_STATE_BUSY:
  673. return TRUE;
  674. break;
  675. case AGENT_STATE_REQUESTED:
  676. __killTimer(TIMER_LOCK_PERIOD);
  677. break;
  678. case AGENT_STATE_POST_PROCESSING:
  679. {
  680. __killTimer(TIMER_POST_PROCESSING);
  681. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  682. }
  683. break;
  684. case AGENT_STATE_REPOSE:
  685. {
  686. //m_IsRepose = false;
  687. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  688. }
  689. break;
  690. case AGENT_STATE_LOGOUT:
  691. return FALSE;
  692. break;
  693. }
  694. __onStatusUpdate(AGENT_STATE_BUSY, true);
  695. m_State = AGENT_STATE_BUSY;
  696. if (m_IsRepose == false)
  697. __reportStatus();
  698. return TRUE;
  699. }
  700. BOOL CAgent::setProcessingForAgentCall(bool IsForce)
  701. {
  702. switch (m_State)
  703. {
  704. case AGENT_STATE_POST_PROCESSING:
  705. return TRUE;
  706. break;
  707. case AGENT_STATE_BUSY:
  708. __onStatusUpdate(AGENT_STATE_BUSY, false);
  709. break;
  710. case AGENT_STATE_FREE:
  711. case AGENT_STATE_REPOSE:
  712. case AGENT_STATE_REQUESTED:
  713. case AGENT_STATE_LOGOUT:
  714. return FALSE;
  715. break;
  716. }
  717. // 统计话后处理开始
  718. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, true);
  719. m_State = AGENT_STATE_POST_PROCESSING;
  720. if (m_TimePostProcessing > 0)
  721. __setTimer(TIMER_POST_PROCESSING, m_TimePostProcessing * 1000); // 启动话后处理定时器
  722. //if (m_IsRepose == false) // 2022-02-24 置忙下的外呼后,话后处理状态,因此屏蔽 取消置忙标识
  723. m_IsRepose = false;
  724. __reportStatus();
  725. return TRUE;
  726. }
  727. /*****************************************************************
  728. **【函数名称】 onAssoExtStatusUpdated
  729. **【函数功能】 关联分机状态更新的处理函数
  730. **【参数】 a_ExtState:分机当前状态
  731. Param:附加参数
  732. **【返回值】
  733. ****************************************************************/
  734. void CAgent::onAssoExtStatusUpdated(INNER_STATE a_ExtState, PARAM Param /*= NULL*/)
  735. {
  736. CPduEntity * pCmd = (CPduEntity *)Param;
  737. m_AssoExtState = a_ExtState;
  738. switch (a_ExtState)
  739. {
  740. case INNER_STATE_ALERTING:
  741. {
  742. if (m_State == AGENT_STATE_POST_PROCESSING || m_State == AGENT_STATE_REPOSE /*|| m_State == AGENT_STATE_REQUESTED*/)
  743. setFreeForAgentCall(true);
  744. //setState(AGENT_STATE_FREE, true);
  745. }
  746. break;
  747. case INNER_STATE_RING_BACK:
  748. {
  749. if (m_State == AGENT_STATE_POST_PROCESSING || m_State == AGENT_STATE_REPOSE /*|| m_State == AGENT_STATE_REQUESTED*/) //2021-11-24 外呼被请求多了个空闲推送
  750. setFreeForAgentCall(true);
  751. //setState(AGENT_STATE_FREE, true);
  752. }
  753. break;
  754. case INNER_STATE_TALKING:
  755. {
  756. if (pCmd == NULL || pCmd->GetDataUInt(10) != PDU_CMD_AGENT_MONI_REPLACE) // 如果是代接操作则不记录应答次数
  757. m_AnswerCount++; // 累计应答计数
  758. //setState(AGENT_STATE_BUSY, true);
  759. setBusyForAgentCall(true);
  760. }
  761. break;
  762. case INNER_STATE_FREE:
  763. {
  764. if (m_State == AGENT_STATE_BUSY)
  765. {
  766. ASSERT(pCmd != NULL);
  767. setProcessingForAgentCall();
  768. /* 2022-02-28 通话中变空闲,状态为话后处理
  769. // 关联线路为非内线,最后通话分机为当前分机,则需要进行话后处理
  770. if (pCmd != NULL && pCmd->GetDataUInt(7) != DEV_RES_TYPE_EXT && (pCmd->GetDataUInt(9) == m_Exten || pCmd->GetDataUInt(12) == 1)) // 2022-01-05 pdu-12 为是否在会议,在会议时最后应答分机不等于当前分机,也弹出
  771. //setState(AGENT_STATE_POST_PROCESSING);
  772. setProcessingForAgentCall();
  773. else
  774. //setState(AGENT_STATE_FREE, true);
  775. setFreeForAgentCall(true);
  776. */
  777. }
  778. else if (m_State == AGENT_STATE_UNKNOWN || m_State == AGENT_STATE_REQUESTED)
  779. //setState(AGENT_STATE_FREE, true);
  780. setFreeForAgentCall(true);
  781. /*
  782. else if (m_State == AGENT_STATE_FREE &&!m_IsRepose) // 2022-01-07 话机外呼失败,空闲变空闲,增加坐席状态回复空闲
  783. sendState(AGENT_STATE_FREE);
  784. else if (m_State == AGENT_STATE_FREE && m_IsRepose) // 2022-07-07 置忙情况下话机外呼后,发送话机忙
  785. sendState(AGENT_STATE_REPOSE);
  786. else if(m_State == AGENT_STATE_REPOSE) // 2022-07-07 小休状态下外呼失败后,向坐席发送小休状态
  787. sendState(AGENT_STATE_REPOSE);
  788. */
  789. else if(m_State == AGENT_STATE_FREE|| m_State == AGENT_STATE_REPOSE)
  790. sendState(m_State);
  791. }
  792. break;
  793. default:
  794. {
  795. if (m_State == AGENT_STATE_UNKNOWN)
  796. setState(AGENT_STATE_FREE);
  797. }
  798. break;
  799. }
  800. }
  801. /*****************************************************************
  802. **【函数名称】 lock
  803. **【函数功能】 锁定座席
  804. **【参数】
  805. **【返回值】
  806. ****************************************************************/
  807. BOOL CAgent::lock(void)
  808. {
  809. if (isFree())
  810. return setState(AGENT_STATE_REQUESTED);
  811. else
  812. return FALSE;
  813. }
  814. BOOL CAgent::lockForCall(void)
  815. {
  816. if (isFreeForCall())
  817. return setRequestedForAgentCall();
  818. //return setState(AGENT_STATE_REQUESTED);
  819. else
  820. return FALSE;
  821. }
  822. void CAgent::GetAgentProperty(CAgentProperty& AgentProperty)
  823. {
  824. AgentProperty.m_AnswerCount = m_AnswerCount;
  825. AgentProperty.m_ReposeCount = m_ReposeCount;
  826. AgentProperty.m_TimeFree = m_TimeFree;
  827. AgentProperty.m_TimePostProcessing = m_TimePostProcessing;
  828. AgentProperty.m_TimeRepos = m_TimeRepos;
  829. AgentProperty.m_TimeTalk = m_TimeTalk;
  830. }
  831. bool CAgent::queueJump()
  832. {
  833. if (m_bFirstQueue) {
  834. m_bFirstQueue = false;
  835. return true;
  836. }
  837. else
  838. {
  839. return false;
  840. }
  841. }