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.

1416 lines
62 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 System.Text;
using DS.Module.Core;
using DS.Module.Core.Data;
using DS.Module.Core.Helpers;
using DS.Module.DjyRulesEngine;
using DS.Module.DjyServiceStatus;
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.Flow.Entity;
using DS.WMS.Core.Flow.Interface;
using DS.WMS.Core.Flow.Method;
using DS.WMS.Core.Info.Interface;
using DS.WMS.Core.Invoice.Dtos;
using DS.WMS.Core.Op.Dtos;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Op.Interface;
using DS.WMS.Core.Sys.Entity;
using DS.WMS.Core.TaskInteraction.Dtos;
using DS.WMS.Core.TaskInteraction.Entity;
using DS.WMS.Core.TaskInteraction.Interface;
using DS.WMS.Core.TaskInteraction.Method.ActionSelector;
using DS.WMS.Core.TaskPlat;
using DS.WMS.Core.TaskPlat.Dtos;
using DS.WMS.Core.TaskPlat.Entity;
using DS.WMS.Core.TaskPlat.Interface;
using Mapster;
using Masuit.Tools;
using Masuit.Tools.Systems;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
namespace DS.WMS.Core.TaskInteraction.Method
{
/// <summary>
/// 任务交互服务
/// </summary>
public class TaskService : ServiceBase, ITaskService, IAuditTaskService
{
const long PERMISSION_ID = 1815294400855674880;
/// <summary>
/// 获取支持审核的任务类型
/// </summary>
public static readonly TaskBaseTypeEnum[] AuditTaskTypes;
/// <summary>
/// 通过任务台创建,而非通过工作流创建的任务类型,需手动调用函数来创建驳回任务,且重新提交时不创建工作流
/// </summary>
static readonly TaskBaseTypeEnum[] AuditTaskTypesManualReject;
static TaskService()
{
var dic = typeof(TaskBaseTypeEnum).GetDictionary();
var enumValues = dic.Where(x => x.Key != -1).GroupBy(x => Math.Abs(x.Key)).Select(x => new
{
Value = x.Key,
Count = x.Count()
}).Where(x => x.Count > 1);
AuditTaskTypesManualReject = [TaskBaseTypeEnum.WAIT_SI];
// 这里把非工作流创建任务类型排除一下,防止虽然需要审核但是不需要创建工作流的任务创建工作流
AuditTaskTypes = enumValues.Select(x => (TaskBaseTypeEnum)Math.Abs(x.Value)).Distinct().Except(AuditTaskTypesManualReject).ToArray();
}
/// <summary>
/// 确定任务类型是否为业务订单任务
/// </summary>
/// <param name="taskType">任务类型</param>
/// <returns></returns>
public static bool IsOrderType(TaskBaseTypeEnum taskType)
{
int val = (int)taskType;
return val >= 200 && val <= 399;
}
/// <summary>
/// 返回审核任务类型所对应的驳回类型
/// </summary>
/// <param name="auditTaskType">审核任务类型</param>
/// <returns></returns>
public static TaskBaseTypeEnum? GetRejectedType(TaskBaseTypeEnum auditTaskType)
{
if (!AuditTaskTypes.Contains(auditTaskType))
return null;
int negativeVal = -(int)auditTaskType;
return (TaskBaseTypeEnum)negativeVal;
}
/// <summary>
/// 任务管理服务
/// </summary>
protected ITaskManageService ManagerService { get; private set; }
/// <summary>
/// 日志服务
/// </summary>
protected ITaskLogService LogService { get; private set; }
/// <summary>
/// 任务分配
/// </summary>
protected Lazy<ITaskAllocationService> TaskAllocationService { get; private set; }
/// <summary>
/// 工作流服务
/// </summary>
protected Lazy<IClientFlowInstanceService> FlowService { get; private set; }
/// <summary>
/// 动作服务
/// </summary>
protected IActionManagerService ActionService { get; private set; }
readonly Lazy<IClientParamService> ClientParamService;
/// <summary>
/// 规则库服务
/// </summary>
protected Lazy<IRuleEngineService> RuleEngineService { get; private set; }
/// <summary>
/// 海运出口公共服务
/// </summary>
protected Lazy<ISeaExportCommonService> seaComService { get; private set; }
/// <summary>
/// 大简云服务状态服务
/// </summary>
protected Lazy<IDjyServiceStatusService> djyStatusService { get; private set; }
/// <summary>
/// 初始化
/// </summary>
/// <param name="provider"></param>
public TaskService(IServiceProvider provider) : base(provider)
{
ManagerService = provider.GetRequiredService<ITaskManageService>();
LogService = provider.GetRequiredService<ITaskLogService>();
ActionService = provider.GetRequiredService<IActionManagerService>();
TaskAllocationService = new Lazy<ITaskAllocationService>(provider.GetRequiredService<ITaskAllocationService>());
ClientParamService = new Lazy<IClientParamService>(provider.GetRequiredService<IClientParamService>());
FlowService = new Lazy<IClientFlowInstanceService>(provider.GetRequiredService<IClientFlowInstanceService>());
RuleEngineService = new Lazy<IRuleEngineService>(provider.GetRequiredService<IRuleEngineService>());
seaComService = new Lazy<ISeaExportCommonService>(provider.GetRequiredService<ISeaExportCommonService>());
djyStatusService = new Lazy<IDjyServiceStatusService>(provider.GetRequiredService<IDjyServiceStatusService>());
TenantDb.QueryFilter.Clear<IOrgId>();
}
/// <summary>
/// 批量创建关联任务
/// </summary>
/// <param name="request"></param>
/// <param name="useTransaction">是否使用事务</param>
/// <returns></returns>
public virtual async Task<DataResult> CreateMultipleTaskAsync(TaskCreationRequest request, bool useTransaction = true)
{
var ids = request.Ids;
ids ??= [request.BusinessId];
List<string> strList = [];
DataResult result;
for (int i = 0; i < ids.Length; i++)
{
request.BusinessId = ids[i];
result = await CreateTaskAsync(request, useTransaction);
if (!result.Succeeded)
{
if (result.Data == null)
return result;
strList.Add(result.Data.ToString()!);
}
}
if (strList.Count == 0)
return DataResult.Success;
return DataResult.Failed(string.Format(
MultiLanguageConst.GetDescription(MultiLanguageConst.OrderTaskSubmitted), string.Join("、", strList)));
}
/// <summary>
/// 创建关联任务
/// </summary>
/// <param name="request"></param>
/// <param name="useTransaction">是否使用事务</param>
/// <returns></returns>
public virtual async Task<DataResult> CreateTaskAsync(TaskCreationRequest request, bool useTransaction = true)
{
if (!await HasAuthorizedAsync())
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ModuleUnauthorized));
//检查步骤类型是否重复
if (request.Steps?.Count > 0)
{
if (request.Steps.Where(x => x.Type != StepType.NotSpecified).GroupBy(x => x.Type).Select(x => x.Key).Count() > 1)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DuplicateStepType));
if (request.Steps.Any(x => x.Type == StepType.NotSpecified && string.IsNullOrEmpty(x.Name)))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TypeOrName));
}
if (request.HasCabin.GetValueOrDefault() && request.BusinessType.HasValue)
{
//如果为现舱,获取下一任务类型进行创建
var nextType = await GetNextTypeAsync(request.BusinessId, request.BusinessType.Value, request.TaskType, request.HasCabin);
if (nextType.HasValue)
request.TaskTypeName = nextType.Value.ToString();
}
DataResult result = DataResult.Success;
bool updateFlag = false;
var task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).FirstAsync();
if (task != null)
{
//可审核任务类型允许挂起或取消的任务重新提交
if (AuditTaskTypes.Contains(request.TaskType) && (task.TaskStatus == TaskStatusEnum.Pending || task.TaskStatus == TaskStatusEnum.Cancel))
{
updateFlag = true;
}
else //其他任务类型返回已存在提示
{
if (IsOrderType(request.TaskType))
{
string custNO = await TenantDb.Queryable<SeaExport>().Where(x => x.Id == request.BusinessId)
.Select(x => x.CustomerNo).FirstAsync();
result = DataResult.Failed(string.Format(
MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.OrderTaskSubmitted)) + request.TaskType.GetDescription(), custNO));
result.Data = custNO;
return result;
}
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskExists));
}
}
if (request.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT)
{
result = await CheckRulesAsync(request.BusinessId, request.BusinessType.Value, RuleEngineType.COMMON_ORDER_AUDIT);
if (!result.Succeeded)
return result;
}
long userId = long.Parse(User.UserId);
DateTime dtNow = DateTime.Now;
if (useTransaction)
await TenantDb.Ado.BeginTranAsync();
try
{
TaskManageOrderMessageInfo? info = null;
if (task == null)
{
info = await CreateMessageAsync(request);
if ((request.RecvUserIdList == null || request.RecvUserIdList.Length == 0) && IsOrderType(request.TaskType))
{
//根据配置获取默认接收人
info.Main.RecvUserInfoList = await GetRecvUsersAsync(request.BusinessId, request.BusinessType, request.TaskType);
}
else if (AuditTaskTypes.Contains(request.TaskType))
{
//审核任务默认为提交人,生成工作流后替换为工作流执行人
info.Main.RecvUserInfoList = await FillInUserInfoAsync(long.Parse(User.UserId));
}
else
{
info.Main.RecvUserInfoList = await FillInUserInfoAsync(request.RecvUserIdList);
}
result = await ManagerService.InitTaskJob(info);
if (!result.Succeeded)
return result;
task = new BusinessTask
{
ParentId = request.ParentId,
BusinessId = request.BusinessId,
BusinessType = request.BusinessType,
ParentBusinessId = request.ParentBusinessId,
TaskType = request.TaskType,
TaskStatus = TaskStatusEnum.Create,
RecvUsers = string.Join(',', info.Main.RecvUserInfoList.Select(x => x.RecvUserId)) ?? string.Empty,
NextType = request.NextType,
CreateBy = userId,
CreateTime = dtNow
};
if (IsOrderType(request.TaskType) && !task.NextType.HasValue)
task.NextType = await GetNextTypeAsync(task);
await TenantDb.Insertable(task).ExecuteCommandAsync();
if (request.Steps?.Count > 0)
{
var steps = request.Steps.Select(x => new TaskStep
{
TaskId = task.Id,
IsCompleted = x.IsCompleted,
Name = x.Name,
Type = x.Type,
Priority = x.Priority ?? request.Steps.IndexOf(x),
CreateBy = userId,
CreateTime = dtNow
}).ToList();
await TenantDb.Insertable(steps).ExecuteCommandAsync();
}
result = await OnTaskCreated(task);
if (!result.Succeeded)
return result;
//记录日志
await LogService.WriteLogAsync(task);
}
//审核任务需创建工作流
if (AuditTaskTypes.Contains(request.TaskType))
{
result = await CreateAndStartWorkflow(task);
if (!result.Succeeded)
return result;
if (updateFlag)
{
result = await SetTaskStatusAsync(new TaskUpdateRequest
{
BusinessId = request.BusinessId,
BusinessType = request.BusinessType,
TaskTypeName = request.TaskTypeName,
TaskStatus = TaskStatusEnum.Create
}, false);
if (!result.Succeeded)
return result;
}
}
if (useTransaction)
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
if (useTransaction)
await TenantDb.Ado.RollbackTranAsync();
if (result.Data is FlowInstance instance)
await Db.Deleteable(instance).ExecuteCommandAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <summary>
/// 创建并启动审批工作流
/// </summary>
/// <param name="task"></param>
/// <param name="changeMarker">同时变更任务执行人</param>
/// <returns></returns>
protected async Task<DataResult> CreateAndStartWorkflow(BusinessTask task, bool changeMarker = true)
{
var template = await FindTemplateAsync(task.TaskType);
if (template == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TemplateNotFound));
var result = FlowService.Value.CreateFlowInstance(new CreateFlowInstanceReq
{
BusinessId = task.BusinessId,
BusinessType = task.BusinessType,
TemplateId = template.Id
});
//创建并启动实例
if (result.Succeeded)
{
var instance = result.Data as FlowInstance;
task.FlowId = instance!.Id;
await TenantDb.Updateable(task).UpdateColumns(x => x.FlowId).ExecuteCommandAsync();
if (instance.FlowStatus == FlowStatusEnum.Approve)
{
await SetTaskStatusAsync(new TaskUpdateRequest
{
BusinessId = task.BusinessId,
BusinessType = task.BusinessType,
RejectReason = instance.Note,
TaskTypeName = task.TaskType.ToString(),
TaskStatus = TaskStatusEnum.Complete
}, false);
}
else
{
result = FlowService.Value.StartFlowInstance(instance.Id.ToString());
instance = result.Data as FlowInstance;
if (result.Succeeded && changeMarker)
{
string[] ids = FlowInstanceService.GetMarkers(instance);
//变更任务接收人为所有审批执行人
var users = await FillInUserInfoAsync(ids.Select(long.Parse).ToArray());
result = await ManagerService.TransferTask(task.BusinessId, task.TaskType, users, TenantDb);
if (result.Succeeded)
{
task.RecvUsers = string.Join(",", ids);
await TenantDb.Updateable(task).UpdateColumns(x => x.RecvUsers).ExecuteCommandAsync();
}
}
}
result.Data = instance;
}
return result;
}
/// <summary>
/// 当任务创建时调用
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
protected virtual Task<DataResult> OnTaskCreated(BusinessTask task)
{
return Task.FromResult(DataResult.Success);
}
/// <summary>
/// 设置任务状态
/// </summary>
/// <param name="request"></param>
/// <param name="useTransaction">是否使用事务</param>
/// <returns></returns>
public virtual async Task<DataResult> SetTaskStatusAsync(TaskUpdateRequest request, bool useTransaction = true)
{
if (!await HasAuthorizedAsync())
return DataResult.FailedWithDesc(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.ModuleUnauthorized)));
if (useTransaction)
await TenantDb.Ado.BeginTranAsync();
try
{
BusinessTask task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).FirstAsync();
if (task == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskNotExists));
if (task.TaskStatus == TaskStatusEnum.Complete)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
if (request.TaskStatus == TaskStatusEnum.Complete && await TenantDb.Queryable<BusinessTask>().AnyAsync(x => x.ParentId == task.Id && x.TaskStatus != request.TaskStatus))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.UnfinishedItems));
//检查是否有未完成的任务步骤
var steps = await TenantDb.Queryable<TaskStep>().Where(x => x.TaskId == task.Id && !x.IsCompleted)
.Select(x => new { x.Type, x.Name }).ToListAsync();
if (steps.Count > 0)
return DataResult.Failed(
MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.UnfinishedItems)) + "" + string.Join("|", steps.Select(x => x.Type == StepType.NotSpecified ? x.Name : x.Type.GetDescription())),
nameof(MultiLanguageConst.UnfinishedItems));
//触发任务状态变更通知
if (task.TaskStatus != request.TaskStatus)
await OnTaskStatusChanged(request);
task.UpdateBy = long.Parse(User.UserId);
task.UpdateTime = DateTime.Now;
task.RejectReason = request.RejectReason;
//更新当前任务状态
task.TaskStatus = request.TaskStatus;
await TenantDb.Updateable(task).UpdateColumns(x => new
{
x.TaskStatus,
x.RejectReason,
x.UpdateBy,
x.UpdateTime
}).ExecuteCommandAsync();
DataResult result;
if (request.ParentId.HasValue || request.ParentBusinessId.HasValue) //设置子任务状态
{
var parentTask = await TenantDb.Queryable<BusinessTask>().Where(x => x.BusinessType == request.BusinessType)
.WhereIF(request.ParentId.HasValue, x => x.Id == request.ParentId)
.WhereIF(request.ParentBusinessId.HasValue, x => x.BusinessId == request.ParentBusinessId && x.TaskType == request.ParentTaskType)
.Select(x => new
{
x.BusinessId,
x.TaskType
}).FirstAsync();
if (parentTask == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.MainTaskNotFound));
result = await ManagerService.SetTaskStatusWithBsno(
parentTask.BusinessId, parentTask.TaskType,
request.TaskStatus, DateTime.Now, false, request.TaskDesc,
childBsno: request.BusinessId,
childTaskBaseTypeEnum: request.TaskType);
}
else
{
result = await ManagerService.SetTaskStatusWithBsno(request.BusinessId, request.TaskType, request.TaskStatus, DateTime.Now, false, request.TaskDesc);
}
if (!result.Succeeded)
return DataResult.Failed(result.Message, result.MultiCode);
if (task.TaskStatus == TaskStatusEnum.Complete && task.NextType.HasValue && request.AutoCreateNext)
{
//存在下一任务,则继续创建
var req = new TaskCreationRequest
{
BusinessId = request.BusinessId,
BusinessType = request.BusinessType,
TaskTypeName = task.NextType.Value.ToString()
};
result = await CreateTaskAsync(req, false);
if (!result.Succeeded)
return DataResult.Failed("创建下一关联任务时返回错误:" + result.Message, result.MultiCode);
}
//记录日志
await LogService.WriteLogAsync(request);
if (useTransaction)
await TenantDb.Ado.CommitTranAsync();
if (task.TaskStatus == TaskStatusEnum.Complete && IsOrderType(request.TaskType))//目前限制任务完成才触发
{
Dictionary<string, object>? dic = null;
if (task.NextType == TaskBaseTypeEnum.WAIT_BOOKING)
{
dic = [];
var param = await ClientParamService.Value.GetParamAsync<string>(task.BusinessId, BookingSelector.Booking_Route,
(x, y) => x.CustomerId == y.ForwarderId);
dic[TaskFlowDataNameConst.ClientParam] = param;
}
await ActionService.TriggerActionAsync(task, additionalData: dic);
}
return DataResult.Success;
}
catch (Exception ex)
{
if (useTransaction)
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <summary>
/// 设置任务步骤状态
/// </summary>
/// <param name="request"></param>
/// <param name="useTransaction">是否使用事务</param>
/// <returns></returns>
public virtual async Task<DataResult> SetStepsAsync(TaskRequest request, bool useTransaction = true)
{
if (!await HasAuthorizedAsync())
return DataResult.FailedWithDesc(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.ModuleUnauthorized)));
if (request.Steps == null || request.Steps.Count == 0)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.SubTaskCannotNull));
BusinessTask task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).FirstAsync();
if (task == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskNotExists));
if (task.TaskStatus == TaskStatusEnum.Complete)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
if (useTransaction)
await TenantDb.Ado.BeginTranAsync();
try
{
var allSteps = await TenantDb.Queryable<TaskStep>().Where(x => x.TaskId == task.Id && !x.IsCompleted).OrderBy(x => x.Priority)
.Select(x => new TaskStep
{
Id = x.Id,
Type = x.Type,
Name = x.Name,
IsCompleted = x.IsCompleted,
Priority = x.Priority
}).ToListAsync();
if (allSteps.Count == 0)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
//获取未完成的优先级最高的步骤
var topSteps = allSteps.GroupBy(x => x.Priority).OrderBy(x => x.Key).FirstOrDefault();
List<TaskStep> steps = [];
long userId = long.Parse(User.UserId);
DateTime dtNow = DateTime.Now;
foreach (var item in allSteps)
{
var reqStep = item.Id == 0 ?
request.Steps.Find(x => x.Type == item.Type || (x.Type == StepType.NotSpecified && x.Name == item.Name)) :
request.Steps.Find(x => x.Id == item.Id);
if (reqStep == null)
continue;
if (topSteps.Any(x => x.Priority > item.Priority))
return DataResult.Failed(
MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.HigherUnfinishedItems)) + "" + string.Join("|", topSteps.Select(x => x.Type == StepType.NotSpecified ? x.Name : x.Type.GetDescription())),
nameof(MultiLanguageConst.HigherUnfinishedItems));
item.SetValue(reqStep.Value);
item.IsCompleted = reqStep.IsCompleted;
item.UpdateBy = userId;
item.UpdateTime = dtNow;
steps.Add(item);
}
await TenantDb.Updateable(steps).UpdateColumns(x => new
{
x.Value,
x.IsCompleted,
x.UpdateBy,
x.UpdateTime
}).ExecuteCommandAsync();
if (request.AutoSync && allSteps.Count == allSteps.Count(x => x.IsCompleted))
{
DataResult result = await SetTaskStatusAsync(new TaskUpdateRequest
{
ParentId = request.ParentId,
BusinessId = request.BusinessId,
BusinessType = request.BusinessType,
TaskTypeName = request.TaskTypeName,
TaskStatus = TaskStatusEnum.Complete
}, false);
if (!result.Succeeded)
return result;
}
if (useTransaction)
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
if (useTransaction)
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <summary>
/// 当任务状态发生变化时调用
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
protected virtual Task OnTaskStatusChanged(TaskUpdateRequest request)
{
return Task.CompletedTask;
}
/// <summary>
/// 获取任务信息
/// </summary>
/// <param name="bsId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="withSubTask">是否获取子任务</param>
/// <param name="types">任务类型</param>
/// <returns></returns>
public async Task<DataResult<List<BusinessTask>>> GetTasks(long bsId, BusinessType? businessType, bool withSubTask, params TaskBaseTypeEnum[] types)
{
var list = await TenantDb.Queryable<BusinessTask>().Includes(x => x.Steps).Where(x => x.BusinessId == bsId)
.WhereIF(businessType.HasValue, x => x.BusinessType == businessType)
.WhereIF(types != null && types.Length > 0, x => types.Contains(x.TaskType))
.ToListAsync();
if (list.Count > 0 && withSubTask)
{
var ids = list.Select(x => x.Id);
var list2 = await TenantDb.Queryable<BusinessTask>().Includes(x => x.Steps)
.Where(x => x.ParentId.HasValue && ids.Contains(x.ParentId.Value)).ToListAsync();
foreach (var item in list)
item.SubTasks = list2.FindAll(x => x.ParentId == item.Id);
}
var result = DataResult<List<BusinessTask>>.Success(list);
result.Count = list.Count;
return result;
}
/// <summary>
/// 返回指定类型的任务是否已存在
/// </summary>
/// <param name="bsId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="type">任务类型</param>
/// <returns></returns>
public async Task<DataResult<bool>> ExistsAsync(long bsId, BusinessType businessType, TaskBaseTypeEnum type)
{
var value = await TenantDb.Queryable<BusinessTask>().AnyAsync(x =>
x.BusinessId == bsId && x.BusinessType == businessType && x.TaskType == type);
return DataResult<bool>.Success(value);
}
/// <summary>
/// 返回任务交互模块是否已授权
/// </summary>
/// <returns></returns>
public async Task<bool> HasAuthorizedAsync()
{
long tid = long.Parse(User.TenantId);
var authStr = await Db.Queryable<SysTenantPermissionAuth>().ClearFilter(typeof(ITenantId)).Where(x => x.PermissionId == PERMISSION_ID && x.TenantId == tid &&
SqlFunc.Subqueryable<SysPermissionTenant>().Where(spt => spt.PermissionId == x.PermissionId && x.TenantId == tid).Any())
.Select(x => x.AuthNum).FirstAsync();
if (authStr.IsNullOrEmpty())
return false;
var appSecret = await Db.Queryable<SysTenant>().Where(x => x.Id == tid).Select(x => x.AppSecret).FirstAsync();
return int.TryParse(EncrypteHelper.DecryptData(authStr, appSecret), out int authNum) && authNum > 0;
}
/// <summary>
/// 重新发起任务审核
/// </summary>
/// <param name="request"></param>
/// <param name="useTransaction">是否使用事务</param>
/// <returns></returns>
public virtual async Task<DataResult> SubmitAuditAsync(TaskRequest request, bool useTransaction = true)
{
var task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).FirstAsync();
if (task == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
if (task.TaskStatus == TaskStatusEnum.Complete)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
if (task.TaskStatus == TaskStatusEnum.Pending)
{
DataResult result;
if (task.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT)
{
result = await CheckRulesAsync(request.BusinessId, request.BusinessType.Value, RuleEngineType.COMMON_ORDER_AUDIT);
if (!result.Succeeded)
return result;
}
if (useTransaction)
await TenantDb.Ado.BeginTranAsync();
try
{
var req = new TaskUpdateRequest
{
AutoCreateNext = false,
BusinessId = request.BusinessId,
BusinessType = request.BusinessType,
TaskStatus = TaskStatusEnum.Create,
TaskTypeName = request.TaskTypeName
};
//重置任务为待处理
result = await SetTaskStatusAsync(req, false);
if (!result.Succeeded)
return DataResult.Failed(result.Message, result.MultiCode);
//创建&启动工作流
DataResult result2;
if (!AuditTaskTypesManualReject.Contains(request.TaskType))
{
result2 = await CreateAndStartWorkflow(task, false);
if (!result2.Succeeded)
return result2;
}
else
{
result2 = DataResult.Successed("操作成功", MultiLanguageConst.OperationSuccess);
}
await TenantDb.Updateable<BusinessTask>().SetColumns(x => x.TaskStatus == TaskStatusEnum.Create)
.Where(x => x.BusinessId == request.BusinessId && x.BusinessType == request.BusinessType && x.TaskType == request.TaskType)
.ExecuteCommandAsync();
//记录日志
await LogService.WriteLogAsync(req, "重新审批");
if (useTransaction)
await TenantDb.Ado.CommitTranAsync();
return result2;
}
catch (Exception ex)
{
if (useTransaction)
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskStatusNotSupported));
}
/// <summary>
/// 撤销审核任务
/// </summary>
/// <param name="request"></param>
/// <param name="useTransaction">是否使用事务</param>
/// <returns></returns>
public virtual async Task<DataResult> WithdrawAsync(TaskRequest request, bool useTransaction = true)
{
if (!AuditTaskTypes.Contains(request.TaskType))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskTypeNotSupported));
var task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).Select(x => new BusinessTask
{
Id = x.Id,
TaskStatus = x.TaskStatus,
FlowId = x.FlowId,
RecvUsers = x.RecvUsers
}).FirstAsync();
if (task == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
if (task.TaskStatus == TaskStatusEnum.Complete)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
if (!task.FlowId.HasValue)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NotInFlows));
DataResult result;
DateTime dt = DateTime.Now;
long userId = long.Parse(User.UserId);
if (useTransaction)
await TenantDb.Ado.BeginTranAsync();
try
{
result = await ManagerService.SetTaskStatusWithBsno(request.BusinessId, request.TaskType, TaskStatusEnum.Cancel, dt, false);
if (!result.Succeeded)
return result;
result = await FlowService.Value.WithdrawAsync([task.FlowId.Value], "用户撤销审核");
if (!result.Succeeded)
return result;
await TenantDb.Updateable<BusinessTask>().Where(x => x.Id == task.Id)
.SetColumns(x => x.TaskStatus == TaskStatusEnum.Cancel)
.SetColumns(x => x.UpdateBy == userId)
.SetColumns(x => x.UpdateTime == dt)
.ExecuteCommandAsync();
await LogService.WriteLogAsync(new BusinessTaskLog
{
ActionType = ActionType.StatusChanged,
AuditStatus = FlowStatusEnum.Draft,
BusinessId = request.BusinessId,
BusinessType = request.BusinessType,
CreateBy = userId,
CreateTime = dt,
TaskStatus = TaskStatusEnum.Cancel,
TaskType = request.TaskType
});
//海运出口撤销审单 更新状态等操作
if (request.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT)
{
//await TenantDb.Updateable<SeaExport>().SetColumns(x => x.BusinessStatusName == null)
//.Where(x => x.Id == request.BusinessId).ExecuteCommandAsync();
//删除提交货物状态
var goodsStatus = TenantDb.Queryable<BookingGoodsStatus>().First(x => x.StatusCode == "TIJIAO" && x.BusinessId == request.BusinessId);
if (goodsStatus != null)
await TenantDb.Deleteable(goodsStatus).ExecuteCommandAsync();
var order = TenantDb.Queryable<SeaExport>().Filter(null, true).First(x => x.Id == request.BusinessId);
var oldOrder = order.Adapt<SeaExport>();
order.BusinessStatusName = string.Empty;
order.BusinessStatus = string.Empty;
await TenantDb.Updateable(order).UpdateColumns(x => new
{
x.BusinessStatusName,
x.BusinessStatus
}).EnableDiffLogEvent().ExecuteCommandAsync();
// 记录日志
await seaComService.Value.SaveSeaExportLogAsync(new SeaExportSaveLog()
{
OperateType = "Update",
OldOrder = oldOrder,
NewOrder = order,
SourceCode = "WithdrawAsync",
SourceName = "撤销审单更新",
}, TenantDb);
//更新大简云货物状态
var pushModel = new EmbedServiceProjectStatusDto
{
businessId = request.BusinessId.ToString(),
SourceType = 1,
StatusCodes = new List<EmbedServiceProjectStatusDetailDto> {
new EmbedServiceProjectStatusDetailDto{
StatusCode = "TIJIAO"
}
}
};
await djyStatusService.Value.CancelServiceStatus(pushModel);
}
if (useTransaction)
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
if (useTransaction)
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <summary>
/// 任务审核
/// </summary>
/// <param name="request"></param>
public virtual async Task<DataResult> AuditAsync(TaskAuditRequest request)
{
var tasks = await TenantDb.Queryable<BusinessTask>().Where(x => x.TaskType == request.TaskType && request.Ids.Contains(x.BusinessId))
.WhereIF(request.BusinessType.HasValue, x => x.BusinessType == request.BusinessType.Value).ToListAsync();
if (tasks.Count == 0)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskNotExists));
if (tasks.Count != request.Ids.Length)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCountNotMatch));
if (tasks.Exists(x => x.TaskStatus == TaskStatusEnum.Complete))
{
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
}
else if (tasks.Exists(x => x.TaskStatus != TaskStatusEnum.Create && x.TaskStatus != TaskStatusEnum.Pending))
{
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskAuditStatusError));
}
if (tasks.Exists(x => !AuditTaskTypesManualReject.Contains(x.TaskType) && x.FlowId == null))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.FlowNotFound));
DataResult result = DataResult.Success;
await TenantDb.Ado.BeginTranAsync();
try
{
var flowIds = tasks.Where(x => !AuditTaskTypesManualReject.Contains(x.TaskType)).Select(x => x.FlowId.Value);
var flowInstances = await Db.Queryable<FlowInstance>().Where(x => flowIds.Contains(x.Id)).ToListAsync();
foreach (var instance in flowInstances)
{
//如果当前审批为终审,则调用规则库进行校验
if (request.Result == 1 && request.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT && instance.GetMarkerList().Length == 1)
{
result = await CheckRulesAsync(instance.BusinessId, request.BusinessType.GetValueOrDefault(), RuleEngineType.COMMON_OCEAN_BOOKING);
if (!result.Succeeded)
return result;
}
result = await FlowService.Value.AuditAsync(new FlowAuditInfo
{
AuditNote = request.Remark,
Status = request.Result,
Instance = instance
});
if (!result.Succeeded)
return result;
var req = new TaskUpdateRequest
{
BusinessId = instance.BusinessId,
BusinessType = instance.BusinessType,
RejectReason = request.Remark,
TaskTypeName = request.TaskType.ToString(),
TaskStatus = request.Result == 1 ? TaskStatusEnum.Complete : TaskStatusEnum.Pending,
AutoCreateNext = true
};
//根据审批结果更新任务状态
await SetTaskStatusAsync(req, false);
if (instance.FlowStatus == FlowStatusEnum.Reject)
result.Message = MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskRejected));
if (IsOrderType(request.TaskType))
result.Data = new { instance.IsCompleted, instance.FlowStatus };
}
if (request.Result == 2)
{
var manualRejectTask = tasks.Where(x => AuditTaskTypesManualReject.Contains(x.TaskType)).ToList();
foreach (var item in manualRejectTask)
{
// 驳回工作流创建的任务时会自动通过http创建驳回任务但是驳回非工作流创建的任务不会自动创建驳回任务所以在下面手动调用
var req = new TaskUpdateRequest
{
BusinessId = item.BusinessId,
BusinessType = request.BusinessType.GetValueOrDefault(),
RejectReason = request.Remark,
TaskTypeName = request.TaskType.ToString(),
TaskStatus = request.Result == 1 ? TaskStatusEnum.Complete : TaskStatusEnum.Pending,
AutoCreateNext = false
};
//根据审批结果更新任务状态
await SetTaskStatusAsync(req);
// 创建相应的驳回任务
await UpdateBusinessAsync(new FlowCallback()
{
AuditType = request.TaskType,
BusinessId = item.BusinessId,
BusinessType = request.BusinessType.GetValueOrDefault(),
FlowStatus = FlowStatusEnum.Reject,
InstanceId = 0,
RejectReason = request.Remark,
});
}
}
await TenantDb.Ado.CommitTranAsync();
return result;
}
catch (Exception ex)
{
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <summary>
/// 通知审批执行人变更
/// </summary>
/// <param name="callback">回调信息</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"><paramref name="callback"/>为null时引发</exception>
public virtual async Task MarkerChangedAsync(MarkerChangedCallback callback)
{
ArgumentNullException.ThrowIfNull(callback, nameof(callback));
long userId = long.Parse(User.UserId);
var users = await FillInUserInfoAsync(userId);
var dt = DateTime.Now;
await ManagerService.SetTaskUserStatus(
callback.BusinessId,
callback.AuditType.GetValueOrDefault(),
TaskStatusEnum.Complete,
//callback.Status == FlowStatusEnum.Approve ? TaskStatusEnum.Complete : TaskStatusEnum.Pending
dt,
users);
//记录日志
await LogService.WriteLogAsync(new BusinessTaskLog
{
ActionType = ActionType.Audit,
AuditStatus = callback.Status,
BusinessId = callback.BusinessId,
BusinessType = callback.BusinessType.Value,
CreateBy = userId,
CreateTime = dt,
TaskStatus = TaskStatusEnum.Complete,
TaskType = callback.AuditType.GetValueOrDefault(),
RecvUsers = users.Count > 0 ? users[0].RecvUserName : null
});
}
/// <summary>
/// 审批完成回调更新
/// </summary>
/// <param name="callback">回调信息</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"><paramref name="callback"/>为null时引发</exception>
public virtual async Task UpdateBusinessAsync(FlowCallback callback)
{
ArgumentNullException.ThrowIfNull(callback, nameof(callback));
if (callback.AuditType == null)
return;
string remark = "终审完成,审批结果为:" + callback.FlowStatus.GetDescription();
if (callback.FlowStatus == FlowStatusEnum.Reject)
{
var task = await GetQuery(callback.BusinessId, callback.BusinessType, callback.AuditType.Value).FirstAsync();
var request = new TaskCreationRequest
{
BusinessId = callback.BusinessId,
BusinessType = callback.BusinessType,
TaskTypeName = GetRejectedType(callback.AuditType.Value).ToString(),
RecvUserIdList = [task.CreateBy] //通知任务发起人
};
//创建驳回任务以进行通知
await CreateTaskAsync(request, false);
//更新任务描述为驳回原因
await SetTaskBaseDescription(callback.BusinessId, request.TaskType, callback.RejectReason!);
remark += ";驳回原因:" + callback.RejectReason;
}
long userId = long.Parse(User.UserId);
var users = await FillInUserInfoAsync(userId);
//记录日志
await LogService.WriteLogAsync(new BusinessTaskLog
{
ActionType = ActionType.Audit,
AuditStatus = callback.FlowStatus,
BusinessId = callback.BusinessId,
BusinessType = callback.BusinessType,
CreateBy = userId,
CreateTime = DateTime.Now,
TaskStatus = callback.FlowStatus == FlowStatusEnum.Approve ? TaskStatusEnum.Complete : TaskStatusEnum.Pending,
TaskType = callback.AuditType.GetValueOrDefault(),
RecvUsers = users.Count > 0 ? users[0].RecvUserName : null,
Remark = remark
});
}
/// <summary>
/// 创建任务台消息
/// </summary>
/// <param name="request">任务创建请求</param>
/// <returns>任务台消息</returns>
protected async Task<TaskManageOrderMessageInfo> CreateMessageAsync(TaskCreationRequest request)
{
var info = new TaskManageOrderMessageInfo
{
Head = new TaskManageOrderMessageHeadInfo
{
GID = Guid.NewGuid().ToString(),
BSNO = request.ParentBusinessId ?? request.BusinessId,
MessageType = "WORK_FLOW_TASK",
SenderId = "WorkFlow",
SenderName = "工作流平台",
ReceiverId = "TaskManage",
ReceiverName = "任务管理平台",
RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
IsChild = request.ParentBusinessId.HasValue,
ChildBSNO = request.ParentBusinessId.HasValue ? request.BusinessId : 0
},
Main = new TaskManageOrderMessageMainInfo
{
TaskType = request.ParentTaskType ?? request.TaskType,
TaskSource = TaskSourceEnum.WORK_FLOW,
TaskTitle = request.TaskTitle,
TaskDesp = request.TaskDescription,
TaskUserId = User.UserId,
TaskUserName = User.UserName,
TaskTenatId = long.Parse(User.TenantId),
TaskTenatName = User.TenantName,
IsCheckExistsByTaskType = true,
ChildTaskType = request.TaskType
}
};
//仅为业务订单任务自动填充任务标题/描述
if (info.Main.TaskTitle.IsNullOrEmpty() && IsOrderType(request.TaskType))
{
var biz = await TenantDb.Queryable<SeaExport>().Select(x => new
{
x.Id,
x.CustomerNo,
x.MBLNO,
x.Vessel,
x.Voyno,
x.ETD,
x.DischargePortId,
x.DischargePortCode,
x.DischargePort,
x.LoadPortId,
x.LoadPortCode,
x.LoadPort,
x.CarrierId,
x.Carrier,
//x.BookingNo,
//x.HBLNO,
//x.CustomerNum,
}).FirstAsync(x => x.Id == request.BusinessId);
info.Main.TaskTitle = $"【{request.TaskType.GetDescription()}】{biz?.CustomerNo} {biz?.Vessel} {biz?.Voyno} ETD:{biz?.ETD?.ToString("yyyy-MM-dd")}";
info.Main.CustomerNo = biz?.CustomerNo;
info.Main.MBlNo = biz?.MBLNO;
info.Main.ETD = biz?.ETD;
info.Main.PortDischarge = biz?.DischargePort;
info.Main.PortDischargeCode = biz?.DischargePortCode;
info.Main.PortDischargeId = biz?.DischargePortId;
info.Main.PortLoad = biz?.LoadPort;
info.Main.PortLoadId = biz?.LoadPortId;
info.Main.PortLoadCode = biz?.LoadPortCode;
info.Main.CarrierId = biz?.Carrier;
info.Main.CarrierPK = biz?.CarrierId;
//info.Main.HBLNO = biz?.HBLNO;
//info.Main.BookingNo = biz?.BookingNo;
//info.Main.CustomsNum = biz?.CustomerNum;
}
info.Main.TaskDesp = info.Main.TaskDesp ?? info.Main.TaskTitle;
return info;
}
async Task<DataResult> CheckRulesAsync(long bsId, BusinessType businessType, RuleEngineType ruleType)
{
var rulesReq = new RuleEngineReq();
var order = await TenantDb.Queryable<SeaExport>().Where(x => x.Id == bsId).FirstAsync();
rulesReq.Main.BusinessInfo = order.Adapt<RulesEngineOrderBookingMainBusinessInfo>();
rulesReq.Main.ProjectCode = [ruleType.ToString()];
var ruleResult = await RuleEngineService.Value.ExecuteSeaExportAuditRulesAsync(rulesReq);
if (string.Equals(ruleResult.Succ, bool.FalseString, StringComparison.OrdinalIgnoreCase))
{
return DataResult.Failed(ruleResult.Msg);
}
else if (ruleResult.Extra.DetailList?.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (var item in ruleResult?.Extra.DetailList)
sb.Append(item.ResultName);
return DataResult.Failed(sb.ToString());
}
return DataResult.Success;
}
/// <summary>
/// 获取给定任务的下一任务类型
/// </summary>
/// <param name="current">当前任务对象</param>
/// <returns></returns>
protected async Task<TaskBaseTypeEnum?> GetNextTypeAsync(BusinessTask current)
{
return await GetNextTypeAsync(current.BusinessId, current.BusinessType, current.TaskType);
}
/// <summary>
/// 获取给定任务的下一任务类型
/// </summary>
/// <param name="bsId">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="currentType">当前任务类型</param>
/// <param name="hasCabin">是否现舱</param>
/// <returns></returns>
protected async Task<TaskBaseTypeEnum?> GetNextTypeAsync(long bsId, BusinessType? businessType, TaskBaseTypeEnum currentType, bool? hasCabin = null)
{
object? order = null;
if (businessType.HasValue)
order = await ActionService.GetBusinessDataAsync(bsId, businessType.Value);
TaskFlowRuner flowRuner = new(TenantDb, ServiceProvider);
var dataContext = new TaskFlowDataContext(
(TaskFlowDataNameConst.Business, order),
(nameof(hasCabin), hasCabin.HasValue ? hasCabin.ToString() : string.Empty)
);
return await flowRuner.GetWorkFlowNextConfigByTaskType(TaskBaseTypeEnum.WORK_FLOW_MAIN, dataContext, currentType);
}
/// <summary>
/// 获取指定类型的业务关联任务
/// </summary>
/// <param name="id">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="taskTypes">任务类型</param>
/// <returns></returns>
protected internal ISugarQueryable<BusinessTask> GetQuery(long id, BusinessType? businessType, params TaskBaseTypeEnum[] taskTypes)
{
return TenantDb.Queryable<BusinessTask>().Where(x => x.BusinessId == id)
.WhereIF(businessType.HasValue, x => x.BusinessType == businessType)
.WhereIF(taskTypes != null && taskTypes.Length > 0, x => taskTypes.Contains(x.TaskType));
}
/// <summary>
/// 从任务配置中获取接收用户列表
/// </summary>
/// <param name="id">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="taskType">任务类型</param>
/// <returns></returns>
protected internal async Task<List<RecvUserInfo>> GetRecvUsersAsync(long id, BusinessType? businessType, TaskBaseTypeEnum taskType)
{
var dic = await GetRecvUsersAsync(id, businessType, [taskType]);
return dic?.Count > 0 ? dic.FirstOrDefault().Value : [];
}
/// <summary>
/// 从任务配置中获取接收用户列表
/// </summary>
/// <param name="id">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="taskTypes">任务类型</param>
/// <returns></returns>
protected internal async Task<Dictionary<TaskBaseTypeEnum, List<RecvUserInfo>>> GetRecvUsersAsync(long id, BusinessType? businessType, List<TaskBaseTypeEnum> taskTypes)
{
object? biz = null;
if (businessType.HasValue)
biz = await ActionService.GetBusinessDataAsync(id, businessType.Value);
var result = await TaskAllocationService.Value.GetAllotUserBySeaExportId(taskTypes, id, new TaskFlowDataContext(
(TaskFlowDataNameConst.Business, biz)
));
return result.Succeeded ? result.Data : [];
}
internal async Task<List<RecvUserInfo>> FillInUserInfoAsync(params long[] ids)
{
return await Db.Queryable<SysUser>().Where(x => ids.Contains(x.Id)).Select(
x => new RecvUserInfo { RecvUserId = x.Id, RecvUserName = x.UserName }).ToListAsync();
}
/// <summary>
/// 删除任务
/// </summary>
/// <param name="id">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="remark">备注</param>
/// <param name="taskTypes">任务类型,不指定任务类型则删除全部任务</param>
/// <returns></returns>
public async Task<DataResult> DeleteAsync(long id, BusinessType? businessType, string? remark = null, params TaskBaseTypeEnum[] taskTypes)
{
if (!await HasAuthorizedAsync())
return DataResult.SuccessedWithDesc(nameof(MultiLanguageConst.ModuleUnauthorized));
string[]? typeNames = taskTypes?.Select(x => x.ToString()).ToArray();
int rows = 0;
await TenantDb.Ado.BeginTranAsync();
try
{
rows = await Db.Deleteable<FlowInstance>().Where(x => x.BusinessId == id)
.WhereIF(businessType.HasValue, x => x.BusinessType == businessType)
.WhereIF(taskTypes != null && taskTypes.Length > 0, x => taskTypes.Contains(x.AuditType.Value))
.ExecuteCommandAsync();
rows += await TenantDb.Deleteable<TaskBaseAllocation>().Where(x => SqlFunc.Subqueryable<TaskBaseInfo>().Where(
y => x.TaskId == y.Id && y.TASK_SOURCE == "WORK_FLOW" && y.OUT_BS_NO == id)
.WhereIF(typeNames != null && typeNames.Length > 0, x => typeNames.Contains(x.TASK_TYPE))
.Any()).ExecuteCommandAsync();
rows += await TenantDb.Deleteable<TaskBaseInfo>().Where(x => x.TASK_SOURCE == "WORK_FLOW" && x.OUT_BS_NO == id)
.WhereIF(typeNames != null && typeNames.Length > 0, x => typeNames.Contains(x.TASK_TYPE))
.ExecuteCommandAsync();
rows += await TenantDb.Deleteable<TaskStep>().Where(x => SqlFunc.Subqueryable<BusinessTask>()
.Where(y => x.TaskId == y.BusinessId || x.TaskId == y.ParentBusinessId)
.WhereIF(businessType.HasValue, y => y.BusinessType == businessType)
.WhereIF(typeNames != null && typeNames.Length > 0, y => taskTypes.Contains(y.TaskType))
.Any()).ExecuteCommandAsync();
rows += await TenantDb.Deleteable<BusinessTask>().Where(x => x.BusinessId == id || x.ParentBusinessId == id)
.WhereIF(businessType.HasValue, x => x.BusinessType == businessType)
.WhereIF(typeNames != null && typeNames.Length > 0, x => taskTypes.Contains(x.TaskType))
.ExecuteCommandAsync();
if (string.IsNullOrEmpty(remark))
remark = "删除任务" + (typeNames != null && typeNames.Length > 0 ? $"【{string.Join(",", typeNames)}】,受影响行数:" + rows : string.Empty);
await LogService.WriteLogAsync(new BusinessTaskLog
{
BusinessId = id,
BusinessType = businessType,
ActionType = ActionType.Delete,
CreateBy = long.Parse(User.UserId),
CreateTime = DateTime.Now,
TaskType = TaskBaseTypeEnum.NOT_SPECIFIED,
Remark = remark
});
await TenantDb.Ado.CommitTranAsync();
return DataResult.Success;
}
catch (Exception ex)
{
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <summary>
/// 更新任务台描述
/// </summary>
/// <returns></returns>
/// <param name="id">业务ID</param>
/// <param name="taskType">任务类型</param>
/// <param name="description">描述信息</param>
public async Task SetTaskBaseDescription(long id, TaskBaseTypeEnum taskType, string description)
{
await ManagerService.SetTaskBaseInfoPropertyWithBsno(id, taskType, null, null, x => x.TASK_DESP == description);
}
}
/// <summary>
/// 校验规则类型
/// </summary>
public enum RuleEngineType
{
/// <summary>
/// 订单提交审核
/// </summary>
COMMON_ORDER_AUDIT,
/// <summary>
/// 订舱
/// </summary>
COMMON_OCEAN_BOOKING
}
}