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 { /// /// 动作执行管理 /// public class ActionManagerService : ServiceBase, IActionManagerService { ITaskLogService logService; /// /// 初始化 /// public ActionManagerService(IServiceProvider serviceProvider) : base(serviceProvider) { logService = serviceProvider.GetRequiredService(); TenantDb.QueryFilter.Clear(); } /// /// 根据指定条件返回是否匹配的结果 /// /// 任务请求 /// 匹配条件 /// public async Task IsMatchAsync(TaskRequest request, IEnumerable 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; } /// /// 获取所需业务数据 /// /// 业务ID /// 业务类型 /// 条件字段 /// public async Task GetBusinessDataAsync(long businessId, BusinessType businessType, IEnumerable conditions) { ArgumentNullException.ThrowIfNull(conditions, nameof(conditions)); HashSet 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()); } /// /// 获取所需业务数据 /// /// 业务ID /// 业务类型 /// 返回字段列表 /// public async Task 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().ClearFilter(typeof(IOrgId)).Where(a => a.Id == businessId) .Select().Mapper(it => { it.DischargePortCountry = TenantDb.Queryable().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().AS("op_sea_export").ClearFilter(typeof(IOrgId)) .Where("Id=@Id", new { Id = businessId }).Select(selectors).FirstAsync(); } break; case BusinessType.OceanShippingImport: break; } return biz; } /// /// 触发任务执行动作 /// /// /// public async Task TriggerActionAsync(TaskFlowDataContext dataContext) { ArgumentNullException.ThrowIfNull(dataContext, nameof(dataContext)); long businessId = dataContext.GetOrDefault(nameof(businessId)); BusinessType businessType = BusinessType.OceanShippingExport; if (dataContext.TryGetValue(nameof(businessType), out object? value) && value != null) { if (value is string strValue) businessType = Enum.Parse(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(strValue); else taskType = (TaskBaseTypeEnum)Convert.ChangeType(value2, typeof(TaskBaseTypeEnum)); } await TriggerActionAsync(businessId, businessType, taskType); } /// /// 触发任务执行动作 /// /// 业务ID /// 业务类型 /// 任务类型 /// public async Task TriggerActionAsync(long businessId, BusinessType businessType, TaskBaseTypeEnum taskType) { var businessTask = await TenantDb.Queryable().Where( x => x.BusinessId == businessId && x.BusinessType == businessType && x.TaskType == taskType).FirstAsync(); if (businessTask != null) await TriggerActionAsync(businessTask); } /// /// 触发任务执行动作 /// /// 任务信息 /// 是否包含订单数据 /// public async Task TriggerActionAsync(BusinessTask businessTask, bool includeOrder = false) { ArgumentNullException.ThrowIfNull(businessTask, nameof(businessTask)); ////目前只限制任务完成才触发 //if (businessTask.TaskStatus != TaskStatusEnum.Complete) // return; TaskFlowDataContext dataContext = new( (TaskFlowDataNameConst.BusinessTask, businessTask) ); if (includeOrder) { var biz = GetBusinessDataAsync(businessTask.BusinessId, businessTask.BusinessType); dataContext[TaskFlowDataNameConst.Business] = biz; } TaskFlowRuner taskFlow = new(TenantDb, ServiceProvider); await taskFlow.RunWithBsno(businessTask.TaskType, businessTask.BusinessId, dataContext); } /// /// 执行动作 /// /// /// public async Task ExecuteAsync(TaskFlowDataContext dataContext) { ArgumentNullException.ThrowIfNull(dataContext, nameof(dataContext)); var context = new ActionExecutionContext { ActionManager = this, TaskInfo = dataContext.GetOrDefault(TaskFlowDataNameConst.BusinessTask), ServiceProvider = ServiceProvider }; foreach (var key in dataContext.Keys) context.AdditionalData[key] = dataContext[key]; var typeName = dataContext.GetOrDefault("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(); await logService.WriteLogAsync(context.TaskInfo, $"开始运行后台任务({currentExecutor.GetType().FullName})..."); await currentExecutor.ExecuteAsync(context); } public async Task TriggerTestAsync(TaskBaseTypeEnum taskType, long? id) { var task = await TenantDb.Queryable() .Where(t => t.TaskType == taskType //&& SqlFunc.Subqueryable().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; } } }