QualityController.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. using Hotline.Caching.Interfaces;
  2. using MapsterMapper;
  3. using XF.Domain.Authentications;
  4. using XF.Domain.Repository;
  5. using Hotline.Quality;
  6. using Hotline.Permissions;
  7. using Hotline.Repository.SqlSugar.Extensions;
  8. using Hotline.Settings;
  9. using Hotline.Share.Dtos;
  10. using Hotline.Share.Dtos.File;
  11. using Microsoft.AspNetCore.Mvc;
  12. using XF.Domain.Exceptions;
  13. using Hotline.Share.Dtos.Quality;
  14. using Hotline.Share.Dtos.Order;
  15. using Hotline.Share.Enums.Quality;
  16. using Hotline.Share.Enums.Order;
  17. using XF.Utility.EnumExtensions;
  18. using System.Xml.Linq;
  19. using System.Threading;
  20. using Hotline.CallCenter.Calls;
  21. using Hotline.Application.Quality;
  22. using Microsoft.AspNetCore.Authorization;
  23. using Hotline.Orders;
  24. using Hotline.Ai.Quality;
  25. using Newtonsoft.Json;
  26. using Polly;
  27. using Hotline.Api.Filter;
  28. using Hotline.Application.CallCenter;
  29. using Hotline.CallCenter.Configs;
  30. using Microsoft.Extensions.Options;
  31. using XF.Domain.Constants;
  32. using Hotline.Repository.SqlSugar.CallCenter;
  33. namespace Hotline.Api.Controllers
  34. {
  35. public class QualityController : BaseController
  36. {
  37. private readonly ISessionContext _sessionContext;
  38. private readonly IMapper _mapper;
  39. private readonly IQualityRepository _qualitey;
  40. private readonly IRepository<QualityDetail> _qualiteyDetail;
  41. private readonly IRepository<QualityItem> _qualiteyItem;
  42. private readonly IRepository<QualityTemplate> _qualityTemplate;
  43. private readonly IRepository<QualityTemplateDetail> _qualiteyTemplateDetail;
  44. private readonly IRepository<QualityProhibited> _qualiteyProhibited;
  45. private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
  46. //private readonly IRepository<TrCallRecord> _trCallRecordRepository;
  47. private readonly IQualityApplication _qualityApplication;
  48. private readonly IOrderRepository _orderRepository;
  49. private readonly IAiQualityService _aiQualityService;
  50. private readonly ILogger<QualityController> _logger;
  51. private readonly ISystemSettingCacheManager _systemSettingCacheManager;
  52. private readonly ICallApplication _callApplication;
  53. private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
  54. private readonly IRepository<SystemLog> _logRepository;
  55. public QualityController(
  56. ISessionContext sessionContext,
  57. IMapper mapper,
  58. IQualityRepository qualitey,
  59. IRepository<Quality.QualityDetail> qualiteyDetail,
  60. IRepository<QualityItem> qualiteyItem,
  61. IRepository<QualityTemplate> qualityTemplate,
  62. IRepository<QualityTemplateDetail> qualiteyTemplateDetail,
  63. IRepository<QualityProhibited> qualiteyProhibited,
  64. ISystemDicDataCacheManager systemDicDataCacheManager,
  65. //IRepository<TrCallRecord> trCallRecordRepository,
  66. IQualityApplication qualityApplication,
  67. IOrderRepository orderRepository,
  68. IAiQualityService aiQualityService,
  69. ILogger<QualityController> logger,
  70. ISystemSettingCacheManager systemSettingCacheManager,
  71. ICallApplication callApplication,
  72. IOptionsSnapshot<CallCenterConfiguration> callcenterOptions,
  73. IRepository<SystemLog> logRepository)
  74. {
  75. _sessionContext = sessionContext;
  76. _mapper = mapper;
  77. _qualitey = qualitey;
  78. _qualiteyDetail = qualiteyDetail;
  79. _qualiteyItem = qualiteyItem;
  80. _qualityTemplate = qualityTemplate;
  81. _qualiteyTemplateDetail = qualiteyTemplateDetail;
  82. _qualiteyProhibited = qualiteyProhibited;
  83. _systemDicDataCacheManager = systemDicDataCacheManager;
  84. //_trCallRecordRepository = trCallRecordRepository;
  85. _qualityApplication = qualityApplication;
  86. _orderRepository = orderRepository;
  87. _aiQualityService = aiQualityService;
  88. _logger = logger;
  89. _systemSettingCacheManager = systemSettingCacheManager;
  90. _callApplication = callApplication;
  91. _callcenterOptions = callcenterOptions;
  92. _logRepository = logRepository;
  93. }
  94. #region 质检管理
  95. /// <summary>
  96. /// 删除质检
  97. /// </summary>
  98. /// <param name="dto"></param>
  99. /// <returns></returns>
  100. [HttpDelete]
  101. public async Task Delete([FromBody] DeleteQualityDto dto)
  102. {
  103. foreach (var Id in dto.Ids)
  104. {
  105. await _qualitey.RemoveAsync(x => x.Id == Id);
  106. List<QualityDetail> details = await _qualiteyDetail.Queryable().Where(x => x.QualityId == Id).ToListAsync();
  107. await _qualiteyDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
  108. }
  109. }
  110. /// <summary>
  111. /// 更新质检
  112. /// </summary>
  113. /// <param name="dto"></param>
  114. /// <returns></returns>
  115. [Permission(EPermission.UpdateQuality)]
  116. [HttpPut]
  117. public async Task Update([FromBody] UpdateQualityDto dto)
  118. {
  119. await _qualityApplication.UpdateQualityAsync(dto, HttpContext.RequestAborted);
  120. }
  121. /// <summary>
  122. /// 获取质检列表
  123. /// </summary>
  124. /// <param name="dto"></param>
  125. /// <returns></returns>
  126. [HttpGet("list")]
  127. public async Task<PagedDto<QualityDto>> List([FromQuery] QualityListDto dto)
  128. {
  129. var (total, items) = await _qualitey.Queryable()
  130. .Includes(x => x.Order)
  131. .Includes(x => x.Visit)
  132. .Includes(x => x.Visit, e => e.Employee)
  133. .Includes(x => x.QualityDetails)
  134. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!) || x.Order.No.Contains(dto.Keyword!))
  135. .WhereIF(dto.State.HasValue, x => x.State == dto.State)
  136. .WhereIF(dto.Source.HasValue, x => x.Source == dto.Source)
  137. .WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Accepted, x => !string.IsNullOrEmpty(x.Order.CallId))
  138. .WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Visit, x => !string.IsNullOrEmpty(x.Visit.CallId))
  139. .WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart)
  140. .WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd)
  141. .WhereIF(dto.MaxGrade.HasValue, x => x.Grade <= dto.MaxGrade)
  142. .WhereIF(dto.MinGrade.HasValue, x => x.Grade >= dto.MinGrade)
  143. .OrderByDescending(x => x.CreationTime)
  144. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  145. return new PagedDto<QualityDto>(total, _mapper.Map<IReadOnlyList<QualityDto>>(items));
  146. }
  147. /// <summary>
  148. /// 获取质检实体
  149. /// </summary>
  150. /// <param name="id"></param>
  151. /// <returns></returns>
  152. [HttpGet("{id}")]
  153. public async Task<QualityDto> Entity(string id)
  154. {
  155. var quality = await _qualitey.Queryable()
  156. .Includes(x => x.Order)
  157. .Includes(x => x.Visit)
  158. .Includes(x => x.Visit, e => e.Employee)
  159. .Includes(x => x.QualityDetails)
  160. .FirstAsync(x => x.Id == id);
  161. var qualityDto = _mapper.Map<QualityDto>(quality);
  162. // if (qualityDto.Order != null) {
  163. // //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync(); //由CallAccept改为OtherAccept
  164. // var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Order.CallId).FirstAsync();
  165. // if (call != null)
  166. // {
  167. // qualityDto.Order.RecordingBaseAddress = call.RecordingBaseAddress;
  168. // qualityDto.Order.RecordingAbsolutePath = call.RecordingAbsolutePath;
  169. // }
  170. // }
  171. // if (qualityDto.Visit != null)
  172. // {
  173. // //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync(); //由CallAccept改为OtherAccept
  174. // var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Visit.CallId).FirstAsync();
  175. // if (call != null)
  176. // {
  177. // qualityDto.Visit.RecordingBaseAddress = call.RecordingBaseAddress;
  178. // qualityDto.Visit.RecordingAbsolutePath = call.RecordingAbsolutePath;
  179. // }
  180. // }
  181. if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.TianRun)
  182. {
  183. if (qualityDto.Order != null)
  184. {
  185. //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync(); //由CallAccept改为OtherAccept
  186. //var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Order.CallId).FirstAsync();
  187. var call = await _callApplication.GetTianrunCallAsync(qualityDto.Order.CallId, HttpContext.RequestAborted);
  188. if (call != null)
  189. {
  190. qualityDto.Order.RecordingBaseAddress = call.RecordingBaseAddress;
  191. qualityDto.Order.RecordingAbsolutePath = call.RecordingAbsolutePath;
  192. }
  193. }
  194. if (qualityDto.Visit != null)
  195. {
  196. //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync(); //由CallAccept改为OtherAccept
  197. // var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Visit.CallId).FirstAsync();
  198. var call = await _callApplication.GetTianrunCallAsync(qualityDto.Visit.CallId, HttpContext.RequestAborted);
  199. if (call != null)
  200. {
  201. qualityDto.Visit.RecordingBaseAddress = call.RecordingBaseAddress;
  202. qualityDto.Visit.RecordingAbsolutePath = call.RecordingAbsolutePath;
  203. }
  204. }
  205. }
  206. else if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.XingTang)
  207. {
  208. if (!string.IsNullOrEmpty(qualityDto?.Order?.CallId))
  209. {
  210. var call = await _callApplication.GetCallAsync(qualityDto.Order.CallId, HttpContext.RequestAborted);
  211. if (call != null)
  212. {
  213. qualityDto.Order.RecordingBaseAddress = call.AudioFile;
  214. qualityDto.Order.RecordingAbsolutePath = call.AudioFile;
  215. }
  216. }
  217. if (!string.IsNullOrEmpty(qualityDto.Visit.CallId))
  218. {
  219. var call = await _callApplication.GetCallAsync(qualityDto.Visit.CallId, HttpContext.RequestAborted);
  220. if (call != null)
  221. {
  222. qualityDto.Visit.RecordingBaseAddress = call.AudioFile;
  223. qualityDto.Visit.RecordingAbsolutePath = call.AudioFile;
  224. }
  225. }
  226. }
  227. return qualityDto;
  228. }
  229. #endregion
  230. #region 质检项管理
  231. /// <summary>
  232. /// 新增项目
  233. /// </summary>
  234. /// <param name="dtos"></param>
  235. /// <returns></returns>
  236. [Permission(EPermission.AddQualityItem)]
  237. [HttpPost("item")]
  238. public async Task Add([FromBody] QualityItemAddDto dto)
  239. {
  240. var count = await _qualiteyItem.CountAsync(x => x.Name == dto.Name);
  241. if (count > 0)
  242. throw UserFriendlyException.SameMessage("质检项目名称已存在");
  243. var model = _mapper.Map<QualityItem>(dto);
  244. await _qualiteyItem.AddAsync(model, HttpContext.RequestAborted);
  245. }
  246. ///// <summary>
  247. ///// 删除项目
  248. ///// </summary>
  249. ///// <param name="dto"></param>
  250. ///// <returns></returns>
  251. //[Permission(EPermission.DeleteQualityItem)]
  252. //[HttpDelete("item")]
  253. //public async Task Delete([FromBody] QualityItemDeleteDto dto)
  254. //{
  255. // await _qualiteyItem.RemoveAsync(x => x.Id == dto.Id);
  256. //}
  257. /// <summary>
  258. /// 删除项目
  259. /// </summary>
  260. /// <param name="dto"></param>
  261. /// <returns></returns>
  262. [Permission(EPermission.DeleteQualityItem)]
  263. [HttpDelete("itemBatch")]
  264. public async Task Delete([FromBody] QualityItemBatchDeleteDto dto)
  265. {
  266. List<QualityItem> items = await _qualiteyItem.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
  267. foreach (var item in items)
  268. {
  269. var detail = await _qualiteyDetail.Queryable().Where(x => x.Name == item.Name).AnyAsync();
  270. //质检中已存在不可以删
  271. if (detail) items.Remove(item);
  272. }
  273. if (items.Any())
  274. {
  275. await _qualiteyItem.RemoveRangeAsync(items, true, HttpContext.RequestAborted);
  276. var tempItems = await _qualiteyTemplateDetail.Queryable().In(x => x.ItemId, items.Select(x => x.Id)).ToListAsync(HttpContext.RequestAborted);
  277. if (tempItems.Any()) await _qualiteyTemplateDetail.RemoveRangeAsync(tempItems, HttpContext.RequestAborted);
  278. }
  279. }
  280. /// <summary>
  281. /// 更新项目
  282. /// </summary>
  283. /// <param name="dto"></param>
  284. /// <returns></returns>
  285. [Permission(EPermission.UpdateQualityItem)]
  286. [HttpPut("item")]
  287. public async Task Update([FromBody] QualityItemUpdateDto dto)
  288. {
  289. var item = await _qualiteyItem.GetAsync(dto.Id, HttpContext.RequestAborted);
  290. if (item is null)
  291. throw UserFriendlyException.SameMessage("无效质检项目");
  292. if (item.IsEnable != dto.IsEnable || item.Name != dto.Name)
  293. {
  294. var detail = await _qualiteyDetail.Queryable().Where(x => x.Name == item.Name && !x.IsDeleted).AnyAsync();
  295. if (detail) throw UserFriendlyException.SameMessage("质检项目在中心质检中已使用,不能修改状态和名称!");
  296. }
  297. _mapper.Map(dto, item);
  298. item.LastModificationName = _sessionContext.UserName;
  299. await _qualiteyItem.UpdateAsync(item, HttpContext.RequestAborted);
  300. }
  301. /// <summary>
  302. /// 获取项目列表
  303. /// </summary>
  304. /// <param name="dto"></param>
  305. /// <returns></returns>
  306. [Permission(EPermission.QualityItemList)]
  307. [HttpGet("item/list")]
  308. public async Task<PagedDto<QualityItemDto>> List([FromQuery] QualityItemListDto dto)
  309. {
  310. var (total, items) = await _qualiteyItem.Queryable()
  311. .WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
  312. .WhereIF(!string.IsNullOrEmpty(dto.GroupingName), d => d.GroupingName.Contains(dto.GroupingName!))
  313. .WhereIF(dto.IsEnable.HasValue, d => d.IsEnable == dto.IsEnable)
  314. .OrderByDescending(x => x.CreationTime)
  315. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  316. return new PagedDto<QualityItemDto>(total, _mapper.Map<IReadOnlyList<QualityItemDto>>(items));
  317. }
  318. /// <summary>
  319. /// 获取项目实体
  320. /// </summary>
  321. /// <param name="id"></param>
  322. /// <returns></returns>
  323. [HttpGet("item/{id}")]
  324. public async Task<QualityItem> ItemEntity(string id)
  325. {
  326. return await _qualiteyItem.Queryable()
  327. .FirstAsync(x => x.Id == id);
  328. }
  329. #endregion
  330. #region 质检模版管理
  331. /// <summary>
  332. /// 新增模版
  333. /// </summary>
  334. /// <param name="dtos"></param>
  335. /// <returns></returns>
  336. [Permission(EPermission.AddQualityTemplate)]
  337. [HttpPost("template")]
  338. public async Task Add([FromBody] TemplateAddDto dto)
  339. {
  340. var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.IsEnable == 1);
  341. if (groupingCount > 0 && dto.IsEnable == 1)
  342. throw UserFriendlyException.SameMessage("当前已存在");
  343. var names = dto.TemplateDetails.Select(x => x.ItemId).ToList();
  344. var nameCount = names.GroupBy(x => x).Count(c => c.Count() > 1);
  345. if (nameCount > 0)
  346. throw UserFriendlyException.SameMessage("质检模版存在重复质检项");
  347. var model = _mapper.Map<QualityTemplate>(dto);
  348. var id = await _qualityTemplate.AddAsync(model, HttpContext.RequestAborted);
  349. if (!string.IsNullOrEmpty(id))
  350. {
  351. foreach (var item in dto.TemplateDetails)
  352. {
  353. item.TemplateId = id;
  354. }
  355. List<QualityTemplateDetail> details = _mapper.Map<List<QualityTemplateDetail>>(dto.TemplateDetails);
  356. await _qualiteyTemplateDetail.AddRangeAsync(details, HttpContext.RequestAborted);
  357. }
  358. }
  359. /// <summary>
  360. /// 删除模版
  361. /// </summary>
  362. /// <param name="dto"></param>
  363. /// <returns></returns>
  364. [Permission(EPermission.DeleteQualityTemplate)]
  365. [HttpDelete("template")]
  366. public async Task Delete([FromBody] TemplateDeleteDto dto)
  367. {
  368. await _qualityTemplate.RemoveAsync(x => x.Id == dto.Id);
  369. List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().Where(x => x.TemplateId == dto.Id).ToListAsync();
  370. await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
  371. }
  372. /// <summary>
  373. /// 删除模版
  374. /// </summary>
  375. /// <param name="dto"></param>
  376. /// <returns></returns>
  377. [Permission(EPermission.DeleteQualityTemplate)]
  378. [HttpDelete("templateBatch")]
  379. public async Task Delete([FromBody] TemplateBatchDeleteDto dto)
  380. {
  381. List<QualityTemplate> templates = await _qualityTemplate.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
  382. List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().In(x => x.TemplateId, dto.Ids).ToListAsync();
  383. await _qualityTemplate.RemoveRangeAsync(templates, HttpContext.RequestAborted);
  384. await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
  385. }
  386. /// <summary>
  387. /// 更新模版
  388. /// </summary>
  389. /// <param name="dto"></param>
  390. /// <returns></returns>
  391. [Permission(EPermission.UpdateQualityTemplate)]
  392. [HttpPut("template")]
  393. public async Task Update([FromBody] TemplateUpdateDto dto)
  394. {
  395. var template = await _qualityTemplate.GetAsync(dto.Id, HttpContext.RequestAborted);
  396. if (template is null)
  397. throw UserFriendlyException.SameMessage("无效质检模版");
  398. var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.Id != dto.Id && x.IsEnable == 1);
  399. if (groupingCount > 0)
  400. throw UserFriendlyException.SameMessage("当前质检分类已存在");
  401. _mapper.Map(dto, template);
  402. template.LastModificationName = _sessionContext.UserName;
  403. await _qualityTemplate.UpdateAsync(template, HttpContext.RequestAborted);
  404. if (dto.TemplateDetails.Any())
  405. {
  406. List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().Where(x => x.TemplateId == dto.Id).ToListAsync();
  407. await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
  408. foreach (var item in dto.TemplateDetails)
  409. {
  410. item.TemplateId = dto.Id;
  411. }
  412. List<QualityTemplateDetail> newDetails = _mapper.Map<List<QualityTemplateDetail>>(dto.TemplateDetails);
  413. await _qualiteyTemplateDetail.AddRangeAsync(newDetails, HttpContext.RequestAborted);
  414. }
  415. }
  416. /// <summary>
  417. /// 获取模版列表
  418. /// </summary>
  419. /// <param name="dto"></param>
  420. /// <returns></returns>
  421. [Permission(EPermission.QualityTemplateList)]
  422. [HttpGet("template/list")]
  423. public async Task<PagedDto<QualityTemplateDto>> List([FromQuery] TemplateListDto dto)
  424. {
  425. var (total, items) = await _qualityTemplate.Queryable()
  426. .Includes(x => x.templateDetails)
  427. .Includes(x => x.templateDetails, y => y.QualityItem)
  428. .WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
  429. .WhereIF(dto.Grouping.HasValue, d => d.Grouping == dto.Grouping)
  430. .WhereIF(dto.IsEnable.HasValue, d => d.IsEnable == dto.IsEnable)
  431. .OrderByDescending(x => x.CreationTime)
  432. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  433. return new PagedDto<QualityTemplateDto>(total, _mapper.Map<IReadOnlyList<QualityTemplateDto>>(items));
  434. }
  435. /// <summary>
  436. /// 获取模版实体
  437. /// </summary>
  438. /// <param name="id"></param>
  439. /// <returns></returns>
  440. [HttpGet("template/{id}")]
  441. public async Task<QualityTemplateDto> TemplateEntity(string id)
  442. {
  443. var template = await _qualityTemplate.Queryable()
  444. .Includes(x => x.templateDetails)
  445. .Includes(x => x.templateDetails, y => y.QualityItem)
  446. .FirstAsync(x => x.Id == id);
  447. return _mapper.Map<QualityTemplateDto>(template);
  448. }
  449. /// <summary>
  450. /// 启禁用
  451. /// </summary>
  452. /// <param name="dto"></param>
  453. /// <returns></returns>
  454. [Permission(EPermission.EnableQualityTemplate)]
  455. [HttpPut("template/enable")]
  456. public async Task Enable([FromBody] TemplateUpdateDto dto)
  457. {
  458. var template = await _qualityTemplate.GetAsync(dto.Id, HttpContext.RequestAborted);
  459. var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.Id != dto.Id && x.IsEnable == 1);
  460. if (groupingCount > 0)
  461. throw UserFriendlyException.SameMessage("当前质检分类已存在");
  462. if (template is null)
  463. throw UserFriendlyException.SameMessage("无效质检模版");
  464. _mapper.Map(dto, template);
  465. await _qualityTemplate.UpdateAsync(template, HttpContext.RequestAborted);
  466. }
  467. #endregion
  468. #region 质检词库管理
  469. /// <summary>
  470. /// 新增违禁词
  471. /// </summary>
  472. /// <param name="dtos"></param>
  473. /// <returns></returns>
  474. [Permission(EPermission.AddQualityProhibited)]
  475. [HttpPost("prohibited")]
  476. public async Task Add([FromBody] ProhibitedAddDto dto)
  477. {
  478. var model = _mapper.Map<QualityProhibited>(dto);
  479. await _qualiteyProhibited.AddAsync(model, HttpContext.RequestAborted);
  480. }
  481. /// <summary>
  482. /// 删除违禁词
  483. /// </summary>
  484. /// <param name="dto"></param>
  485. /// <returns></returns>
  486. [Permission(EPermission.DeleteQualityProhibited)]
  487. [HttpDelete("prohibited")]
  488. public async Task Delete([FromBody] ProhibitedDeleteDto dto)
  489. {
  490. await _qualiteyProhibited.RemoveAsync(x => x.Id == dto.Id);
  491. }
  492. /// <summary>
  493. /// 删除违禁词
  494. /// </summary>
  495. /// <param name="dto"></param>
  496. /// <returns></returns>
  497. [Permission(EPermission.DeleteQualityProhibited)]
  498. [HttpDelete("prohibitedBatch")]
  499. public async Task Delete([FromBody] ProhibitedBatchDeleteDto dto)
  500. {
  501. List<QualityProhibited> prohibiteds = await _qualiteyProhibited.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
  502. await _qualiteyProhibited.RemoveRangeAsync(prohibiteds, HttpContext.RequestAborted);
  503. }
  504. /// <summary>
  505. /// 更新违禁词
  506. /// </summary>
  507. /// <param name="dto"></param>
  508. /// <returns></returns>
  509. [Permission(EPermission.UpdateQualityProhibited)]
  510. [HttpPut("prohibited")]
  511. public async Task Update([FromBody] ProhibitedUpdateDto dto)
  512. {
  513. var prohibited = await _qualiteyProhibited.GetAsync(dto.Id, HttpContext.RequestAborted);
  514. if (prohibited is null)
  515. throw UserFriendlyException.SameMessage("无效质检模版");
  516. _mapper.Map(dto, prohibited);
  517. prohibited.LastModificationName = _sessionContext.UserName;
  518. await _qualiteyProhibited.UpdateAsync(prohibited, HttpContext.RequestAborted);
  519. }
  520. /// <summary>
  521. /// 获取违禁词列表
  522. /// </summary>
  523. /// <param name="dto"></param>
  524. /// <returns></returns>
  525. [Permission(EPermission.QualityProhibitedList)]
  526. [HttpGet("prohibited/list")]
  527. public async Task<PagedDto<QualityProhibitedDto>> List([FromQuery] ProhibitedListDto dto)
  528. {
  529. var (total, items) = await _qualiteyProhibited.Queryable()
  530. .WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
  531. .WhereIF(!string.IsNullOrEmpty(dto.Classify), d => d.Classify.Contains(dto.Classify!))
  532. .WhereIF(!string.IsNullOrEmpty(dto.Type), d => d.Type.Contains(dto.Type!))
  533. .OrderByDescending(x => x.CreationTime)
  534. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  535. return new PagedDto<QualityProhibitedDto>(total, _mapper.Map<IReadOnlyList<QualityProhibitedDto>>(items));
  536. }
  537. /// <summary>
  538. /// 获取违禁词实体
  539. /// </summary>
  540. /// <param name="id"></param>
  541. /// <returns></returns>
  542. [HttpGet("prohibited/{id}")]
  543. public async Task<QualityProhibited> ProhibitedEntity(string id)
  544. {
  545. return await _qualiteyProhibited.Queryable()
  546. .FirstAsync(x => x.Id == id);
  547. }
  548. #endregion
  549. /// <summary>
  550. /// 获取质检基本信息
  551. /// </summary>
  552. /// <returns></returns>
  553. [HttpGet("base")]
  554. public async Task<object> Base()
  555. {
  556. var rsp = new
  557. {
  558. QualityState = EnumExts.GetDescriptions<EQualityState>(),
  559. QualitySource = EnumExts.GetDescriptions<EQualitySource>()
  560. };
  561. return rsp;
  562. }
  563. /// <summary>
  564. /// 获取质检项目基本信息
  565. /// </summary>
  566. /// <returns></returns>
  567. [HttpGet("item_base")]
  568. public async Task<object> ItemBase()
  569. {
  570. var rsp = new
  571. {
  572. QualityItemGrouping = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.QualityItemGrouping)
  573. };
  574. return rsp;
  575. }
  576. /// <summary>
  577. /// 获取质检模版基本信息
  578. /// </summary>
  579. /// <returns></returns>
  580. [HttpGet("template_base")]
  581. public async Task<object> TemplateBase()
  582. {
  583. var rsp = new
  584. {
  585. TemplateGrouping = EnumExts.GetDescriptions<ETemplateGrouping>()
  586. };
  587. return rsp;
  588. }
  589. /// <summary>
  590. /// 获取质检违禁词基本信息
  591. /// </summary>
  592. /// <returns></returns>
  593. [HttpGet("prohibited_base")]
  594. public async Task<object> ProhibitedBase()
  595. {
  596. var rsp = new
  597. {
  598. ProhibitedClassify = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProhibitedClassify),
  599. ProhibitedType = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProhibitedType),
  600. };
  601. return rsp;
  602. }
  603. /// <summary>
  604. /// 智能质检结果返回接收
  605. /// </summary>
  606. /// <param name="dto"></param>
  607. /// <returns></returns>
  608. [AllowAnonymous]
  609. [HttpPost("AiResult")]
  610. [LogFilter("智能质检结果返回接收")]
  611. public async Task AiResult([FromBody] List<AiQualityResultDto> dto)
  612. {
  613. //Request.EnableBuffering();
  614. //var sr = new StreamReader(Request.Body);
  615. //var data = await sr.ReadToEndAsync(HttpContext.RequestAborted);
  616. // _logger.LogInformation(data);
  617. // await _logRepository.Updateable().SetColumns( x=> new SystemLog(){ ExecuteParam = data }).Where(x => x.Id == "08dcb132-cf60-4d1f-84ae-eb0c463f2175").ExecuteCommandAsync();
  618. await _qualityApplication.AiResultAsync(dto, HttpContext.RequestAborted);
  619. }
  620. /// <summary>
  621. /// 重推质检
  622. /// </summary>
  623. /// <param name="id"></param>
  624. /// <returns></returns>
  625. [AllowAnonymous]
  626. [HttpPost("AiResultTest/{id}")]
  627. public async Task TaskAsync(string id)
  628. {
  629. var quality = await _qualitey.GetAsync(id, HttpContext.RequestAborted);
  630. var order = await _orderRepository.GetAsync(quality.OrderId, HttpContext.RequestAborted);
  631. if (order != null && !string.IsNullOrEmpty(order.CallId))
  632. {
  633. quality.AiQuality = true;
  634. //var call = await _trCallRecordRepository.GetAsync(x => x.CallAccept == order.CallId, HttpContext.RequestAborted); //由CallAccept改为OtherAccept
  635. //var call = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == order.CallId, HttpContext.RequestAborted);
  636. var audioFile = string.Empty;
  637. var fromNo = string.Empty;
  638. DateTime? callStartTime = null;
  639. if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.TianRun)
  640. {
  641. var call = await _callApplication.GetTianrunCallAsync(order.CallId, HttpContext.RequestAborted);
  642. audioFile = call.RecordingAbsolutePath;
  643. fromNo = call.CPN;
  644. callStartTime = call.CreatedTime;
  645. }
  646. else if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.XingTang)
  647. {
  648. var call = await _callApplication.GetCallAsync(order.CallId, HttpContext.RequestAborted);
  649. audioFile = call.AudioFile;
  650. fromNo = call.FromNo;
  651. callStartTime = call.BeginIvrTime;
  652. }
  653. var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
  654. try
  655. {
  656. _aiQualityService.CreateAiOrderQualityTask(
  657. quality.Id,
  658. audioFile,
  659. fromNo,
  660. callStartTime,
  661. setting?.SettingValue[0], quality.Source.ToString(),HttpContext.RequestAborted);
  662. }
  663. catch (Exception e)
  664. {
  665. _logger.LogError($"写入智能质检异常!, \r\n{e.Message}");
  666. }
  667. await _qualitey.UpdateAsync(quality, HttpContext.RequestAborted);
  668. }
  669. }
  670. }
  671. }