zhangxiaofeng 3 months ago
commit b4b7c3e347

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

@ -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
/// <summary>
/// 根据ContitionContent条件从数据上下文TaskFlowDataContext中取出指定数据然后判断条件是否符合
/// </summary>
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<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>;
}
@ -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))
{

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

@ -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();

@ -1197,6 +1197,16 @@ public class SeaExportReq
/// 船司航线
/// </summary>
public string CarrierLane { get; set; }
/// <summary>
/// SO备注
/// </summary>
public string SORemark { get; set; }
/// <summary>
/// 签单要求
/// </summary>
public string IssueRemark { get; set; }
}
/// <summary>

@ -1384,4 +1384,14 @@ public class SeaExportRes
/// 船司航线
/// </summary>
public string CarrierLane { get; set; }
/// <summary>
/// SO备注
/// </summary>
public string SORemark { get; set; }
/// <summary>
/// 签单要求
/// </summary>
public string IssueRemark { get; set; }
}

@ -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
/// <summary>
/// 任务审核请求
/// </summary>
public class TaskAuditRequest : AuditRequest
public class TaskAuditRequest : AuditRequest, IValidatableObject
{
/// <summary>
/// 任务类型名称
@ -19,5 +20,22 @@ namespace DS.WMS.Core.Op.Dtos.TaskInteraction
/// </summary>
[IgnoreDataMember]
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))
{
yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 值无效");
yield return new ValidationResult($"参数 {nameof(TaskTypeName)} 值不在有效枚举范围之内");
}
}
}

@ -864,9 +864,9 @@ public class SeaExport : BaseOrgModel<long>
public DateTime? CloseDocDate { get; set; }
/// <summary>
/// 截单备注
/// 截单备注(SI)
/// </summary>
[SqlSugar.SugarColumn(ColumnDescription = "截单备注", IsNullable = true, ColumnDataType = StaticConfig.CodeFirst_BigString)]
[SqlSugar.SugarColumn(ColumnDescription = "截单备注(SI)", IsNullable = true, ColumnDataType = StaticConfig.CodeFirst_BigString)]
public string CloseDocRemark { get; set; }
/// <summary>
/// 订舱备注
@ -1569,4 +1569,16 @@ public class SeaExport : BaseOrgModel<long>
/// </summary>
[SugarColumn(ColumnDescription = "船司航线", IsNullable = true, Length = 100)]
public string CarrierLane { get; set; }
/// <summary>
/// SO备注
/// </summary>
[SqlSugar.SugarColumn(ColumnDescription = "SO备注", IsNullable = true, ColumnDataType = StaticConfig.CodeFirst_BigString)]
public string SORemark { get; set; }
/// <summary>
/// 签单要求
/// </summary>
[SugarColumn(ColumnDescription = "签单要求", IsNullable = true, Length = 200)]
public string IssueRemark { get; set; }
}

@ -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
/// </summary>
[SugarColumn(ColumnDescription = "审批驳回理由", Length = 200, IsNullable = true)]
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.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
/// </summary>
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>
@ -17,7 +36,7 @@ namespace DS.WMS.Core.Op.Interface.TaskInteraction
/// <param name="businessType">业务类型</param>
/// <param name="fields">返回字段列表</param>
/// <returns></returns>
dynamic? GetBusinessData(long businessId, BusinessType businessType, params string[] fields);
Task<dynamic?> GetBusinessDataAsync(long businessId, BusinessType businessType, params string[] fields);
/// <summary>
/// 执行特定动作

@ -583,7 +583,7 @@ public partial class SeaExportService : ISeaExportService
//开启事务
await dbScope.Ado.BeginTranAsync();
info.Note = "正常编辑";
await tenantDb.Updateable(info).IgnoreColumns(ignoreAllNullColumns: true).EnableDiffLogEvent().ExecuteCommandAsync();
await tenantDb.Updateable(info).EnableDiffLogEvent().ExecuteCommandAsync();//.IgnoreColumns(ignoreAllNullColumns: true)
await seaComService.SaveSeaExportLogAsync(new SeaExportSaveLog()
{

@ -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
{
/// <summary>
/// 订舱动作
/// </summary>
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<DataResult> CreateTask(ActionExecutionContext context)
protected async Task<DataResult> 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
{

@ -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
{
/// <summary>
/// 用于发送EDI的执行器

@ -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
{
/// <summary>
/// 用于邮件发送的执行器
@ -31,7 +31,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor
var taskMailService = context.ServiceProvider.GetRequiredService<ITaskMailService>();
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;

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

@ -0,0 +1,74 @@
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);
}
}
}
/// <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.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
/// </summary>
public class ActionManagerService : ServiceBase, IActionManagerService
{
ITaskLogService LogService;
/// <summary>
/// 初始化
/// </summary>
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>
@ -32,7 +101,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
/// <param name="businessType">业务类型</param>
/// <param name="fields">返回字段列表</param>
/// <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;
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<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;
@ -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);
}
/// <summary>
/// 执行动作
/// </summary>
/// <param name="dataContext"></param>
/// <returns></returns>
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<string>("SelectorType");
if (selectorType.IsNullOrEmpty())
var typeName = dataContext.GetOrDefault<string>("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<ITaskLogService>();
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<ITaskLogService>();
await logService.WriteLogAsync(context.TaskInfo, $"开始运行后台任务({currentExecutor.GetType().FullName}...");
}
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.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
{
/// <summary>
/// 订舱
/// 订舱选择器
/// </summary>
public class BookingSelector : IActionSelector
{
@ -20,7 +21,6 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionSelector
public async Task<IActionExecutor> GetActionExecutor(ActionExecutionContext context)
{
//var db = context.ServiceProvider.GetRequiredService<ISqlSugarClient>();
var saasService = context.ServiceProvider.GetRequiredService<ISaasDbService>();
var user = context.ServiceProvider.GetRequiredService<IUser>();
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);

@ -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
{

@ -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<BusinessTaskLog>();
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
{
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
}
/// <summary>
/// 当任务状态发生变化时调用
/// 创建关联子任务
/// </summary>
/// <param name="request"></param>
/// <param name="dataContext"></param>
/// <returns></returns>
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));
}
}
///// <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)
{
var svcList = await GetServicesAsync(id);
@ -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();
}
//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:海运出口主表信息
//}
}
}

