diff --git a/ds-wms-service/DS.Module.Core/Condition/ConditionContent.cs b/ds-wms-service/DS.Module.Core/Condition/ConditionContent.cs index 650caa1c..036e4e94 100644 --- a/ds-wms-service/DS.Module.Core/Condition/ConditionContent.cs +++ b/ds-wms-service/DS.Module.Core/Condition/ConditionContent.cs @@ -1,11 +1,11 @@ namespace DS.Module.Core.Condition { - public class ContitionContent + public class ConditionContent { /// /// 逻辑操作符 /// - public string LogicalOperator { get; set; } + public string LogicalOperator { get; set; } = "and"; /// /// 条件组 @@ -15,7 +15,7 @@ /// /// 条件组 /// - public List Groups { get; set; } + public List? Groups { get; set; } /// /// 数据源名称 diff --git a/ds-wms-service/DS.Module.Core/Condition/ConditionHelper.cs b/ds-wms-service/DS.Module.Core/Condition/ConditionHelper.cs index 1ee02e7b..b88e9b40 100644 --- a/ds-wms-service/DS.Module.Core/Condition/ConditionHelper.cs +++ b/ds-wms-service/DS.Module.Core/Condition/ConditionHelper.cs @@ -1,5 +1,4 @@ using DS.Module.Core.Data; -using Fasterflect; namespace DS.Module.Core.Condition { @@ -8,7 +7,7 @@ namespace DS.Module.Core.Condition /// /// 根据ContitionContent条件,从数据上下文TaskFlowDataContext中取出指定数据,然后判断条件是否符合 /// - public static bool IsPass(ContitionContent conditionContent, TaskFlowDataContext dataContext) + public static bool IsPass(ConditionContent conditionContent, TaskFlowDataContext dataContext) { bool? thisScopeResult = null; @@ -18,7 +17,7 @@ namespace DS.Module.Core.Condition } IDictionary? dataDic = null; - if (dataContext.ContainsKey(conditionContent.SourceName)) + if (!string.IsNullOrEmpty(conditionContent.SourceName) && dataContext.ContainsKey(conditionContent.SourceName)) { dataDic = dataContext[conditionContent.SourceName] as IDictionary; } @@ -28,10 +27,9 @@ namespace DS.Module.Core.Condition var itemResult = false; string? valStr = null; - if (dataDic != null) + if (dataDic != null && dataDic.TryGetValue(item.Field, out object? objVal)) { - var obj = dataDic[item.Field]; - valStr = obj?.ToString(); + valStr = objVal?.ToString(); } else if (dataContext.ContainsKey(item.Field)) { diff --git a/ds-wms-service/DS.Module.Core/Enums/TaskPlat/TaskBaseTypeEnum.cs b/ds-wms-service/DS.Module.Core/Enums/TaskPlat/TaskBaseTypeEnum.cs index 9f83d9b4..cd30b13f 100644 --- a/ds-wms-service/DS.Module.Core/Enums/TaskPlat/TaskBaseTypeEnum.cs +++ b/ds-wms-service/DS.Module.Core/Enums/TaskPlat/TaskBaseTypeEnum.cs @@ -226,9 +226,9 @@ namespace DS.Module.Core [Description("处理Draft")] WAIT_DRAFT = 207, /// - /// 放单 + /// 截单 /// - [Description("放单")] + [Description("截单")] WAIT_CHECKOUT_BILL = 208, /// /// 退舱 @@ -286,7 +286,7 @@ namespace DS.Module.Core /// /// 报商检 /// - [Description("报商检")] + [Description("商检")] WAIT_SHANGJIAN = 308, /// /// 报COA @@ -304,10 +304,10 @@ namespace DS.Module.Core [Description("拖车")] WAIT_TUOCHE = 311, /// - /// 办保险 + /// 保险 /// - [Description("办保险")] - WAIT_Insurance = 312, + [Description("保险")] + WAIT_INSURANCE = 312, /// /// 出号 /// @@ -319,9 +319,9 @@ namespace DS.Module.Core [Description("内点入货")] WAIT_NDRH = 314, /// - /// 发快递 + /// 快递 /// - [Description("发快递")] + [Description("快递")] WAIT_DELIVERY = 315, /// /// 箱使 diff --git a/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs b/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs index 5bc2e993..33497664 100644 --- a/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs +++ b/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs @@ -437,12 +437,12 @@ public class FlowInstanceService : ServiceBase, IFlowInstanceService #endregion 或签 int nextNodeType = runtime.GetNextNodeType(); - var serializerSettings = new JsonSerializerSettings - { - // 设置为驼峰命名 - ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() - }; - instance.Content = JsonConvert.SerializeObject(runtime.ToFlowRoot(), Formatting.None, serializerSettings); + //var serializerSettings = new JsonSerializerSettings + //{ + // // 设置为驼峰命名 + // ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() + //}; + //instance.Content = JsonConvert.SerializeObject(runtime.ToFlowRoot(), Formatting.None, serializerSettings); instance.Note = auditNote; Db.Updateable(instance).ExecuteCommand(); diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskAuditRequest.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskAuditRequest.cs index 2380701d..3013eb08 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskAuditRequest.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskAuditRequest.cs @@ -1,4 +1,5 @@ -using System.Runtime.Serialization; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; using DS.Module.Core; using DS.WMS.Core.Fee.Dtos; @@ -7,7 +8,7 @@ namespace DS.WMS.Core.Op.Dtos.TaskInteraction /// /// 任务审核请求 /// - public class TaskAuditRequest : AuditRequest + public class TaskAuditRequest : AuditRequest, IValidatableObject { /// /// 任务类型名称 @@ -19,5 +20,22 @@ namespace DS.WMS.Core.Op.Dtos.TaskInteraction /// [IgnoreDataMember] public TaskBaseTypeEnum TaskType => string.IsNullOrEmpty(TaskTypeName) ? TaskBaseTypeEnum.NOT_SPECIFIED : Enum.Parse(TaskTypeName); + + /// + /// 确定当前对象是否有效 + /// + /// 验证上下文 + /// + public virtual IEnumerable Validate(ValidationContext validationContext) + { + if (string.IsNullOrEmpty(TaskTypeName)) + { + yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 不能为空"); + } + else if (!Enum.TryParse(TaskTypeName, out TaskBaseTypeEnum taskType)) + { + yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 值不在有效枚举范围之内"); + } + } } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskRequest.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskRequest.cs index 227c4891..c44564d0 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskRequest.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskRequest.cs @@ -49,7 +49,7 @@ namespace DS.WMS.Core.Op.Dtos.TaskInteraction } else if (!Enum.TryParse(TaskTypeName, out TaskBaseTypeEnum taskType)) { - yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 值无效"); + yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 值不在有效枚举范围之内"); } } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Entity/TaskInteraction/BusinessTask.cs b/ds-wms-service/DS.WMS.Core/Op/Entity/TaskInteraction/BusinessTask.cs index 416f9b42..a90ada24 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Entity/TaskInteraction/BusinessTask.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Entity/TaskInteraction/BusinessTask.cs @@ -1,5 +1,4 @@ using DS.Module.Core; -using DS.Module.Core.Data; using DS.Module.Core.Extensions; using SqlSugar; @@ -83,5 +82,11 @@ namespace DS.WMS.Core.Op.Entity.TaskInteraction /// [SugarColumn(ColumnDescription = "审批驳回理由", Length = 200, IsNullable = true)] public string? RejectReason { get; set; } + + /// + /// 下一任务配置ID + /// + [SugarColumn(ColumnDescription = "下一任务配置ID", IsNullable = true)] + public long? NextId { get; set; } } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/IActionManagerService.cs b/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/IActionManagerService.cs index 7a932736..3b08145d 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/IActionManagerService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/IActionManagerService.cs @@ -1,5 +1,7 @@ using DS.Module.Core; +using DS.Module.Core.Condition; using DS.Module.Core.Data; +using DS.WMS.Core.Op.Dtos.TaskInteraction; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Entity.TaskInteraction; @@ -10,6 +12,23 @@ namespace DS.WMS.Core.Op.Interface.TaskInteraction /// public interface IActionManagerService { + /// + /// 根据指定条件返回是否匹配的结果 + /// + /// 任务请求 + /// 匹配条件 + /// + Task IsMatchAsync(TaskRequest request, IEnumerable conditions); + + /// + /// 获取所需业务数据 + /// + /// 业务ID + /// 业务类型 + /// 条件字段 + /// + Task GetBusinessDataAsync(long businessId, BusinessType businessType, IEnumerable conditions); + /// /// 获取所需业务数据 /// @@ -17,7 +36,7 @@ namespace DS.WMS.Core.Op.Interface.TaskInteraction /// 业务类型 /// 返回字段列表 /// - dynamic? GetBusinessData(long businessId, BusinessType businessType, params string[] fields); + Task GetBusinessDataAsync(long businessId, BusinessType businessType, params string[] fields); /// /// 执行特定动作 diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/BookingActionExecutor.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/BookingActionExecutor.cs similarity index 93% rename from ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/BookingActionExecutor.cs rename to ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/BookingActionExecutor.cs index 823cf605..b2a339ba 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/BookingActionExecutor.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/BookingActionExecutor.cs @@ -4,8 +4,11 @@ using DS.WMS.Core.Op.Interface.TaskInteraction; using Masuit.Tools.Systems; using Microsoft.Extensions.DependencyInjection; -namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor +namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking { + /// + /// 订舱动作 + /// public class BookingActionExecutor : DefaultActionExecutor { internal const TaskBaseTypeEnum Booking_TaskType = TaskBaseTypeEnum.WAIT_BOOKING; @@ -27,7 +30,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor return Task.CompletedTask; } - protected async Task CreateTask(ActionExecutionContext context) + protected async Task CreateTask(ActionExecutionContext context) { var result = await TaskService.Exists(context.TaskInfo.BusinessId, context.TaskInfo.BusinessType, Booking_TaskType); //任务已存在,跳过创建步骤 @@ -42,7 +45,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor }); } - protected async Task SetTaskComplete(ActionExecutionContext context) + protected async Task SetTaskComplete(ActionExecutionContext context) { var result = await TaskService.SetTaskStatusAsync(new TaskUpdateRequest { diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/EDIActionExecutor.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/EDIActionExecutor.cs similarity index 95% rename from ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/EDIActionExecutor.cs rename to ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/EDIActionExecutor.cs index 1040a6a5..42472b6f 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/EDIActionExecutor.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/EDIActionExecutor.cs @@ -4,7 +4,7 @@ using DS.WMS.Core.Op.Interface; using Masuit.Tools.Systems; using Microsoft.Extensions.DependencyInjection; -namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor +namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking { /// /// 用于发送EDI的执行器 diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/MailActionExecutor.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/MailActionExecutor.cs similarity index 92% rename from ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/MailActionExecutor.cs rename to ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/MailActionExecutor.cs index 3c6506a6..164ae1d8 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/MailActionExecutor.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/Booking/MailActionExecutor.cs @@ -6,7 +6,7 @@ using Masuit.Tools.Systems; using Microsoft.Extensions.DependencyInjection; using SqlSugar; -namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor +namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking { /// /// 用于邮件发送的执行器 @@ -31,7 +31,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor var taskMailService = context.ServiceProvider.GetRequiredService(); MailService mailService = new(context.ServiceProvider); BusinessTaskMail? mailConfig = null; - if (context.AdditionalData.TryGetValue(nameof(BusinessTaskMail.Id), out var id)) + if (context.AdditionalData.TryGetValue(nameof(BusinessTaskMail) + "." + nameof(BusinessTaskMail.Id), out var id)) { if (id == null) { @@ -41,7 +41,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor var idVal = (long)Convert.ChangeType(id, typeof(long)); mailConfig = (await taskMailService.GetAsync(idVal)).Data; } - else if (context.AdditionalData.TryGetValue(nameof(BusinessTaskMail.Name), out var name)) + else if (context.AdditionalData.TryGetValue(nameof(BusinessTaskMail) + "." + nameof(BusinessTaskMail.Name), out var name)) { var mailName = name as string; if (mailName.IsNullOrEmpty()) @@ -59,7 +59,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor } result = await mailService.SendAsync(mailConfig, context.TaskInfo.BusinessId, context.TaskInfo.BusinessType); - if (!result.Succeeded) + if (!result.Succeeded) { await LogService.WriteLogAsync(context.TaskInfo, result.Message); return; diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/DefaultActionExecutor.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/DefaultActionExecutor.cs index 5de5a9af..565aa1b2 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/DefaultActionExecutor.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/DefaultActionExecutor.cs @@ -4,6 +4,9 @@ using DS.WMS.Core.Op.Interface.TaskInteraction; namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor { + /// + /// 默认动作执行器 + /// public class DefaultActionExecutor : IActionExecutor { internal static readonly ApiFox Api; @@ -13,6 +16,11 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor Api = new ApiFox(); } + /// + /// 执行空的动作 + /// + /// + /// public virtual Task ExecuteAsync(ActionExecutionContext context) { return Task.CompletedTask; diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/SpaceRelease/SpaceReleaseActionExecutor.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/SpaceRelease/SpaceReleaseActionExecutor.cs new file mode 100644 index 00000000..f6b69bc3 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/SpaceRelease/SpaceReleaseActionExecutor.cs @@ -0,0 +1,91 @@ +using System.ComponentModel; +using DS.WMS.Core.Op.Dtos.TaskInteraction; +using DS.WMS.Core.Op.Entity.TaskInteraction; +using DS.WMS.Core.Op.Interface; +using DS.WMS.Core.Op.Interface.TaskInteraction; +using Microsoft.Extensions.DependencyInjection; + +namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.SpaceRelease +{ + /// + /// 放舱动作 + /// + public class SpaceReleaseActionExecutor : DefaultActionExecutor + { + public override async Task ExecuteAsync(ActionExecutionContext context) + { + if (!context.AdditionalData.TryGetValue("ActionType", out object? val)) + return; + + SpaceReleaseActionType actionType = (SpaceReleaseActionType)Convert.ChangeType(val, typeof(int)); + if (actionType == SpaceReleaseActionType.None) + return; + + var opService = context.ServiceProvider.GetRequiredService(); + var logService = context.ServiceProvider.GetRequiredService(); + + if (actionType.HasFlag(SpaceReleaseActionType.ShippingOrder)) + await SendShippingOrderAsync(opService, logService, context.TaskInfo); + + + } + + //下货纸 + internal async Task SendShippingOrderAsync(ISeaExportService opService, ITaskLogService logService, BusinessTask task) + { + var result = await opService.SendXHZ(task.BusinessId.ToString()); + if (!result.Succeeded) + { + await logService.WriteLogAsync(task, "发送下货纸失败:" + result.Message); + } + } + + //入货通知 + internal async Task SendIncomingNotification(IOpBusinessYardService opService, ITaskLogService logService, BusinessTask task) + { + var result = opService.GetBusinessYardByKeyId(task.BusinessId.ToString()); + if (!result.Succeeded) + { + await logService.WriteLogAsync(task, "获取入货通知数据源失败:" + result.Message); + return; + } + + + } + + ////转发BC + //internal async Task RelayBC(ISeaExportService opService, ITaskLogService logService, BusinessTask task) + //{ + //} + } + + /// + /// 放舱动作类型 + /// + [Flags] + public enum SpaceReleaseActionType + { + /// + /// 未设置 + /// + None = 0, + + /// + /// 下货纸 + /// + [Description("下货纸")] + ShippingOrder = 1 << 0, + + /// + /// 入货通知 + /// + [Description("入货通知")] + IncomingNotification = 1 << 1, + + /// + /// 转发BC + /// + [Description("船东BC")] + RelayBC = 1 << 2 + } +} diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionManagerService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionManagerService.cs index 85f9fc5c..243ece04 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionManagerService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionManagerService.cs @@ -1,15 +1,16 @@ using DS.Module.Core; +using DS.Module.Core.Condition; using DS.Module.Core.Data; using DS.WMS.Core.Op.Dtos.TaskInteraction; +using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Entity.TaskInteraction; +using DS.WMS.Core.Op.Interface; using DS.WMS.Core.Op.Interface.TaskInteraction; using DS.WMS.Core.TaskPlat; -using Masuit.Tools; -using SqlSugar; using Fasterflect; +using Masuit.Tools; using Microsoft.Extensions.DependencyInjection; -using DS.WMS.Core.Op.Entity; -using DS.WMS.Core.Op.Interface; +using SqlSugar; namespace DS.WMS.Core.Op.Method.TaskInteraction { @@ -18,11 +19,79 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction /// public class ActionManagerService : ServiceBase, IActionManagerService { + ITaskLogService LogService; + /// /// 初始化 /// public ActionManagerService(IServiceProvider serviceProvider) : base(serviceProvider) { + LogService = serviceProvider.GetRequiredService(); + } + + /// + /// 根据指定条件返回是否匹配的结果 + /// + /// 任务请求 + /// 匹配条件 + /// + public async Task IsMatchAsync(TaskRequest request, IEnumerable conditions) + { + ArgumentNullException.ThrowIfNull(request, nameof(request)); + ArgumentNullException.ThrowIfNull(conditions, nameof(conditions)); + + var biz = await GetBusinessDataAsync(request.BusinessId, request.BusinessType, conditions); + if (biz != null) + { + TaskFlowDataContext dataContext = new( + (TaskFlowDataNameConst.Business, biz) + ); + //循环匹配 + foreach (var item in conditions) + { + if (ConditionHelper.IsPass(item, dataContext)) + { + var logEntity = new BusinessTaskLog + { + ActionType = ActionType.Create, + BusinessId = request.BusinessId, + BusinessType = request.BusinessType, + TaskType = request.TaskType, + CreateBy = long.Parse(User.UserId), + CreateTime = DateTime.Now, + Remark = $"符合设定条件,已跳过任务的创建" + }; + await LogService.WriteLogAsync(logEntity); + return true; + } + } + } + + return false; + } + + /// + /// 获取所需业务数据 + /// + /// 业务ID + /// 业务类型 + /// 条件字段 + /// + public async Task GetBusinessDataAsync(long businessId, BusinessType businessType, IEnumerable conditions) + { + ArgumentNullException.ThrowIfNull(conditions, nameof(conditions)); + + HashSet fields = []; + foreach (var item in conditions) + { + if (item.Conditions != null) + fields.AddRange(item.Conditions.Select(x => x.Field)); + + if (item.Groups != null) + fields.AddRange(item.Groups.SelectMany(x => x.Conditions.Select(x => x.Field))); + } + + return await GetBusinessDataAsync(businessId, businessType, fields.ToArray()); } /// @@ -32,7 +101,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction /// 业务类型 /// 返回字段列表 /// - public dynamic? GetBusinessData(long businessId, BusinessType businessType, params string[] fields) + public async Task GetBusinessDataAsync(long businessId, BusinessType businessType, params string[] fields) { object? biz = null; switch (businessType) @@ -46,7 +115,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction else { var selectors = fields.Select(x => new SelectModel { FieldName = x }).ToList(); - biz = TenantDb.Queryable().AS("op_sea_export").Where("Id=@Id", new { Id = businessId }).Select(selectors).First(); + biz = await TenantDb.Queryable().AS("op_sea_export").Where("Id=@Id", new { Id = businessId }).Select(selectors).FirstAsync(); } break; @@ -70,17 +139,22 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction if (businessTask.TaskStatus != TaskStatusEnum.Complete) return; - var biz = GetBusinessData(businessTask.BusinessId, businessTask.BusinessType); + //var biz = GetBusinessDataAsync(businessTask.BusinessId, businessTask.BusinessType); // 执行自动化操作 TaskFlowDataContext dataContext = new( - (TaskFlowDataNameConst.BusinessTask, businessTask), - (TaskFlowDataNameConst.Business, biz) + (TaskFlowDataNameConst.BusinessTask, businessTask) + //(TaskFlowDataNameConst.Business, biz) ); TaskFlowRuner taskFlow = new(TenantDb, ServiceProvider); await taskFlow.RunWithBsno(businessTask.TaskType, businessTask.BusinessId, dataContext); } + /// + /// 执行动作 + /// + /// + /// public async Task ExecuteAsync(TaskFlowDataContext dataContext) { ArgumentNullException.ThrowIfNull(dataContext, nameof(dataContext)); @@ -93,30 +167,36 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction foreach (var key in dataContext.Keys) context.AdditionalData[key] = dataContext[key]; - string selectorType = dataContext.GetOrDefault("SelectorType"); - if (selectorType.IsNullOrEmpty()) + var typeName = dataContext.GetOrDefault("TypeName"); + if (typeName.IsNullOrEmpty()) return; - Type? t = Type.GetType(selectorType, true, false); + Type? t = Type.GetType(typeName, true, false); if (t == null) { - await new ApplicationException($"未能获取类型【{selectorType}】的信息").LogAsync(Db); + await new ApplicationException($"未能获取类型【{typeName}】的信息").LogAsync(Db); return; } - IActionSelector? selector = ConstructorExtensions.CreateInstance(t) as IActionSelector; - if (selector == null) + + IActionExecutor currentExecutor = null; + if (ConstructorExtensions.CreateInstance(t) is IActionSelector selector) { - await new ApplicationException($"未能创建执行选择器【{t.AssemblyQualifiedName}】的实例").LogAsync(Db); - return; + currentExecutor = await selector.GetActionExecutor(context); + } + else if (ConstructorExtensions.CreateInstance(t) is IActionExecutor executor) + { + currentExecutor = executor; } - var executor = await selector.GetActionExecutor(context); - if (executor != null) + if (currentExecutor == null) { - executor.ExecuteAsync(context); - var logService = context.ServiceProvider.GetRequiredService(); - await logService.WriteLogAsync(context.TaskInfo, $"开始运行后台任务({executor.GetType().FullName})..."); + await new ApplicationException($"未能创建类型【{t.AssemblyQualifiedName}】的实例").LogAsync(Db); + return; } + + await currentExecutor.ExecuteAsync(context); + var logService = context.ServiceProvider.GetRequiredService(); + await logService.WriteLogAsync(context.TaskInfo, $"开始运行后台任务({currentExecutor.GetType().FullName})..."); } public async Task TriggerTest(TaskBaseTypeEnum taskType, long? id) diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionSelector/BookingSelector.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionSelector/BookingSelector.cs index 48b41611..9b4123ca 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionSelector/BookingSelector.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionSelector/BookingSelector.cs @@ -7,12 +7,13 @@ using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Entity.TaskInteraction; using DS.WMS.Core.Op.Interface.TaskInteraction; using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor; +using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking; using Microsoft.Extensions.DependencyInjection; namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionSelector { /// - /// 订舱 + /// 订舱选择器 /// public class BookingSelector : IActionSelector { @@ -20,7 +21,6 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionSelector public async Task GetActionExecutor(ActionExecutionContext context) { - //var db = context.ServiceProvider.GetRequiredService(); var saasService = context.ServiceProvider.GetRequiredService(); var user = context.ServiceProvider.GetRequiredService(); var tenantDb = saasService.GetBizDbScopeById(user.TenantId); diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/MailService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/MailService.cs index 76e9dbee..2fecc83b 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/MailService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/MailService.cs @@ -17,6 +17,7 @@ using DS.Module.Core; using Masuit.Tools; using Masuit.Tools.Systems; using DS.WMS.Core.Op.Entity; +using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking; namespace DS.WMS.Core.Op.Method.TaskInteraction { diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/SeaExportTaskService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/SeaExportTaskService.cs index 98858253..9173eec2 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/SeaExportTaskService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/SeaExportTaskService.cs @@ -1,4 +1,5 @@ using DS.Module.Core; +using DS.Module.Core.Data; using DS.Module.Core.Extensions; using DS.Module.DjyServiceStatus; using DS.WMS.Core.Op.Dtos.TaskInteraction; @@ -47,7 +48,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction var taskLogList = new List(); var first = request.First(); - var defaultUsers = await GetRecvUsers(first.RecvUserIdList); + var defaultUsers = await GetRecvUsersAsync(first.RecvUserIdList); var biz = await TenantDb.Queryable().Select(x => new { x.Id, @@ -58,9 +59,10 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction x.ETD, }).FirstAsync(x => x.Id == first.BusinessId); + var dic = await GetRecvUsersAsync(first.BusinessId, first.BusinessType, request.Select(x => x.TaskType).ToList()); foreach (var item in request) { - var recvUsers = await GetRecvUsersFromConfig(item.BusinessId, item.BusinessType, item.TaskType); + var recvUsers = dic[item.TaskType]; var info = new TaskManageOrderMessageInfo { Head = new TaskManageOrderMessageHeadInfo @@ -122,24 +124,39 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction } /// - /// 当任务状态发生变化时调用 + /// 创建关联子任务 /// - /// + /// /// - protected override async Task OnTaskStatusChanged(TaskUpdateRequest request) + public async Task CreateSubTaskAsync(TaskFlowDataContext dataContext) { - //放舱结束,根据业务所选服务,生成子任务 - if (request.TaskType == TaskBaseTypeEnum.WAIT_SPACE_RELEASE && request.TaskStatus == TaskStatusEnum.Complete) + if (dataContext[TaskFlowDataNameConst.BusinessTask] is BusinessTask task + && task.TaskStatus == TaskStatusEnum.Complete) { - var task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).FirstAsync(); - if (task != null) - { - var list = await GetSubRequestAsync(request.BusinessId, request.BusinessType, task.RecvUserIdArray); - await CreateSubTaskAsync(list.FindAll(x => x.TaskType != TaskBaseTypeEnum.NOT_SPECIFIED).OrderBy(x => x.TaskType)); - } + var list = await GetSubRequestAsync(task.BusinessId, task.BusinessType, task.RecvUserIdArray); + await CreateSubTaskAsync(list.FindAll(x => x.TaskType != TaskBaseTypeEnum.NOT_SPECIFIED).OrderBy(x => x.TaskType)); } } + ///// + ///// 当任务状态发生变化时调用 + ///// + ///// + ///// + //protected override async Task OnTaskStatusChanged(TaskUpdateRequest request) + //{ + // //放舱结束,根据业务所选服务,生成子任务 + // if (request.TaskType == TaskBaseTypeEnum.WAIT_SPACE_RELEASE && request.TaskStatus == TaskStatusEnum.Complete) + // { + // var task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).FirstAsync(); + // if (task != null) + // { + // var list = await GetSubRequestAsync(request.BusinessId, request.BusinessType, task.RecvUserIdArray); + // await CreateSubTaskAsync(list.FindAll(x => x.TaskType != TaskBaseTypeEnum.NOT_SPECIFIED).OrderBy(x => x.TaskType)); + // } + // } + //} + internal async Task> GetSubRequestAsync(long id, BusinessType businessType, params long[]? recvUsers) { var svcList = await GetServicesAsync(id); @@ -172,7 +189,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction else if (svcName == "拖车") dto.TaskTypeName = TaskBaseTypeEnum.WAIT_TUOCHE.ToString(); else if (svcName == "保险") - dto.TaskTypeName = TaskBaseTypeEnum.WAIT_Insurance.ToString(); + dto.TaskTypeName = TaskBaseTypeEnum.WAIT_INSURANCE.ToString(); else if (svcName == "出号") dto.TaskTypeName = TaskBaseTypeEnum.WAIT_CHUHAO.ToString(); else if (svcName == "内点入货") @@ -202,28 +219,5 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction return extArray.Where(x => x["isYield"].Value()).Select(x => x["projectName"]?.Value() ?? string.Empty).ToArray(); } - //public override async Task MarkerChangedAsync(MarkerChangedCallback callback) - //{ - // if (callback.Type != AuditType.SeaExport) - // return; - - // await base.MarkerChangedAsync(callback); - //} - - ///// - ///// 审批完成回调更新 - ///// - ///// 回调信息 - ///// - //public override async Task UpdateBusinessAsync(FlowCallback callback) - //{ - // if (callback.Type != AuditType.SeaExport) - // return; - - // await base.UpdateBusinessAsync(callback); - - // //todo:海运出口主表信息 - //} - } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs index 7720243d..d2d9db00 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs @@ -11,6 +11,7 @@ using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Entity.TaskInteraction; using DS.WMS.Core.Op.Interface.TaskInteraction; using DS.WMS.Core.Sys.Entity; +using DS.WMS.Core.TaskPlat; using DS.WMS.Core.TaskPlat.Dtos; using DS.WMS.Core.TaskPlat.Entity; using DS.WMS.Core.TaskPlat.Interface; @@ -76,18 +77,23 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction /// /// 获取给定任务的下一任务类型 /// - /// 任务信息 + /// /// - internal static TaskBaseTypeEnum? GetNextType(BusinessTask current) + public async Task GetNextTypeAsync(BusinessTask current) { - if (current.TaskType == TaskBaseTypeEnum.NOT_SPECIFIED || current.TaskType == TaskBaseTypeEnum.WAIT_CHECKOUT_BILL) //流程的最后一步 - return null; + TaskFlowRuner flowRuner = new TaskFlowRuner(TenantDb, ServiceProvider); - int currentTypeVal = (int)current.TaskType; - if (currentTypeVal >= 300) //300开始的枚举值为可选服务项目,不存在前后关联性 - return null; + var result = await flowRuner.GetWorkFlowNextConfig(new TaskFlowDataContext( + + ), current.NextId); - return (TaskBaseTypeEnum)(currentTypeVal + 1); + if (result.HasValue) + { + current.NextId = result.Value.configId; + return result.Value.taskType; + } + + return null; } /// @@ -252,8 +258,8 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction if (task != null && task.TaskStatus != TaskStatusEnum.Cancel) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskExists)); - //if (await ShouldSkipAsync(request)) - // return DataResult.Success; + if (await ShouldSkipAsync(request)) + return DataResult.Success; long tenatId = long.Parse(User.TenantId); string tenatName = Db.Queryable().Where(x => x.Id == tenatId).Select(x => x.Name).First(); @@ -289,12 +295,12 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction if (request.RecvUserIdList == null || request.RecvUserIdList.Length == 0) { //根据配置获取默认接收人 - info.Main.RecvUserInfoList = await GetRecvUsersFromConfig(request.BusinessId, request.BusinessType, request.TaskType); + info.Main.RecvUserInfoList = await GetRecvUsersAsync(request.BusinessId, request.BusinessType, request.TaskType); if (info.Main.RecvUserInfoList == null || info.Main.RecvUserInfoList.Count == 0) { if (AuditTaskTypes.Contains(request.TaskType)) { - info.Main.RecvUserInfoList = await GetRecvUsers(long.Parse(User.UserId)); + info.Main.RecvUserInfoList = await GetRecvUsersAsync(long.Parse(User.UserId)); } else { @@ -304,7 +310,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction } else { - info.Main.RecvUserInfoList = await GetRecvUsers(request.RecvUserIdList); + info.Main.RecvUserInfoList = await GetRecvUsersAsync(request.RecvUserIdList); } if (info.Main.TaskTitle.IsNullOrEmpty()) @@ -341,7 +347,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction CreateBy = long.Parse(User.UserId), CreateTime = DateTime.Now }; - task.NextType = GetNextType(task); + task.NextType = await GetNextTypeAsync(task); await TenantDb.Insertable(task).ExecuteCommandAsync(); //审核任务需创建工作流 @@ -374,53 +380,17 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction } } - internal async Task ShouldSkipAsync(TaskRequest request) + internal async Task ShouldSkipAsync(TaskRequest request) { var configList = await TenantDb.Queryable().Where(x => x.TaskType == request.TaskType && x.IsSkip) .Select(x => new { x.Id, x.SourceName, x.MatchCondition }).ToListAsync(); if (configList.Count > 0) { - var conditionList = configList.Select(x => new { x.Id, x.SourceName, MatchCondition = JsonConvert.DeserializeObject(x.MatchCondition) }).ToList(); - HashSet fields = []; + var conditionList = configList.Select(x => new { x.Id, x.SourceName, MatchCondition = JsonConvert.DeserializeObject(x.MatchCondition) }).ToList(); foreach (var item in conditionList) - { - if (item.MatchCondition.Conditions != null) - fields.AddRange(item.MatchCondition.Conditions.Select(x => x.Field)); + item.MatchCondition.SourceName = item.SourceName; - if (item.MatchCondition.Groups != null) - fields.AddRange(item.MatchCondition.Groups.SelectMany(x => x.Conditions.Select(x => x.Field))); - } - var biz = ActionService.Value.GetBusinessData(request.BusinessId, request.BusinessType, fields.ToArray()); - if (biz != null) - { - //循环匹配 - foreach (var item in configList) - { - var content = conditionList.Find(x => x.Id == item.Id)?.MatchCondition; - if (content == null) - continue; - - content.SourceName = item.SourceName; - TaskFlowDataContext dataContext = new( - (TaskFlowDataNameConst.Business, biz) - ); - if (ConditionHelper.IsPass(content, dataContext)) - { - var logEntity = new BusinessTaskLog - { - ActionType = ActionType.Create, - BusinessId = request.BusinessId, - BusinessType = request.BusinessType, - TaskType = request.TaskType, - CreateBy = long.Parse(User.UserId), - CreateTime = DateTime.Now, - Remark = $"符合设定条件({item.Id}),已跳过任务的创建" - }; - await LogService.WriteLogAsync(logEntity); - return true; - } - } - } + return await ActionService.Value.IsMatchAsync(request, conditionList.Select(x => x.MatchCondition)); } return false; @@ -459,7 +429,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction { string[] ids = FlowInstanceService.GetMarkers(instance); //变更任务接收人为所有审批执行人 - var users = await GetRecvUsers(ids.Select(long.Parse).ToArray()); + var users = await GetRecvUsersAsync(ids.Select(long.Parse).ToArray()); result = await ManagerService.TransferTask(task.BusinessId, task.TaskType, users); if (result.Succeeded) { @@ -546,8 +516,8 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction if (useTransaction) await TenantDb.Ado.CommitTranAsync(); - //ActionService.Value.TriggerAction(task); - return DataResult.Success(task.TaskStatus == TaskStatusEnum.Complete ? GetNextType(task) : null); + ActionService.Value.TriggerAction(task); + return DataResult.Success(task.TaskStatus == TaskStatusEnum.Complete ? await GetNextTypeAsync(task) : null); } catch (Exception ex) { @@ -580,7 +550,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction ArgumentNullException.ThrowIfNull(callback, nameof(callback)); long userId = long.Parse(User.UserId); - var users = await GetRecvUsers(userId); + var users = await GetRecvUsersAsync(userId); var dt = DateTime.Now; var taskType = TypeMappings.Where(x => x.Value == callback.Type.GetValueOrDefault()).Select(x => x.Key).FirstOrDefault(); @@ -630,7 +600,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction await SetTaskStatusAsync(req); long userId = long.Parse(User.UserId); - var users = await GetRecvUsers(userId); + var users = await GetRecvUsersAsync(userId); string remark = "终审完成,审批结果为:" + callback.FlowStatus.GetDescription(); if (callback.FlowStatus == FlowStatusEnum.Reject) @@ -685,10 +655,29 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction /// 业务类型 /// 任务类型 /// - protected internal async Task?> GetRecvUsersFromConfig(long id, BusinessType businessType, TaskBaseTypeEnum taskType) + protected internal async Task> GetRecvUsersAsync(long id, BusinessType businessType, TaskBaseTypeEnum taskType) + { + //var biz = ActionService.Value.GetBusinessDataAsync(id, businessType); + //var result = await TaskAllocationService.Value.GetAllotUserBySeaExportId(taskType, id, new TaskFlowDataContext( + // (TaskFlowDataNameConst.Business, biz) + // )); + //return result.Succeeded ? result.Data : []; + + var dic = await GetRecvUsersAsync(id, businessType, [taskType]); + return dic?.Count > 0 ? dic.FirstOrDefault().Value : []; + } + + /// + /// 从任务配置中获取接收用户列表 + /// + /// 业务ID + /// 业务类型 + /// 任务类型 + /// + protected internal async Task>> GetRecvUsersAsync(long id, BusinessType businessType, List taskTypes) { - var biz = ActionService.Value.GetBusinessData(id, businessType); - var result = await TaskAllocationService.Value.GetAllotUserBySeaExportId(taskType, id, new TaskFlowDataContext( + var biz = ActionService.Value.GetBusinessDataAsync(id, businessType); + var result = await TaskAllocationService.Value.GetAllotUserBySeaExportId(taskTypes, id, new TaskFlowDataContext( (TaskFlowDataNameConst.Business, biz) )); return result.Succeeded ? result.Data : []; @@ -699,7 +688,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction /// /// 用户ID /// - protected internal async Task> GetRecvUsers(params long[] ids) + protected internal async Task> GetRecvUsersAsync(params long[] ids) { return await Db.Queryable().Where(x => ids.Contains(x.Id)).Select( x => new RecvUserInfo { RecvUserId = x.Id, RecvUserName = x.UserName }).ToListAsync(); diff --git a/ds-wms-service/DS.WMS.Core/TaskPlat/Entity/TaskFlowConfig.cs b/ds-wms-service/DS.WMS.Core/TaskPlat/Entity/TaskFlowConfig.cs index 8aa5e3ae..f2780a11 100644 --- a/ds-wms-service/DS.WMS.Core/TaskPlat/Entity/TaskFlowConfig.cs +++ b/ds-wms-service/DS.WMS.Core/TaskPlat/Entity/TaskFlowConfig.cs @@ -40,6 +40,12 @@ namespace DS.WMS.Core.TaskPlat.Entity [SugarColumn(ColumnDescription = "所属主入口流程主键", IsNullable = true)] public long? MainConfigId { get; set; } + ///// + ///// 下一流程主键 + ///// + //[SugarColumn(ColumnDescription = "下一流程主键", IsNullable = true)] + //public long? NextConfigId { get; set; } + /// /// 父项流程主键 /// diff --git a/ds-wms-service/DS.WMS.Core/TaskPlat/Method/TaskAllocationService.cs b/ds-wms-service/DS.WMS.Core/TaskPlat/Method/TaskAllocationService.cs index 668a277e..87cd1d7e 100644 --- a/ds-wms-service/DS.WMS.Core/TaskPlat/Method/TaskAllocationService.cs +++ b/ds-wms-service/DS.WMS.Core/TaskPlat/Method/TaskAllocationService.cs @@ -3,6 +3,7 @@ using DS.Module.Core.Condition; using DS.Module.Core.Data; using DS.Module.SqlSugar; using DS.Module.UserModule; +using DS.WMS.Core.Op.Dtos; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Sys.Interface; using DS.WMS.Core.Sys.Method; @@ -10,6 +11,7 @@ using DS.WMS.Core.TaskPlat.Dtos; using DS.WMS.Core.TaskPlat.Entity; using DS.WMS.Core.TaskPlat.Interface; using LanguageExt.Pipes; +using Mapster; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using SqlSugar; @@ -255,7 +257,7 @@ namespace DS.WMS.Core.TaskPlat.Method } else { - var contitionContent = JsonConvert.DeserializeObject(item.Condition)!; + var contitionContent = JsonConvert.DeserializeObject(item.Condition)!; if (ConditionHelper.IsPass(contitionContent, dataContext)) { allotTargetList.Add(item); @@ -273,7 +275,8 @@ namespace DS.WMS.Core.TaskPlat.Method var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); if (dataContext.ContainsKey(TaskFlowDataNameConst.Business)) { - order = dataContext.Get(TaskFlowDataNameConst.Business); + var orderDto = dataContext.Get(TaskFlowDataNameConst.Business); + order = orderDto.Adapt(); } else { @@ -385,7 +388,7 @@ namespace DS.WMS.Core.TaskPlat.Method } else { - var contitionContent = JsonConvert.DeserializeObject(allotItem.Condition)!; + var contitionContent = JsonConvert.DeserializeObject(allotItem.Condition)!; if (ConditionHelper.IsPass(contitionContent, dataContext)) { itemResult.Add(allotItem); @@ -403,7 +406,8 @@ namespace DS.WMS.Core.TaskPlat.Method var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); if (dataContext.ContainsKey(TaskFlowDataNameConst.Business)) { - order = dataContext.Get(TaskFlowDataNameConst.Business); + var orderDto = dataContext.Get(TaskFlowDataNameConst.Business); + order = orderDto.Adapt(); } else { diff --git a/ds-wms-service/DS.WMS.Core/TaskPlat/Other/TaskFlowRuner.cs b/ds-wms-service/DS.WMS.Core/TaskPlat/Other/TaskFlowRuner.cs index ec3e4aa4..ed7b07ee 100644 --- a/ds-wms-service/DS.WMS.Core/TaskPlat/Other/TaskFlowRuner.cs +++ b/ds-wms-service/DS.WMS.Core/TaskPlat/Other/TaskFlowRuner.cs @@ -81,7 +81,7 @@ namespace DS.WMS.Core.TaskPlat var conditionItem = allConditionList.FirstOrDefault(x => x.ConfigId == configItem.Id); if (conditionItem != null && !string.IsNullOrEmpty(conditionItem.Content)) { - var contitionContent = JsonConvert.DeserializeObject(conditionItem.Content)!; + var contitionContent = JsonConvert.DeserializeObject(conditionItem.Content)!; var oldValue = configMatchCount[configItem.Id]; if (ConditionHelper.IsPass(contitionContent, dataContext)) @@ -179,7 +179,7 @@ namespace DS.WMS.Core.TaskPlat continue; } - var contitionContent = JsonConvert.DeserializeObject(condition.Content)!; + var contitionContent = JsonConvert.DeserializeObject(condition.Content)!; if (ConditionHelper.IsPass(contitionContent, dataContext)) { matchedConfigList.Add(waitMatchConfigItem); @@ -357,6 +357,85 @@ namespace DS.WMS.Core.TaskPlat .FirstAsync(); return await Run(taskBaseType, taskId, dataContext); } + + /// + /// 根据当前节点Id,获取工作流下一个任务类型 + /// + /// + /// 当前执行的配置Id(如果为空,则返回首个任务类型) + /// (下一个任务类型,下一节点Id) + public async Task<(TaskBaseTypeEnum taskType, long configId)?> GetWorkFlowNextConfig(TaskFlowDataContext dataContext, long? currentConfigId = null) + { + var allConfigList = await tenantDb.Queryable() + .Where(t => t.MainConfigId == SqlFunc.Subqueryable().Where(x => x.IsMain && x.TaskType == "WORK_FLOW").Select(x => x.Id)) + .OrderBy(t => t.Id) + .ToListAsync(); + + if (allConfigList.Count == 0) return null; + + List waitMatchConfigList = new(); + if (currentConfigId == null) + { + waitMatchConfigList.Add(allConfigList.First(x => x.IsMain)); + } + else + { + var currentConfig = allConfigList.FirstOrDefault(x => x.Id == currentConfigId); + if (currentConfig == null) return null; + + waitMatchConfigList.AddRange(allConfigList.Where(x => x.ParentConfigId == currentConfig.Id)); + } + + if (waitMatchConfigList.Count == 0) return null; + + var configIdList = waitMatchConfigList.Select(x => x.Id); + var conditionList = await tenantDb.Queryable() + .Where(x => configIdList.Contains(x.ConfigId)) + .ToListAsync(); + + var matchedConfigList = new List(); + foreach (var item in waitMatchConfigList) + { + var condition = conditionList.FirstOrDefault(x => x.ConfigId == item.Id); + if (condition == null || string.IsNullOrEmpty(condition.Content)) + { + matchedConfigList.Add(item); + } + else + { + var contitionContent = JsonConvert.DeserializeObject(condition.Content)!; + if (ConditionHelper.IsPass(contitionContent, dataContext)) + { + matchedConfigList.Add(item); + } + } + } + + TaskFlowConfig? executeConfig = null; + if (matchedConfigList.Count == 1) + { + executeConfig = matchedConfigList[0]; + } + else if (matchedConfigList.Count > 1) + { + executeConfig = matchedConfigList.FirstOrDefault(x => x.IsMoreMatchDefault); + } + + if (executeConfig == null) + { + executeConfig = waitMatchConfigList.FirstOrDefault(x => x.IsUnMatchDefault); + } + + if (executeConfig == null) return null; + + var taskType = await tenantDb.Queryable().Where(x => x.Id == executeConfig.ExecuteModuleId).Select(x => x.TaskType).FirstAsync(); + + if (taskType != null && Enum.TryParse(typeof(TaskBaseTypeEnum), taskType, out object? temp)) + { + return ((TaskBaseTypeEnum)temp, executeConfig.Id); + } + return null; + } static string WriteLog(string throwMsg, Exception ex) { return string.Format("【自定义错误】:{0} \r\n【异常类型】:{1} \r\n【异常信息】:{2} \r\n【堆栈调用】:{3}", new object[] diff --git a/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs b/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs index d9f441e5..878fe597 100644 --- a/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs +++ b/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs @@ -94,6 +94,9 @@ namespace DS.WMS.OpApi.Controllers [HttpPost, Route("SubmitAudit")] public async Task SubmitAuditAsync(TaskRequest request) { + if (!ModelState.IsValid) + return DataResult.Failed(ModelState.GetErrorMessage(), MultiLanguageConst.IllegalRequest); + return await taskService.SubmitAuditAsync(request); } @@ -105,6 +108,9 @@ namespace DS.WMS.OpApi.Controllers [HttpPost, Route("Audit")] public async virtual Task AuditAsync([FromBody] TaskAuditRequest request) { + if (!ModelState.IsValid) + return DataResult.Failed(ModelState.GetErrorMessage(), MultiLanguageConst.IllegalRequest); + return await taskService.AuditAsync(request); } @@ -126,7 +132,7 @@ namespace DS.WMS.OpApi.Controllers /// 回调信息 /// [HttpPost, Route("MarkerChanged")] - public virtual async Task MarkerChangedAsync([FromBody] MarkerChangedCallback callback) + public async Task MarkerChangedAsync([FromBody] MarkerChangedCallback callback) { await taskService.MarkerChangedAsync(callback); return StatusCode((int)HttpStatusCode.NoContent); diff --git a/ds-wms-service/DS.WMS.OpApi/Controllers/SpaceBookingMSKAPISpotController.cs b/ds-wms-service/DS.WMS.OpApi/Controllers/SpaceBookingMSKAPISpotController.cs index 96cf1e64..245a0655 100644 --- a/ds-wms-service/DS.WMS.OpApi/Controllers/SpaceBookingMSKAPISpotController.cs +++ b/ds-wms-service/DS.WMS.OpApi/Controllers/SpaceBookingMSKAPISpotController.cs @@ -8,7 +8,7 @@ namespace DS.WMS.OpApi.Controllers /// /// 预订舱马士基API即期订舱 /// - public class SpaceBookingMSKAPISpotController : Controller + public class SpaceBookingMSKAPISpotController : ApiController { private readonly ISpaceBookingMSKSPOTAPIService _spaceBookingMSKSPOTAPIService; diff --git a/ds-wms-service/DS.WMS.Test/SaasTest.cs b/ds-wms-service/DS.WMS.Test/SaasTest.cs index 6e9a1278..0d4890cf 100644 --- a/ds-wms-service/DS.WMS.Test/SaasTest.cs +++ b/ds-wms-service/DS.WMS.Test/SaasTest.cs @@ -1,5 +1,6 @@ using System.Reflection; using DS.Module.Core; +using DS.Module.Core.Data; using DS.Module.Core.Extensions; using DS.Module.SqlSugar; using DS.WMS.Core.Check.Entity; @@ -8,6 +9,7 @@ using DS.WMS.Core.Info.Entity; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Entity.BookingSlot; using DS.WMS.Core.Sys.Entity; +using DS.WMS.Core.TaskPlat; using DS.WMS.Core.TaskPlat.Entity; using Mapster; using Masuit.Tools.Strings; @@ -53,7 +55,7 @@ public class SaasTest StaticConfig.CodeFirst_MySqlCollate = "utf8mb4_0900_ai_ci";//较高版本支持 types = types.Where(it => it.Name != "BusinessFeeStatus").ToArray(); types = types.Where(it => it.Name != "BusinessOrderContact").ToArray(); - + tenantDb.CodeFirst.InitTables(types); // //初始化数库 // tenantDb.DbMaintenance.CreateDatabase(); @@ -66,7 +68,7 @@ public class SaasTest /// [Fact] public void MasterInitTableTest() - { + { StaticConfig.CodeFirst_MySqlCollate = "utf8mb4_0900_ai_ci";//较高版本支持 db.CodeFirst.InitTables(typeof(SysPrintTemplate)); //tenantDb.CodeFirst.InitTables(typeof(CheckBillAutoDetail)); @@ -251,4 +253,18 @@ public class SaasTest //tenantDb.CodeFirst.InitTables(typeof(TaskFlowLogDetail)); Assert.True(true); } + + [Fact] + public async Task ZxfTest() + { + var tenantDb = saasService.GetBizDbScopeById("1819549542425694208"); + + var order = await tenantDb.Queryable().FirstAsync(x => x.Id == 1816649497120477184); + + TaskFlowDataContext dataContext = new( + (TaskFlowDataNameConst.Business, order) + ); + TaskFlowRuner runer = new TaskFlowRuner(tenantDb, _serviceProvider); + var result =await runer.GetWorkFlowNextConfig(dataContext, null); + } } \ No newline at end of file