using DotNetCore.CAP; using Hotline.Application.Quality; using Hotline.FlowEngine.Notifications; using Hotline.FlowEngine.WorkflowModules; using Hotline.FlowEngine.Workflows; using Hotline.KnowledgeBase; using Hotline.Orders; using Hotline.Settings; using Hotline.Settings.TimeLimits; using Hotline.Share.Dtos.FlowEngine.Workflow; using Hotline.Share.Dtos.Order; using Hotline.Share.Dtos.Settings; using Hotline.Share.Enums.FlowEngine; using Hotline.Share.Enums.Order; using Hotline.Share.Enums.Quality; using Hotline.Share.Mq; using MapsterMapper; using MediatR; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using XF.Domain.Repository; namespace Hotline.Application.Handlers.FlowEngine; public class WorkflowNextHandler : INotificationHandler { private readonly IOrderDomainService _orderDomainService; private readonly IKnowledgeDomainService _knowledgeDomainService; private readonly IOrderRepository _orderRepository; private readonly ITimeLimitDomainService _timeLimitDomainService; private readonly IWorkflowDomainService _workflowDomainService; private readonly ICapPublisher _capPublisher; private readonly IMapper _mapper; private readonly ILogger _logger; private readonly IOrderScreenRepository _orderScreenRepository; private readonly IQualityApplication _qualityApplication; private readonly IOrderDelayRepository _orderDelayRepository; private readonly IKnowledgeRepository _knowledgeRepository; private readonly IKnowledgeWorkFlowRepository _knowledgeWorkFlowRepository; public WorkflowNextHandler( IOrderDomainService orderDomainService, IKnowledgeDomainService knowledgeDomainService, IOrderRepository orderRepository, ITimeLimitDomainService timeLimitDomainService, IWorkflowDomainService workflowDomainService, ICapPublisher capPublisher, IMapper mapper, ILogger logger, IOrderScreenRepository orderScreenRepository, IQualityApplication qualityApplication, IKnowledgeRepository knowledgeRepository, IKnowledgeWorkFlowRepository knowledgeWorkFlowRepository, IOrderDelayRepository orderDelayRepository) { _orderDomainService = orderDomainService; _knowledgeDomainService = knowledgeDomainService; _orderRepository = orderRepository; _timeLimitDomainService = timeLimitDomainService; _workflowDomainService = workflowDomainService; _capPublisher = capPublisher; _mapper = mapper; _logger = logger; _orderScreenRepository = orderScreenRepository; _qualityApplication = qualityApplication; _orderDelayRepository = orderDelayRepository; _knowledgeRepository = knowledgeRepository; _knowledgeWorkFlowRepository = knowledgeWorkFlowRepository; } /// Handles a notification /// The notification /// Cancellation token public async Task Handle(NextStepNotify notification, CancellationToken cancellationToken) { //_logger.LogInformation( // $"收到{nameof(NextStepNotify)}, notification: {JsonConvert.SerializeObject(notification)}"); var workflow = notification.Workflow; var data = notification.Dto; var assignInfo = notification.FlowAssignInfo; var currentTag = string.IsNullOrEmpty(notification.Trace.Tag) ? null : System.Text.Json.JsonSerializer.Deserialize(notification.Trace.Tag); var nextTag = string.IsNullOrEmpty(notification.NextStepDefine.Tag) ? null : System.Text.Json.JsonSerializer.Deserialize(notification.NextStepDefine.Tag); switch (workflow.ModuleCode) { case WorkflowModuleConsts.OrderHandle: var order = await _orderDomainService.GetOrderAsync(workflow.ExternalId, withHotspot: true, withAcceptor: true, withExtension: true, cancellationToken: cancellationToken); order.CheckIfFiled(); _mapper.Map(workflow, order); var expiredTimeChanged = false; if (data.FlowDirection.HasValue && data.External.TimeLimit.HasValue && data.External.TimeLimitUnit.HasValue) { // 1. calc expiredTime 2. update order.expiredTime 3. update workflow.expiredTime 4. publish province // var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, // data.External.TimeLimitUnit.Value, // data.External.TimeLimit.Value, data.FlowDirection is EFlowDirection.OrgToCenter); var expiredTimeConfig = _timeLimitDomainService.CalcEndTime(DateTime.Now, new TimeConfig(data.External.TimeLimit.Value, data.External.TimeLimitUnit.Value), order.AcceptTypeCode); if (data.FlowDirection is EFlowDirection.OrgToCenter) { order.OrgToCenter(expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime); } else if (data.FlowDirection is EFlowDirection.CenterToOrg) { order.CenterToOrg(expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime); //写入质检 await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, cancellationToken); } await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTimeConfig.ExpiredTime, expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken); expiredTimeChanged = true; } await _orderRepository.UpdateAsync(order, cancellationToken); var orderDto = _mapper.Map(order); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowHandled, new OrderFlowDto { Order = orderDto, WorkflowTrace = _mapper.Map(notification.Trace), ExpiredTimeChanged = expiredTimeChanged, HandlerOrgLevel = notification.HandlerOrgCode.CalcOrgLevel() }, cancellationToken: cancellationToken); break; case WorkflowModuleConsts.KnowledgeAdd: case WorkflowModuleConsts.KnowledgeUpdate: case WorkflowModuleConsts.KnowledgeDelete: var knowledgeWork = await _knowledgeWorkFlowRepository.Queryable().Where(x=>x.Id==workflow.ExternalId).FirstAsync(cancellationToken); var knowledge = await _knowledgeRepository.Queryable().Where(x => x.Id == knowledgeWork.KnowledgeId).FirstAsync(cancellationToken); knowledge.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs); await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken); break; case WorkflowModuleConsts.OrderScreen: var screen = await _orderScreenRepository.Queryable().Includes(x => x.Order) .Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken); if (screen != null) { screen.Status = EScreenStatus.Approval; screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs); await _orderScreenRepository.UpdateAsync(screen, cancellationToken); } if (nextTag is not null && nextTag.Type == TagDefaults.TagType.Org) { switch (nextTag.Value) { case TagDefaults.TagValue.Province: if (screen != null) { var screenDto = _mapper.Map(screen); if (screen.Order != null && screen.Order.Source == ESource.ProvinceStraight) { var screenOrderDto = _mapper.Map(screen.Order); //推省上 _capPublisher.Publish(EventNames.HotlineOrderScreenApply, new PublishScreenDto() { Order = screenOrderDto, Screen = screenDto, ClientGuid = "" }); //try //{ // await _provinceService.ScreenCaseInfoSend(new PublishScreenDto() // { // Order = screenOrderDto, // Screen = screenDto, // ClientGuid = "" // }, cancellationToken); //} //catch (Exception e) //{ // _logger.LogError( // "_provinceService.ScreenCaseInfoSend throw exception: {ex}", e.Message); //} } } break; } } break; case WorkflowModuleConsts.OrderDelay: var orderDelay = await _orderDelayRepository.Queryable().Includes(x => x.Order) .Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken); if (orderDelay != null) { orderDelay.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs); await _orderDelayRepository.UpdateAsync(orderDelay, cancellationToken); } if (nextTag is not null && nextTag.Type == TagDefaults.TagType.Org) { switch (nextTag.Value) { case TagDefaults.TagValue.Province: //TODO 发起省延期审批 //var orderDelay = await _orderDelayRepository.Queryable().Includes(x => x.Order) // .Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken); try { if (orderDelay != null) { //推送 var publishOrderDelay = _mapper.Map(orderDelay); await _capPublisher.PublishAsync(EventNames.HotlineOrderApplyDelay, publishOrderDelay, cancellationToken: cancellationToken); //await _provinceService.DelayCaseInfoSend(publishOrderDelay, cancellationToken); } } catch (Exception e) { _logger.LogError("_provinceService.DelayCaseInfoSend throw exception: {ex}", e.Message); } break; } } break; } } }