@ -74,11 +74,11 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
}
/// <summary>
/// 获取给定任务的下一任务类型
/// 获取给定任务的下一默认任务类型
/// </summary>
/// <param name="current">任务信息</param>
/// <returns></returns>
internal static TaskBaseTypeEnum? GetNextType(BusinessTask current)
internal static TaskBaseTypeEnum? GetDefaultNextType(BusinessTask current)
{
if (current.TaskType == TaskBaseTypeEnum.NOT_SPECIFIED || current.TaskType == TaskBaseTypeEnum.WAIT_CHECKOUT_BILL) //流程的最后一步
return null;
@ -252,8 +252,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<SysTenant>().Where(x => x.Id == tenatId).Select(x => x.Name).First();
@ -289,12 +289,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 +304,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 +341,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
CreateBy = long.Parse(User.UserId),
CreateTime = DateTime.Now
};
task.NextType = GetNextType(task);
task.NextType = GetDefaultNextType(task);
await TenantDb.Insertable(task).ExecuteCommandAsync();
//审核任务需创建工作流
@ -374,53 +374,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)
.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<ContitionContent>(x.MatchCondition) }).ToList();
HashSet<string> fields = [];
var conditionList = configList.Select(x => new { x.Id, x.SourceName, MatchCondition = JsonConvert.DeserializeObject<ConditionContent>(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 +423,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 +510,8 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
if (useTransaction)
await TenantDb.Ado.CommitTranAsync();
//ActionService.Value.TriggerAction(task);
return DataResult<TaskBaseTypeEnum?>.Success(task.TaskStatus == TaskStatusEnum.Complete ? GetNextType(task) : null);
ActionService.Value.TriggerAction(task);
return DataResult<TaskBaseTypeEnum?>.Success(task.TaskStatus == TaskStatusEnum.Complete ? GetDefaultNextType(task) : null);
}
catch (Exception ex)
{
@ -580,7 +544,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 +594,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 +649,29 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
/// <param name="businessType">业务类型</param>
/// <param name="taskType">任务类型</param>
/// <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 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 +682,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
/// </summary>
/// <param name="ids">用户ID</param>
/// <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(
x => new RecvUserInfo { RecvUserId = x.Id, RecvUserName = x.UserName }).ToListAsync();

@ -1081,7 +1081,7 @@ public class CommonService : ICommonService
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var list = await tenantDb.Queryable<CodePort>()
.Where(x => x.Status == StatusEnum.Enable)
.WhereIF(!string.IsNullOrEmpty(queryKey), x => x.PortName.Contains(queryKey) || x.CnName.Contains(queryKey))
.WhereIF(!string.IsNullOrEmpty(queryKey), x => x.PortName.Contains(queryKey) || x.CnName.Contains(queryKey) || x.EdiCode.Contains(queryKey))
.Select(x => new CodePortSelectRes()
{
PinYinCode = !String.IsNullOrEmpty(x.EdiCode) ? x.EdiCode + "/" + x.PortName : x.PortName,

@ -94,6 +94,9 @@ namespace DS.WMS.OpApi.Controllers
[HttpPost, Route("SubmitAudit")]
public async Task<DataResult> 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<DataResult> 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
/// <param name="callback">回调信息</param>
/// <returns></returns>
[HttpPost, Route("MarkerChanged")]
public virtual async Task<IActionResult> MarkerChangedAsync([FromBody] MarkerChangedCallback callback)
public async Task<IActionResult> MarkerChangedAsync([FromBody] MarkerChangedCallback callback)
{
await taskService.MarkerChangedAsync(callback);
return StatusCode((int)HttpStatusCode.NoContent);

Loading…
Cancel
Save