using DotNetCore.CAP; using Hotline.Api.Filter; using Hotline.Application.ExportExcel; using Hotline.Application.FlowEngine; using Hotline.Application.Orders; using Hotline.Application.Quality; using Hotline.Caching.Interfaces; using Hotline.CallCenter.Calls; using Hotline.Enterprise; using Hotline.File; using Hotline.FlowEngine.Definitions; using Hotline.FlowEngine.WorkflowModules; using Hotline.FlowEngine.Workflows; using Hotline.Import; using Hotline.Orders; using Hotline.Orders.Notifications; using Hotline.Permissions; using Hotline.Push.FWMessage; using Hotline.Push.Notifies; using Hotline.Repository.SqlSugar.Extensions; using Hotline.Repository.SqlSugar.Ts; using Hotline.Settings; using Hotline.Settings.Hotspots; using Hotline.Settings.TimeLimits; using Hotline.Share.Dtos; using Hotline.Share.Dtos.Enterprise; using Hotline.Share.Dtos.FlowEngine; using Hotline.Share.Dtos.Order; using Hotline.Share.Dtos.Push; using Hotline.Share.Dtos.Settings; using Hotline.Share.Enums.FlowEngine; using Hotline.Share.Enums.Order; using Hotline.Share.Enums.Push; using Hotline.Share.Enums.Quality; using Hotline.Share.Enums.Settings; using Hotline.Share.Requests; using Hotline.Users; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using MiniExcelLibs; using SqlSugar; using XF.Domain.Authentications; using XF.Domain.Cache; using XF.Domain.Constants; using XF.Domain.Exceptions; using XF.Domain.Repository; using XF.Utility.EnumExtensions; namespace Hotline.Api.Controllers; /// /// 工单 /// public class OrderController : BaseController { private readonly IOrderDomainService _orderDomainService; private readonly IOrderRepository _orderRepository; private readonly IWorkflowApplication _workflowApplication; private readonly IWorkflowDomainService _workflowDomainService; private readonly IRepository _hotspotTypeRepository; private readonly ISystemOrganizeRepository _organizeRepository; private readonly IDefinitionDomainService _definitionDomainService; private readonly ISystemDicDataCacheManager _sysDicDataCacheManager; private readonly ISessionContext _sessionContext; private readonly IMapper _mapper; private readonly IMediator _mediator; private readonly IRepository _orderPublishRepository; private readonly IRepository _orderVisitRepository; private readonly IRepository _orderVisitedDetailRepository; private readonly ICapPublisher _capPublisher; private readonly IOrderDelayRepository _orderDelayRepository; private readonly ITimeLimitDomainService _timeLimitDomainService; private readonly ISystemSettingCacheManager _systemSettingCacheManager; private readonly IRepository _orderRedoRepository; private readonly IRepository _orderSuperviseRepository; private readonly IRepository _orderUrgeRepository; private readonly IFileRepository _fileRepository; private readonly IOrderScreenRepository _orderScreenRepository; private readonly IRepository _orderPublishHistoryRepository; private readonly IRepositoryTextSearch _repositoryts; private readonly IQualityApplication _qualityApplication; private readonly IRepository _workflowRepository; private readonly IRepository _workflowStepRepository; private readonly ICitizenRepository _citizenRepository; private readonly IRepository _labelDetailRepository; private readonly IRepository _repeatableEventRepository; private readonly IRepeatableEventDetailRepository _repeatableEventDetailRepository; private readonly IRepository _orderWrodRepository; private readonly IRepository _orderObserveRepository; private readonly IRepository _orderVisitApplyRepository; private readonly IRepository _orderFinalityRepository; private readonly IRepository _orderSendBackRepository; private readonly IRepository _orderSpecialRepository; private readonly IRepository _workflowTraceRepository; private readonly IRepository _trCallRecordRepository; private readonly IOrderApplication _orderApplication; private readonly IEnterpriseService _enterpriseService; private readonly IPushDomainService _pushDomainService; private readonly ILogger _logger; private readonly ITypedCache _cacheResponse; private readonly IRepository _orderSendBackAuditRepository; private readonly IRepository _userRepository; private readonly IExportApplication _exportApplication; public OrderController( IOrderDomainService orderDomainService, IOrderRepository orderRepository, IWorkflowApplication workflowApplication, IWorkflowDomainService workflowDomainService, IRepository hotspotTypeRepository, ISystemOrganizeRepository organizeRepository, IDefinitionDomainService definitionDomainService, ISystemDicDataCacheManager sysDicDataCacheManager, ISessionContext sessionContext, IMapper mapper, IMediator mediator, IRepository orderPublishRepository, IRepository orderVisitRepository, IRepository orderVisitedDetailRepository, ICapPublisher capPublisher, IOrderDelayRepository orderDelayRepository, ITimeLimitDomainService timeLimitDomainService, ISystemSettingCacheManager systemSettingCacheManager, IRepository orderRedoRepository, IRepository orderSuperviseRepository, IRepository orderUrgeRepository, IFileRepository fileRepository, IOrderScreenRepository orderScreenRepository, IRepository orderPublishHistoryRepository, IRepositoryTextSearch repositoryts, IQualityApplication qualityApplication, IRepository workflowRepository, IRepository workflowStepRepository, ICitizenRepository citizenRepository, IRepository labelDetailRepository, IRepository repeatableEventRepository, IRepeatableEventDetailRepository repeatableEventDetailRepository, IRepository orderWrodRepository, IRepository orderObserveRepository, IRepository orderFinalityRepository, IRepository orderVisitApplyRepository, IRepository orderSendBackRepository, IRepository orderSpecialRepository, IRepository workflowTraceRepository, IRepository trCallRecordRepository, IOrderApplication orderApplication, IEnterpriseService enterpriseService, IPushDomainService pushDomainService, ILogger logger, ITypedCache cacheResponse, IRepository orderSendBackAuditRepository, IRepository userRepository, IExportApplication exportApplication ) { _orderDomainService = orderDomainService; _orderRepository = orderRepository; _workflowApplication = workflowApplication; _workflowDomainService = workflowDomainService; _hotspotTypeRepository = hotspotTypeRepository; _organizeRepository = organizeRepository; _definitionDomainService = definitionDomainService; _sysDicDataCacheManager = sysDicDataCacheManager; _sessionContext = sessionContext; _mapper = mapper; _mediator = mediator; _orderPublishRepository = orderPublishRepository; _orderVisitRepository = orderVisitRepository; _orderVisitedDetailRepository = orderVisitedDetailRepository; _capPublisher = capPublisher; _orderDelayRepository = orderDelayRepository; _timeLimitDomainService = timeLimitDomainService; _systemSettingCacheManager = systemSettingCacheManager; _orderRedoRepository = orderRedoRepository; _orderSuperviseRepository = orderSuperviseRepository; _orderUrgeRepository = orderUrgeRepository; _fileRepository = fileRepository; _orderScreenRepository = orderScreenRepository; _orderPublishHistoryRepository = orderPublishHistoryRepository; _repositoryts = repositoryts; _qualityApplication = qualityApplication; _workflowRepository = workflowRepository; _workflowStepRepository = workflowStepRepository; _citizenRepository = citizenRepository; _labelDetailRepository = labelDetailRepository; _repeatableEventRepository = repeatableEventRepository; _repeatableEventDetailRepository = repeatableEventDetailRepository; _orderWrodRepository = orderWrodRepository; _orderObserveRepository = orderObserveRepository; _orderFinalityRepository = orderFinalityRepository; _orderVisitApplyRepository = orderVisitApplyRepository; _orderSendBackRepository = orderSendBackRepository; _orderSpecialRepository = orderSpecialRepository; _workflowTraceRepository = workflowTraceRepository; _trCallRecordRepository = trCallRecordRepository; _logger = logger; _orderApplication = orderApplication; _enterpriseService = enterpriseService; _pushDomainService = pushDomainService; _cacheResponse = cacheResponse; _orderSendBackAuditRepository = orderSendBackAuditRepository; _userRepository = userRepository; _exportApplication = exportApplication; } #region 工单发布 /// /// 查询(工单发布) /// /// /// [HttpGet("publish")] public async Task> PublishOrderList([FromQuery] QueryOrderPublishDto dto) { var (total, items) = await _orderRepository.Queryable() .Includes(d => d.OrderPublish) .Where(x => x.Status == EOrderStatus.Filed) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!)) .WhereIF(dto.PubState == EPubState.Pub, d => d.Status >= EOrderStatus.Published) .WhereIF(dto.PubState == EPubState.NoPub, d => d.Status < EOrderStatus.Published) .WhereIF(!string.IsNullOrEmpty(dto.PubMan), d => d.AcceptorName.Contains(dto.PubMan!) || d.AcceptorStaffNo.Contains(dto.PubMan!)) .WhereIF(dto.PubRange == EPublicState.Pub, d => d.OrderPublish.PublishState) .WhereIF(dto.PubRange == EPublicState.NoPub, d => !d.OrderPublish.PublishState) .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.CenterFiled, d => d.ProcessType == EProcessType.Zhiban) .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.OrgFiled, d => d.ProcessType == EProcessType.Jiaoban) .WhereIF(dto.IsCountersign != null && dto.IsCountersign == true, d => d.CounterSignType != null) .WhereIF(dto.IsCountersign != null && dto.IsCountersign == false, d => d.CounterSignType == null) .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType)) .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(dto.FiledTimeStart.HasValue, d => d.OrderPublish.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.FiledTimeEnd.HasValue, d => d.OrderPublish.CreationTime <= dto.CreationTimeEnd) .OrderByDescending(d => d.FiledTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 批量发布工单 /// /// /// [HttpPost("batch-publish")] public async Task BatchPublishOrder([FromBody] BatchPublishOrderDto dto) { foreach (var item in dto.Ids) { var order = await _orderRepository.GetAsync(item, HttpContext.RequestAborted); if (order != null) { try { OrderPublish orderPublish = new OrderPublish(); orderPublish.OrderId = order.Id; orderPublish.No = order.No; orderPublish.PublishState = false;//当前写死为false orderPublish.ArrangeTitle = order.Title; orderPublish.ArrangeContent = order.Content; orderPublish.ArrangeOpinion = order.ActualOpinion; orderPublish.ProPublishState = false; orderPublish.FeedBackPhone = order.Contact; orderPublish.CreatorName = _sessionContext.UserName; await _orderPublishRepository.AddAsync(orderPublish); order.Publish(orderPublish.PublishState); await _orderRepository.UpdateAsync(order); //推省上 var publishPublishOrder = _mapper.Map(orderPublish); publishPublishOrder.Order = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderPublishOrder, publishPublishOrder); var orderVisit = new OrderVisit(); orderVisit.No = order.No; orderVisit.OrderId = order.Id; orderVisit.VisitState = EVisitState.WaitForVisit; orderVisit.PublishTime = DateTime.Now; orderVisit.IsCanHandle = true; if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null }) { orderVisit.VisitState = EVisitState.Visited; } if (order.CounterSignType != ECounterSignType.Center) { orderVisit.IsCanAiVisit = true; } string visitId = await _orderVisitRepository.AddAsync(orderVisit); //新增回访信息 var visitedDetail = new List(); var seatDetail = new OrderVisitDetail(); seatDetail.VisitId = visitId; seatDetail.VisitTarget = EVisitTarget.Seat; var orgDetail = new OrderVisitDetail(); orgDetail.VisitId = visitId; orgDetail.VisitOrgCode = order.ActualHandleOrgCode; orgDetail.VisitOrgName = order.ActualHandleOrgName; orgDetail.VisitTarget = EVisitTarget.Org; if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null }) { var satisfy = new Kv() { Key = "4", Value = "满意" }; orgDetail.OrgProcessingResults = satisfy; orgDetail.OrgHandledAttitude = satisfy; } visitedDetail.Add(orgDetail); if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null }) { seatDetail.VoiceEvaluate = EVoiceEvaluate.Satisfied; seatDetail.SeatEvaluate = ESeatEvaluate.Satisfied; order.Visited("4", "满意"); order.Status = EOrderStatus.Visited; await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); } visitedDetail.Add(seatDetail); await _orderVisitedDetailRepository.AddRangeAsync(visitedDetail, HttpContext.RequestAborted); } catch { } } } } /// /// 发布工单 /// /// [Permission(EPermission.PublishOrder)] [HttpPost("publish")] [LogFilter("发布工单")] public async Task PublishOrder([FromBody] PublishOrderDto dto) { //验证订单 var order = await _orderRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (order is null) throw UserFriendlyException.SameMessage("未找到工单,无法发布"); //新增发布工单 var orderPublish = _mapper.Map(dto); orderPublish.OrderId = order.Id; orderPublish.No = order.No; string id = await _orderPublishRepository.AddAsync(orderPublish); order.Publish(orderPublish.PublishState); await _orderRepository.UpdateAsync(order); //推省上 var publishPublishOrder = _mapper.Map(orderPublish); publishPublishOrder.Order = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderPublishOrder, publishPublishOrder); var orderVisit = new OrderVisit(); orderVisit.No = order.No; orderVisit.OrderId = order.Id; orderVisit.VisitState = EVisitState.WaitForVisit; orderVisit.PublishTime = DateTime.Now; orderVisit.IsCanHandle = true; if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null }) { orderVisit.VisitState = EVisitState.Visited; } if (order.CounterSignType != ECounterSignType.Center) { orderVisit.IsCanAiVisit = true; } string visitId = await _orderVisitRepository.AddAsync(orderVisit); //新增回访信息 var visitedDetail = new List(); var seatDetail = new OrderVisitDetail(); seatDetail.VisitId = visitId; seatDetail.VisitTarget = EVisitTarget.Seat; foreach (var item in dto.IdNames) { var orgDetail = new OrderVisitDetail(); orgDetail.VisitId = visitId; orgDetail.VisitOrgCode = item.Key; orgDetail.VisitOrgName = item.Value; orgDetail.VisitTarget = EVisitTarget.Org; if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null }) { var satisfy = new Kv() { Key = "4", Value = "满意" }; orgDetail.OrgProcessingResults = satisfy; orgDetail.OrgHandledAttitude = satisfy; } visitedDetail.Add(orgDetail); } if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null }) { seatDetail.VoiceEvaluate = EVoiceEvaluate.Satisfied; seatDetail.SeatEvaluate = ESeatEvaluate.Satisfied; order.Visited("4", "满意"); order.Status = EOrderStatus.Visited; await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); } visitedDetail.Add(seatDetail); await _orderVisitedDetailRepository.AddRangeAsync(visitedDetail, HttpContext.RequestAborted); //推送回访信息 //推门户 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisitedWeb, new PublishVisitAllDto() { Id = orderVisit.Id, Order = _mapper.Map(order), OrderVisitDetails = _mapper.Map>(orderVisit.OrderVisitDetails), VisitName = _sessionContext.UserName, VisitTime = orderVisit.VisitTime, VisitType = orderVisit.VisitType, VisitState = orderVisit.VisitState, PublishTime = orderVisit.PublishTime, }, cancellationToken: HttpContext.RequestAborted); } /// /// 发布页面基础信息 /// /// [HttpGet("publish-order-pagebase/{id}")] public async Task PublishOrderPageBase(string id) { var order = await _orderRepository.Queryable() .Includes(d => d.OrderExtension) .FirstAsync(d => d.Id == id); if (order is null) throw UserFriendlyException.SameMessage("未知工单,无法发布"); var res = new PublishOrderPageBaseDto() { SourceChannel = order.SourceChannel, OrderTitle = order.Title, Content = order.Content, ActualOpinion = order.ActualOpinion, NetizenEvaluateType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.NetizenEvaluateType).Select(x => new Kv { Key = x.DicDataValue, Value = x.DicDataName }).ToList() }; var (idName, idNames) = await _workflowDomainService.GetUnvisitOrgsAsync(order.WorkflowId, HttpContext.RequestAborted); res.ActualHandleOrgName = idName; res.idNames = idNames.ToList(); return res; } /// /// 已发布列表 /// /// /// [Permission(EPermission.PublishedOrder)] [HttpGet("published")] public async Task> PublishedOrderList([FromQuery] PagedKeywordRequest dto) { var (total, items) = await _orderPublishRepository.Queryable() .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .OrderBy(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 发布详情 /// /// /// [HttpGet("published-order/{id}")] public async Task PublishedOrder(string id) { var publishedOrder = await _orderPublishRepository.GetAsync(id, HttpContext.RequestAborted); if (publishedOrder is null) { throw UserFriendlyException.SameMessage("未知数据!"); } var pubentity = _mapper.Map(publishedOrder); var visit = await _orderVisitRepository.Queryable().Includes(x => x.OrderVisitDetails) .OrderByDescending(x => x.CreationTime) .FirstAsync(x => x.OrderId == publishedOrder.OrderId, HttpContext.RequestAborted); if (visit != null) { var details = visit.OrderVisitDetails.Where(x => x.VisitTarget == EVisitTarget.Org).ToList(); if (details != null && details.Count > 0) { pubentity.IdNames = new List(); details.ForEach(f => pubentity.IdNames.Add(new Kv() { Key = f.VisitOrgCode, Value = f.VisitOrgName })); } } return pubentity; } /// /// 修改发布内容 /// /// /// [Permission(EPermission.PublishedModify)] [HttpPost("published-order-modify")] [LogFilter("修改发布内容")] public async Task PublishedModify([FromBody] PublishOrderModifyDto dto) { var publishOrder = await _orderPublishRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (publishOrder is null) { throw UserFriendlyException.SameMessage("无效数据"); } var history = new OrderPublishHistory(); history.ArrangeTitleBefor = publishOrder.ArrangeTitle; history.ArrangeTitleAfter = dto.ArrangeTitle; history.ArrangeContentBefor = publishOrder.ArrangeContent; history.ArrangeContentAfter = dto.ArrangeContent; history.ArrangeOpinionBefor = publishOrder.ArrangeOpinion; history.ArrangeOpinionAfter = dto.ArrangeOpinion; history.No = publishOrder.No; history.OrderId = publishOrder.OrderId; history.OrderPublishId = publishOrder.Id; publishOrder.ArrangeTitle = dto.ArrangeTitle; publishOrder.ArrangeContent = dto.ArrangeContent; publishOrder.ArrangeOpinion = dto.ArrangeOpinion; await _orderPublishRepository.UpdateAsync(publishOrder, HttpContext.RequestAborted); await _orderPublishHistoryRepository.AddAsync(history, HttpContext.RequestAborted); } /// /// 发布修改记录 /// /// /// [HttpGet("published-history-list/{id}")] public async Task> QueryPublishedHistory(string id) { return await _orderPublishHistoryRepository.Queryable().Where(x => x.OrderPublishId == id) .OrderByDescending(x => x.CreationTime).ToListAsync(HttpContext.RequestAborted); } #endregion #region 工单回访 /// /// 回访列表 /// /// /// [HttpGet("visit")] public async Task> QueryOrderVisitList([FromQuery] QueryOrderVisitDto dto) { var (total, items) = await _orderVisitRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.Employee) .Includes(x => x.OrderVisitDetails) .WhereIF(dto.VisitState == EVisitStateQuery.NoVisit, x => (x.VisitState == Share.Enums.Order.EVisitState.WaitForVisit || x.VisitState == Share.Enums.Order.EVisitState.NoSatisfiedWaitForVisit) && x.Order.IsProvince == false) .WhereIF(dto.VisitState == EVisitStateQuery.Visited, x => x.VisitState == Share.Enums.Order.EVisitState.Visited) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!) || x.Order.No.Contains(dto.Keyword!)) .WhereIF(dto.VisitType != null, x => x.VisitType == dto.VisitType) .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.CenterFiled, d => d.Order.ProcessType == EProcessType.Zhiban) .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.OrgFiled, d => d.Order.ProcessType == EProcessType.Jiaoban) .WhereIF(dto.IsCountersign != null && dto.IsCountersign == true, d => d.Order.CounterSignType != null) .WhereIF(dto.IsCountersign != null && dto.IsCountersign == false, d => d.Order.CounterSignType == null) .OrderByDescending(x => x.PublishTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 回访查询基础数据 /// /// [HttpGet("visit/basedata")] public async Task VisitBaseData() { var rsp = new { VisitType = EnumExts.GetDescriptions(), }; return rsp; } /// /// 回访详情 /// /// [HttpGet("visit/{id}")] public async Task VisitInfo(string id) { var orderVisit = await _orderVisitRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.Employee) .Includes(x => x.OrderVisitDetails.OrderBy(d => d.VisitTarget).ToList()) .FirstAsync(x => x.Id == id, HttpContext.RequestAborted); if (orderVisit is null) { throw UserFriendlyException.SameMessage("未知工单回访"); } int visitCount = await _orderVisitRepository.CountAsync( x => x.OrderId == orderVisit.OrderId && x.VisitState == Share.Enums.Order.EVisitState.Visited, HttpContext.RequestAborted); //int againCount = await _orderVisitRepository.CountAsync( // x => x.OrderId == orderVisit.OrderId && x.AgainState == EAgainState.DoAgain, HttpContext.RequestAborted); var voiceEvaluate = EnumExts.GetDescriptions(); var seatEvaluate = EnumExts.GetDescriptions(); var visitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction); var dissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason); var visitManner = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitManner); var callRecord = await _trCallRecordRepository.GetAsync(x => x.CallAccept == orderVisit.CallId); var recordingFileUrl = ""; if (callRecord != null) { recordingFileUrl = callRecord.RecordingFileUrl; } return new { OrderVisitModel = _mapper.Map(orderVisit), VisitCount = visitCount, //AgainCount = againCount, VisitSatisfaction = visitSatisfaction, DissatisfiedReason = dissatisfiedReason, VisitManner = visitManner, ViceEvaluate = voiceEvaluate, SeatEvaluate = seatEvaluate, RecordingFileUrl = recordingFileUrl }; } /// /// 回访明细 /// /// [HttpGet("visit/detail")] public async Task> VisitDetailList([FromQuery] VisitDetailListDto dto) { var (total, items) = await _orderVisitedDetailRepository.Queryable() .Includes(x => x.OrderVisit, s => s.Order) .WhereIF(dto.VisitState == EVisitStateQuery.NoVisit, x => x.OrderVisit.VisitState == Share.Enums.Order.EVisitState.WaitForVisit || x.OrderVisit.VisitState == Share.Enums.Order.EVisitState.NoSatisfiedWaitForVisit) .WhereIF(dto.VisitState == EVisitStateQuery.Visited, x => x.OrderVisit.VisitState == Share.Enums.Order.EVisitState.Visited) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.OrderVisit.Order.Title.Contains(dto.Keyword!) || d.OrderVisit.Order.No.Contains(dto.Keyword!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 回访保存 /// /// [Permission(EPermission.Visit)] [HttpPost("visit")] [LogFilter("工单回访")] public async Task Visit([FromBody] VisitDto dto) { //var visit = await _orderVisitRepository.GetAsync(dto.Id, HttpContext.RequestAborted); var visit = await _orderVisitRepository.Queryable() .Includes(d => d.Order) .Includes(d => d.OrderVisitDetails) .FirstAsync(d => d.Id == dto.Id, HttpContext.RequestAborted); if (visit is null) throw UserFriendlyException.SameMessage("未知回访信息"); if (visit.VisitState == EVisitState.Visited) throw UserFriendlyException.SameMessage("已回访,不能重复回访"); var first = dto.VisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org); visit.IsPutThrough = dto.IsPutThrough; visit.AgainState = dto.IsAgain ? EAgainState.NeedAgain : EAgainState.NoAgain; visit.EmployeeId = _sessionContext.UserId; visit.CallId = dto.CallId; if (first != null) { visit.NowEvaluate = first.OrgProcessingResults; } //update order if (dto.IsPutThrough) { visit.VisitState = Share.Enums.Order.EVisitState.Visited; visit.VisitTime = DateTime.Now; if (!string.IsNullOrEmpty(visit.CallId)) { visit.VisitType = EVisitType.CallVisit; } if (visit.VisitType is null) { visit.VisitType = EVisitType.ArtificialVisit; } if (first != null) { visit.Order.Visited(first.OrgProcessingResults.Key, first.OrgProcessingResults.Value); } //_mapper.Map(dto.VisitDetails,visit.OrderVisitDetails); for (int i = 0; i < visit.OrderVisitDetails.Count; i++) { var detail = visit.OrderVisitDetails[i]; var detaildto = dto.VisitDetails.FirstOrDefault(x => x.Id == detail.Id); if (detaildto != null) { _mapper.Map(detaildto, visit.OrderVisitDetails[i]); } } await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); await _orderVisitedDetailRepository.UpdateRangeAsync(visit.OrderVisitDetails, HttpContext.RequestAborted); await _orderRepository.UpdateAsync(visit.Order, HttpContext.RequestAborted); var orderDto = _mapper.Map(visit.Order); if (first != null) { //推省上 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisited, new PublishVisitDto() { Order = orderDto, No = visit.No, VisitType = visit.VisitType, VisitName = visit.CreatorName, VisitTime = visit.VisitTime, VisitRemark = first.VisitContent, AreaCode = visit.Order.AreaCode!, SubjectResultSatifyCode = first.OrgProcessingResults.Key, FirstSatisfactionCode = visit.Order.FirstVisitResultCode!, ClientGuid = "" }, cancellationToken: HttpContext.RequestAborted); //推门户 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisitedWeb, new PublishVisitAllDto() { Id = visit.Id, Order = orderDto, OrderVisitDetails = _mapper.Map>(visit.OrderVisitDetails), VisitName = _sessionContext.UserName, VisitTime = visit.VisitTime, VisitType = visit.VisitType, VisitState = visit.VisitState, PublishTime = visit.PublishTime, }, cancellationToken: HttpContext.RequestAborted); } if (first != null) { //写入质检 await _qualityApplication.AddQualityAsync(EQualitySource.Visit, visit.Order.Id, visit.Id, HttpContext.RequestAborted); } } else { await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); } } /// /// 批量分配回访人员 /// /// /// [HttpPost("visit/distribution")] public async Task DistributionVisit([FromBody] DistributionVisitDto dto) { int error = 0; foreach (var id in dto.Ids) { var visit = await _orderVisitRepository.Queryable().FirstAsync(d => d.Id == id, HttpContext.RequestAborted); if (visit != null && visit.VisitState != EVisitState.WaitForVisit) { visit.EmployeeId = dto.EmployeeId; await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); } else { error++; } } return new DistributionVisitRspDto() { ErrorCount = error, SuccessCount = dto.Ids.Count - error }; } #endregion #region 二次回访申请 /// /// 可二次回访申请列表 /// /// /// [Permission(EPermission.OrderVisitAgainList)] [HttpGet("visitapply/visitagainlist")] public async Task> OrderVisitAgainList([FromQuery] OrderVisitAgainListDto dto) { var (total, items) = await _orderVisitedDetailRepository.Queryable() .Includes(x => x.OrderVisit, x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrderVisit.Order.No.Contains(dto.Keyword)) .Where(x => x.OrderVisit.VisitState == EVisitState.Visited && (x.OrderVisit.VisitType == EVisitType.SmsVisit || x.OrderVisit.VisitType == EVisitType.ChipVoiceVisit)) .Where(x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2") .Where(x => x.OrderVisit.IsCanHandle) .Where(x => x.VisitTarget == EVisitTarget.Org) .OrderByDescending(x => x.OrderVisit.VisitTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 二次回访申请 /// /// /// /// [Permission(EPermission.ApplyOrderVisit)] [HttpPost("visitapply/add")] [LogFilter("新增工单二次回访申请")] public async Task ApplyOrderVisit([FromBody] AddVisitApplyDto dto) { var orderVisitApply = _mapper.Map(dto); //验证是否可以申请二次回访 var isAny = await _orderVisitApplyRepository.AnyAsync( x => x.OrderId == orderVisitApply.OrderId && x.VisitApplyState != EVisitApplyState.NoPass, HttpContext.RequestAborted); if (isAny) throw UserFriendlyException.SameMessage("当前状态不能申请二次回访"); var orderModel = await _orderRepository.GetAsync(x => x.Id == orderVisitApply.OrderId, HttpContext.RequestAborted); if (orderModel?.CounterSignType != null) throw UserFriendlyException.SameMessage("会签件不能申请二次回访"); var orderVisitModel = await _orderVisitRepository.GetAsync(x => x.Id == dto.OrderVisitId && x.IsCanHandle, HttpContext.RequestAborted); if (orderVisitModel == null) throw UserFriendlyException.SameMessage("当前状态不能进行二次回访"); orderVisitModel.IsCanHandle = false; await _orderVisitRepository.UpdateAsync(orderVisitModel, HttpContext.RequestAborted); orderVisitApply.EmployeeId = _sessionContext.RequiredUserId; orderVisitApply.VisitApplyState = EVisitApplyState.Examining; await _orderVisitApplyRepository.AddAsync(orderVisitApply, HttpContext.RequestAborted); } /// /// 二次回访审核 /// /// /// [Permission(EPermission.ExaminOrderVisit)] [HttpPost("visitapply/examin")] [LogFilter("新增工单二次回访审核")] public async Task ExaminOrderVisit([FromBody] ExaminOrderVisitDto dto) { //获取二次回访申请 var visitApplyModel = await _orderVisitApplyRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (visitApplyModel == null) throw UserFriendlyException.SameMessage("无效申请"); if (visitApplyModel.VisitApplyState != EVisitApplyState.Examining) throw UserFriendlyException.SameMessage("当前状态不能审核"); if (dto.IsPass) visitApplyModel.VisitApplyState = EVisitApplyState.Pass; else visitApplyModel.VisitApplyState = EVisitApplyState.NoPass; visitApplyModel.ExaminOpinion = dto.ExaminOpinion; visitApplyModel.ExaminManId = _sessionContext.RequiredUserId; visitApplyModel.ExaminTime = DateTime.Now; await _orderVisitApplyRepository.UpdateAsync(visitApplyModel, HttpContext.RequestAborted); //TODO 处理通过后的业务 if (dto.IsPass) { //处理申请单 visitApplyModel.VisitApplyState = EVisitApplyState.Pass; await _orderVisitApplyRepository.UpdateAsync(visitApplyModel, HttpContext.RequestAborted); //处理原回访数据 var visitModel = await _orderVisitRepository.GetAsync(visitApplyModel.OrderVisitId, HttpContext.RequestAborted); if (visitModel != null) { visitModel.VisitState = EVisitState.None; await _orderVisitRepository.UpdateAsync(visitModel, HttpContext.RequestAborted); //处理新回访数据 //查询原回访数据子表 var visitModelNew = _mapper.Map(visitModel); visitModelNew.InitId(); visitModelNew.CreationTime = DateTime.Now; visitModelNew.CreatorId = string.Empty; visitModelNew.CreatorName = string.Empty; visitModelNew.CreatorOrgId = string.Empty; visitModelNew.CreatorOrgName = string.Empty; visitModelNew.CreatorOrgLevel = 0; visitModelNew.AreaId = string.Empty; visitModelNew.VisitState = EVisitState.WaitForVisit; visitModelNew.IsCanHandle = false; var id = await _orderVisitRepository.AddAsync(visitModelNew, HttpContext.RequestAborted); var visitModelDetail = await _orderVisitedDetailRepository.Queryable() .Where(x => x.VisitId == visitModel.Id).ToListAsync(HttpContext.RequestAborted); var visitDetailListNew = new List(); foreach (var item in visitModelDetail) { var visitDetail = new OrderVisitDetail(); visitDetail.VisitId = id; visitDetail.VisitOrgCode = item.VisitOrgCode; visitDetail.VisitOrgName = item.VisitOrgName; visitDetail.VisitTarget = item.VisitTarget; visitDetailListNew.Add(visitDetail); } await _orderVisitedDetailRepository.AddRangeAsync(visitDetailListNew, HttpContext.RequestAborted); } } else { //处理申请单 visitApplyModel.VisitApplyState = EVisitApplyState.NoPass; visitApplyModel.ExaminManId = _sessionContext.RequiredUserId; visitApplyModel.ExaminOpinion = dto.ExaminOpinion; visitApplyModel.ExaminTime = DateTime.Now; await _orderVisitApplyRepository.UpdateAsync(visitApplyModel, HttpContext.RequestAborted); var visitModel = await _orderVisitRepository.GetAsync(visitApplyModel.OrderVisitId, HttpContext.RequestAborted); if (visitModel != null) { visitModel.IsCanHandle = true; await _orderVisitRepository.UpdateAsync(visitModel, HttpContext.RequestAborted); } } } /// /// 二次回访申请列表 /// /// /// [Permission(EPermission.VisitApplyList)] [HttpGet("visitapply/list")] public async Task> VisitApplyList([FromQuery] VisitApplyListDto dto) { var (total, items) = await _orderVisitApplyRepository.Queryable() .Includes(d => d.Order) .Includes(d => d.OrderVisit, d => d.OrderVisitDetails.Where(x => x.VisitTarget == EVisitTarget.Org).ToList()) .Includes(d => d.OrderVisit, d => d.Employee) .Includes(d => d.Employee) .WhereIF(dto.VisitApplyState != null, x => x.VisitApplyState == dto.VisitApplyState) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrderNo.Contains(dto.Keyword)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取二次回访申请 /// /// /// [HttpGet("visitapply/{id}")] public async Task VisitApplyEntity(string id) { var model = await _orderVisitApplyRepository.GetExtAsync(x => x.Id == id, x => x.Includes(d => d.Order)); return _mapper.Map(model); } /// /// 页面基础信息 /// /// [HttpGet("visitapply/basedata")] public async Task VisitApplyBaseData() { var rsp = new { VisitApplyState = EnumExts.GetDescriptions() }; return rsp; } #endregion #region 工单重办 /// /// 重办查询 /// /// /// [HttpGet("redo")] public async Task> QueryOrderRedo([FromQuery] QueryOrderRedoRecordDto dto) { var (total, items) = await _orderRedoRepository.Queryable() .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, items); } /// /// 重办详情 /// /// /// [HttpGet("redo/{id}")] public async Task GetOrderRedo(string id) { return await _orderRedoRepository.Queryable() .Includes(x => x.Order) .FirstAsync(x => x.Id == id); } /// /// 发起重办 /// [HttpPost("redo")] [LogFilter("新增工单重办")] public async Task AddRedo([FromBody] OrderRedoStartFlowDto dto) { var redo = _mapper.Map(dto.Data); redo.CreatorName = _sessionContext.UserName ?? string.Empty; redo.CreatorOrgName = _sessionContext.OrgName ?? string.Empty; //redo.TimeLimitCount = dto.Workflow.Extension.TimeLimitCount; //redo.TimeLimitUnit = dto.Workflow.Extension.TimeLimitUnit; //todo var handler = dto.Workflow.NextHandlers.First(); redo.RedoOrgCode = handler.Key; redo.RedoOrgCode = handler.Value; var id = await _orderRedoRepository.AddAsync(redo, HttpContext.RequestAborted); try { var order = await _orderRepository.GetAsync(dto.Data.OrderId, HttpContext.RequestAborted); if (order == null) throw UserFriendlyException.SameMessage("无效工单编号"); if (string.IsNullOrEmpty(order.WorkflowId)) throw UserFriendlyException.SameMessage("无效工单流程编号"); var redoFlowDto = _mapper.Map(dto.Workflow); redoFlowDto.WorkflowId = order.WorkflowId; await _workflowApplication.RedoAsync(redoFlowDto, HttpContext.RequestAborted); return id; } catch (Exception e) { await _orderRedoRepository.RemoveAsync(id, cancellationToken: HttpContext.RequestAborted); throw new UserFriendlyException($"发起重办失败,{e.Message}"); } } /// /// 重办基础数据 /// /// [HttpGet("base-data-redo")] public async Task BaseDataRedo() { var rsp = new { OrderRedoReasonOptions = EnumExts.GetDescriptions(), }; return rsp; } #endregion #region 工单延期 /// /// 可申请延期工单 /// /// /// [HttpGet("candelay")] public async Task> CanDelayOrderList([FromQuery] CanDelayOrderListDto dto) { var (total, items) = await _orderRepository.Queryable() .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!)) .Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.Filed && SqlFunc.Subqueryable() .Where(s => s.OrderId == d.Id && s.DelayState == EDelayState.Examining).NotAny()) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 申请延期 /// /// /// //[Permission(EPermission.ApplyDelay)] [HttpPost("delay")] [LogFilter("新增工单延期申请")] public async Task ApplyDelay([FromBody] DelayStartFlowDto dto) { var delaydto = dto.Data; if (string.IsNullOrEmpty(dto.Workflow.Opinion)) throw UserFriendlyException.SameMessage("办理意见不能为空!"); //验证工单是否可以申请 var order = await _orderRepository.GetAsync(delaydto.OrderId, HttpContext.RequestAborted); if (order is null) throw UserFriendlyException.SameMessage("无效工单"); //验证工单是否在办理中 if (order.Status == EOrderStatus.WaitForAccept || order.Status >= EOrderStatus.Filed) throw UserFriendlyException.SameMessage("当前工单状态不能申请延期"); bool IsHas = await _orderDelayRepository.AnyAsync( x => x.OrderId == delaydto.OrderId && x.DelayState == EDelayState.Examining, HttpContext.RequestAborted); if (IsHas) throw UserFriendlyException.SameMessage("该存在延期申请正在审核"); //验证延期次数 var setting = _systemSettingCacheManager.GetSetting(SettingConstants.DelayNum); if (int.Parse(setting?.SettingValue[0]) != 0) { int count = await _orderDelayRepository.CountAsync(x => x.OrderId == delaydto.OrderId && x.DelayState == EDelayState.Pass); if (count >= int.Parse(setting?.SettingValue[0])) throw UserFriendlyException.SameMessage("延期申请已超过系统预定设置,不能申请"); } var model = _mapper.Map(delaydto); model.EmployeeId = _sessionContext.RequiredUserId; model.EmployeeName = _sessionContext.UserName; model.ApplyOrgName = _sessionContext.OrgName; model.ApplyOrgCode = _sessionContext.RequiredOrgId; model.BeforeDelay = order.ExpiredTime; model.DelayState = EDelayState.Examining; model.DelayReason = dto.Workflow.Opinion; if (model.BeforeDelay != null) { model.AfterDelay = _timeLimitDomainService .CalcEndTime(model.BeforeDelay.Value, delaydto.DelayUnit, delaydto.DelayNum, order.AcceptTypeCode)?.EndTime; //todo } model.ApplyDelayTime = DateTime.Now; model.No = order.No; model.InitId(); if (dto.Data.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted); await _orderDelayRepository.AddAsync(model, HttpContext.RequestAborted); try { var startDto = _mapper.Map(dto.Workflow); startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderDelay; startDto.Title = model.DelayReason; string workFlowId = await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted); //model.WorkflowId = workFlowId; //await _orderDelayRepository.UpdateAsync(model, HttpContext.RequestAborted); } catch (Exception ex) { await _orderDelayRepository.RemoveAsync(model.Id, false, HttpContext.RequestAborted); throw new UserFriendlyException($"工单延期流程失败!, {ex.Message}", "工单延期流程失败"); } } /// /// 工单延期修改后下一步流程 /// [HttpPost("delay/initial_nextFlow")] [LogFilter("开始工单延期流程")] public async Task InitialNextFlow([FromBody] DelayNextFlowDto dto) { var delay = await _orderDelayRepository.GetAsync(dto.Data.Id); _mapper.Map(dto.Data, delay); if (dto.Data.Files.Any()) delay.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, delay.Id, "", HttpContext.RequestAborted); await _orderDelayRepository.UpdateAsync(delay, HttpContext.RequestAborted); try { dto.NextWorkflow.WorkflowId = delay.WorkflowId; await _workflowApplication.NextAsync(dto.NextWorkflow, cancellationToken: HttpContext.RequestAborted); } catch (Exception e) { throw new UserFriendlyException($"工单延期下一步流程失败!, {e.Message}", "工单延期下一步流程失败"); } } /// /// 取消工单延期 /// /// /// [HttpPost("delay/cancel")] [LogFilter("取消工单延期")] public async Task CancelDelay([FromBody] CancelDelayDto dto) { var orderDelay = await _orderDelayRepository.GetAsync(x => x.OrderId == dto.Id && x.DelayState == EDelayState.Examining, HttpContext.RequestAborted); if (orderDelay != null) { await _workflowDomainService.TerminateAsync(new TerminateDto() { WorkflowId = orderDelay.WorkflowId, Opinion = "" }, HttpContext.RequestAborted); orderDelay.DelayState = EDelayState.Withdraw; await _orderDelayRepository.UpdateAsync(orderDelay, HttpContext.RequestAborted); } else { throw UserFriendlyException.SameMessage("无效数据"); } } /// /// 延期列表 /// /// //[Permission(EPermission.DelayList)] [HttpGet("delay")] public async Task> DelayList([FromQuery] DelayListDto dto) { var (total, items) = await _orderDelayRepository.Queryable(permissionVerify: true) .Includes(x => x.Order) .Includes(x => x.Workflow) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .WhereIF(dto.IsApply == true, x => x.DelayState != EDelayState.Examining) .WhereIF(dto.IsApply == false, x => x.DelayState == EDelayState.Examining) .WhereIF(dto.DelayState != null, x => x.DelayState == dto.DelayState) .OrderByDescending(x => x.ApplyDelayTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 延期列表 /// /// //[Permission(EPermission.DelayList)] [HttpGet("wait_delay")] public async Task> WaitDelayList([FromQuery] DelayListDto dto) { var isHandled = dto.IsApply.HasValue && dto.IsApply.Value; var (total, items) = await _orderDelayRepository .Queryable(viewFilter: true, handlerFilter: !isHandled) .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!)) //.WhereIF(dto.IsApply == true, x => x.DelayState != EDelayState.Examining) //.WhereIF(dto.IsApply == false, x => x.DelayState == EDelayState.Examining) .WhereIF(dto.DelayState != null, x => x.DelayState == dto.DelayState) .OrderByDescending(x => x.ApplyDelayTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 延期详情 /// /// /// //[Permission(EPermission.DelayEntity)] [HttpGet("delay/{id}")] public async Task DelayEntity(string id) { var model = await _orderDelayRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.Workflow) .FirstAsync(x => x.Id == id); var rspModel = _mapper.Map(model); rspModel.IsCanHandle = model.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId); rspModel.Handle = await _workflowDomainService.CheckCurrentIsStartStepAsync(rspModel.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, HttpContext.RequestAborted); if (rspModel.FileJson != null && rspModel.FileJson.Any()) { var ids = rspModel.FileJson.Select(x => x.Id).ToList(); rspModel.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted); } return rspModel; } /// /// 计算期满时间 /// /// /// [HttpPost("delay/calc-endtime")] public async Task DelayCalcEndTime([FromBody] DelayCalcEndTimeDto dto) { return _timeLimitDomainService.CalcEndTime(dto.BeginTime, dto.DelayUnit, dto.DelayNum, 0); } /// /// 查询工单延期流程开启参数 /// /// [HttpGet("delay/startflow")] public async Task GetDelayFlowStartOptions() { return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderDelay, HttpContext.RequestAborted); } /// /// 延期页面基础信息 /// /// [HttpGet("delay/basedata")] public async Task DelayBaseData() { var rsp = new { DelayState = EnumExts.GetDescriptions(), TimeType = EnumExts.GetDescriptions() }; return rsp; } #endregion #region 工单甄别 /// /// 工单甄别待申请列表 /// /// /// [Permission(EPermission.CanOrderScreen)] [HttpGet("mayscreen")] public async Task> MayScreenList([FromQuery] MayScreenListDto dto) { var query = _orderVisitedDetailRepository.Queryable(false, true) .Includes(x => x.OrderVisit) .Includes(x => x.OrderVisit, y => y.Order) .Includes(x => x.OrderVisit, y => y.Employee) .LeftJoin((x, s) => x.Id == s.VisitDetailId && (int)s.Status < 2 && s.IsDeleted == false) .Where((x, s) => s.Id == null) .Where((x, s) => x.OrderVisit.VisitState != EVisitState.None && x.OrderVisit.IsCanHandle); if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter) { query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) || x.OrderVisit.Order.No.Contains(dto.Keyword!)) .Where((x, s) => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode.StartsWith(_sessionContext.OrgId) && ( SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2" )); } else { query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) || x.OrderVisit.Order.No.Contains(dto.Keyword!)) .Where((x, s) => x.VisitTarget == EVisitTarget.Org && ( SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2" )); } var (total, items) = await query .OrderBy((x, s) => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 工单甄别列表 /// /// /// [HttpGet("screen")] public async Task> ScreenList([FromQuery] ScreenListDto dto) { var view = dto.source == 1; var handler = dto.source == 1 && dto.Status is EScreenStatus.Apply; var query = _orderScreenRepository.Queryable(viewFilter: view, handlerFilter: handler) .Includes(x => x.Order) .Includes(x => x.VisitDetail) .Includes(x => x.Visit, d => d.Order) .Includes(x => x.Workflow) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Visit.Order.Title.Contains(dto.Keyword!) || x.Visit.Order.No.Contains(dto.Keyword!)); if (dto.Status is EScreenStatus.Apply) { query.Where(x => (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval)); } if (dto.Status.HasValue && dto.Status == EScreenStatus.MyHandle) { query.Where(x => (x.Status != EScreenStatus.Apply)); } var (total, items) = await query //.WhereIF(dto.Status.HasValue && dto.Status == EScreenStatus.MyHandle, // x => x.Status != EScreenStatus.Apply && x.CreatorId == _sessionContext.UserId) .WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd) .WhereIF(!string.IsNullOrEmpty(dto.OrderId), x => x.OrderId == dto.OrderId) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 开始工单甄别流程 /// [Permission(EPermission.ApplyScreen)] [HttpPost("screen/startflow")] [LogFilter("开始工单甄别流程")] public async Task StartFlow([FromBody] ScreenStartFlowDto dto) { var screenAny = await _orderScreenRepository.AnyAsync(x => x.VisitDetailId == dto.Data.VisitDetailId && (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval)); if (screenAny) throw UserFriendlyException.SameMessage("该工单已提起甄别申请,正在审批过程中,不能申请"); var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ScreenApplyNum); int count = await _orderScreenRepository.CountAsync(x => x.OrderId == dto.Data.OrderId && x.Status == EScreenStatus.Refuse); if (count > int.Parse(setting?.SettingValue[0])) throw UserFriendlyException.SameMessage("甄别申请已超过系统预定设置,不能申请"); var visit = await _orderVisitRepository.GetAsync(dto.Data.VisitId, HttpContext.RequestAborted); setting = _systemSettingCacheManager.GetSetting(SettingConstants.ScreenApplyEndTime); var endTime = _timeLimitDomainService .CalcEndTime(visit.VisitTime.Value, ETimeType.WorkDay, int.Parse(setting?.SettingValue[0]), 0).EndTime; if (DateTime.Now > endTime) throw UserFriendlyException.SameMessage("甄别申请时限已超过系统预定设置,不能申请"); var model = _mapper.Map(dto.Data); model.Status = EScreenStatus.Apply; model.ApplyEndTime = endTime; model.InitId(); if (dto.Data.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted); await _orderScreenRepository.AddAsync(model, HttpContext.RequestAborted); var workflowId = string.Empty; try { //二次回访会改写数据 //await _orderRepository.OrderScreenRevisionVisit(visit.Id, false, HttpContext.RequestAborted); var startDto = _mapper.Map(dto.Workflow); startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderScreen; startDto.Title = dto.Data.Content; workflowId = await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted); //var screen = await _orderScreenRepository.GetAsync(model.Id, HttpContext.RequestAborted); //if (screen != null) //{ // screen.WorkflowId = workflowId; // await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted); //} } catch (Exception e) { await _orderScreenRepository.RemoveAsync(model.Id); model.Id = string.Empty; throw new UserFriendlyException($"工单开启甄别流程失败!, {e.Message}", "工单开启甄别流程失败"); } } /// /// 工单甄别修改后下一步流程 /// [HttpPost("screen/initial_nextFlow")] [LogFilter("开始工单甄别流程")] public async Task InitialNextFlow([FromBody] ScreenNextFlowDto dto) { var screen = await _orderScreenRepository.GetAsync(dto.Data.Id); _mapper.Map(dto.Data, screen); if (dto.Data.Files.Any()) screen.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, screen.Id, "", HttpContext.RequestAborted); await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted); try { dto.NextWorkflow.WorkflowId = screen.WorkflowId; await _workflowApplication.NextAsync(dto.NextWorkflow, cancellationToken: HttpContext.RequestAborted); } catch (Exception e) { throw new UserFriendlyException($"工单甄别下一步流程失败!, {e.Message}", "工单甄别下一步流程失败"); } } /// /// 查询工单甄别流程开启参数 /// /// [HttpGet("screen/startflow")] public async Task GetScreenFlowStartOptionsAsync() { //return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.OrderScreen, // HttpContext.RequestAborted); return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderScreen, HttpContext.RequestAborted); } /// /// 查询工单甄别流程参数 /// /// [HttpGet("screen/workflow/{id}")] public async Task GetScreenWorkFlowAsync(string id) { var workflow = await _workflowRepository.Queryable().FirstAsync(x => x.ExternalId == id); return workflow.Id; } /// /// 列表页面基础数据 /// /// [HttpGet("screen/base")] public async Task ScreenBaseData() { var rsp = new { ScreenStatus = EnumExts.GetDescriptions(), ScreenType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ScreenType), }; return rsp; } /// /// 甄别详情 /// /// /// [HttpGet("screen/{id}")] public async Task ScreenEntity(string id) { var model = await _orderScreenRepository.Queryable(viewFilter: false) .Includes(x => x.Order) .Includes(x => x.Workflow) .Includes(x => x.Visit, d => d.Order) .FirstAsync(x => x.Id == id); var rspModel = _mapper.Map(model); rspModel.IsCanHandle = model.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId); rspModel.Handle = await _workflowDomainService.CheckCurrentIsStartStepAsync(rspModel.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, HttpContext.RequestAborted); if (rspModel.FileJson != null && rspModel.FileJson.Any()) { var ids = rspModel.FileJson.Select(x => x.Id).ToList(); rspModel.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted); } return rspModel; } #endregion #region 工单督办 /// /// 工单督办列表 /// /// /// [HttpGet("supervise")] public async Task> SuperviseList([FromQuery] SuperviseListDto dto) { var (total, items) = await _orderSuperviseRepository.Queryable() .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .WhereIF(dto.SuperviseState > -1, x => x.State == dto.SuperviseState) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .Where(x => x.OrgId == _sessionContext.OrgId) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 申请督办 /// /// /// [Permission(EPermission.ApplySupervise)] [HttpPost("supervise/apply")] [LogFilter("新增工单督办")] public async Task ApplySupervise([FromBody] ApplyOrderSuperviseDto dto) { if (!dto.SuperviseOrgDtos.Any()) throw UserFriendlyException.SameMessage("请选择被督办部门"); //验证工单是否可以申请 var order = await _orderRepository.GetAsync(dto.OrderId, HttpContext.RequestAborted); if (order is null) throw UserFriendlyException.SameMessage("无效工单"); foreach (var item in dto.SuperviseOrgDtos) { var model = _mapper.Map(dto); model.OrgId = item.OrgId; model.OrgName = item.OrgName; model.LaunchOrgName = _sessionContext.OrgName; model.CrUser = _sessionContext.UserName; model.State = 0; model.InitId(); if (dto.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", HttpContext.RequestAborted); await _orderSuperviseRepository.AddAsync(model, HttpContext.RequestAborted); if (dto.AcceptSms) { //发送短信 try { //查询部门所有账号 var userlist = await _userRepository.Queryable().Where(x => x.OrgId == model.OrgId).ToListAsync(); //发送短信 foreach (var user in userlist) { var messageDto = new MessageDto { PushBusiness = EPushBusiness.OrderSupervise, ExternalId = order.Id, OrderId = order.Id, PushPlatform = EPushPlatform.Sms, Remark = order.Title, Name = user.PhoneNo, TemplateCode = "1003", Params = new List() { order.No }, TelNumber = user.PhoneNo, }; await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted); } } catch { } } //推省上 if (!string.IsNullOrEmpty(model.Id) && ("001170".Equals(model.OrgId) || "001177".Equals(model.OrgId))) { var orderDto = _mapper.Map(order); var supervise = await _orderSuperviseRepository.GetAsync(x => x.Id == model.Id); if (supervise != null) { var superviseDto = _mapper.Map(supervise); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderUrgeInform, new PublishUrgeDto() { Order = orderDto, Urge = _mapper.Map(superviseDto), ClientGuid = "" }); //try //{ // await _provinceService.SendSuperviseProcessInfo(new PublishSuperviseDto() // { // Order = orderDto, // Supervise = superviseDto, // ClientGuid = "" // }, HttpContext.RequestAborted); //} //catch (Exception e) //{ // _logger.LogError("_provinceService.SendSuperviseProcessInfo throw exception: {ex}", e.Message); //} } } } } /// /// 回复督办 /// /// /// [HttpPost("supervise/reply")] [LogFilter("回复工单督办")] public async Task ReplySupervise([FromBody] ReplyOrderSuperviseDto dto) { //验证是否存在督办 var supervise = await _orderSuperviseRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (supervise is null) throw UserFriendlyException.SameMessage("无效督办"); if (supervise.State > 0) throw UserFriendlyException.SameMessage("督办已回复,请勿重复回复"); _mapper.Map(dto, supervise); supervise.ReplyId = _sessionContext.UserId; supervise.ReUser = _sessionContext.UserName; supervise.ReplyTime = DateTime.Now; supervise.State = 1; if (dto.Files.Any()) supervise.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, supervise.Id, "", HttpContext.RequestAborted); await _orderSuperviseRepository.UpdateAsync(supervise, HttpContext.RequestAborted); var order = await _orderRepository.GetAsync(supervise.OrderId, HttpContext.RequestAborted); //推省上 if (order != null && ("001170".Equals(supervise.OrgId) || "001177".Equals(supervise.OrgId))) { var orderDto = _mapper.Map(order); var superviseDto = _mapper.Map(supervise); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderSuperviseResult, new PublishSuperviseDto() { Order = orderDto, Supervise = superviseDto, ClientGuid = "" }, cancellationToken: HttpContext.RequestAborted); //try //{ // await _provinceService.SendSuperviseProcessInfo(new PublishSuperviseDto() // { // Order = orderDto, // Supervise = superviseDto, // ClientGuid = "" // }, HttpContext.RequestAborted); //} //catch (Exception e) //{ // _logger.LogError("_provinceService.SendSuperviseProcessInfo throw exception: {ex}", e.Message); //} } } /// /// 签收督办 /// /// /// [HttpPost("supervise/sign")] [LogFilter("签收工单督办")] public async Task SignSupervise([FromBody] SignOrderSuperviseDto dto) { //验证是否存在督办 var supervise = await _orderSuperviseRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (supervise is null) throw UserFriendlyException.SameMessage("无效督办"); //supervise.State = 2; supervise.SignTime = DateTime.Now; supervise.SignUser = _sessionContext.UserName; await _orderSuperviseRepository.UpdateAsync(supervise, HttpContext.RequestAborted); var order = await _orderRepository.GetAsync(supervise.OrderId, HttpContext.RequestAborted); //推省上 if (order != null && ("001170".Equals(supervise.OrgId) || "001177".Equals(supervise.OrgId))) { var orderDto = _mapper.Map(order); var superviseDto = _mapper.Map(supervise); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderSuperviseCourse, new PublishSuperviseDto() { Order = orderDto, Supervise = superviseDto, ClientGuid = "" }, cancellationToken: HttpContext.RequestAborted); //try //{ // await _provinceService.SendSuperviseProcessInfo(new PublishSuperviseDto() // { // Order = orderDto, // Supervise = superviseDto, // ClientGuid = "" // }, HttpContext.RequestAborted); //} //catch (Exception e) //{ // _logger.LogError("_provinceService.SendSuperviseProcessInfo throw exception: {ex}", e.Message); //} } } /// /// 督办详情 /// /// /// [HttpGet("supervise/{id}")] public async Task SuperviseEntity(string id) { var orderSupervise = await _orderSuperviseRepository.Queryable() .Includes(x => x.Order) .FirstAsync(x => x.Id == id); var orderSuperviseDto = new OrderSuperviseDto(); if (orderSupervise != null) { orderSuperviseDto = _mapper.Map(orderSupervise); if (orderSuperviseDto.FileJson != null && orderSuperviseDto.FileJson.Any()) { var ids = orderSuperviseDto.FileJson.Select(x => x.Id).ToList(); var files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted); orderSuperviseDto.Files = files.Where(x => x.Classify == "督办申请").ToList(); orderSuperviseDto.ReplyFiles = files.Where(x => x.Classify == "督办回复").ToList(); } } return orderSuperviseDto; } #endregion #region 工单催办 /// /// 工单催办列表 /// /// /// [HttpGet("urge")] public async Task> UrgeList([FromQuery] UrgeListDto dto) { var (total, items) = await _orderUrgeRepository.Queryable(permissionVerify:true) .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .WhereIF(dto.UrgeState > -1, x => x.State == dto.UrgeState) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .Where(x => x.OrgId == _sessionContext.OrgId) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 申请催办 /// /// /// [Permission(EPermission.ApplyUrge)] [HttpPost("urge/apply")] [LogFilter("新增工单催办")] public async Task ApplyUrge([FromBody] ApplyOrderUrgeDto dto) { if (!dto.UrgeOrgDtos.Any()) throw UserFriendlyException.SameMessage("请选择被催办部门"); //验证工单是否可以申请 var order = await _orderRepository.GetAsync(dto.OrderId, HttpContext.RequestAborted); if (order is null) throw UserFriendlyException.SameMessage("无效工单"); foreach (var item in dto.UrgeOrgDtos) { var model = _mapper.Map(dto); model.OrgId = item.OrgId; model.OrgName = item.OrgName; model.CreatorOrgName = _sessionContext.OrgName; model.CrUser = _sessionContext.UserName; model.State = 0; model.InitId(); if (dto.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", HttpContext.RequestAborted); await _orderUrgeRepository.AddAsync(model, HttpContext.RequestAborted); if (dto.AcceptSms) { try { //查询部门所有账号 var userlist = await _userRepository.Queryable().Where(x => x.OrgId == model.OrgId).ToListAsync(); foreach (var user in userlist) { //发送短信 var messageDto = new MessageDto { PushBusiness = EPushBusiness.OrderUrge, ExternalId = order.Id, OrderId = order.Id, PushPlatform = EPushPlatform.Sms, Remark = order.Title, Name = user.PhoneNo, TemplateCode = "1002", Params = new List() { order.No }, TelNumber = user.PhoneNo, }; await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted); } } catch { } } //推省上 if (!string.IsNullOrEmpty(model.Id) && ("001170".Equals(model.OrgId) || "001177".Equals(model.OrgId))) { var orderDto = _mapper.Map(order); var urge = await _orderUrgeRepository.GetAsync(x => x.Id == model.Id); if (urge != null) { var urgeDto = _mapper.Map(urge); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderUrgeInform, new PublishUrgeDto() { Order = orderDto, Urge = urgeDto, ClientGuid = "" }); } } } } /// /// 回复催办 /// /// /// [HttpPost("urge/reply")] [LogFilter("回复工单催办")] public async Task ReplyUrge([FromBody] ReplyOrderUrgeDto dto) { //验证是否存在催办 var urge = await _orderUrgeRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (urge is null) throw UserFriendlyException.SameMessage("无效催办"); if (urge.State > 0) throw UserFriendlyException.SameMessage("督办已回复,请勿重复回复"); _mapper.Map(dto, urge); urge.ReplyId = _sessionContext.UserId; urge.ReUser = _sessionContext.UserName; urge.ReplyContent = dto.ReplyContent; urge.ReplyTime = DateTime.Now; urge.State = 1; if (dto.Files.Any()) urge.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, urge.Id, "", HttpContext.RequestAborted); await _orderUrgeRepository.UpdateAsync(urge, HttpContext.RequestAborted); } /// /// 签收催办 /// /// /// [HttpPost("urge/sign")] [LogFilter("签收工单催办")] public async Task SignUrge([FromBody] SignOrderUrgeDto dto) { //验证是否存在催办 var urge = await _orderUrgeRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (urge is null) throw UserFriendlyException.SameMessage("无效催办"); urge.State = 2; urge.SignUser = _sessionContext.UserName; urge.SignTime = DateTime.Now; await _orderUrgeRepository.UpdateAsync(urge, HttpContext.RequestAborted); } /// /// 催办详情 /// /// /// [HttpGet("urge/{id}")] public async Task UrgeEntity(string id) { var orderUrge = await _orderUrgeRepository.Queryable() .Includes(x => x.Order) .FirstAsync(x => x.Id == id); var orderUrgeDto = new OrderUrgeDto(); if (orderUrge != null) { orderUrgeDto = _mapper.Map(orderUrge); if (orderUrgeDto.FileJson != null && orderUrgeDto.FileJson.Any()) { var ids = orderUrgeDto.FileJson.Select(x => x.Id).ToList(); orderUrgeDto.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted); } } return orderUrgeDto; } #endregion #region 工单办理 /// /// 工单列表 /// /// /// [Permission(EPermission.OrderQuery)] [HttpGet] public async Task> Query([FromQuery] QueryOrderDto dto) { var (total, items) = await _orderRepository.Queryable(viewFilter: true) .Includes(x => x.OrderScreens) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!)) //标题 .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), d => d.ProvinceNo.Contains(dto.ProvinceNo)) //省本地编号 .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No)) //工单编码 //.WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!)) .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType)) //受理类型 .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannelCode)) //来源渠道 .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) //热点类型 .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone!)) //转接号码 //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode))) .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门 .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo!) || d.AcceptorStaffNo.Contains(dto.NameOrNo!)) //受理人/坐席 .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始 .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束 .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel)) //紧急程度 .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone.Contains(dto.FromPhone)) //来电号码 .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.Contact.Contains(dto.PhoneNo!)) //联系电话 .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) //推送分类 .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始 .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束 .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status)) //工单状态 .WhereIF(dto.Statuses.Any(d => d == EOrderStatus.BackToUnAccept), d => d.Status <= EOrderStatus.BackToUnAccept) .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.ActualHandlerName.Contains(dto.ActualHandlerName)) //接办人 .WhereIF(dto.IsScreen == true, d => d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //有甄别 .WhereIF(dto.IsScreen == false, d => !d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //无甄别 .WhereIF(!string.IsNullOrEmpty(dto.CurrentStepCode), d => d.ActualHandleStepCode == dto.CurrentStepCode) //当前办理节点 .WhereIF(dto.ActualHandleTimeStart.HasValue, d => d.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始 .WhereIF(dto.ActualHandleTimeEnd.HasValue, d => d.ActualHandleTime <= dto.ActualHandleTimeEnd) //办结时间结束 .WhereIF(dto.IsOverTime == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //是 超期 .WhereIF(dto.IsOverTime == false, d => (d.ExpiredTime > DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime > d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //否 超期 .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体 .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.FromName.Contains(dto.FromName)) //来电人姓名 .WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域 .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true,x=>x.IsProvince == true) .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false,x=>x.IsProvince == false) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 历史工单 /// /// /// [HttpGet("history")] public async Task> Query([FromQuery] QueryOrderHistoryDto dto) { var (total, items) = await _orderRepository.Queryable() .Where(d => d.FromPhone == dto.PhoneNo) .WhereIF(!string.IsNullOrEmpty(dto.OrderId), d => d.Id != dto.OrderId) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!)) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 查询重复工单 /// [HttpGet("duplicate")] public async Task> Query([FromQuery] QueryOrderDuplicateDto dto) { if (!dto.OrderIds.Any()) return new PagedDto(0, new List()); var (total, items) = await _orderRepository.Queryable() .Where(d => dto.OrderIds.Contains(d.Id)) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 查询工单详情 /// /// /// [HttpGet("{id}")] public async Task Get(string id) { var order = await _orderRepository.Queryable() .Includes(d => d.OrderExtension) .Includes(d => d.OrderDelays) //.Includes(d => d.OrderScreens) .Includes(d => d.OrderVisits, x => x.OrderVisitDetails) .Includes(d => d.OrderVisits, x => x.Employee) .FirstAsync(d => d.Id == id); if (order == null) return new(); string? countersignId = null; if (!string.IsNullOrEmpty(order.WorkflowId)) { var (workflow, unCompleteCountersignId) = await _workflowDomainService.GetWorkflowHandlePermissionAsync( order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, cancellationToken: HttpContext.RequestAborted); order.Workflow = workflow; countersignId = unCompleteCountersignId; await _mediator.Publish(new GetOrderDetailNotify(order.Workflow, _sessionContext.RequiredUserId, _sessionContext.UserName, _sessionContext.RequiredOrgId, _sessionContext.OrgName, _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName)); } var dto = _mapper.Map(order!); dto.CountersignId = countersignId; dto.CanHandle = order.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId); dto.IsCanDelay = !order.OrderDelays.Any(x => x.DelayState == EDelayState.Examining); var delayModel = order.OrderDelays.Where(x => x.DelayState == EDelayState.Pass).MaxBy(x => x.CreationTime); dto.DelayString = delayModel != null ? delayModel?.DelayNum + "个" + delayModel?.DelayUnit.GetDescription() : ""; if (dto.FileJson != null && dto.FileJson.Any()) { var ids = order.FileJson.Select(x => x.Id).ToList(); var files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted); dto.Files = files.Where(x => x.Classify == "办理上传" && string.IsNullOrEmpty(x.FlowKey)).ToList(); } var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == order.CallId).FirstAsync(); if (call != null) dto.RecordingFileUrl = call.RecordingFileUrl; if (order.Workflow != null) { dto.CanPrevious = !order.Workflow.IsInCountersign; } var repeatablesMap = await _repeatableEventDetailRepository.Queryable() .Includes(x => x.Order) .Where(x => x.OrderId == id).Distinct().ToListAsync(); var repeatables = _mapper.Map>(repeatablesMap); dto.RepeatableEventDetails = repeatables; return dto; } /// /// 新增工单 /// /// /// [Permission(EPermission.OrderAdd)] [HttpPost] [LogFilter("新增工单")] public async Task Add([FromBody] AddOrderDto dto) { dto.InitAddress(); //todo dto validation if (!string.IsNullOrEmpty(dto.CallId)) { var exists = await _orderRepository.AnyAsync(d => d.CallId == dto.CallId, HttpContext.RequestAborted); if (exists) throw UserFriendlyException.SameMessage("来电已保存工单"); } var order = _mapper.Map(dto); order.SignerId = _sessionContext.UserId; order.SignerName = _sessionContext.UserName; order.InitId(); if (dto.Files.Any()) order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, "", HttpContext.RequestAborted); await _orderDomainService.AddAsync(order, true, HttpContext.RequestAborted); //if (dto.Tags.Any()) await _repositoryts.AddVectorAsync(orderId, DateTime.Now, dto.Tags, HttpContext.RequestAborted); if (dto.RepeatableEventDetails?.Any() ?? false) { dto.RepeatableEventDetails.ForEach(x => x.OrderId = order.Id); List repeatables = _mapper.Map>(dto.RepeatableEventDetails); await _repeatableEventDetailRepository.AddRangeAsync(repeatables, HttpContext.RequestAborted); } //工单ID跟通话记录相关联 var callRecord = await _trCallRecordRepository.GetAsync(p => p.CallAccept == order.CallId, HttpContext.RequestAborted); if (callRecord != null && string.IsNullOrEmpty(callRecord.ExternalId)) { callRecord.ExternalId = order.Id; callRecord.CallOrderType = Share.Enums.CallCenter.ECallOrderType.Order; await _trCallRecordRepository.UpdateAsync(callRecord, HttpContext.RequestAborted); } //内容分词 await _orderApplication.OrderParticiple(dto.Content, order.Id, HttpContext.RequestAborted); //sms try { if (order.AcceptSms) { _logger.LogInformation($"推送短信: orderNo: {order.No}"); var messageDto = new MessageDto { PushBusiness = EPushBusiness.OrderAccept, ExternalId = order.Id, OrderId = order.Id, PushPlatform = EPushPlatform.Sms, //Content = // $"温馨提示:您的来电已受理(流水号:{order.No};提取码:{order.Password},可通过网站(http://hotline.12345lm.cn)进行查询,谢谢。【宜宾12345热线平台】)", Remark = order.Title, Name = order.FromName, TemplateCode = "1005", Params = new List() { order.No, order.Password }, TelNumber = order.Contact, }; await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted); //await _pushDomainService.PushAsync(MessageDto, HttpContext.RequestAborted); order.SmsSended = true; await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); } } catch (Exception e) { _logger.LogError("新增工单发送短信失败,Error:{err}", e.Message); } return order.Id; } /// /// 提供ds调用 /// [HttpPost("add-anonymous")] [AllowAnonymous] public async Task AddAnonymous([FromBody] AddOrderDto dto) { return await _orderApplication.ReceiveOrderFromExternalAsync(dto, HttpContext.RequestAborted); } /// /// 删除工单 /// /// /// [HttpDelete("{id}")] [LogFilter("删除工单")] public async Task Remove(string id) { var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted); if (order == null) return; if (order.Status != EOrderStatus.WaitForAccept) throw UserFriendlyException.SameMessage("非草稿工单不可删除"); await _orderRepository.RemoveAsync(order); } /// /// 更新工单信息 /// /// /// [Permission(EPermission.OrderUpdate)] [HttpPut] [LogFilter("更新工单")] public async Task Update([FromBody] UpdateOrderDto dto) { dto.InitAddress(); var order = await _orderRepository.Queryable() .FirstAsync(d => d.Id == dto.Id); if (order == null) throw UserFriendlyException.SameMessage("无效工单编号"); if (order.Status > EOrderStatus.BackToUnAccept) throw UserFriendlyException.SameMessage("工单已发起流程,不可编辑"); if (order.Content != dto.Content) await _orderApplication.OrderParticiple(dto.Content, dto.Id, HttpContext.RequestAborted); if (dto.RepeatableEventDetails?.Any() ?? false) { var reAdds = dto.RepeatableEventDetails.Where(x => string.IsNullOrEmpty(x.OrderId) && !x.IsDeleted) .ToList(); var reDeletes = dto.RepeatableEventDetails.Where(x => !string.IsNullOrEmpty(x.OrderId) && x.IsDeleted) .ToList(); reAdds.ForEach(x => x.OrderId = dto.Id); List repeatables = _mapper.Map>(reAdds); await _repeatableEventDetailRepository.AddRangeAsync(repeatables, HttpContext.RequestAborted); if (reDeletes?.Any() ?? false) { await _repeatableEventDetailRepository.DeleteAsync(reDeletes, HttpContext.RequestAborted); } } _mapper.Map(dto, order); if (dto.Files.Any()) order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, "", HttpContext.RequestAborted); await _orderRepository.UpdateNav(order).Include(d => d.OrderExtension).ExecuteCommandAsync(); } /// /// 开始工单办理流程 /// [HttpPost("startflow")] public async Task StartFlow([FromBody] OrderStartFlowDto dto) { var id = dto.Data.Id; var isAdd = string.IsNullOrEmpty(dto.Data.Id); if (isAdd) { id = await Add(dto.Data); } else { await Update(dto.Data); } try { var expiredTimeConfig = new ExpiredTimeWithConfig(); if (dto.Workflow.NextHandlers.Any(d => d.Key == "001170" || d.Key == "001177")) { var s = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80); expiredTimeConfig = new ExpiredTimeWithConfig { Count = 45, TimeType = ETimeType.WorkDay, TimeText = "45个工作日", ExpiredTime = s.EndTime, NearlyExpiredTime = s.NearlyExpiredTime }; } else { //期满时间 expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.OrgToCenter, dto.Data.AcceptTypeCode); } // if(dto.Workflow.HandlerType is EHandlerType.AssignedOrg or EHandlerType.OrgLevel or EHandlerType.OrgType && dto.Workflow.NextStepCode) var startDto = _mapper.Map(dto.Workflow); startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderHandle; startDto.Title = dto.Data.Title; await _workflowApplication.StartWorkflowAsync(startDto, id, expiredTimeConfig, HttpContext.RequestAborted); } catch (Exception e) { if (isAdd) await Remove(id); throw new UserFriendlyException($"工单开启流程失败!, {e.Message}, {e.StackTrace}", "工单开启流程失败"); } } /// /// 查询工单办理流程开启参数 /// /// [HttpGet("startflow")] public async Task GetFlowStartOptions() { return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderHandle, HttpContext.RequestAborted); } /// /// 工单办理 /// [HttpPost("handle")] public async Task Handle([FromBody] NextWorkflowDto dto) { //todo 需求待确认 var order = await _orderRepository.Queryable() .FirstAsync(d => d.WorkflowId == dto.WorkflowId, HttpContext.RequestAborted); //if (await _orderDelayRepository.AnyAsync(x => x.OrderId == order.Id && x.DelayState == EDelayState.Examining, HttpContext.RequestAborted)) //{ // throw UserFriendlyException.SameMessage("该工单存在正在审核中的延期,不能办理"); //} if (order != null && await _orderSendBackAuditRepository.AnyAsync(x => x.OrderId == order.Id && x.State == ESendBackAuditState.Apply, HttpContext.RequestAborted)) { throw UserFriendlyException.SameMessage("该工单存在正在审核中的退回,不能办理"); } await _workflowApplication.NextAsync(dto, HttpContext.RequestAborted); } /// /// 查询工单办理下一步可选节点(带推荐部门) /// [HttpGet("nextsteps/{orderId}")] public async Task> GetNextStepsWithRecommend(string orderId) { var order = await _orderDomainService.GetOrderAsync(orderId, cancellationToken: HttpContext.RequestAborted); if (string.IsNullOrEmpty(order.WorkflowId)) throw UserFriendlyException.SameMessage("该工单未开启流程"); var dto = await _workflowApplication.GetNextStepsAsync(order.WorkflowId, HttpContext.RequestAborted); var rsp = _mapper.Map>(dto); foreach (var step in rsp.Steps) { if (dto.CurrentStepBusinessType is not EBusinessType.Send || step.BusinessType is not EBusinessType.Department) continue; var org = await _organizeRepository.GetAsync(d => d.AreaCode == order.AreaCode, HttpContext.RequestAborted); if (org is null) continue; step.RecommendOrgId = org.Id; step.RecommendOrgName = org.Name; } return rsp; } /// /// 结束会签 /// [HttpPost("endcs")] public async Task EndCountersign([FromBody] EndCountersignDto dto) { var workflow = await _workflowDomainService.TerminalCountersignAsync(dto.CountersignId, HttpContext.RequestAborted); var order = await _orderRepository.GetAsync(d => d.WorkflowId == workflow.Id, HttpContext.RequestAborted); if (order is null) throw new UserFriendlyException($"工单未开启流程, workflowId: {workflow.Id}"); _mapper.Map(workflow, order); await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); } /// /// 查询工单办理的期满时间配置 /// [HttpGet("time-config")] public async Task GetOrderHandleTimeConfigByAcceptType(EFlowDirection flowDirection, string? acceptTypeCode) { return flowDirection switch { EFlowDirection.CenterToOrg => _timeLimitDomainService.GetOrderTimeLimitConfig(acceptTypeCode), EFlowDirection.OrgToCenter => _timeLimitDomainService.GetOrderTimeLimitConfig(), _ => throw new ArgumentOutOfRangeException(nameof(flowDirection), flowDirection, null) }; } /// /// 列表页面基础数据 /// /// [HttpGet("base-data")] public async Task BaseData() { var wfModule = await _workflowApplication.GetWorkflowModuleAsync(WorkflowModuleConsts.OrderHandle, HttpContext.RequestAborted); var definition = wfModule.Definition; var rsp = new { AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType), ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel), OrgsOptions = await _organizeRepository.GetOrgJson(), EmergencyLevelOptions = EnumExts.GetDescriptions(), PushTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PushType), OrderStatusOptions = EnumExts.GetDescriptions(), CurrentStepOptions = definition?.Steps.Select(x => new Kv(x.Code, x.Name)), IdentityTypeOptions = EnumExts.GetDescriptions() }; return rsp; } /// /// 新增页面基础数据 /// /// [HttpGet("base-data-add")] public async Task BaseDataAdd() { var rsp = new { ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel), AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType), EmergencyLevelOptions = EnumExts.GetDescriptions(), PushTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PushType), GenderOptions = EnumExts.GetDescriptions(), IdentityTypeOptions = EnumExts.GetDescriptions(), LicenceTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.LicenceType), AgeRangeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AgeRange), OrderTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.OrderType), }; return rsp; } /// /// 扩展信息新增页面基础数据 /// /// [HttpGet("base-data-ext")] public async Task BaseDataExtension() { var rsp = new { LicenceTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.LicenceType), IdentityTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProviderIdentityType), IdentityOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Identity), NationalityOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Nationality), NationOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Nation), MarketTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.MarketType), IndustryClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.IndustryClassify), BrandOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Brand), ObjectClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ObjectClassify), ComplainClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ComplainClassify), ReportClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ReportClassify), SalesModeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SalesMode), ECommercePlatformOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ECommercePlatform), PatentTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PatentType), AffairTargetOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AffairTarget), ComplainTypeOptions = EnumExts.GetDescriptions().Select(d => new Kv(d.Key.ToString(), d.Value)), SalesChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SalesChannel), }; return rsp; } /// /// 扩展信息新增页面基础数据 /// /// [HttpPost("order_repeatable_event")] public async Task RepeatableEvent(QueryRepeatableEventDto dto) { var exp = Expressionable.Create() .OrIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), x => x.HotspotSpliceName.EndsWith(dto.HotspotSpliceName!)) .OrIF(!string.IsNullOrEmpty(dto.Address), x => x.Address != null && x.Address.EndsWith(dto.Address!)); var count = await _orderRepository.Queryable() .Where(exp.ToExpression()) .Where(d => d.CreationTime.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd")) .CountAsync(); var setting = _systemSettingCacheManager.GetSetting(SettingConstants.RepeatableEventNum); return count >= int.Parse(setting?.SettingValue[0] ?? "0"); } #endregion #region 工单待办 /// /// 查询待办工单 /// [HttpGet("waited")] public async Task> QueryWaited([FromQuery] QueryOrderWaitedDto dto) { var isHandled = dto.IsHandled.HasValue && dto.IsHandled.Value; var (total, items) = await _orderRepository .Queryable(viewFilter: true, handlerFilter: !isHandled) .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.No.Contains(dto.Keyword) || d.Title.Contains(dto.Keyword)) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue) .Where(x => x.Source < ESource.MLSQ || x.Source > ESource.WZSC) .Where(x=>x.Status!= EOrderStatus.BackToProvince) .OrderByDescending(d => d.StartTime) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 查询坐席待办 /// [HttpGet("waited/sign")] public async Task> QueryWaitedForSeat([FromQuery] QueryOrderWaitedDto dto) { EOrderStatus[] handleStatuses = EnumExts.GetFields().Select(d => (EOrderStatus)d.Key).ToArray(); handleStatuses = handleStatuses.WhereIF(dto.IsHandled.HasValue, d => dto.IsHandled!.Value ? d is not EOrderStatus.WaitForAccept and not EOrderStatus.BackToUnAccept : d is EOrderStatus.WaitForAccept or EOrderStatus.BackToUnAccept) .ToArray(); var (total, items) = await _orderRepository.Queryable(viewFilter: false) .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince) .WhereIF(dto.IsHandled.HasValue, d => handleStatuses.Contains(d.Status)) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.No.Contains(dto.Keyword!) || d.Title.Contains(dto.Keyword!)) .Where(d => string.IsNullOrEmpty(d.SignerId) || d.SignerId == _sessionContext.RequiredUserId) .Where(x => x.Source < ESource.MLSQ || x.Source > ESource.WZSC) .OrderBy(d => d.Status) .OrderByIF(dto.IsHandled == true, d => d.StartTime, OrderByType.Asc) .OrderByIF(dto.IsHandled == false, d => d.CreationTime, OrderByType.Desc) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 业务工单退回 /// /// 工单退回退回(返回前一节点) /// [HttpPost("order_previous")] public async Task Previous([FromBody] PreviousWorkflowDto dto) { var oneSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.OneOrgSendBack)?.SettingValue[0]); var twoSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.TwoOrgSendBack)?.SettingValue[0]); if (oneSendBack || twoSendBack) { var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, cancellationToken: HttpContext.RequestAborted); var currentStep = _workflowDomainService.GetUnHandleStep(workflow.Steps, _sessionContext.RequiredOrgId, _sessionContext.RequiredUserId); if (workflow.FlowType is EFlowType.Review && currentStep.StepType is EStepType.Start && currentStep.IsOrigin) throw UserFriendlyException.SameMessage("当前流程已退回到开始节点"); var prevStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.PrevStepId); if (prevStep == null) throw UserFriendlyException.SameMessage("未查询到前一节点"); var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply ).AnyAsync(); if (sendBack) throw UserFriendlyException.SameMessage("当前工单已经生成退回记录"); var order = await _orderRepository .Queryable() .Includes(d => d.Workflow) .FirstAsync(d => d.Id == workflow.ExternalId); if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行退回!"); var applyOrg = _organizeRepository.Get(currentStep.AcceptorOrgId); var sendBackOrg = _organizeRepository.Get(prevStep.AcceptorOrgId); if ((twoSendBack && 2.Equals(applyOrg.Level) && 1.Equals(sendBackOrg.Level) && !sendBackOrg.IsCenter) || (oneSendBack && 1.Equals(applyOrg.Level) && sendBackOrg.IsCenter && !applyOrg.IsCenter)) { var audit = new OrderSendBackAudit { OrderId = workflow.ExternalId, State = ESendBackAuditState.Apply, Content = dto.Opinion, SendBackData = dto, ApplyOrgId = applyOrg.Id, ApplyOrgName = applyOrg.Name, SendBackOrgId = sendBackOrg.Id, SendBackOrgName = sendBackOrg.Name, WorkflowOrgId = _sessionContext.RequiredOrgId, WorkflowUserId = _sessionContext.RequiredUserId }; await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted); } //中心内部流转 不走审批流程 3级部门不走审批 if ((sendBackOrg.IsCenter && applyOrg.IsCenter) || 3.Equals(applyOrg.Level)) { await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted); //发送短信TODO } } else { await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted); //发送短信TODO } } /// /// 工单业务退回审批 /// /// /// [Permission(EPermission.OrderPreviousAudit)] [HttpPost("order_previous_audit")] public async Task Audit([FromBody] AuditSendBackDto dto) { if (dto.State == ESendBackAuditState.Refuse && string.IsNullOrEmpty(dto.AuditContent)) throw UserFriendlyException.SameMessage("退回拒绝,请填写审批拒绝原因"); //验证是否存在退回 var sendBack = await _orderSendBackAuditRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (sendBack is null) throw UserFriendlyException.SameMessage("无效退回"); if (sendBack.State != ESendBackAuditState.Apply) throw UserFriendlyException.SameMessage("退回已审批,请勿重复审批"); _mapper.Map(dto, sendBack); sendBack.AuditId = _sessionContext.UserId; sendBack.AuditUser = _sessionContext.UserName; sendBack.AuditTime = DateTime.Now; //执行退回 if (sendBack.State == ESendBackAuditState.End) { await _workflowApplication.OrderPreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId, HttpContext.RequestAborted); //发送短信TODO } await _orderSendBackAuditRepository.UpdateAsync(sendBack, HttpContext.RequestAborted); } /// /// 工单业务退回审批列表 /// /// /// [Permission(EPermission.OrderPreviousList)] [HttpGet("order_previous_list")] public async Task> AuditList([FromQuery] SendBackListDto dto) { var (total, items) = await _orderSendBackAuditRepository.Queryable() .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(dto.State.HasValue, d => d.State == dto.State) .Where(x=>x.SendBackOrgId == _sessionContext.OrgId) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 退回详情 /// /// /// [HttpGet("order_previous/{id}")] public async Task OrderSendBackEntity(string id) { return await _orderSendBackAuditRepository.Queryable() .Includes(x => x.Order) .FirstAsync(x => x.Id == id); } #endregion #region 省工单退回 /// /// 工单退回列表 /// /// /// [Permission(EPermission.SendBackOrder)] [HttpGet("send_back")] public async Task> UrgeList([FromQuery] OrderSendBackListDto dto) { var (total, items) = await _orderSendBackRepository.Queryable() .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(dto.State is > 0, d => d.State > 0) .WhereIF(dto.State is 0, d => d.State == 0) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 批量省工单退回 /// /// /// [HttpPost("send_back/batch")] public async Task BatchApplyUrge([FromBody]BatchOrderSendBackAddDto dto) { int count = dto.OrderIds.Count; int successCount = 0; int errorCount = 0; var SendDatas = new List(); foreach (var item in dto.OrderIds) { //验证工单是否可以申请 var order = await _orderRepository.GetAsync(item, HttpContext.RequestAborted); if (order is null) { errorCount++; continue; } if (order.Status >= EOrderStatus.BackToUnAccept) { errorCount++; continue; } if (order.Source <= ESource.HotlineImport) { errorCount++; continue; } var model = new OrderSendBack() { Content = dto.Content, OrderId = item, Destination = ESendBackDestination.Province }; await _orderSendBackRepository.AddAsync(model, HttpContext.RequestAborted); if (!string.IsNullOrEmpty(model.Id)) { order.Status = EOrderStatus.BackToProvince; await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); successCount++; var sendBackDto = _mapper.Map(model); var OrderDto = _mapper.Map(order); SendDatas.Add(new PublishOrderSendBackModelDto() { Order = OrderDto, SendBack = sendBackDto, ClientGuid = "" }); } } //推省上 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowPrevious, new PublishOrderSendBackDto() { SendDatas = SendDatas }); return new { Count = count, ErrorCount = errorCount, SuccessCount = successCount }; } /// /// 退回申请 /// /// /// [Permission(EPermission.ApplySendBack)] [HttpPost("send_back/apply")] [LogFilter("新增工单退回申请")] public async Task ApplyUrge([FromBody] OrderSendBackAddDto dto) { //验证工单是否可以申请 var order = await _orderRepository.GetAsync(dto.OrderId, HttpContext.RequestAborted); if (order is null) throw UserFriendlyException.SameMessage("无效工单"); if (order.Status >= EOrderStatus.BackToUnAccept) throw UserFriendlyException.SameMessage("工单状态无效,请确认当前工单状态"); if (order.Source <= ESource.HotlineImport) throw UserFriendlyException.SameMessage("工单来源无效,请确认当前工单来源"); var model = _mapper.Map(dto); model.InitId(); if (dto.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", HttpContext.RequestAborted); await _orderSendBackRepository.AddAsync(model, HttpContext.RequestAborted); if (!string.IsNullOrEmpty(model.Id)) { order.Status = EOrderStatus.BackToProvince; await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); var sendBackDto = _mapper.Map(model); var OrderDto = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowPrevious, new PublishOrderSendBackDto() { SendDatas = new List() { new PublishOrderSendBackModelDto() { Order = OrderDto, SendBack = sendBackDto, ClientGuid = "" } } }); } } /// /// 退回审核 /// /// /// [Permission(EPermission.AuditSendBack)] [HttpPost("send_back/audit")] [LogFilter("审核工单退回申请")] public async Task ReplyUrge([FromBody] AuditOrderSendBackDto dto) { //验证是否存在退回 var sendBack = await _orderSendBackRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (sendBack is null) throw UserFriendlyException.SameMessage("无效退回"); if (sendBack.State > 0) throw UserFriendlyException.SameMessage("退回已审核,请勿重复审核"); _mapper.Map(dto, sendBack); sendBack.AuditName = _sessionContext.UserName; sendBack.AuditTime = DateTime.Now; await _orderSendBackRepository.UpdateAsync(sendBack, HttpContext.RequestAborted); //推省上 if (sendBack.State == 1) { var order = await _orderRepository.GetAsync(sendBack.OrderId); var sendBackDto = _mapper.Map(sendBack); var OrderDto = _mapper.Map(order); //await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowPrevious, // new PublishOrderSendBackDto() { Order = OrderDto, SendBack = sendBackDto, ClientGuid = "" }); //try //{ // await _provinceService.GetCaseBackApply( // new PublishOrderSendBackDto { Order = OrderDto, SendBack = sendBackDto, ClientGuid = "" }, // HttpContext.RequestAborted); //} //catch (Exception e) //{ // _logger.LogError("_provinceService.GetCaseBackApply throw exception: {ex}", e.Message); //} } } /// /// 退回详情 /// /// /// [HttpGet("send_back/{id}")] public async Task SendBackEntity(string id) { return await _orderSendBackRepository.Queryable() .Includes(x => x.Order) .FirstAsync(x => x.Id == id); } #endregion #region 工单特提 /// /// 工单特提信息 /// /// /// [Permission(EPermission.ApplySpecial)] [HttpPost("special")] [LogFilter("新增工单特提")] public async Task Add([FromBody] OrderSpecialAddDto dto) { var specialAny = await _orderSpecialRepository.Queryable().Where(x => x.OrderId == dto.OrderId && x.State == 0) .AnyAsync(); if (specialAny) throw UserFriendlyException.SameMessage("工单已存在待审批特提信息!"); var screen = await _orderScreenRepository.Queryable().Where(x => x.OrderId == dto.OrderId && (int)x.Status < 2).AnyAsync(); if (screen) throw UserFriendlyException.SameMessage("工单存在甄别中的信息!"); var order = await _orderRepository .Queryable() .Includes(d => d.Workflow) .FirstAsync(d => d.Id == dto.OrderId); if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行特提!"); var model = _mapper.Map(dto); var orgs = order.HandlerOrgs; model.OrgId = orgs != null && orgs.Count > 0 ? orgs[0].Key : ""; model.OrgName = orgs != null && orgs.Count > 0 ? orgs[0].Value : ""; var step = await _workflowDomainService.FindLastStepAsync(model.WorkflowId, HttpContext.RequestAborted); model.StepName = step.Name; model.StepCode = step.Code; //if (!dto.Audit) model.State = 1; //取消根据进入界面判断是否审批 最新按照系统配置设定 var audit = true; var setting = _systemSettingCacheManager.GetSetting(SettingConstants.SeatsMonitor); var settingStr = setting?.SettingValue; var roles = _sessionContext.Roles; foreach (var item in settingStr) { if (roles != null && roles.Contains(item)) audit = false; } if (!audit) model.State = 1; model.InitId(); if (dto.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", HttpContext.RequestAborted); await _orderSpecialRepository.AddAsync(model, HttpContext.RequestAborted); if (model.State == 1) { var recall = new RecallDto { WorkflowId = dto.WorkflowId!, NextStepCode = dto.NextStepCode, NextStepName = dto.NextStepName, NextHandlers = dto.NextHandlers, Opinion = dto.Cause }; if (dto.AlterTime) recall.External = new External { TimeLimit = dto.TimeLimit, TimeLimitUnit = dto.TimeLimitUnit }; //if (dto.Files.Any()) recall.Files = dto.Files; await _workflowApplication.RecallAsync(recall, HttpContext.RequestAborted); var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == dto.OrderId); if (publish != null) { var publishHistory = _mapper.Map(publish); publishHistory.OrderPublishId = publish.Id; publishHistory.ArrangeTitleAfter = publish.ArrangeTitle; publishHistory.ArrangeTitleBefor = publish.ArrangeTitle; publishHistory.ArrangeContentAfter = publish.ArrangeContent; publishHistory.ArrangeContentBefor = publish.ArrangeContent; publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion; publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion; await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted); await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted); } var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == dto.OrderId && x.VisitState != EVisitState.None); if (visit != null) { visit.VisitState = EVisitState.None; await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); } if (order != null && ("001170".Equals(model.OrgId) || "001177".Equals(model.OrgId) || "001180".Equals(model.OrgId))) { await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled, new PublishSpecialDto { Order = _mapper.Map(order), Special = _mapper.Map(model) }, cancellationToken: HttpContext.RequestAborted); //try //{ // await _provinceService.RevokeOrder( // new PublishSpecialDto // { Order = _mapper.Map(order), Special = _mapper.Map(model) }, // HttpContext.RequestAborted); //} //catch (Exception e) //{ // _logger.LogError("_provinceService.RevokeOrder throw exception: {ex}", e.Message); //} } } } /// /// 审批工单特提信息 /// /// /// [Permission(EPermission.AuditSpecial)] [HttpPut("special")] [LogFilter("审批工单特提")] public async Task Update([FromBody] AuditOrderSpecialDto dto) { var special = await _orderSpecialRepository.GetAsync(dto.Id); if (special is null) throw UserFriendlyException.SameMessage("无效特提审批信息!"); if (special.State != 0) throw UserFriendlyException.SameMessage("无效特提审批信息,特提审批信息错误,该信息已审核!"); if (string.IsNullOrEmpty(dto.NextStepName)) dto.NextStepName = special.NextStepName; if (string.IsNullOrEmpty(dto.NextStepCode)) dto.NextStepCode = special.NextStepCode; if (dto.NextHandlers.Count <= 0) dto.NextHandlers = special.NextHandlers; _mapper.Map(dto, special); if (dto.Files.Any()) special.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, special.Id, "", HttpContext.RequestAborted); await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted); if (special.State == 1) { var recall = new RecallDto { WorkflowId = dto.WorkflowId!, NextStepCode = dto.NextStepCode, NextStepName = dto.NextStepName, NextHandlers = dto.NextHandlers, Opinion = dto.Opinion }; if (dto.AlterTime) recall.External = new External { TimeLimit = dto.TimeLimit, TimeLimitUnit = dto.TimeLimitUnit }; //if (dto.Files.Any()) recall.Files = dto.Files; await _workflowApplication.RecallAsync(recall, HttpContext.RequestAborted); var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == special.OrderId); if (publish != null) { var publishHistory = _mapper.Map(publish); publishHistory.OrderPublishId = publish.Id; publishHistory.ArrangeTitleAfter = publish.ArrangeTitle; publishHistory.ArrangeTitleBefor = publish.ArrangeTitle; publishHistory.ArrangeContentAfter = publish.ArrangeContent; publishHistory.ArrangeContentBefor = publish.ArrangeContent; publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion; publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion; await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted); await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted); } var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == special.OrderId && x.VisitState != EVisitState.None); if (visit != null) { visit.VisitState = EVisitState.None; await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); } var order = await _orderRepository.GetAsync(x => x.Id == special.OrderId); if (order != null && ("001170".Equals(special.OrgId) || "001177".Equals(special.OrgId) || "001180".Equals(special.OrgId))) { await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled, new PublishSpecialDto { Order = _mapper.Map(order), Special = _mapper.Map(special) }, cancellationToken: HttpContext.RequestAborted); //try //{ // await _provinceService.RevokeOrder( // new PublishSpecialDto // { Order = _mapper.Map(order), Special = _mapper.Map(special) }, // HttpContext.RequestAborted); //} //catch (Exception e) //{ // _logger.LogError("_provinceService.RevokeOrder throw exception: {ex}", e.Message); //} } } } /// /// 获取工单特提信息列表 /// /// /// [Permission(EPermission.AuditSpecialOrderList)] [HttpGet("special/list")] public async Task> List([FromQuery] OrderSpecialListDto dto) { var (total, items) = await _orderSpecialRepository.Queryable() .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.No.Contains(dto.Keyword!) || x.Order.Title.Contains(dto.Keyword!)) .WhereIF(dto.State.HasValue, x => x.State == dto.State) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 特提列表 /// /// /// // [Permission(EPermission.AuditSpecialOrderList)] [HttpGet("special/getspeciallist")] public async Task> GetSpecialList([FromQuery] SpecialPagedListDto pagedDto) { RefAsync total = 0; var dataList = await _orderRepository.Queryable(viewFilter: true) .LeftJoin((x, p) => x.Id == p.OrderId) .WhereIF(pagedDto.StartTime.HasValue, (x, p) => p.CreationTime >= pagedDto.StartTime) .WhereIF(pagedDto.EndTime.HasValue, (x, p) => p.CreationTime <= pagedDto.EndTime) .WhereIF(!string.IsNullOrEmpty(pagedDto.No), (x, p) => x.No.Contains(pagedDto.No)) .WhereIF(pagedDto.State.HasValue, (x, p) => p.State == pagedDto.State) .Select((x, p) => new { index = SqlFunc.RowNumber($"{p.CreationTime} desc ", $"{p.OrderId}"), x.Title, x.Status, x.No, x.AcceptType, x.AcceptTypeCode, x.HotspotName, x.HotspotId, x.HotspotSpliceName, x.ActualHandleTime, x.ExpiredTime, x.NearlyExpiredTime, p.NextStepName, p.NextStepCode, p.StepName, p.StepCode, p.CreatorName, p.CreatorOrgName, p.CreationTime, p.State, p.Opinion, SpecialId = p.Id, p.OrderId, p.WorkflowId }) //将结果合并成一个表 .MergeTable() //取第一条数据 .Where(d => d.index == 1) .OrderByDescending(d => d.CreationTime) //转分页数据 .ToPageListAsync(pagedDto.PageIndex, pagedDto.PageSize, total); //返回数据 return new PagedDto(total.Value, _mapper.Map>(dataList)); } /// /// 工单列表 /// /// /// [HttpGet("special/apply_list")] public async Task> SpecialList([FromQuery] QueryOrderDto dto) { var query = _orderRepository.Queryable() .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!)) //.WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!)) .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType)) .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannel)) .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone!)) .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.Workflow.ActualHandleOrgCode)) .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo!) || d.AcceptorStaffNo.Contains(dto.NameOrNo!)) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel)) .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.FromPhone.Contains(dto.PhoneNo!) || d.Contact.Contains(dto.PhoneNo!)) .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status)) .WhereIF(dto.Statuses.Any(d => d == EOrderStatus.BackToUnAccept), d => d.Status <= EOrderStatus.BackToUnAccept); if (!_sessionContext.OrgIsCenter && _sessionContext.OrgId.Length >= 6) { var oneCode = _sessionContext.OrgId.Substring(0, 6); query = query.Where(x => x.AcceptorOrgCode.StartsWith(oneCode) && !x.AcceptorOrgCode.StartsWith(_sessionContext.OrgId)); } var (total, items) = await query .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取工单特提信息 /// /// /// [HttpGet("special/{id}")] public async Task SpecialEntity(string id) { var item = await _orderSpecialRepository.Queryable() .Includes(x => x.Order) .FirstAsync(x => x.Id == id); var itemDto = new OrderSpecialDto(); if (item != null) { itemDto = _mapper.Map(item); if (itemDto.FileJson != null && itemDto.FileJson.Any()) { var ids = itemDto.FileJson.Select(x => x.Id).ToList(); itemDto.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted); } } return itemDto; } /// /// 列表页面基础数据 /// /// [HttpGet("special/base/{id}")] public async Task SpecialBaseData(string id) { var rsp = new { SpecialTimeType = EnumExts.GetDescriptions(), SpecialReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SpecialReason), Step = await _workflowApplication.GetRecallStepsAsync(id, HttpContext.RequestAborted) }; return rsp; } #endregion #region 市民信息 /// /// 新增市民信息 /// /// /// [HttpPost("citizen")] [LogFilter("新增市民信息")] public async Task Add([FromBody] CitizenAddDto dto) { var citizen = await _citizenRepository.CountAsync(x => x.PhoneNumber == dto.PhoneNumber, HttpContext.RequestAborted); if (citizen > 0) throw UserFriendlyException.SameMessage("市民联系电话信息重复"); await _citizenRepository.AddAsync(dto, HttpContext.RequestAborted); } /// /// 删除市民信息 /// /// /// [Permission(EPermission.DeleteCitizen)] [HttpDelete("citizen")] [LogFilter("删除市民信息")] public async Task Delete([FromBody] CitizenDeleteDto dto) { await _citizenRepository.RemoveAsync(x => x.Id == dto.Id); } /// /// 更新市民信息 /// /// /// [Permission(EPermission.UpdateCitizen)] [HttpPut("citizen")] [LogFilter("更新市民信息")] public async Task Update([FromBody] CitizenUpdateDto dto) { var citizen = await _citizenRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (citizen is null) throw UserFriendlyException.SameMessage("无效市民信息"); _mapper.Map(dto, citizen); citizen.LastModificationName = _sessionContext.UserName; await _citizenRepository.UpdateAsync(citizen, HttpContext.RequestAborted); } /// /// 获取市民信息列表 /// /// /// [Permission(EPermission.CitizenList)] [HttpGet("citizen/list")] public async Task> List([FromQuery] CitizenListDto dto) { var (total, items) = await _citizenRepository.Queryable() .WhereIF(!string.IsNullOrEmpty(dto.PhoneNumber), x => x.PhoneNumber.Contains(dto.PhoneNumber!)) .WhereIF(!string.IsNullOrEmpty(dto.Label), x => x.Label != null && x.Label.Contains(dto.Label!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取市民信息 /// /// /// [HttpGet("citizen/{id}")] public async Task CitizenEntity(string id) { return await _citizenRepository.Queryable() .Includes(x => x.labelDetails) .FirstAsync(x => x.Id == id); } /// /// 获取市民信息 /// /// /// [HttpGet("citizen_phone/{phone}")] public async Task Citizen(string phone) { //市民基本信息 var citizen = await _citizenRepository.Queryable() .Includes(x => x.labelDetails) .FirstAsync(x => x.PhoneNumber == phone); //工单历史 var oders = await _orderRepository.Queryable().Where(x => x.Contact == phone) .OrderBy(x => x.CreationTime, OrderByType.Desc).ToListAsync(); var allOrderNum = oders.Count; var endOrderNum = oders.Count(x => (int)x.Status >= 300); var handOrderNum = oders.Count(x => (int)x.Status < 300); var DissatisfactionNum = await _orderVisitedDetailRepository.Queryable() .Includes(x => x.OrderVisit) .Includes(x => x.OrderVisit, v => v.Order) .Where(x => x.OrderVisit.Order.Contact == phone && (SqlFunc.JsonField(x.OrgProcessingResults, "Value") == "不满意" || SqlFunc.JsonField(x.OrgProcessingResults, "Value") == "非常不满意")) .Distinct().Select(x => new { x.OrderVisit.OrderId }).CountAsync(); //来电历史 var calls = await _trCallRecordRepository.Queryable().Where(x => x.CallDirection == 0 && x.CPN == phone).OrderBy(x => x.CreatedTime).ToListAsync(); var oneCallTime = calls != null && calls.Count() > 0 ? calls[0].CreatedTime : DateTime.Now; var lastNum = calls != null && calls.Count() > 0 ? calls.Count() - 1 : -1; var lastCallTime = lastNum >= 0 ? calls[lastNum].CreatedTime : DateTime.Now; //关注诉求 var hotspotNames = string.Join(",", oders.Select(x => x.HotspotName).Distinct().Take(5).ToList()); var rsp = new { Citizen = citizen, OneCallTime = oneCallTime, LastCallTime = lastCallTime, Order = new { allOrderNum = allOrderNum, endOrderNum = endOrderNum, handOrderNum = handOrderNum, DissatisfactionNum = DissatisfactionNum }, CallHistory = new { AllCallNum = 0, ConnectNum = 0, CallBackNum = 0 }, HotspotNames = hotspotNames, }; return rsp; } /// /// 新增市民标签信息 /// /// /// [HttpPost("citizen_label")] public async Task Add([FromBody] LabelDetailAddDto dto) { var label = await _labelDetailRepository.CountAsync(x => x.CitizenId == dto.CitizenId && x.Label == dto.Label, HttpContext.RequestAborted); if (label > 0) throw UserFriendlyException.SameMessage("市民联系标签信息重复"); await _citizenRepository.LabelAddAsync(dto, HttpContext.RequestAborted); } /// /// 删除市民标签信息 /// /// /// [HttpDelete("citizen_label")] public async Task Delete([FromBody] LabelDetailDeleteDto dto) { var label = await _labelDetailRepository.GetAsync(x => x.Id == dto.Id, HttpContext.RequestAborted); if (label == null || (label.CreatorName != _sessionContext.UserName)) throw UserFriendlyException.SameMessage("市民联系标签信息错误"); await _citizenRepository.LabelDeleteAsync(label, HttpContext.RequestAborted); } /// /// 获取市民标签信息列表 /// /// /// [HttpGet("citizen_label/list")] public async Task> List([FromQuery] CitizenQueryDto dto) { var (total, items) = await _labelDetailRepository.Queryable() .Includes(x => x.Citizen) .WhereIF(!string.IsNullOrEmpty(dto.Label), x => x.Label.Contains(dto.Label!)) .WhereIF(!string.IsNullOrEmpty(dto.CreatorName), x => x.CreatorName != null && x.CreatorName.Contains(dto.CreatorName!)) .Where(x => x.CitizenId == dto.CitizenId) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 重复性事件 /// /// 新增重复性事件 /// /// /// [HttpPost("repeatable_event")] [LogFilter("新增重复性事件")] public async Task Add([FromBody] RepeatableEventAddDto dto) { var repeatable = _mapper.Map(dto); var repeatableId = await _repeatableEventRepository.AddAsync(repeatable, HttpContext.RequestAborted); List detail; if (!string.IsNullOrEmpty(repeatableId) && dto.Details.Any()) dto.Details.ForEach(x => x.RepeatableId = repeatableId); detail = _mapper.Map>(dto.Details); if (detail.Any()) await _repeatableEventDetailRepository.AddRangeAsync(detail, HttpContext.RequestAborted); } /// /// 删除重复性事件 /// /// /// [HttpDelete("repeatable_event")] [LogFilter("删除重复性事件")] public async Task Delete([FromBody] RepeatableEventDeleteDto dto) { await _repeatableEventRepository.RemoveAsync(x => x.Id == dto.Id); await _repeatableEventDetailRepository.RemoveAsync(x => x.RepeatableId == dto.Id); } /// /// 删除重复性事件明细 /// /// /// [HttpDelete("repeatable_event_detail/{id}")] [LogFilter("删除重复性事件")] public async Task Delete([FromBody] string id) { await _repeatableEventDetailRepository.RemoveAsync(x => x.Id == id); } /// /// 更新重复性事件 /// /// /// [Permission(EPermission.UpdateRepeatableEvent)] [HttpPut("repeatable_event")] [LogFilter("更新重复性事件")] public async Task Update([FromBody] RepeatableEventUpdateDto dto) { var repeatable = await _repeatableEventRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (repeatable is null) throw UserFriendlyException.SameMessage("无效重复性事件"); _mapper.Map(dto, repeatable); repeatable.LastModificationName = _sessionContext.UserName; await _repeatableEventRepository.UpdateAsync(repeatable, HttpContext.RequestAborted); List detail; if (dto.Details.Any()) dto.Details.ForEach(x => x.RepeatableId = dto.Id); await _repeatableEventDetailRepository.DeleteAsync(dto.Id, HttpContext.RequestAborted); detail = _mapper.Map>(dto.Details); if (detail.Any()) await _repeatableEventDetailRepository.AddRangeAsync(detail, HttpContext.RequestAborted); } /// /// 获取重复性事件列表 /// /// /// [HttpGet("repeatable_event/list")] public async Task> List([FromQuery] RepeatableEventListDto dto) { var (total, items) = await _repeatableEventRepository.Queryable() .Includes(x => x.Details) .Includes(x => x.Details, y => y.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || (d.KeyWords != null && d.KeyWords.Contains(dto.Keyword!))) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(!string.IsNullOrEmpty(dto.Code), x => x.Code != null && x.Code.Contains(dto.Code!)) .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Contains(dto.Title!)) .WhereIF(!string.IsNullOrEmpty(dto.KeyWords), x => x.KeyWords != null && x.KeyWords.Contains(dto.KeyWords!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取重复性事件 /// /// /// [HttpGet("repeatable_event")] public async Task CitizenEntity([FromQuery] RepeatableEventEntityDto dto) { return await _repeatableEventRepository.Queryable() .Includes(x => x.Details.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!)) .ToList()) .Includes(x => x.Details, y => y.Order) .FirstAsync(x => x.Id == dto.Id); } #endregion #region 工单词库 /// /// 新增工单词库 /// /// /// [Permission(EPermission.AddOrderWord)] [HttpPost("order_word")] [LogFilter("新增工单词库")] public async Task Add([FromBody] OrderWordAddDto dto) { var word = _mapper.Map(dto); await _orderWrodRepository.AddAsync(word, HttpContext.RequestAborted); } /// /// 删除工单词库 /// /// /// [Permission(EPermission.DeleteOrderWord)] [HttpDelete("order_word")] [LogFilter("删除工单词库")] public async Task Delete([FromBody] OrderWordDeleteDto dto) { await _orderRepository.RemoveOrderWrodBatchAsync(dto.Ids, HttpContext.RequestAborted); } /// /// 更新工单词库 /// /// /// [Permission(EPermission.UpdateOrderWord)] [HttpPut("order_word")] [LogFilter("更新工单词库")] public async Task Update([FromBody] OrderWordUpdateDto dto) { var word = await _orderWrodRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (word is null) throw UserFriendlyException.SameMessage("无效工单词库"); _mapper.Map(dto, word); word.LastModificationName = _sessionContext.UserName; await _orderWrodRepository.UpdateAsync(word, HttpContext.RequestAborted); } /// /// 获取工单词库列表 /// /// /// [Permission(EPermission.OrderWordList)] [HttpGet("order_word/list")] public async Task> List([FromQuery] OrderWordListDto dto) { var (total, items) = await _orderWrodRepository.Queryable() .WhereIF(!string.IsNullOrEmpty(dto.Tag), x => x.Tag == dto.Tag!) .WhereIF(!string.IsNullOrEmpty(dto.Classify), x => x.Classify.Contains(dto.Classify!)) .WhereIF(!string.IsNullOrEmpty(dto.Synonym), x => x.Synonym != null && x.Synonym.Contains(dto.Synonym!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取工单词库 /// /// /// [HttpGet("order_word/{id}")] public async Task OrderWordEntity(string id) { return await _orderWrodRepository.Queryable() .FirstAsync(x => x.Id == id); } /// /// 获取工单词库基本信息 /// /// [HttpGet("order_word/base")] public async Task Base() { var rsp = new { OrderWordClassify = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.OrderWordClassify), }; return rsp; } #endregion #region 工单观察 /// /// 新增工单观察 /// /// /// [Permission(EPermission.AddOrderObserve)] [HttpPost("order_observe")] [LogFilter("新增工单观察")] public async Task Add([FromBody] OrderObserveAddDto dto) { var ids = dto.OrderIds.Select(x => x.OrderId).ToList(); var list = await _orderObserveRepository.Queryable().In(x => x.OrderId, ids).Select(x => x.OrderId) .ToListAsync(); if (list.Any()) dto.OrderIds = ids.Except(list).Select(x => new OrdersObserveAddDto { OrderId = x }).ToList(); if (!dto.OrderIds.Any()) throw UserFriendlyException.SameMessage("无效工单观察,当前所选工单都已观察"); var observe = _mapper.Map>(dto.OrderIds); await _orderObserveRepository.AddRangeAsync(observe, HttpContext.RequestAborted); } /// /// 删除工单观察 /// /// /// [HttpDelete("order_observe")] [LogFilter("删除工单观察")] public async Task Delete([FromBody] OrderObserveDeleteDto dto) { await _orderRepository.RemoveOrderObserveBatchAsync(dto.Ids, HttpContext.RequestAborted); } /// /// 更新工单观察 /// /// /// [HttpPut("order_observe")] [LogFilter("更新工单观察")] public async Task Update([FromBody] OrderObserveUpdateDto dto) { var word = await _orderObserveRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (word is null) throw UserFriendlyException.SameMessage("无效工单观察"); _mapper.Map(dto, word); await _orderObserveRepository.UpdateAsync(word, HttpContext.RequestAborted); } /// /// 获取工单观察列表 /// /// /// [HttpGet("order_observe/list")] public async Task> List([FromQuery] OrderObserveListDto dto) { var (total, items) = await _orderObserveRepository.Queryable() .Includes(x => x.Order) .WhereIF(dto.IsProvince.HasValue, x => x.Order.IsProvince == dto.IsProvince) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.No.Contains(dto.Keyword!) || x.Order.Title.Contains(dto.Keyword!)) //.WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title!)) //.WhereIF(!string.IsNullOrEmpty(dto.No), x => x.Order.No.Contains(dto.No!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取工单观察 /// /// /// [HttpGet("order_observe/{id}")] public async Task OrderObserveEntity(string id) { return await _orderObserveRepository.Queryable() .FirstAsync(x => x.Id == id); } #endregion #region 工单终结 /// /// 新增工单终结 /// /// /// [Permission(EPermission.AddOrderFinality)] [HttpPost("order_finality")] [LogFilter("新增工单终结")] public async Task Add([FromBody] OrderFinalityAddDto dto) { var ids = dto.OrderIds.Select(x => x.OrderId).ToList(); var list = await _orderFinalityRepository.Queryable().In(x => x.OrderId, ids).Select(x => x.OrderId) .ToListAsync(); if (list.Any()) dto.OrderIds = ids.Except(list).Select(x => new OrdersFinalityAddDto { OrderId = x }).ToList(); if (!dto.OrderIds.Any()) throw UserFriendlyException.SameMessage("无效工单终结,当前所选工单都已终结"); var observe = _mapper.Map>(dto.OrderIds); await _orderFinalityRepository.AddRangeAsync(observe, HttpContext.RequestAborted); } /// /// 删除工单终结 /// /// /// [HttpDelete("order_finality")] [LogFilter("删除工单终结")] public async Task Delete([FromBody] OrderFinalityDeleteDto dto) { await _orderRepository.RemoveOrderFinalityBatchAsync(dto.Ids, HttpContext.RequestAborted); } /// /// 更新工单终结 /// /// /// [HttpPut("order_finality")] [LogFilter("更新工单终结")] public async Task Update([FromBody] OrderFinalityUpdateDto dto) { var word = await _orderFinalityRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (word is null) throw UserFriendlyException.SameMessage("无效工单观察"); _mapper.Map(dto, word); await _orderFinalityRepository.UpdateAsync(word, HttpContext.RequestAborted); } /// /// 获取工单终结列表 /// /// /// [HttpGet("order_finality/list")] public async Task> List([FromQuery] OrderFinalityListDto dto) { var (total, items) = await _orderFinalityRepository.Queryable() .Includes(x => x.Order) .WhereIF(dto.IsProvince.HasValue, x => x.Order.IsProvince == dto.IsProvince) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.No.Contains(dto.Keyword!) || x.Order.Title.Contains(dto.Keyword!)) //.WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title!)) //.WhereIF(!string.IsNullOrEmpty(dto.No), x => x.Order.No.Contains(dto.No!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取工单终结 /// /// /// [HttpGet("order_finality/{id}")] public async Task OrderFinalityEntity(string id) { return await _orderFinalityRepository.Queryable() .FirstAsync(x => x.Id == id); } #endregion #region 超期查询 /// /// 工单即将超期列表 /// /// /// [HttpGet("order/about_expire/list")] public async Task> AboutList([FromQuery] AboutToExpireListDto dto) { return await _orderApplication.GetAboutToExpireAsync(dto, HttpContext.RequestAborted); } ///// ///// 工单即将超期节点列表 ///// ///// ///// //[HttpGet("order/about_expire_node/list")] //public async Task> AboutNodeList([FromQuery] AboutToExpireListDto dto) //{ // return await _orderApplication.GetAboutToExpireNodeAsync(dto, HttpContext.RequestAborted); //} /// /// 工单超期列表 /// /// /// [HttpGet("order/expire/list")] public async Task> List([FromQuery] AboutToExpireListDto dto) { return await _orderApplication.GetToExpireAsync(dto, HttpContext.RequestAborted); } ///// ///// 工单超期节点列表 ///// ///// ///// //[HttpGet("order/expire_node/list")] //public async Task> NodeList([FromQuery] AboutToExpireListDto dto) //{ // return await _orderApplication.GetToExpireNodeAsync(dto, HttpContext.RequestAborted); //} #endregion #region 工单签收 /// /// 工单签收 /// [HttpPost("sign/{orderId}")] [LogFilter("工单签收")] public async Task Sign(string orderId) { var order = await _orderRepository.GetAsync(orderId, HttpContext.RequestAborted); if (order == null) throw new UserFriendlyException($"无效工单编号, orderId: {orderId}", "无效工单编号"); if (order.IsSigned()) throw new UserFriendlyException("该工单已被签收"); order.Sign(_sessionContext.RequiredUserId, _sessionContext.UserName); await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); } #endregion #region 获取企业信息 /// /// 获取企业信息 /// /// /// [HttpGet("enterprise/list")] [LogFilter("查询企业列表")] public async Task GetEnterpriseList([FromQuery] PagedKeywordRequest dto) { return await _enterpriseService.GetEnterpriseList(dto.Keyword!, dto.PageIndex, dto.PageSize, HttpContext.RequestAborted, _cacheResponse); } #endregion #region 导入工单 /// /// 下载工单导入模板 /// /// [HttpGet("download-order-template")] public async Task DownLoadOrderTemplate() { List list = new List(); ExcelContent excelContent = new ExcelContent() { ExternalId = "自编号", AcceptTypeCode = "字典值", AcceptType = "字典名称" }; list.Add(excelContent); return _exportApplication.ExportData(list, "demo.xlsx"); } /// ExternalId /// 导入工单 /// /// /// [HttpPost("import-order")] public async Task ImportOrder(IFormFile file) { using (var stream = new MemoryStream()) { file.CopyTo(stream); var list = MiniExcel.Query(stream).ToList(); int count = 0; int errorCount = 0; int addCount = 0; int modifyCount = 0; if (list != null && list.Count > 0) { count = list.Count; foreach (var item in list) { try { if (item.Source < ESource.MLSQ || item.Source > ESource.WZSC) { errorCount++; continue; } var order = await _orderRepository.GetAsync(x => x.ExternalId == item.ExternalId && x.Source == item.Source, HttpContext.RequestAborted); if (order is null) { order = _mapper.Map(item); //order.Source = item; var id = await _orderRepository.AddAsync(order, HttpContext.RequestAborted); if (!string.IsNullOrEmpty(id)) { addCount++; } else { errorCount++; } } else { _mapper.Map(item, order); await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); modifyCount++; } } catch (Exception ex) { errorCount++; } } } return new { Count = count, ErrorCount = errorCount, AddCount = addCount, ModifyCount = modifyCount }; } } /// /// 导入基础数据 /// /// [HttpGet("import-basedata")] public async Task ImportBaseData() { var rsp = new { Source = EnumExts.GetDescriptions(), }; return rsp; } #endregion }