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 ITrunkIvrManagerRepository _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. ITrunkIvrManagerRepository 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. }