|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
using DS.Module.Core;
|
|
|
|
|
using DS.Module.Core.Extensions;
|
|
|
|
|
using DS.Module.Core.Helpers;
|
|
|
|
|
using DS.WMS.Core.Fee.Dtos;
|
|
|
|
|
using DS.WMS.Core.Fee.Method;
|
|
|
|
|
using DS.WMS.Core.Flow.Dtos;
|
|
|
|
|
using DS.WMS.Core.Flow.Entity;
|
|
|
|
@ -46,11 +47,28 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
FlowService = new Lazy<IClientFlowInstanceService>(provider.GetRequiredService<IClientFlowInstanceService>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取给定任务的下一任务类型
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="current">任务信息</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
internal static TaskBaseTypeEnum? GetNextType(BusinessTask current)
|
|
|
|
|
{
|
|
|
|
|
if (current.TaskType == TaskBaseTypeEnum.WAIT_CHECKOUT_BILL) //流程的最后一步
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
int currentTypeVal = (int)current.TaskType;
|
|
|
|
|
if (currentTypeVal >= 300) //300开始的枚举值为可选服务项目,不存在前后关联性
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
return (TaskBaseTypeEnum)currentTypeVal++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 确保任务交互模块已授权
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
protected virtual async Task<bool> EnsureModuleAuthorized()
|
|
|
|
|
protected virtual async Task<bool> EnsureModuleAuthorized()
|
|
|
|
|
{
|
|
|
|
|
//if (!await Db.Queryable<SysPermissionTenant>().AnyAsync(x => x.PermissionId == PERMISSION_ID))
|
|
|
|
|
// return false;
|
|
|
|
@ -66,6 +84,53 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
return int.TryParse(EncrypteHelper.DecryptData(authStr, appSecret), out int authNum) && authNum > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 任务审核
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="request"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async virtual Task<DataResult> AuditAsync(AuditRequest request)
|
|
|
|
|
{
|
|
|
|
|
long id = request.Ids[0];
|
|
|
|
|
var task = await GetQuery(id, request.BusinessType.GetValueOrDefault(), TaskBaseTypeEnum.WAIT_ORDER_AUDIT).FirstAsync();
|
|
|
|
|
if (task == null)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
|
|
|
|
|
|
|
|
|
|
if (task.TaskStatus == TaskStatusEnum.Complete)
|
|
|
|
|
{
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted));
|
|
|
|
|
}
|
|
|
|
|
else if (task.TaskStatus == TaskStatusEnum.Pending) //二次审核
|
|
|
|
|
{
|
|
|
|
|
//重新创建工作流
|
|
|
|
|
var result = await Create_StartWorkflow(task);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
var flow = result.Data as FlowInstance;
|
|
|
|
|
//更新当前任务的工作流ID
|
|
|
|
|
task.FlowId = flow?.Id;
|
|
|
|
|
await TenantDb.Updateable(task).UpdateColumns(x => new { x.FlowId }).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
return FlowService.Value.AuditFlowInstance(new FlowAuditInfo
|
|
|
|
|
{
|
|
|
|
|
AuditNote = request.Remark,
|
|
|
|
|
Status = request.Result,
|
|
|
|
|
Instance = flow
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (task.FlowId == null)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.FlowNotFound));
|
|
|
|
|
|
|
|
|
|
return FlowService.Value.AuditFlowInstance(new FlowAuditInfo
|
|
|
|
|
{
|
|
|
|
|
AuditNote = request.Remark,
|
|
|
|
|
Status = request.Result,
|
|
|
|
|
Instance = await Db.Queryable<FlowInstance>().FirstAsync(x => x.Id == task.FlowId.Value)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 创建关联任务
|
|
|
|
|
/// </summary>
|
|
|
|
@ -77,9 +142,9 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
if (!await EnsureModuleAuthorized())
|
|
|
|
|
return DataResult.SuccessedWithDesc(nameof(MultiLanguageConst.ModuleUnauthorized));
|
|
|
|
|
|
|
|
|
|
var task = await GetTaskAsync(request.BusinessId, request.BusinessType, request.TaskType);
|
|
|
|
|
if (task != null)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Task_Exists));
|
|
|
|
|
var task = await GetQuery(request.BusinessId, request.BusinessType, request.TaskType).FirstAsync();
|
|
|
|
|
if (task != null && task.TaskStatus != TaskStatusEnum.Cancel)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskExists));
|
|
|
|
|
|
|
|
|
|
long tenatId = long.Parse(User.TenantId);
|
|
|
|
|
string tenatName = Db.Queryable<SysTenant>().Where(x => x.Id == tenatId).Select(x => x.Name).First();
|
|
|
|
@ -159,38 +224,9 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
//待审核,需创建工作流
|
|
|
|
|
if (task.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT)
|
|
|
|
|
{
|
|
|
|
|
var template = await FindTemplateAsync(AuditType.SeaExport);
|
|
|
|
|
if (template == null)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TemplateNotFound));
|
|
|
|
|
|
|
|
|
|
result = FlowService.Value.CreateFlowInstance(new CreateFlowInstanceReq
|
|
|
|
|
{
|
|
|
|
|
BusinessId = task.BusinessId,
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
|
|
result = FlowService.Value.StartFlowInstance(instance.Id.ToString());
|
|
|
|
|
//工作流为会签,需要更新任务接收人
|
|
|
|
|
if (result.Succeeded && instance.ActivityType == 0)
|
|
|
|
|
{
|
|
|
|
|
var marker = FlowInstanceService.GetNextMarker(instance);
|
|
|
|
|
await UpdateReceiverAsync(new MakerChangedCallback
|
|
|
|
|
{
|
|
|
|
|
BusinessId = request.BusinessId,
|
|
|
|
|
BusinessType = request.BusinessType,
|
|
|
|
|
InstanceId = instance.Id,
|
|
|
|
|
Type = instance.Type,
|
|
|
|
|
NextUserId = long.Parse(marker)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result = await Create_StartWorkflow(task);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = await OnTaskCreated(task);
|
|
|
|
@ -212,6 +248,50 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 创建并启动审批工作流
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="task"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
protected internal async Task<DataResult> Create_StartWorkflow(BusinessTask task)
|
|
|
|
|
{
|
|
|
|
|
var template = await FindTemplateAsync(AuditType.SeaExport);
|
|
|
|
|
if (template == null)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TemplateNotFound));
|
|
|
|
|
|
|
|
|
|
var result = FlowService.Value.CreateFlowInstance(new CreateFlowInstanceReq
|
|
|
|
|
{
|
|
|
|
|
BusinessId = task.BusinessId,
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
|
|
result = FlowService.Value.StartFlowInstance(instance.Id.ToString());
|
|
|
|
|
instance = result.Data as FlowInstance;
|
|
|
|
|
//工作流为会签,需要更新任务接收人
|
|
|
|
|
if (result.Succeeded && instance.ActivityType == 0)
|
|
|
|
|
{
|
|
|
|
|
var marker = FlowInstanceService.GetNextMarker(instance);
|
|
|
|
|
await UpdateReceiverAsync(new MakerChangedCallback
|
|
|
|
|
{
|
|
|
|
|
BusinessId = task.BusinessId,
|
|
|
|
|
BusinessType = task.BusinessType,
|
|
|
|
|
InstanceId = instance.Id,
|
|
|
|
|
Type = instance.Type,
|
|
|
|
|
NextUserId = long.Parse(marker)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 当任务创建时调用
|
|
|
|
|
/// </summary>
|
|
|
|
@ -242,14 +322,19 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
//更新当前任务状态
|
|
|
|
|
BusinessTask task = await GetTaskAsync(request.BusinessId, request.BusinessType, request.TaskType);
|
|
|
|
|
BusinessTask 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.Cancel)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCancelled));
|
|
|
|
|
|
|
|
|
|
//触发任务状态变更通知
|
|
|
|
|
if (task.TaskStatus != request.TaskStatus)
|
|
|
|
|
await OnTaskStatusChanged(request);
|
|
|
|
|
|
|
|
|
|
//更新当前任务状态
|
|
|
|
|
task.TaskStatus = request.TaskStatus;
|
|
|
|
|
if (task.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT)
|
|
|
|
|
task.FlowId = null;
|
|
|
|
@ -306,8 +391,24 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
public virtual async Task UpdateReceiverAsync(MakerChangedCallback callback)
|
|
|
|
|
{
|
|
|
|
|
ArgumentNullException.ThrowIfNull(callback, nameof(callback));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (callback.NextUserId == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var users = await GetRecvUsers(callback.NextUserId.Value);
|
|
|
|
|
var result = await ManagerService.TransferTask(callback.BusinessId, TaskBaseTypeEnum.WAIT_ORDER_AUDIT, users);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
//记录日志
|
|
|
|
|
await new ApplicationException("任务API调用失败:" + result.Message).LogAsync(Db);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string recvUser = callback.NextUserId.Value.ToString();
|
|
|
|
|
await TenantDb.Updateable<BusinessTask>().Where(x => x.BusinessId == callback.BusinessId &&
|
|
|
|
|
x.BusinessType == callback.BusinessType && x.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT)
|
|
|
|
|
.SetColumns(x => x.RecvUsers == recvUser)
|
|
|
|
|
.ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -320,25 +421,26 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
{
|
|
|
|
|
ArgumentNullException.ThrowIfNull(callback, nameof(callback));
|
|
|
|
|
|
|
|
|
|
//更新任务状态为完成
|
|
|
|
|
//根据审批结果更新任务状态
|
|
|
|
|
await SetTaskStatusAsync(new TaskUpdateRequest
|
|
|
|
|
{
|
|
|
|
|
BusinessId = callback.BusinessId,
|
|
|
|
|
BusinessType = callback.BusinessType.GetValueOrDefault(),
|
|
|
|
|
TaskType = TaskBaseTypeEnum.WAIT_ORDER_AUDIT,
|
|
|
|
|
TaskStatus = TaskStatusEnum.Complete
|
|
|
|
|
TaskStatus = callback.FlowStatus == FlowStatusEnum.Approve ? TaskStatusEnum.Complete : TaskStatusEnum.Pending,
|
|
|
|
|
AutoCreateNext = callback.FlowStatus == FlowStatusEnum.Approve
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (callback.FlowStatus == FlowStatusEnum.Reject)
|
|
|
|
|
{
|
|
|
|
|
//创建审单驳回任务以进行通知
|
|
|
|
|
var task = await GetTaskAsync(callback.BusinessId, callback.BusinessType.GetValueOrDefault(), TaskBaseTypeEnum.WAIT_ORDER_AUDIT);
|
|
|
|
|
var task = await GetQuery(callback.BusinessId, callback.BusinessType.GetValueOrDefault(), TaskBaseTypeEnum.WAIT_ORDER_AUDIT).FirstAsync();
|
|
|
|
|
await CreateTaskAsync(new TaskCreationRequest
|
|
|
|
|
{
|
|
|
|
|
BusinessId = callback.BusinessId,
|
|
|
|
|
BusinessType = callback.BusinessType.GetValueOrDefault(),
|
|
|
|
|
TaskType = TaskBaseTypeEnum.ORDER_AUDIT_REJECTED,
|
|
|
|
|
RecvUserIdList = task.RecvUserIdArray
|
|
|
|
|
RecvUserIdList = [task.CreateBy] //通知任务发起人
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -350,29 +452,12 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction
|
|
|
|
|
/// <param name="businessType">业务类型</param>
|
|
|
|
|
/// <param name="taskType">任务类型</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
protected internal async Task<BusinessTask> GetTaskAsync(long id, BusinessType businessType, TaskBaseTypeEnum taskType)
|
|
|
|
|
protected internal ISugarQueryable<BusinessTask> GetQuery(long id, BusinessType businessType, TaskBaseTypeEnum taskType)
|
|
|
|
|
{
|
|
|
|
|
return await TenantDb.Queryable<BusinessTask>().FirstAsync(x =>
|
|
|
|
|
return TenantDb.Queryable<BusinessTask>().Where(x =>
|
|
|
|
|
x.BusinessId == id && x.BusinessType == businessType && x.TaskType == taskType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取给定任务的下一任务类型
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="current">任务信息</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static TaskBaseTypeEnum? GetNextType(BusinessTask current)
|
|
|
|
|
{
|
|
|
|
|
if (current.TaskType == TaskBaseTypeEnum.WAIT_CHECKOUT_BILL) //流程的最后一步
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
int currentTypeVal = (int)current.TaskType;
|
|
|
|
|
if (currentTypeVal >= 300) //300开始的枚举值为可选服务项目,不存在前后关联性
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
return (TaskBaseTypeEnum)currentTypeVal++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取任务接收用户列表
|
|
|
|
|
/// </summary>
|
|
|
|
|