You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
BookingHeChuan/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowManageServic...

1082 lines
53 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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.Extensions.Logging;
using Microsoft.Extensions.Options;
using Myshipping.Application.Entity;
using Myshipping.Core;
using Myshipping.Core.Entity;
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.Tasks;
namespace Myshipping.Application
{
/// <summary>
/// 服务流程管理
/// </summary>
[AllowAnonymous, ApiDescriptionSettings("Application", Name = "ServiceWorkFlowManage", Order = 20)]
public class ServiceWorkFlowManageService : IServiceWorkFlowManageService, IDynamicApiController, ITransient
{
private readonly ILogger<ServiceWorkFlowManageService> _logger;
private readonly SqlSugarRepository<ServiceWorkFlowBaseInfo> _serviceWorkFlowBaseRepository;
private readonly SqlSugarRepository<ServiceWorkFlowActivitiesInfo> _serviceWorkFlowActivitiesInfoRepository;
private readonly SqlSugarRepository<ServiceWorkFlowProjectRelation> _serviceWorkFlowProjectRelationRepository;
private readonly SqlSugarRepository<ServiceWorkFlowActivitiesRelation> _serviceWorkFlowActivitiesRelationRepository;
private readonly SqlSugarRepository<ServiceWorkFlowActivitiesSubRelation> _serviceWorkFlowActivitiesSubRelationRepository;
private readonly SqlSugarRepository<ServiceWorkFlowReleaseInfo> _serviceWorkFlowReleaseInfoRepository;
private readonly SqlSugarRepository<ServiceWorkFlowRunInfo> _serviceWorkFlowRunInfoRepository;
private readonly SqlSugarRepository<ServiceWorkFlowRunActivitiesInfo> _serviceWorkFlowRunActivitiesInfoRepository;
private readonly SqlSugarRepository<StatusSkuBaseInfo> _statusSkuBaseInfoRepository;
private readonly SqlSugarRepository<SysUser> _sysUserRepository;
private readonly SqlSugarRepository<ServiceProjectBaseInfo> _serviceProjectBaseInfoRepository;
private readonly SqlSugarRepository<ServiceWorkFlowRunLogInfo> _serviceWorkFlowRunLogInfoRepository;
private readonly ICache _cache;
private readonly CacheOptions _cacheOptions;
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<ServiceWorkFlowBaseInfo> serviceWorkFlowBaseRepository,
ILogger<ServiceWorkFlowManageService> logger,
SqlSugarRepository<ServiceWorkFlowActivitiesInfo> serviceWorkFlowActivitiesInfoRepository,
SqlSugarRepository<ServiceWorkFlowProjectRelation> serviceWorkFlowProjectRelationRepository,
SqlSugarRepository<ServiceWorkFlowActivitiesRelation> serviceWorkFlowActivitiesRelationRepository,
SqlSugarRepository<ServiceWorkFlowActivitiesSubRelation> serviceWorkFlowActivitiesSubRelationRepository,
SqlSugarRepository<ServiceWorkFlowReleaseInfo> serviceWorkFlowReleaseInfoRepository,
SqlSugarRepository<ServiceWorkFlowRunInfo> serviceWorkFlowRunInfoRepository,
SqlSugarRepository<ServiceWorkFlowRunActivitiesInfo> serviceWorkFlowRunActivitiesInfoRepository,
SqlSugarRepository<StatusSkuBaseInfo> statusSkuBaseInfoRepository,
IServiceWorkFlowBaseService serviceWorkFlowBaseService, SqlSugarRepository<SysUser> sysUserRepository,
SqlSugarRepository<ServiceProjectBaseInfo> serviceProjectBaseInfoRepository,
SqlSugarRepository<ServiceWorkFlowRunLogInfo> serviceWorkFlowRunLogInfoRepository,
IOptions<CacheOptions> cacheOptions, Func<string, ISingleton, object> resolveNamed)
{
_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;
_cacheOptions = cacheOptions.Value;
_cache = resolveNamed(_cacheOptions.CacheType.ToString(), default) as ICache;
}
#region 推送状态
/// <summary>
/// 推送状态
/// </summary>
/// <param name="info">服务流程详情</param>
/// <returns>返回回执</returns>
[HttpPost("/ServiceWorkFlowManage/PushStatus")]
public async Task<TaskManageOrderResultDto> 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<ServiceWorkFlowActivitiesInfo>((sts, act) => sts.PK_ID == act.STATUS_SKU_ID)
.LeftJoin<ServiceWorkFlowActivitiesRelation>((sts,act,rela)=>
act.PK_ID == rela.SERVICE_ACTIVITIES_ID)
.LeftJoin<ServiceWorkFlowBaseInfo>((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<ServiceWorkFlowRunActivitiesInfo>(
(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<List<ServiceWorkFlowBaseShowDto>>(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 单票单服务项目查询
/// <summary>
/// 单票单服务项目查询
/// </summary>
/// <param name="info">查询服务流程详情</param>
/// <returns>返回回执</returns>
[HttpPost("/ServiceWorkFlowManage/QuerySingleBusinessPerServiceProject")]
public async Task<TaskManageOrderResultDto> 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<ServiceWorkFlowRunActivitiesInfo>((m, s) => m.PK_ID == s.RUN_ID)
.LeftJoin<ServiceWorkFlowProjectRelation>((m, s, rela) =>
m.SERVICE_WF_ID == rela.SERVICE_WORKFLOW_ID && m.RELEASE_VERSION == rela.WF_VERSION)
.LeftJoin<ServiceProjectBaseInfo>((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 单票所有相关服务项目查询
/// <summary>
/// 单票所有相关服务项目查询
/// </summary>
/// <param name="info">查询服务流程详情</param>
/// <returns>返回回执</returns>
[HttpPost("/ServiceWorkFlowManage/QuerySingleBusinessAll")]
public async Task<TaskManageOrderResultDto> 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<ServiceWorkFlowRunActivitiesInfo>((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
/// <summary>
/// 取消状态
/// </summary>
/// <param name="info">服务流程报文详情</param>
/// <returns>返回回执</returns>
[HttpPost("/ServiceWorkFlowManage/CancelStatus")]
public async Task<TaskManageOrderResultDto> 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<ServiceWorkFlowActivitiesInfo>((sts, act) => sts.PK_ID == act.STATUS_SKU_ID)
.LeftJoin<ServiceWorkFlowActivitiesRelation>((sts, act, rela) =>
act.PK_ID == rela.SERVICE_ACTIVITIES_ID)
.LeftJoin<ServiceWorkFlowBaseInfo>((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<ServiceWorkFlowRunActivitiesInfo>(
(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<List<ServiceWorkFlowBaseShowDto>>(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 查询订舱表查询用户和租户信息
/// <summary>
/// 查询订舱表查询用户和租户信息
/// </summary>
/// <param name="djyUserId">大简云用户ID</param>
/// <param name="djyUserEmail">大简云用户邮箱</param>
/// <returns>返回用户和租户信息</returns>
private UserTendDto GetUserTendInfoByDJYUserId(string djyUserId, string djyUserEmail)
{
UserTendDto userTendDto = null;
//这里因为接口是不做授权验证的所以这里直接写的动态sql提取了用户和租户信息
var userTendInfo = _sysUserRepository.EntityContext.Queryable<dynamic>("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 查询订舱表查询用户和租户信息
/// <summary>
/// 查询订舱表查询用户和租户信息
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>返回用户和租户信息</returns>
private UserTendDto GetUserTendInfo(string userId)
{
UserTendDto userTendDto = null;
//这里因为接口是不做授权验证的所以这里直接写的动态sql提取了用户和租户信息
var userTendInfo = _sysUserRepository.EntityContext.Queryable<dynamic>("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
/// <summary>
/// 查询当前租户下可用服务项目与状态详情
/// </summary>
/// <param name="info">查询服务项目请求报文</param>
/// <returns>返回回执</returns>
[HttpPost("/ServiceWorkFlowManage/QueryServiceInfo")]
public async Task<TaskManageOrderResultDto> 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;
}
}
}