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

322 lines
13 KiB
C#

This file contains ambiguous Unicode characters!

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

using DS.Module.Core;
using DS.Module.Core.Condition;
using DS.Module.Core.Data;
using DS.WMS.Core.Code.Entity;
using DS.WMS.Core.Op.Dtos;
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.TaskInteraction;
using DS.WMS.Core.Op.Method.TaskInteraction.ActionSelector;
using DS.WMS.Core.TaskPlat;
using Fasterflect;
using Masuit.Tools;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
namespace DS.WMS.Core.Op.Method.TaskInteraction
{
/// <summary>
/// 动作执行管理
/// </summary>
public class ActionManagerService : ServiceBase, IActionManagerService
{
ITaskLogService logService;
/// <summary>
/// 初始化
/// </summary>
public ActionManagerService(IServiceProvider serviceProvider) : base(serviceProvider)
{
logService = serviceProvider.GetRequiredService<ITaskLogService>();
TenantDb.QueryFilter.Clear<IOrgId>();
}
/// <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>
/// <param name="businessId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="fields">返回字段列表</param>
/// <returns></returns>
public async Task<dynamic?> GetBusinessDataAsync(long businessId, BusinessType businessType, params string[] fields)
{
object? biz = null;
switch (businessType)
{
case BusinessType.OceanShippingExport:
//未设置查询字段
if (fields == null || fields.Length == 0)
{
biz = await TenantDb.Queryable<SeaExport>().Where(a => a.Id == businessId)
.Select<SeaExportRes>().Mapper(it =>
{
it.DischargePortCountry = TenantDb.Queryable<CodePort>().Where(x => x.Id == it.DischargePortId).Select(x => x.CountryName).First();
}).FirstAsync();
}
else
{
var selectors = fields.Select(x => new SelectModel { FieldName = x }).ToList();
biz = await TenantDb.Queryable<object>().AS("op_sea_export")
.Where("Id=@Id", new { Id = businessId }).Select(selectors).FirstAsync();
}
break;
case BusinessType.OceanShippingImport:
break;
}
return biz;
}
/// <summary>
/// 触发任务执行动作
/// </summary>
/// <param name="dataContext"></param>
/// <returns></returns>
public async Task TriggerActionAsync(TaskFlowDataContext dataContext)
{
ArgumentNullException.ThrowIfNull(dataContext, nameof(dataContext));
long businessId = dataContext.GetOrDefault<long>(TaskFlowDataNameConst.BusinessId);
BusinessType businessType = BusinessType.OceanShippingExport;
if (dataContext.TryGetValue(nameof(businessType), out object? value) && value != null)
{
if (value is string strValue)
businessType = Enum.Parse<BusinessType>(strValue);
else
businessType = (BusinessType)Convert.ChangeType(value, typeof(BusinessType));
}
TaskBaseTypeEnum taskType = TaskBaseTypeEnum.WAIT_SPACE_RELEASE;
if (dataContext.TryGetValue(nameof(taskType), out object? value2) && value2 != null)
{
if (value2 is string strValue)
taskType = Enum.Parse<TaskBaseTypeEnum>(strValue);
else
taskType = (TaskBaseTypeEnum)Convert.ChangeType(value2, typeof(TaskBaseTypeEnum));
}
await TriggerActionAsync(businessId, businessType, taskType);
}
/// <summary>
/// 触发任务执行动作
/// </summary>
/// <param name="businessId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="taskType">任务类型</param>
/// <returns></returns>
public async Task TriggerActionAsync(long businessId, BusinessType businessType, TaskBaseTypeEnum taskType)
{
var businessTask = await TenantDb.Queryable<BusinessTask>().Where(
x => x.BusinessId == businessId && x.BusinessType == businessType && x.TaskType == taskType).FirstAsync();
if (businessTask != null)
await TriggerActionAsync(businessTask);
}
/// <summary>
/// 执行放舱任务(任务台使用)
/// </summary>
public async Task SpaceReleaseTask(TaskFlowDataContext dataContext)
{
dataContext.Set("TypeName", "DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor.SpaceRelease.SpaceReleaseActionExecutor,DS.WMS.Core");
var businessId = dataContext.Get<long?>(TaskFlowDataNameConst.BusinessId);
ArgumentNullException.ThrowIfNull(businessId, TaskFlowDataNameConst.BusinessId);
//await TriggerActionAsync(businessId.Value, BusinessType.OceanShippingExport, TaskBaseTypeEnum.WAIT_SPACE_RELEASE);
var businessTask = await TenantDb.Queryable<BusinessTask>().Where(
x => x.BusinessId == businessId && x.BusinessType == BusinessType.OceanShippingExport && x.TaskType == TaskBaseTypeEnum.WAIT_SPACE_RELEASE).FirstAsync();
dataContext.Set(TaskFlowDataNameConst.BusinessTask, businessTask);
await ExecuteAsync(dataContext);
//var service = ServiceProvider.GetRequiredService<ISeaExportTaskService>();
//await service.CreateSubTaskAsync(businessTask);
}
/// <summary>
/// 触发任务执行动作
/// </summary>
/// <param name="businessTask">任务信息</param>
/// <param name="includeOrder">是否包含订单数据</param>
/// <param name="additionalData">附加参数</param>
/// <returns></returns>
public async Task TriggerActionAsync(BusinessTask businessTask, bool includeOrder = false, IDictionary<string, object>? additionalData = null)
{
ArgumentNullException.ThrowIfNull(businessTask, nameof(businessTask));
TaskFlowDataContext dataContext = new(
(TaskFlowDataNameConst.BusinessTask, businessTask)
);
if (includeOrder)
{
var biz = GetBusinessDataAsync(businessTask.BusinessId, businessTask.BusinessType);
dataContext[TaskFlowDataNameConst.Business] = biz;
}
if (additionalData != null)
{
foreach (var item in additionalData)
dataContext[item.Key] = item.Value;
}
TaskFlowRuner taskFlow = new(TenantDb, ServiceProvider);
await taskFlow.RunWithBsno(businessTask.TaskType, businessTask.BusinessId, dataContext);
}
/// <summary>
/// 自动订舱
/// </summary>
/// <param name="businessId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <returns></returns>
public async Task<DataResult> AutomaticBooking(long businessId, BusinessType businessType)
{
try
{
var businessTask = await TenantDb.Queryable<BusinessTask>().Where(
x => x.BusinessId == businessId && x.BusinessType == businessType && x.TaskType == TaskBaseTypeEnum.WAIT_BOOKING).FirstAsync();
if (businessTask == null)
return DataResult.FailedWithDesc(MultiLanguageConst.BookingTaskNotFound);
TaskFlowDataContext dataContext = new
(
(TaskFlowDataNameConst.BusinessTask, businessTask),
("TypeName", typeof(BookingSelector).AssemblyQualifiedName)
);
await ExecuteAsync(dataContext);
return DataResult.Success;
}
catch (Exception ex)
{
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(MultiLanguageConst.Operation_Failed);
}
}
/// <summary>
/// 执行动作
/// </summary>
/// <param name="dataContext"></param>
/// <returns></returns>
public async Task ExecuteAsync(TaskFlowDataContext dataContext)
{
ArgumentNullException.ThrowIfNull(dataContext, nameof(dataContext));
var context = new ActionExecutionContext
{
ActionManager = this,
TaskInfo = dataContext.GetOrDefault<BusinessTask>(TaskFlowDataNameConst.BusinessTask),
ServiceProvider = ServiceProvider
};
foreach (var key in dataContext.Keys)
context.AdditionalData[key] = dataContext[key];
var typeName = dataContext.GetOrDefault<string>("TypeName");
if (typeName.IsNullOrEmpty())
return;
Type? t = Type.GetType(typeName, true, false);
if (t == null)
{
await new ApplicationException($"未能获取类型【{typeName}】的信息,请检查配置").LogAsync(Db);
return;
}
IActionExecutor? currentExecutor = null;
object instance = ConstructorExtensions.CreateInstance(t);
if (instance is IActionSelector selector)
{
currentExecutor = await selector.GetActionExecutor(context);
}
else if (instance is IActionExecutor executor)
{
currentExecutor = executor;
}
if (currentExecutor == null)
{
await new ApplicationException($"未能创建类型【{t.AssemblyQualifiedName}】的实例").LogAsync(Db);
return;
}
var logService = context.ServiceProvider.GetRequiredService<ITaskLogService>();
await logService.WriteLogAsync(context.TaskInfo, $"开始运行后台任务({currentExecutor.GetType().FullName}...");
await currentExecutor.ExecuteAsync(context);
}
}
}