using DotNetCore.CAP; using Hotline.Application.FlowEngine; using Hotline.Caching.Interfaces; using Hotline.File; using Hotline.FlowEngine.Definitions; using Hotline.FlowEngine.Workflows; using Hotline.Orders; using Hotline.Orders.Notifications; using Hotline.Permissions; using Hotline.Quality; using Hotline.Repository.SqlSugar.Extensions; using Hotline.Repository.SqlSugar.Ts; using Hotline.Settings; using Hotline.Settings.Hotspots; using Hotline.Settings.TimeLimits; using Hotline.Share.Dtos; using Hotline.Share.Dtos.FlowEngine; using Hotline.Share.Dtos.Order; using Hotline.Share.Dtos.Settings; using Hotline.Share.Enums.Order; using Hotline.Share.Enums.Quality; using Hotline.Share.Enums.Settings; using Hotline.Share.Mq; using Hotline.Share.Requests; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Mvc; using SqlSugar; using Hotline.FlowEngine.WorkflowModules; using Hotline.Share.Enums.FlowEngine; using XF.Domain.Authentications; using XF.Domain.Constants; using XF.Domain.Exceptions; using XF.Domain.Repository; using XF.Utility.EnumExtensions; using Hotline.CallCenter.Calls; using Hotline.DataSharing.Province.Services; using Hotline.Share.Dtos.File; 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 IProvinceService _provinceService; private readonly IRepository _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 IRepository _orderScreenRepository; private readonly IRepository _orderPublishHistoryRepository; private readonly IRepositoryTextSearch _repositoryts; private readonly IQualityRepository _qualityRepository; 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; 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, IProvinceService provinceService, IRepository orderDelayRepository, ITimeLimitDomainService timeLimitDomainService, ISystemSettingCacheManager systemSettingCacheManager, IRepository orderRedoRepository, IRepository orderSuperviseRepository, IRepository orderUrgeRepository, IFileRepository fileRepository, IRepository orderScreenRepository, IRepository orderPublishHistoryRepository, IRepositoryTextSearch repositoryts, IQualityRepository qualityRepository, 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 ) { _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; _provinceService = provinceService; _orderDelayRepository = orderDelayRepository; _timeLimitDomainService = timeLimitDomainService; _systemSettingCacheManager = systemSettingCacheManager; _orderRedoRepository = orderRedoRepository; _orderSuperviseRepository = orderSuperviseRepository; _orderUrgeRepository = orderUrgeRepository; _fileRepository = fileRepository; _orderScreenRepository = orderScreenRepository; _orderPublishHistoryRepository = orderPublishHistoryRepository; _repositoryts = repositoryts; _qualityRepository = qualityRepository; _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; } #region 工单发布 /// /// 查询(工单发布) /// /// /// [HttpGet("publish")] public async Task> PublishOrderList([FromQuery] QueryOrderPublishDto dto) { var (total, items) = await _orderRepository.Queryable() .Includes(d => d.OrderPublish) .Where(x => x.Status == EOrderStatus.Filed) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!)) .WhereIF(dto.PubState == EPubState.Pub, d => d.Status >= EOrderStatus.Published) .WhereIF(dto.PubState == EPubState.NoPub, d => d.Status < EOrderStatus.Published) .WhereIF(!string.IsNullOrEmpty(dto.PubMan), d => d.Acceptor.Name.Contains(dto.PubMan!) || d.Acceptor.StaffNo.Contains(dto.PubMan!)) .WhereIF(dto.PubRange == EPublicState.Pub, d => d.OrderPublish.PublishState) .WhereIF(dto.PubRange == EPublicState.NoPub, d => !d.OrderPublish.PublishState) .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType)) .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(dto.FiledTimeStart.HasValue, d => d.OrderPublish.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.FiledTimeEnd.HasValue, d => d.OrderPublish.CreationTime <= dto.CreationTimeEnd) .OrderBy(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 发布工单 /// /// [Permission(EPermission.PublishOrder)] [HttpPost("publish")] public async Task PublishOrder([FromBody] PublishOrderDto dto) { //验证订单 var order = await _orderRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (order is null) throw UserFriendlyException.SameMessage("未找到工单,无法发布"); //新增发布工单 OrderPublish orderPublish = new OrderPublish(); orderPublish.OrderId = order.Id; orderPublish.No = order.No; orderPublish.PublishState = dto.PublishState; orderPublish.ArrangeTitle = dto.ArrangeTitle; orderPublish.ArrangeContent = dto.ArrangeContent; orderPublish.ArrangeOpinion = dto.ArrangeOpinion; orderPublish.ProPublishState = dto.ProPublishState; orderPublish.FeedBackPhone = dto.FeedBackPhone; orderPublish.NoPubReason = dto.NoPubReason; orderPublish.CreatorName = _sessionContext.UserName; string id = await _orderPublishRepository.AddAsync(orderPublish); order.Publish(orderPublish.PublishState); await _orderRepository.UpdateAsync(order); //TODO 推省上 try { var publishPublishOrder = _mapper.Map(orderPublish); publishPublishOrder.Order = _mapper.Map(order); } catch {} 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; } 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); } /// /// 发布页面基础信息 /// /// [HttpGet("publish-order-pagebase/{id}")] public async Task PublishOrderPageBase(string id) { var order = await _orderRepository.Queryable() .Includes(d => d.Acceptor) .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 }; var (idName, idNames) = await _workflowDomainService.GetUnvisitOrgsAsync(order.WorkflowId, HttpContext.RequestAborted); res.ActualHandleOrgName = idName; res.idNames = idNames.ToList(); return res; } /// /// 已发布列表 /// /// /// [Permission(EPermission.PublishedOrderList)] [HttpGet("published")] public async Task> PublishedOrderList([FromQuery] PagedKeywordRequest dto) { var (total, items) = await _orderPublishRepository.Queryable() .Includes(x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .OrderBy(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 发布详情 /// /// /// [Permission(EPermission.PublishedOrder)] [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")] public async Task PublishedModify([FromBody] PublishOrderModifyDto dto) { var publishOrder = await _orderPublishRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (publishOrder is null) { throw UserFriendlyException.SameMessage("无效数据"); } var history = new OrderPublishHistory(); history.ArrangeTitleBefor = publishOrder.ArrangeTitle; history.ArrangeTitleAfter = dto.ArrangeTitle; history.ArrangeContentBefor = publishOrder.ArrangeContent; history.ArrangeContentAfter = dto.ArrangeContent; history.ArrangeOpinionBefor = publishOrder.ArrangeOpinion; history.ArrangeOpinionAfter = dto.ArrangeOpinion; history.No = publishOrder.No; history.OrderId = publishOrder.OrderId; history.OrderPublishId = publishOrder.Id; publishOrder.ArrangeTitle = dto.ArrangeTitle; publishOrder.ArrangeContent = dto.ArrangeContent; publishOrder.ArrangeOpinion = dto.ArrangeOpinion; await _orderPublishRepository.UpdateAsync(publishOrder, HttpContext.RequestAborted); await _orderPublishHistoryRepository.AddAsync(history, HttpContext.RequestAborted); } /// /// 发布修改记录 /// /// /// [HttpGet("published-history-list/{id}")] public async Task> QueryPublishedHistory(string id) { return await _orderPublishHistoryRepository.Queryable().Where(x => x.OrderPublishId == id) .OrderByDescending(x => x.CreationTime).ToListAsync(HttpContext.RequestAborted); } #endregion #region 工单回访 /// /// 回访列表 /// /// /// [HttpGet("visit")] public async Task> QueryOrderVisitList([FromQuery] QueryOrderVisitDto dto) { var (total, items) = await _orderVisitRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.Employee) .Includes(x => x.OrderVisitDetails) .WhereIF(dto.VisitState == EVisitStateQuery.NoVisit, x => (x.VisitState == Share.Enums.Order.EVisitState.WaitForVisit || x.VisitState == Share.Enums.Order.EVisitState.NoSatisfiedWaitForVisit) && x.Order.IsProvince == false) .WhereIF(dto.VisitState == EVisitStateQuery.Visited, x => x.VisitState == Share.Enums.Order.EVisitState.Visited) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!) || x.Order.No.Contains(dto.Keyword!)) .OrderBy(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 回访详情 /// /// [HttpGet("visit/{id}")] public async Task VisitInfo(string id) { var orderVisit = await _orderVisitRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.Employee) .Includes(x => x.OrderVisitDetails.OrderBy(d=>d.VisitTarget).ToList()) .FirstAsync(x => x.Id == id, HttpContext.RequestAborted); if (orderVisit is null) { throw UserFriendlyException.SameMessage("未知工单回访"); } int visitCount = await _orderVisitRepository.CountAsync( x => x.OrderId == orderVisit.OrderId && x.VisitState == Share.Enums.Order.EVisitState.Visited, HttpContext.RequestAborted); //int againCount = await _orderVisitRepository.CountAsync( // x => x.OrderId == orderVisit.OrderId && x.AgainState == EAgainState.DoAgain, HttpContext.RequestAborted); var voiceEvaluate = EnumExts.GetDescriptions(); var seatEvaluate = EnumExts.GetDescriptions(); var visitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction); var dissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason); var visitManner = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitManner); return new { OrderVisitModel = orderVisit, VisitCount = visitCount, //AgainCount = againCount, VisitSatisfaction = visitSatisfaction, DissatisfiedReason = dissatisfiedReason, VisitManner = visitManner, ViceEvaluate = voiceEvaluate, SeatEvaluate = seatEvaluate }; } /// /// 回访明细 /// /// [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")] 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; if (first != null) { visit.NowEvaluate = first.OrgProcessingResults; } //update order if (dto.IsPutThrough) { visit.VisitState = Share.Enums.Order.EVisitState.Visited; visit.VisitTime = DateTime.Now; visit.VisitType = EVisitType.ArtificialVisit; if (first != null) { visit.Order.Visited(first.OrgProcessingResults.Key, first.OrgProcessingResults.Value); } //_mapper.Map(dto.VisitDetails,visit.OrderVisitDetails); for (int i = 0; i < visit.OrderVisitDetails.Count; i++) { var detail = visit.OrderVisitDetails[i]; var detaildto = dto.VisitDetails.FirstOrDefault(x => x.Id == detail.Id); if (detaildto != null) { _mapper.Map(detaildto, visit.OrderVisitDetails[i]); } } await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); await _orderVisitedDetailRepository.UpdateRangeAsync(visit.OrderVisitDetails, HttpContext.RequestAborted); await _orderRepository.UpdateAsync(visit.Order, HttpContext.RequestAborted); var orderDto = _mapper.Map(visit.Order); if (first != null) { //推省上 //_capPublisher.Publish(EventNames.HotlineOrderVisited, // new PublishVisitDto() // { // Order = orderDto, // No = visit.No, // VisitType = visit.VisitType, // VisitName = visit.CreatorName, // VisitTime = visit.VisitTime, // VisitRemark = first.VisitContent, // AreaCode = visit.Order.AreaCode!, // SubjectResultSatifyCode = first.OrgProcessingResults.Key, // FirstSatisfactionCode = visit.Order.FirstVisitResultCode!, // ClientGuid = "" // }); await _provinceService.SubmitVisitInfo(new PublishVisitDto() { Order = orderDto, No = visit.No, VisitType = visit.VisitType, VisitName = visit.CreatorName, VisitTime = visit.VisitTime, VisitRemark = first.VisitContent, AreaCode = visit.Order.AreaCode!, SubjectResultSatifyCode = first.OrgProcessingResults.Key, FirstSatisfactionCode = visit.Order.FirstVisitResultCode!, ClientGuid = "" }, HttpContext.RequestAborted); } if (first != null) { //写入质检 await _qualityRepository.AddQualityAsync(EQualitySource.Visit, visit.Order.Id, visit.Id, HttpContext.RequestAborted); } } else { await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); } } /// /// 批量分配回访人员 /// /// /// [HttpPost("visit/distribution")] public async Task DistributionVisit([FromBody] DistributionVisitDto dto) { int error = 0; foreach (var id in dto.Ids) { var visit = await _orderVisitRepository.Queryable().FirstAsync(d => d.Id == id, HttpContext.RequestAborted); if (visit != null && visit.VisitState != EVisitState.WaitForVisit) { visit.EmployeeId = dto.EmployeeId; await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); } else { error++; } } return new DistributionVisitRspDto() { ErrorCount = error, SuccessCount = dto.Ids.Count - error }; } #endregion #region 二次回访申请 /// /// 可二次回访申请列表 /// /// /// [Permission(EPermission.OrderVisitAgainList)] [HttpGet("visitapply/visitagainlist")] public async Task> OrderVisitAgainList([FromQuery] OrderVisitAgainListDto dto) { var (total, items) = await _orderVisitedDetailRepository.Queryable() .Includes(x => x.OrderVisit, x => x.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrderVisit.Order.No.Contains(dto.Keyword)) .Where(x => x.OrderVisit.VisitState == EVisitState.Visited && (x.OrderVisit.VisitType == EVisitType.SmsVisit || x.OrderVisit.VisitType == EVisitType.ChipVoiceVisit)) .Where(x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2") .Where(x => x.OrderVisit.IsCanHandle) .Where(x => x.VisitTarget == EVisitTarget.Org) .OrderByDescending(x => x.OrderVisit.VisitTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 二次回访申请 /// /// /// /// [Permission(EPermission.ApplyOrderVisit)] [HttpPost("visitapply/add")] 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")] 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")] 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() .Includes(d => d.Acceptor) .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")] 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); int count = await _orderDelayRepository.CountAsync(x => x.OrderId == delaydto.OrderId); if (count > int.Parse(setting?.SettingValue[0])) throw UserFriendlyException.SameMessage("延期申请已超过系统预定设置,不能申请"); var model = _mapper.Map(delaydto); model.EmployeeId = _sessionContext.UserId; model.ApplyOrgName = _sessionContext.OrgName; model.ApplyOrgCode = _sessionContext.OrgId; 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, false)?.EndTime; //todo } model.ApplyDelayTime = DateTime.Now; model.No = order.No; model.InitId(); if (dto.Data.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted); await _orderDelayRepository.AddAsync(model, HttpContext.RequestAborted); try { var startDto = _mapper.Map(dto.Workflow); startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderDelay; startDto.Title = model.DelayReason; string workFlowId = await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted); model.WorkflowId = workFlowId; await _orderDelayRepository.UpdateAsync(model, HttpContext.RequestAborted); } catch (Exception ex) { await _orderDelayRepository.RemoveAsync(model.Id, false, HttpContext.RequestAborted); throw new UserFriendlyException($"工单延期流程失败!, {ex.Message}", "工单延期流程失败"); } } /// /// 延期列表 /// /// //[Permission(EPermission.DelayList)] [HttpGet("delay")] public async Task> DelayList([FromQuery] DelayListDto dto) { var (total, items) = await _orderDelayRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.Employee) .Includes(x => x.Workflow) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!)) .WhereIF(dto.IsApply==true, x => x.DelayState != EDelayState.Examining) .WhereIF(dto.IsApply==false, x => x.DelayState == EDelayState.Examining) .WhereIF(dto.DelayState != null, x => x.DelayState == dto.DelayState) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 延期详情 /// /// /// //[Permission(EPermission.DelayEntity)] [HttpGet("delay/{id}")] public async Task DelayEntity(string id) { var model = await _orderDelayRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.Employee) .Includes(x => x.Workflow) .FirstAsync(x => x.Id == id); var rspModel = _mapper.Map(model); rspModel.IsCanHandle = model.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId); var files = await _fileRepository.Queryable().Where(x => x.Key == rspModel.Id && string.IsNullOrEmpty(x.FlowKey)).ToListAsync(); if (files.Any()) rspModel.Files = _mapper.Map>(files); return rspModel; } /// /// 计算期满时间 /// /// /// [HttpPost("delay/calc-endtime")] public async Task DelayCalcEndTime([FromBody] DelayCalcEndTimeDto dto) { return _timeLimitDomainService.CalcEndTime(dto.BeginTime, dto.DelayUnit, dto.DelayNum, false); } /// /// 查询工单延期流程开启参数 /// /// [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.MayOrderScreenList)] [HttpGet("mayscreen")] public async Task> MayScreenList([FromQuery] MayScreenListDto dto) { var query = _orderVisitedDetailRepository.Queryable() .Includes(x => x.OrderVisit) .Includes(x => x.OrderVisit, y => y.Order) .Includes(x => x.OrderVisit, y => y.Employee) .Where(x => x.OrderVisit.VisitState != EVisitState.None && x.OrderVisit.IsCanHandle); if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter) { query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrderVisit.Order.Title.Contains(dto.Keyword!) || x.OrderVisit.Order.No.Contains(dto.Keyword!)) .Where(x => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode.StartsWith(_sessionContext.OrgId) && ( SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2" )); } else { query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrderVisit.Order.Title.Contains(dto.Keyword!) || x.OrderVisit.Order.No.Contains(dto.Keyword!)) .Where(x => x.VisitTarget == EVisitTarget.Org && ( SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2" )); } var (total, items) = await query .OrderBy(x => 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 query = _orderScreenRepository.Queryable() .Includes(x => x.Order) .Includes(x => x.VisitDetail) .Includes(x => x.Visit, d => d.Order) .Includes(x => x.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(x => (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval) && SqlFunc.JsonListObjectAny(x.Workflow.HandlerUsers, "Key", _sessionContext.RequiredUserId)); } 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), x => x.OrderId == dto.OrderId) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 开始工单甄别流程 /// [Permission(EPermission.ApplyScreen)] [HttpPost("screen/startflow")] public async Task StartFlow([FromBody] ScreenStartFlowDto dto) { var screenAny = await _orderScreenRepository.AnyAsync(x => x.VisitDetailId == dto.Data.VisitDetailId && (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval)); if (screenAny) throw UserFriendlyException.SameMessage("该工单已提起甄别申请,正在审批过程中,不能申请"); var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ScreenApplyNum); int count = await _orderScreenRepository.CountAsync(x => x.OrderId == dto.Data.OrderId && x.Status == EScreenStatus.Refuse); if (count > int.Parse(setting?.SettingValue[0])) throw UserFriendlyException.SameMessage("甄别申请已超过系统预定设置,不能申请"); var visit = await _orderVisitRepository.GetAsync(dto.Data.VisitId, HttpContext.RequestAborted); setting = _systemSettingCacheManager.GetSetting(SettingConstants.ScreenApplyEndTime); var endTime = _timeLimitDomainService .CalcEndTime(visit.VisitTime.Value, ETimeType.WorkDay, int.Parse(setting?.SettingValue[0]), false).EndTime; if (DateTime.Now > endTime) throw UserFriendlyException.SameMessage("甄别申请时限已超过系统预定设置,不能申请"); var model = _mapper.Map(dto.Data); model.Status = EScreenStatus.Apply; model.ApplyEndTime = endTime; model.InitId(); if (dto.Data.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted); await _orderScreenRepository.AddAsync(model, HttpContext.RequestAborted); var workflowId = string.Empty; try { await _orderRepository.OrderScreenRevisionVisit(visit.Id, false, HttpContext.RequestAborted); var startDto = _mapper.Map(dto.Workflow); startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderScreen; startDto.Title = dto.Data.Content; workflowId = await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted); var screen = await _orderScreenRepository.GetAsync(model.Id, HttpContext.RequestAborted); if (screen != null) { screen.WorkflowId = workflowId; await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted); } } catch (Exception e) { await _orderScreenRepository.RemoveAsync(model.Id); model.Id = string.Empty; throw new UserFriendlyException($"工单开启甄别流程失败!, {e.Message}", "工单开启甄别流程失败"); } } /// /// 查询工单甄别流程开启参数 /// /// [HttpGet("screen/startflow")] public async Task GetScreenFlowStartOptionsAsync() { //return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.OrderScreen, // HttpContext.RequestAborted); return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderScreen, HttpContext.RequestAborted); } /// /// 查询工单甄别流程参数 /// /// [HttpGet("screen/workflow/{id}")] public async Task GetScreenWorkFlowAsync(string id) { var workflow = await _workflowRepository.Queryable().FirstAsync(x => x.ExternalId == id); return workflow.Id; } /// /// 列表页面基础数据 /// /// [HttpGet("screen/base")] public async Task ScreenBaseData() { var rsp = new { ScreenStatus = EnumExts.GetDescriptions(), ScreenType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ScreenType), }; return rsp; } /// /// 甄别详情 /// /// /// [HttpGet("screen/{id}")] public async Task ScreenEntity(string id) { var model = await _orderScreenRepository.Queryable() .Includes(x => x.Workflow) .Includes(x => x.Visit, d => d.Order) .FirstAsync(x => x.Id == id); var rspModel = _mapper.Map(model); rspModel.IsCanHandle = model.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId); var files = await _fileRepository.Queryable().Where(x => x.Key == rspModel.Id && string.IsNullOrEmpty(x.FlowKey)).ToListAsync(); if (files.Any()) rspModel.Files = _mapper.Map>(files); 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")] 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) { //TODO 发送短信 } //推省上 if (!string.IsNullOrEmpty(model.Id) && order.Source == ESource.ProvinceStraight) { var orderDto = _mapper.Map(order); var supervise = await _orderSuperviseRepository.GetAsync(x => x.Id == model.Id); if (supervise != null) { var superviseDto = _mapper.Map(supervise); //_capPublisher.Publish(EventNames.HotlineOrderSuperviseCourse, new PublishSuperviseDto() //{ // Order = orderDto, // Supervise = superviseDto, // ClientGuid = "" //}); await _provinceService.SendSuperviseProcessInfo(new PublishSuperviseDto() { Order = orderDto, Supervise = superviseDto, ClientGuid = "" }, HttpContext.RequestAborted); } } } } /// /// 回复督办 /// /// /// [HttpPost("supervise/reply")] public async Task ReplySupervise([FromBody] ReplyOrderSuperviseDto dto) { //验证是否存在督办 var supervise = await _orderSuperviseRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (supervise is null) throw UserFriendlyException.SameMessage("无效督办"); if (supervise.State > 0) throw UserFriendlyException.SameMessage("督办已回复,请勿重复回复"); _mapper.Map(dto, supervise); supervise.ReplyId = _sessionContext.UserId; supervise.ReUser = _sessionContext.UserName; supervise.ReplyTime = DateTime.Now; supervise.State = 1; if (dto.Files.Any()) supervise.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, supervise.Id, "", HttpContext.RequestAborted); await _orderSuperviseRepository.UpdateAsync(supervise, HttpContext.RequestAborted); var order = await _orderRepository.GetAsync(supervise.OrderId, HttpContext.RequestAborted); //推省上 if (order != null && order.Source == ESource.ProvinceStraight) { var orderDto = _mapper.Map(order); var superviseDto = _mapper.Map(supervise); //_capPublisher.Publish(EventNames.HotlineOrderSuperviseCourse, new PublishSuperviseDto() //{ // Order = orderDto, // Supervise = superviseDto, // ClientGuid = "" //}); await _provinceService.SendSuperviseProcessInfo(new PublishSuperviseDto() { Order = orderDto, Supervise = superviseDto, ClientGuid = "" }, HttpContext.RequestAborted); } } /// /// 签收督办 /// /// /// [HttpPost("supervise/sign")] public async Task SignSupervise([FromBody] SignOrderSuperviseDto dto) { //验证是否存在督办 var supervise = await _orderSuperviseRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (supervise is null) throw UserFriendlyException.SameMessage("无效督办"); //supervise.State = 2; supervise.SignTime = DateTime.Now; supervise.SignUser = _sessionContext.UserName; await _orderSuperviseRepository.UpdateAsync(supervise, HttpContext.RequestAborted); var order = await _orderRepository.GetAsync(supervise.OrderId, HttpContext.RequestAborted); //推省上 if (order != null && order.Source == ESource.ProvinceStraight) { var orderDto = _mapper.Map(order); var superviseDto = _mapper.Map(supervise); //_capPublisher.Publish(EventNames.HotlineOrderSuperviseCourse, new PublishSuperviseDto() //{ // Order = orderDto, // Supervise = superviseDto, // ClientGuid = "" //}); await _provinceService.SendSuperviseProcessInfo(new PublishSuperviseDto() { Order = orderDto, Supervise = superviseDto, ClientGuid = "" }, HttpContext.RequestAborted); } } /// /// 督办详情 /// /// /// [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); var files = await _fileRepository.Queryable().Where(x => x.Key == orderSupervise.Id).ToListAsync(); if (files.Any()) { var applyFiles = files.Where(x => x.Classify == "督办申请").ToList(); if (applyFiles.Any()) orderSuperviseDto.Files = _mapper.Map>(applyFiles); var replyFiles = files.Where(x => x.Classify == "督办回复").ToList(); if (replyFiles.Any()) orderSuperviseDto.ReplyFiles = _mapper.Map>(replyFiles); } } 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")] 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) { //TODO 发送短信 } //推省上 if (!string.IsNullOrEmpty(model.Id) && order.Source == ESource.ProvinceStraight) { var orderDto = _mapper.Map(order); var urge = await _orderUrgeRepository.GetAsync(x => x.Id == model.Id); if (urge != null) { var urgeDto = _mapper.Map(urge); //_capPublisher.Publish(EventNames.HotlineOrderSuperviseCourse, new PublishUrgeDto() //{ // Order = orderDto, // Urge = urgeDto, // ClientGuid = "" //}); } } } } /// /// 回复催办 /// /// /// [HttpPost("urge/reply")] 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")] 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); var files = await _fileRepository.Queryable().Where(x => x.Key == orderUrge.Id).ToListAsync(); if (files.Any()) orderUrgeDto.Files = _mapper.Map>(files); } return orderUrgeDto; } #endregion #region 工单办理 /// /// 工单列表 /// /// /// [Permission(EPermission.OrderQuery)] [HttpGet] public async Task> Query([FromQuery] QueryOrderDto dto) { var (total, items) = await _orderRepository.Queryable(workflowFilter: false) .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 => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode))) .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.Workflow.ActualHandleOrgCode)) .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo!) || d.AcceptorStaffNo.Contains(dto.NameOrNo!)) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel)) .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.FromPhone.Contains(dto.PhoneNo!) || d.Contact.Contains(dto.PhoneNo!)) .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status)) .WhereIF(dto.Statuses.Any(d => d == EOrderStatus.BackToUnAccept), d => d.Status <= EOrderStatus.BackToUnAccept) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 历史工单 /// /// /// [HttpGet("history")] public async Task> Query([FromQuery] QueryOrderHistoryDto dto) { var (total, items) = await _orderRepository.Queryable() .Where(d => d.FromPhone == dto.PhoneNo) .WhereIF(!string.IsNullOrEmpty(dto.OrderId), d => d.Id != dto.OrderId) .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(workflowFilter: false) .Includes(d => d.Acceptor) .Includes(d => d.OrderExtension) .Includes(d => d.OrderDelays) .Includes(d => d.OrderScreens) .Includes(d => d.OrderVisits, x => x.OrderVisitDetails) .FirstAsync(d => d.Id == id); if (order == null) return new(); var canHandle = false; if (!string.IsNullOrEmpty(order?.WorkflowId)) { var (workflow, handlePermission) = await _workflowDomainService.GetWorkflowHandlePermissionAsync( order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, withSteps: true, withSupplements: true, cancellationToken: HttpContext.RequestAborted); order.Workflow = workflow; canHandle = handlePermission; await _mediator.Publish(new GetOrderDetailNotify(order.Workflow, _sessionContext.RequiredUserId, _sessionContext.UserName, _sessionContext.RequiredOrgId, _sessionContext.OrgName, _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName)); } var dto = _mapper.Map(order!); var files = await _fileRepository.Queryable().Where(x => x.Key == dto.Id && x.Classify == "受理上传" && string.IsNullOrEmpty(x.FlowKey)).ToListAsync(); dto.Files = _mapper.Map>(files); var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == order.CallId).FirstAsync(); if (call != null) dto.RecordingFileUrl = call.RecordingFileUrl; if (order?.Workflow != null) dto.Workflow.CanHandle = canHandle; 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] public async Task Add([FromBody] AddOrderDto dto) { //todo dto validation 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, 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); } //内容分词 await _orderRepository.OrderParticiple(dto.Content, order.Id, HttpContext.RequestAborted); return order.Id; } /// /// 删除工单 /// /// /// [HttpDelete("{id}")] 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] public async Task Update([FromBody] UpdateOrderDto dto) { var order = await _orderRepository.Queryable() .FirstAsync(d => d.Id == dto.Id); if (order == null) throw UserFriendlyException.SameMessage("无效工单编号"); if (order.Status > EOrderStatus.BackToUnAccept) throw UserFriendlyException.SameMessage("工单已发起流程"); if (order.Content != dto.Content) await _orderRepository.OrderParticiple(dto.Content, dto.Id, HttpContext.RequestAborted); if (dto.RepeatableEventDetails?.Any() ?? false) { var reAdds = dto.RepeatableEventDetails.Where(x => string.IsNullOrEmpty(x.OrderId) && !x.IsDeleted) .ToList(); var reDeletes = dto.RepeatableEventDetails.Where(x => !string.IsNullOrEmpty(x.OrderId) && x.IsDeleted) .ToList(); reAdds.ForEach(x => x.OrderId = dto.Id); List repeatables = _mapper.Map>(reAdds); await _repeatableEventDetailRepository.AddRangeAsync(repeatables, HttpContext.RequestAborted); if (reDeletes?.Any() ?? false) { await _repeatableEventDetailRepository.DeleteAsync(reDeletes, HttpContext.RequestAborted); } } _mapper.Map(dto, order); if (dto.Files.Any()) order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, "", HttpContext.RequestAborted); await _orderRepository.UpdateNav(order).Include(d => d.OrderExtension).ExecuteCommandAsync(); } /// /// 开始工单办理流程 /// [HttpPost("startflow")] public async Task StartFlow([FromBody] OrderStartFlowDto dto) { var id = dto.Data.Id; var isAdd = string.IsNullOrEmpty(dto.Data.Id); if (isAdd) { id = await Add(dto.Data); } else { await Update(dto.Data); } try { //期满时间 var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.Day, 1, true); var startDto = _mapper.Map(dto.Workflow); startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderHandle; startDto.Title = dto.Data.Title; await _workflowApplication.StartWorkflowAsync(startDto, id, expiredTime, HttpContext.RequestAborted); } catch (Exception e) { if (isAdd) await Remove(id); throw new UserFriendlyException($"工单开启流程失败!, {e.Message}", "工单开启流程失败"); } } /// /// 查询工单办理流程开启参数 /// /// [HttpGet("startflow")] public async Task GetFlowStartOptions() { //return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.OrderHandle, // HttpContext.RequestAborted); return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderHandle, HttpContext.RequestAborted); } /// /// 查询工单办理的期满时间配置 /// [HttpGet("time-config")] public async Task GetOrderHandleTimeConfig(EFlowDirection flowDirection, string? acceptType) { switch (flowDirection) { case EFlowDirection.CenterToOrg: return new TimeConfig { Count = 3, TimeType = ETimeType.Day }; case EFlowDirection.OrgToCenter: return new TimeConfig { Count = 1, TimeType = ETimeType.Day }; default: throw new ArgumentOutOfRangeException(nameof(flowDirection), flowDirection, null); } } /// /// 列表页面基础数据 /// /// [HttpGet("base-data")] public async Task BaseData() { var rsp = new { AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType), ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel), OrgsOptions = await _organizeRepository.GetOrgJson(), EmergencyLevelOptions = EnumExts.GetDescriptions(), PushTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PushType), OrderStatusOptions = EnumExts.GetDescriptions(), }; return rsp; } /// /// 新增页面基础数据 /// /// [HttpGet("base-data-add")] public async Task BaseDataAdd() { var rsp = new { ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel), AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType), EmergencyLevelOptions = EnumExts.GetDescriptions(), PushTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PushType), GenderOptions = EnumExts.GetDescriptions(), IdentityTypeOptions = EnumExts.GetDescriptions(), LicenceTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.LicenceType), AgeRangeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AgeRange), OrderTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.OrderType), }; return rsp; } /// /// 扩展信息新增页面基础数据 /// /// [HttpGet("base-data-ext")] public async Task BaseDataExtension() { var rsp = new { LicenceTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.LicenceType), IdentityTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProviderIdentityType), IdentityOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Identity), NationalityOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Nationality), NationOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Nation), MarketTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.MarketType), IndustryClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.IndustryClassify), BrandOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Brand), ObjectClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ObjectClassify), ComplainClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ComplainClassify), ReportClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ReportClassify), SalesModeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SalesMode), ECommercePlatformOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ECommercePlatform), PatentTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PatentType), AffairTargetOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AffairTarget), ComplainTypeOptions = EnumExts.GetDescriptions().Select(d => new Kv(d.Key.ToString(), d.Value)), SalesChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SalesChannel), }; return rsp; } /// /// 扩展信息新增页面基础数据 /// /// [HttpPost("order_repeatable_event")] public async Task RepeatableEvent(QueryRepeatableEventDto dto) { var exp = Expressionable.Create() .OrIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), x => x.HotspotSpliceName.EndsWith(dto.HotspotSpliceName!)) .OrIF(!string.IsNullOrEmpty(dto.Address), x => x.Address != null && x.Address.EndsWith(dto.Address!)); var count = await _orderRepository.Queryable() .Where(exp.ToExpression()) .Where(d => d.CreationTime.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd")) .CountAsync(); var setting = _systemSettingCacheManager.GetSetting(SettingConstants.RepeatableEventNum); return count >= int.Parse(setting?.SettingValue[0] ?? "0"); } #endregion #region 工单待办 /// /// 查询待办工单 /// [HttpGet("waited")] public async Task> QueryWaited([FromQuery] QueryOrderWaitedDto dto) { EWorkflowStepStatus[] handleStatuses = Array.Empty(); if (dto.IsHandled.HasValue) handleStatuses = dto.IsHandled.Value ? new[] { EWorkflowStepStatus.Handled } : new[] { EWorkflowStepStatus.WaitForAccept, EWorkflowStepStatus.WaitForHandle }; var (total, items) = await _orderRepository.Queryable(workflowFilter: false) .Includes(d => d.Workflow, x => x.Steps) .Where(d => SqlFunc.JsonListObjectAny(d.Workflow.HandlerUsers, "Key", _sessionContext.RequiredUserId) || SqlFunc.JsonListObjectAny(d.Workflow.HandlerOrgs, "Key", _sessionContext.RequiredOrgId)) .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince) .WhereIF(dto.IsHandled.HasValue, d => d.Workflow.Steps.Any(x => handleStatuses.Contains(x.Status))) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.No.Contains(dto.Keyword) || d.Title.Contains(dto.Keyword)) .OrderByDescending(d => d.ExpiredTime) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 查询坐席待办 /// [HttpGet("waited/sign")] public async Task> QueryWaitedForSeat([FromQuery] QueryOrderWaitedDto dto) { EOrderStatus[] handleStatuses = EnumExts.GetFields().Select(d => (EOrderStatus)d.Key).ToArray(); handleStatuses = handleStatuses.WhereIF(dto.IsHandled.HasValue, d => dto.IsHandled!.Value ? d is not EOrderStatus.WaitForAccept and not EOrderStatus.BackToUnAccept : d is EOrderStatus.WaitForAccept or EOrderStatus.BackToUnAccept) .ToArray(); var (total, items) = await _orderRepository.Queryable(workflowFilter: 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) .OrderByDescending(d => d.ExpiredTime) .ToPagedListAsync(dto, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 工单退回 /// /// 工单退回列表 /// /// /// [Permission(EPermission.SendBackOrderList)] [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)); } /// /// 退回申请 /// /// /// [Permission(EPermission.ApplySendBack)] [HttpPost("send_back/apply")] public async Task ApplyUrge([FromBody] OrderSendBackAddDto dto) { //验证工单是否可以申请 var order = await _orderRepository.GetAsync(dto.OrderId, HttpContext.RequestAborted); if (order is null) throw UserFriendlyException.SameMessage("无效工单"); if ((int)order.Status > 1) throw UserFriendlyException.SameMessage("工单状态无效,请确认当前工单状态"); if ((int)order.Source <= 1) 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 = await _orderRepository.GetAsync(dto.OrderId, HttpContext.RequestAborted); order.Status = EOrderStatus.BackToProvince; await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); } } /// /// 退回审核 /// /// /// [Permission(EPermission.AuditSendBack)] [HttpPost("send_back/audit")] 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); //_capPublisher.Publish(EventNames.HotlineOrderSendBackApplyed, // new PublishOrderSendBackDto() { Order = OrderDto, SendBack = sendBackDto, ClientGuid = "" }); await _provinceService.GetCaseBackApply( new PublishOrderSendBackDto { Order = OrderDto, SendBack = sendBackDto, ClientGuid = "" }, HttpContext.RequestAborted); } } /// /// 退回详情 /// /// /// [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")] 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 model = _mapper.Map(dto); model.OrgId = _sessionContext.OrgId; model.OrgName = _sessionContext.OrgName; if (!dto.Audit) model.State = 1; model.InitId(); if (dto.Files.Any()) model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", HttpContext.RequestAborted); await _orderSpecialRepository.AddAsync(model, HttpContext.RequestAborted); if (model.State == 1) { var recall = new RecallDto { WorkflowId = dto.WorkflowId!, NextStepCode = dto.NextStepCode, NextStepName = dto.NextStepName, NextHandlers = dto.NextHandlers, Opinion = dto.Cause }; if (dto.AlterTime) recall.External = new External { TimeLimit = dto.TimeLimit, TimeLimitUnit = dto.TimeLimitUnit }; //if (dto.Files.Any()) recall.Files = dto.Files; await _workflowApplication.RecallAsync(recall, HttpContext.RequestAborted); var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == dto.OrderId) ; if (publish != null) { var publishHistory = _mapper.Map(publish); await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted); await _orderPublishRepository.RemoveAsync(publish,false, HttpContext.RequestAborted); } var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == dto.OrderId); if (visit != null) { visit.VisitState = EVisitState.None; await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); } } } /// /// 审批工单特提信息 /// /// /// [Permission(EPermission.AuditSpecial)] [HttpPut("special")] public async Task Update([FromBody] AuditOrderSpecialDto dto) { var special = await _orderSpecialRepository.GetAsync(dto.Id); if (special is null) throw UserFriendlyException.SameMessage("无效特提审批信息!"); if (special.State != 0) throw UserFriendlyException.SameMessage("无效特提审批信息,特提审批信息错误,该信息已审核!"); _mapper.Map(dto, special); if (dto.Files.Any()) special.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, special.Id, "", HttpContext.RequestAborted); await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted); if (special.State == 1) { var recall = new RecallDto { WorkflowId = dto.WorkflowId!, NextStepCode = dto.NextStepCode, NextStepName = dto.NextStepName, NextHandlers = dto.NextHandlers, Opinion = dto.Opinion }; if (dto.AlterTime) recall.External = new External { TimeLimit = dto.TimeLimit, TimeLimitUnit = dto.TimeLimitUnit }; //if (dto.Files.Any()) recall.Files = dto.Files; await _workflowApplication.RecallAsync(recall, HttpContext.RequestAborted); var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == special.OrderId); if (publish != null) { var publishHistory = _mapper.Map(publish); await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted); await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted); } var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == special.OrderId); if (visit != null) { visit.VisitState = EVisitState.None; await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted); } } } /// /// 获取工单特提信息列表 /// /// /// [Permission(EPermission.SpecialOrderList)] [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.ApplySpecialOrderList)] [HttpGet("special/apply_list")] public async Task> SpecialList([FromQuery] QueryOrderDto dto) { var query = _orderRepository.Queryable() .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!)) .WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!)) .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType)) .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannel)) .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone!)) .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.Workflow.ActualHandleOrgCode)) .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo!) || d.AcceptorStaffNo.Contains(dto.NameOrNo!)) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel)) .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.FromPhone.Contains(dto.PhoneNo!) || d.Contact.Contains(dto.PhoneNo!)) .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status)) .WhereIF(dto.Statuses.Any(d => d == EOrderStatus.BackToUnAccept), d => d.Status <= EOrderStatus.BackToUnAccept); if (!_sessionContext.OrgIsCenter && _sessionContext.OrgId.Length >= 6) { var oneCode = _sessionContext.OrgId.Substring(0, 6); query = query.Where(x => x.AcceptorOrgCode.StartsWith(oneCode) && !x.AcceptorOrgCode.StartsWith(_sessionContext.OrgId)); } var (total, items) = await query .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取工单特提信息 /// /// /// [HttpGet("special/{id}")] public async Task SpecialEntity(string id) { var item = await _orderSpecialRepository.Queryable() .Includes(x => x.Order) .FirstAsync(x => x.Id == id); var itemDto = new OrderSpecialDto(); if (item != null) { itemDto = _mapper.Map(item); var files = await _fileRepository.Queryable().Where(x => x.Key == item.Id).ToListAsync(); if (files.Any()) itemDto.Files = _mapper.Map>(files); } return itemDto; } /// /// 列表页面基础数据 /// /// [HttpGet("special/base/{id}")] public async Task SpecialBaseData(string id) { var rsp = new { SpecialTimeType = EnumExts.GetDescriptions(), SpecialReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SpecialReason), Step = await _workflowApplication.GetRecallStepsAsync(id, HttpContext.RequestAborted) }; return rsp; } /// /// 获取办理时限 /// /// /// [HttpGet("special/handle_time")] public async Task SpecialHandleTime([FromQuery] OrderSpecialHandleTime dto) { var order = await _orderRepository.GetAsync(dto.OrderId); if (dto.FlowDirection != null && dto.FlowDirection == EFlowDirection.OrgToCenter) return _timeLimitDomainService.GetOrderTimeLimitConfig(string.Empty); return _timeLimitDomainService.GetOrderTimeLimitConfig(order.AcceptTypeCode); } #endregion #region 市民信息 /// /// 新增市民信息 /// /// /// [HttpPost("citizen")] 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")] public async Task Delete([FromBody] CitizenDeleteDto dto) { await _citizenRepository.RemoveAsync(x => x.Id == dto.Id); } /// /// 更新市民信息 /// /// /// [Permission(EPermission.UpdateCitizen)] [HttpPut("citizen")] 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() .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取市民信息 /// /// /// [HttpGet("citizen/{id}")] public async Task CitizenEntity(string id) { return await _citizenRepository.Queryable() .Includes(x => x.labelDetails) .FirstAsync(x => x.Id == id); } /// /// 获取市民信息 /// /// /// [HttpGet("citizen_phone/{phone}")] public async Task Citizen(string phone) { //市民基本信息 var citizen = await _citizenRepository.Queryable() .Includes(x => x.labelDetails) .FirstAsync(x => x.PhoneNumber == phone); //工单历史 var oders = await _orderRepository.Queryable().Where(x => x.Contact == phone) .OrderBy(x => x.CreationTime, OrderByType.Desc).ToListAsync(); var allOrderNum = oders.Count; var endOrderNum = oders.Count(x => x.Status == EOrderStatus.Published || x.Status == EOrderStatus.Visited || x.Status == EOrderStatus.Filed); var handOrderNum = oders.Count(x => x.Status == EOrderStatus.Handling || x.Status == EOrderStatus.Countersigning); var DissatisfactionNum = await _orderVisitedDetailRepository.Queryable() .Includes(x => x.OrderVisit) .Where(x => SqlFunc.JsonField(x.OrgProcessingResults, "Value") == "不满意" || SqlFunc.JsonField(x.OrgProcessingResults, "Value") == "非常不满意") .Distinct().Select(s => new { s.OrderVisit.OrderId }).CountAsync(); //来电历史 //TODO 等待通讯对接完成 还缺少 上次来电时间 //关注诉求 var hotspotNames = string.Join(",", oders.Select(x => x.HotspotName).Distinct().Take(5).ToList()); var rsp = new { Citizen = citizen, LastCallTime = DateTime.Now, Order = new { allOrderNum = allOrderNum, endOrderNum = endOrderNum, handOrderNum = handOrderNum, DissatisfactionNum = DissatisfactionNum }, CallHistory = new { AllCallNum = 0, ConnectNum = 0, CallBackNum = 0 }, HotspotNames = hotspotNames, }; return rsp; } /// /// 新增市民标签信息 /// /// /// [HttpPost("citizen_label")] public async Task Add([FromBody] LabelDetailAddDto dto) { var label = await _labelDetailRepository.CountAsync(x => x.CitizenId == dto.CitizenId && x.Label == dto.Label, HttpContext.RequestAborted); if (label > 0) throw UserFriendlyException.SameMessage("市民联系标签信息重复"); await _citizenRepository.LabelAddAsync(dto, HttpContext.RequestAborted); } /// /// 删除市民标签信息 /// /// /// [HttpDelete("citizen_label")] public async Task Delete([FromBody] LabelDetailDeleteDto dto) { var label = await _labelDetailRepository.GetAsync(x => x.Id == dto.Id, HttpContext.RequestAborted); if (label == null || (label.CreatorName != _sessionContext.UserName)) throw UserFriendlyException.SameMessage("市民联系标签信息错误"); await _citizenRepository.LabelDeleteAsync(label, HttpContext.RequestAborted); } /// /// 获取市民标签信息列表 /// /// /// [HttpGet("citizen_label/list")] public async Task> List([FromQuery] CitizenQueryDto dto) { var (total, items) = await _labelDetailRepository.Queryable() .Includes(x => x.Citizen) .WhereIF(!string.IsNullOrEmpty(dto.Label), x => x.Label.Contains(dto.Label!)) .WhereIF(!string.IsNullOrEmpty(dto.CreatorName), x => x.CreatorName != null && x.CreatorName.Contains(dto.CreatorName!)) .Where(x => x.CitizenId == dto.CitizenId) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } #endregion #region 重复性事件 /// /// 新增重复性事件 /// /// /// [HttpPost("repeatable_event")] 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")] 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}")] public async Task Delete([FromBody] string id) { await _repeatableEventDetailRepository.RemoveAsync(x => x.Id == id); } /// /// 更新重复性事件 /// /// /// [Permission(EPermission.UpdateRepeatableEvent)] [HttpPut("repeatable_event")] public async Task Update([FromBody] RepeatableEventUpdateDto dto) { var repeatable = await _repeatableEventRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (repeatable is null) throw UserFriendlyException.SameMessage("无效重复性事件"); _mapper.Map(dto, repeatable); repeatable.LastModificationName = _sessionContext.UserName; await _repeatableEventRepository.UpdateAsync(repeatable, HttpContext.RequestAborted); List detail; if (dto.Details.Any()) dto.Details.ForEach(x => x.RepeatableId = dto.Id); await _repeatableEventDetailRepository.DeleteAsync(dto.Id, HttpContext.RequestAborted); detail = _mapper.Map>(dto.Details); if (detail.Any()) await _repeatableEventDetailRepository.AddRangeAsync(detail, HttpContext.RequestAborted); } /// /// 获取重复性事件列表 /// /// /// [HttpGet("repeatable_event/list")] public async Task> List([FromQuery] RepeatableEventListDto dto) { var (total, items) = await _repeatableEventRepository.Queryable() .Includes(x => x.Details) .Includes(x => x.Details, y => y.Order) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || (d.KeyWords != null && d.KeyWords.Contains(dto.Keyword!))) .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) .WhereIF(!string.IsNullOrEmpty(dto.Code), x => x.Code != null && x.Code.Contains(dto.Code!)) .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Contains(dto.Title!)) .WhereIF(!string.IsNullOrEmpty(dto.KeyWords), x => x.KeyWords != null && x.KeyWords.Contains(dto.KeyWords!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取重复性事件 /// /// /// [HttpGet("repeatable_event")] public async Task CitizenEntity([FromQuery] RepeatableEventEntityDto dto) { return await _repeatableEventRepository.Queryable() .Includes(x => x.Details.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!)) .ToList()) .Includes(x => x.Details, y => y.Order) .FirstAsync(x => x.Id == dto.Id); } #endregion #region 工单词库 /// /// 新增工单词库 /// /// /// [Permission(EPermission.AddOrderWord)] [HttpPost("order_word")] public async Task Add([FromBody] OrderWordAddDto dto) { var word = _mapper.Map(dto); await _orderWrodRepository.AddAsync(word, HttpContext.RequestAborted); } /// /// 删除工单词库 /// /// /// [Permission(EPermission.DeleteOrderWord)] [HttpDelete("order_word")] public async Task Delete([FromBody] OrderWordDeleteDto dto) { await _orderRepository.RemoveOrderWrodBatchAsync(dto.Ids, HttpContext.RequestAborted); } /// /// 更新工单词库 /// /// /// [Permission(EPermission.UpdateOrderWord)] [HttpPut("order_word")] 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")] 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")] public async Task Delete([FromBody] OrderObserveDeleteDto dto) { await _orderRepository.RemoveOrderObserveBatchAsync(dto.Ids, HttpContext.RequestAborted); } /// /// 更新工单观察 /// /// /// [HttpPut("order_observe")] 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")] 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")] public async Task Delete([FromBody] OrderFinalityDeleteDto dto) { await _orderRepository.RemoveOrderFinalityBatchAsync(dto.Ids, HttpContext.RequestAborted); } /// /// 更新工单终结 /// /// /// [HttpPut("order_finality")] public async Task Update([FromBody] OrderFinalityUpdateDto dto) { var word = await _orderFinalityRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (word is null) throw UserFriendlyException.SameMessage("无效工单观察"); _mapper.Map(dto, word); await _orderFinalityRepository.UpdateAsync(word, HttpContext.RequestAborted); } /// /// 获取工单终结列表 /// /// /// [HttpGet("order_finality/list")] public async Task> List([FromQuery] OrderFinalityListDto dto) { var (total, items) = await _orderFinalityRepository.Queryable() .Includes(x => x.Order) .WhereIF(dto.IsProvince.HasValue, x => x.Order.IsProvince == dto.IsProvince) .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.No.Contains(dto.Keyword!) || x.Order.Title.Contains(dto.Keyword!)) //.WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title!)) //.WhereIF(!string.IsNullOrEmpty(dto.No), x => x.Order.No.Contains(dto.No!)) .OrderByDescending(x => x.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 获取工单终结 /// /// /// [HttpGet("order_finality/{id}")] public async Task OrderFinalityEntity(string id) { return await _orderFinalityRepository.Queryable() .FirstAsync(x => x.Id == id); } #endregion #region 超期查询 /// /// 工单即将超期列表 /// /// /// [HttpGet("order/about_expire/list")] public async Task> AboutList([FromQuery] AboutToExpireListDto dto) { return await _orderRepository.GetAboutToExpireAsync(dto, HttpContext.RequestAborted); } ///// ///// 工单即将超期节点列表 ///// ///// ///// //[HttpGet("order/about_expire_node/list")] //public async Task> AboutNodeList([FromQuery] AboutToExpireListDto dto) //{ // return await _orderRepository.GetAboutToExpireNodeAsync(dto, HttpContext.RequestAborted); //} /// /// 工单超期列表 /// /// /// [HttpGet("order/expire/list")] public async Task> List([FromQuery] AboutToExpireListDto dto) { return await _orderRepository.GetToExpireAsync(dto, HttpContext.RequestAborted); } ///// ///// 工单超期节点列表 ///// ///// ///// //[HttpGet("order/expire_node/list")] //public async Task> NodeList([FromQuery] AboutToExpireListDto dto) //{ // return await _orderRepository.GetToExpireNodeAsync(dto, HttpContext.RequestAborted); //} #endregion #region 工单签收 /// /// 工单签收 /// [HttpPost("sign/{orderId}")] public async Task Sign(string orderId) { var order = await _orderRepository.GetAsync(orderId, HttpContext.RequestAborted); if (order == null) throw new UserFriendlyException($"无效工单编号, orderId: {orderId}", "无效工单编号"); if (order.IsSigned()) throw new UserFriendlyException("该工单已被签收"); order.Sign(_sessionContext.RequiredUserId, _sessionContext.UserName); await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted); } #endregion }