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.OrderTranspond; using Hotline.Permissions; using Hotline.Push.FWMessage; using Hotline.Push.Notifies; using Hotline.Repository.SqlSugar.Extensions; using Hotline.Repository.SqlSugar.Ts; using Hotline.SeedData; 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.FlowEngine.Workflow; using Hotline.Share.Dtos.Order; using Hotline.Share.Dtos.Order.Migration; using Hotline.Share.Dtos.Order.Publish; using Hotline.Share.Dtos.Settings; using Hotline.Share.Enums.CallCenter; 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.Tools; using Hotline.Users; using Hotline.YbEnterprise.Sdk; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.OpenApi.Writers; using MiniExcelLibs; using MongoDB.Driver; using NPOI.SS.Formula.Functions; using NPOI.SS.Util; using Org.BouncyCastle.Utilities; using SqlSugar; using StackExchange.Redis; using System.Diagnostics.Tracing; using XF.Domain.Authentications; using XF.Domain.Cache; using XF.Domain.Constants; using XF.Domain.Entities; 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; private readonly IRepository _transpondCityRawDataRepository; private readonly IRepository _orderSpecialDetailRepository; private readonly IOrderSecondaryHandlingApplication _orderSecondaryHandlingApplication; private readonly IRepository _orderCopyRepository; private readonly IRepository _externalCitizensRepository; private readonly IRepository _orderModifyingRecordsRepository; 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, IRepository transpondCityRawDataRepository, IRepository orderSpecialDetailRepository, IOrderSecondaryHandlingApplication orderSecondaryHandlingApplication, IRepository orderCopyRepository, IRepository externalCitizensRepository, IRepository orderModifyingRecordsRepository ) { _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; _transpondCityRawDataRepository = transpondCityRawDataRepository; _orderSpecialDetailRepository = orderSpecialDetailRepository; _orderSecondaryHandlingApplication = orderSecondaryHandlingApplication; _orderCopyRepository = orderCopyRepository; _externalCitizensRepository = externalCitizensRepository; _orderModifyingRecordsRepository = orderModifyingRecordsRepository; } #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.StartsWith(dto.Keyword!)) .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) .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.Resolve.HasValue, d => d.OrderPublish.Resolve == dto.Resolve) .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) .WhereIF(dto.QuerySelf.HasValue && dto.QuerySelf.Value, d => d.WaitForPublisherId == _sessionContext.RequiredUserId) .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; orderVisit.EmployeeId = _sessionContext.RequiredUserId; 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; } /// /// 已发布列表 /// /// /// [HttpGet("published")] public async Task> PublishedOrderList([FromQuery] PublishedPagedRequest dto) { var (total, items) = await _orderPublishRepository.Queryable() .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.StartsWith(dto.Keyword!)) .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.Order.No == dto.No!) .WhereIF(dto.Resolve.HasValue, x => x.Resolve == dto.Resolve) .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.Queryable() .Includes(x => x.Order) .Where(x => x.Id == dto.Id) .FirstAsync(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.PublishStateBefor = publishOrder.PublishState; history.PublishStateAfter = dto.PublishState; history.No = publishOrder.No; history.OrderId = publishOrder.OrderId; history.OrderPublishId = publishOrder.Id; publishOrder.ArrangeTitle = dto.ArrangeTitle; publishOrder.ArrangeContent = dto.ArrangeContent; publishOrder.ArrangeOpinion = dto.ArrangeOpinion; publishOrder.PublishState = dto.PublishState; await _orderPublishRepository.UpdateAsync(publishOrder, HttpContext.RequestAborted); await _orderPublishHistoryRepository.AddAsync(history, HttpContext.RequestAborted); //推省上 var publishPublishOrder = _mapper.Map(publishOrder); publishPublishOrder.Order = _mapper.Map(publishOrder.Order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderPublishOrder, publishPublishOrder); } /// /// 发布修改记录 /// /// /// [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); } /// /// 查询发布平移待办理人 /// [HttpGet("published/migration")] public async Task> PublishMigration() { var setting = _systemSettingCacheManager.GetSetting(SettingConstants.RolePaiDan); var roles = setting?.SettingValue.ToList(); var users = await _userRepository.Queryable() .Includes(d => d.Organization) .Includes(d => d.Roles) .Where(d => d.Roles.Any(x => roles.Contains(x.Name))) .ToListAsync(HttpContext.RequestAborted); return users.Select(d => new OrderMigrationHandler { UserId = d.Id, Username = d.Name, OrgId = d.OrgId, OrgName = d.Organization.Name, RoleNames = string.Join(',', d.Roles.Select(x => x.DisplayName).ToList()) }).ToList(); } /// /// 发布平移 /// [HttpPost("publish/migration")] public async Task PublishMigrationBatch([FromBody] PublishMigrationDto dto) { var orders = await _orderRepository.Queryable() .Where(d => dto.OrderIds.Contains(d.Id) && d.Status == EOrderStatus.Filed) .ToListAsync(HttpContext.RequestAborted); foreach (var order in orders) { order.WaitForPublisherId = dto.UserId; } await _orderRepository.UpdateRangeAsync(orders, 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 == EVisitState.WaitForVisit || x.VisitState == EVisitState.NoSatisfiedWaitForVisit) && x.Order.IsProvince == false) .WhereIF(dto.VisitState == EVisitStateQuery.Visited, x => x.VisitState == EVisitState.Visited) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.StartsWith(dto.Keyword!)) .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) .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) .WhereIF(dto.QuerySelf.HasValue && dto.QuerySelf.Value, d => d.EmployeeId == _sessionContext.RequiredUserId) .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).Where(x => x.DicDataValue != "-1"); var dissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason); var visitManner = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitManner).Where(x => x.DicDataValue != "-1"); //var callRecord = await _trCallRecordRepository.GetAsync(x => x.CallAccept == orderVisit.CallId); //由CallAccept改为OtherAccept var callRecord = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == orderVisit.CallId && string.IsNullOrEmpty(x.OtherAccept) == false, HttpContext.RequestAborted); var recordingFileUrl = ""; var recordingBaseAddress = ""; var recordingAbsolutePath = ""; if (callRecord != null) { recordingFileUrl = callRecord.RecordingFileUrl; recordingBaseAddress = callRecord.RecordingBaseAddress; recordingAbsolutePath = callRecord.RecordingAbsolutePath; } return new { OrderVisitModel = _mapper.Map(orderVisit), VisitCount = visitCount, //AgainCount = againCount, VisitSatisfaction = visitSatisfaction, DissatisfiedReason = dissatisfiedReason, VisitManner = visitManner, ViceEvaluate = voiceEvaluate, SeatEvaluate = seatEvaluate, RecordingFileUrl = recordingFileUrl, RecordingBaseAddress = recordingBaseAddress, RecordingAbsolutePath = recordingAbsolutePath, }; } /// /// 回访明细 /// /// [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); } visit.OrgJudge = dto.OrgJudge; visit.SeatJudge = dto.SeatJudge; if (visit.OrgJudge == true || visit.SeatJudge == true) { visit.JudgeState = EJudgeState.Judging; } //_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) { if (visit.Order.SourceChannelCode != "RGDH" && detaildto.VisitTarget == EVisitTarget.Seat) { detaildto.SeatEvaluate = ESeatEvaluate.DefaultSatisfied; } _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 = string.IsNullOrEmpty(first.VisitContent) ? first.OrgProcessingResults?.Value : 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); //} } /// /// 扭转列表 /// /// /// [HttpGet("visit/judge-query")] public async Task> VisitJudgeQuery([FromQuery] VisitJudgeQueryReq dto) { var (total, items) = await _orderVisitRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.Employee) .Where(x => x.VisitState == EVisitState.Visited) .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No == dto.No) .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title)) .WhereIF(!string.IsNullOrEmpty(dto.VisitUserName), x => x.Employee.Name.Contains(dto.VisitUserName)) .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.Order.AcceptTypeCode)) //受理类型 .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.Order.HotspotId)) //热点类型 .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.Order.ActualHandleOrgCode)) //接办部门 .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.Order.AcceptorName.Contains(dto.NameOrNo!) || d.Order.AcceptorStaffNo.Contains(dto.NameOrNo!)) //受理人/坐席 .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始 .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束 .WhereIF(dto.ActualHandleTimeStart.HasValue, d => d.Order.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始 .WhereIF(dto.ActualHandleTimeEnd.HasValue, d => d.Order.ActualHandleTime <= dto.ActualHandleTimeEnd) //办结时间结束 .WhereIF(dto.VisitTimeStart.HasValue, d => d.VisitTime >= dto.VisitTimeStart) //回访开始时间 .WhereIF(dto.VisitTimeEnd.HasValue, d => d.VisitTime <= dto.VisitTimeEnd) .WhereIF(dto.IsIng == true, d => d.JudgeState == EJudgeState.Judging) .WhereIF(dto.IsIng == false, d => d.JudgeState != EJudgeState.Judging) .WhereIF(dto.JudgeState != null, d => d.JudgeState == dto.JudgeState) .WhereIF(dto.OrgJudge != null, d => d.OrgJudge == dto.OrgJudge) .WhereIF(dto.SeatJudge != null, d => d.SeatJudge == dto.SeatJudge) .OrderByDescending(x => x.VisitTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 扭转满意度 /// /// /// [HttpPost("visit/judge")] public async Task JudgeVisit([FromBody] JudgeVisitReq dto) { int error = 0; var list = await _orderVisitRepository.Queryable().Where(x => dto.Ids.Contains(x.Id) && x.VisitState == EVisitState.Visited).ToListAsync(HttpContext.RequestAborted); list.ForEach(visit => { visit.JudgeState = dto.IsAgree ? EJudgeState.Agreed : EJudgeState.UnAgreed; visit.JudgeUserId = _sessionContext.RequiredUserId; visit.JudgeUserName = _sessionContext.UserName; visit.JudgeTime = DateTime.Now; visit.JudgeContent = dto.JudgeContent; }); await _orderVisitRepository.UpdateRangeAsync(list, HttpContext.RequestAborted); return new JudgeVisitRsp() { ErrorCount = error, SuccessCount = dto.Ids.Count - error }; } /// /// 回访平移 /// /// /// [HttpPost("visit/migration")] public async Task VisitMigrationBatch([FromBody] DistributionVisitDto dto) { var visits = await _orderVisitRepository.Queryable() .Where(d => d.VisitState == EVisitState.WaitForVisit && dto.Ids.Contains(d.Id)) .ToListAsync(HttpContext.RequestAborted); foreach (var visit in visits) { visit.EmployeeId = dto.EmployeeId; } await _orderVisitRepository.UpdateRangeAsync(visits, HttpContext.RequestAborted); } #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.ApplyOrgCode == _sessionContext.RequiredOrgId && 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.DelayApplyType = EDelayApplyType.LocalApply; 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, _sessionContext, 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, _sessionContext, cancellationToken: HttpContext.RequestAborted); } catch (Exception e) { throw new UserFriendlyException($"工单延期下一步流程失败!, {e.Message}", "工单延期下一步流程失败"); } } /// /// 延期查询流程办理下一步可选节点 /// /// /// [HttpGet("delay/{workflowId}/nextsteps")] public async Task OrderDelayNextsteps(string workflowId) { var workflow = await _workflowRepository.GetAsync(workflowId, HttpContext.RequestAborted); if (workflow != null) { var orderDelay = await _orderDelayRepository.Queryable().Includes(x => x.Order).Where(x => x.Id == workflow.ExternalId).FirstAsync(HttpContext.RequestAborted); if (orderDelay != null) { var result = await _workflowApplication.GetNextStepsAsync(workflowId, HttpContext.RequestAborted); if (!orderDelay.Order.IsProvince) { if (result.Steps.Any(x => x.Value == "省审批")) { result.Steps.Remove(result.Steps.First(x => x.Value == "省审批")); } } return result; } } return null; } /// /// 取消工单延期 /// /// /// [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) { if (orderDelay.DelayApplyType == EDelayApplyType.ProvinceApply) { throw UserFriendlyException.SameMessage("当前处于【省平台】审批,无法取消"); } 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(canView: true) .Includes(d => d.Order) .Includes(d => d.Workflow) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .WhereIF(dto.IsApply == true, d => d.DelayState != EDelayState.Examining) .WhereIF(dto.IsApply == false, d => d.DelayState == EDelayState.Examining) .WhereIF(dto.DelayState != null, d => d.DelayState == dto.DelayState) .OrderByDescending(d => d.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(hasHandled: !isHandled) .Includes(d => d.Order) .Includes(d => d.Workflow) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!)) //.WhereIF(dto.IsApply == true, d => d.DelayState != EDelayState.Examining) .WhereIF(dto.IsApply == false, d => d.DelayState == EDelayState.Examining) //.WhereIF(dto.DelayState != null, x => x.DelayState == dto.DelayState) //.Where(x=>x.DelayState == EDelayState.Examining) .OrderByDescending(d => d.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(d => d.Order) .Includes(d => d.Workflow, x => x.Steps) .FirstAsync(d => d.Id == id); var rspModel = _mapper.Map(model); //rspModel.IsCanHandle = model.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId); rspModel.IsCanHandle = model.Workflow?.IsCanHandle( _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles) ?? false; rspModel.Handle = false; if (!string.IsNullOrEmpty(rspModel.WorkflowId)) { 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) { dto.CreationTimeEnd = DateTime.Now; dto.CreationTimeStart = DateTime.Now; if (dto.IsHomePage != null && dto.IsHomePage == true) { dto.CreationTimeStart = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5); } 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) .WhereIF(dto.IsHomePage.HasValue && dto.IsHomePage == true, x => x.OrderVisit.VisitTime < dto.CreationTimeEnd && x.OrderVisit.VisitTime > dto.CreationTimeStart) .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order!.No!.Contains(dto.No!)) .WhereIF(dto.IsProvince.HasValue, x => x.OrderVisit.Order!.IsProvince == dto.IsProvince) .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order!.Title!.Contains(dto.Title!)) .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), x => x.OrderVisit.Order!.SourceChannelCode! == dto.SourceChannel!) .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), x => x.OrderVisit.Order!.AcceptTypeCode! == dto.AcceptType!) .WhereIF(dto.CounterSignType.HasValue, x => x.OrderVisit.Order!.CounterSignType == dto.CounterSignType) .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), x => x.OrderVisit.Order!.OrgLevelOneName!.Contains(dto.OrgLevelOneName!)) .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.OrderVisit.Order!.ActualHandleOrgName!.Contains(dto.ActualHandleOrgName!)) .WhereIF(dto.ActualHandleTime.HasValue && dto.EndActualHandleTime.HasValue, x => x.OrderVisit.Order!.ActualHandleTime >= dto.ActualHandleTime && x.OrderVisit.Order!.ActualHandleTime <= dto.EndActualHandleTime) .WhereIF(dto.FiledTime.HasValue && dto.EndFiledTime.HasValue, x => x.OrderVisit.Order!.FiledTime == dto.FiledTime && x.OrderVisit.Order!.FiledTime <= dto.EndFiledTime) .WhereIF(dto.CreationTime.HasValue && dto.EndCreationTime.HasValue, x => x.OrderVisit.Order!.CreationTime == dto.CreationTime && x.OrderVisit.Order!.CreationTime <= dto.EndCreationTime) .WhereIF(dto.VisitTime.HasValue && dto.EndVisitTime.HasValue, x => x.OrderVisit.VisitTime == dto.VisitTime && x.OrderVisit.VisitTime <= dto.EndVisitTime) .WhereIF(!string.IsNullOrEmpty(dto.VisitOrgName), x => x.VisitOrgName!.Contains(dto.VisitOrgName!)) .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults) .WhereIF(!string.IsNullOrEmpty(dto.OrgHandledAttitude), x => SqlFunc.JsonListObjectAny(x.OrgHandledAttitude, "Key", dto.OrgHandledAttitude)) .WhereIF(!string.IsNullOrEmpty(dto.OrgNoSatisfiedReason), x => SqlFunc.JsonField(x.OrgNoSatisfiedReason, "Key") == dto.OrgNoSatisfiedReason) .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 == _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 .OrderByDescending((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(canView: view, hasHandled: handler) .Includes(d => d.Order) .Includes(d => d.VisitDetail) .Includes(d => d.Visit, v => v.Order) .Includes(d => d.Workflow) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Visit.Order.Title.Contains(dto.Keyword!) || d.Visit.Order.No.Contains(dto.Keyword!)); if (dto.Status is EScreenStatus.Apply) { query.Where(d => (d.Status == EScreenStatus.Apply || d.Status == EScreenStatus.Approval)); } if (dto.Status.HasValue && dto.Status == EScreenStatus.MyHandle) { query.Where(d => (d.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, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(!string.IsNullOrEmpty(dto.OrderId), d => d.OrderId == dto.OrderId) .OrderByDescending(d => d.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 isNoPass = await _orderScreenRepository.AnyAsync(x => x.Status == EScreenStatus.Refuse && x.VisitDetailId == dto.Data.VisitDetailId); if (isNoPass) throw UserFriendlyException.SameMessage("该工单已被拒绝过甄别申请,不能再次申请"); var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ScreenApplyNum); int count = await _orderScreenRepository.CountAsync(x => x.OrderId == dto.Data.OrderId && x.Status == EScreenStatus.Refuse && x.VisitDetailId == dto.Data.VisitDetailId); if (count > int.Parse(setting?.SettingValue[0]) && int.Parse(setting?.SettingValue[0]) > -1) 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 && int.Parse(setting?.SettingValue[0]) > 0) throw UserFriendlyException.SameMessage("甄别申请时限已超过系统预定设置,不能申请"); var model = _mapper.Map(dto.Data); model.Status = EScreenStatus.Apply; model.ApplyEndTime = endTime; model.TimeConsuming = _timeLimitDomainService.CalcWorkTimeToDecimal(visit.VisitTime.Value, DateTime.Now, false); 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, _sessionContext, 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, _sessionContext, 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/{workflowId}/nextsteps")] public async Task OrderScreenNextsteps(string workflowId) { var workflow = await _workflowRepository.GetAsync(workflowId, HttpContext.RequestAborted); if (workflow != null) { var orderScreen = await _orderScreenRepository.Queryable().Includes(x => x.Order).Where(x => x.Id == workflow.ExternalId).FirstAsync(HttpContext.RequestAborted); if (orderScreen != null) { var result = await _workflowApplication.GetNextStepsAsync(workflowId, HttpContext.RequestAborted); if (!orderScreen.Order.IsProvince) { if (result.Steps.Any(x => x.Value == "省审批")) { result.Steps.Remove(result.Steps.First(x => x.Value == "省审批")); } } return result; } } return null; } /// /// 列表页面基础数据 /// /// [HttpGet("screen/base")] public async Task ScreenBaseData() { var rsp = new { ScreenStatus = EnumExts.GetDescriptions(), ScreenType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ScreenType), CounterSignType = EnumExts.GetDescriptions(), AcceptType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType), SourceChannel = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SourceChannel), VisitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction), DissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason), }; return rsp; } /// /// 甄别详情 /// /// /// [HttpGet("screen/{id}")] public async Task ScreenEntity(string id) { var model = await _orderScreenRepository.Queryable(canView: false) .Includes(x => x.Order) .Includes(x => x.Workflow, d => d.Steps) .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.IsCanHandle = model.Workflow?.IsCanHandle( _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles) ?? false; rspModel.Handle = false; if (!string.IsNullOrEmpty(rspModel.WorkflowId)) { 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 && !string.IsNullOrEmpty(x.PhoneNo) && x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e")).ToListAsync(); //发送短信 foreach (var user in userlist) { var messageDto = new Share.Dtos.Push.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) && ("001171".Equals(model.OrgId) || "001178".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 (supervise.Province.HasValue && supervise.Province.Value) { 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 (supervise.Province.HasValue && supervise.Province.Value) { 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() .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 && !string.IsNullOrEmpty(x.PhoneNo) && x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e")).ToListAsync(); foreach (var user in userlist) { //发送短信 var messageDto = new Share.Dtos.Push.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) && ("001171".Equals(model.OrgId) || "001178".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 工单办理 /// /// 工单列表 /// /// /// [HttpGet] public async Task> Query([FromQuery] QueryOrderDto dto) { var query = _orderApplication.QueryOrders(dto); var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } [HttpPost("order/export")] public async Task ExportOrders([FromBody] ExportExcelDto dto) { var query = _orderApplication.QueryOrders(dto.QueryDto); List orders; if (dto.IsExportAll) { orders = await query.ToListAsync(HttpContext.RequestAborted); } else { var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted); orders = items; } var orderDtos = _mapper.Map>(orders); dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos); var dtos = orderDtos .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass)) .Cast() .ToList(); var stream = ExcelHelper.CreateStream(dtos); return ExcelStreamResult(stream, "工单数据"); } /// /// 历史工单 /// /// /// [HttpGet("history")] public async Task> Query([FromQuery] QueryOrderHistoryDto dto) { var (total, items) = await _orderRepository.Queryable() .Where(d => d.Contact == 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.OrderPublish) //.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(); var dto = _mapper.Map(order); if (!string.IsNullOrEmpty(order.WorkflowId)) { var result = await _workflowDomainService.GetWorkflowHandlePermissionAsync( order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles, cancellationToken: HttpContext.RequestAborted); dto.Workflow = _mapper.Map(result.Workflow); dto.CountersignId = result.CountersignId; dto.CanHandle = result.CanHandle; dto.CanPrevious = result.CanPrevious; await _mediator.Publish(new GetOrderDetailNotify(result.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); if (order.OrderDelays.Any(x => x.DelayState == EDelayState.Examining && x.ApplyOrgCode == _sessionContext.RequiredOrgId)) { dto.CanHandle = false; } dto.IsCanCancelDelay = order.OrderDelays.Any(x => x.DelayState == EDelayState.Examining && x.ApplyOrgCode == _sessionContext.RequiredOrgId); var delayModel = order.OrderDelays.MaxBy(x => x.AfterDelay); if (delayModel != null) { var workFlow = await _workflowRepository.GetAsync(delayModel.WorkflowId); switch (delayModel.DelayState) { case EDelayState.Examining: dto.DelayString = "延期状态:审批中 当前节点:" + workFlow?.ActualHandleStepName; break; case EDelayState.Pass: dto.DelayString = "已延期" + delayModel?.DelayNum + "个" + delayModel?.DelayUnit.GetDescription(); break; case EDelayState.NoPass: dto.DelayString = "延期状态:拒绝 当前节点:" + workFlow?.ActualHandleStepName; break; case EDelayState.Withdraw: dto.DelayString = "延期状态:撤销 当前节点:" + workFlow?.ActualHandleStepName; break; default: break; } } else { dto.DelayString = ""; } //dto.CanPrevious = canPrevious; if (order.OrderPublish != null) { dto.PublishState = order.OrderPublish.PublishState; } if (dto.FileJson != null && dto.FileJson.Any()) { var ids = order.FileJson.Select(x => x.Id).ToList(); var files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted); //x.Classify == "办理上传" && dto.Files = files.Where(x => string.IsNullOrEmpty(x.FlowKey)).ToList(); } //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == order.CallId).FirstAsync();//由CallAccept改为OtherAccept var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == order.CallId).FirstAsync(); if (call != null) { dto.RecordingBaseAddress = call.RecordingBaseAddress; dto.RecordingAbsolutePath = call.RecordingAbsolutePath; } 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 //交通工单校验 var valid = await _orderDomainService.OrderValidation(dto, HttpContext.RequestAborted); if (valid.Validation) throw UserFriendlyException.SameMessage(valid.Result); 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);//由CallAccept改为OtherAccept var callRecord = await _trCallRecordRepository.GetAsync(p => p.OtherAccept == order.CallId && string.IsNullOrEmpty(p.OtherAccept) == false, 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); //敏感分词 await _orderApplication.OrderSensitiveParticiple(dto.Content, order.Id, HttpContext.RequestAborted); //sms try { if (order.AcceptSms) { _logger.LogInformation($"推送短信: orderNo: {order.No}"); var messageDto = new Share.Dtos.Push.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); } // 副本工单 var copy = new OrderCopy(); _mapper.Map(order, copy); copy.OrderId = order.Id; copy.AuditTime = DateTime.Now; copy.AuditUserId = _sessionContext.UserId; copy.AuditUserName = _sessionContext.UserName; copy.InitId(); await _orderCopyRepository.AddAsync(copy, HttpContext.RequestAborted); return order.Id; } /// /// 提供ds调用 /// [HttpPost("add-anonymous")] [AllowAnonymous] public async Task AddAnonymous([FromBody] AddOrderDto dto) { return await _orderApplication.ReceiveOrderFromExternalAsync(dto, _sessionContext, HttpContext.RequestAborted); } /// /// 提供ds调用--获取当天催办数量 /// [HttpGet("get-orderurge-count")] [AllowAnonymous] public async Task GetOrderUrgeCount() { var totle = await _orderUrgeRepository.Queryable() .Where(p => p.CreationTime >= Convert.ToDateTime(DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd 00:00:00"))) .Where(p => p.CreationTime <= Convert.ToDateTime(DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd 23:59:59"))) .CountAsync(); return new SubmitCaseTotalnfo() { Totle = totle }; } /// /// 提供ds调用 /// [HttpPost("update-orderfiles")] [AllowAnonymous] public async Task UpdateOrderFilesAnonymous([FromBody] UpdateOrderFilesDto dto) { await _orderApplication.UpdateOrderFilesAnonymousAsync(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 valid = await _orderDomainService.OrderValidation(dto, HttpContext.RequestAborted); if (valid.Validation) throw UserFriendlyException.SameMessage(valid.Result); var order = await _orderRepository.Queryable() .FirstAsync(d => d.Id == dto.Id); if (order == null) throw UserFriendlyException.SameMessage("无效工单编号"); if (order.Status > EOrderStatus.SpecialToUnAccept) 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(); //敏感分词 await _orderApplication.OrderSensitiveParticiple(dto.Content, order.Id, HttpContext.RequestAborted); // 副本工单 var copy = new OrderCopy(); _mapper.Map(order, copy); copy.OrderId = order.Id; copy.AuditTime = DateTime.Now; copy.AuditUserId = _sessionContext.UserId; copy.AuditUserName = _sessionContext.UserName; copy.InitId(); await _orderCopyRepository.AddAsync(copy, HttpContext.RequestAborted); } /// /// 开始工单办理流程 /// [HttpPost("startflow")] public async Task StartFlow([FromBody] OrderStartFlowDto dto) { ExpiredTimeWithConfig expiredTimeConfig; if (dto.Workflow.NextHandlers.Any(d => d.Key == "001171" || d.Key == "001178")) { var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80); expiredTimeConfig = new ExpiredTimeWithConfig { Count = 45, TimeType = ETimeType.WorkDay, TimeText = "45个工作日", ExpiredTime = timeResult.EndTime, NearlyExpiredTime = timeResult.NearlyExpiredTime }; } //else if (dto.Workflow.FlowDirection == EFlowDirection.CenterToCenter) //{ // var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 1, 0); // expiredTimeConfig = new ExpiredTimeWithConfig // { // Count = 1, // TimeType = ETimeType.WorkDay, // TimeText = "1个工作日", // ExpiredTime = timeResult.EndTime, // NearlyExpiredTime = timeResult.NearlyExpiredTime // }; //} else { //期满时间 expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, dto.Data.AcceptTypeCode); } _mapper.Map(expiredTimeConfig, dto.Data); 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 averageSendOrder = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.AverageSendOrder).SettingValue[0]); if (dto.Workflow.BusinessType == EBusinessType.Send && averageSendOrder) { var handler = await _orderDomainService.AverageOrder(HttpContext.RequestAborted); dto.Workflow.NextHandlers = new List { handler }; } //是否市州互转 if (dto.Data.Transpond.HasValue && dto.Data.Transpond.Value) { var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted); var orderDto = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderTranspondCity, orderDto); //保存本地数据 TranspondCityRawData cityRawData = new TranspondCityRawData { OrderCode = order.No, TransferOutTime = DateTime.Now, CityName = order.TranspondCityName, Direction = ETranspondDirection.Out }; await _transpondCityRawDataRepository.AddAsync(cityRawData, HttpContext.RequestAborted); } var startDto = _mapper.Map(dto.Workflow); startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderHandle; startDto.Title = dto.Data.Title; await _workflowApplication.StartWorkflowAsync(startDto, _sessionContext, id, dto.Data.ExpiredTime, 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) { var order = await _orderRepository.Queryable() .FirstAsync(d => d.WorkflowId == dto.WorkflowId, HttpContext.RequestAborted); if (order is null) throw new UserFriendlyException("无效工单编号"); //if (await _orderDelayRepository.AnyAsync(x => x.OrderId == order.Id && x.DelayState == EDelayState.Examining, HttpContext.RequestAborted)) //{ // throw UserFriendlyException.SameMessage("该工单存在正在审核中的延期,不能办理"); //} if (await _orderSendBackAuditRepository.AnyAsync(x => x.OrderId == order.Id && x.State == ESendBackAuditState.Apply, HttpContext.RequestAborted)) { throw UserFriendlyException.SameMessage("该工单存在正在审核中的退回,不能办理"); } ExpiredTimeWithConfig? expiredTimeConfig = null; if (dto.NextHandlers.Any(d => d.Key == "001171" || d.Key == "001178")) { var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80); expiredTimeConfig = new ExpiredTimeWithConfig { Count = 45, TimeType = ETimeType.WorkDay, TimeText = "45个工作日", ExpiredTime = timeResult.EndTime, NearlyExpiredTime = timeResult.NearlyExpiredTime }; var canUpdateOrderSender = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CanUpdateOrderSender).SettingValue[0]); order.CenterToOrg( expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime, dto.Opinion, _sessionContext.RequiredUserId, _sessionContext.UserName, canUpdateOrderSender); } else if (dto.FlowDirection is EFlowDirection.CenterToOrg) { expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, order.AcceptTypeCode); var canUpdateOrderSender = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CanUpdateOrderSender).SettingValue[0]); order.CenterToOrg( expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime, dto.Opinion, _sessionContext.RequiredUserId, _sessionContext.UserName, canUpdateOrderSender); //写入质检 await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, HttpContext.RequestAborted); } else if (dto.FlowDirection is EFlowDirection.CenterToCenter) { expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, order.AcceptTypeCode); order.CenterToCenter(expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime); } _mapper.Map(expiredTimeConfig, order); await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); var averageSendOrder = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.AverageSendOrder).SettingValue[0]); // 平均派单 if (dto.BusinessType == EBusinessType.Send && averageSendOrder) { var handler = await _orderDomainService.AverageOrder(HttpContext.RequestAborted); dto.NextHandlers = new List { handler }; } await _workflowApplication.NextAsync(dto, _sessionContext, order.ExpiredTime, 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); dto.ExpiredTime = order.ExpiredTime; 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 { TranspondCity = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.TranspondCity), 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 { TranspondCity = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.TranspondCity), 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"); } /// /// 触发平均派单 /// /// [HttpPost("trigger_average_order")] [AllowAnonymous] public async Task TriggerAverageOrder() { await _orderDomainService.TriggerAverageOrder(HttpContext.RequestAborted); } #endregion #region 工单待办 /// /// 查询待办工单 /// [HttpGet("waited")] public async Task> QueryWaited([FromQuery] QueryOrderWaitedDto dto) { var isHandled = dto.IsHandled.HasValue && dto.IsHandled.Value; if (dto.EndTime.HasValue) dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1); //var (total, items) = await _orderRepository // .Queryable(hasHandled: !isHandled) // .Includes(d => d.OrderSpecials) // .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince) // .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword)) // .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) // .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue) // .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue) // .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办 // .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == false, d => d.NearlyExpiredTime < DateTime.Now && d.ExpiredTime > DateTime.Now)//即将超期 未办 // .Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC) // .Where(d => d.Status != EOrderStatus.BackToProvince && d.Status < EOrderStatus.Filed) // //.Where(d => SqlFunc.Subqueryable().Where(os => os.OrderId == d.Id).NotAny()) // .Where(d => d.OrderSpecials.Any() == false || d.OrderSpecials.Any(s => s.State > 0)) // .WhereIF(dto.StartTime.HasValue, d => d.StartTime >= dto.StartTime) // .WhereIF(dto.EndTime.HasValue, d => d.StartTime <= dto.EndTime) // .OrderByDescending(d => d.StartTime) // .ToPagedListAsync(dto, HttpContext.RequestAborted); if (!isHandled) { var (total, items) = await _orderRepository .Queryable(hasHandled: !isHandled) .Includes(d => d.OrderSpecials) .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword)) .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue) .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办 .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == false, d => d.NearlyExpiredTime < DateTime.Now && d.ExpiredTime > DateTime.Now)//即将超期 未办 .Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC) .Where(d => d.Status != EOrderStatus.BackToProvince && d.Status < EOrderStatus.Filed) //.Where(d => SqlFunc.Subqueryable().Where(os => os.OrderId == d.Id).NotAny()) .Where(d => d.OrderSpecials.Any() == false || d.OrderSpecials.Any(s => s.State > 0)) .WhereIF(dto.StartTime.HasValue, d => d.StartTime >= dto.StartTime) .WhereIF(dto.EndTime.HasValue, d => d.StartTime <= dto.EndTime) .OrderByDescending(d => d.StartTime) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } else { var (total, items) = await _orderRepository.Queryable() .Where(d => SqlFunc.Subqueryable() .Where(step => step.ExternalId == d.Id && ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) || (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) || (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))) && step.Status == EWorkflowStepStatus.Handled).Any()) .Includes(d => d.OrderSpecials) .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword)) .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue) .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办 .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == false, d => d.NearlyExpiredTime < DateTime.Now && d.ExpiredTime > DateTime.Now)//即将超期 未办 .Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC) .Where(d => d.Status != EOrderStatus.BackToProvince && d.Status < EOrderStatus.Filed) //.Where(d => SqlFunc.Subqueryable().Where(os => os.OrderId == d.Id).NotAny()) .Where(d => d.OrderSpecials.Any() == false || d.OrderSpecials.Any(s => s.State > 0)) .WhereIF(dto.StartTime.HasValue, d => d.StartTime >= dto.StartTime) .WhereIF(dto.EndTime.HasValue, d => d.StartTime <= dto.EndTime) .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 and not EOrderStatus.SpecialToUnAccept : d is EOrderStatus.WaitForAccept or EOrderStatus.BackToUnAccept or EOrderStatus.SpecialToUnAccept) .ToArray(); if (dto.EndTime.HasValue) dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1); //var (total, items) = await _orderRepository.Queryable(canView: 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!)) // .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue) // .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue) // .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办 // .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == false, d => d.NearlyExpiredTime < DateTime.Now && d.ExpiredTime > DateTime.Now)//即将超期 未办 // .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime) // .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime) // .Where(d => (string.IsNullOrEmpty(d.WorkflowId) && (string.IsNullOrEmpty(d.SignerId) || d.SignerId == _sessionContext.RequiredUserId))) // .Where(d => string.IsNullOrEmpty(d.SignerId) || d.SignerId == _sessionContext.RequiredUserId) // .Where(x => x.Source < ESource.MLSQ || x.Source > ESource.WZSC) // .Where(x => x.Status != EOrderStatus.BackToProvince && x.Status < EOrderStatus.Filed) // .OrderBy(d => d.Status) // .OrderByIF(dto.IsHandled == true, d => d.StartTime, OrderByType.Desc) // .OrderByIF(dto.IsHandled == false, d => d.CreationTime, OrderByType.Desc) // .ToPagedListAsync(dto, HttpContext.RequestAborted); var (total, items) = await _orderRepository.Queryable() .LeftJoin((d, step) => d.Id == step.ExternalId) .Where((d, step) => ((string.IsNullOrEmpty(d.WorkflowId) && (string.IsNullOrEmpty(d.SignerId) || d.SignerId == _sessionContext.RequiredUserId)) || (!string.IsNullOrEmpty(d.WorkflowId) && ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) || (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) || (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))) && (((dto.IsHandled.HasValue && dto.IsHandled == false) || step.Status != EWorkflowStepStatus.Handled) || ((dto.IsHandled.HasValue && dto.IsHandled == true)) || step.Status == EWorkflowStepStatus.Handled) ))) .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.Title.StartsWith(dto.Keyword!)) .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue) .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办 .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == false, d => d.NearlyExpiredTime < DateTime.Now && d.ExpiredTime > DateTime.Now)//即将超期 未办 .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime) .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime) .Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC) .Where(d => d.Status != EOrderStatus.BackToProvince && d.Status < EOrderStatus.Filed) .OrderBy(d => d.Status) .OrderByIF(dto.IsHandled == true, d => d.StartTime, OrderByType.Desc) .OrderByIF(dto.IsHandled == false, d => d.CreationTime, OrderByType.Desc) .Select((d, step) => d) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 查询中心待办 /// [HttpGet("waited/center")] public async Task> QueryWaitedForCenter([FromQuery] QueryOrderWaitedCenterDto dto) { if (dto.EndCreationTime.HasValue) dto.EndCreationTime = dto.EndCreationTime.Value.AddDays(1).AddSeconds(-1); if (dto.StartTimeEnd.HasValue) dto.StartTimeEnd = dto.StartTimeEnd.Value.AddDays(1).AddSeconds(-1); var (total, items) = await _orderRepository.Queryable(canView: false) .Where(x => x.Workflow.Steps.Any(s => s.Status < EWorkflowStepStatus.Handled && s.HandlerOrgId == OrgSeedData.CenterId)) .Where(x => x.Source < ESource.MLSQ || x.Source > ESource.WZSC) .Where(x => x.Status != EOrderStatus.BackToProvince && x.Status < EOrderStatus.Filed) .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No!.Contains(dto.No!)) .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title!.Contains(dto.Title!)) .WhereIF(dto is { StCreationTime: not null, EndCreationTime: not null }, x => x.CreationTime >= dto.StCreationTime && x.CreationTime <= dto.EndCreationTime) .WhereIF(dto is { StartTimeSt: not null, StartTimeEnd: not null }, x => x.StartTime >= dto.StartTimeSt && x.StartTime <= dto.StartTimeEnd) .WhereIF(!string.IsNullOrEmpty(dto.StepName), x => x.Workflow.Steps.Any(s => s.Name == dto.StepName)) .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.ActualHandleOrgName!.Contains(dto.ActualHandleOrgName!)) .WhereIF(dto.Status.HasValue, x => x.Status == dto.Status) .WhereIF(!string.IsNullOrEmpty(dto.AcceptorName), x => x.AcceptorName!.Contains(dto.AcceptorName!)) .WhereIF(dto.ExpiredStatus is EExpiredStatus.Normal, x => DateTime.Now < x.NearlyExpiredTime) .WhereIF(dto.ExpiredStatus is EExpiredStatus.GoingToExpired, x => DateTime.Now > x.NearlyExpiredTime && DateTime.Now < x.ExpiredTime) .WhereIF(dto.ExpiredStatus is EExpiredStatus.Expired, x => DateTime.Now >= x.ExpiredTime) .OrderBy(x => x.Status) .OrderBy(x => x.CreationTime, OrderByType.Desc) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 查询中心待办基础数据 /// /// [HttpGet("waited/center/base")] public async Task WaitedForCenterBaseData() { var rsp = new { OrderStatus = EnumExts.GetDescriptions(), ExpiredStatus = EnumExts.GetDescriptions(), StepNames = new string[] { "话务部", "派单组" } }; return rsp; } /// /// 首页查询 /// /// /// [HttpGet("waited/home")] public async Task QueryWaitedHome([FromQuery] QueryOrderWaitedDto dto) { var isHandled = dto.IsHandled.HasValue && dto.IsHandled.Value; if (dto.EndTime.HasValue) dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1); var (total, items) = await _orderRepository .Queryable(hasHandled: !isHandled) .Includes(d => d.OrderSpecials) .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) .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办 .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == false, d => d.NearlyExpiredTime < DateTime.Now && d.ExpiredTime > DateTime.Now)//即将超期 未办 .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime) .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime) .Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC) .Where(d => d.Status != EOrderStatus.BackToProvince && d.Status < EOrderStatus.Filed) //.Where(d => SqlFunc.Subqueryable().Where(os => os.OrderId == d.Id).NotAny()) .Where(d => d.OrderSpecials.Any() == false || d.OrderSpecials.Any(s => s.State == 0) == false) .OrderByDescending(d => d.StartTime) .ToPagedListAsync(dto, HttpContext.RequestAborted); var page1 = new PagedDto(total, _mapper.Map>(items)); dto.IsHandled = false; isHandled = dto.IsHandled.HasValue && dto.IsHandled.Value; 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 and not EOrderStatus.SpecialToUnAccept : d is EOrderStatus.WaitForAccept or EOrderStatus.BackToUnAccept or EOrderStatus.SpecialToUnAccept) .ToArray(); var (total2, items2) = await _orderRepository.Queryable(canView: 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) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue) .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue) .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办 .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == false, d => d.NearlyExpiredTime < DateTime.Now && d.ExpiredTime > DateTime.Now)//即将超期 未办 .Where(x => x.Source < ESource.MLSQ || x.Source > ESource.WZSC) .Where(x => x.Status != EOrderStatus.BackToProvince && x.Status < EOrderStatus.Filed) .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); var page2 = new PagedDto(total2, _mapper.Map>(items2)); return new { Waited = page1, Sign = page2 }; } #endregion #region 业务工单退回 /// /// 工单退回退回(返回前一节点) /// [HttpPost("order_previous")] public async Task Previous([FromBody] OrderPreviousDto dto) { var oneSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.OneOrgSendBack)?.SettingValue[0]); var twoSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.TwoOrgSendBack)?.SettingValue[0]); var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, cancellationToken: HttpContext.RequestAborted); var order = await _orderRepository .Queryable() .Includes(d => d.Workflow) .FirstAsync(d => d.Id == workflow.ExternalId); if (oneSendBack || twoSendBack) { var (currentStep, prevStep, isOrgToCenter, isSecondToFirstOrgLevel) = await _workflowApplication.GetPreviousInformationAsync( dto.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles, HttpContext.RequestAborted); var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply).AnyAsync(); if (sendBack) throw UserFriendlyException.SameMessage("当前工单已经生成退回记录"); var specialAny = await _orderSpecialRepository.Queryable().Where(x => x.OrderId == dto.OrderId && x.State == 0) .AnyAsync(); if (specialAny) throw UserFriendlyException.SameMessage("工单已存在待审批特提信息!"); if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行退回!"); if ((oneSendBack && isOrgToCenter) || (twoSendBack && isSecondToFirstOrgLevel)) { var audit = new OrderSendBackAudit { OrderId = workflow.ExternalId, State = ESendBackAuditState.Apply, Content = dto.Opinion, SendBackData = dto, ApplyOrgId = currentStep.AcceptorOrgId, ApplyOrgName = currentStep!.AcceptorOrgName, SendBackOrgId = prevStep.HandlerOrgId,//prevStep.AcceptorOrgId, SendBackOrgName = prevStep.HandlerOrgName,//prevStep!.AcceptorOrgName, WorkflowOrgId = _sessionContext.RequiredOrgId, WorkflowUserId = _sessionContext.RequiredUserId, WorkflowRoleIds = _sessionContext.Roles.ToList() }; await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted); } else { var flowDirection = await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted); var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType }) .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted); //发送短信TODO } } else { var flowDirection = await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted); var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType }) .Where(o => o.Id == order.Id).ExecuteCommandAsync(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) { //string applicantId, string applicantOrgId, string[] applicantRoleIds, // ISessionContext current, CancellationToken cancellationToken); var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId, sendBack.WorkflowOrgId, sendBack.WorkflowRoleIds.ToArray(), _sessionContext, HttpContext.RequestAborted); //var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId, HttpContext.RequestAborted); var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType }) .Where(o => o.Id == sendBack.OrderId).ExecuteCommandAsync(HttpContext.RequestAborted); //发送短信TODO } await _orderSendBackAuditRepository.UpdateAsync(sendBack, HttpContext.RequestAborted); } /// /// 工单业务批量退回审批 /// /// [HttpPost("order_previous_audit_batch")] public async Task AuditBatch([FromBody] BatchAuditSendBackDto dto) { foreach (string id in dto.Ids) { if (dto.State == ESendBackAuditState.Refuse && string.IsNullOrEmpty(dto.AuditContent)) throw UserFriendlyException.SameMessage("退回拒绝,请填写审批拒绝原因"); //验证是否存在退回 var sendBack = await _orderSendBackAuditRepository.GetAsync(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) { var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId, sendBack.WorkflowOrgId, sendBack.WorkflowRoleIds.ToArray(), _sessionContext, HttpContext.RequestAborted); //var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId, HttpContext.RequestAborted); var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType }) .Where(o => o.Id == sendBack.OrderId).ExecuteCommandAsync(HttpContext.RequestAborted); //发送短信TODO } await _orderSendBackAuditRepository.UpdateAsync(sendBack, HttpContext.RequestAborted); } } /// /// 工单业务退回审批列表 /// /// /// [Permission(EPermission.OrderPreviousList)] [HttpGet("order_previous_list")] public async Task> AuditList([FromQuery] SendBackListDto dto) { var query = _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.AuditState == 1, d => d.State == ESendBackAuditState.Apply) .WhereIF(dto.AuditState == 2 && !dto.State.HasValue, d => d.State > ESendBackAuditState.Apply) .WhereIF(dto.AuditState == 2 && dto.State.HasValue, d => d.State == dto.State) .WhereIF(_sessionContext.Roles.Contains("role_sysadmin") == false, x => x.SendBackOrgId == _sessionContext.OrgId);// 123 系统管理员 var (total, items) = await query.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.OrderId, HttpContext.RequestAborted); if (order is null) { errorCount++; continue; } if (order.Status >= EOrderStatus.SpecialToUnAccept) { errorCount++; continue; } if (order.Source <= ESource.HotlineImport) { errorCount++; continue; } var model = new OrderSendBack() { Content = dto.Content, OrderId = item.OrderId, 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.SpecialToUnAccept) 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("工单存在甄别中的信息!"); if (await _orderSendBackAuditRepository.AnyAsync(x => x.OrderId == dto.OrderId && x.State == ESendBackAuditState.Apply, HttpContext.RequestAborted)) { 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, FlowDirection = dto.FlowDirection, HandlerType = dto.HandlerType, BusinessType = dto.BusinessType }; // 计算期满时间 //if (dto.AlterTime) //{ var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, order.AcceptTypeCode); var processType = dto.FlowDirection == EFlowDirection.OrgToCenter || dto.FlowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban; //var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, // ETimeType.WorkDay, // dto.TimeLimit.Value, order.AcceptTypeCode); await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, ProcessType = processType }) .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted); var orderDto = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: HttpContext.RequestAborted); //} await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, 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 && ("001171".Equals(model.OrgId) || "001178".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.ApplySpecial)] [HttpPost("re_transact")] [LogFilter("工单重办")] public async Task Add([FromBody] OrderReTransactDto 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("工单存在甄别中的信息!"); if (await _orderSendBackAuditRepository.AnyAsync(x => x.OrderId == dto.OrderId && x.State == ESendBackAuditState.Apply, HttpContext.RequestAborted)) { 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; model.State = 1; model.ESpecialType = ESpecialType.ReTransact; model.InitId(); if (dto.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", HttpContext.RequestAborted); await _orderSpecialRepository.AddAsync(model, HttpContext.RequestAborted); if (dto.ReTransactError.Any()) { List details = new(); foreach (var item in dto.ReTransactError) { var detail = new OrderSpecialDetail(); _mapper.Map(item, detail); detail.SpecialId = model.Id; details.Add(detail); } await _orderSpecialDetailRepository.AddRangeAsync(details, 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, FlowDirection = dto.FlowDirection, HandlerType = dto.HandlerType, BusinessType = dto.BusinessType }; DateTime endTime = order.ExpiredTime!.Value; // 计算期满时间 if (dto.AlterTime) { var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, dto.TimeLimit.Value, order.AcceptTypeCode); endTime = expiredTime.EndTime; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.EndTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime }) .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted); var orderDto = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: HttpContext.RequestAborted); } var processType = dto.FlowDirection == EFlowDirection.OrgToCenter || dto.FlowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType }) .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted); await _workflowApplication.RecallAsync(recall, endTime, 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 reTransactNum = order.ReTransactNum.HasValue ? order.ReTransactNum.Value + 1 : 1; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ReTransactNum = reTransactNum }).Where(o => o.Id == order.Id).ExecuteCommandAsync(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); } } } /// /// 审批工单特提信息 /// /// /// [Permission(EPermission.AuditSpecial)] [HttpPut("special")] [LogFilter("审批工单特提")] public async Task Update([FromBody] AuditOrderSpecialDto dto) { var special = await _orderSpecialRepository .Queryable() .Includes(d => d.Order) .FirstAsync(d => d.Id == dto.Id); if (special is null) throw UserFriendlyException.SameMessage("无效特提审批信息!"); if (special.State != 0) throw UserFriendlyException.SameMessage("无效特提审批信息,特提审批信息错误,该信息已审核!"); special.State = dto.State; special.Opinion = dto.Opinion; if (dto.Files.Any()) special.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, special.Id, "", HttpContext.RequestAborted); await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted); var order = await _orderRepository.GetAsync(x => x.Id == special.OrderId); if (special.State == 1) { var recall = new RecallDto { WorkflowId = special.WorkflowId!, NextStepCode = special.NextStepCode, NextStepName = special.NextStepName, NextHandlers = special.NextHandlers, Opinion = dto.Opinion, FlowDirection = special.FlowDirection, HandlerType = special.HandlerType.Value, BusinessType = special.BusinessType.Value }; //if (dto.AlterTime) // recall.External = new External { TimeLimit = dto.TimeLimit, TimeLimitUnit = dto.TimeLimitUnit }; //if (dto.Files.Any()) recall.Files = dto.Files; // 计算期满时间 //if (dto.AlterTime) //{ var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, order.AcceptTypeCode); var processType = dto.FlowDirection == EFlowDirection.OrgToCenter || dto.FlowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, ProcessType = processType }) .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted); var orderDto = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: HttpContext.RequestAborted); //} //todo 特提重办,按审批通过时间依据中心派至部门的规则计算期满时间,更新order await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, 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); } if (order != null && ("001171".Equals(special.OrgId) || "001178".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); //} } } } /// /// 批量审批工单特提 /// /// /// [HttpPut("special_batch")] [LogFilter("批量审批工单特提")] public async Task UpdateBatch([FromBody] BatchAuditOrderSpecialDto dto) { foreach (string id in dto.ids) { var special = await _orderSpecialRepository .Queryable() .Includes(d => d.Order) .FirstAsync(d => d.Id == id); if (special is null) throw UserFriendlyException.SameMessage("无效特提审批信息!"); if (special.State != 0) throw UserFriendlyException.SameMessage("无效特提审批信息,特提审批信息错误,该信息已审核!"); special.State = dto.State; special.Opinion = dto.Opinion; if (dto.Files.Any()) special.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, special.Id, "", HttpContext.RequestAborted); await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted); var order = await _orderRepository.GetAsync(x => x.Id == special.OrderId); if (special.State == 1) { var recall = new RecallDto { WorkflowId = special.WorkflowId!, NextStepCode = special.NextStepCode, NextStepName = special.NextStepName, NextHandlers = special.NextHandlers, Opinion = dto.Opinion, FlowDirection = special.FlowDirection, HandlerType = special.HandlerType.Value, BusinessType = special.BusinessType.Value }; //if (dto.AlterTime) // recall.External = new External { TimeLimit = dto.TimeLimit, TimeLimitUnit = dto.TimeLimitUnit }; //if (dto.Files.Any()) recall.Files = dto.Files; // 计算期满时间 //if (dto.AlterTime) //{ var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, order.AcceptTypeCode); var processType = dto.FlowDirection == EFlowDirection.OrgToCenter || dto.FlowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban; await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, ProcessType = processType }) .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted); var orderDto = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: HttpContext.RequestAborted); //} //todo 特提重办,按审批通过时间依据中心派至部门的规则计算期满时间,更新order await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, 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); } if (order != null && ("001171".Equals(special.OrgId) || "001178".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() .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.SpecialToUnAccept); 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 step = await _workflowApplication.GetRecallStepsAsync(id, HttpContext.RequestAborted); var specialSeats = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SpecialSeats).SettingValue[0]); var specialSendOrder = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SpecialSendOrder).SettingValue[0]); var baseTypeId = string.Empty; if (step != null && step.Steps.Any() && _sessionContext.Roles.Contains("zuoxi") && specialSeats && !_sessionContext.Roles.Contains("paidanyuan")) { step.Steps = step.Steps.Where(x => x.Key.ToLower() == "start").ToList(); if (step.Steps.Any()) baseTypeId = step.Steps[0].Key; } if (step != null && step.Steps.Any() && _sessionContext.Roles.Contains("paidanyuan") && specialSendOrder && !_sessionContext.Roles.Contains("zuoxi")) { step.Steps = step.Steps.Where(d => d.BusinessType is EBusinessType.Send).ToList(); if (step.Steps.Any()) baseTypeId = step.Steps[0].Key; } var rsp = new { SpecialTimeType = EnumExts.GetDescriptions(), SpecialReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SpecialReason), Step = step, BaseTypeId = baseTypeId }; return rsp; } /// /// 重办基础数据 /// /// [HttpGet("reTransact/base/{id}")] public async Task ReTransactBaseData(string id) { var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted); List orgs = new(); if (order == null) throw UserFriendlyException.SameMessage("无效工单信息!"); //中心会签调取方法 var org = await _workflowDomainService.GetLevelOneOrgsAsync(order.WorkflowId, HttpContext.RequestAborted); orgs.AddRange(org); var step = await _workflowApplication.GetRecallStepsAsync(order.WorkflowId, HttpContext.RequestAborted); //获取部门信息 var rsp = new { SpecialTimeType = EnumExts.GetDescriptions(), SpecialReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SpecialReason), ReTransactErrorType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ReTransactErrorType), Step = step, Orgs = orgs, }; 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 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 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 callsHistory = await _trCallRecordRepository.Queryable().Where(x => x.CPN == phone || x.CDPN == phone).ToListAsync(); var allCallNum = 0; var connectNum = 0; var callBackNum = 0; if (callsHistory != null && callsHistory.Any()) { allCallNum = callsHistory.Count(x => x.CallDirection == ECallDirection.In); connectNum = callsHistory.Count(x => x.CallDirection == ECallDirection.In && x.Duration > 0); callBackNum = callsHistory.Count(x => x.CallDirection == ECallDirection.Out); } //关注诉求 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 = allCallNum, ConnectNum = connectNum, CallBackNum = callBackNum }, 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) { var repeatableEvent = 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); return _mapper.Map(repeatableEvent); } #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) { var (total, items) = await _orderApplication.GetAboutToExpireAsync(dto).ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 工单即将超期列表导出 /// /// [HttpPost("order/about_expire/_export")] public async Task AboutListExport([FromBody] ExportExcelDto dto) { var query = _orderApplication.GetAboutToExpireAsync(dto.QueryDto); List orders; if (dto.IsExportAll) { orders = await query.ToListAsync(HttpContext.RequestAborted); } else { var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted); orders = items; } var ordersDtos = _mapper.Map>(orders); dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos); var dtos = ordersDtos .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass)) .Cast() .ToList(); var stream = ExcelHelper.CreateStream(dtos); return ExcelStreamResult(stream, "工单即将超期列表数据"); } ///// ///// 工单即将超期节点列表 ///// ///// ///// //[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> ExpireList([FromQuery] AboutToExpireListDto dto) { var (total, items) = await _orderApplication.GetToExpireAsync(dto).ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 工单超期列表导出 /// /// [HttpPost("order/expire/_export")] public async Task ExpireListExport([FromBody] ExportExcelDto dto) { var query = _orderApplication.GetToExpireAsync(dto.QueryDto); List orders; if (dto.IsExportAll) { orders = await query.ToListAsync(HttpContext.RequestAborted); } else { var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted); orders = items; } var ordersDtos = _mapper.Map>(orders); dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos); var dtos = ordersDtos .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass)) .Cast() .ToList(); var stream = ExcelHelper.CreateStream(dtos); return ExcelStreamResult(stream, "工单超期列表数据"); } ///// ///// 工单超期节点列表 ///// ///// ///// //[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); if (!string.IsNullOrEmpty(order.WorkflowId)) { var workflow = await _workflowDomainService.SignToSomebodyAsync( order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.UserName, _sessionContext.RequiredOrgId, _sessionContext.OrgName, HttpContext.RequestAborted); order.HandlerOrgs = workflow.HandlerOrgs; order.HandlerUsers = workflow.HandlerUsers; order.FlowedOrgIds = workflow.FlowedOrgIds; order.FlowedUserIds = workflow.FlowedUserIds; } await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); } #endregion #region 获取企业信息 /// /// 获取企业信息 /// /// /// [HttpGet("enterprise/list")] [LogFilter("查询企业列表")] public async Task QueryYbEnterprises([FromQuery] PagedKeywordRequest dto) { return await _enterpriseService.QueryYbEnterprisesAsync(dto.Keyword!, dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); } #endregion #region 导入工单 /// /// 下载工单导入模板 /// /// [HttpGet("download-order-template")] public async Task DownLoadOrderTemplate() { List list = new List(); ExcelContent excelContent = new ExcelContent() { ExternalId = "自编号" }; 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 != "麻辣社区" || item.Source != "人民网" || item.Source != "省长信箱" || item.Source != "问政四川") //if (item.Source < ESource.MLSQ || item.Source > ESource.WZSC) { errorCount++; continue; } int SourceCode = 0; switch (item.Source) { case "麻辣社区": SourceCode = 500; break; case "人民网": SourceCode = 501; break; case "省长信箱": SourceCode = 502; break; case "问政四川": SourceCode = 529; break; default: break; } var order = await _orderRepository.GetAsync(x => x.ExternalId == item.ExternalId && x.Source == (ESource)SourceCode, HttpContext.RequestAborted); order = _mapper.Map(item); #region 处理数据开始 order.Source = (ESource)SourceCode; //来源 //处理热点 //处理一级热点 string hotspotId = ""; string hotspotName = ""; string hotspotFullName = ""; var hotspotOne = await _hotspotTypeRepository.Queryable().FirstAsync(x => x.HotSpotName == item.HotspotNameOne, HttpContext.RequestAborted); if (hotspotOne != null) { hotspotId = hotspotOne.Id; hotspotName = hotspotOne.HotSpotName; hotspotFullName = hotspotOne.HotSpotFullName; var hotspotTwo = await _hotspotTypeRepository.Queryable().FirstAsync(x => x.HotSpotName == item.HotspotNameTwo && x.ParentId == hotspotId, HttpContext.RequestAborted); if (hotspotTwo != null) { hotspotId = hotspotTwo.Id; hotspotName = hotspotTwo.HotSpotName; hotspotFullName = hotspotTwo.HotSpotFullName; var hotspotThree = await _hotspotTypeRepository.Queryable().FirstAsync(x => x.HotSpotName == item.HotspotNameThree && x.ParentId == hotspotId, HttpContext.RequestAborted); if (hotspotThree != null) { hotspotId = hotspotThree.Id; hotspotName = hotspotThree.HotSpotName; hotspotFullName = hotspotThree.HotSpotFullName; var hotspotFour = await _hotspotTypeRepository.Queryable().FirstAsync(x => x.HotSpotName == item.HotspotNameFour && x.ParentId == hotspotId, HttpContext.RequestAborted); if (hotspotFour != null) { hotspotId = hotspotFour.Id; hotspotName = hotspotFour.HotSpotName; hotspotFullName = hotspotFour.HotSpotFullName; var hotspotFive = await _hotspotTypeRepository.Queryable().FirstAsync(x => x.HotSpotName == item.HotspotNameFive && x.ParentId == hotspotId, HttpContext.RequestAborted); if (hotspotFive != null) { hotspotId = hotspotFive.Id; hotspotName = hotspotFive.HotSpotName; hotspotFullName = hotspotFive.HotSpotFullName; } } } } } order.HotspotId = hotspotId; order.HotspotName = hotspotName; order.HotspotSpliceName = hotspotFullName; //处理部门 var orgOne = await _organizeRepository.Queryable().FirstAsync(x => x.Name == item.OrgLevelOneName, HttpContext.RequestAborted); if (orgOne != null) { order.OrgLevelOneCode = orgOne.Id; order.OrgLevelOneName = orgOne.Name; var orgTwo = await _organizeRepository.Queryable().FirstAsync(x => x.Name == item.OrgLevelTwoName && x.ParentId == order.OrgLevelOneCode, HttpContext.RequestAborted); if (orgTwo != null) { order.OrgLevelTwoCode = orgTwo.Id; order.OrgLevelTwoName = orgTwo.Name; } } //承办部门 var ActualHandleOrg = await _organizeRepository.Queryable().FirstAsync(x => x.Name == item.ActualHandleOrgName, HttpContext.RequestAborted); if (ActualHandleOrg != null) { order.ActualHandleOrgCode = ActualHandleOrg.Id; } //处理地址 order.Address = $"{order.Province}{order.City}{order.County}{order.Town}"; order.FullAddress = $"{order.Address}{order.Street}"; #endregion if (order is null) { //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 #region 二次办理 /// /// 新增二次办理 /// /// /// [HttpPost("secondary_handling")] [LogFilter("新增二次办理")] public async Task OrderSecondaryHandlingAdd([FromBody] AddOrderSecondaryHandlingDto dto) { await _orderSecondaryHandlingApplication.AddAsync(dto, HttpContext.RequestAborted); } /// /// 二次办理退回 /// /// /// [HttpPost("secondary_handling/send_back")] [LogFilter("二次办理退回")] public async Task OrderSecondaryHandlingSendBackAsync([FromBody] SendBackOrderSecondaryHandlingDto dto) { await _orderSecondaryHandlingApplication.SendBackAsync(dto, HttpContext.RequestAborted); } /// /// 二次办理审批 /// /// /// [HttpPut("secondary_handling/audit")] [LogFilter("二次办理审批")] public async Task OrderSecondaryHandlingAudit([FromBody] AuditOrderSecondaryHandlingDto dto) { var model = await _orderSecondaryHandlingApplication.Entity(dto.Id, HttpContext.RequestAborted); if (model == null || model.State != ESecondaryHandlingState.Apply) throw UserFriendlyException.SameMessage("无效二次办理审批信息!"); await _orderSecondaryHandlingApplication.AuditAsync(dto, model, HttpContext.RequestAborted); } /// /// 二次办理批量审批 /// /// /// [HttpPut("secondary_handling/batch_audit")] [LogFilter("二次办理批量审批")] public async Task OrderSecondaryHandlingBatchAudit([FromBody] AuditOrderSecondaryHandlingDto dto) { foreach (var item in dto.Ids) { var model = await _orderSecondaryHandlingApplication.Entity(item, HttpContext.RequestAborted); if (model == null || model.State != ESecondaryHandlingState.Apply) throw UserFriendlyException.SameMessage("无效二次办理审批信息!"); await _orderSecondaryHandlingApplication.AuditAsync(dto, model, HttpContext.RequestAborted); } } /// /// 二次办理申请列表 /// /// [HttpGet("secondary_handling/apply")] public async Task> OrderSecondaryHandlingApplyQuery([FromQuery] MayScreenListDto dto) { var query = _orderSecondaryHandlingApplication.ApplyQuery(dto, HttpContext.RequestAborted); var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 二次办理申请列表导出 /// /// [HttpPost("secondary_handling/apply_export")] public async Task OrderSecondaryHandlingApplyExport([FromBody] ExportExcelDto dto) { var query = _orderSecondaryHandlingApplication.ApplyQuery(dto.QueryDto, HttpContext.RequestAborted); List visitDetails; if (dto.IsExportAll) { visitDetails = await query.ToListAsync(HttpContext.RequestAborted); } else { var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted); visitDetails = items; } var visitDetailsDtos = _mapper.Map>(visitDetails); dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos); var dtos = visitDetailsDtos .Select(stu => _mapper.Map(stu, typeof(OrderVisitDetailDto), dynamicClass)) .Cast() .ToList(); var stream = ExcelHelper.CreateStream(dtos); return ExcelStreamResult(stream, "二次办理申请列表数据"); } /// /// 二次办理列表 /// /// [HttpGet("secondary_handling")] public async Task> OrderSecondaryHandlingQuery([FromQuery] SecondaryHandlingListDto dto) { var query = _orderSecondaryHandlingApplication.Query(dto, HttpContext.RequestAborted); var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 二次办理列表导出 /// /// [HttpPost("secondary_handling/_export")] public async Task OrderSecondaryHandlingExport([FromBody] ExportExcelDto dto) { var query = _orderSecondaryHandlingApplication.Query(dto.QueryDto, HttpContext.RequestAborted); List secondaryHandling; if (dto.IsExportAll) { secondaryHandling = await query.ToListAsync(HttpContext.RequestAborted); } else { var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted); secondaryHandling = items; } var secondaryHandlingDtos = _mapper.Map>(secondaryHandling); dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos); var dtos = secondaryHandlingDtos .Select(stu => _mapper.Map(stu, typeof(OrderSecondaryHandlingDto), dynamicClass)) .Cast() .ToList(); var stream = ExcelHelper.CreateStream(dtos); return ExcelStreamResult(stream, "二次办理列表数据"); } /// /// 获取实体 /// /// /// [HttpGet("secondary_handling/{id}")] public async Task OrderSecondaryHandlingEntity(string id) { var model = await _orderSecondaryHandlingApplication.Entity(id, HttpContext.RequestAborted); var dto = _mapper.Map(model); if (model.FileJson != null && model.FileJson.Any()) { var ids = model.FileJson.Select(x => x.Id).ToList(); var files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted); dto.Files = files.Where(x => x.Classify == "二次办理申请").ToList(); } return dto; } /// /// 列表页面基础数据 /// /// [HttpGet("secondary_handling/base")] public async Task SecondaryHandlingBaseData() { var rsp = new { Status = EnumExts.GetDescriptions(), CounterSignType = EnumExts.GetDescriptions(), AcceptType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType), SourceChannel = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SourceChannel), VisitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction), DissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason), }; return rsp; } #endregion #region 副本工单 /// /// 获取副本工单列表 /// /// /// [HttpGet("order_copy/list")] public async Task> OrderCopyList([FromQuery] OrderCopyListDto dto) { var (total, items) = await _orderCopyRepository.Queryable() .Where(x => x.OrderId == dto.OrderId) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.No.Contains(dto.Keyword!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 外部市民管理 /// /// 下载外部市民导入模板 /// /// [HttpGet("download-externalcitizens-template")] public async Task DownLoadCitizensTemplate() { List list = new List(); ExternalCitizensExcelContent excelContent = new ExternalCitizensExcelContent() { }; list.Add(excelContent); return _exportApplication.ExportData(list, "demo.xlsx"); } /// /// 导入外部市民 /// /// /// [HttpPost("import-externalcitizens")] public async Task ImportExternalcitizens(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; List listreturn = new List(); if (list != null && list.Count > 0) { count = list.Count; foreach (var item in list) { try { var externalcitizens = await _externalCitizensRepository.GetAsync(x => x.PhoneNum == item.PhoneNum, HttpContext.RequestAborted); if (externalcitizens is null) { externalcitizens = _mapper.Map(item); var id = await _externalCitizensRepository.AddAsync(externalcitizens, HttpContext.RequestAborted); if (!string.IsNullOrEmpty(id)) { addCount++; listreturn.Add(item); } else { errorCount++; } } else { listreturn.Add(item); //_mapper.Map(item, externalcitizens); //await _externalCitizensRepository.UpdateAsync(externalcitizens, HttpContext.RequestAborted); //modifyCount++; } } catch (Exception ex) { errorCount++; } } } return new { Count = count, ErrorCount = errorCount, AddCount = addCount, ResultList = listreturn /*, ModifyCount = modifyCount*/ }; } } /// /// 外部市民列表 /// /// [HttpGet("externalcitizens-list")] public async Task> QueryExternalcitizens([FromQuery] QueryExternalcitizensRequest dto) { var (total, items) = await _externalCitizensRepository.Queryable() .WhereIF(!string.IsNullOrEmpty(dto.PhoneNum), x => x.PhoneNum.Contains(dto.PhoneNum)) .WhereIF(!string.IsNullOrEmpty(dto.Name), x => x.Name.Contains(dto.Name)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 工单期满时间、来源方式修改 /// /// 修改期满时间 /// /// /// [HttpPost("update-orderexpired-time")] public async Task UpdateOrderExpiredTime([FromBody] UpdateOrderExpiredTimeDto dto) { if (dto == null || string.IsNullOrEmpty(dto.Id) || !dto.ExpiredTime.HasValue) throw UserFriendlyException.SameMessage("参数信息有误!"); var orderData = await _orderRepository.GetAsync(p => p.Id == dto.Id, HttpContext.RequestAborted); if (orderData == null) throw UserFriendlyException.SameMessage("工单查询失败!"); #region 写入操作记录 OrderModifyingRecords orderModifyingRecords = new() { OrderId = orderData.Id, OrderNo = orderData.No, ProvinceNo = orderData.ProvinceNo, UpdateOrderType = EUpdateType.ExpiredTime, OldValue = orderData.ExpiredTime == null ? "" : orderData.ExpiredTime.Value.ToString("yyyy-MM-dd HH:mm:ss"), NewValue = dto.ExpiredTime.Value.ToString("yyyy-MM-dd HH:mm:ss") }; await _orderModifyingRecordsRepository.AddAsync(orderModifyingRecords, HttpContext.RequestAborted); #endregion //写入新的数据 orderData.ExpiredTime = dto.ExpiredTime; await _orderRepository.UpdateAsync(orderData, HttpContext.RequestAborted); //向省上推送数据 if (dto.IsPush && orderData.Status > EOrderStatus.WaitForAccept) { var orderDto = _mapper.Map(orderData); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: HttpContext.RequestAborted); } } /// /// 修改来源方式 /// /// /// [HttpPost("update-order-sourcechannel")] public async Task UpdateOrderSourceChannel([FromBody] UpdateOrderSourceChannelDto dto) { if (dto == null || dto.Ids == null || dto.Ids.Count == 0) throw UserFriendlyException.SameMessage("参数信息有误!"); foreach (var item in dto.Ids) { var orderData = await _orderRepository.GetAsync(p => p.Id == item, HttpContext.RequestAborted); if (orderData != null) { #region 写入操作记录 OrderModifyingRecords orderModifyingRecords = new() { OrderId = orderData.Id, OrderNo = orderData.No, ProvinceNo = orderData.ProvinceNo, UpdateOrderType = EUpdateType.SourceChannel, OldValue = orderData.SourceChannelCode + "_" + orderData.SourceChannel, NewValue = "QT_其他" }; await _orderModifyingRecordsRepository.AddAsync(orderModifyingRecords, HttpContext.RequestAborted); #endregion orderData.SourceChannel = "其他"; orderData.SourceChannelCode = "QT"; await _orderRepository.UpdateAsync(orderData, HttpContext.RequestAborted); //向省上推送数据 if (dto.IsPush) { var orderDto = _mapper.Map(orderData); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: HttpContext.RequestAborted); } } } } /// /// 获取修改记录 /// /// [HttpGet("get-order-modifying-records-list")] public async Task> GetOrderModifyingRecordsList([FromQuery] string Id) { var list = await _orderModifyingRecordsRepository.Queryable().Where(p => p.OrderId == Id).OrderByDescending(p => p.CreationTime).ToListAsync(); return _mapper.Map>(list); } #endregion #region 工单平移 /// /// 查询工单平移待办理人 /// /// [HttpGet("migration/{orderId}")] public async Task Migration(string orderId) { var steps = await _workflowStepRepository.Queryable() .Where(d => d.ExternalId == orderId && d.Status != EWorkflowStepStatus.Handled) .ToListAsync(HttpContext.RequestAborted); if (!steps.Any()) throw new UserFriendlyException("未查询到待办理节点"); if (steps.Count > 1) throw new UserFriendlyException("多个待办理节点暂不支持平移"); var step = steps.First(); if (step.BusinessType is not EBusinessType.Center and not EBusinessType.Send) throw UserFriendlyException.SameMessage("当前办理节点非中心暂不支持平移"); var setting = step.BusinessType is EBusinessType.Center ? _systemSettingCacheManager.GetSetting(SettingConstants.RoleZuoXi) : _systemSettingCacheManager.GetSetting(SettingConstants.RolePaiDan); var roles = setting?.SettingValue.ToList(); var users = await _userRepository.Queryable() .Includes(d => d.Organization) .Includes(d => d.Roles) .Where(d => d.Roles.Any(x => roles.Contains(x.Name))) .ToListAsync(HttpContext.RequestAborted); return new GetOrderMigrationDto { StepId = step.Id, Handlers = users.Select(d => new OrderMigrationHandler { UserId = d.Id, Username = d.Name, OrgId = d.OrgId, OrgName = d.Organization.Name, RoleNames = string.Join(',', d.Roles.Select(x => x.DisplayName).ToList()) }).ToList() }; } #endregion }