using Furion.DependencyInjection; using Furion.DistributedIDGenerator; using Furion.DynamicApiController; using Furion.FriendlyException; using Furion.JsonSerialization; using Google.Protobuf.Collections; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Myshipping.Application.Entity; using Myshipping.Core; using Myshipping.Core.Entity; using NPOI.OpenXmlFormats.Vml; using NPOI.SS.Formula.Functions; using Org.BouncyCastle.Asn1.Tsp; using Org.BouncyCastle.Ocsp; using StackExchange.Profiling.Internal; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace Myshipping.Application { /// /// 服务流程管理 /// [AllowAnonymous, ApiDescriptionSettings("Application", Name = "ServiceWorkFlowManage", Order = 20)] public class ServiceWorkFlowManageService : IServiceWorkFlowManageService, IDynamicApiController, ITransient { private readonly ILogger _logger; private readonly SqlSugarRepository _serviceWorkFlowBaseRepository; private readonly SqlSugarRepository _serviceWorkFlowActivitiesInfoRepository; private readonly SqlSugarRepository _serviceWorkFlowProjectRelationRepository; private readonly SqlSugarRepository _serviceWorkFlowActivitiesRelationRepository; private readonly SqlSugarRepository _serviceWorkFlowActivitiesSubRelationRepository; private readonly SqlSugarRepository _serviceWorkFlowReleaseInfoRepository; private readonly SqlSugarRepository _serviceWorkFlowRunInfoRepository; private readonly SqlSugarRepository _serviceWorkFlowRunActivitiesInfoRepository; private readonly SqlSugarRepository _statusSkuBaseInfoRepository; private readonly SqlSugarRepository _sysUserRepository; private readonly SqlSugarRepository _serviceProjectBaseInfoRepository; private readonly SqlSugarRepository _serviceWorkFlowRunLogInfoRepository; private readonly IServiceWorkFlowBaseService _serviceWorkFlowBaseService; public ServiceWorkFlowManageService(SqlSugarRepository serviceWorkFlowBaseRepository, ILogger logger, SqlSugarRepository serviceWorkFlowActivitiesInfoRepository, SqlSugarRepository serviceWorkFlowProjectRelationRepository, SqlSugarRepository serviceWorkFlowActivitiesRelationRepository, SqlSugarRepository serviceWorkFlowActivitiesSubRelationRepository, SqlSugarRepository serviceWorkFlowReleaseInfoRepository, SqlSugarRepository serviceWorkFlowRunInfoRepository, SqlSugarRepository serviceWorkFlowRunActivitiesInfoRepository, SqlSugarRepository statusSkuBaseInfoRepository, IServiceWorkFlowBaseService serviceWorkFlowBaseService, SqlSugarRepository sysUserRepository, SqlSugarRepository serviceProjectBaseInfoRepository, SqlSugarRepository serviceWorkFlowRunLogInfoRepository) { _serviceWorkFlowBaseRepository = serviceWorkFlowBaseRepository; _serviceWorkFlowActivitiesInfoRepository = serviceWorkFlowActivitiesInfoRepository; _serviceWorkFlowProjectRelationRepository = serviceWorkFlowProjectRelationRepository; _serviceWorkFlowActivitiesRelationRepository = serviceWorkFlowActivitiesRelationRepository; _logger = logger; _serviceWorkFlowActivitiesSubRelationRepository = serviceWorkFlowActivitiesSubRelationRepository; _serviceWorkFlowReleaseInfoRepository = serviceWorkFlowReleaseInfoRepository; _serviceWorkFlowRunInfoRepository = serviceWorkFlowRunInfoRepository; _serviceWorkFlowRunActivitiesInfoRepository = serviceWorkFlowRunActivitiesInfoRepository; _statusSkuBaseInfoRepository = statusSkuBaseInfoRepository; _serviceWorkFlowBaseService = serviceWorkFlowBaseService; _sysUserRepository = sysUserRepository; _serviceProjectBaseInfoRepository = serviceProjectBaseInfoRepository; _serviceWorkFlowRunLogInfoRepository = serviceWorkFlowRunLogInfoRepository; } #region 推送状态 /// /// 推送状态 /// /// 服务流程详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/PushStatus")] public async Task PushStatus([FromBody] TrackingMessageInfo info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no} 接收推送状态 msg={msg}", batchNo, JSON.Serialize(info)); try { /* 1、首先判断业务的主键,如果存在则需要提取所有主键下的服务流程活动,来更新。 2、状态可以批量处理。 */ if (info.Main == null) { _logger.LogInformation("批次={no} 接收推送状态错误 报文Main不能为空", batchNo); throw Oops.Oh($"报文Main不能为空", typeof(InvalidOperationException)); } if (string.IsNullOrWhiteSpace(info.Main.BusiSystemCode)) { _logger.LogInformation("批次={no} 接收推送状态错误 报文Main的业务系统代码不能为空", batchNo); throw Oops.Oh($"报文Main的业务系统代码不能为空", typeof(InvalidOperationException)); } if (string.IsNullOrWhiteSpace(info.Main.BusiId)) { _logger.LogInformation("批次={no} 接收推送状态错误 报文Main的业务主键不能为空", batchNo); throw Oops.Oh($"报文Main的业务主键不能为空", typeof(InvalidOperationException)); } if (info.Head != null && (string.IsNullOrWhiteSpace(info.Head.RequestAction) || !info.Head.RequestAction.Equals("AddOrModify",StringComparison.OrdinalIgnoreCase))) { _logger.LogInformation("批次={no} 报文Head的请求操作类型不能为空并且必需等于AddOrModify", batchNo); throw Oops.Oh($"报文Head的请求操作类型不能为空并且必需等于AddOrModify", typeof(InvalidOperationException)); } if (info.Main.StatusList == null || info.Main.StatusList.Count == 0) { _logger.LogInformation("批次={no} 接收推送状态错误 报文Main的状态列表不能为空,并且至少需要提供一个以上的状态信息", batchNo); throw Oops.Oh($"报文Main的状态列表不能为空,并且至少需要提供一个以上的状态信息", typeof(InvalidOperationException)); } //校验状态代码是否一致,不一致直接返回错误不允许推送 var statusArg = info.Main.StatusList.Select(a => a?.StatusCode.ToUpper()) .Where(a => !string.IsNullOrWhiteSpace(a)).Distinct().ToArray(); if (statusArg.Length == 0) { _logger.LogInformation("批次={no} 报文Main的状态列表至少需要提供一个以上的状态信息", batchNo); throw Oops.Oh($"报文Main的状态列表至少需要提供一个以上的状态信息", typeof(InvalidOperationException)); } UserTendDto userTendInfo = GetUserTendInfo(info.Main.RecvUserId); //检索状态对应所有的服务流程,如果已经提取到的状态数量与推送的不一致,提示错误不能入库s var skuList = _statusSkuBaseInfoRepository.AsQueryable().Filter(null, true) .LeftJoin((sts, act) => sts.PK_ID == act.STATUS_SKU_ID) .LeftJoin((sts,act,rela)=> act.PK_ID == rela.SERVICE_ACTIVITIES_ID) .LeftJoin((sts, act, rela,wf)=> rela.SERVICE_WORKFLOW_ID == wf.PK_ID && rela.WF_VERSION == wf.RELEASE_VERSION) .Where((sts, act) => statusArg.Contains(sts.STATUS_SKU_CODE) && !sts.IsDeleted && sts.IS_ENABLE == 1 && !act.IsDeleted) .Select((sts, act,rela,wf) => new { Sku = sts, Act = act, Rela = rela,WF = wf }).ToList(); //推送状态与已有状态进行匹配 var reqStatusList = info.Main.StatusList.GroupJoin(skuList, l => l.StatusCode, r => r.Sku.STATUS_SKU_CODE, (l, r) => { var currList = r.ToList(); if (currList.Count > 0) return new { Exists = true, Sku = currList.FirstOrDefault().Sku,Act = currList.FirstOrDefault().Act,Req = l }; return new { Exists = false, Sku = new StatusSkuBaseInfo(), Act = new ServiceWorkFlowActivitiesInfo(),Req = l }; }).ToList(); //如果有不存在的状态则提示无法入库 if (reqStatusList.Any(a => !a.Exists)) { var errList = reqStatusList.Where(a => !a.Exists) .Select(a => a.Req.StatusCode).ToArray(); string errMsg = $"以下状态不存在 {(string.Join(",", errList))} 不能入库"; _logger.LogInformation("批次={no} {msg}", batchNo, errMsg); throw Oops.Oh(errMsg, typeof(InvalidOperationException)); } //先从运行表按主键获取运行主表和活动表 var runList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .LeftJoin( (m, s) => m.PK_ID == s.RUN_ID) .Where((m, s) => m.BUSI_ID == info.Main.BusiId && m.BUSI_SYSTEM_CODE.Equals(info.Main.BusiSystemCode) && !m.IsDeleted && !s.IsDeleted) .Select((m, s) => new { main = m, sub = s }).ToList(); var wfList = skuList.Select(a => a.WF) .Distinct().ToList(); var checkList = wfList.GroupJoin(runList, l => l.PK_ID, r => r.main.SERVICE_WF_ID, (l, r) => { var currList = r.ToList(); if (currList.Count > 0) { return new { Exists = true, WF = l }; } return new { Exists = false, WF = l }; }).ToList(); if(checkList.Any(a=>a.Exists)) { reqStatusList.ForEach(async reqMd => { var currRun = runList.FirstOrDefault(x => x.sub.PK_ID == reqMd.Act.PK_ID); var currRunAct = currRun.sub; currRunAct.ACT_DATE = reqMd.Req.StatusDate; currRunAct.IS_YIELD = 1; await _serviceWorkFlowRunActivitiesInfoRepository.AsUpdateable(currRunAct).UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, }).ExecuteCommandAsync(); }); } if (checkList.Any(a => !a.Exists)) { var noExistsList = checkList.Where(l => !l.Exists).Select(a=>a.WF.PK_ID).Distinct().ToList(); //状态关联的服务流程与运行表中的服务流程对应,对已经有的进行更新,对未进入运行表的进行写入 var actArg = reqStatusList.Select(a => a.Act.PK_ID).ToArray(); //根据服务流程活动获取所有相关的服务流程 var wfRlt = _serviceWorkFlowBaseService.GetServiceWorkFlowListByActivities(actArg).GetAwaiter().GetResult(); if (!wfRlt.succ) { string errMsg = $"获取服务流程失败,原因:{wfRlt.msg}"; _logger.LogInformation("批次={no} {msg}", batchNo, errMsg); throw Oops.Oh(errMsg, typeof(InvalidOperationException)); } var list = JSON.Deserialize>(JSON.Serialize(wfRlt.ext)); if(list.Count > 0) list = list.Where(a=> noExistsList.Contains( a.PKId)).ToList(); DateTime nowDate = DateTime.Now; list.ForEach(async wf => { ServiceWorkFlowRunInfo serviceWorkFlowRunInfo = new ServiceWorkFlowRunInfo { PK_ID = IDGen.NextID().ToString(), SERVICE_WF_ID = wf.PKId, BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(), BUSI_ID = info.Main.BusiId.ToUpper(), MBL_NO = info.Main?.MBlNo.ToUpper(), VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(), ORDER_NO = info.Main?.OrderNo, STATUS = TaskStatusEnum.Create.ToString(), RELEASE_VERSION = wf.ReleaseVersion, ACTIVITIES_NUM = wf.StatusNum, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = userTendInfo.userId, CreatedUserName = userTendInfo.userName, TenantId = userTendInfo.tendId, TenantName = userTendInfo.tenantName, SERVICE_PROJECT_CODE = wf.ServiceProject.ServiceProjectCode, SERVICE_PROJECT_NAME = wf.ServiceProject.ServiceProjectName, }; await _serviceWorkFlowRunInfoRepository.InsertAsync(serviceWorkFlowRunInfo); int endNum = wf.StatusSkuList.Max(sku => sku.SortNo); string lastActId = string.Empty; wf.StatusSkuList.ForEach(async sku => { var currReq = reqStatusList.FirstOrDefault(x => x.Act.PK_ID == sku.PKId); ServiceWorkFlowRunActivitiesInfo activitiesRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = serviceWorkFlowRunInfo.PK_ID, EXEC_SORT_NO = sku.SortNo, IS_START = sku.SortNo == 1 ? 1 : 0, IS_END = sku.SortNo == endNum ? 1 : 0, ACT_ID = sku.PKId, STATUS_SKU_CODE = sku.statusSkuBase.StatusSKUCode, STATUS_SKU_ID = sku.StatusSKUId, SHOW_NAME = sku.ShowName, IS_SUB = 0, IS_SUB_JUST = 0, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = userTendInfo.userId, CreatedUserName = userTendInfo.userName, TenantId = userTendInfo.tendId, TenantName = userTendInfo.tenantName, IsDeleted = false, SOURCE_TYPE = "AUTO" }; if (currReq != null) { activitiesRunInfo.ACT_DATE = currReq.Req.StatusDate; activitiesRunInfo.ACT_VAL = currReq.Req.StatusVal; activitiesRunInfo.IS_YIELD = 1; } if (!string.IsNullOrWhiteSpace(lastActId)) activitiesRunInfo.NEXT_ACT_ID = lastActId; await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesRunInfo); lastActId = activitiesRunInfo.PK_ID; if (sku.IsContainsSub == 1) { string lastSubActId = string.Empty; sku.SubList.ForEach(async sub => { var currSubReq = reqStatusList.FirstOrDefault(x => x.Act.PK_ID == sub.PKId); ServiceWorkFlowRunActivitiesInfo activitiesSubRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = serviceWorkFlowRunInfo.PK_ID, EXEC_SORT_NO = sub.SortNo, IS_START = sub.SortNo == 1 ? 1 : 0, IS_END = sub.SortNo == endNum ? 1 : 0, ACT_ID = sub.PKId, STATUS_SKU_CODE = sub.statusSkuBase.StatusSKUCode, STATUS_SKU_ID = sub.StatusSKUId, SHOW_NAME = sub.ShowName, IS_SUB = 1, IS_SUB_JUST = 1, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = userTendInfo.userId, CreatedUserName = userTendInfo.userName, TenantId = userTendInfo.tendId, TenantName = userTendInfo.tenantName, IsDeleted = false, SOURCE_TYPE = "AUTO", PARENT_ID = activitiesRunInfo.PK_ID }; if (currSubReq != null) { activitiesSubRunInfo.ACT_DATE = currSubReq.Req.StatusDate; activitiesSubRunInfo.ACT_VAL = currSubReq.Req.StatusVal; activitiesSubRunInfo.IS_YIELD = 1; } if (!string.IsNullOrWhiteSpace(lastSubActId)) activitiesSubRunInfo.NEXT_ACT_ID = lastSubActId; await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesSubRunInfo); lastSubActId = activitiesSubRunInfo.PK_ID; }); } }); }); } result.succ = true; result.msg = "推送成功"; } catch (Exception ex) { result.succ = false; result.msg = $"推送状态失败,原因:{ex.Message}"; } return result; } #endregion #region 单票单服务项目查询 /// /// 单票单服务项目查询 /// /// 查询服务流程详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/QuerySingleBusinessPerServiceProject")] public async Task QuerySingleBusinessPerServiceProject(TrackingQueryMessageInfo info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no} 单票单服务项目查询 msg={msg}", batchNo, JSON.Serialize(info)); try { var runList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .LeftJoin((m, s) => m.PK_ID == s.RUN_ID) .LeftJoin((m, s, rela) => m.SERVICE_WF_ID == rela.SERVICE_WORKFLOW_ID && m.RELEASE_VERSION == rela.WF_VERSION) .LeftJoin((m, s, rela, p) => rela.SERVICE_PROJECT_ID == p.PK_ID) .Where((m, s, rela, p) => m.BUSI_SYSTEM_CODE == info.Main.BusiSystemCode && m.BUSI_ID == info.Main.BusiId && info.Main.ServiceProjectCodeList.Contains(p.SERVICE_PROJECT_CODE)) .Select((m, s) => new { Run = m, Sub = s }).ToList(); var resultList = runList.GroupBy(a=>a.Run.PK_ID) .Select(a => { var currList = a.ToList(); var runInfo = currList.FirstOrDefault().Run; var showModel = new ServiceWorkFlowRunDto(); showModel.PKId = runInfo.PK_ID; showModel.ServiceProjectCode = runInfo.SERVICE_PROJECT_CODE; showModel.ServiceProjectName = runInfo.SERVICE_PROJECT_NAME; showModel.ActivitiesList = currList.Where(t => t.Sub.IS_SUB == 0) .Select(t => { var runModel = new ServiceWorkFlowActivitiesRunDto { PKId = t.Sub.PK_ID, ActDate = t.Sub.ACT_DATE, ActId = t.Sub.ACT_ID, ExecSortNo = t.Sub.EXEC_SORT_NO, ActVal = t.Sub.ACT_VAL, IsStart = t.Sub.IS_START, IsEnd = t.Sub.IS_END, IsYield = t.Sub.IS_YIELD, RunId = t.Sub.RUN_ID, ShowName = t.Sub.SHOW_NAME, SourceType = t.Sub.SOURCE_TYPE, StatusSKUCode = t.Sub.STATUS_SKU_CODE, StatusSKUId = t.Sub.STATUS_SKU_ID }; return runModel; }).ToList(); var subList = currList.Where(t => t.Sub.IS_SUB == 1) .Select(t => t.Sub).ToList(); showModel.ActivitiesList = showModel.ActivitiesList.GroupJoin(subList, l => l.PKId, r => r.PARENT_ID, (l, r) => { var currList = r.ToList(); if (currList.Count > 0) { l.SubList = currList.Select(x => { var subModel = new ServiceWorkFlowActivitiesRunSubDto { PKId = x.PK_ID, ActDate = x.ACT_DATE, ActId = x.ACT_ID, ExecSortNo = x.EXEC_SORT_NO, ActVal = x.ACT_VAL, IsStart = x.IS_START, IsEnd = x.IS_END, IsYield = x.IS_YIELD, RunId = x.RUN_ID, ShowName = x.SHOW_NAME, SourceType = x.SOURCE_TYPE, StatusSKUCode = x.STATUS_SKU_CODE, StatusSKUId = x.STATUS_SKU_ID }; return subModel; }).OrderBy(x=>x.ExecSortNo).ToList(); } return l; }).OrderBy(t => t.ExecSortNo).ToList(); return showModel; }).ToList(); result.succ = true; result.ext = resultList; } catch (Exception ex) { result.succ = false; result.msg = $"单票单服务项目查询失败,原因:{ex.Message}"; } return result; } #endregion #region 单票所有相关服务项目查询 /// /// 单票所有相关服务项目查询 /// /// 查询服务流程详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/QuerySingleBusinessAll")] public async Task QuerySingleBusinessAll(TrackingQueryMessageInfo info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no} 单票所有相关服务项目查询 msg={msg}", batchNo, JSON.Serialize(info)); try { var runList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .LeftJoin((m, s) => m.PK_ID == s.RUN_ID) .Where((m, s) => m.BUSI_SYSTEM_CODE == info.Main.BusiSystemCode && m.BUSI_ID == info.Main.BusiId) .Select((m, s) => new { Run = m, Sub = s }).ToList(); var resultList = runList.GroupBy(a => a.Run.PK_ID) .Select(a => { var currList = a.ToList(); var runInfo = currList.FirstOrDefault().Run; var showModel = new ServiceWorkFlowRunDto(); showModel.PKId = runInfo.PK_ID; showModel.ServiceProjectCode = runInfo.SERVICE_PROJECT_CODE; showModel.ServiceProjectName = runInfo.SERVICE_PROJECT_NAME; showModel.ActivitiesList = currList.Where(t => t.Sub.IS_SUB == 0) .Select(t => { var runModel = new ServiceWorkFlowActivitiesRunDto { PKId = t.Sub.PK_ID, ActDate = t.Sub.ACT_DATE, ActId = t.Sub.ACT_ID, ExecSortNo = t.Sub.EXEC_SORT_NO, ActVal = t.Sub.ACT_VAL, IsStart = t.Sub.IS_START, IsEnd = t.Sub.IS_END, IsYield = t.Sub.IS_YIELD, RunId = t.Sub.RUN_ID, ShowName = t.Sub.SHOW_NAME, SourceType = t.Sub.SOURCE_TYPE, StatusSKUCode = t.Sub.STATUS_SKU_CODE, StatusSKUId = t.Sub.STATUS_SKU_ID }; return runModel; }).ToList(); var subList = currList.Where(t => t.Sub.IS_SUB == 1) .Select(t => t.Sub).ToList(); showModel.ActivitiesList = showModel.ActivitiesList.GroupJoin(subList, l => l.PKId, r => r.PARENT_ID, (l, r) => { var currList = r.ToList(); if (currList.Count > 0) { l.SubList = currList.Select(x => { var subModel = new ServiceWorkFlowActivitiesRunSubDto { PKId = x.PK_ID, ActDate = x.ACT_DATE, ActId = x.ACT_ID, ExecSortNo = x.EXEC_SORT_NO, ActVal = x.ACT_VAL, IsStart = x.IS_START, IsEnd = x.IS_END, IsYield = x.IS_YIELD, RunId = x.RUN_ID, ShowName = x.SHOW_NAME, SourceType = x.SOURCE_TYPE, StatusSKUCode = x.STATUS_SKU_CODE, StatusSKUId = x.STATUS_SKU_ID }; return subModel; }).OrderBy(x => x.ExecSortNo).ToList(); } return l; }).OrderBy(t => t.ExecSortNo).ToList(); return showModel; }).ToList(); result.succ = true; result.ext = resultList; } catch (Exception ex) { result.succ = false; result.msg = $"单票所有相关服务项目查询失败,原因:{ex.Message}"; } return result; } #endregion /// /// 取消状态 /// /// 服务流程报文详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/CancelStatus")] public async Task CancelStatus(TrackingMessageInfo info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no} 接收推送状态 msg={msg}", batchNo, JSON.Serialize(info)); try { /* 1、首先判断业务的主键,如果存在则需要提取所有主键下的服务流程活动,来更新。 2、状态可以批量处理。 */ if (info.Main == null) { _logger.LogInformation("批次={no} 接收推送状态错误 报文Main不能为空", batchNo); throw Oops.Oh($"报文Main不能为空", typeof(InvalidOperationException)); } if (string.IsNullOrWhiteSpace(info.Main.BusiSystemCode)) { _logger.LogInformation("批次={no} 接收推送状态错误 报文Main的业务系统代码不能为空", batchNo); throw Oops.Oh($"报文Main的业务系统代码不能为空", typeof(InvalidOperationException)); } if (string.IsNullOrWhiteSpace(info.Main.BusiId)) { _logger.LogInformation("批次={no} 接收推送状态错误 报文Main的业务主键不能为空", batchNo); throw Oops.Oh($"报文Main的业务主键不能为空", typeof(InvalidOperationException)); } if (info.Main.StatusList == null || info.Main.StatusList.Count == 0) { _logger.LogInformation("批次={no} 接收推送状态错误 报文Main的状态列表不能为空,并且至少需要提供一个以上的状态信息", batchNo); throw Oops.Oh($"报文Main的状态列表不能为空,并且至少需要提供一个以上的状态信息", typeof(InvalidOperationException)); } //校验状态代码是否一致,不一致直接返回错误不允许推送 var statusArg = info.Main.StatusList.Select(a => a?.StatusCode.ToUpper()) .Where(a => !string.IsNullOrWhiteSpace(a)).Distinct().ToArray(); if (statusArg.Length == 0) { _logger.LogInformation("批次={no} 报文Main的状态列表至少需要提供一个以上的状态信息", batchNo); throw Oops.Oh($"报文Main的状态列表至少需要提供一个以上的状态信息", typeof(InvalidOperationException)); } UserTendDto userTendInfo = GetUserTendInfo(info.Main.RecvUserId); //检索状态对应所有的服务流程,如果已经提取到的状态数量与推送的不一致,提示错误不能入库s var skuList = _statusSkuBaseInfoRepository.AsQueryable().Filter(null, true) .LeftJoin((sts, act) => sts.PK_ID == act.STATUS_SKU_ID) .LeftJoin((sts, act, rela) => act.PK_ID == rela.SERVICE_ACTIVITIES_ID) .LeftJoin((sts, act, rela, wf) => rela.SERVICE_WORKFLOW_ID == wf.PK_ID && rela.WF_VERSION == wf.RELEASE_VERSION) .Where((sts, act) => statusArg.Contains(sts.STATUS_SKU_CODE) && !sts.IsDeleted && sts.IS_ENABLE == 1 && !act.IsDeleted) .Select((sts, act, rela, wf) => new { Sku = sts, Act = act, Rela = rela, WF = wf }).ToList(); //推送状态与已有状态进行匹配 var reqStatusList = info.Main.StatusList.GroupJoin(skuList, l => l.StatusCode, r => r.Sku.STATUS_SKU_CODE, (l, r) => { var currList = r.ToList(); if (currList.Count > 0) return new { Exists = true, Sku = currList.FirstOrDefault().Sku, Act = currList.FirstOrDefault().Act, Req = l }; return new { Exists = false, Sku = new StatusSkuBaseInfo(), Act = new ServiceWorkFlowActivitiesInfo(), Req = l }; }).ToList(); //如果有不存在的状态则提示无法入库 if (reqStatusList.Any(a => !a.Exists)) { var errList = reqStatusList.Where(a => !a.Exists) .Select(a => a.Req.StatusCode).ToArray(); string errMsg = $"以下状态不存在 {(string.Join(",", errList))} 不能入库"; _logger.LogInformation("批次={no} {msg}", batchNo, errMsg); throw Oops.Oh(errMsg, typeof(InvalidOperationException)); } //先从运行表按主键获取运行主表和活动表 var runList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .LeftJoin( (m, s) => m.PK_ID == s.RUN_ID) .Where((m, s) => m.BUSI_ID == info.Main.BusiId && m.BUSI_SYSTEM_CODE.Equals(info.Main.BusiSystemCode) && !m.IsDeleted && !s.IsDeleted) .Select((m, s) => new { main = m, sub = s }).ToList(); var wfList = skuList.Select(a => a.WF) .Distinct().ToList(); var checkList = wfList.GroupJoin(runList, l => l.PK_ID, r => r.main.SERVICE_WF_ID, (l, r) => { var currList = r.ToList(); if (currList.Count > 0) { return new { Exists = true, WF = l }; } return new { Exists = false, WF = l }; }).ToList(); if (checkList.Any(a => a.Exists)) { reqStatusList.ForEach(async reqMd => { var currRun = runList.FirstOrDefault(x => x.sub.PK_ID == reqMd.Act.PK_ID); var currRunAct = currRun.sub; currRunAct.ACT_DATE = reqMd.Req.StatusDate; currRunAct.IS_YIELD = 1; await _serviceWorkFlowRunActivitiesInfoRepository.AsUpdateable(currRunAct).UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, }).ExecuteCommandAsync(); }); } if (checkList.Any(a => !a.Exists)) { var noExistsList = checkList.Where(l => !l.Exists).Select(a => a.WF.PK_ID).Distinct().ToList(); //状态关联的服务流程与运行表中的服务流程对应,对已经有的进行更新,对未进入运行表的进行写入 var actArg = reqStatusList.Select(a => a.Act.PK_ID).ToArray(); //根据服务流程活动获取所有相关的服务流程 var wfRlt = _serviceWorkFlowBaseService.GetServiceWorkFlowListByActivities(actArg).GetAwaiter().GetResult(); if (!wfRlt.succ) { string errMsg = $"获取服务流程失败,原因:{wfRlt.msg}"; _logger.LogInformation("批次={no} {msg}", batchNo, errMsg); throw Oops.Oh(errMsg, typeof(InvalidOperationException)); } var list = JSON.Deserialize>(JSON.Serialize(wfRlt.ext)); if (list.Count > 0) list = list.Where(a => noExistsList.Contains(a.PKId)).ToList(); DateTime nowDate = DateTime.Now; list.ForEach(async wf => { ServiceWorkFlowRunInfo serviceWorkFlowRunInfo = new ServiceWorkFlowRunInfo { PK_ID = IDGen.NextID().ToString(), SERVICE_WF_ID = wf.PKId, BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(), BUSI_ID = info.Main.BusiId.ToUpper(), MBL_NO = info.Main?.MBlNo.ToUpper(), VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(), ORDER_NO = info.Main?.OrderNo, STATUS = TaskStatusEnum.Create.ToString(), RELEASE_VERSION = wf.ReleaseVersion, ACTIVITIES_NUM = wf.StatusNum, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = userTendInfo.userId, CreatedUserName = userTendInfo.userName, TenantId = userTendInfo.tendId, TenantName = userTendInfo.tenantName, SERVICE_PROJECT_CODE = wf.ServiceProject.ServiceProjectCode, SERVICE_PROJECT_NAME = wf.ServiceProject.ServiceProjectName, }; await _serviceWorkFlowRunInfoRepository.InsertAsync(serviceWorkFlowRunInfo); int endNum = wf.StatusSkuList.Max(sku => sku.SortNo); string lastActId = string.Empty; wf.StatusSkuList.ForEach(async sku => { var currReq = reqStatusList.FirstOrDefault(x => x.Act.PK_ID == sku.PKId); ServiceWorkFlowRunActivitiesInfo activitiesRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = serviceWorkFlowRunInfo.PK_ID, EXEC_SORT_NO = sku.SortNo, IS_START = sku.SortNo == 1 ? 1 : 0, IS_END = sku.SortNo == endNum ? 1 : 0, ACT_ID = sku.PKId, STATUS_SKU_CODE = sku.statusSkuBase.StatusSKUCode, STATUS_SKU_ID = sku.StatusSKUId, SHOW_NAME = sku.ShowName, IS_SUB = 0, IS_SUB_JUST = 0, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = userTendInfo.userId, CreatedUserName = userTendInfo.userName, TenantId = userTendInfo.tendId, TenantName = userTendInfo.tenantName, IsDeleted = false, SOURCE_TYPE = "AUTO" }; if (currReq != null) { activitiesRunInfo.ACT_DATE = currReq.Req.StatusDate; activitiesRunInfo.ACT_VAL = currReq.Req.StatusVal; activitiesRunInfo.IS_YIELD = 1; } if (!string.IsNullOrWhiteSpace(lastActId)) activitiesRunInfo.NEXT_ACT_ID = lastActId; await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesRunInfo); lastActId = activitiesRunInfo.PK_ID; if (sku.IsContainsSub == 1) { string lastSubActId = string.Empty; sku.SubList.ForEach(async sub => { var currSubReq = reqStatusList.FirstOrDefault(x => x.Act.PK_ID == sub.PKId); ServiceWorkFlowRunActivitiesInfo activitiesSubRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = serviceWorkFlowRunInfo.PK_ID, EXEC_SORT_NO = sub.SortNo, IS_START = sub.SortNo == 1 ? 1 : 0, IS_END = sub.SortNo == endNum ? 1 : 0, ACT_ID = sub.PKId, STATUS_SKU_CODE = sub.statusSkuBase.StatusSKUCode, STATUS_SKU_ID = sub.StatusSKUId, SHOW_NAME = sub.ShowName, IS_SUB = 1, IS_SUB_JUST = 1, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = userTendInfo.userId, CreatedUserName = userTendInfo.userName, TenantId = userTendInfo.tendId, TenantName = userTendInfo.tenantName, IsDeleted = false, SOURCE_TYPE = "AUTO", PARENT_ID = activitiesRunInfo.PK_ID }; if (currSubReq != null) { activitiesSubRunInfo.ACT_DATE = currSubReq.Req.StatusDate; activitiesSubRunInfo.ACT_VAL = currSubReq.Req.StatusVal; activitiesSubRunInfo.IS_YIELD = 1; } if (!string.IsNullOrWhiteSpace(lastSubActId)) activitiesSubRunInfo.NEXT_ACT_ID = lastSubActId; await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesSubRunInfo); lastSubActId = activitiesSubRunInfo.PK_ID; }); } }); }); } result.succ = true; result.msg = "推送成功"; } catch (Exception ex) { result.succ = false; result.msg = $"推送状态失败,原因:{ex.Message}"; } return result; } #region 查询订舱表查询用户和租户信息 /// /// 查询订舱表查询用户和租户信息 /// /// 大简云用户ID /// 大简云用户邮箱 /// 返回用户和租户信息 private UserTendDto GetUserTendInfoByDJYUserId(string djyUserId, string djyUserEmail) { UserTendDto userTendDto = null; //这里因为接口是不做授权验证的,所以这里直接写的动态sql提取了用户和租户信息 var userTendInfo = _sysUserRepository.EntityContext.Queryable("user").AS("sys_user") .AddJoinInfo("sys_tenant", "ten", "user.TenantId=ten.Id") .Where("user.DjyUserId=@id and user.Email like '%" + djyUserEmail + "%'", new { id = djyUserId }) .Select("user.Id as UserId,user.Name as UserName,ten.Id as TendId,ten.Name as TendName").First(); if (userTendInfo == null || userTendInfo.TendId == null) throw Oops.Oh("当前用户详情获取失败,请确认{0}赋值是否准确", nameof(TaskManageOrderMessageInfo.Main.TaskUserId)); userTendDto = new UserTendDto { userId = long.Parse(userTendInfo.UserId.ToString()), userName = userTendInfo.UserName.ToString(), tendId = long.Parse(userTendInfo.TendId.ToString()), tenantName = userTendInfo.TendName.ToString() }; return userTendDto; } #endregion #region 查询订舱表查询用户和租户信息 /// /// 查询订舱表查询用户和租户信息 /// /// 用户ID /// 返回用户和租户信息 private UserTendDto GetUserTendInfo(string userId) { UserTendDto userTendDto = null; //这里因为接口是不做授权验证的,所以这里直接写的动态sql提取了用户和租户信息 var userTendInfo = _sysUserRepository.EntityContext.Queryable("user").AS("sys_user") .AddJoinInfo("sys_tenant", "ten", "user.TenantId=ten.Id") .Where("user.Id=@id", new { id = long.Parse(userId) }) .Select("user.Id as UserId,user.Name as UserName,ten.Id as TendId,ten.Name as TendName").First(); if (userTendInfo == null || userTendInfo.TendId == null) throw Oops.Oh("当前用户详情获取失败,请确认{0}赋值是否准确", nameof(TaskManageOrderMessageInfo.Main.TaskUserId)); userTendDto = new UserTendDto { userId = long.Parse(userTendInfo.UserId.ToString()), userName = userTendInfo.UserName.ToString(), tendId = long.Parse(userTendInfo.TendId.ToString()), tenantName = userTendInfo.TendName.ToString() }; return userTendDto; } #endregion } }