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.

258 lines
9.7 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.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>().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="businessTask">任务信息</param>
/// <returns></returns>
public async Task TriggerActionAsync(BusinessTask businessTask)
{
ArgumentNullException.ThrowIfNull(businessTask, nameof(businessTask));
//目前只限制任务完成才触发
if (businessTask.TaskStatus != TaskStatusEnum.Complete)
return;
//var biz = GetBusinessDataAsync(businessTask.BusinessId, businessTask.BusinessType);
// 执行自动化操作
TaskFlowDataContext dataContext = new(
(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));
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);
}
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;
}
}
/// <summary>
/// 任务执行类型
/// </summary>
public enum TaskActionType
{
/// <summary>
/// 后台任务
/// </summary>
Background,
/// <summary>
/// 邮件
/// </summary>
Email,
/// <summary>
/// EDI
/// </summary>
EDI,
}
}