123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- using Hotline.Application.CallCenter.Calls;
- using Hotline.Caching.Interfaces;
- using Hotline.Caching.Services;
- using Hotline.CallCenter.Calls;
- using Hotline.Orders;
- using Hotline.Permissions;
- using Hotline.Repository.SqlSugar.Extensions;
- using Hotline.Settings;
- using Hotline.Share.Dtos;
- using Hotline.Share.Dtos.Order;
- using Hotline.Share.Dtos.TrCallCenter;
- using Hotline.Share.Enums.CallCenter;
- using Hotline.Share.Enums.KnowledgeBase;
- using Hotline.Users;
- using MapsterMapper;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Mvc;
- using System.Text.Json;
- using Tr.Sdk;
- using Tr.Sdk.Blacklist;
- using Tr.Sdk.Tels;
- using XF.Domain.Authentications;
- using XF.Domain.Filters;
- using XF.Domain.Repository;
- using XF.Utility.EnumExtensions;
- namespace Hotline.Api.Controllers
- {
- public class IPPbxController:BaseController
- {
- private readonly ITrClient _trClient;
- private readonly IMapper _mapper;
- private readonly IUserDomainService _userDomainService;
- private readonly ISessionContext _sessionContext;
- private readonly IRepository<TrCallRecord> _trCallRecordRepository;
- private readonly ITrApplication _trApplication;
- private readonly IRepository<TrCallEvaluate> _trCallEvaluate;
- private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
- private readonly ILogger<IPPbxController> _logger;
- private readonly IOrderRepository _orderRepository;
- private readonly IRepository<OrderVisit> _orderVisitRepository;
- private readonly IUserCacheManager _userCacheManager;
- public IPPbxController(ITrClient trClient,IMapper mapper,IUserDomainService userDomainService,ISessionContext sessionContext,IRepository<TrCallRecord> trCallRecordRepository,ITrApplication trApplication,IRepository<TrCallEvaluate> trCallRecord,ISystemDicDataCacheManager systemDicDataCacheManager,ILogger<IPPbxController> logger,IOrderRepository orderRepository,IRepository<OrderVisit> orderVisitRepository, IUserCacheManager userCacheManager)
- {
- _trClient = trClient;
- _mapper = mapper;
- _userDomainService = userDomainService;
- _sessionContext = sessionContext;
- _trCallRecordRepository = trCallRecordRepository;
- _trApplication = trApplication;
- _trCallEvaluate = trCallRecord;
- _systemDicDataCacheManager = systemDicDataCacheManager;
- _logger = logger;
- _orderRepository = orderRepository;
- _orderVisitRepository = orderVisitRepository;
- _userCacheManager = userCacheManager;
- }
- #region 添添呼
- #region 分机
- /// <summary>
- /// 查询所有分机
- /// </summary>
- /// <returns></returns>
- [HttpGet("query-tels")]
- public async Task<IReadOnlyList<TrTelDto>> TrQueryTels()
- {
- var tels = await _trClient.QueryTelsAsync(new QueryTelRequest() { }, HttpContext.RequestAborted);
- return _mapper.Map<IReadOnlyList<TrTelDto>>(tels);
- }
- #endregion
- #region 黑白名单
- /// <summary>
- /// 新增黑白名单
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [Permission(EPermission.AddBlackList)]
- [HttpPost("add-blacklist")]
- public async Task AddBlacklist([FromBody]TrAddBlacklistDto dto)
- {
- await _trClient.AddBlacklistAsync(new AddBlacklistRequest() { Phone = dto.Phone, SpecialFlag = dto.SpecialFlag }, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 删除黑白名单
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [Permission(EPermission.RemoveBlacklist)]
- [HttpPost("remove-blacklist")]
- public async Task DelBlacklist([FromBody]TrDelBlacklistDto dto)
- {
- await _trClient.DelBlacklistAsync(new DelBlacklistRequest() { Phone = dto.Phone, SpecialFlag = dto.SpecialFlag }, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 查询黑白名单
- /// </summary>
- /// <returns></returns>
- [Permission(EPermission.QueryPagedBlack)]
- [HttpGet("query-blacklist")]
- public async Task<IReadOnlyList<TrQueryBlacklistResponseDto>> QueryBlacklist([FromQuery]TrQueryBlacklistDto dto)
- {
- var blacklist = await _trClient.QueryBlacklistAsync(new QueryBlacklistRequest() { Phone = dto.Phone, SpecialFlag = dto.SpecialFlag }, HttpContext.RequestAborted);
- return _mapper.Map<IReadOnlyList<TrQueryBlacklistResponseDto>>(blacklist);
- }
- #endregion
- #region 签入后调用
- /// <summary>
- /// 上班
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [Permission(EPermission.OnDuty)]
- [HttpPost("on-duty")]
- public async Task<TrOnDutyResponseDto> OnDuty([FromBody] TrOnDutyDto dto)
- {
- //return await _userDomainService.TrOnDutyAsync(_sessionContext.RequiredUserId,dto.TelNo, HttpContext.RequestAborted);
- return await _trApplication.OnSign(_sessionContext.RequiredUserId, dto.TelNo, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 下班
- /// </summary>
- /// <returns></returns>
- [Permission(EPermission.OffDuty)]
- [HttpPost("off-duty")]
- public async Task OffDuty()
- {
- await _userDomainService.TrOffDutyAsync(_sessionContext.RequiredUserId, HttpContext.RequestAborted);
- }
- #endregion
- #region 添添呼小休
- /// <summary>
- /// 小休页面基础数据
- /// </summary>
- /// <returns></returns>
- [HttpGet("rest/basedata")]
- public async Task<object> RestBasePaegData()
- {
- var rsp = new
- {
- RestReason = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.RestReason)
- };
- return rsp;
- }
- #endregion
- #region 通话记录(对外)
- /// <summary>
- /// 接收通话记录
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [AllowAnonymous]
- [HttpPost("receivecallrecord")]
- public async Task<OpenResponse> ReceiveCallRecord([FromBody]ReceiveCallRecordDto dto)
- {
- var model = _mapper.Map<TrCallRecord>(dto);
- model.Duration = 0;
- model.RingTimes = 0;
- model.QueueTims = 0;
- model.OnState = Share.Enums.CallCenter.EOnState.NoOn;
- //计算通话时长
- if (model.AnsweredTime != null)
- {
- model.OnState = Share.Enums.CallCenter.EOnState.On; //是否接通
- TimeSpan tsend = new TimeSpan(model.OverTime.Ticks);
- TimeSpan tsbegin = new TimeSpan(model.AnsweredTime.Value.Ticks);
- model.Duration = Convert.ToInt32(tsend.Subtract(tsbegin).TotalSeconds);
- }
- //计算振铃时长
- if (model.BeginRingTime !=null)
- {
- TimeSpan tsbegin = new TimeSpan(model.BeginRingTime.Value.Ticks);
- if (model.EndRingTimg!=null)
- {
- TimeSpan tsend = new TimeSpan(model.EndRingTimg.Value.Ticks);
- model.RingTimes = Convert.ToInt32(tsend.Subtract(tsbegin).TotalSeconds);
- }
- else
- {
- TimeSpan tsend = new TimeSpan(model.OverTime.Ticks);
- model.RingTimes = Convert.ToInt32(tsend.Subtract(tsbegin).TotalSeconds);
- }
- }
- //计算队列时长
- if (model.BeginQueueTime!=null && model.EndQueueTime!=null)
- {
- TimeSpan tsend = new TimeSpan(model.EndQueueTime.Value.Ticks);
- TimeSpan tsbegin = new TimeSpan(model.BeginQueueTime.Value.Ticks);
- model.QueueTims = Convert.ToInt32(tsend.Subtract(tsbegin).TotalSeconds);
- }
- //获取分机号
- if (model.CallDirection == ECallDirection.In)
- {
- model.TelNo = model.CDPN;
- }
- else
- {
- model.TelNo = model.CPN;
- }
- //获取用户
- var work = await _userCacheManager.GetWorkByTelNoLast(model.TelNo);
- if (work!=null)
- {
- model.UserId = work.UserId;
- model.UserName = work.UserName;
- model.StaffNo = work.StaffNo;
- }
- await _trCallRecordRepository.AddAsync(model, HttpContext.RequestAborted);
- return OpenResponse.Ok("success");
- }
- /// <summary>
- /// 接受通话语音评价
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [AllowAnonymous]
- [HttpPost("receivecallevaluate")]
- public async Task<OpenResponse> ReceiveCallEvaluate([FromBody]ReceiveCallEvaluateDto dto)
- {
- var model = _mapper.Map<TrCallEvaluate>(dto);
- await _trCallEvaluate.AddAsync(model, HttpContext.RequestAborted);
- return OpenResponse.Ok("success");
- }
- #endregion
- #region 通话记录(对内)
- /// <summary>
- /// 获取通话记录列表
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("calls/call-list")]
- public async Task<PagedDto<TrCallDto>> GetCallList([FromQuery]GetCallListDto dto)
- {
- var (total, items) = await _trCallRecordRepository.Queryable()
- .WhereIF(!string.IsNullOrEmpty(dto.CPN), x => x.CPN.Contains(dto.CPN))
- .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.CDPN.Contains(dto.CDPN))
- .WhereIF(dto.CallDirection != null, x => x.CallDirection == dto.CallDirection)
- .WhereIF(dto.OnState != null, x => x.OnState == dto.OnState)
- .OrderByDescending(x => x.CreatedTime)
- .ToPagedListAsync(dto.PageIndex, dto.PageSize);
- return new PagedDto<TrCallDto>(total, _mapper.Map<IReadOnlyList<TrCallDto>>(items));
- }
- /// <summary>
- /// 通话记录基础数据
- /// </summary>
- /// <returns></returns>
- [HttpGet("calls/basedata")]
- public async Task<object> CallBaseData()
- {
- return new
- {
- OnState = EnumExts.GetDescriptions<EOnState>(),
- CallDirection = EnumExts.GetDescriptions<ECallDirection>(),
- };
- }
- #endregion
- #region 关联
- /// <summary>
- /// 可关联工单
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("canlink-order")]
- public async Task<PagedDto<OrderDto>> CanLinkCallRecordOrder([FromQuery]CanLinkCallRecordOrderDto dto)
- {
- var (total,items) = await _orderRepository.Queryable()
- .Where(x=> string.IsNullOrEmpty(x.CallId) && x.Source == Share.Enums.Order.ESource.Hotline)
- .WhereIF(!string.IsNullOrEmpty(dto.Keyword),x=>x.No.Contains(dto.Keyword))
- .OrderByDescending(x=>x.CreationTime)
- .ToPagedListAsync(dto.PageIndex,dto.PageSize,HttpContext.RequestAborted);
- return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
- }
- /// <summary>
- /// 可关联回访
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("canlink-ordervisit")]
- public async Task<PagedDto<OrderVisitDto>> CanLinkCallRecordOrderVisit([FromQuery]CanLinkCallRecordOrderVisitDto dto)
- {
- var (total, items) = await _orderVisitRepository.Queryable()
- .Includes(x=>x.Order)
- .Where(x => string.IsNullOrEmpty(x.CallId) && x.VisitType == Share.Enums.Order.EVisitType.ArtificialVisit)
- .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.No.Contains(dto.Keyword))
- .OrderByDescending(x => x.CreationTime)
- .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
- return new PagedDto<OrderVisitDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDto>>(items));
- }
- /// <summary>
- /// 关联工单或者回访
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpPost("link-callrecord")]
- public async Task LinkCallRecord([FromBody]LinkCallRecordDto dto)
- {
-
- if (dto.IsOrder)
- {
- //工单
- var order = await _orderRepository.GetAsync(x => x.Id == dto.Id, HttpContext.RequestAborted);
- order.CallId = dto.CallId;
- await _orderRepository.UpdateAsync(order);
- }
- else
- {
- //回访
- var visit = await _orderVisitRepository.GetAsync(x => x.Id == dto.Id, HttpContext.RequestAborted);
- visit.CallId = dto.CallId;
- await _orderVisitRepository.UpdateAsync(visit);
- }
- }
- #endregion
- #endregion
- }
- }
|