cjy 4 months ago
commit f56bb58a64

@ -1,11 +1,11 @@
namespace DS.Module.Core.Condition namespace DS.Module.Core.Condition
{ {
public class ContitionContent public class ConditionContent
{ {
/// <summary> /// <summary>
/// 逻辑操作符 /// 逻辑操作符
/// </summary> /// </summary>
public string LogicalOperator { get; set; } public string LogicalOperator { get; set; } = "and";
/// <summary> /// <summary>
/// 条件组 /// 条件组
@ -15,7 +15,7 @@
/// <summary> /// <summary>
/// 条件组 /// 条件组
/// </summary> /// </summary>
public List<ContitionContent> Groups { get; set; } public List<ConditionContent>? Groups { get; set; }
/// <summary> /// <summary>
/// 数据源名称 /// 数据源名称

@ -1,5 +1,4 @@
using DS.Module.Core.Data; using DS.Module.Core.Data;
using Fasterflect;
namespace DS.Module.Core.Condition namespace DS.Module.Core.Condition
{ {
@ -8,7 +7,7 @@ namespace DS.Module.Core.Condition
/// <summary> /// <summary>
/// 根据ContitionContent条件从数据上下文TaskFlowDataContext中取出指定数据然后判断条件是否符合 /// 根据ContitionContent条件从数据上下文TaskFlowDataContext中取出指定数据然后判断条件是否符合
/// </summary> /// </summary>
public static bool IsPass(ContitionContent conditionContent, TaskFlowDataContext dataContext) public static bool IsPass(ConditionContent conditionContent, TaskFlowDataContext dataContext)
{ {
bool? thisScopeResult = null; bool? thisScopeResult = null;
@ -18,7 +17,7 @@ namespace DS.Module.Core.Condition
} }
IDictionary<string, object>? dataDic = null; IDictionary<string, object>? dataDic = null;
if (dataContext.ContainsKey(conditionContent.SourceName)) if (!string.IsNullOrEmpty(conditionContent.SourceName) && dataContext.ContainsKey(conditionContent.SourceName))
{ {
dataDic = dataContext[conditionContent.SourceName] as IDictionary<string, object>; dataDic = dataContext[conditionContent.SourceName] as IDictionary<string, object>;
} }
@ -28,10 +27,9 @@ namespace DS.Module.Core.Condition
var itemResult = false; var itemResult = false;
string? valStr = null; string? valStr = null;
if (dataDic != null) if (dataDic != null && dataDic.TryGetValue(item.Field, out object? objVal))
{ {
var obj = dataDic[item.Field]; valStr = objVal?.ToString();
valStr = obj?.ToString();
} }
else if (dataContext.ContainsKey(item.Field)) else if (dataContext.ContainsKey(item.Field))
{ {

@ -226,9 +226,9 @@ namespace DS.Module.Core
[Description("处理Draft")] [Description("处理Draft")]
WAIT_DRAFT = 207, WAIT_DRAFT = 207,
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[Description("单")] [Description("单")]
WAIT_CHECKOUT_BILL = 208, WAIT_CHECKOUT_BILL = 208,
/// <summary> /// <summary>
/// 退舱 /// 退舱
@ -286,7 +286,7 @@ namespace DS.Module.Core
/// <summary> /// <summary>
/// 报商检 /// 报商检
/// </summary> /// </summary>
[Description("商检")] [Description("商检")]
WAIT_SHANGJIAN = 308, WAIT_SHANGJIAN = 308,
/// <summary> /// <summary>
/// 报COA /// 报COA
@ -304,10 +304,10 @@ namespace DS.Module.Core
[Description("拖车")] [Description("拖车")]
WAIT_TUOCHE = 311, WAIT_TUOCHE = 311,
/// <summary> /// <summary>
/// 保险 /// 保险
/// </summary> /// </summary>
[Description("保险")] [Description("保险")]
WAIT_Insurance = 312, WAIT_INSURANCE = 312,
/// <summary> /// <summary>
/// 出号 /// 出号
/// </summary> /// </summary>
@ -319,9 +319,9 @@ namespace DS.Module.Core
[Description("内点入货")] [Description("内点入货")]
WAIT_NDRH = 314, WAIT_NDRH = 314,
/// <summary> /// <summary>
/// 快递 /// 快递
/// </summary> /// </summary>
[Description("快递")] [Description("快递")]
WAIT_DELIVERY = 315, WAIT_DELIVERY = 315,
/// <summary> /// <summary>
/// 箱使 /// 箱使

@ -437,12 +437,12 @@ public class FlowInstanceService : ServiceBase, IFlowInstanceService
#endregion 或签 #endregion 或签
int nextNodeType = runtime.GetNextNodeType(); int nextNodeType = runtime.GetNextNodeType();
var serializerSettings = new JsonSerializerSettings //var serializerSettings = new JsonSerializerSettings
{ //{
// 设置为驼峰命名 // // 设置为驼峰命名
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() // ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
}; //};
instance.Content = JsonConvert.SerializeObject(runtime.ToFlowRoot(), Formatting.None, serializerSettings); //instance.Content = JsonConvert.SerializeObject(runtime.ToFlowRoot(), Formatting.None, serializerSettings);
instance.Note = auditNote; instance.Note = auditNote;
Db.Updateable(instance).ExecuteCommand(); Db.Updateable(instance).ExecuteCommand();

@ -1,4 +1,5 @@
using System.Runtime.Serialization; using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using DS.Module.Core; using DS.Module.Core;
using DS.WMS.Core.Fee.Dtos; using DS.WMS.Core.Fee.Dtos;
@ -7,7 +8,7 @@ namespace DS.WMS.Core.Op.Dtos.TaskInteraction
/// <summary> /// <summary>
/// 任务审核请求 /// 任务审核请求
/// </summary> /// </summary>
public class TaskAuditRequest : AuditRequest public class TaskAuditRequest : AuditRequest, IValidatableObject
{ {
/// <summary> /// <summary>
/// 任务类型名称 /// 任务类型名称
@ -19,5 +20,22 @@ namespace DS.WMS.Core.Op.Dtos.TaskInteraction
/// </summary> /// </summary>
[IgnoreDataMember] [IgnoreDataMember]
public TaskBaseTypeEnum TaskType => string.IsNullOrEmpty(TaskTypeName) ? TaskBaseTypeEnum.NOT_SPECIFIED : Enum.Parse<TaskBaseTypeEnum>(TaskTypeName); public TaskBaseTypeEnum TaskType => string.IsNullOrEmpty(TaskTypeName) ? TaskBaseTypeEnum.NOT_SPECIFIED : Enum.Parse<TaskBaseTypeEnum>(TaskTypeName);
/// <summary>
/// 确定当前对象是否有效
/// </summary>
/// <param name="validationContext">验证上下文</param>
/// <returns></returns>
public virtual IEnumerable<ValidationResult> 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)} 值不在有效枚举范围之内");
}
}
} }
} }

@ -49,7 +49,7 @@ namespace DS.WMS.Core.Op.Dtos.TaskInteraction
} }
else if (!Enum.TryParse(TaskTypeName, out TaskBaseTypeEnum taskType)) else if (!Enum.TryParse(TaskTypeName, out TaskBaseTypeEnum taskType))
{ {
yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 值无效"); yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 值不在有效枚举范围之内");
} }
} }
} }

