PbxController.cs 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  1. using Hotline.Application.FlowEngine;
  2. using Hotline.Caching.Interfaces;
  3. using Hotline.CallCenter.Calls;
  4. using Hotline.CallCenter.Devices;
  5. using Hotline.CallCenter.Ivrs;
  6. using Hotline.CallCenter.Tels;
  7. using Hotline.FlowEngine.WfModules;
  8. using Hotline.Permissions;
  9. using Hotline.Settings;
  10. using Hotline.Share.Dtos.CallCenter;
  11. using Hotline.Share.Dtos.FlowEngine;
  12. using Hotline.Share.Dtos.Trunk;
  13. using Hotline.Share.Enums.CallCenter;
  14. using Hotline.Share.Requests;
  15. using Hotline.Users;
  16. using MapsterMapper;
  17. using Microsoft.AspNetCore.Mvc;
  18. using SqlSugar;
  19. using Wex.Sdk;
  20. using Wex.Sdk.Tel;
  21. using XF.Domain.Authentications;
  22. using XF.Domain.Cache;
  23. using XF.Domain.Constants;
  24. using XF.Domain.Exceptions;
  25. using XF.Utility.EnumExtensions;
  26. using System.Linq;
  27. using Hotline.Share.Dtos;
  28. using Microsoft.AspNetCore.Authorization;
  29. using XF.Domain.Repository;
  30. namespace Hotline.Api.Controllers
  31. {
  32. /// <summary>
  33. /// 话机设备管理
  34. /// </summary>
  35. public class PbxController : BaseController
  36. {
  37. private readonly ITelRepository _telRepository;
  38. private readonly ITelRestRepository _telRestRepository;
  39. private readonly ITelDomainService _telDomainService;
  40. private readonly ITypedCache<Tel> _cacheTel;
  41. private readonly ITypedCache<TelGroup> _cacheTelGroup;
  42. private readonly ITelGroupRepository _telGroupRepository;
  43. private readonly IMapper _mapper;
  44. private readonly IWorkRepository _workRepository;
  45. private readonly IDeviceManager _deviceManager;
  46. private readonly IUserCacheManager _userCacheManager;
  47. private readonly ISessionContext _sessionContext;
  48. private readonly ICallRepository _callRepository;
  49. private readonly IRepository<TrunkIvrManager> _trunkIvrManagerRepository;
  50. private readonly IIvrCategoryRepository _ivrCategoryRepository;
  51. private readonly IWorkflowApplication _workflowApplication;
  52. private readonly ISystemSettingCacheManager _systemSettingCacheManager;
  53. private readonly IIvrDomainService _ivrDomainService;
  54. private readonly IIvrCacheManager _ivrCacheManager;
  55. private readonly ILogger<TelController> _logger;
  56. private readonly ICallDetailRepository _callDetailRepository;
  57. private readonly IRepository<User> _userRepository;
  58. private readonly IWexClient _wexClient;
  59. private readonly IWexTelGroupRepository _wexTelGroupRepository;
  60. public PbxController(
  61. ITelRepository telRepository,
  62. ITelRestRepository telRestRepository,
  63. ITelDomainService telDomainService,
  64. ITypedCache<Tel> cacheTel,
  65. ITypedCache<TelGroup> cacheTelGroup,
  66. ITelGroupRepository telGroupRepository,
  67. IMapper mapper,
  68. IWorkRepository workRepository,
  69. IDeviceManager deviceManager,
  70. IUserCacheManager userCacheManager,
  71. ISessionContext sessionContext,
  72. ICallRepository callRepository,
  73. IRepository<TrunkIvrManager> trunkIvrManagerRepository,
  74. IIvrCategoryRepository ivrCategoryRepository,
  75. IWorkflowApplication workflowApplication,
  76. ISystemSettingCacheManager systemSettingCacheManager,
  77. IIvrDomainService ivrDomainService,
  78. IIvrCacheManager ivrCacheManager,
  79. ILogger<TelController> logger,
  80. ICallDetailRepository callDetailRepository,
  81. IRepository<User> userRepository,
  82. IWexClient wexClient,
  83. IWexTelGroupRepository wexTelGroupRepository)
  84. {
  85. _telRepository = telRepository;
  86. _telRestRepository = telRestRepository;
  87. _telDomainService = telDomainService;
  88. _cacheTel = cacheTel;
  89. _cacheTelGroup = cacheTelGroup;
  90. _telGroupRepository = telGroupRepository;
  91. _mapper = mapper;
  92. _workRepository = workRepository;
  93. _deviceManager = deviceManager;
  94. _userCacheManager = userCacheManager;
  95. _sessionContext = sessionContext;
  96. _callRepository = callRepository;
  97. _trunkIvrManagerRepository = trunkIvrManagerRepository;
  98. _ivrCategoryRepository = ivrCategoryRepository;
  99. _workflowApplication = workflowApplication;
  100. _systemSettingCacheManager = systemSettingCacheManager;
  101. _ivrDomainService = ivrDomainService;
  102. _ivrCacheManager = ivrCacheManager;
  103. _logger = logger;
  104. _callDetailRepository = callDetailRepository;
  105. _userRepository = userRepository;
  106. _wexClient = wexClient;
  107. _wexTelGroupRepository = wexTelGroupRepository;
  108. }
  109. #region 话机
  110. /// <summary>
  111. /// 根据设备自动同步分机数据到数据库
  112. /// </summary>
  113. /// <returns></returns>
  114. [Permission(EPermission.SyncTelsAsync)]
  115. [HttpPut("sync-tels")]
  116. public async Task SyncTelsAsync()
  117. {
  118. var dbTels = await _telRepository.QueryAsync();
  119. foreach (var dbTel in dbTels)
  120. {
  121. _cacheTel.Remove(dbTel.No);
  122. }
  123. //await _telRepository.RemoveRangeAsync(dbTels);
  124. var tels = await _telDomainService.QueryTelsAsync(HttpContext.RequestAborted);
  125. var list = tels.ExceptBy(dbTels.Select(e => e.No), x => x.No).ToList();
  126. var delList = dbTels.ExceptBy(tels.Select(e => e.No), x => x.No).ToList();
  127. for (int i = 0; i < delList.Count; i++)
  128. {
  129. delList[i].SoftDelete();
  130. }
  131. await _telRepository.UpdateRangeAsync(delList);
  132. await _telRepository.AddRangeAsync(list);
  133. }
  134. /// <summary>
  135. /// 查询所有分机
  136. /// </summary>
  137. /// <returns></returns>
  138. [Permission(EPermission.QueryTels)]
  139. [HttpGet("query-tels")]
  140. public async Task<IReadOnlyList<TelDto>> QueryTels()
  141. {
  142. var tels = await _telRepository.QueryExtAsync(d => true, d => d.Includes(x => x.Groups));
  143. return _mapper.Map<IReadOnlyList<TelDto>>(tels);
  144. }
  145. #endregion
  146. #region 分机组
  147. /// <summary>
  148. /// 页面基础信息
  149. /// </summary>
  150. /// <returns></returns>
  151. [Permission(EPermission.GetBaseInfoGroup)]
  152. [HttpGet("base-info-group")]
  153. public async Task<dynamic> GetBaseInfoGroup()
  154. {
  155. return new
  156. {
  157. Distributions = EnumExts.GetDescriptions<EDistribution>()
  158. };
  159. }
  160. /// <summary>
  161. /// 查询所有分机组
  162. /// </summary>
  163. /// <returns></returns>
  164. [Permission(EPermission.QueryTelGroups)]
  165. [HttpGet("query-telgroups")]
  166. public async Task<IReadOnlyList<TelGroupDto>> QueryTelGroups()
  167. {
  168. var groups = await _telGroupRepository.QueryExtAsync(d => true, d => d.Includes(x => x.Tels));
  169. return _mapper.Map<IReadOnlyList<TelGroupDto>>(groups);
  170. }
  171. /// <summary>
  172. /// 新增分机组
  173. /// </summary>
  174. /// <param name="dto"></param>
  175. /// <returns></returns>
  176. [Permission(EPermission.AddTelGroup)]
  177. [HttpPost("add-telgroup")]
  178. public async Task AddTelGroup([FromBody] AddTelGroupDto dto)
  179. {
  180. var works = await _workRepository.QueryAsync(d => dto.TelNos.Contains(d.TelNo) && !d.EndTime.HasValue);
  181. await _deviceManager.AssginConfigGroupAsync(
  182. dto.No,
  183. dto.Distribution,
  184. ext: works.Select(d => d.TelNo).ToList(),
  185. voiceFile: dto.Voice ?? null,
  186. cancellationToken: HttpContext.RequestAborted);
  187. var group = _mapper.Map<TelGroup>(dto);
  188. var tels = await _telRepository.QueryAsync(d => dto.TelNos.Contains(d.No));
  189. group.Tels = tels;
  190. await _telGroupRepository.AddNavTelsAsync(group, HttpContext.RequestAborted);
  191. _cacheTelGroup.Remove(dto.No);
  192. }
  193. /// <summary>
  194. /// 更新分机组
  195. /// </summary>
  196. /// <param name="dto"></param>
  197. /// <returns></returns>
  198. [Permission(EPermission.UpdateTelGroup)]
  199. [HttpPut("update-telgroup")]
  200. public async Task UpdateTelGroup([FromBody] UpdateTelGroupDto dto)
  201. {
  202. var works = await _workRepository.QueryAsync(d => dto.TelNos.Contains(d.TelNo) && !d.EndTime.HasValue);
  203. await _deviceManager.AssginConfigGroupAsync(
  204. dto.No,
  205. dto.Distribution,
  206. ext: works.Select(d => d.TelNo).ToList(),
  207. voiceFile: dto.Voice ?? null,
  208. cancellationToken: HttpContext.RequestAborted);
  209. var group = _mapper.Map<TelGroup>(dto);
  210. var tels = await _telRepository.QueryAsync(d => dto.TelNos.Contains(d.No));
  211. group.Tels = tels;
  212. await _telGroupRepository.UpdateNavTelsAsync(group, HttpContext.RequestAborted);
  213. _cacheTelGroup.Remove(dto.No);
  214. }
  215. #endregion
  216. #region 话机设备操作
  217. /// <summary>
  218. /// 查询小修流程开启参数
  219. /// </summary>
  220. /// <returns></returns>
  221. [HttpGet("flow-start")]
  222. public async Task<DefinedStepDto> GetFlowStartOptionsAsync()
  223. {
  224. return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.TelRestApply,
  225. HttpContext.RequestAborted);
  226. }
  227. /// <summary>
  228. /// 分机休息
  229. /// </summary>
  230. /// <returns></returns>
  231. [Permission(EPermission.Rest)]
  232. [HttpPost("rest")]
  233. public async Task Rest([FromBody] StartRestDto dto)
  234. {
  235. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  236. if (work is null)
  237. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  238. bool isCanApply = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.RestApproval).SettingValue[0]);
  239. if (isCanApply)
  240. {
  241. var isApply = await _telRepository.IsApplyingAsync(work.TelNo, HttpContext.RequestAborted);
  242. if (isApply)
  243. throw new UserFriendlyException("分机休息申请正在审核阶段");
  244. }
  245. var isResting = await _telRepository.IsRestingAsync(work.TelNo, HttpContext.RequestAborted);
  246. if (isResting)
  247. throw new UserFriendlyException("当前坐席正在休息");
  248. var user = _userRepository.Get(work.UserId);
  249. var telRest = new TelRest(work.TelId, work.TelNo, work.UserId, work.UserName, dto.Reason, isCanApply,user.StaffNo);
  250. await _telRestRepository.AddAsync(telRest, HttpContext.RequestAborted);
  251. if (!isCanApply)
  252. {
  253. await _telDomainService.TelRestApplyPassAsync(telRest.Id, HttpContext.RequestAborted);
  254. }
  255. else
  256. {
  257. var startWorkflowDto = _mapper.Map<StartWorkflowDto>(dto);
  258. startWorkflowDto.DefinitionModuleCode = WorkflowModuleConsts.TelRestApply;
  259. startWorkflowDto.Title = dto.Reason;
  260. await _workflowApplication.StartWorkflowAsync(startWorkflowDto, telRest.Id, HttpContext.RequestAborted);
  261. }
  262. }
  263. #region 威尔信
  264. /// <summary>
  265. /// 分机休息流程开始
  266. /// </summary>
  267. /// <param name="dto"></param>
  268. /// <returns></returns>
  269. [Permission(EPermission.Rest)]
  270. [HttpPost("rest-flow")]
  271. public async Task RestFlow([FromBody] StartRestDto dto)
  272. {
  273. var tel = await _wexClient.QueryTelsAsync(new QueryTelRequest() { StaffNo = _sessionContext.StaffNo },HttpContext.RequestAborted);
  274. if (tel.Data == null || tel.Data.Count == 0)
  275. throw UserFriendlyException.SameMessage("未找到分机信息");
  276. if (tel.Data[0].Sigin == 0)
  277. throw UserFriendlyException.SameMessage("分机未签入,不能休息");
  278. var isApply = await _telRepository.IsApplyingAsync(tel.Data[0].TelNo, HttpContext.RequestAborted);
  279. if (isApply)
  280. throw UserFriendlyException.SameMessage("分机休息申请正在审核阶段");
  281. var isResting = await _telRepository.IsRestingAsync(tel.Data[0].TelNo, HttpContext.RequestAborted);
  282. if (isResting)
  283. throw new UserFriendlyException("当前坐席正在休息");
  284. var telRest = new TelRest(tel.Data[0].TelNo, tel.Data[0].TelNo, _sessionContext.RequiredUserId, _sessionContext.UserName, dto.Reason, true, _sessionContext.StaffNo);
  285. await _telRestRepository.AddAsync(telRest, HttpContext.RequestAborted);
  286. var startWorkflowDto = _mapper.Map<StartWorkflowDto>(dto);
  287. startWorkflowDto.DefinitionModuleCode = WorkflowModuleConsts.TelRestApply;
  288. startWorkflowDto.Title = dto.Reason;
  289. await _workflowApplication.StartWorkflowAsync(startWorkflowDto, telRest.Id, HttpContext.RequestAborted);
  290. }
  291. /// <summary>
  292. /// 开始分机休息
  293. /// </summary>
  294. /// <param name="id"></param>
  295. /// <returns></returns>
  296. [Permission(EPermission.Rest)]
  297. [HttpGet("begin-rest")]
  298. public async Task BeginRest()
  299. {
  300. var tel = await _wexClient.QueryTelsAsync(new QueryTelRequest() { StaffNo = _sessionContext.StaffNo }, HttpContext.RequestAborted);
  301. if (tel.Data == null || tel.Data.Count == 0)
  302. throw UserFriendlyException.SameMessage("未找到分机信息");
  303. if (tel.Data[0].Sigin == 0)
  304. throw UserFriendlyException.SameMessage("分机未签入,不能休息");
  305. var telRest = await _telRestRepository.GetAsync(x => !x.EndTime.HasValue && !x.StartTime.HasValue && x.TelNo == tel.Data[0].TelNo, HttpContext.RequestAborted);
  306. if (telRest == null)
  307. throw new UserFriendlyException($"错误");
  308. //if (string.IsNullOrEmpty(id))
  309. // throw UserFriendlyException.SameMessage("无效分机休息编号");
  310. //var telRest = await _telRestRepository.GetAsync(id, HttpContext.RequestAborted);
  311. //if (telRest == null)
  312. // throw new UserFriendlyException($"无效分机休息编号, telRestId: {id}", "无效分机休息编号");
  313. telRest.ApplyStatus = ETelRestApplyStatus.Resting;
  314. telRest.StartTime = DateTime.Now;
  315. await _telRestRepository.UpdateAsync(telRest, HttpContext.RequestAborted);
  316. }
  317. /// <summary>
  318. /// 分机休息
  319. /// </summary>
  320. /// <param name="dto"></param>
  321. /// <returns></returns>
  322. [Permission(EPermission.Rest)]
  323. [HttpPost("rest-add")]
  324. public async Task Rest([FromBody] ResstDto dto)
  325. {
  326. var tel = await _wexClient.QueryTelsAsync(new QueryTelRequest() { StaffNo = _sessionContext.StaffNo }, HttpContext.RequestAborted);
  327. if (tel.Data == null || tel.Data.Count == 0)
  328. throw UserFriendlyException.SameMessage("未找到分机信息");
  329. if (tel.Data[0].Sigin == 0)
  330. throw UserFriendlyException.SameMessage("分机未签入,不能休息");
  331. var telRest = new TelRest(tel.Data[0].TelNo, tel.Data[0].TelNo, _sessionContext.RequiredUserId, _sessionContext.UserName, dto.Reason, false, _sessionContext.StaffNo);
  332. await _telRestRepository.AddAsync(telRest, HttpContext.RequestAborted);
  333. }
  334. /// <summary>
  335. /// 删除分机休息
  336. /// </summary>
  337. /// <returns></returns>
  338. /// <exception cref="UserFriendlyException"></exception>
  339. [Permission(EPermission.Rest)]
  340. [HttpGet("rest-del")]
  341. public async Task DelRest()
  342. {
  343. var tel = await _wexClient.QueryTelsAsync(new QueryTelRequest() { StaffNo = _sessionContext.StaffNo }, HttpContext.RequestAborted);
  344. if (tel.Data == null || tel.Data.Count == 0)
  345. throw UserFriendlyException.SameMessage("未找到分机信息");
  346. if (tel.Data[0].Sigin == 0)
  347. throw UserFriendlyException.SameMessage("分机未签入,不能休息");
  348. var restingTel = await _telRestRepository.GetAsync(d => d.TelId == tel.Data[0].TelNo && !d.EndTime.HasValue, HttpContext.RequestAborted);
  349. if (restingTel is null)
  350. throw new UserFriendlyException("未查询到分机休息信息");
  351. await _telRestRepository.RemoveAsync(restingTel.Id, false, HttpContext.RequestAborted);
  352. }
  353. /// <summary>
  354. /// 分机结束休息(威尔信)
  355. /// </summary>
  356. /// <returns></returns>
  357. [Permission(EPermission.UnRest)]
  358. [HttpGet("un-rest-wex")]
  359. public async Task<TelRestDto> UnRestWEX()
  360. {
  361. var tel = await _wexClient.QueryTelsAsync(new QueryTelRequest() { StaffNo = _sessionContext.StaffNo }, HttpContext.RequestAborted);
  362. if (tel.Data == null || tel.Data.Count == 0)
  363. throw UserFriendlyException.SameMessage("未找到分机信息");
  364. if (tel.Data[0].Sigin == 0)
  365. throw UserFriendlyException.SameMessage("分机未签入,不能休息");
  366. var telRest = await _telDomainService.UnRestWexAsync(tel.Data[0].TelNo, HttpContext.RequestAborted);
  367. return _mapper.Map<TelRestDto>(telRest);
  368. }
  369. #endregion
  370. /// <summary>
  371. /// 分机结束休息
  372. /// </summary>
  373. [Permission(EPermission.UnRest)]
  374. [HttpPut("un-rest")]
  375. public async Task<TelRestDto> UnRest()
  376. {
  377. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  378. if (work is null)
  379. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  380. var telRest = await _telDomainService.UnRestAsync(work.TelId, HttpContext.RequestAborted);
  381. return _mapper.Map<TelRestDto>(telRest);
  382. }
  383. /// <summary>
  384. /// 保持通话
  385. /// </summary>
  386. [Permission(EPermission.Hold)]
  387. [HttpPut("hold")]
  388. public async Task Hold(string callId)
  389. {
  390. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  391. if (work is null)
  392. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  393. await _telDomainService.HoldAsync(work.TelId, _sessionContext.RequiredUserId, _sessionContext.UserName, callId, HttpContext.RequestAborted);
  394. }
  395. /// <summary>
  396. /// 恢复通话(解除hold状态)
  397. /// </summary>
  398. [Permission(EPermission.UnHold)]
  399. [HttpPut("un-hold")]
  400. public async Task UnHold(string callId)
  401. {
  402. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  403. if (work is null)
  404. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  405. await _telDomainService.UnHoldAsync(work.TelId, _sessionContext.RequiredUserId, callId, HttpContext.RequestAborted);
  406. }
  407. /// <summary>
  408. /// 分机呼分机
  409. /// </summary>
  410. /// <returns></returns>
  411. [Permission(EPermission.TelToTel)]
  412. [HttpPost("tel-to-tel")]
  413. public async Task TelToTel([FromBody] TelToTelDto dto)
  414. {
  415. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  416. if (work is null)
  417. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  418. //获取对方是否在工作
  419. var toWork = _userCacheManager.GetWorkByTel(dto.TelNo);
  420. if (toWork is null)
  421. throw UserFriendlyException.SameMessage("转接分机未进行工作");
  422. //判断分机状态
  423. var telState =await _deviceManager.QueryTelState(dto.TelNo,HttpContext.RequestAborted);
  424. if (telState != ETelStatus.Ready)
  425. throw UserFriendlyException.SameMessage("被叫分机不在线或正在通话中");
  426. bool isRest = await _telRepository.IsRestingAsync(dto.TelNo, HttpContext.RequestAborted);
  427. if (isRest)
  428. throw new UserFriendlyException("被叫分机正在休息不能转接");
  429. await _deviceManager.ExtToExtAsync(work.TelNo, dto.TelNo, HttpContext.RequestAborted);
  430. }
  431. /// <summary>
  432. /// 分机拨打外部电话
  433. /// </summary>
  434. /// <param name="dto"></param>
  435. /// <returns></returns>
  436. [Permission(EPermission.TelToOuter)]
  437. [HttpPost("tel-to-outer")]
  438. public async Task TelToOuter([FromBody] TelToOuterDto dto)
  439. {
  440. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  441. if (work is null)
  442. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  443. await _deviceManager.ExtToOuterAsync(work.TelNo, dto.OuterNo, HttpContext.RequestAborted);
  444. }
  445. /// <summary>
  446. /// 指定模拟外线外呼(分机拨打外部电话)
  447. /// OM设备多个外线时调用此接口
  448. /// </summary>
  449. /// <param name="dto"></param>
  450. /// <returns></returns>
  451. [Permission(EPermission.TelToOuterByLine)]
  452. [HttpPost("tel-to-outer-line")]
  453. public async Task TelToOuterByLine([FromBody] TelToOuterByLineDto dto)
  454. {
  455. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  456. if (work is null)
  457. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  458. string newOuter = dto.LineId + "," + dto.OuterNo;
  459. await _deviceManager.ExtToOuterAsync(work.TelNo, newOuter, HttpContext.RequestAborted);
  460. }
  461. /// <summary>
  462. /// 来电转分机
  463. /// </summary>
  464. /// <param name="dto"></param>
  465. /// <returns></returns>
  466. [Permission(EPermission.VisitorToTel)]
  467. [HttpPost("visitor-to-tel")]
  468. public async Task VisitorToTel([FromBody] VisitorToTelDto dto)
  469. {
  470. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  471. if (work is null)
  472. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  473. var toWork = _userCacheManager.GetWorkByTel(dto.TelNo);
  474. if (toWork is null)
  475. throw UserFriendlyException.SameMessage("转接分机未进行工作");
  476. var totelState = await _deviceManager.QueryTelState(dto.TelNo, HttpContext.RequestAborted);
  477. if (totelState != ETelStatus.Ready)
  478. throw UserFriendlyException.SameMessage("被叫分机不在线或正在通话中");
  479. bool isRest = await _telRepository.IsRestingAsync(dto.TelNo, HttpContext.RequestAborted);
  480. if (isRest)
  481. throw new UserFriendlyException("被叫分机正在休息不能转接");
  482. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  483. if (!string.IsNullOrEmpty(tel.ConversationId))
  484. await _deviceManager.VisitorToExtAsync(tel.ConversationId, dto.TelNo, HttpContext.RequestAborted);
  485. else
  486. throw UserFriendlyException.SameMessage("当前分机没有通话");
  487. }
  488. /// <summary>
  489. /// 来电转外部电话
  490. /// </summary>
  491. /// <param name="dto"></param>
  492. /// <returns></returns>
  493. [Permission(EPermission.VisitorToOuter)]
  494. [HttpPost("visitor-to-outer")]
  495. public async Task VisitorToOuter([FromBody] VisitorToOuterDto dto)
  496. {
  497. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  498. if (work is null)
  499. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  500. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  501. if (!string.IsNullOrEmpty(tel.ConversationId))
  502. await _deviceManager.VisitorToOuterAsync(tel.ConversationId, dto.OuterNo, HttpContext.RequestAborted);
  503. else
  504. throw UserFriendlyException.SameMessage("当前分机没有通话");
  505. }
  506. /// <summary>
  507. /// 来电转分机组队列
  508. /// </summary>
  509. /// <param name="dto"></param>
  510. /// <returns></returns>
  511. [Permission(EPermission.VisitorToGroup)]
  512. [HttpPost("visitor-to-group")]
  513. public async Task VisitorToGroup([FromBody] VisitorToGroupDto dto)
  514. {
  515. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  516. if (work is null)
  517. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  518. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  519. if (!string.IsNullOrEmpty(tel.ConversationId))
  520. await _deviceManager.VisitorToGroupAsync(tel.ConversationId, dto.groupid, HttpContext.RequestAborted);
  521. else
  522. throw UserFriendlyException.SameMessage("当前分机没有通话");
  523. }
  524. /// <summary>
  525. /// 去电转外部电话
  526. /// </summary>
  527. /// <param name="dto"></param>
  528. /// <returns></returns>
  529. /// <exception cref="UserFriendlyException"></exception>
  530. [Permission(EPermission.OuterToOuter)]
  531. [HttpPost("outer-to-outer")]
  532. public async Task OuterToOuter([FromBody] OuterToOuterDto dto)
  533. {
  534. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  535. if (work is null)
  536. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  537. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  538. if (!string.IsNullOrEmpty(tel.ConversationId))
  539. await _deviceManager.OuterToOuterAsync(tel.ConversationId, dto.OuterNo, HttpContext.RequestAborted);
  540. else
  541. throw UserFriendlyException.SameMessage("当前分机没有通话");
  542. }
  543. /// <summary>
  544. /// 去电转分机
  545. /// </summary>
  546. /// <param name="dto"></param>
  547. /// <returns></returns>
  548. /// <exception cref="UserFriendlyException"></exception>
  549. [Permission(EPermission.OuterToTel)]
  550. [HttpPost("outer-to-tel")]
  551. public async Task OuterToTel([FromBody] OuterToTelDto dto)
  552. {
  553. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  554. if (work is null)
  555. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  556. var toWork = _userCacheManager.GetWorkByTel(dto.TelNo);
  557. if (toWork is null)
  558. throw UserFriendlyException.SameMessage("转接分机未进行工作");
  559. var totelState = await _deviceManager.QueryTelState(dto.TelNo, HttpContext.RequestAborted);
  560. if (totelState != ETelStatus.Ready)
  561. throw UserFriendlyException.SameMessage("被叫分机不在线或正在通话中");
  562. bool isRest = await _telRepository.IsRestingAsync(dto.TelNo, HttpContext.RequestAborted);
  563. if (isRest)
  564. throw new UserFriendlyException("被叫分机正在休息不能转接");
  565. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  566. if (!string.IsNullOrEmpty(tel.ConversationId))
  567. await _deviceManager.OuterToExtAsync(tel.ConversationId, dto.TelNo, HttpContext.RequestAborted);
  568. else
  569. throw UserFriendlyException.SameMessage("当前分机没有通话");
  570. }
  571. /// <summary>
  572. /// 三方会议
  573. /// 先建立两方通话,然后调用保持通话接口,拨通第三方分机,然后再调用三方会议接口
  574. /// 1. 分机 A 正在和 B 通话;
  575. /// 2. 分机 A 把原通话呼叫保持;
  576. /// 3. 分机 A 向 C 发起新的呼叫,并建立通话;
  577. /// 4. 此时,使用该 API 能够实现以分机 A 为主持方建立 A、B、C 的三方会议。
  578. /// </summary>
  579. /// <param name="dto">TelNo:会议发起方分机号</param>
  580. /// <returns></returns>
  581. /// <exception cref="UserFriendlyException"></exception>
  582. [Permission(EPermission.Conference)]
  583. [HttpPost("meeting")]
  584. public async Task Conference([FromBody] ConferenceDto dto)
  585. {
  586. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  587. if (work is null)
  588. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  589. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  590. if (!string.IsNullOrEmpty(tel.ConversationId))
  591. await _deviceManager.ConferenceMeetingAsync(dto.TelNo, HttpContext.RequestAborted);
  592. else
  593. throw UserFriendlyException.SameMessage("当前分机没有通话");
  594. }
  595. #region 监听和强插
  596. /// <summary>
  597. /// 监听分机
  598. /// </summary>
  599. /// <param name="request"></param>
  600. /// <returns></returns>
  601. [Permission(EPermission.MonitorExt)]
  602. [HttpPost("monitor-ext")]
  603. public async Task MonitorExt([FromBody] MonitorExtRequest request)
  604. {
  605. await _deviceManager.MonitorExtAsync(request.firstTelNo, request.secondTelNo, HttpContext.RequestAborted);
  606. }
  607. /// <summary>
  608. /// 从监听到插播状态变换
  609. /// 1. 已知:分机 A 在监听分机 B 与其通话方的通话;
  610. /// 2. 执行分机 A 的从监听到插播状态变换的 API;
  611. /// 3. 执行成功时,分机 A 与分机 B 建立通话,分机 B 的原通话方听保持音。
  612. /// </summary>
  613. /// <param name="request"></param>
  614. /// <returns></returns>
  615. [Permission(EPermission.MonitorExtToTalk)]
  616. [HttpPost("monitor-ext-to-talk")]
  617. public async Task MonitorExtToTalk([FromBody] MonitorExtToTalkRequest request)
  618. {
  619. await _deviceManager.MonitorExtToTalkAsync(request.telNo, HttpContext.RequestAborted);
  620. }
  621. /// <summary>
  622. /// 从插播到监听状态变换
  623. /// 1. 已知:分机 A 在插播分机 B 的通话;
  624. /// 2. 执行分机 A 的从插播到监听状态变换的 API;
  625. /// 3. 执行成功时,分机 A 监听分机 B 及其原通话方的通话。
  626. /// </summary>
  627. /// <param name="request"></param>
  628. /// <returns></returns>
  629. [Permission(EPermission.MonitorExtToListen)]
  630. [HttpPost("monitor-ext-to-listen")]
  631. public async Task MonitorExtToListen([FromBody] MonitorExtToListenRequest request)
  632. {
  633. await _deviceManager.MonitorExtToListenAsync(request.telNo, HttpContext.RequestAborted);
  634. }
  635. #endregion
  636. #region 强插
  637. /// <summary>
  638. /// 强插
  639. /// 1. 已知:分机 A 当前空闲,分机 B 正在通话中;
  640. /// 2. 执行分机 A 强插分机 B 的 API;
  641. /// 3. 执行成功时,分机 A 振铃,摘机后即可形成三方通话。
  642. /// </summary>
  643. /// <param name="request"></param>
  644. /// <returns></returns>
  645. [Permission(EPermission.BargeinExt)]
  646. [HttpPost("bargein-ext")]
  647. public async Task BargeinExt([FromBody] BargeinExtRequest request)
  648. {
  649. await _deviceManager.BargeinExtAsync(request.firstTelNo, request.secondTelNo, HttpContext.RequestAborted);
  650. }
  651. #endregion
  652. #region 强拆
  653. /// <summary>
  654. /// 强拆分机
  655. /// </summary>
  656. /// <param name="request"></param>
  657. /// <returns></returns>
  658. [Permission(EPermission.ClearExt)]
  659. [HttpPost("clear-ext")]
  660. public async Task ClearExt([FromBody] ClearExtRequest request)
  661. {
  662. //查询当前通话记录
  663. //var call = await _callRepository.GetAsync(request.CallId, HttpContext.RequestAborted);
  664. //if (call is null)
  665. // throw UserFriendlyException.SameMessage("无效通话,无法挂断");
  666. //if (call.CallStatus == ECallStatus.Bye)
  667. // throw UserFriendlyException.SameMessage("通话已结束");
  668. await _deviceManager.ClearExtAsync(request.CallId, HttpContext.RequestAborted);
  669. }
  670. /// <summary>
  671. /// 强拆来电
  672. /// </summary>
  673. /// <param name="request"></param>
  674. /// <returns></returns>
  675. [Permission(EPermission.ClearVisitor)]
  676. [HttpPost("clear-visitor")]
  677. public async Task ClearVisitor([FromBody] ClearVisitorRequest request)
  678. {
  679. //查询当前通话记录
  680. var call = await _callRepository.GetAsync(request.CallId, HttpContext.RequestAborted);
  681. if (call is null)
  682. throw UserFriendlyException.SameMessage("无效通话,无法挂断");
  683. if (call.CallStatus == ECallStatus.Bye)
  684. throw UserFriendlyException.SameMessage("通话已结束");
  685. await _deviceManager.ClearVisitorAsync(call.ConversationId, HttpContext.RequestAborted);
  686. }
  687. /// <summary>
  688. /// 强拆去电
  689. /// </summary>
  690. /// <param name="request"></param>
  691. /// <returns></returns>
  692. [Permission(EPermission.ClearOuter)]
  693. [HttpPost("clear-outer")]
  694. public async Task ClearOuter([FromBody] ClearOuterRequest request)
  695. {
  696. //查询当前通话记录
  697. var call = await _callRepository.GetAsync(request.CallId, HttpContext.RequestAborted);
  698. if (call is null)
  699. throw UserFriendlyException.SameMessage("无效通话,无法挂断");
  700. if (call.CallStatus == ECallStatus.Bye)
  701. throw UserFriendlyException.SameMessage("通话已结束");
  702. await _deviceManager.ClearOuterAsync(call.ConversationId, HttpContext.RequestAborted);
  703. }
  704. #endregion
  705. #region 静音和取消静音
  706. /// <summary>
  707. /// 静音
  708. /// </summary>
  709. /// <returns></returns>
  710. [Permission(EPermission.Mute)]
  711. [HttpGet("mute")]
  712. public async Task Mute()
  713. {
  714. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  715. if (work is null)
  716. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  717. await _deviceManager.MuteAsync(work.TelNo, HttpContext.RequestAborted);
  718. }
  719. /// <summary>
  720. /// 取消静音
  721. /// </summary>
  722. /// <returns></returns>
  723. [Permission(EPermission.UnMute)]
  724. [HttpGet("unmute")]
  725. public async Task UnMute()
  726. {
  727. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  728. if (work is null)
  729. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  730. await _deviceManager.UnMuteAsync(work.TelNo, HttpContext.RequestAborted);
  731. }
  732. #endregion
  733. #endregion
  734. #region 线路管理
  735. /// <summary>
  736. /// 获取线路列表
  737. /// </summary>
  738. /// <returns></returns>
  739. [Permission(EPermission.GetTrunkList)]
  740. [HttpGet("trunk-list")]
  741. public async Task<IReadOnlyList<TrunkIvrManager>> GetTrunkList()
  742. {
  743. return await _trunkIvrManagerRepository.Queryable()
  744. .Includes(d => d.WorkCategoryModel)
  745. .Includes(d => d.RestCategoryModel)
  746. .Includes(d => d.WorkToGroupModel.MappingField(z => z.No, () => d.WorkToGroup))
  747. .Includes(d => d.RestToGroupModel.MappingField(z => z.No, () => d.RestToGroup))
  748. .ToListAsync();
  749. }
  750. /// <summary>
  751. /// 获取线路对象
  752. /// </summary>
  753. /// <param name="id"></param>
  754. /// <returns></returns>
  755. [Permission(EPermission.GetTrunk)]
  756. [HttpGet("trunk/{id}")]
  757. public async Task<TrunkIvrManager> GetTrunk(string id)
  758. {
  759. var trunk = await _trunkIvrManagerRepository.GetAsync(id, HttpContext.RequestAborted);
  760. if (trunk is null)
  761. throw UserFriendlyException.SameMessage("无效线路");
  762. return trunk;
  763. }
  764. /// <summary>
  765. /// 新增线路
  766. /// </summary>
  767. /// <param name="dto"></param>
  768. /// <returns></returns>
  769. [Permission(EPermission.AddTrunk)]
  770. [HttpPost("addtrunk")]
  771. public async Task AddTrunk([FromBody] AddTrunkDto dto)
  772. {
  773. var trunk = _mapper.Map<TrunkIvrManager>(dto);
  774. await _trunkIvrManagerRepository.AddAsync(trunk, HttpContext.RequestAborted);
  775. }
  776. /// <summary>
  777. /// 修改线路
  778. /// </summary>
  779. /// <param name="dto"></param>
  780. /// <returns></returns>
  781. [Permission(EPermission.UpdateTrunk)]
  782. [HttpPost("updatetrunk")]
  783. public async Task UpdateTrunk([FromBody] UpdateTrunkDto dto)
  784. {
  785. var trunk = await _trunkIvrManagerRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  786. if (trunk is null)
  787. throw UserFriendlyException.SameMessage("无效线路");
  788. _mapper.Map(dto, trunk);
  789. await _trunkIvrManagerRepository.UpdateAsync(trunk, HttpContext.RequestAborted);
  790. }
  791. /// <summary>
  792. /// 删除线路
  793. /// </summary>
  794. /// <param name="id"></param>
  795. /// <returns></returns>
  796. [Permission(EPermission.RemoveTrunk)]
  797. [HttpGet("removetrunk/{id}")]
  798. public async Task RemoveTrunk(string id)
  799. {
  800. var trunk = await _trunkIvrManagerRepository.GetAsync(id, HttpContext.RequestAborted);
  801. if (trunk is null)
  802. throw UserFriendlyException.SameMessage("无效线路");
  803. await _trunkIvrManagerRepository.RemoveAsync(id, false, HttpContext.RequestAborted);
  804. }
  805. /// <summary>
  806. /// 线路页面基础信息
  807. /// </summary>
  808. /// <returns></returns>
  809. [Permission(EPermission.TrunkPageInfo)]
  810. [HttpGet("trunk-page-info")]
  811. public async Task<object> TrunkPageInfo()
  812. {
  813. var ivr = await _ivrCategoryRepository.QueryAsync();
  814. var group = await _telGroupRepository.QueryAsync();
  815. var workDay = new List<WorkDayModel>();
  816. workDay.Add(new WorkDayModel() { weekName = "星期日", weekValue = "0" });
  817. workDay.Add(new WorkDayModel() { weekName = "星期一", weekValue = "1" });
  818. workDay.Add(new WorkDayModel() { weekName = "星期二", weekValue = "2" });
  819. workDay.Add(new WorkDayModel() { weekName = "星期三", weekValue = "3" });
  820. workDay.Add(new WorkDayModel() { weekName = "星期四", weekValue = "4" });
  821. workDay.Add(new WorkDayModel() { weekName = "星期五", weekValue = "5" });
  822. workDay.Add(new WorkDayModel() { weekName = "星期六", weekValue = "6" });
  823. return new { WorkCategorys = ivr, RestCategory = ivr, WorkToGroup = group, RestToGroup = group, WorkDay = workDay };
  824. }
  825. #endregion
  826. #region 话机业务
  827. /// <summary>
  828. /// 语音评价
  829. /// </summary>
  830. /// <param name="callId"></param>
  831. /// <returns></returns>
  832. [Permission(EPermission.Evaluate)]
  833. [HttpGet("evaluate/{callId}")]
  834. public async Task Evaluate(string callId)
  835. {
  836. //检查通话是否存在
  837. var call = await _callRepository.GetAsync(callId, HttpContext.RequestAborted);
  838. if (call is null)
  839. {
  840. throw new UserFriendlyException("未找到当前通话");
  841. }
  842. if (call.CallDirection != ECallDirection.In)
  843. {
  844. throw new UserFriendlyException("当前通话不是来电,不能发送评价邀请");
  845. }
  846. if (call.CallStatus == ECallStatus.Bye)
  847. {
  848. throw new UserFriendlyException("当前通话已结束");
  849. }
  850. if (call.CallStatus != ECallStatus.Answered && call.CallStatus != ECallStatus.Answer)
  851. {
  852. throw new UserFriendlyException("当前未进行通话,不能发送评价邀请");
  853. }
  854. //获取配置
  855. var correct = _ivrDomainService.GetCorrectIvr(call.ToNo, true);
  856. if (correct is null)
  857. throw new UserFriendlyException("系统未配置评价,请联系管理员");
  858. //检查是否有评价录音配置
  859. var ivrList = await _ivrCacheManager.GetIvrsAsync(HttpContext.RequestAborted);
  860. if (!ivrList.Any())
  861. throw new UserFriendlyException("未查到任何ivr配置");
  862. var ivr = ivrList.First(x => x.IvrCategoryId == correct.ReturnValue && x.IsRoot);
  863. _logger.LogInformation("transfer to ivr.no:{ivrNo}", ivr.No);
  864. //写入子表
  865. var detail = new CallDetail()
  866. {
  867. CallId = call.Id,
  868. CallStatus = ECallStatus.Evaluate,
  869. ConversationId = call.ConversationId,
  870. EventName = "EVALUATE",
  871. FromNo = call.FromNo,
  872. ToNo = call.ToNo,
  873. };
  874. await _callDetailRepository.AddAsync(detail, HttpContext.RequestAborted);
  875. await _deviceManager.VisitorToMenuAsync(call.ConversationId, ivr.No, HttpContext.RequestAborted);
  876. }
  877. #endregion
  878. #region 威尔信分机和分机组操作
  879. /// <summary>
  880. /// 查询分机
  881. /// </summary>
  882. /// <param name="dto"></param>
  883. /// <returns></returns>
  884. [Permission(EPermission.QueryTels)]
  885. [HttpGet("query-tel-list")]
  886. public async Task<PagedDto<TelListPageDto>> QueryTelList([FromQuery]QueryTelListDto dto)
  887. {
  888. var rsp = await _wexClient.QueryTelsPageAsync(new QueryTelPageRequest() { PageIndex = dto.PageIndex, PageSize = dto.PageSize,input = new Input() { TelNo = dto.TelNo } }, HttpContext.RequestAborted);
  889. var telList = rsp?.Data;
  890. var count = rsp.Count;
  891. if (telList!=null)
  892. {
  893. var telGroup = _wexTelGroupRepository.Queryable().ToList();
  894. var list = (from a in telList
  895. join b in telGroup on a.TelNo equals b.TelNo into output
  896. from j in output.DefaultIfEmpty()
  897. select new TelListPageDto
  898. {
  899. Id = (j==null ? "": j.Id),
  900. TelNo = a.TelNo,
  901. GroupName = (j==null ? "": j.GroupName),
  902. GroupId = (j==null ? 0: j.GroupId)
  903. }).ToList();
  904. return new PagedDto<TelListPageDto>(count, list);
  905. }
  906. return new PagedDto<TelListPageDto>(0, null);
  907. }
  908. /// <summary>
  909. /// 新增或修改分机关联分机组
  910. /// </summary>
  911. /// <param name="dto"></param>
  912. /// <returns></returns>
  913. [Permission(EPermission.AddTelGroup)]
  914. [HttpPost("add-update-telgroup")]
  915. public async Task AddOrUpdateTelGroup([FromBody]AddOrUpdateTelGroupDto dto)
  916. {
  917. if(string.IsNullOrEmpty(dto.Id))
  918. {
  919. //新增
  920. var telGroup = new WexTelGroup();
  921. telGroup.TelNo = dto.TelNo;
  922. telGroup.GroupId = dto.GroupId;
  923. telGroup.GroupName = dto.GroupName;
  924. telGroup.ZuoGroupName = dto.ZuoGroupName;
  925. await _wexTelGroupRepository.AddAsync(telGroup, HttpContext.RequestAborted);
  926. }
  927. else
  928. {
  929. //修改
  930. var telGroup = await _wexTelGroupRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  931. if (telGroup is null)
  932. {
  933. throw UserFriendlyException.SameMessage("未找到对应数据,无法修改");
  934. }
  935. if (dto.GroupId == 0)
  936. {
  937. await _wexTelGroupRepository.RemoveAsync(dto.Id, false, HttpContext.RequestAborted);
  938. }
  939. else
  940. {
  941. telGroup.GroupId = dto.GroupId;
  942. telGroup.GroupName = dto.GroupName;
  943. telGroup.ZuoGroupName = dto.ZuoGroupName;
  944. await _wexTelGroupRepository.UpdateAsync(telGroup);
  945. }
  946. }
  947. }
  948. /// <summary>
  949. /// 分机组列表
  950. /// </summary>
  951. /// <returns></returns>
  952. [Permission(EPermission.QueryTelGroups)]
  953. [HttpGet("telgroup-list")]
  954. public async Task<List<WexTelGroupDto>> TelGroupList()
  955. {
  956. var rsp = await _wexClient.QueryGroupAsync(new QueryGroupRequest() { }, HttpContext.RequestAborted);
  957. var groupList = rsp.Data;
  958. var list = _mapper.Map<List<WexTelGroupDto>>(groupList);
  959. return list;
  960. }
  961. /// <summary>
  962. /// 根据分机号查询分机关联坐席组
  963. /// </summary>
  964. /// <param name="telno"></param>
  965. /// <returns></returns>
  966. [Permission(EPermission.QueryTelGroups)]
  967. [HttpGet("telgroup/{telno}")]
  968. public async Task<WexTelGroup> TelGroup(string telno)
  969. {
  970. var telGroup = await _wexTelGroupRepository.GetAsync(x => x.TelNo == telno, HttpContext.RequestAborted);
  971. if (telGroup is null)
  972. {
  973. return new WexTelGroup() { TelNo = telno, };
  974. }
  975. return telGroup;
  976. }
  977. #endregion
  978. }
  979. }