diff --git a/Myshipping.Application/Entity/TrackingSystem/ServiceWorkFlowRunActivitiesInfo.cs b/Myshipping.Application/Entity/TrackingSystem/ServiceWorkFlowRunActivitiesInfo.cs index 217c42c6..fe8e0ddd 100644 --- a/Myshipping.Application/Entity/TrackingSystem/ServiceWorkFlowRunActivitiesInfo.cs +++ b/Myshipping.Application/Entity/TrackingSystem/ServiceWorkFlowRunActivitiesInfo.cs @@ -59,6 +59,11 @@ namespace Myshipping.Application.Entity /// public Nullable ACT_DATE { get; set; } + /// + /// 下一个活动ID + /// + public string NEXT_ACT_ID { get; set; } + /// /// 是否已产生 1-已产生 0-未产生 /// @@ -83,5 +88,20 @@ namespace Myshipping.Application.Entity /// 来源类型 AUTO-自动 MANUAL-人工 /// public string SOURCE_TYPE { get; set; } + + /// + /// 父状态主键 + /// + public string PARENT_ID { get; set;} + + /// + /// 是否子状态 1-是子状态 0-不是子状态 + /// + public int IS_SUB { get; set; } + + /// + /// 是否子状态满足一个即可 1-其中一个子状态出现即主状态触发 0-不是 + /// + public int IS_SUB_JUST { get; set; } } } diff --git a/Myshipping.Application/Entity/TrackingSystem/ServiceWorkFlowRunInfo.cs b/Myshipping.Application/Entity/TrackingSystem/ServiceWorkFlowRunInfo.cs index 4f0cc363..24fb6591 100644 --- a/Myshipping.Application/Entity/TrackingSystem/ServiceWorkFlowRunInfo.cs +++ b/Myshipping.Application/Entity/TrackingSystem/ServiceWorkFlowRunInfo.cs @@ -54,6 +54,11 @@ namespace Myshipping.Application.Entity /// public string ORDER_NO { get; set; } + /// + /// 发布版本 + /// + public string RELEASE_VERSION { get; set; } + /// /// 状态 /// diff --git a/Myshipping.Application/Service/BookingOrder/BookingOrderService.cs b/Myshipping.Application/Service/BookingOrder/BookingOrderService.cs index d4715cc2..1a125b1a 100644 --- a/Myshipping.Application/Service/BookingOrder/BookingOrderService.cs +++ b/Myshipping.Application/Service/BookingOrder/BookingOrderService.cs @@ -206,6 +206,12 @@ namespace Myshipping.Application [HttpPost("/BookingOrder/PageData")] public async Task PageData(BookingOrderInput input) { + var traceTime = false; + var ticks = DateTime.Now; + if (traceTime) + { + _logger.LogInformation($"PageData Stage 0 "); + } List userlist = await _right.GetDataScopeList(MenuConst.MenuBookingOrder); List pidlist = new List(); @@ -217,6 +223,13 @@ namespace Myshipping.Application var etoday = DateTime.Now.AddDays(15); //List userlist = await DataFilterExtensions.GetDataScopeIdList(); + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"PageData Stage 1 {et.TotalMilliseconds}"); + } + //按部门查询 List saleUserList = null; List opUserList = null; @@ -232,6 +245,13 @@ namespace Myshipping.Application opUserList = tmpList.Select(x => x.ToString()).ToList(); } + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"PageData Stage 2 {et.TotalMilliseconds}"); + } + #region var query = _rep.AsQueryable().Filter(null, true).Where(x => x.TenantId == UserManager.TENANT_ID) .WhereIF(!input.ISDel, x => x.IsDeleted == false) @@ -403,7 +423,23 @@ namespace Myshipping.Application #endregion var entities = await query.ToPagedListAsync(input.PageNo, input.PageSize); + + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"PageData Stage 3 {et.TotalMilliseconds}"); + } + var list = entities.Adapt>(); + + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"PageData Stage 4 {et.TotalMilliseconds}"); + } + var bookingidlist = list.Items.Select(x => x.Id).ToList(); var itgoodsStatus = _goodsStatus.AsQueryable().LeftJoin(_goodsStatusConfig.AsQueryable(), (goods, config) => config.Id == goods.ConfigId && bookingidlist.Contains((long)goods.bookingId)). @@ -420,7 +456,7 @@ namespace Myshipping.Application CreatedUserId = config.CreatedUserId, Sort = config.Sort }).ToList(); - var configID = itgoodsStatus.Select(x => x.ConfigId).ToList(); + var configID = itgoodsStatus.Select(x => x.ConfigId).Distinct().ToList(); var itconfigs = _goodsStatusConfig.AsQueryable().Where(x => configID.Contains(x.Id)).Select(config => new { @@ -435,12 +471,28 @@ namespace Myshipping.Application Sort = config.Sort }).ToList(); + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"PageData Stage 5 {et.TotalMilliseconds}"); + } + var statusloglist = _repStatuslog.AsQueryable().Filter(null, true).Where(x => bookingidlist.Contains((long)x.BookingId) && (x.Status == "提箱" || x.Status == "返场") && x.IsDeleted == false).ToList(); var statuslogId = statusloglist.Select(x => x.Id).ToList(); var statuslogdetaillist = _statuslogdetail.AsQueryable().Where(x => statuslogId.Contains(x.PId)).ToList(); var BookingStatusList = _repBookingStatus.AsQueryable().Filter(null, true).Where(x => bookingidlist.Contains((long)x.BookingId)).ToList(); var bookingremarkList = _bookingremark.AsQueryable().Filter(null, true).Where(x => bookingidlist.Contains(x.PId)).ToList(); + + + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"PageData Stage 6 {et.TotalMilliseconds}"); + } + foreach (var item in list.Items) { var sta = BookingStatusList.Where(x => x.BookingId == item.Id).ToList(); @@ -587,6 +639,14 @@ namespace Myshipping.Application item.statuslogs1 = CNTRNODtolist; } + + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"PageData Stage 7 {et.TotalMilliseconds}"); + } + return list; } @@ -732,14 +792,14 @@ namespace Myshipping.Application { var mlist = await _rep.AsQueryable().Filter(null, true).Where(x => x.Id == input.Id).FirstAsync(); - var rightlist= await _right.GetDataScopeList(MenuConst.MenuBookingOrder,true); + var rightlist = await _right.GetDataScopeList(MenuConst.MenuBookingOrder, true); if (!( - mlist.OPID == UserManager.UserId.ToString() || + mlist.OPID == UserManager.UserId.ToString() || mlist.DOCID == UserManager.UserId.ToString() || mlist.CUSTSERVICEID == UserManager.UserId.ToString() || mlist.ROUTEID == UserManager.UserId.ToString() || mlist.CreatedUserId.ToString() == UserManager.UserId.ToString() || - UserManager.DjyUserId == "d85fd590-d9f6-4410-93a1-f6fac77b606e"|| + UserManager.DjyUserId == "d85fd590-d9f6-4410-93a1-f6fac77b606e" || rightlist.Contains((long)mlist.CreatedUserId) )) { @@ -7616,7 +7676,12 @@ namespace Myshipping.Application public async Task GetAllData(long bookingId) { - + var traceTime = false; + var ticks = DateTime.Now; + if (traceTime) + { + _logger.LogInformation($"{bookingId} GetAllData Stage 0 "); + } BookingAllData allData = new BookingAllData(); if (bookingId == 0) @@ -7631,6 +7696,13 @@ namespace Myshipping.Application var filelist = await _bookingfile.AsQueryable().Filter(null, true).Where(u => u.BookingId == bookingId).ToListAsync(); allData.file = filelist; + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"GetAllData Stage 1 {et.TotalMilliseconds}"); + } + var statuslog = await _repStatuslog.AsQueryable().Filter(null, true).Where(x => x.BookingId == bookingId).OrderByDescending(x => x.CreatedTime).ToListAsync(); var dto = statuslog.Adapt>(); var statuslogdetail = await _statuslogdetail.AsQueryable().ToListAsync(); @@ -7641,6 +7713,13 @@ namespace Myshipping.Application } allData.statuslog = dto; + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"GetAllData Stage 2 {et.TotalMilliseconds}"); + } + List list = new List(); var main = await _bookinglog.AsQueryable().Where(u => u.BookingId == bookingId).ToListAsync(); list = main.Adapt>(); @@ -7656,6 +7735,13 @@ namespace Myshipping.Application allData.log = list; + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"GetAllData Stage 3 {et.TotalMilliseconds}"); + } + var order = _rep.Where(x => x.Id == bookingId).First(); var userid = order.CreatedUserId; var username = order.CreatedUserName; @@ -7663,6 +7749,12 @@ namespace Myshipping.Application { _GoodsConfig.InitGoodsStatusConfig(Convert.ToInt64(userid), username); + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"GetAllData Stage 4 {et.TotalMilliseconds}"); + } var GoodsStatus = await _goodsStatus.AsQueryable().LeftJoin(_goodsStatusConfig.AsQueryable(), (goods, config) => config.Id == goods.ConfigId).Where((goods, config) => config.CreatedUserId == userid && goods.bookingId == bookingId). @@ -7682,6 +7774,13 @@ namespace Myshipping.Application Sort = config.Sort }).ToListAsync(); + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"GetAllData Stage 5 {et.TotalMilliseconds}"); + } + var config = _goodsStatusConfig.AsQueryable().Where(config => config.CreatedUserId == userid).ToList().Select(config => new GoodsStatusQuery { @@ -7697,6 +7796,13 @@ namespace Myshipping.Application Sort = config.Sort }).ToList(); + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"GetAllData Stage 6 {et.TotalMilliseconds}"); + } + foreach (var item in GoodsStatus) { config.RemoveAll(x => x.ConfigId == item.ConfigId); @@ -7706,6 +7812,13 @@ namespace Myshipping.Application allData.GoodsStatus = GoodsStatus.Union(config).OrderBy(x => x.Sort).ToList(); + + if (traceTime) + { + var et = DateTime.Now - ticks; + ticks = DateTime.Now; + _logger.LogInformation($"GetAllData Stage 7 {et.TotalMilliseconds}"); + } } diff --git a/Myshipping.Application/Service/TrackingSystem/Dtos/TrackingMessageInfo.cs b/Myshipping.Application/Service/TrackingSystem/Dtos/TrackingMessageInfo.cs new file mode 100644 index 00000000..3aa95c23 --- /dev/null +++ b/Myshipping.Application/Service/TrackingSystem/Dtos/TrackingMessageInfo.cs @@ -0,0 +1,196 @@ +using Furion.DistributedIDGenerator; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Myshipping.Application +{ + /// + /// 追踪报文 + /// + public class TrackingMessageInfo + { + /// + /// 表头 + /// + public TrackingMessageHeadInfo Head { get; set; } + + /// + /// 表体 + /// + public TrackingMessageMainInfo Main { get; set; } + } + + public class TrackingMessageHeadInfo + { + /// + /// 报文惟一主键 + /// + ///08dabd4e-dcc3-471a-8031-cf066ed0a8f4 + public string GID { get; set; } = IDGen.NextID().ToString(); + + /// + /// 报文类型 TASK-任务 + /// + /// TASK + [Required(ErrorMessage = "必填")] + public string MessageType { get; set; } + + /// + /// 发送方代码 + /// + /// MAIL_PARSE + [Required(ErrorMessage = "必填")] + public string SenderId { get; set; } + + /// + /// 发送方名称 + /// + /// 邮件解析 + [Required(ErrorMessage = "必填")] + public string SenderName { get; set; } + + /// + /// 接收方代码 + /// + /// TaskManage + [Required(ErrorMessage = "必填")] + public string ReceiverId { get; set; } + + /// + /// 接收方名称 + /// + /// 任务管理平台 + [Required(ErrorMessage = "必填")] + public string ReceiverName { get; set; } + + /// + /// 请求方登录TOKEN(可以是真实的登录人TOKEN或者是服务模拟登录人TOKEN) + /// + /// eyJhbGciOiJSUzI1NiIsImtpZCI6IkQ1RTkxMDI5OUU0RURFNUZEM0EwNTJBMEFDRDUzMUQzIiwidHlwIjoiYXQrand0In0 + public string Token { get; set; } + + /// + /// 版本号 默认1.0 + /// + /// 1.0 + [Required(ErrorMessage = "必填")] + public string Version { get; set; } = "1.0"; + + /// + /// 请求时间 + /// + /// 2022-12-23 14:29:11 + public string RequestDate { get; set; } + + /// + /// 请求授权KEY + /// + /// testkey + public string SenderKey { get; set; } + + /// + /// 请求操作类型 + /// + /// Add + [Required(ErrorMessage = "必填")] + public string RequestAction { get; set; } = "Add"; + } + + public class TrackingMessageMainInfo + { + /// + /// 业务系统代码 + /// + [Required(ErrorMessage = "必填")] + public string BusiSystemCode { get; set; } + + /// + /// 业务主键 + /// + public string BusiId { get; set;} + + /// + /// 提单号 + /// + public string MBlNo { get; set; } + + /// + /// 船名航次 + /// + public string VesselVoyno { get; set; } + + /// + /// 订舱编号 + /// + public string OrderNo { get; set; } + + /// + /// 任务对应接收操作人ID + /// + public string RecvUserId { get; set; } + + /// + /// 任务对应接收操作人名称 + /// + public string RecvUserName { get; set; } + + /// + /// 任务对应接收操作人ID(大简云账户体系) + /// + public string DJYRecvUserId { get; set; } + + /// + /// 任务对应接收操作人名称(大简云账户体系) + /// + public string DJYRecvUserName { get; set; } + + /// + /// 任务对应接收操作人邮箱(大简云账户体系) + /// + public string DJYRecvUserEmail { get; set; } + + /// + /// 任务对应部门代码(大简云账户体系) + /// + public string DJYTaskOrgCode { get; set; } + + /// + /// 任务对应部门名称(大简云账户体系) + /// + public string DJYTaskOrgName { get; set; } + + /// + /// 状态列表 + /// + public List StatusList { get; set; } + } + + public class TrackingMessageMainStatusInfo + { + /// + /// 状态代码 + /// + [Required(ErrorMessage = "必填")] + public string StatusCode { get; set; } + + /// + /// 状态名称 + /// + [Required(ErrorMessage = "必填")] + public string StatusName { get; set; } + + /// + /// 状态产生时间 + /// + public DateTime StatusDate { get; set; } + + /// + /// 状态产生值 + /// + public string StatusVal { get; set; } + } +} diff --git a/Myshipping.Application/Service/TrackingSystem/Interface/IServiceWorkFlowBaseService.cs b/Myshipping.Application/Service/TrackingSystem/Interface/IServiceWorkFlowBaseService.cs index b578cd4a..a37b1558 100644 --- a/Myshipping.Application/Service/TrackingSystem/Interface/IServiceWorkFlowBaseService.cs +++ b/Myshipping.Application/Service/TrackingSystem/Interface/IServiceWorkFlowBaseService.cs @@ -10,7 +10,7 @@ namespace Myshipping.Application /// /// 服务流程 /// - internal interface IServiceWorkFlowBaseService + public interface IServiceWorkFlowBaseService { /// /// 保存 @@ -98,5 +98,12 @@ namespace Myshipping.Application /// 保存服务流程活动详情 /// 返回回执 Task SaveWFActivities(ServiceWorkFlowActivitiesDto info); + + /// + /// 通过服务活动主键获取所有相关服务流程列表 + /// + /// 服务活动主键数组 + /// 返回回执 + Task GetServiceWorkFlowListByActivities(string[] activitiesArgs); } } diff --git a/Myshipping.Application/Service/TrackingSystem/Interface/IServiceWorkFlowManageService.cs b/Myshipping.Application/Service/TrackingSystem/Interface/IServiceWorkFlowManageService.cs index 8b3f8799..cdc0c7f1 100644 --- a/Myshipping.Application/Service/TrackingSystem/Interface/IServiceWorkFlowManageService.cs +++ b/Myshipping.Application/Service/TrackingSystem/Interface/IServiceWorkFlowManageService.cs @@ -9,14 +9,14 @@ namespace Myshipping.Application /// /// 服务流程管理 /// - internal interface IServiceWorkFlowManageService + public interface IServiceWorkFlowManageService { /// /// 推送状态 /// - /// 服务流程详情 + /// 服务流程报文详情 /// 返回回执 - Task PushStatus(ServiceWorkFlowBaseDto info); + Task PushStatus(TrackingMessageInfo info); /// diff --git a/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowBaseService.cs b/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowBaseService.cs index f068aaf4..3d06539c 100644 --- a/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowBaseService.cs +++ b/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowBaseService.cs @@ -12,6 +12,8 @@ using Myshipping.Application.Helper; using Myshipping.Core; using Myshipping.Core.Entity; using MySqlX.XDevAPI.Common; +using NPOI.SS.Formula.PTG; +using NPOI.Util; using SqlSugar; using StackExchange.Profiling.Internal; using System; @@ -26,7 +28,7 @@ namespace Myshipping.Application /// /// 服务流程 /// - [ApiDescriptionSettings("Application", Name = "ServiceWorkFlowBase", Order = 10)] + [ApiDescriptionSettings("Application", Name = "ServiceWorkFlowBase", Order = 20)] public class ServiceWorkFlowBaseService : IServiceWorkFlowBaseService, IDynamicApiController, ITransient { private readonly SqlSugarRepository _serviceWorkFlowBaseRepository; @@ -420,17 +422,6 @@ namespace Myshipping.Application 1、获取关联的服务项目(单条) 2、获取关联的服务活动列表(多条) */ - - var projectInfo = _serviceWorkFlowProjectRelationRepository.AsQueryable() - .LeftJoin((rela, prj) => rela.SERVICE_PROJECT_ID == prj.PK_ID) - .Where(rela => rela.SERVICE_WORKFLOW_ID == pkId) - .Select((rela, prj) => prj).First(); - - if (projectInfo != null) - { - showModel.ServiceProject = projectInfo.Adapt(); - } - string currVersion = string.Empty; if(!string.IsNullOrWhiteSpace(model.DEVELOP_VERSION)) @@ -442,6 +433,16 @@ namespace Myshipping.Application currVersion = model.RELEASE_VERSION; } + var projectInfo = _serviceWorkFlowProjectRelationRepository.AsQueryable() + .LeftJoin((rela, prj) => rela.SERVICE_PROJECT_ID == prj.PK_ID) + .Where(rela => rela.SERVICE_WORKFLOW_ID == pkId && rela.WF_VERSION == currVersion) + .Select((rela, prj) => prj).First(); + + if (projectInfo != null) + { + showModel.ServiceProject = projectInfo.Adapt(); + } + var activitiesList = _serviceWorkFlowActivitiesRelationRepository.AsQueryable() .LeftJoin((rela, act) => rela.SERVICE_ACTIVITIES_ID == act.PK_ID && rela.SERVICE_WORKFLOW_ID == pkId && rela.WF_VERSION == currVersion) @@ -512,6 +513,150 @@ namespace Myshipping.Application } #endregion + /// + /// 通过服务活动主键获取所有相关服务流程列表 + /// + /// 服务活动主键数组 + /// 返回回执 + [HttpPost("/ServiceWorkFlowBase/GetServiceWorkFlowListByActivities")] + public async Task GetServiceWorkFlowListByActivities([FromBody]string[] activitiesArgs) + { + TaskManageOrderResultDto result = new TaskManageOrderResultDto(); + + try + { + /* + 1、通过服务活动ID获取所有关联的服务流程详情列表 + 2、轮询服务流程列表,组织详细的服务流程列表 + */ + var activitiesList = _serviceWorkFlowActivitiesRelationRepository.AsQueryable() + .LeftJoin((rela, wf) => rela.SERVICE_WORKFLOW_ID == wf.PK_ID) + .Where((rela,wf) => activitiesArgs.Contains(rela.SERVICE_ACTIVITIES_ID) + && !wf.IsDeleted && wf.IS_ENABLE == 1 && !string.IsNullOrWhiteSpace(wf.RELEASE_VERSION)) + .Select((rela, wf) => wf).Distinct().ToList(); + + var subActList = _serviceWorkFlowActivitiesSubRelationRepository.AsQueryable() + .LeftJoin((rela, wf) => rela.SERVICE_WORKFLOW_ID == wf.PK_ID) + .Where((rela, wf) => activitiesArgs.Contains(rela.SUB_SERVICE_ACTIVITIES_ID) + && !wf.IsDeleted && wf.IS_ENABLE == 1 && !string.IsNullOrWhiteSpace(wf.RELEASE_VERSION)) + .Select((rela, wf) => wf).Distinct().ToList(); + + if(subActList.Count > 0) + { + activitiesList.AddRange(subActList); + //去重 + activitiesList = activitiesList.Distinct().ToList(); + } + + if(activitiesList.Count == 0) + { + _logger.LogInformation($"{JSON.Serialize(activitiesArgs)} 未检索到有效服务流程"); + + throw Oops.Oh("未检索到有效服务流程", typeof(InvalidOperationException)); + } + + var wfArg = activitiesList.Select(a => a.PK_ID).ToArray(); + + var mergeList = + _serviceWorkFlowBaseRepository.AsQueryable() + .LeftJoin((wf, rela) => wf.PK_ID == rela.SERVICE_WORKFLOW_ID + && wf.RELEASE_VERSION == rela.WF_VERSION) + .Where(wf => wfArg.Contains(wf.PK_ID)) + .Select((wf, rela) => new { WF = wf, Rela = rela }) + .LeftJoin((rela, act) => + rela.Rela.SERVICE_ACTIVITIES_ID == act.PK_ID) + .LeftJoin((rela, act, sku) => + act.STATUS_SKU_ID == sku.PK_ID) + .Select((rela, act, sku) => + new { WF = rela.WF, Act = act, Sku = sku, SortNo = rela.Rela.SORT_NO, IsSub = rela.Rela.IS_CONTAINS_SUB, ValType = rela.Rela.VAL_TYPE }) + .ToList(); + + var mergeSubList = + _serviceWorkFlowBaseRepository.AsQueryable() + .LeftJoin((wf, rela) => wf.PK_ID == rela.SERVICE_WORKFLOW_ID + && wf.RELEASE_VERSION == rela.WF_VERSION) + .Where(wf => wfArg.Contains(wf.PK_ID)) + .Select((wf, rela) => new { WF = wf, Rela = rela }) + .LeftJoin((rela, act) => + rela.Rela.SUB_SERVICE_ACTIVITIES_ID == act.PK_ID) + .LeftJoin((rela, act, sku) => + act.STATUS_SKU_ID == sku.PK_ID) + .Select((rela, act, sku) => + new { WF = rela.WF, Act = act, Sku = sku, SortNo = rela.Rela.SORT_NO, ParentId = rela.Rela.SERVICE_ACTIVITIES_ID, ValType = rela.Rela.VAL_TYPE }) + .ToList(); + + + var prjectList = _serviceWorkFlowBaseRepository.AsQueryable() + .LeftJoin((wf, rela) => wf.PK_ID == rela.SERVICE_WORKFLOW_ID + && wf.RELEASE_VERSION == rela.WF_VERSION) + .Select((wf,rela)=> new { WF = wf, Rela = rela }) + .LeftJoin((rela, prj) => + rela.Rela.SERVICE_PROJECT_ID == prj.PK_ID) + .Select((rela, prj) => new{ WF = rela.WF, Rela = rela.Rela,Prj = prj }).ToList(); + + + var list = mergeList.GroupBy(a => a.WF.PK_ID) + .Select(a => { + var model = a.FirstOrDefault().WF; + + var showModel = model.Adapt(); + + showModel.StatusSkuList = a.ToList().OrderBy(a => a.SortNo) + .Select(a => + { + var actModel = a.Act.Adapt(); + + actModel.SortNo = a.SortNo; + actModel.IsContainsSub = a.IsSub; + actModel.ValType = a.ValType; + actModel.statusSkuBase = a.Sku.Adapt(); + + if(a.IsSub == 1) + { + actModel.SubList = mergeSubList.Where( + b => + b.WF.PK_ID == a.WF.PK_ID && b.Act.PK_ID == a.Act.PK_ID).OrderBy(b => b.SortNo) + .Select(b => + { + + var actModel = b.Act.Adapt(); + + actModel.SortNo = b.SortNo; + actModel.statusSkuBase = b.Sku.Adapt(); + + return actModel; + }).ToList(); + } + + return actModel; + }).ToList(); + + return showModel; + }).ToList(); + + list = list.GroupJoin(prjectList, l => l.PKId, + r => r.WF.PK_ID, + (l, r) => + { + var currList = r.ToList(); + + l.ServiceProject = currList.FirstOrDefault().Prj.Adapt(); + + return l; + }).ToList(); + + result.succ = true; + result.ext = list; + } + catch (Exception ex) + { + result.succ = false; + result.msg = $"保存服务流程活动异常,原因:{ex.Message}"; + } + + return result; + } + #region 保存并启用 /// /// 保存并启用 diff --git a/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowManageService.cs b/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowManageService.cs index d98eaac9..b8a859b4 100644 --- a/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowManageService.cs +++ b/Myshipping.Application/Service/TrackingSystem/ServiceWorkFlowManageService.cs @@ -1,6 +1,17 @@ using Furion.DependencyInjection; +using Furion.DistributedIDGenerator; using Furion.DynamicApiController; +using Furion.FriendlyException; +using Furion.JsonSerialization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Myshipping.Application.Entity; +using Myshipping.Core; +using Myshipping.Core.Entity; +using NPOI.SS.Formula.Functions; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Ocsp; +using StackExchange.Profiling.Internal; using System; using System.Collections.Generic; using System.Linq; @@ -12,23 +23,324 @@ namespace Myshipping.Application /// /// 服务流程管理 /// - [ApiDescriptionSettings("Application", Name = "ServiceWorkFlowManage", Order = 10)] + [ApiDescriptionSettings("Application", Name = "ServiceWorkFlowManage", Order = 30)] public class ServiceWorkFlowManageService : IServiceWorkFlowManageService, IDynamicApiController, ITransient { - public ServiceWorkFlowManageService() + 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 IServiceWorkFlowBaseService _serviceWorkFlowBaseService; + + public ServiceWorkFlowManageService(SqlSugarRepository serviceWorkFlowBaseRepository, + ILogger logger, + SqlSugarRepository serviceWorkFlowActivitiesInfoRepository, + SqlSugarRepository serviceWorkFlowProjectRelationRepository, + SqlSugarRepository serviceWorkFlowActivitiesRelationRepository, + SqlSugarRepository serviceWorkFlowActivitiesSubRelationRepository, + SqlSugarRepository serviceWorkFlowReleaseInfoRepository, + SqlSugarRepository serviceWorkFlowRunInfoRepository, + SqlSugarRepository serviceWorkFlowRunActivitiesInfoRepository, + SqlSugarRepository statusSkuBaseInfoRepository, + IServiceWorkFlowBaseService serviceWorkFlowBaseService, SqlSugarRepository sysUserRepository) { + _serviceWorkFlowBaseRepository = serviceWorkFlowBaseRepository; + _serviceWorkFlowActivitiesInfoRepository = serviceWorkFlowActivitiesInfoRepository; + _serviceWorkFlowProjectRelationRepository = serviceWorkFlowProjectRelationRepository; + _serviceWorkFlowActivitiesRelationRepository = serviceWorkFlowActivitiesRelationRepository; + + _logger = logger; + _serviceWorkFlowActivitiesSubRelationRepository = serviceWorkFlowActivitiesSubRelationRepository; + _serviceWorkFlowReleaseInfoRepository = serviceWorkFlowReleaseInfoRepository; + _serviceWorkFlowRunInfoRepository = serviceWorkFlowRunInfoRepository; + _serviceWorkFlowRunActivitiesInfoRepository = serviceWorkFlowRunActivitiesInfoRepository; + _statusSkuBaseInfoRepository = statusSkuBaseInfoRepository; + _serviceWorkFlowBaseService = serviceWorkFlowBaseService; + _sysUserRepository = sysUserRepository; } + + #region 推送状态 /// /// 推送状态 /// /// 服务流程详情 /// 返回回执 [HttpPost("/ServiceWorkFlowManage/PushStatus")] - public async Task PushStatus([FromBody] ServiceWorkFlowBaseDto info) + public async Task PushStatus([FromBody] TrackingMessageInfo info) { - return new TaskManageOrderResultDto(); - } + 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 = null; + + //如果大简云用户ID不为空,接收人为空时,通过大简云用户ID关联订舱人ID + if (!string.IsNullOrWhiteSpace(info.Main.DJYRecvUserId)) + { + userTendInfo = GetUserTendInfoByDJYUserId(info.Main.DJYRecvUserId, info.Main.DJYRecvUserEmail); + } + else + { + userTendInfo = GetUserTendInfo(info.Main.RecvUserId); + } + + //根据状态编号检索对应的状态和活动信息,如果已经提取到的状态数量与推送的不一致不能直接返回错误 + var skuList = _statusSkuBaseInfoRepository.AsQueryable() + .LeftJoin((sts, act) => sts.PK_ID == act.STATUS_SKU_ID) + .Where((sts, act) => statusArg.Contains(sts.STATUS_SKU_CODE) && !sts.IsDeleted && sts.IS_ENABLE == 1 + && !act.IsDeleted) + .Select((sts, act) => new { Sku = sts, Act = act }).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() + .LeftJoin( + (m, s) => m.PK_ID == s.RUN_ID) + .Where((m, s) => m.BUSI_ID == info.Main.BusiId + && m.BUSI_SYSTEM_CODE.Equals(info.Main.BusiSystemCode) && !m.IsDeleted && !s.IsDeleted) + .Select((m, s) => new { main = m, sub = s }).ToList(); + + //如果有已经运行的业务主键则只补充对应的活动表 + if(runList.Count > 0) + { + 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(); + }); + } + else + { + 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)); + } + + DateTime nowDate = DateTime.Now; + + var list = JSON.Deserialize>(JSON.Serialize(wfRlt.ext)); + + 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 + }; + + 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, + ACT_DATE = currReq.Req.StatusDate, + ACT_VAL = currReq.Req.StatusVal, + STATUS_SKU_CODE = sku.statusSkuBase.StatusSKUCode, + STATUS_SKU_ID = sku.StatusSKUId, + SHOW_NAME = sku.ShowName, + IS_SUB = 0, + IS_SUB_JUST = 0, + IS_YIELD = 1, + CreatedTime = nowDate, + UpdatedTime = nowDate, + CreatedUserId = userTendInfo.userId, + CreatedUserName = userTendInfo.userName, + TenantId = userTendInfo.tendId, + TenantName = userTendInfo.tenantName, + IsDeleted = false, + SOURCE_TYPE = "AUTO" + }; + + 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, + ACT_DATE = currSubReq.Req.StatusDate, + ACT_VAL = currSubReq.Req.StatusVal, + STATUS_SKU_CODE = sub.statusSkuBase.StatusSKUCode, + STATUS_SKU_ID = sub.StatusSKUId, + SHOW_NAME = sub.ShowName, + IS_SUB = 1, + IS_SUB_JUST = 1, + IS_YIELD = 1, + CreatedTime = nowDate, + UpdatedTime = nowDate, + CreatedUserId = userTendInfo.userId, + CreatedUserName = userTendInfo.userName, + TenantId = userTendInfo.tendId, + TenantName = userTendInfo.tenantName, + IsDeleted = false, + SOURCE_TYPE = "AUTO" + }; + + 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 /// /// 查询单票业务单服务项目查询 @@ -52,6 +364,69 @@ namespace Myshipping.Application { return new TaskManageOrderResultDto(); } + + #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 } }