@ -1,5 +1,4 @@
using DS.Module.Core; using DS.Module.Core;
using DS.Module.Core.Data;
using DS.Module.Core.Extensions; using DS.Module.Core.Extensions;
using SqlSugar; using SqlSugar;
@ -83,5 +82,11 @@ namespace DS.WMS.Core.Op.Entity.TaskInteraction
/// </summary> /// </summary>
[SugarColumn(ColumnDescription = "审批驳回理由", Length = 200, IsNullable = true)] [SugarColumn(ColumnDescription = "审批驳回理由", Length = 200, IsNullable = true)]
public string? RejectReason { get; set; } public string? RejectReason { get; set; }
/// <summary>
/// 下一任务配置ID
/// </summary>
[SugarColumn(ColumnDescription = "下一任务配置ID", IsNullable = true)]
public long? NextId { get; set; }
} }
} }

@ -1,5 +1,7 @@
using DS.Module.Core; using DS.Module.Core;
using DS.Module.Core.Condition;
using DS.Module.Core.Data; using DS.Module.Core.Data;
using DS.WMS.Core.Op.Dtos.TaskInteraction;
using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Op.Entity.TaskInteraction; using DS.WMS.Core.Op.Entity.TaskInteraction;
@ -10,6 +12,23 @@ namespace DS.WMS.Core.Op.Interface.TaskInteraction
/// </summary> /// </summary>
public interface IActionManagerService public interface IActionManagerService
{ {
/// <summary>
/// 根据指定条件返回是否匹配的结果
/// </summary>
/// <param name="request">任务请求</param>
/// <param name="conditions">匹配条件</param>
/// <returns></returns>
Task<bool> IsMatchAsync(TaskRequest request, IEnumerable<ConditionContent> conditions);
/// <summary>
/// 获取所需业务数据
/// </summary>
/// <param name="businessId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="conditions">条件字段</param>
/// <returns></returns>
Task<dynamic?> GetBusinessDataAsync(long businessId, BusinessType businessType, IEnumerable<ConditionContent> conditions);
/// <summary> /// <summary>
/// 获取所需业务数据 /// 获取所需业务数据
/// </summary> /// </summary>
@ -17,7 +36,7 @@ namespace DS.WMS.Core.Op.Interface.TaskInteraction
/// <param name="businessType">业务类型</param> /// <param name="businessType">业务类型</param>
/// <param name="fields">返回字段列表</param> /// <param name="fields">返回字段列表</param>
/// <returns></returns> /// <returns></returns>
dynamic? GetBusinessData(long businessId, BusinessType businessType, params string[] fields); Task<dynamic?> GetBusinessDataAsync(long businessId, BusinessType businessType, params string[] fields);
/// <summary> /// <summary>
/// 执行特定动作 /// 执行特定动作

@ -4,8 +4,11 @@ using DS.WMS.Core.Op.Interface.TaskInteraction;
using Masuit.Tools.Systems; using Masuit.Tools.Systems;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking
{ {
/// <summary>
/// 订舱动作
/// </summary>
public class BookingActionExecutor : DefaultActionExecutor public class BookingActionExecutor : DefaultActionExecutor
{ {
internal const TaskBaseTypeEnum Booking_TaskType = TaskBaseTypeEnum.WAIT_BOOKING; internal const TaskBaseTypeEnum Booking_TaskType = TaskBaseTypeEnum.WAIT_BOOKING;
@ -27,7 +30,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor
return Task.CompletedTask; return Task.CompletedTask;
} }
protected async Task<DataResult> CreateTask(ActionExecutionContext context) protected async Task<DataResult> CreateTask(ActionExecutionContext context)
{ {
var result = await TaskService.Exists(context.TaskInfo.BusinessId, context.TaskInfo.BusinessType, Booking_TaskType); 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 var result = await TaskService.SetTaskStatusAsync(new TaskUpdateRequest
{ {

@ -4,7 +4,7 @@ using DS.WMS.Core.Op.Interface;
using Masuit.Tools.Systems; using Masuit.Tools.Systems;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking
{ {
/// <summary> /// <summary>
/// 用于发送EDI的执行器 /// 用于发送EDI的执行器

@ -6,7 +6,7 @@ using Masuit.Tools.Systems;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using SqlSugar; using SqlSugar;
namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking
{ {
/// <summary> /// <summary>
/// 用于邮件发送的执行器 /// 用于邮件发送的执行器
@ -31,7 +31,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor
var taskMailService = context.ServiceProvider.GetRequiredService<ITaskMailService>(); var taskMailService = context.ServiceProvider.GetRequiredService<ITaskMailService>();
MailService mailService = new(context.ServiceProvider); MailService mailService = new(context.ServiceProvider);
BusinessTaskMail? mailConfig = null; 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) if (id == null)
{ {
@ -41,7 +41,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor
var idVal = (long)Convert.ChangeType(id, typeof(long)); var idVal = (long)Convert.ChangeType(id, typeof(long));
mailConfig = (await taskMailService.GetAsync(idVal)).Data; 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; var mailName = name as string;
if (mailName.IsNullOrEmpty()) 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); result = await mailService.SendAsync(mailConfig, context.TaskInfo.BusinessId, context.TaskInfo.BusinessType);
if (!result.Succeeded) if (!result.Succeeded)
{ {
await LogService.WriteLogAsync(context.TaskInfo, result.Message); await LogService.WriteLogAsync(context.TaskInfo, result.Message);
return; return;

@ -4,6 +4,9 @@ using DS.WMS.Core.Op.Interface.TaskInteraction;
namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor
{ {
/// <summary>
/// 默认动作执行器
/// </summary>
public class DefaultActionExecutor : IActionExecutor public class DefaultActionExecutor : IActionExecutor
{ {
internal static readonly ApiFox Api; internal static readonly ApiFox Api;
@ -13,6 +16,11 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor
Api = new ApiFox(); Api = new ApiFox();
} }
/// <summary>
/// 执行空的动作
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public virtual Task ExecuteAsync(ActionExecutionContext context) public virtual Task ExecuteAsync(ActionExecutionContext context)
{ {
return Task.CompletedTask; return Task.CompletedTask;

@ -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
{
/// <summary>
/// 放舱动作
/// </summary>
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<ISeaExportService>();
var logService = context.ServiceProvider.GetRequiredService<ITaskLogService>();
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)
//{
//}
}
/// <summary>
/// 放舱动作类型
/// </summary>
[Flags]
public enum SpaceReleaseActionType
{
/// <summary>
/// 未设置
/// </summary>
None = 0,
/// <summary>
/// 下货纸
/// </summary>
[Description("下货纸")]
ShippingOrder = 1 << 0,
/// <summary>
/// 入货通知
/// </summary>
[Description("入货通知")]
IncomingNotification = 1 << 1,
/// <summary>
/// 转发BC
/// </summary>
[Description("船东BC")]
RelayBC = 1 << 2
}
}

@ -1,15 +1,16 @@
using DS.Module.Core; using DS.Module.Core;
using DS.Module.Core.Condition;
using DS.Module.Core.Data; using DS.Module.Core.Data;
using DS.WMS.Core.Op.Dtos.TaskInteraction; 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.Entity.TaskInteraction;
using DS.WMS.Core.Op.Interface;
using DS.WMS.Core.Op.Interface.TaskInteraction; using DS.WMS.Core.Op.Interface.TaskInteraction;
using DS.WMS.Core.TaskPlat; using DS.WMS.Core.TaskPlat;
using Masuit.Tools;
using SqlSugar;
using Fasterflect; using Fasterflect;
using Masuit.Tools;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using DS.WMS.Core.Op.Entity; using SqlSugar;
using DS.WMS.Core.Op.Interface;
namespace DS.WMS.Core.Op.Method.TaskInteraction namespace DS.WMS.Core.Op.Method.TaskInteraction
{ {
@ -18,11 +19,79 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
/// </summary> /// </summary>
public class ActionManagerService : ServiceBase, IActionManagerService public class ActionManagerService : ServiceBase, IActionManagerService
{ {
ITaskLogService LogService;
/// <summary> /// <summary>
/// 初始化 /// 初始化
/// </summary> /// </summary>
public ActionManagerService(IServiceProvider serviceProvider) : base(serviceProvider) public ActionManagerService(IServiceProvider serviceProvider) : base(serviceProvider)
{ {
LogService = serviceProvider.GetRequiredService<ITaskLogService>();
}
/// <summary>
/// 根据指定条件返回是否匹配的结果
/// </summary>
/// <param name="request">任务请求</param>
/// <param name="conditions">匹配条件</param>
/// <returns></returns>
public async Task<bool> IsMatchAsync(TaskRequest request, IEnumerable<ConditionContent> 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;
}
/// <summary>
/// 获取所需业务数据
/// </summary>
/// <param name="businessId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="conditions">条件字段</param>
/// <returns></returns>
public async Task<dynamic?> GetBusinessDataAsync(long businessId, BusinessType businessType, IEnumerable<ConditionContent> conditions)
{
ArgumentNullException.ThrowIfNull(conditions, nameof(conditions));
HashSet<string> 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());
} }
/// <summary> /// <summary>
@ -32,7 +101,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
/// <param name="businessType">业务类型</param> /// <param name="businessType">业务类型</param>
/// <param name="fields">返回字段列表</param> /// <param name="fields">返回字段列表</param>
/// <returns></returns> /// <returns></returns>
public dynamic? GetBusinessData(long businessId, BusinessType businessType, params string[] fields) public async Task<dynamic?> GetBusinessDataAsync(long businessId, BusinessType businessType, params string[] fields)
{ {
object? biz = null; object? biz = null;
switch (businessType) switch (businessType)
@ -46,7 +115,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
else else
{ {
var selectors = fields.Select(x => new SelectModel { FieldName = x }).ToList(); var selectors = fields.Select(x => new SelectModel { FieldName = x }).ToList();
biz = TenantDb.Queryable<object>().AS("op_sea_export").Where("Id=@Id", new { Id = businessId }).Select(selectors).First(); biz = await TenantDb.Queryable<object>().AS("op_sea_export").Where("Id=@Id", new { Id = businessId }).Select(selectors).FirstAsync();
} }
break; break;
@ -70,17 +139,22 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
if (businessTask.TaskStatus != TaskStatusEnum.Complete) if (businessTask.TaskStatus != TaskStatusEnum.Complete)
return; return;
var biz = GetBusinessData(businessTask.BusinessId, businessTask.BusinessType); //var biz = GetBusinessDataAsync(businessTask.BusinessId, businessTask.BusinessType);
// 执行自动化操作 // 执行自动化操作
TaskFlowDataContext dataContext = new( TaskFlowDataContext dataContext = new(
(TaskFlowDataNameConst.BusinessTask, businessTask), (TaskFlowDataNameConst.BusinessTask, businessTask)
(TaskFlowDataNameConst.Business, biz) //(TaskFlowDataNameConst.Business, biz)
); );
TaskFlowRuner taskFlow = new(TenantDb, ServiceProvider); TaskFlowRuner taskFlow = new(TenantDb, ServiceProvider);
await taskFlow.RunWithBsno(businessTask.TaskType, businessTask.BusinessId, dataContext); await taskFlow.RunWithBsno(businessTask.TaskType, businessTask.BusinessId, dataContext);
} }
/// <summary>
/// 执行动作
/// </summary>
/// <param name="dataContext"></param>
/// <returns></returns>
public async Task ExecuteAsync(TaskFlowDataContext dataContext) public async Task ExecuteAsync(TaskFlowDataContext dataContext)
{ {
ArgumentNullException.ThrowIfNull(dataContext, nameof(dataContext)); ArgumentNullException.ThrowIfNull(dataContext, nameof(dataContext));
@ -93,30 +167,36 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
foreach (var key in dataContext.Keys) foreach (var key in dataContext.Keys)
context.AdditionalData[key] = dataContext[key]; context.AdditionalData[key] = dataContext[key];
string selectorType = dataContext.GetOrDefault<string>("SelectorType"); var typeName = dataContext.GetOrDefault<string>("TypeName");
if (selectorType.IsNullOrEmpty()) if (typeName.IsNullOrEmpty())
return; return;
Type? t = Type.GetType(selectorType, true, false); Type? t = Type.GetType(typeName, true, false);
if (t == null) if (t == null)
{ {
await new ApplicationException($"未能获取类型【{selectorType}】的信息").LogAsync(Db); await new ApplicationException($"未能获取类型【{typeName}】的信息").LogAsync(Db);
return; 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); currentExecutor = await selector.GetActionExecutor(context);
return; }
else if (ConstructorExtensions.CreateInstance(t) is IActionExecutor executor)
{
currentExecutor = executor;
} }
var executor = await selector.GetActionExecutor(context); if (currentExecutor == null)
if (executor != null)
{ {
executor.ExecuteAsync(context); await new ApplicationException($"未能创建类型【{t.AssemblyQualifiedName}】的实例").LogAsync(Db);
var logService = context.ServiceProvider.GetRequiredService<ITaskLogService>(); return;
await logService.WriteLogAsync(context.TaskInfo, $"开始运行后台任务({executor.GetType().FullName}...");
} }
await currentExecutor.ExecuteAsync(context);
var logService = context.ServiceProvider.GetRequiredService<ITaskLogService>();
await logService.WriteLogAsync(context.TaskInfo, $"开始运行后台任务({currentExecutor.GetType().FullName}...");
} }
public async Task<DataResult> TriggerTest(TaskBaseTypeEnum taskType, long? id) public async Task<DataResult> TriggerTest(TaskBaseTypeEnum taskType, long? id)

@ -7,12 +7,13 @@ using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Op.Entity.TaskInteraction; using DS.WMS.Core.Op.Entity.TaskInteraction;
using DS.WMS.Core.Op.Interface.TaskInteraction; using DS.WMS.Core.Op.Interface.TaskInteraction;
using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor; using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor;
using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionSelector namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionSelector
{ {
/// <summary> /// <summary>
/// 订舱 /// 订舱选择器
/// </summary> /// </summary>
public class BookingSelector : IActionSelector public class BookingSelector : IActionSelector
{ {
@ -20,7 +21,6 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionSelector
public async Task<IActionExecutor> GetActionExecutor(ActionExecutionContext context) public async Task<IActionExecutor> GetActionExecutor(ActionExecutionContext context)
{ {
//var db = context.ServiceProvider.GetRequiredService<ISqlSugarClient>();
var saasService = context.ServiceProvider.GetRequiredService<ISaasDbService>(); var saasService = context.ServiceProvider.GetRequiredService<ISaasDbService>();
var user = context.ServiceProvider.GetRequiredService<IUser>(); var user = context.ServiceProvider.GetRequiredService<IUser>();
var tenantDb = saasService.GetBizDbScopeById(user.TenantId); var tenantDb = saasService.GetBizDbScopeById(user.TenantId);

@ -17,6 +17,7 @@ using DS.Module.Core;
using Masuit.Tools; using Masuit.Tools;
using Masuit.Tools.Systems; using Masuit.Tools.Systems;
using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.Booking;
namespace DS.WMS.Core.Op.Method.TaskInteraction namespace DS.WMS.Core.Op.Method.TaskInteraction
{ {

@ -1,4 +1,5 @@
using DS.Module.Core; using DS.Module.Core;
using DS.Module.Core.Data;
using DS.Module.Core.Extensions; using DS.Module.Core.Extensions;
using DS.Module.DjyServiceStatus; using DS.Module.DjyServiceStatus;
using DS.WMS.Core.Op.Dtos.TaskInteraction; using DS.WMS.Core.Op.Dtos.TaskInteraction;
@ -47,7 +48,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
var taskLogList = new List<BusinessTaskLog>(); var taskLogList = new List<BusinessTaskLog>();
var first = request.First(); var first = request.First();
var defaultUsers = await GetRecvUsers(first.RecvUserIdList); var defaultUsers = await GetRecvUsersAsync(first.RecvUserIdList);
var biz = await TenantDb.Queryable<SeaExport>().Select(x => new var biz = await TenantDb.Queryable<SeaExport>().Select(x => new
{ {
x.Id, x.Id,
@ -58,9 +59,10 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
x.ETD, x.ETD,
}).FirstAsync(x => x.Id == first.BusinessId); }).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) foreach (var item in request)
{ {
var recvUsers = await GetRecvUsersFromConfig(item.BusinessId, item.BusinessType, item.TaskType); var recvUsers = dic[item.TaskType];
var info = new TaskManageOrderMessageInfo var info = new TaskManageOrderMessageInfo
{ {
Head = new TaskManageOrderMessageHeadInfo Head = new TaskManageOrderMessageHeadInfo
@ -122,24 +124,39 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
} }
/// <summary> /// <summary>
/// 当任务状态发生变化时调用 /// 创建关联子任务
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="dataContext"></param>
/// <returns></returns> /// <returns></returns>
protected override async Task OnTaskStatusChanged(TaskUpdateRequest request) public async Task CreateSubTaskAsync(TaskFlowDataContext dataContext)
{ {
//放舱结束,根据业务所选服务,生成子任务 if (dataContext[TaskFlowDataNameConst.BusinessTask] is BusinessTask task
if (request.TaskType == TaskBaseTypeEnum.WAIT_SPACE_RELEASE && request.TaskStatus == TaskStatusEnum.Complete) && task.TaskStatus == TaskStatusEnum.Complete)
{ {
var task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).FirstAsync(); var list = await GetSubRequestAsync(task.BusinessId, task.BusinessType, task.RecvUserIdArray);
if (task != null) await CreateSubTaskAsync(list.FindAll(x => x.TaskType != TaskBaseTypeEnum.NOT_SPECIFIED).OrderBy(x => x.TaskType));
{
var list = await GetSubRequestAsync(request.BusinessId, request.BusinessType, task.RecvUserIdArray);
await CreateSubTaskAsync(list.FindAll(x => x.TaskType != TaskBaseTypeEnum.NOT_SPECIFIED).OrderBy(x => x.TaskType));
}
} }
} }
///// <summary>
///// 当任务状态发生变化时调用
///// </summary>
///// <param name="request"></param>
///// <returns></returns>
//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<List<TaskCreationRequest>> GetSubRequestAsync(long id, BusinessType businessType, params long[]? recvUsers) internal async Task<List<TaskCreationRequest>> GetSubRequestAsync(long id, BusinessType businessType, params long[]? recvUsers)
{ {
var svcList = await GetServicesAsync(id); var svcList = await GetServicesAsync(id);
@ -172,7 +189,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
else if (svcName == "拖车") else if (svcName == "拖车")
dto.TaskTypeName = TaskBaseTypeEnum.WAIT_TUOCHE.ToString(); dto.TaskTypeName = TaskBaseTypeEnum.WAIT_TUOCHE.ToString();
else if (svcName == "保险") else if (svcName == "保险")
dto.TaskTypeName = TaskBaseTypeEnum.WAIT_Insurance.ToString(); dto.TaskTypeName = TaskBaseTypeEnum.WAIT_INSURANCE.ToString();
else if (svcName == "出号") else if (svcName == "出号")
dto.TaskTypeName = TaskBaseTypeEnum.WAIT_CHUHAO.ToString(); dto.TaskTypeName = TaskBaseTypeEnum.WAIT_CHUHAO.ToString();
else if (svcName == "内点入货") else if (svcName == "内点入货")
@ -202,28 +219,5 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
return extArray.Where(x => x["isYield"].Value<bool>()).Select(x => x["projectName"]?.Value<string>() ?? string.Empty).ToArray(); return extArray.Where(x => x["isYield"].Value<bool>()).Select(x => x["projectName"]?.Value<string>() ?? string.Empty).ToArray();
} }
//public override async Task MarkerChangedAsync(MarkerChangedCallback callback)
//{
// if (callback.Type != AuditType.SeaExport)
// return;
// await base.MarkerChangedAsync(callback);
//}
///// <summary>
///// 审批完成回调更新
///// </summary>
///// <param name="callback">回调信息</param>
///// <returns></returns>
//public override async Task UpdateBusinessAsync(FlowCallback callback)
//{
// if (callback.Type != AuditType.SeaExport)
// return;
// await base.UpdateBusinessAsync(callback);
// //todo:海运出口主表信息
//}
} }
} }

@ -11,6 +11,7 @@ using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Op.Entity.TaskInteraction; using DS.WMS.Core.Op.Entity.TaskInteraction;
using DS.WMS.Core.Op.Interface.TaskInteraction; using DS.WMS.Core.Op.Interface.TaskInteraction;
using DS.WMS.Core.Sys.Entity; using DS.WMS.Core.Sys.Entity;
using DS.WMS.Core.TaskPlat;
using DS.WMS.Core.TaskPlat.Dtos; using DS.WMS.Core.TaskPlat.Dtos;
using DS.WMS.Core.TaskPlat.Entity; using DS.WMS.Core.TaskPlat.Entity;
using DS.WMS.Core.TaskPlat.Interface; using DS.WMS.Core.TaskPlat.Interface;
@ -76,18 +77,23 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
/// <summary> /// <summary>
/// 获取给定任务的下一任务类型 /// 获取给定任务的下一任务类型
/// </summary> /// </summary>
/// <param name="current">任务信息</param> /// <param name="current"></param>
/// <returns></returns> /// <returns></returns>
internal static TaskBaseTypeEnum? GetNextType(BusinessTask current) public async Task<TaskBaseTypeEnum?> GetNextTypeAsync(BusinessTask current)
{ {
if (current.TaskType == TaskBaseTypeEnum.NOT_SPECIFIED || current.TaskType == TaskBaseTypeEnum.WAIT_CHECKOUT_BILL) //流程的最后一步 TaskFlowRuner flowRuner = new TaskFlowRuner(TenantDb, ServiceProvider);
return null;
int currentTypeVal = (int)current.TaskType; var result = await flowRuner.GetWorkFlowNextConfig(new TaskFlowDataContext(
if (currentTypeVal >= 300) //300开始的枚举值为可选服务项目不存在前后关联性
return null; ), current.NextId);
return (TaskBaseTypeEnum)(currentTypeVal + 1); if (result.HasValue)
{
current.NextId = result.Value.configId;
return result.Value.taskType;
}
return null;
} }
/// <summary> /// <summary>
@ -252,8 +258,8 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
if (task != null && task.TaskStatus != TaskStatusEnum.Cancel) if (task != null && task.TaskStatus != TaskStatusEnum.Cancel)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskExists)); return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskExists));
//if (await ShouldSkipAsync(request)) if (await ShouldSkipAsync(request))
// return DataResult.Success; return DataResult.Success;
long tenatId = long.Parse(User.TenantId); long tenatId = long.Parse(User.TenantId);
string tenatName = Db.Queryable<SysTenant>().Where(x => x.Id == tenatId).Select(x => x.Name).First(); string tenatName = Db.Queryable<SysTenant>().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) 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 (info.Main.RecvUserInfoList == null || info.Main.RecvUserInfoList.Count == 0)
{ {
if (AuditTaskTypes.Contains(request.TaskType)) if (AuditTaskTypes.Contains(request.TaskType))
{ {
info.Main.RecvUserInfoList = await GetRecvUsers(long.Parse(User.UserId)); info.Main.RecvUserInfoList = await GetRecvUsersAsync(long.Parse(User.UserId));
} }
else else
{ {
@ -304,7 +310,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
} }
else else
{ {
info.Main.RecvUserInfoList = await GetRecvUsers(request.RecvUserIdList); info.Main.RecvUserInfoList = await GetRecvUsersAsync(request.RecvUserIdList);
} }
if (info.Main.TaskTitle.IsNullOrEmpty()) if (info.Main.TaskTitle.IsNullOrEmpty())
@ -341,7 +347,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
CreateBy = long.Parse(User.UserId), CreateBy = long.Parse(User.UserId),
CreateTime = DateTime.Now CreateTime = DateTime.Now
}; };
task.NextType = GetNextType(task); task.NextType = await GetNextTypeAsync(task);
await TenantDb.Insertable(task).ExecuteCommandAsync(); await TenantDb.Insertable(task).ExecuteCommandAsync();
//审核任务需创建工作流 //审核任务需创建工作流
@ -374,53 +380,17 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
} }
} }
internal async Task<bool> ShouldSkipAsync(TaskRequest request) internal async Task<bool> ShouldSkipAsync(TaskRequest request)
{ {
var configList = await TenantDb.Queryable<BusinessTaskConfig>().Where(x => x.TaskType == request.TaskType && x.IsSkip) var configList = await TenantDb.Queryable<BusinessTaskConfig>().Where(x => x.TaskType == request.TaskType && x.IsSkip)
.Select(x => new { x.Id, x.SourceName, x.MatchCondition }).ToListAsync(); .Select(x => new { x.Id, x.SourceName, x.MatchCondition }).ToListAsync();
if (configList.Count > 0) if (configList.Count > 0)
{ {
var conditionList = configList.Select(x => new { x.Id, x.SourceName, MatchCondition = JsonConvert.DeserializeObject<ContitionContent>(x.MatchCondition) }).ToList(); var conditionList = configList.Select(x => new { x.Id, x.SourceName, MatchCondition = JsonConvert.DeserializeObject<ConditionContent>(x.MatchCondition) }).ToList();
HashSet<string> fields = [];
foreach (var item in conditionList) foreach (var item in conditionList)
{ item.MatchCondition.SourceName = item.SourceName;
if (item.MatchCondition.Conditions != null)
fields.AddRange(item.MatchCondition.Conditions.Select(x => x.Field));
if (item.MatchCondition.Groups != null) return await ActionService.Value.IsMatchAsync(request, conditionList.Select(x => x.MatchCondition));
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 false; return false;
@ -459,7 +429,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
{ {
string[] ids = FlowInstanceService.GetMarkers(instance); 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); result = await ManagerService.TransferTask(task.BusinessId, task.TaskType, users);
if (result.Succeeded) if (result.Succeeded)
{ {
@ -546,8 +516,8 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
if (useTransaction) if (useTransaction)
await TenantDb.Ado.CommitTranAsync(); await TenantDb.Ado.CommitTranAsync();
//ActionService.Value.TriggerAction(task); ActionService.Value.TriggerAction(task);
return DataResult<TaskBaseTypeEnum?>.Success(task.TaskStatus == TaskStatusEnum.Complete ? GetNextType(task) : null); return DataResult<TaskBaseTypeEnum?>.Success(task.TaskStatus == TaskStatusEnum.Complete ? await GetNextTypeAsync(task) : null);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -580,7 +550,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
ArgumentNullException.ThrowIfNull(callback, nameof(callback)); ArgumentNullException.ThrowIfNull(callback, nameof(callback));
long userId = long.Parse(User.UserId); long userId = long.Parse(User.UserId);
var users = await GetRecvUsers(userId); var users = await GetRecvUsersAsync(userId);
var dt = DateTime.Now; var dt = DateTime.Now;
var taskType = TypeMappings.Where(x => x.Value == callback.Type.GetValueOrDefault()).Select(x => x.Key).FirstOrDefault(); 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); await SetTaskStatusAsync(req);
long userId = long.Parse(User.UserId); long userId = long.Parse(User.UserId);
var users = await GetRecvUsers(userId); var users = await GetRecvUsersAsync(userId);
string remark = "终审完成,审批结果为:" + callback.FlowStatus.GetDescription(); string remark = "终审完成,审批结果为:" + callback.FlowStatus.GetDescription();
if (callback.FlowStatus == FlowStatusEnum.Reject) if (callback.FlowStatus == FlowStatusEnum.Reject)
@ -685,10 +655,29 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
/// <param name="businessType">业务类型</param> /// <param name="businessType">业务类型</param>
/// <param name="taskType">任务类型</param> /// <param name="taskType">任务类型</param>
/// <returns></returns> /// <returns></returns>
protected internal async Task<List<RecvUserInfo>?> GetRecvUsersFromConfig(long id, BusinessType businessType, TaskBaseTypeEnum taskType) protected internal async Task<List<RecvUserInfo>> 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 : [];
}
/// <summary>
/// 从任务配置中获取接收用户列表
/// </summary>
/// <param name="id">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="taskTypes">任务类型</param>
/// <returns></returns>
protected internal async Task<Dictionary<TaskBaseTypeEnum, List<RecvUserInfo>>> GetRecvUsersAsync(long id, BusinessType businessType, List<TaskBaseTypeEnum> taskTypes)
{ {
var biz = ActionService.Value.GetBusinessData(id, businessType); var biz = ActionService.Value.GetBusinessDataAsync(id, businessType);
var result = await TaskAllocationService.Value.GetAllotUserBySeaExportId(taskType, id, new TaskFlowDataContext( var result = await TaskAllocationService.Value.GetAllotUserBySeaExportId(taskTypes, id, new TaskFlowDataContext(
(TaskFlowDataNameConst.Business, biz) (TaskFlowDataNameConst.Business, biz)
)); ));
return result.Succeeded ? result.Data : []; return result.Succeeded ? result.Data : [];
@ -699,7 +688,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
/// </summary> /// </summary>
/// <param name="ids">用户ID</param> /// <param name="ids">用户ID</param>
/// <returns></returns> /// <returns></returns>
protected internal async Task<List<RecvUserInfo>> GetRecvUsers(params long[] ids) protected internal async Task<List<RecvUserInfo>> GetRecvUsersAsync(params long[] ids)
{ {
return await Db.Queryable<SysUser>().Where(x => ids.Contains(x.Id)).Select( return await Db.Queryable<SysUser>().Where(x => ids.Contains(x.Id)).Select(
x => new RecvUserInfo { RecvUserId = x.Id, RecvUserName = x.UserName }).ToListAsync(); x => new RecvUserInfo { RecvUserId = x.Id, RecvUserName = x.UserName }).ToListAsync();

@ -40,6 +40,12 @@ namespace DS.WMS.Core.TaskPlat.Entity
[SugarColumn(ColumnDescription = "所属主入口流程主键", IsNullable = true)] [SugarColumn(ColumnDescription = "所属主入口流程主键", IsNullable = true)]
public long? MainConfigId { get; set; } public long? MainConfigId { get; set; }
///// <summary>
///// 下一流程主键
///// </summary>
//[SugarColumn(ColumnDescription = "下一流程主键", IsNullable = true)]
//public long? NextConfigId { get; set; }
/// <summary> /// <summary>
/// 父项流程主键 /// 父项流程主键
/// </summary> /// </summary>

@ -3,6 +3,7 @@ using DS.Module.Core.Condition;
using DS.Module.Core.Data; using DS.Module.Core.Data;
using DS.Module.SqlSugar; using DS.Module.SqlSugar;
using DS.Module.UserModule; using DS.Module.UserModule;
using DS.WMS.Core.Op.Dtos;
using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Interface; using DS.WMS.Core.Sys.Interface;
using DS.WMS.Core.Sys.Method; 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.Entity;
using DS.WMS.Core.TaskPlat.Interface; using DS.WMS.Core.TaskPlat.Interface;
using LanguageExt.Pipes; using LanguageExt.Pipes;
using Mapster;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using SqlSugar; using SqlSugar;
@ -255,7 +257,7 @@ namespace DS.WMS.Core.TaskPlat.Method
} }
else else
{ {
var contitionContent = JsonConvert.DeserializeObject<ContitionContent>(item.Condition)!; var contitionContent = JsonConvert.DeserializeObject<ConditionContent>(item.Condition)!;
if (ConditionHelper.IsPass(contitionContent, dataContext)) if (ConditionHelper.IsPass(contitionContent, dataContext))
{ {
allotTargetList.Add(item); allotTargetList.Add(item);
@ -273,7 +275,8 @@ namespace DS.WMS.Core.TaskPlat.Method
var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId);
if (dataContext.ContainsKey(TaskFlowDataNameConst.Business)) if (dataContext.ContainsKey(TaskFlowDataNameConst.Business))
{ {
order = dataContext.Get<SeaExport>(TaskFlowDataNameConst.Business); var orderDto = dataContext.Get<SeaExportRes>(TaskFlowDataNameConst.Business);
order = orderDto.Adapt<SeaExport>();
} }
else else
{ {
@ -385,7 +388,7 @@ namespace DS.WMS.Core.TaskPlat.Method
} }
else else
{ {
var contitionContent = JsonConvert.DeserializeObject<ContitionContent>(allotItem.Condition)!; var contitionContent = JsonConvert.DeserializeObject<ConditionContent>(allotItem.Condition)!;
if (ConditionHelper.IsPass(contitionContent, dataContext)) if (ConditionHelper.IsPass(contitionContent, dataContext))
{ {
itemResult.Add(allotItem); itemResult.Add(allotItem);
@ -403,7 +406,8 @@ namespace DS.WMS.Core.TaskPlat.Method
var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId);
if (dataContext.ContainsKey(TaskFlowDataNameConst.Business)) if (dataContext.ContainsKey(TaskFlowDataNameConst.Business))
{ {
order = dataContext.Get<SeaExport>(TaskFlowDataNameConst.Business); var orderDto = dataContext.Get<SeaExportRes>(TaskFlowDataNameConst.Business);
order = orderDto.Adapt<SeaExport>();
} }
else else
{ {

@ -81,7 +81,7 @@ namespace DS.WMS.Core.TaskPlat
var conditionItem = allConditionList.FirstOrDefault(x => x.ConfigId == configItem.Id); var conditionItem = allConditionList.FirstOrDefault(x => x.ConfigId == configItem.Id);
if (conditionItem != null && !string.IsNullOrEmpty(conditionItem.Content)) if (conditionItem != null && !string.IsNullOrEmpty(conditionItem.Content))
{ {
var contitionContent = JsonConvert.DeserializeObject<ContitionContent>(conditionItem.Content)!; var contitionContent = JsonConvert.DeserializeObject<ConditionContent>(conditionItem.Content)!;
var oldValue = configMatchCount[configItem.Id]; var oldValue = configMatchCount[configItem.Id];
if (ConditionHelper.IsPass(contitionContent, dataContext)) if (ConditionHelper.IsPass(contitionContent, dataContext))
@ -179,7 +179,7 @@ namespace DS.WMS.Core.TaskPlat
continue; continue;
} }
var contitionContent = JsonConvert.DeserializeObject<ContitionContent>(condition.Content)!; var contitionContent = JsonConvert.DeserializeObject<ConditionContent>(condition.Content)!;
if (ConditionHelper.IsPass(contitionContent, dataContext)) if (ConditionHelper.IsPass(contitionContent, dataContext))
{ {
matchedConfigList.Add(waitMatchConfigItem); matchedConfigList.Add(waitMatchConfigItem);
@ -357,6 +357,85 @@ namespace DS.WMS.Core.TaskPlat
.FirstAsync(); .FirstAsync();
return await Run(taskBaseType, taskId, dataContext); return await Run(taskBaseType, taskId, dataContext);
} }
/// <summary>
/// 根据当前节点Id获取工作流下一个任务类型
/// </summary>
/// <param name="dataContext"></param>
/// <param name="currentConfigId">当前执行的配置Id如果为空则返回首个任务类型</param>
/// <returns>下一个任务类型下一节点Id</returns>
public async Task<(TaskBaseTypeEnum taskType, long configId)?> GetWorkFlowNextConfig(TaskFlowDataContext dataContext, long? currentConfigId = null)
{
var allConfigList = await tenantDb.Queryable<TaskFlowConfig>()
.Where(t => t.MainConfigId == SqlFunc.Subqueryable<TaskFlowConfig>().Where(x => x.IsMain && x.TaskType == "WORK_FLOW").Select(x => x.Id))
.OrderBy(t => t.Id)
.ToListAsync();
if (allConfigList.Count == 0) return null;
List<TaskFlowConfig> 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<TaskFlowCondition>()
.Where(x => configIdList.Contains(x.ConfigId))
.ToListAsync();
var matchedConfigList = new List<TaskFlowConfig>();
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<ConditionContent>(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<TaskFlowModule>().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) static string WriteLog(string throwMsg, Exception ex)
{ {
return string.Format("【自定义错误】:{0} \r\n【异常类型】{1} \r\n【异常信息】{2} \r\n【堆栈调用】{3}", new object[] return string.Format("【自定义错误】:{0} \r\n【异常类型】{1} \r\n【异常信息】{2} \r\n【堆栈调用】{3}", new object[]

@ -94,6 +94,9 @@ namespace DS.WMS.OpApi.Controllers
[HttpPost, Route("SubmitAudit")] [HttpPost, Route("SubmitAudit")]
public async Task<DataResult> SubmitAuditAsync(TaskRequest request) public async Task<DataResult> SubmitAuditAsync(TaskRequest request)
{ {
if (!ModelState.IsValid)
return DataResult.Failed(ModelState.GetErrorMessage(), MultiLanguageConst.IllegalRequest);
return await taskService.SubmitAuditAsync(request); return await taskService.SubmitAuditAsync(request);
} }
@ -105,6 +108,9 @@ namespace DS.WMS.OpApi.Controllers
[HttpPost, Route("Audit")] [HttpPost, Route("Audit")]
public async virtual Task<DataResult> AuditAsync([FromBody] TaskAuditRequest request) public async virtual Task<DataResult> AuditAsync([FromBody] TaskAuditRequest request)
{ {
if (!ModelState.IsValid)
return DataResult.Failed(ModelState.GetErrorMessage(), MultiLanguageConst.IllegalRequest);
return await taskService.AuditAsync(request); return await taskService.AuditAsync(request);
} }
@ -126,7 +132,7 @@ namespace DS.WMS.OpApi.Controllers
/// <param name="callback">回调信息</param> /// <param name="callback">回调信息</param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("MarkerChanged")] [HttpPost, Route("MarkerChanged")]
public virtual async Task<IActionResult> MarkerChangedAsync([FromBody] MarkerChangedCallback callback) public async Task<IActionResult> MarkerChangedAsync([FromBody] MarkerChangedCallback callback)
{ {
await taskService.MarkerChangedAsync(callback); await taskService.MarkerChangedAsync(callback);
return StatusCode((int)HttpStatusCode.NoContent); return StatusCode((int)HttpStatusCode.NoContent);

@ -8,7 +8,7 @@ namespace DS.WMS.OpApi.Controllers
/// <summary> /// <summary>
/// 预订舱马士基API即期订舱 /// 预订舱马士基API即期订舱
/// </summary> /// </summary>
public class SpaceBookingMSKAPISpotController : Controller public class SpaceBookingMSKAPISpotController : ApiController
{ {
private readonly ISpaceBookingMSKSPOTAPIService _spaceBookingMSKSPOTAPIService; private readonly ISpaceBookingMSKSPOTAPIService _spaceBookingMSKSPOTAPIService;

@ -1,5 +1,6 @@
using System.Reflection; using System.Reflection;
using DS.Module.Core; using DS.Module.Core;
using DS.Module.Core.Data;
using DS.Module.Core.Extensions; using DS.Module.Core.Extensions;
using DS.Module.SqlSugar; using DS.Module.SqlSugar;
using DS.WMS.Core.Check.Entity; 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;
using DS.WMS.Core.Op.Entity.BookingSlot; using DS.WMS.Core.Op.Entity.BookingSlot;
using DS.WMS.Core.Sys.Entity; using DS.WMS.Core.Sys.Entity;
using DS.WMS.Core.TaskPlat;
using DS.WMS.Core.TaskPlat.Entity; using DS.WMS.Core.TaskPlat.Entity;
using Mapster; using Mapster;
using Masuit.Tools.Strings; using Masuit.Tools.Strings;
@ -53,7 +55,7 @@ public class SaasTest
StaticConfig.CodeFirst_MySqlCollate = "utf8mb4_0900_ai_ci";//较高版本支持 StaticConfig.CodeFirst_MySqlCollate = "utf8mb4_0900_ai_ci";//较高版本支持
types = types.Where(it => it.Name != "BusinessFeeStatus").ToArray(); types = types.Where(it => it.Name != "BusinessFeeStatus").ToArray();
types = types.Where(it => it.Name != "BusinessOrderContact").ToArray(); types = types.Where(it => it.Name != "BusinessOrderContact").ToArray();
tenantDb.CodeFirst.InitTables(types); tenantDb.CodeFirst.InitTables(types);
// //初始化数库 // //初始化数库
// tenantDb.DbMaintenance.CreateDatabase(); // tenantDb.DbMaintenance.CreateDatabase();
@ -66,7 +68,7 @@ public class SaasTest
/// </summary> /// </summary>
[Fact] [Fact]
public void MasterInitTableTest() public void MasterInitTableTest()
{ {
StaticConfig.CodeFirst_MySqlCollate = "utf8mb4_0900_ai_ci";//较高版本支持 StaticConfig.CodeFirst_MySqlCollate = "utf8mb4_0900_ai_ci";//较高版本支持
db.CodeFirst.InitTables(typeof(SysPrintTemplate)); db.CodeFirst.InitTables(typeof(SysPrintTemplate));
//tenantDb.CodeFirst.InitTables(typeof(CheckBillAutoDetail)); //tenantDb.CodeFirst.InitTables(typeof(CheckBillAutoDetail));
@ -251,4 +253,18 @@ public class SaasTest
//tenantDb.CodeFirst.InitTables(typeof(TaskFlowLogDetail)); //tenantDb.CodeFirst.InitTables(typeof(TaskFlowLogDetail));
Assert.True(true); Assert.True(true);
} }
[Fact]
public async Task ZxfTest()
{
var tenantDb = saasService.GetBizDbScopeById("1819549542425694208");
var order = await tenantDb.Queryable<SeaExport>().FirstAsync(x => x.Id == 1816649497120477184);
TaskFlowDataContext dataContext = new(
(TaskFlowDataNameConst.Business, order)
);
TaskFlowRuner runer = new TaskFlowRuner(tenantDb, _serviceProvider);
var result =await runer.GetWorkFlowNextConfig(dataContext, null);
}
} }
Loading…
Cancel
Save