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.Entity; using Fasterflect; using LanguageExt.Pipes; using Masuit.Tools; using Masuit.Tools.Systems; 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 bool IsMatch(object source, ConditionContent condition) { if (source == null || condition == null) return false; TaskFlowDataContext dataContext = new((TaskFlowDataNameConst.Business, source)); if (condition.SourceName.IsNullOrEmpty()) condition.SourceName = TaskFlowDataNameConst.Business; return ConditionHelper.IsPass(condition, dataContext); } /// /// 根据指定条件返回是否匹配的结果 /// /// 业务ID /// 业务类型 /// 匹配条件 /// public async Task IsMatchAsync(long bsId, BusinessType businessType, IEnumerable conditions) { ArgumentNullException.ThrowIfNull(conditions, nameof(conditions)); var biz = await GetBusinessDataAsync(bsId, businessType, conditions); if (biz != null) { TaskFlowDataContext dataContext = new((TaskFlowDataNameConst.Business, biz)); //循环匹配 foreach (var item in conditions) { if (ConditionHelper.IsPass(item, dataContext)) 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().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") .Where("Id=@Id", new { Id = businessId }).Select(selectors).FirstAsync(); } break; case BusinessType.OceanShippingImport: break; } return biz; } /// /// 执行放舱任务(任务台使用) /// 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(TaskFlowDataNameConst.BusinessId); ArgumentNullException.ThrowIfNull(businessId, TaskFlowDataNameConst.BusinessId); //await TriggerActionAsync(businessId.Value, BusinessType.OceanShippingExport, TaskBaseTypeEnum.WAIT_SPACE_RELEASE); var businessTask = await TenantDb.Queryable().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(); //await service.CreateSubTaskAsync(businessTask); } /// /// 触发任务执行动作 /// /// 任务信息 /// 是否包含订单数据 /// 附加参数 /// public async Task TriggerActionAsync(BusinessTask businessTask, bool includeOrder = false, IDictionary? additionalData = null) { ArgumentNullException.ThrowIfNull(businessTask, nameof(businessTask)); if (businessTask.BusinessType == null) return DataResult.Success; TaskFlowDataContext dataContext = new( (TaskFlowDataNameConst.BusinessTask, businessTask) ); var paramList = await GetTaskParamsAsync(businessTask.TaskType); var gpList = paramList.GroupBy(x => x.FieldName).Select(x => new { FieldName = x.Key, Values = x.Select(y => y.FieldValue) }).ToList(); foreach (var g in gpList) { if (g.FieldName == TaskFlowDataNameConst.TypeName) { dataContext[g.FieldName] = g.Values; } else { if (g.Values.Count() == 1) dataContext[g.FieldName] = g.Values.FirstOrDefault(); else dataContext[g.FieldName] = g.Values; } } if (additionalData != null) { foreach (var item in additionalData) dataContext[item.Key] = item.Value; } if (!dataContext.TryGetValue(TaskFlowDataNameConst.TypeName, out object value)) return DataResult.Success; if (includeOrder) { var biz = GetBusinessDataAsync(businessTask.BusinessId, businessTask.BusinessType.Value); dataContext[TaskFlowDataNameConst.Business] = biz; } try { IEnumerable? typeNames = value as IEnumerable; string typeStr = typeNames == null ? value.ToString() : string.Join(",", typeNames); await logService.WriteLogAsync(businessTask, $"开始运行【{businessTask.TaskType.GetDescription()}】动作:{typeStr} ..."); await ExecuteAsync(dataContext); await logService.WriteLogAsync(businessTask, $"【{businessTask.TaskType.GetDescription()}】动作:{typeStr} 运行结束"); return DataResult.Success; } catch (Exception ex) { await logService.WriteLogAsync(businessTask, $"执行【{businessTask.TaskType.GetDescription()}】动作时出错:{ex.Message}" + Environment.NewLine + "调用堆栈:" + ex.StackTrace); return DataResult.FailedWithDesc(MultiLanguageConst.Operation_Failed); } } /// /// 自动订舱 /// /// 业务ID /// 业务类型 /// public async Task AutomaticBooking(long businessId, BusinessType businessType) { var businessTask = await TenantDb.Queryable().Where( x => x.BusinessId == businessId && x.BusinessType == businessType && x.TaskType == TaskBaseTypeEnum.WAIT_BOOKING).FirstAsync(); if (businessTask == null) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.BookingTaskNotFound)); var dic = new Dictionary { [TaskFlowDataNameConst.TypeName] = new string[1] { typeof(BookingSelector).AssemblyQualifiedName } }; return await TriggerActionAsync(businessTask, false, dic); } /// /// 获取指定任务类型的参数 /// /// 任务类型 /// internal async Task> GetTaskParamsAsync(TaskBaseTypeEnum taskType) { return await TenantDb.Queryable() .InnerJoin((p, c) => p.ConfigId == c.Id) .InnerJoin((p, c, m) => c.ExecuteModuleId == m.Id) .Where((p, c, m) => m.TaskType == taskType.ToString() && m.ModuleType == 2).ToListAsync(); } /// /// 执行动作 /// /// /// 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]; if (!dataContext.TryGetValue(TaskFlowDataNameConst.TypeName, out object typeNameObj) || typeNameObj == null) return; IEnumerable typeNames = typeNameObj as IEnumerable; typeNames ??= [typeNameObj.ToString()]; if (typeNames.IsNullOrEmpty()) return; foreach (var typeName in typeNames) { 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; } await currentExecutor.ExecuteAsync(context); } } } }