using Furion.DependencyInjection; using Furion.DistributedIDGenerator; using Furion.DynamicApiController; using Furion.FriendlyException; using Furion.JsonSerialization; using Google.Protobuf.Collections; using Mapster; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Myshipping.Application.Entity; using Myshipping.Core; using Myshipping.Core.Entity; using Npoi.Mapper; using NPOI.OpenXmlFormats.Vml; using NPOI.SS.Formula.Functions; using NPOI.SS.Formula.PTG; 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; 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 ICache _cache; private readonly CacheOptions _cacheOptions; private readonly SqlSugarRepository _bookingOrderRepository; private readonly SqlSugarRepository _serviceStatusBookingSyncHisInfoRepository; private readonly SqlSugarRepository _bookingGoodsStatusRepository; private readonly SqlSugarRepository _bookingGoodsStatusConfigRepository; private readonly SqlSugarRepository _sysTenantRepository; private readonly IServiceWorkFlowBaseService _serviceWorkFlowBaseService; const string CONST_CACHE_ENABLE_PROJECT = "service_project_list_enable"; const string CONST_CACHE_ENABLE_PROJECT_STATUS = "service_project_status_list_enable"; const string CONST_CACHE_ENABLE_STATUS = "service_status_list_enable"; 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, IOptions cacheOptions, Func resolveNamed, SqlSugarRepository bookingOrderRepository, SqlSugarRepository serviceStatusBookingSyncHisInfoRepository, SqlSugarRepository bookingGoodsStatusRepository, SqlSugarRepository bookingGoodsStatusConfigRepository, SqlSugarRepository sysTenantRepository) { _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; _bookingOrderRepository = bookingOrderRepository; _serviceStatusBookingSyncHisInfoRepository = serviceStatusBookingSyncHisInfoRepository; _bookingGoodsStatusRepository = bookingGoodsStatusRepository; _bookingGoodsStatusConfigRepository = bookingGoodsStatusConfigRepository; _sysTenantRepository = sysTenantRepository; _cacheOptions = cacheOptions.Value; _cache = resolveNamed(_cacheOptions.CacheType.ToString(), default) as ICache; } #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)); } var statusList = _serviceWorkFlowBaseService.GetEnableProjectWithStatusList(info.Main.OperTenantId.ToString()).GetAwaiter().GetResult(); var projectList = _cache.Get>($"{CONST_CACHE_ENABLE_PROJECT}_{info.Main.OperTenantId}"); DateTime nowDate = DateTime.Now; if (info.Main.PushType == TrackingPushTypeEnum.Project) { if (info.Main.ProjectList == null || info.Main.ProjectList.Count == 0) { _logger.LogInformation("批次={no} 推送类型是【服务项目】,服务项目列表不能为空", batchNo); throw Oops.Oh($"推送类型是【服务项目】,服务项目列表不能为空", typeof(InvalidOperationException)); } //提取所有已经有run记录的 var runBaseList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.BUSI_ID == info.Main.BusiId && a.BUSI_SYSTEM_CODE.Equals(info.Main.BusiSystemCode) && !a.IsDeleted && a.TenantId == info.Main.OperTenantId).ToList(); var needProjectArg = info.Main.ProjectList.Select(a => a.ServiceProjectCode).ToArray(); var needProjectList = statusList.Where(a => needProjectArg.Contains(a.ProjectCode)).ToList(); var tskList = needProjectList.GroupJoin(runBaseList, l => l.WFPKId, r => r.SERVICE_WF_ID, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) { //标识当前服务项目写入运行主表 return new { OperType = "Insert", Info = l, Run = new ServiceWorkFlowRunInfo() }; } return new { OperType = "Update", Info = l, Run = currList.FirstOrDefault() }; }).ToList(); tskList.ForEach(async tsk => { if (tsk.OperType == "Insert") { ServiceWorkFlowRunInfo serviceWorkFlowRunInfo = new ServiceWorkFlowRunInfo { PK_ID = IDGen.NextID().ToString(), SERVICE_WF_ID = tsk.Info.WFPKId, 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 = tsk.Info.ReleaseVersion, ACTIVITIES_NUM = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = long.Parse(info.Main.OperUserId), CreatedUserName = info.Main.OperUserName, TenantId = info.Main.OperTenantId, TenantName = info.Main.OperTenantName, SERVICE_PROJECT_CODE = tsk.Info.ProjectCode, SERVICE_PROJECT_NAME = tsk.Info.ProjectName, SERVICE_PROJECT_ID = tsk.Info.ProjectPKId, IS_YIELD = 1, ACT_DATE = nowDate, }; await _serviceWorkFlowRunInfoRepository.InsertAsync(serviceWorkFlowRunInfo); #region 写入运行日志 var runLog = serviceWorkFlowRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = serviceWorkFlowRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_PROJECT.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Insert"; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion } else if (tsk.OperType == "Update") { var runInfo = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .First(a => a.PK_ID == tsk.Run.PK_ID); if (runInfo != null) { runInfo.IS_YIELD = 1; runInfo.ACT_DATE = nowDate; runInfo.UpdatedTime = nowDate; runInfo.UpdatedUserId = long.Parse(info.Main.OperUserId); runInfo.UpdatedUserName = info.Main.OperUserName; await _serviceWorkFlowRunInfoRepository.AsUpdateable(runInfo).UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); #region 写入运行日志 var runLog = runInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = runInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_PROJECT.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Update"; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion } } }); result.succ = true; result.msg = "推送成功"; return result; } //校验状态代码是否一致,不一致直接返回错误不允许推送 var statusArg = info.Main.StatusList.Select(a => a?.StatusCode.ToUpper()) .Where(a => !string.IsNullOrWhiteSpace(a)).Distinct().ToArray(); if (statusArg.Length == 0) { _logger.LogInformation("批次={no} 服务状态列表不能为空", batchNo); throw Oops.Oh($"服务状态列表不能为空", typeof(InvalidOperationException)); } /* 1、从缓存拉取服务项目和状态详情。 2、检索所有相关状态的服务项目。 3、拉取run表相关的订单记录。 4、如果当前订单没有记录,需要按照服务项目和状态生成run表记录。 5、标记相关状态为完成,并更新时间。 */ statusList = statusList.Where(a => a.StatusList.Any(b => { if (statusArg.Contains(b.StatusSKUCode)) return true; if (b.SubStatusList != null && b.SubStatusList.Any(c => statusArg.Contains(c.StatusSKUCode))) return true; return false; })).ToList(); if (statusList.Count == 0) throw Oops.Oh($"未检索到可用服务项目和状态列表", typeof(InvalidOperationException)); var wfArgs = statusList.Select(a => a.WFPKId).ToArray(); //获取订单下所有Run表记录 var runHisList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .LeftJoin((main, detail) => main.PK_ID == detail.RUN_ID) .Where((main, detail) => main.BUSI_SYSTEM_CODE == info.Main.BusiSystemCode && main.BUSI_ID == info.Main.BusiId && wfArgs.Contains(main.SERVICE_WF_ID)) .Select((main, detail) => new { Main = main, Detail = detail }).ToList(); /* 1、提前将状态按照流程分组。 2、如果服务项目没有run记录则批量写入。 */ int doTimes = 0; statusList.ForEach(async wf => { if(doTimes > 0) { //每处理完一种重新读取run runHisList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .LeftJoin((main, detail) => main.PK_ID == detail.RUN_ID) .Where((main, detail) => main.BUSI_SYSTEM_CODE == info.Main.BusiSystemCode && main.BUSI_ID == info.Main.BusiId && wfArgs.Contains(main.SERVICE_WF_ID)) .Select((main, detail) => new { Main = main, Detail = detail }).ToList(); } var runList = runHisList .Where(a => a.Main.SERVICE_WF_ID == wf.WFPKId) .ToList(); if(runList.Count == 0) { #region 处理run表 //需要生成run表记录包含活动明细 ServiceWorkFlowRunInfo serviceWorkFlowRunInfo = new ServiceWorkFlowRunInfo { PK_ID = IDGen.NextID().ToString(), SERVICE_WF_ID = wf.WFPKId, 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 = long.Parse(info.Main.OperUserId), CreatedUserName = info.Main.OperUserName, TenantId = info.Main.OperTenantId, TenantName = info.Main.OperTenantName, SERVICE_PROJECT_CODE = wf.ProjectCode, SERVICE_PROJECT_NAME = wf.ProjectName, SERVICE_PROJECT_ID = wf.ProjectPKId, IS_YIELD = 1, ACT_DATE = nowDate, }; //写入run主表 await _serviceWorkFlowRunInfoRepository.InsertAsync(serviceWorkFlowRunInfo); #region 写入运行日志 var runLog = serviceWorkFlowRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = serviceWorkFlowRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Insert"; runLog.BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(); runLog.BUSI_ID = info.Main.BusiId.ToUpper(); runLog.SERVICE_WF_ID = wf.WFPKId; runLog.SERVICE_PROJECT_CODE = wf.ProjectCode; runLog.SERVICE_PROJECT_NAME = wf.ProjectName; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion //获取状态最大数 int endNum = wf.StatusList.Max(sku => sku.ActSortNo); string lastActId = string.Empty; wf.StatusList.ForEach(async sku => { ServiceWorkFlowRunActivitiesInfo activitiesRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = serviceWorkFlowRunInfo.PK_ID, EXEC_SORT_NO = sku.ActSortNo, IS_START = sku.ActSortNo == 1 ? 1 : 0, IS_END = sku.ActSortNo == endNum ? 1 : 0, ACT_ID = sku.ActPKId, STATUS_SKU_CODE = sku.StatusSKUCode, STATUS_SKU_ID = sku.SkuPKId, SHOW_NAME = sku.ShowName, IS_SUB = 0, IS_SUB_JUST = 0, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = long.Parse(info.Main.OperUserId), CreatedUserName = info.Main.OperUserName, TenantId = info.Main.OperTenantId, TenantName = info.Main.OperTenantName, IsDeleted = false, SOURCE_TYPE = info.Main.SourceType.ToString() }; if (statusArg.Contains(sku.StatusSKUCode)) { var st = info.Main.StatusList.FirstOrDefault(c => c.StatusCode.Equals(sku.StatusSKUCode, StringComparison.OrdinalIgnoreCase)); bool currIsYield = true; //完成时间为空,备注不为空只保存备注信息,不标记完成 if (!st.StatusDate.HasValue && !string.IsNullOrWhiteSpace(st.Remark)) { currIsYield = false; } if (currIsYield) { activitiesRunInfo.IS_YIELD = 1; if (st.StatusDate.HasValue) { activitiesRunInfo.ACT_DATE = st.StatusDate.Value; } else { activitiesRunInfo.ACT_DATE = nowDate; } } activitiesRunInfo.ACT_VAL = st.StatusVal; activitiesRunInfo.ACT_REMARK = st.Remark; } //写入run活动表 await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesRunInfo); #region 写入运行日志 var runLog = activitiesRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = activitiesRunInfo.RUN_ID; runLog.RUN_DETAIL_ID = activitiesRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Insert"; runLog.MBL_NO = info.Main?.MBlNo.ToUpper(); runLog.VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(); runLog.ORDER_NO = info.Main?.OrderNo; runLog.RELEASE_VERSION = wf.ReleaseVersion; runLog.BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(); runLog.BUSI_ID = info.Main.BusiId.ToUpper(); runLog.SERVICE_WF_ID = wf.WFPKId; runLog.SERVICE_PROJECT_CODE = wf.ProjectCode; runLog.SERVICE_PROJECT_NAME = wf.ProjectName; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion if (sku.SubStatusList != null && sku.SubStatusList.Count > 0) { string lastSubActId = string.Empty; sku.SubStatusList.ForEach(async sub => { ServiceWorkFlowRunActivitiesInfo activitiesSubRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = serviceWorkFlowRunInfo.PK_ID, EXEC_SORT_NO = sub.ActSortNo, IS_START = sub.ActSortNo == 1 ? 1 : 0, IS_END = sub.ActSortNo == endNum ? 1 : 0, ACT_ID = sub.ActPKId, STATUS_SKU_CODE = sub.StatusSKUCode, STATUS_SKU_ID = sub.SkuPKId, SHOW_NAME = sub.ShowName, IS_SUB = 1, IS_SUB_JUST = 1, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = long.Parse(info.Main.OperUserId), CreatedUserName = info.Main.OperUserName, TenantId = info.Main.OperTenantId, TenantName = info.Main.OperTenantName, IsDeleted = false, SOURCE_TYPE = info.Main.SourceType.ToString(), PARENT_ID = activitiesRunInfo.PK_ID }; if (statusArg.Contains(sub.StatusSKUCode)) { bool currIsYield = true; var st = info.Main.StatusList.FirstOrDefault(c => c.StatusCode.Equals(sub.StatusSKUCode, StringComparison.OrdinalIgnoreCase)); //完成时间为空,备注不为空只保存备注信息,不标记完成 if (!st.StatusDate.HasValue && !string.IsNullOrWhiteSpace(st.Remark)) { currIsYield = false; } if (currIsYield) { activitiesSubRunInfo.IS_YIELD = 1; if (st.StatusDate.HasValue) { activitiesSubRunInfo.ACT_DATE = st.StatusDate.Value; } else { activitiesSubRunInfo.ACT_DATE = nowDate; } } activitiesSubRunInfo.ACT_VAL = st.StatusVal; activitiesSubRunInfo.ACT_REMARK = st.Remark; } if (!string.IsNullOrWhiteSpace(lastSubActId)) activitiesSubRunInfo.NEXT_ACT_ID = lastSubActId; await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesSubRunInfo); #region 写入运行日志 var runLog = activitiesSubRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = activitiesSubRunInfo.RUN_ID; runLog.RUN_DETAIL_ID = activitiesSubRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Insert"; runLog.MBL_NO = info.Main?.MBlNo.ToUpper(); runLog.VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(); runLog.ORDER_NO = info.Main?.OrderNo; runLog.RELEASE_VERSION = wf.ReleaseVersion; runLog.BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(); runLog.BUSI_ID = info.Main.BusiId.ToUpper(); runLog.SERVICE_WF_ID = wf.WFPKId; runLog.SERVICE_PROJECT_CODE = wf.ProjectCode; runLog.SERVICE_PROJECT_NAME = wf.ProjectName; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion lastSubActId = activitiesSubRunInfo.PK_ID; }); } }); #endregion } else { if (runList.Any(b => b.Detail == null || (b.Detail != null && string.IsNullOrWhiteSpace(b.Detail.PK_ID)))) { var runMain = runList.FirstOrDefault().Main; //需要补充活动表明细 var runEntity = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .First(rn => rn.PK_ID == runMain.PK_ID); if (runEntity != null && runEntity.IS_YIELD == 0) { runEntity.IS_YIELD = 1; runEntity.ACT_DATE = nowDate; runEntity.UpdatedTime = nowDate; runEntity.CreatedUserId = long.Parse(info.Main.OperUserId); runEntity.CreatedUserName = info.Main.OperUserName; await _serviceWorkFlowRunInfoRepository.AsUpdateable(runEntity).UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); #region 写入运行日志 var runLog = runEntity.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = runEntity.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Update"; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion } //批量写入活动表 #region 批量写入活动表 //获取状态最大数 int endNum = wf.StatusList.Max(sku => sku.ActSortNo); string lastActId = string.Empty; wf.StatusList.ForEach(async sku => { ServiceWorkFlowRunActivitiesInfo activitiesRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = runEntity.PK_ID, EXEC_SORT_NO = sku.ActSortNo, IS_START = sku.ActSortNo == 1 ? 1 : 0, IS_END = sku.ActSortNo == endNum ? 1 : 0, ACT_ID = sku.ActPKId, STATUS_SKU_CODE = sku.StatusSKUCode, STATUS_SKU_ID = sku.SkuPKId, SHOW_NAME = sku.ShowName, IS_SUB = 0, IS_SUB_JUST = 0, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = long.Parse(info.Main.OperUserId), CreatedUserName = info.Main.OperUserName, TenantId = info.Main.OperTenantId, TenantName = info.Main.OperTenantName, IsDeleted = false, SOURCE_TYPE = info.Main.SourceType.ToString(), }; if (statusArg.Contains(sku.StatusSKUCode)) { bool currIsYield = true; var st = info.Main.StatusList.FirstOrDefault(c => c.StatusCode.Equals(sku.StatusSKUCode, StringComparison.OrdinalIgnoreCase)); //完成时间为空,备注不为空只保存备注信息,不标记完成 if (!st.StatusDate.HasValue && !string.IsNullOrWhiteSpace(st.Remark)) { currIsYield = false; } if (currIsYield) { activitiesRunInfo.IS_YIELD = 1; if (st.StatusDate.HasValue) { activitiesRunInfo.ACT_DATE = st.StatusDate.Value; } else { activitiesRunInfo.ACT_DATE = nowDate; } } activitiesRunInfo.ACT_VAL = st.StatusVal; activitiesRunInfo.ACT_REMARK = st.Remark; } //写入run活动表 await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesRunInfo); #region 写入运行日志 var runLog = activitiesRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = activitiesRunInfo.RUN_ID; runLog.RUN_DETAIL_ID = activitiesRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Insert"; runLog.MBL_NO = info.Main?.MBlNo.ToUpper(); runLog.VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(); runLog.ORDER_NO = info.Main?.OrderNo; runLog.RELEASE_VERSION = wf.ReleaseVersion; runLog.BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(); runLog.BUSI_ID = info.Main.BusiId.ToUpper(); runLog.SERVICE_WF_ID = wf.WFPKId; runLog.SERVICE_PROJECT_CODE = wf.ProjectCode; runLog.SERVICE_PROJECT_NAME = wf.ProjectName; await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion if (sku.SubStatusList != null && sku.SubStatusList.Count > 0) { string lastSubActId = string.Empty; sku.SubStatusList.ForEach(async sub => { ServiceWorkFlowRunActivitiesInfo activitiesSubRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = runEntity.PK_ID, EXEC_SORT_NO = sub.ActSortNo, IS_START = sub.ActSortNo == 1 ? 1 : 0, IS_END = sub.ActSortNo == endNum ? 1 : 0, ACT_ID = sub.ActPKId, STATUS_SKU_CODE = sub.StatusSKUCode, STATUS_SKU_ID = sub.SkuPKId, SHOW_NAME = sub.ShowName, IS_SUB = 1, IS_SUB_JUST = 1, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = long.Parse(info.Main.OperUserId), CreatedUserName = info.Main.OperUserName, TenantId = info.Main.OperTenantId, TenantName = info.Main.OperTenantName, IsDeleted = false, SOURCE_TYPE = info.Main.SourceType.ToString(), PARENT_ID = activitiesRunInfo.PK_ID }; var st = info.Main.StatusList.FirstOrDefault(c => c.StatusCode.Equals(sub.StatusSKUCode, StringComparison.OrdinalIgnoreCase)); if (st != null) { if (st.StatusCode.Equals(sub.StatusSKUCode, StringComparison.OrdinalIgnoreCase)) { bool currIsYield = true; //完成时间为空,备注不为空只保存备注信息,不标记完成 if (!st.StatusDate.HasValue && !string.IsNullOrWhiteSpace(st.Remark)) { currIsYield = false; } if (currIsYield) { activitiesSubRunInfo.IS_YIELD = 1; if (st.StatusDate.HasValue) { activitiesSubRunInfo.ACT_DATE = st.StatusDate.Value; } else { activitiesSubRunInfo.ACT_DATE = nowDate; } } activitiesSubRunInfo.ACT_VAL = st.StatusVal; activitiesSubRunInfo.ACT_REMARK = st.Remark; } } if (!string.IsNullOrWhiteSpace(lastSubActId)) activitiesSubRunInfo.NEXT_ACT_ID = lastSubActId; await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesSubRunInfo); #region 写入运行日志 var runLog = activitiesSubRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = activitiesSubRunInfo.RUN_ID; runLog.RUN_DETAIL_ID = activitiesSubRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Insert"; runLog.MBL_NO = info.Main?.MBlNo.ToUpper(); runLog.VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(); runLog.ORDER_NO = info.Main?.OrderNo; runLog.RELEASE_VERSION = wf.ReleaseVersion; runLog.BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(); runLog.BUSI_ID = info.Main.BusiId.ToUpper(); runLog.SERVICE_WF_ID = wf.WFPKId; runLog.SERVICE_PROJECT_CODE = wf.ProjectCode; runLog.SERVICE_PROJECT_NAME = wf.ProjectName; await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion lastSubActId = activitiesSubRunInfo.PK_ID; }); } }); #endregion } else { var runMain = runList.FirstOrDefault().Main; //需要补充活动表明细 var runEntity = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .First(rn => rn.PK_ID == runMain.PK_ID); if (runEntity != null && runEntity.IS_YIELD == 0) { runEntity.IS_YIELD = 1; runEntity.ACT_DATE = nowDate; runEntity.UpdatedTime = nowDate; runEntity.CreatedUserId = long.Parse(info.Main.OperUserId); runEntity.CreatedUserName = info.Main.OperUserName; await _serviceWorkFlowRunInfoRepository.AsUpdateable(runEntity).UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); #region 写入运行日志 var runLog = runEntity.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = runEntity.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Update"; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion } int endNum = wf.StatusList.Max(sku => sku.ActSortNo); //只需要更新完成标记和完成时间 wf.StatusList.ForEach(async sku => { bool isAdd = false; var currRunDetail = runList.FirstOrDefault(p => p.Detail.STATUS_SKU_CODE.Equals(sku.StatusSKUCode))?.Detail; ServiceWorkFlowRunActivitiesInfo activitiesRunInfo = null; if (currRunDetail == null) { isAdd = true; activitiesRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = runEntity.PK_ID, EXEC_SORT_NO = sku.ActSortNo, IS_START = sku.ActSortNo == 1 ? 1 : 0, IS_END = sku.ActSortNo == endNum ? 1 : 0, ACT_ID = sku.ActPKId, STATUS_SKU_CODE = sku.StatusSKUCode, STATUS_SKU_ID = sku.SkuPKId, SHOW_NAME = sku.ShowName, IS_SUB = 0, IS_SUB_JUST = 0, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = long.Parse(info.Main.OperUserId), CreatedUserName = info.Main.OperUserName, TenantId = info.Main.OperTenantId, TenantName = info.Main.OperTenantName, IsDeleted = false, SOURCE_TYPE = info.Main.SourceType.ToString(), }; } else { activitiesRunInfo = _serviceWorkFlowRunActivitiesInfoRepository.AsQueryable() .Filter(null, true) .First(p => p.PK_ID == currRunDetail.PK_ID); } if (statusArg.Contains(sku.StatusSKUCode)) { bool currIsYield = true; var st = info.Main.StatusList.FirstOrDefault(c => c.StatusCode.Equals(sku.StatusSKUCode, StringComparison.OrdinalIgnoreCase)); //完成时间为空,备注不为空只保存备注信息,不标记完成 if (!st.StatusDate.HasValue && !string.IsNullOrWhiteSpace(st.Remark)) { currIsYield = false; } var beforeObj = new { ACT_VAL = activitiesRunInfo.ACT_VAL, ACT_REMARK = activitiesRunInfo.ACT_REMARK, ACT_DATE = activitiesRunInfo.ACT_DATE, IS_YIELD = activitiesRunInfo.IS_YIELD }; _logger.LogInformation("批次={no} 取消状态前记录 msg={msg}", batchNo, JSON.Serialize(beforeObj)); if (currIsYield) { activitiesRunInfo.IS_YIELD = 1; if (st.StatusDate.HasValue) { activitiesRunInfo.ACT_DATE = st.StatusDate.Value; } else { activitiesRunInfo.ACT_DATE = nowDate; } } activitiesRunInfo.ACT_VAL = st.StatusVal; activitiesRunInfo.ACT_REMARK = st.Remark; activitiesRunInfo.EXEC_SORT_NO = sku.ActSortNo; activitiesRunInfo.UpdatedTime = nowDate; activitiesRunInfo.CreatedUserId = long.Parse(info.Main.OperUserId); activitiesRunInfo.CreatedUserName = info.Main.OperUserName; if (isAdd) { //写入run活动表 await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesRunInfo); } else { await _serviceWorkFlowRunActivitiesInfoRepository.AsUpdateable(activitiesRunInfo) .UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, it.ACT_REMARK, it.ACT_VAL, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); } #region 写入运行日志 var runLog = activitiesRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = activitiesRunInfo.RUN_ID; runLog.RUN_DETAIL_ID = activitiesRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = isAdd ? "Insert" : "Update"; runLog.MBL_NO = info.Main?.MBlNo.ToUpper(); runLog.VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(); runLog.ORDER_NO = info.Main?.OrderNo; runLog.RELEASE_VERSION = wf.ReleaseVersion; runLog.BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(); runLog.BUSI_ID = info.Main.BusiId.ToUpper(); runLog.SERVICE_WF_ID = wf.WFPKId; runLog.SERVICE_PROJECT_CODE = wf.ProjectCode; runLog.SERVICE_PROJECT_NAME = wf.ProjectName; runLog.ACT_VAL = beforeObj.ACT_VAL; runLog.ACT_DATE = beforeObj.ACT_DATE; runLog.ACT_REMARK = beforeObj.ACT_REMARK; runLog.IS_YIELD = beforeObj.IS_YIELD; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion } else { //这里考虑如果变更了流程,活动run表记录要更新顺序号 if (!isAdd && sku.ActSortNo != activitiesRunInfo.EXEC_SORT_NO) { activitiesRunInfo.EXEC_SORT_NO = sku.ActSortNo; activitiesRunInfo.UpdatedTime = DateTime.Now; await _serviceWorkFlowRunActivitiesInfoRepository.AsUpdateable(activitiesRunInfo) .UpdateColumns(it => new { it.EXEC_SORT_NO, it.UpdatedTime, }).ExecuteCommandAsync(); } } if (sku.SubStatusList != null && sku.SubStatusList.Count > 0) { sku.SubStatusList.ForEach(async sub => { bool isAddSub = false; var currRunDetailSub = runList.FirstOrDefault(p => p.Detail.STATUS_SKU_CODE.Equals(sub.StatusSKUCode))?.Detail; ServiceWorkFlowRunActivitiesInfo activitiesSubRunInfo = null; if (currRunDetailSub == null) { isAddSub = true; activitiesSubRunInfo = new ServiceWorkFlowRunActivitiesInfo { PK_ID = IDGen.NextID().ToString(), RUN_ID = runEntity.PK_ID, EXEC_SORT_NO = sub.ActSortNo, IS_START = sub.ActSortNo == 1 ? 1 : 0, IS_END = sub.ActSortNo == endNum ? 1 : 0, ACT_ID = sub.ActPKId, STATUS_SKU_CODE = sub.StatusSKUCode, STATUS_SKU_ID = sub.SkuPKId, SHOW_NAME = sub.ShowName, IS_SUB = 1, IS_SUB_JUST = 1, IS_YIELD = 0, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = long.Parse(info.Main.OperUserId), CreatedUserName = info.Main.OperUserName, TenantId = info.Main.OperTenantId, TenantName = info.Main.OperTenantName, IsDeleted = false, SOURCE_TYPE = info.Main.SourceType.ToString(), PARENT_ID = activitiesRunInfo.PK_ID }; } else { activitiesSubRunInfo = _serviceWorkFlowRunActivitiesInfoRepository.AsQueryable() .Filter(null, true) .First(p => p.PK_ID == currRunDetailSub.PK_ID); } if (statusArg.Contains(sub.StatusSKUCode)) { var st = info.Main.StatusList.FirstOrDefault(c => c.StatusCode.Equals(sub.StatusSKUCode, StringComparison.OrdinalIgnoreCase)); bool currIsYield = true; //完成时间为空,备注不为空只保存备注信息,不标记完成 if (!st.StatusDate.HasValue && !string.IsNullOrWhiteSpace(st.Remark)) { currIsYield = false; } var beforeObj = new { ACT_VAL = activitiesRunInfo.ACT_VAL, ACT_REMARK = activitiesRunInfo.ACT_REMARK, ACT_DATE = activitiesRunInfo.ACT_DATE, IS_YIELD = activitiesRunInfo.IS_YIELD }; _logger.LogInformation("批次={no} 取消状态前记录 msg={msg}", batchNo, JSON.Serialize(beforeObj)); if (currIsYield) { activitiesSubRunInfo.IS_YIELD = 1; if (st.StatusDate.HasValue) { activitiesSubRunInfo.ACT_DATE = st.StatusDate.Value; } else { activitiesSubRunInfo.ACT_DATE = nowDate; } } //这里考虑如果变更了流程,活动run表记录要更新顺序号 activitiesSubRunInfo.EXEC_SORT_NO = sub.ActSortNo; activitiesSubRunInfo.ACT_VAL = st.StatusVal; activitiesSubRunInfo.ACT_REMARK = st.Remark; activitiesSubRunInfo.UpdatedTime = nowDate; activitiesSubRunInfo.CreatedUserId = long.Parse(info.Main.OperUserId); activitiesSubRunInfo.CreatedUserName = info.Main.OperUserName; if (isAddSub) { //写入run活动表 await _serviceWorkFlowRunActivitiesInfoRepository.InsertAsync(activitiesSubRunInfo); } else { await _serviceWorkFlowRunActivitiesInfoRepository.AsUpdateable(activitiesSubRunInfo) .UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, it.ACT_REMARK, it.ACT_VAL, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); } #region 写入运行日志 var runLog = activitiesSubRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = activitiesSubRunInfo.RUN_ID; runLog.RUN_DETAIL_ID = activitiesSubRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.PUSH_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Update"; runLog.MBL_NO = info.Main?.MBlNo.ToUpper(); runLog.VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(); runLog.ORDER_NO = info.Main?.OrderNo; runLog.RELEASE_VERSION = wf.ReleaseVersion; runLog.ORDER_NO = info.Main?.OrderNo; runLog.RELEASE_VERSION = wf.ReleaseVersion; runLog.BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(); runLog.BUSI_ID = info.Main.BusiId.ToUpper(); runLog.SERVICE_WF_ID = wf.WFPKId; runLog.SERVICE_PROJECT_CODE = wf.ProjectCode; runLog.SERVICE_PROJECT_NAME = wf.ProjectName; runLog.ACT_VAL = beforeObj.ACT_VAL; runLog.ACT_DATE = beforeObj.ACT_DATE; runLog.ACT_REMARK = beforeObj.ACT_REMARK; runLog.IS_YIELD = beforeObj.IS_YIELD; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion } else { //这里考虑如果变更了流程,活动run表记录要更新顺序号 if (!isAddSub && sku.ActSortNo != activitiesRunInfo.EXEC_SORT_NO) { activitiesRunInfo.EXEC_SORT_NO = sku.ActSortNo; activitiesRunInfo.UpdatedTime = DateTime.Now; await _serviceWorkFlowRunActivitiesInfoRepository.AsUpdateable(activitiesRunInfo) .UpdateColumns(it => new { it.EXEC_SORT_NO, it.UpdatedTime, }).ExecuteCommandAsync(); } } }); } }); } } doTimes++; }); 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 { result.succ = true; result.ext = InnerGetRunListBySingleBusiness(info); } catch (Exception ex) { result.succ = false; result.msg = $"单票单服务项目查询失败,原因:{ex.Message}"; } return result; } #endregion #region 获取单票业务相关的服务项目运行列表 /// /// 获取单票业务相关的服务项目运行列表 /// /// 查询服务流程详情 /// 返回查询列表 private List InnerGetRunListBySingleBusiness(TrackingQueryMessageInfo info) { 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) .InnerJoin((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 == null || info.Main.ServiceProjectCodeList.Contains(p.SERVICE_PROJECT_CODE))) .Select((m, s,rela,p) => 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.ServiceProjectId = runInfo.SERVICE_PROJECT_ID; showModel.ServiceProjectCode = runInfo.SERVICE_PROJECT_CODE; showModel.ServiceProjectName = runInfo.SERVICE_PROJECT_NAME; showModel.IsYield = runInfo.IS_YIELD; showModel.ActDate = runInfo.ACT_DATE; showModel.WFPKId = runInfo.SERVICE_WF_ID; showModel.ActivitiesList = currList.Where(t => !string.IsNullOrWhiteSpace(t.Sub.PK_ID) && 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, ActRemark = t.Sub.ACT_REMARK, }; return runModel; }).ToList(); var subList = currList.Where(t => !string.IsNullOrWhiteSpace(t.Sub.PK_ID) && 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, ActRemark = x.ACT_REMARK }; return subModel; }).OrderBy(x => x.ExecSortNo).ToList(); } return l; }).OrderBy(t => t.ExecSortNo).ToList(); return showModel; }).ToList(); return resultList; } #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 #region 取消状态 /// /// 取消状态 /// /// 服务流程报文详情 /// 返回回执 [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)); } var statusList = _serviceWorkFlowBaseService.GetEnableProjectWithStatusList(info.Main.OperTenantId.ToString()).GetAwaiter().GetResult(); var projectList = _cache.Get>($"{CONST_CACHE_ENABLE_PROJECT}_{info.Main.OperTenantId}"); DateTime nowDate = DateTime.Now; if (info.Main.PushType == TrackingPushTypeEnum.Project) { if (info.Main.ProjectList == null || info.Main.ProjectList.Count == 0) { _logger.LogInformation("批次={no} 推送类型是【服务项目】,服务项目列表不能为空", batchNo); throw Oops.Oh($"推送类型是【服务项目】,服务项目列表不能为空", typeof(InvalidOperationException)); } //提取所有已经有run记录的 var runBaseList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.BUSI_ID == info.Main.BusiId && a.BUSI_SYSTEM_CODE.Equals(info.Main.BusiSystemCode) && !a.IsDeleted && a.TenantId == info.Main.OperTenantId).ToList(); var needProjectArg = info.Main.ProjectList.Select(a => a.ServiceProjectCode).ToArray(); var needProjectList = statusList.Where(a => needProjectArg.Contains(a.ProjectCode)).ToList(); var tskList = needProjectList.GroupJoin(runBaseList, l => l.WFPKId, r => r.SERVICE_WF_ID, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) { //标识当前服务项目写入运行主表 return new { OperType = "None", Info = l, Run = new ServiceWorkFlowRunInfo() }; } return new { OperType = "Update", Info = l, Run = currList.FirstOrDefault() }; }).ToList(); tskList.ForEach(async tsk => { if (tsk.OperType == "Update") { var runInfo = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null,true) .First(a => a.PK_ID == tsk.Run.PK_ID); if (runInfo != null) { runInfo.IS_YIELD = 0; runInfo.ACT_DATE = null; runInfo.UpdatedTime = nowDate; runInfo.UpdatedUserId = long.Parse(info.Main.OperUserId); runInfo.UpdatedUserName = info.Main.OperUserName; await _serviceWorkFlowRunInfoRepository.AsUpdateable(runInfo).UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); #region 写入运行日志 var runLog = runInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = runInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.CANCEL_PROJECT.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Update"; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion } } }); result.succ = true; result.msg = "取消成功"; return result; } //校验状态代码是否一致,不一致直接返回错误不允许推送 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)); } //检索状态相关的服务流程 statusList = statusList.Where(a => a.StatusList.Any(b => { if (statusArg.Contains(b.StatusSKUCode)) return true; if (b.SubStatusList != null && b.SubStatusList.Any(c => statusArg.Contains(c.StatusSKUCode))) return true; return false; })).ToList(); if (statusList.Count == 0) throw Oops.Oh($"未检索到可用服务项目和状态列表", typeof(InvalidOperationException)); //提取关联的服务流程主键数组 var wfArgs = statusList.Select(a => a.WFPKId).ToArray(); //获取订单下所有Run表记录 var runHisList = _serviceWorkFlowRunInfoRepository.AsQueryable().Filter(null, true) .LeftJoin((main, detail) => main.PK_ID == detail.RUN_ID) .Where((main, detail) => main.BUSI_SYSTEM_CODE == info.Main.BusiSystemCode && main.BUSI_ID == info.Main.BusiId && wfArgs.Contains(main.SERVICE_WF_ID)) .Select((main, detail) => new { Main = main, Detail = detail }).ToList(); //按照请求的状态列表轮询 info.Main.StatusList.ForEach(async st => { var relateList = statusList.Where(a => a.StatusList.Any(b => { if (b.StatusSKUCode.Equals(st.StatusCode, StringComparison.OrdinalIgnoreCase)) return true; if (b.SubStatusList != null && b.SubStatusList.Any(c => !string.IsNullOrWhiteSpace(c.StatusSKUCode) && c.StatusSKUCode.Equals(st.StatusCode, StringComparison.OrdinalIgnoreCase))) return true; return false; })).ToList(); relateList.ForEach(async rt => { var runList = runHisList.Where(a => a.Main.SERVICE_WF_ID == rt.WFPKId).ToList(); if(runList.Any(b => b.Detail != null && !string.IsNullOrWhiteSpace(b.Detail.STATUS_SKU_CODE) && b.Detail.STATUS_SKU_CODE.Equals(st.StatusCode,StringComparison.OrdinalIgnoreCase))) { var detail = runList.FirstOrDefault(b => b.Detail.STATUS_SKU_CODE.Equals(st.StatusCode, StringComparison.OrdinalIgnoreCase)); var activitiesRunInfo = _serviceWorkFlowRunActivitiesInfoRepository .AsQueryable().First(b => b.PK_ID == detail.Detail.PK_ID); _logger.LogInformation("批次={no} 取消状态前记录 出问题的地方 info={info} msg={msg}", batchNo,JSON.Serialize(info), JSON.Serialize(activitiesRunInfo)); if(activitiesRunInfo != null) { var beforeObj = new { ACT_VAL = activitiesRunInfo.ACT_VAL, ACT_REMARK = activitiesRunInfo.ACT_REMARK, ACT_DATE = activitiesRunInfo.ACT_DATE, IS_YIELD = activitiesRunInfo.IS_YIELD }; _logger.LogInformation("批次={no} 取消状态前记录 msg={msg}", batchNo, JSON.Serialize(beforeObj)); activitiesRunInfo.ACT_VAL = null; activitiesRunInfo.ACT_REMARK = null; activitiesRunInfo.ACT_DATE = null; activitiesRunInfo.IS_YIELD = 0; activitiesRunInfo.UpdatedTime = nowDate; activitiesRunInfo.UpdatedUserId = long.Parse(info.Main.OperUserId); activitiesRunInfo.UpdatedUserName = info.Main.OperUserName; await _serviceWorkFlowRunActivitiesInfoRepository.AsUpdateable(activitiesRunInfo) .UpdateColumns(it => new { it.ACT_DATE, it.IS_YIELD, it.ACT_REMARK, it.ACT_VAL, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); #region 写入运行日志 var runLog = activitiesRunInfo.Adapt(); runLog.PK_ID = IDGen.NextID().ToString(); runLog.RUN_ID = activitiesRunInfo.RUN_ID; runLog.RUN_DETAIL_ID = activitiesRunInfo.PK_ID; runLog.BATCH_NO = batchNo; runLog.OPER_TYPE = TrackingRunOperTypeEnum.CANCEL_STATUS.ToString(); runLog.EXEC_RESULT = "SUCC"; runLog.EXEC_NOTE = "Update"; runLog.MBL_NO = info.Main?.MBlNo.ToUpper(); runLog.VESSEL_VOYNO = info.Main?.VesselVoyno.ToUpper(); runLog.ORDER_NO = info.Main?.OrderNo; runLog.RELEASE_VERSION = detail.Main.RELEASE_VERSION; runLog.BUSI_SYSTEM_CODE = info.Main.BusiSystemCode.ToUpper(); runLog.BUSI_ID = info.Main.BusiId.ToUpper(); runLog.SERVICE_WF_ID = detail.Main.SERVICE_WF_ID.ToUpper(); runLog.SERVICE_PROJECT_CODE = detail.Main.SERVICE_PROJECT_CODE.ToUpper(); runLog.SERVICE_PROJECT_NAME = detail.Main.SERVICE_PROJECT_NAME.ToUpper(); runLog.ACT_VAL = beforeObj.ACT_VAL; runLog.ACT_DATE = beforeObj.ACT_DATE; runLog.ACT_REMARK = beforeObj.ACT_REMARK; runLog.IS_YIELD = beforeObj.IS_YIELD; runLog.SOURCE_TYPE = info.Main.SourceType.ToString(); await _serviceWorkFlowRunLogInfoRepository.InsertAsync(runLog); #endregion } } }); }); result.succ = true; result.msg = "取消成功"; } catch (Exception ex) { result.succ = false; result.msg = $"取消状态失败,原因:{ex.Message}"; } return result; } #endregion #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 #region 查询当前租户下可用服务项目与状态详情 /// /// 查询当前租户下可用服务项目与状态详情 /// /// 查询服务项目请求报文 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/QueryServiceInfo")] public async Task QueryServiceInfo([FromBody] TrackingQueryMessageInfo info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no} 查询当前租户下可用服务项目 msg={msg}", batchNo, JSON.Serialize(info)); try { /* 1、检索按照租户检索已经发布的服务流程。 2、根据枚举 info.Main.QueryType来判断返回哪些数据。 3、只返回服务项目。 4、只返回服务项目下的服务状态。 5、优先通过缓存获取结果。 */ if (info.Main.QueryType == TrackingQueryTypeEnum.QUERY_SERVICE_PROJECT) { var projectList = await _serviceWorkFlowBaseService.GetEnableProjectList(info.Main.TenantId); if (info.Main.QueryServiceProjectCode != null && info.Main.QueryServiceProjectCode.Length > 0) { result.ext = projectList.Where(a => info.Main.QueryServiceProjectCode.Contains(a.ServiceProjectCode)) .OrderBy(a => a.SortNo).ToList(); } else { result.ext = projectList; } } else if (info.Main.QueryType == TrackingQueryTypeEnum.QUERY_SERVICE_PROJECT_STATUS) { var statusList = await _serviceWorkFlowBaseService.GetEnableProjectList(info.Main.TenantId); if (info.Main.QueryServiceProjectCode != null && info.Main.QueryServiceProjectCode.Length > 0) { result.ext = statusList.Where(a => info.Main.QueryServiceProjectCode.Contains(a.ServiceProjectCode)) .OrderBy(a => a.SortNo).ToList(); } else { result.ext = statusList; } } result.succ = true; } catch (Exception ex) { result.succ = false; result.msg = $"查询服务项目失败,原因:{ex.Message}"; } return result; } #endregion #region 校验取消状态 /// /// 校验取消状态 /// /// 服务流程报文详情 /// 返回回执 public async Task ValidateCancelProject(TrackingMessageInfo info) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no} 接收推送状态 msg={msg}", batchNo, JSON.Serialize(info)); return result; } #endregion #region 检索已选中并且可用的服务项目列表 /// /// 检索已选中并且可用的服务项目列表 /// /// 查询服务项目和状态详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/GetEnableProjectList")] public async Task GetEnableProjectList([FromBody] QueryServiceProjectWithStatus model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { //先获取可用的服务项目 var projectList = await _serviceWorkFlowBaseService.GetEnableProjectList(model.TenantId.ToString()); TrackingQueryMessageInfo messageInfo = new TrackingQueryMessageInfo { Head = new TrackingMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "PROJECT", ReceiverId = "ServiceProjectStatus", ReceiverName = "服务项目和状态", SenderId = "BookingOrder", SenderName = "海运订舱", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "2.0", RequestAction = "AddOrModify", },Main = new TrackingMessageQueryMainInfo { BusiId = model.BookingId.ToString(), BusiSystemCode = "BOOKING_ORDER", TenantId = model.TenantId.ToString(), } }; //在获取运行表已有的记录 var runList = InnerGetRunListBySingleBusiness(messageInfo); var resultList = projectList.GroupJoin(runList, l => l.PKId, r => r.ServiceProjectId, (l, r) => { var currList = r.ToList(); var runInfo = currList.FirstOrDefault(); var dto = new ServiceProjectWithStatusDto { ProjectPKId = l.PKId, ProjectCode = l.ServiceProjectCode, ProjectName = l.ServiceProjectName, SortNo = l.SortNo }; if(runInfo != null) { dto.IsYield = runInfo.IsYield == 1 ? true : false; dto.ActDate = runInfo.ActDate; } return dto; }).ToList(); result.succ = true; result.ext = resultList; } catch (Exception ex) { result.succ = false; result.msg = $"检索已选中并且可用的服务项目列表失败,原因:{ex.Message}"; } return result; } #endregion #region 检索服务项目下的状态列表 /// /// 检索服务项目下的状态列表 /// /// 查询服务项目和状态详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/GetEnableStatusListByProject")] public async Task GetEnableStatusListByProject([FromBody] QueryServiceProjectWithStatus model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var statuList = await _serviceWorkFlowBaseService.GetEnableProjectWithStatusList(model.TenantId.ToString()); var resultList = statuList.Where(a => model.ProjectCodes.Contains(a.ProjectCode)) .OrderBy(a => a.SortNo) .SelectMany(a => a.StatusList.SelectMany(b => { List currList = new List(); currList.Add(b); if (b.SubStatusList != null && b.SubStatusList.Count > 0) { currList.AddRange(b.SubStatusList.OrderBy(e=>e.ActSortNo)); } return currList; } )).ToList() .ToList(); result.succ = true; result.ext = resultList; } catch (Exception ex) { result.succ = false; result.msg = $"检索服务项目下的状态列表失败,原因:{ex.Message}"; } return result; } #endregion #region 单票检索服务项目下的状态列表 /// /// 单票检索服务项目下的状态列表 /// /// 查询服务项目和状态详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/GetEnableStatusListByBusiness")] public async Task GetEnableStatusListByBusiness([FromBody] QueryServiceProjectWithStatus model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var statuList = await _serviceWorkFlowBaseService.GetEnableProjectWithStatusList(model.TenantId.ToString()); TrackingQueryMessageInfo messageInfo = new TrackingQueryMessageInfo { Head = new TrackingMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "PROJECT", ReceiverId = "ServiceProjectStatus", ReceiverName = "服务项目和状态", SenderId = "BookingOrder", SenderName = "海运订舱", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "2.0", RequestAction = "AddOrModify", }, Main = new TrackingMessageQueryMainInfo { BusiId = model.BookingId.ToString(), BusiSystemCode = "BOOKING_ORDER", TenantId = model.TenantId.ToString(), } }; DateTime bDate = DateTime.Now; //在获取运行表已有的记录 var runList = InnerGetRunListBySingleBusiness(messageInfo); DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.LogInformation("测试读取服务状态-读取数据库记录 耗时:{timeDiff}ms. ", timeDiff); int lastWFSortNo = 0; int calcNum = 1; //var allStatus = statuList.SelectMany(b => { // var curArg = b.StatusList.SelectMany(x => x.SubStatusList).ToList(); // if (curArg == null) // curArg = new List(); // curArg.AddRange(b.StatusList); // return curArg; //}).ToList(); var resultList = statuList.Join(runList, l => l.WFPKId, r => r.WFPKId, (l, r) => { var runInfo = r; var rltList = new List(); if (runInfo.ActivitiesList == null || (runInfo.ActivitiesList != null && runInfo.ActivitiesList.Count == 0)) { l.StatusList.ForEach(b => { rltList.Add(new ServiceProjectStatusDto { ActPKId = b.ActPKId, ActSortNo = b.ActSortNo, ShowName = b.ShowName, IsYield = false, StatusSKUCode = b.StatusSKUCode, ActRemark = b.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ActSortNo, SortNo = b.SortNo }); if (b.SubStatusList != null && b.SubStatusList.Count > 0) { rltList.AddRange(b.SubStatusList.Select(c => new ServiceProjectStatusDto { ActPKId = c.ActPKId, ActSortNo = c.ActSortNo, ShowName = c.ShowName, IsYield = false, StatusSKUCode = c.StatusSKUCode, ActRemark = c.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ActSortNo + (c.ActSortNo * 0.001m), SortNo = c.SortNo }).ToList()); } }); } else { l.StatusList.ForEach(b => { var eRunInfo = runInfo.ActivitiesList .FirstOrDefault(p => p.ActId == b.ActPKId); if(eRunInfo != null) { rltList.Add(new ServiceProjectStatusDto { ActPKId = eRunInfo.ActId, ActSortNo = eRunInfo.ExecSortNo, ShowName = eRunInfo.ShowName, IsYield = eRunInfo.IsYield == 1 ? true : false, StatusSKUCode = eRunInfo.StatusSKUCode, ActDate = eRunInfo.ActDate, ActVal = eRunInfo.ActVal, ActRemark = eRunInfo.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)eRunInfo.ExecSortNo, SortNo = b.SortNo }); } else { rltList.Add(new ServiceProjectStatusDto { ActPKId = b.ActPKId, ActSortNo = b.ActSortNo, ShowName = b.ShowName, IsYield = false, StatusSKUCode = b.StatusSKUCode, ActRemark = b.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ActSortNo, SortNo = b.SortNo }); } if (b.SubStatusList != null && b.SubStatusList.Count > 0) { b.SubStatusList.ForEach(sb => { ServiceWorkFlowActivitiesRunSubDto eSubRunInfo = null; if(eRunInfo != null && eRunInfo.SubList != null) { eSubRunInfo = eRunInfo.SubList .FirstOrDefault(p => p.ActId == sb.ActPKId); } if(eSubRunInfo != null) { decimal calcSort = (decimal)b.ActSortNo + (eSubRunInfo.ExecSortNo * 0.001m); if (eRunInfo != null) { calcSort = (decimal)eRunInfo.ExecSortNo + (eSubRunInfo.ExecSortNo * 0.001m); } rltList.Add(new ServiceProjectStatusDto { ActPKId = eSubRunInfo.ActId, ActSortNo = eSubRunInfo.ExecSortNo, ShowName = eSubRunInfo.ShowName, IsYield = eSubRunInfo.IsYield == 1 ? true : false, StatusSKUCode = eSubRunInfo.StatusSKUCode, ActDate = eSubRunInfo.ActDate, ActVal = eSubRunInfo.ActVal, ActRemark = eSubRunInfo.ActRemark, WFSortNo = l.SortNo, CalcSortNo = calcSort, SortNo = sb.SortNo }); } else { decimal calcSort = (decimal)b.ActSortNo + (sb.ActSortNo * 0.001m); if (eRunInfo != null) { calcSort = (decimal)eRunInfo.ExecSortNo + (sb.ActSortNo * 0.001m); } rltList.Add(new ServiceProjectStatusDto { ActPKId = sb.ActPKId, ActSortNo = sb.ActSortNo, ShowName = sb.ShowName, IsYield = false, StatusSKUCode = sb.StatusSKUCode, ActRemark = sb.ActRemark, WFSortNo = l.SortNo, CalcSortNo = calcSort, SortNo = sb.SortNo }); } }); } }); } if (rltList != null && rltList.Count > 0) { var maxSort = rltList.Max(t => t.CalcSortNo); rltList.FirstOrDefault(t => t.CalcSortNo == maxSort).IsEnd = true; } return rltList; }).SelectMany(b => b).OrderBy(b => b.WFSortNo).Select(b => { if(lastWFSortNo == 0) { b.GroupName = calcNum.ToString(); lastWFSortNo = b.WFSortNo; } else if(b.WFSortNo == lastWFSortNo) { b.GroupName = calcNum.ToString(); } else { ++calcNum; lastWFSortNo = b.WFSortNo; b.GroupName = calcNum.ToString(); } return b; }).OrderBy(b => b.WFSortNo).ThenBy(b=>b.CalcSortNo).ToList(); result.succ = true; result.ext = resultList; } catch (Exception ex) { result.succ = false; result.msg = $"检索服务项目下的状态列表失败,原因:{ex.Message}"; } return result; } #endregion #region 保存服务状态 /// /// 保存服务状态 /// /// 修改服务状态详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/SaveServiceStatus")] public async Task SaveServiceStatus([FromBody] ModifyServiceProjectStatusDto model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); try { var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true) .First(a => a.Id == model.BookingId); if (bookingOrder == null) throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废"); _logger.LogInformation("批次={no} 请求保存服务项目 modifyjson={msg}", batchNo, JSON.Serialize(model)); TrackingMessageInfo msgInfo = new TrackingMessageInfo { Head = new TrackingMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "PROJECT", ReceiverId = "ServiceProjectStatus", ReceiverName = "服务项目和状态", SenderId = "BookingOrder", SenderName = "海运订舱", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "2.0", RequestAction = "AddOrModify", }, Main = new TrackingMessageMainInfo { BusiId = model.BookingId.ToString(), BusiSystemCode = "BOOKING_ORDER", MBlNo = bookingOrder.MBLNO, VesselVoyno = $"{bookingOrder.VESSEL}/{bookingOrder.VOYNO}", OrderNo = bookingOrder.BSNO, PushType = TrackingPushTypeEnum.Status, OperTenantId = bookingOrder.TenantId.Value, OperTenantName = bookingOrder.TenantName, OpertType = TrackingOperTypeEnum.MANUAL, OperUserId = UserManager.UserId.ToString(), OperUserName = UserManager.Name, SourceType = model.SourceType, StatusList = model.StatusCodes.Select(a => new TrackingMessageMainStatusInfo { StatusCode = a.StatusCode, StatusDate = a.SetActDate, StatusVal = a.SetActVal, Remark = a.ActRemark }).ToList() } }; DateTime bDate = DateTime.Now; _logger.LogInformation("批次={no} 推送保存服务项目 msg={msg}", batchNo, JSON.Serialize(msgInfo)); var rlt = await PushStatus(msgInfo); DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg} result={rlt}", batchNo, timeDiff, (rlt.succ ? "成功" : "失败") , JSON.Serialize(rlt)); if (!rlt.succ) { result = rlt; } else { result.succ = true; result.msg = "推送成功"; } } catch (Exception ex) { result.succ = false; result.msg = $"服务项目状态推送失败,原因:{ex.Message}"; } return result; } #endregion #region 取消服务状态 /// /// 取消服务状态 /// /// 修改服务状态详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/CancelServiceStatus")] public async Task CancelServiceStatus([FromBody] ModifyServiceProjectStatusDto model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); try { var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true) .First(a => a.Id == model.BookingId); if (bookingOrder == null) throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废"); _logger.LogInformation("批次={no} 请求保存服务项目 modifyjson={msg}", batchNo, JSON.Serialize(model)); TrackingMessageInfo msgInfo = new TrackingMessageInfo { Head = new TrackingMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "PROJECT", ReceiverId = "ServiceProjectStatus", ReceiverName = "服务项目和状态", SenderId = "BookingOrder", SenderName = "海运订舱", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "2.0", RequestAction = "AddOrModify", }, Main = new TrackingMessageMainInfo { BusiId = model.BookingId.ToString(), BusiSystemCode = "BOOKING_ORDER", MBlNo = bookingOrder.MBLNO, VesselVoyno = $"{bookingOrder.VESSEL}/{bookingOrder.VOYNO}", OrderNo = bookingOrder.BSNO, PushType = TrackingPushTypeEnum.Status, OperTenantId = bookingOrder.TenantId.Value, OperTenantName = bookingOrder.TenantName, OpertType = TrackingOperTypeEnum.MANUAL, OperUserId = UserManager.UserId.ToString(), OperUserName = UserManager.Name, SourceType = model.SourceType, StatusList = model.StatusCodes.Select(a => new TrackingMessageMainStatusInfo { StatusCode = a.StatusCode, StatusDate = a.SetActDate, StatusVal = a.SetActVal, Remark = a.ActRemark }).ToList() } }; DateTime bDate = DateTime.Now; _logger.LogInformation("批次={no} 推送保存服务项目 msg={msg}", batchNo, JSON.Serialize(msgInfo)); var rlt = await CancelStatus(msgInfo); DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg} result={rlt}", batchNo, timeDiff, (rlt.succ ? "成功" : "失败") , JSON.Serialize(rlt)); if (!rlt.succ) { result = rlt; } else { result.succ = true; result.msg = "推送成功"; } } catch (Exception ex) { result.succ = false; result.msg = $"服务项目状态推送失败,原因:{ex.Message}"; } return result; } #endregion #region 批量检索服务项目下的状态列表 /// /// 批量检索服务项目下的状态列表 /// /// 批量查询服务项目和状态详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/GetEnableStatusListByBusinessBatch")] public async Task GetEnableStatusListByBusinessBatch([FromBody] QueryServiceProjectWithStatusBatch model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var statuList = await _serviceWorkFlowBaseService.GetEnableProjectWithStatusList(model.TenantId.ToString()); TrackingQueryBatchMessageInfo messageInfo = new TrackingQueryBatchMessageInfo { Head = new TrackingMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "PROJECT", ReceiverId = "ServiceProjectStatus", ReceiverName = "服务项目和状态", SenderId = "BookingOrder", SenderName = "海运订舱", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "2.0", RequestAction = "AddOrModify", }, Main = new TrackingMessageQueryBatchMainInfo { BusiIds = model.BookingIds.Select(a=>a.ToString()).ToList(), BusiSystemCode = "BOOKING_ORDER", TenantId = model.TenantId.ToString(), } }; DateTime bDate = DateTime.Now; //在获取运行表已有的记录 var runList = InnerGetRunListBySingleBusinessBatch(messageInfo); DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.LogInformation("测试读取服务状态-读取数据库记录 耗时:{timeDiff}ms. ", timeDiff); int lastWFSortNo = 0; int calcNum = 1; var resultList = statuList.Join(runList, l => l.WFPKId, r => r.WFPKId, (l, r) => { var runInfo = r; var rltList = new List(); if (runInfo.IsYield == 1) { if (runInfo.ActivitiesList == null || (runInfo.ActivitiesList != null && runInfo.ActivitiesList.Count == 0)) { l.StatusList.ForEach(b => { rltList.Add(new ServiceProjectStatusDto { ActPKId = b.ActPKId, ActSortNo = b.ActSortNo, ShowName = b.ShowName, IsYield = false, StatusSKUCode = b.StatusSKUCode, ActRemark = b.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ActSortNo, BusiSystemCode = runInfo.BusiSystemCode, BusiId = runInfo.BusiId, }); if (b.SubStatusList != null && b.SubStatusList.Count > 0) { rltList.AddRange(b.SubStatusList.Select(c => new ServiceProjectStatusDto { ActPKId = c.ActPKId, ActSortNo = c.ActSortNo, ShowName = c.ShowName, IsYield = false, StatusSKUCode = b.StatusSKUCode, ActRemark = b.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ActSortNo + (c.ActSortNo * 0.001m), BusiSystemCode = runInfo.BusiSystemCode, BusiId = runInfo.BusiId, }).ToList()); } }); } else { runInfo.ActivitiesList.ForEach(b => { rltList.Add(new ServiceProjectStatusDto { ActPKId = b.ActId, ActSortNo = b.ExecSortNo, ShowName = b.ShowName, IsYield = b.IsYield == 1 ? true : false, ActDate = b.ActDate, ActVal = b.ActVal, StatusSKUCode = b.StatusSKUCode, ActRemark = b.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ExecSortNo, BusiSystemCode = runInfo.BusiSystemCode, BusiId = runInfo.BusiId, }); if (b.SubList != null && b.SubList.Count > 0) { rltList.AddRange(b.SubList.Select(c => new ServiceProjectStatusDto { ActPKId = c.ActId, ActSortNo = c.ExecSortNo, ShowName = c.ShowName, IsYield = c.IsYield == 1 ? true : false, ActDate = c.ActDate, ActVal = c.ActVal, StatusSKUCode = c.StatusSKUCode, ActRemark = c.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ExecSortNo + (c.ExecSortNo * 0.001m), BusiSystemCode = runInfo.BusiSystemCode, BusiId = runInfo.BusiId, }).ToList()); } }); } } if (rltList != null && rltList.Count > 0) { var maxSort = rltList.Max(t => t.CalcSortNo); rltList.FirstOrDefault(t => t.CalcSortNo == maxSort).IsEnd = true; } return rltList; }).SelectMany(b => b).OrderBy(b => b.WFSortNo).Select(b => { if (lastWFSortNo == 0) { b.GroupName = calcNum.ToString(); lastWFSortNo = b.WFSortNo; } else if (b.WFSortNo == lastWFSortNo) { b.GroupName = calcNum.ToString(); } else { ++calcNum; lastWFSortNo = b.WFSortNo; b.GroupName = calcNum.ToString(); } return b; }).OrderBy(b => b.WFSortNo).ThenBy(b => b.CalcSortNo).ToList(); result.succ = true; result.ext = resultList; } catch (Exception ex) { result.succ = false; result.msg = $"检索服务项目下的状态列表失败,原因:{ex.Message}"; } return result; } #endregion #region 获取单票业务相关的服务项目运行列表 /// /// 获取单票业务相关的服务项目运行列表 /// /// 查询服务流程详情 /// 返回查询列表 private List InnerGetRunListBySingleBusinessBatch(TrackingQueryBatchMessageInfo info) { 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) .InnerJoin((m, s, rela, p) => rela.SERVICE_PROJECT_ID == p.PK_ID) .Where((m, s, rela, p) => m.BUSI_SYSTEM_CODE == info.Main.BusiSystemCode && info.Main.BusiIds.Contains(m.BUSI_ID) && (info.Main.ServiceProjectCodeList == null || info.Main.ServiceProjectCodeList.Contains(p.SERVICE_PROJECT_CODE))) .Select((m, s, rela, p) => new { Run = m, Sub = s }).ToList(); var resultList = runList.GroupBy(a => $"{a.Run.BUSI_ID}_{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.ServiceProjectId = runInfo.SERVICE_PROJECT_ID; showModel.ServiceProjectCode = runInfo.SERVICE_PROJECT_CODE; showModel.ServiceProjectName = runInfo.SERVICE_PROJECT_NAME; showModel.IsYield = runInfo.IS_YIELD; showModel.ActDate = runInfo.ACT_DATE; showModel.WFPKId = runInfo.SERVICE_WF_ID; showModel.BusiId = runInfo.BUSI_ID; showModel.BusiSystemCode = runInfo.BUSI_SYSTEM_CODE; showModel.ActivitiesList = currList.Where(t => !string.IsNullOrWhiteSpace(t.Sub.PK_ID) && 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, ActRemark = t.Sub.ACT_REMARK, }; return runModel; }).ToList(); var subList = currList.Where(t => !string.IsNullOrWhiteSpace(t.Sub.PK_ID) && 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, ActRemark = x.ACT_REMARK }; return subModel; }).OrderBy(x => x.ExecSortNo).ToList(); } return l; }).OrderBy(t => t.ExecSortNo).ToList(); return showModel; }).ToList(); return resultList; } #endregion /// /// 手工同步历史服务状态(读取booking_goods_status同步到新的状态) /// /// 租户ID /// 349708986646597 /// [HttpGet("/ServiceWorkFlowManage/ManualSyncHistoryServiceStatus")] public async Task ManualSyncHistoryServiceStatus([FromQuery]long tenantId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); string batchNo = IDGen.NextID().ToString(); _logger.LogInformation("批次={no} 触发同步货物状态 tenantId={tenantId}", batchNo, tenantId); //同步总数 int totalSyncNum = 0; int succSyncNum = 0; long maxId = 0; try { if(tenantId == 0) throw Oops.Oh($"租户ID不能为空", typeof(InvalidOperationException)); var tenantInfo = _sysTenantRepository.AsQueryable().Filter(null, true).First(a => a.Id == tenantId); /* 1、按批次读取服务状态数据。(去掉没有完成时间的、并且订舱数据是已删除的记录) 2、写入历史记录表。 3、单票生成触发报文,并推送状态。 4、更新历史记录,标记同步状态 */ maxId =_serviceStatusBookingSyncHisInfoRepository.AsQueryable().Max(a => a.ORG_STATUS_ID); _logger.LogInformation("批次={no} 获取最后同步服务状态的ID={maxId}", batchNo, maxId); int takeNum = 1000; while (true) { var takeList = _bookingGoodsStatusRepository.AsQueryable().Filter(null, true) .InnerJoin((gs, cfg) => gs.ConfigId == cfg.Id) .InnerJoin((gs, cfg, bk) => gs.bookingId == bk.Id) .Where((gs, cfg, bk) => gs.FinishTime.HasValue && gs.TenantId == tenantId && !bk.IsDeleted && gs.FinishUserId != 142307070910551 && (maxId == 0 || gs.Id > maxId)) .OrderBy((gs, cfg, bk) => gs.Id) .Select((gs, cfg, bk) => new { GS = gs, CFG = cfg, BK = bk }) .Take(takeNum).ToList(); totalSyncNum += takeList.Count; _logger.LogInformation("批次={no} 同步待处理任务 totalSyncNum={totalSyncNum}", batchNo, totalSyncNum); //没有记录跳出循环 if (takeList.Count == 0) break; maxId = takeList.Max(a => a.GS.Id); _logger.LogInformation("批次={no} 获取最后同步服务状态的 maxId={maxId}", batchNo, maxId); //写入记录表 takeList.ForEach(async record => { var entity = new ServiceStatusBookingSyncHisInfo { PK_ID = IDGen.NextID().ToString(), ORG_STATUS_ID = record.GS.Id, BOOKING_ID = record.BK.Id, FINISH_TIME = record.GS.FinishTime.Value, FINISH_USER_ID = record.GS.FinishUserId.Value, FINISH_USER_NAME = record.GS.FinishUser, MBL_NO = record.BK.MBLNO, SORT_NO = record.CFG.Sort, STATUS_SKU_CODE = record.CFG.SystemCode, STATUS_SKU_NAME = record.CFG.StatusName, STATUS_REMARK = record.GS.Remark, STATUS_VAL = record.GS.ExtData, TENANT_ID = record.GS.TenantId.Value, TENANT_NAME = tenantInfo.Name, VESSEL = record.BK.VESSEL, VOYNO = record.BK.VOYNO, }; await _serviceStatusBookingSyncHisInfoRepository.InsertAsync(entity); succSyncNum++; }); Thread.Sleep(500); } //停用的状态(接受委托、放箱指令、已发账单、账单确认、账单已回传) string[] deletedStatusCodeArg = new string[] { "JSWTUO", "FXZLING", "YFZD", "ZDQR", "ZDYHC" }; /* 单票触发推送状态 1、取状态是null的,并且每次取前100个订舱记录。 2、按订舱记录取所有的状态记录。 3、生成触发脚本推送PUSH状态。(部分状态自动不执行) 4、执行成功后,更新对应的状态。 */ while (true) { var bookingList = _serviceStatusBookingSyncHisInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.TENANT_ID == tenantId && a.STATUS == null) .Take(100).Select(a => a.BOOKING_ID).Distinct().ToList(); //无数据跳出 if (bookingList.Count == 0) break; var taskList = _serviceStatusBookingSyncHisInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.TENANT_ID == tenantId && bookingList.Contains(a.BOOKING_ID)).ToList(); taskList.GroupBy(a => a.BOOKING_ID).ForEach(a => { DateTime currDate = DateTime.Now; var currStatusList = a.ToList(); var groupCheckList = currStatusList .Where(b=> !deletedStatusCodeArg.Contains(b.STATUS_SKU_CODE)) .GroupBy(b => b.STATUS_SKU_CODE).Select(b => { var currList = b.ToList(); if (currList.Count == 1) return currList.FirstOrDefault(); return currList.OrderByDescending(c => c.ORG_STATUS_ID).FirstOrDefault(); }).ToList(); if(groupCheckList.Count > 0) { var firstInfo = groupCheckList.FirstOrDefault(); TrackingMessageInfo msgInfo = new TrackingMessageInfo { Head = new TrackingMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "PROJECT", ReceiverId = "ServiceProjectStatus", ReceiverName = "服务项目和状态", SenderId = "BookingOrder", SenderName = "海运订舱", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "2.0", RequestAction = "AddOrModify", }, Main = new TrackingMessageMainInfo { BusiId = firstInfo.BOOKING_ID.ToString(), BusiSystemCode = "BOOKING_ORDER", MBlNo = firstInfo.MBL_NO, VesselVoyno = $"{firstInfo.VESSEL}/{firstInfo.VOYNO}", OrderNo = "", PushType = TrackingPushTypeEnum.Status, OperTenantId = firstInfo.TENANT_ID, OperTenantName = firstInfo.TENANT_NAME, OpertType = TrackingOperTypeEnum.AUTO, OperUserId = firstInfo.FINISH_USER_ID.ToString(), OperUserName = firstInfo.FINISH_USER_NAME, SourceType = TrackingSourceTypeEnum.AUTO, StatusList = groupCheckList.Select(a => new TrackingMessageMainStatusInfo { StatusCode = a.STATUS_SKU_CODE, StatusDate = a.FINISH_TIME, StatusVal = a.STATUS_VAL, Remark = a.STATUS_REMARK }).ToList() } }; //推送状态 var pushRlt = PushStatus(msgInfo).GetAwaiter().GetResult(); groupCheckList.ForEach(async t => { t.STATUS = pushRlt.succ ? "SUCC" : "FAILURE"; t.SYNC_TIME = currDate; t.SYNC_RESULT = pushRlt.msg; if (deletedStatusCodeArg.Contains(t.STATUS_SKU_CODE)) { t.STATUS = "FAILURE"; t.SYNC_RESULT = "状态已取消不再同步"; } await _serviceStatusBookingSyncHisInfoRepository.AsUpdateable(t) .UpdateColumns(it => new { it.STATUS, it.SYNC_TIME, it.SYNC_RESULT }).ExecuteCommandAsync(); }); var undoList = currStatusList.GroupJoin(groupCheckList, l => l.ORG_STATUS_ID, r => r.ORG_STATUS_ID, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) return new { IsUpdate = true, Obj = l }; return new { IsUpdate = false, Obj = l }; }).Where(c=>c.IsUpdate) .Select(c=>c.Obj).ToList(); if(undoList.Count > 0) { undoList.ForEach(async t => { t.STATUS = "FAILURE"; t.SYNC_RESULT = "状态已取最后触发记录"; t.SYNC_TIME = currDate; if (deletedStatusCodeArg.Contains(t.STATUS_SKU_CODE)) { t.SYNC_RESULT = "状态已取消不再同步"; } await _serviceStatusBookingSyncHisInfoRepository.AsUpdateable(t) .UpdateColumns(it => new { it.STATUS, it.SYNC_TIME, it.SYNC_RESULT }).ExecuteCommandAsync(); }); } } }); Thread.Sleep(500); } result.succ = true; //result.ext = resultList; } catch(Exception ex) { result.succ = false; result.msg = $"检索服务项目下的状态列表失败,原因:{ex.Message}"; } return result; } #region 检索已选中并且可用的服务项目列表(标准) /// /// 检索已选中并且可用的服务项目列表(标准) /// /// 查询服务项目和状态详情 /// 返回回执 public async Task GetEnableProjectListCommon(EmbedQueryServiceProjectWithStatus model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { //先获取可用的服务项目 var projectList = await _serviceWorkFlowBaseService.GetEnableProjectList(model.TenantId.ToString()); TrackingQueryMessageInfo messageInfo = new TrackingQueryMessageInfo { Head = new TrackingMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "PROJECT", ReceiverId = "ServiceProjectStatus", ReceiverName = "服务项目和状态", SenderId = "BookingOrder", SenderName = "海运订舱", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "2.0", RequestAction = "AddOrModify", }, Main = new TrackingMessageQueryMainInfo { BusiId = model.businessId, BusiSystemCode = "BOOKING_ORDER", TenantId = model.TenantId.ToString(), } }; //在获取运行表已有的记录 var runList = InnerGetRunListBySingleBusiness(messageInfo); var resultList = projectList.GroupJoin(runList, l => l.PKId, r => r.ServiceProjectId, (l, r) => { var currList = r.ToList(); var runInfo = currList.FirstOrDefault(); var dto = new ServiceProjectWithStatusDto { ProjectPKId = l.PKId, ProjectCode = l.ServiceProjectCode, ProjectName = l.ServiceProjectName, SortNo = l.SortNo }; if (runInfo != null) { dto.IsYield = runInfo.IsYield == 1 ? true : false; dto.ActDate = runInfo.ActDate; } return dto; }).ToList(); result.succ = true; result.ext = resultList; } catch (Exception ex) { result.succ = false; result.msg = $"检索已选中并且可用的服务项目列表失败,原因:{ex.Message}"; } return result; } #endregion #region 单票检索服务项目下的状态列表 /// /// 单票检索服务项目下的状态列表 /// /// 查询服务项目和状态详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/GetEnableStatusListByBusinessCommon")] public async Task GetEnableStatusListByBusinessCommon([FromBody] EmbedQueryServiceProjectWithStatus model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var statuList = await _serviceWorkFlowBaseService.GetEnableProjectWithStatusList(model.TenantId.ToString()); TrackingQueryMessageInfo messageInfo = new TrackingQueryMessageInfo { Head = new TrackingMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "PROJECT", ReceiverId = "ServiceProjectStatus", ReceiverName = "服务项目和状态", SenderId = "BookingOrder", SenderName = "海运订舱", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "2.0", RequestAction = "AddOrModify", }, Main = new TrackingMessageQueryMainInfo { BusiId = model.businessId, BusiSystemCode = "BOOKING_ORDER", TenantId = model.TenantId.ToString(), } }; DateTime bDate = DateTime.Now; //在获取运行表已有的记录 var runList = InnerGetRunListBySingleBusiness(messageInfo); DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.LogInformation("测试读取服务状态-读取数据库记录 耗时:{timeDiff}ms. ", timeDiff); int lastWFSortNo = 0; int calcNum = 1; //var allStatus = statuList.SelectMany(b => { // var curArg = b.StatusList.SelectMany(x => x.SubStatusList).ToList(); // if (curArg == null) // curArg = new List(); // curArg.AddRange(b.StatusList); // return curArg; //}).ToList(); var resultList = statuList.Join(runList, l => l.WFPKId, r => r.WFPKId, (l, r) => { var runInfo = r; var rltList = new List(); if (runInfo.ActivitiesList == null || (runInfo.ActivitiesList != null && runInfo.ActivitiesList.Count == 0)) { l.StatusList.ForEach(b => { rltList.Add(new ServiceProjectStatusDto { ActPKId = b.ActPKId, ActSortNo = b.ActSortNo, ShowName = b.ShowName, IsYield = false, StatusSKUCode = b.StatusSKUCode, ActRemark = b.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ActSortNo, SortNo = b.SortNo }); if (b.SubStatusList != null && b.SubStatusList.Count > 0) { rltList.AddRange(b.SubStatusList.Select(c => new ServiceProjectStatusDto { ActPKId = c.ActPKId, ActSortNo = c.ActSortNo, ShowName = c.ShowName, IsYield = false, StatusSKUCode = c.StatusSKUCode, ActRemark = c.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ActSortNo + (c.ActSortNo * 0.001m), SortNo = c.SortNo }).ToList()); } }); } else { l.StatusList.ForEach(b => { var eRunInfo = runInfo.ActivitiesList .FirstOrDefault(p => p.ActId == b.ActPKId); if (eRunInfo != null) { rltList.Add(new ServiceProjectStatusDto { ActPKId = eRunInfo.ActId, ActSortNo = eRunInfo.ExecSortNo, ShowName = eRunInfo.ShowName, IsYield = eRunInfo.IsYield == 1 ? true : false, StatusSKUCode = eRunInfo.StatusSKUCode, ActDate = eRunInfo.ActDate, ActVal = eRunInfo.ActVal, ActRemark = eRunInfo.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)eRunInfo.ExecSortNo, SortNo = b.SortNo }); } else { rltList.Add(new ServiceProjectStatusDto { ActPKId = b.ActPKId, ActSortNo = b.ActSortNo, ShowName = b.ShowName, IsYield = false, StatusSKUCode = b.StatusSKUCode, ActRemark = b.ActRemark, WFSortNo = l.SortNo, CalcSortNo = (decimal)b.ActSortNo, SortNo = b.SortNo }); } if (b.SubStatusList != null && b.SubStatusList.Count > 0) { b.SubStatusList.ForEach(sb => { ServiceWorkFlowActivitiesRunSubDto eSubRunInfo = null; if (eRunInfo != null && eRunInfo.SubList != null) { eSubRunInfo = eRunInfo.SubList .FirstOrDefault(p => p.ActId == sb.ActPKId); } if (eSubRunInfo != null) { decimal calcSort = (decimal)b.ActSortNo + (eSubRunInfo.ExecSortNo * 0.001m); if (eRunInfo != null) { calcSort = (decimal)eRunInfo.ExecSortNo + (eSubRunInfo.ExecSortNo * 0.001m); } rltList.Add(new ServiceProjectStatusDto { ActPKId = eSubRunInfo.ActId, ActSortNo = eSubRunInfo.ExecSortNo, ShowName = eSubRunInfo.ShowName, IsYield = eSubRunInfo.IsYield == 1 ? true : false, StatusSKUCode = eSubRunInfo.StatusSKUCode, ActDate = eSubRunInfo.ActDate, ActVal = eSubRunInfo.ActVal, ActRemark = eSubRunInfo.ActRemark, WFSortNo = l.SortNo, CalcSortNo = calcSort, SortNo = sb.SortNo }); } else { decimal calcSort = (decimal)b.ActSortNo + (sb.ActSortNo * 0.001m); if (eRunInfo != null) { calcSort = (decimal)eRunInfo.ExecSortNo + (sb.ActSortNo * 0.001m); } rltList.Add(new ServiceProjectStatusDto { ActPKId = sb.ActPKId, ActSortNo = sb.ActSortNo, ShowName = sb.ShowName, IsYield = false, StatusSKUCode = sb.StatusSKUCode, ActRemark = sb.ActRemark, WFSortNo = l.SortNo, CalcSortNo = calcSort, SortNo = sb.SortNo }); } }); } }); } if (rltList != null && rltList.Count > 0) { var maxSort = rltList.Max(t => t.CalcSortNo); rltList.FirstOrDefault(t => t.CalcSortNo == maxSort).IsEnd = true; } return rltList; }).SelectMany(b => b).OrderBy(b => b.WFSortNo).Select(b => { if (lastWFSortNo == 0) { b.GroupName = calcNum.ToString(); lastWFSortNo = b.WFSortNo; } else if (b.WFSortNo == lastWFSortNo) { b.GroupName = calcNum.ToString(); } else { ++calcNum; lastWFSortNo = b.WFSortNo; b.GroupName = calcNum.ToString(); } return b; }).OrderBy(b => b.WFSortNo).ThenBy(b => b.CalcSortNo).ToList(); result.succ = true; result.ext = resultList; } catch (Exception ex) { result.succ = false; result.msg = $"检索服务项目下的状态列表失败,原因:{ex.Message}"; } return result; } #endregion } }