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.

289 lines
12 KiB
C#

4 months ago
using DS.Module.Core;
4 months ago
using DS.Module.Core.Condition;
4 months ago
using DS.Module.Core.Data;
using DS.WMS.Core.Code.Entity;
using DS.WMS.Core.Op.Dtos;
using DS.WMS.Core.Op.Dtos.TaskInteraction;
4 months ago
using DS.WMS.Core.Op.Entity;
4 months ago
using DS.WMS.Core.Op.Entity.TaskInteraction;
using DS.WMS.Core.Op.Interface.TaskInteraction;
using DS.WMS.Core.TaskPlat;
using Fasterflect;
4 months ago
using Masuit.Tools;
using Microsoft.Extensions.DependencyInjection;
4 months ago
using SqlSugar;
4 months ago
namespace DS.WMS.Core.Op.Method.TaskInteraction
{
/// <summary>
/// 动作执行管理
/// </summary>
public class ActionManagerService : ServiceBase, IActionManagerService
4 months ago
{
ITaskLogService logService;
4 months ago
4 months ago
/// <summary>
/// 初始化
/// </summary>
public ActionManagerService(IServiceProvider serviceProvider) : base(serviceProvider)
4 months ago
{
logService = serviceProvider.GetRequiredService<ITaskLogService>();
TenantDb.QueryFilter.Clear<IOrgId>();
4 months ago
}
/// <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);
4 months ago
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());
4 months ago
}
/// <summary>
/// 获取所需业务数据
/// </summary>
/// <param name="businessId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="fields">返回字段列表</param>
/// <returns></returns>
4 months ago
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>().ClearFilter(typeof(IOrgId)).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").ClearFilter(typeof(IOrgId))
.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>(nameof(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);
}
4 months ago
/// <summary>
/// 触发任务执行动作
/// </summary>
/// <param name="businessTask">任务信息</param>
/// <param name="includeOrder">是否包含订单数据</param>
4 months ago
/// <returns></returns>
public async Task TriggerActionAsync(BusinessTask businessTask, bool includeOrder = false)
4 months ago
{
ArgumentNullException.ThrowIfNull(businessTask, nameof(businessTask));
////目前只限制任务完成才触发
//if (businessTask.TaskStatus != TaskStatusEnum.Complete)
// return;
4 months ago
TaskFlowDataContext dataContext = new(
4 months ago
(TaskFlowDataNameConst.BusinessTask, businessTask)
4 months ago
);
if (includeOrder)
{
var biz = GetBusinessDataAsync(businessTask.BusinessId, businessTask.BusinessType);
dataContext[TaskFlowDataNameConst.Business] = biz;
}
4 months ago
TaskFlowRuner taskFlow = new(TenantDb, ServiceProvider);
await taskFlow.RunWithBsno(businessTask.TaskType, businessTask.BusinessId, dataContext);
4 months ago
}
4 months ago
/// <summary>
/// 执行动作
/// </summary>
/// <param name="dataContext"></param>
/// <returns></returns>
4 months ago
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];
4 months ago
var typeName = dataContext.GetOrDefault<string>("TypeName");
if (typeName.IsNullOrEmpty())
return;
4 months ago
Type? t = Type.GetType(typeName, true, false);
if (t == null)
{
await new ApplicationException($"未能获取类型【{typeName}】的信息,请检查配置").LogAsync(Db);
return;
}
4 months ago
IActionExecutor? currentExecutor = null;
object instance = ConstructorExtensions.CreateInstance(t);
if (instance is IActionSelector selector)
{
4 months ago
currentExecutor = await selector.GetActionExecutor(context);
}
else if (instance is IActionExecutor executor)
4 months ago
{
currentExecutor = executor;
}
4 months ago
if (currentExecutor == null)
{
4 months ago
await new ApplicationException($"未能创建类型【{t.AssemblyQualifiedName}】的实例").LogAsync(Db);
return;
}
4 months ago
var logService = context.ServiceProvider.GetRequiredService<ITaskLogService>();
await logService.WriteLogAsync(context.TaskInfo, $"开始运行后台任务({currentExecutor.GetType().FullName}...");
await currentExecutor.ExecuteAsync(context);
4 months ago
}
public async Task<DataResult> TriggerTestAsync(TaskBaseTypeEnum taskType, long? id)
{
var task = await TenantDb.Queryable<BusinessTask>()
.Where(t => t.TaskType == taskType
//&& SqlFunc.Subqueryable<SeaExport>().Where(s => t.BusinessId == s.Id && s.BillSubmitStatus == AuditStatusEnum.Approve).Any()
)
//.Where(x => x.TaskStatus == TaskStatusEnum.Complete)
.WhereIF(id.HasValue, x => x.BusinessId == id)
.OrderByDescending(t => SqlFunc.GetRandom()).Take(1).FirstAsync();
if (task != null)
{
TaskFlowDataContext dataContext = new(
(TaskFlowDataNameConst.BusinessTask, task)
);
TaskFlowRuner taskFlow = new(TenantDb, ServiceProvider);
await taskFlow.RunWithBsno(task.TaskType, task.BusinessId, dataContext);
return DataResult.Success;
}
var result = DataResult.Failed("找不到指定类型的任务");
result.Data = 404;
return result;
}
4 months ago
}
}