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.

388 lines
16 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.Extensions;
using DS.Module.Core.Helpers;
using DS.WMS.Core.Fee.Method;
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.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.Sys.Entity;
using DS.WMS.Core.TaskPlat.Dtos;
using DS.WMS.Core.TaskPlat.Interface;
using Masuit.Tools.Systems;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
namespace DS.WMS.Core.Op.Method.TaskInteraction
{
/// <summary>
/// 任务交互服务
/// </summary>
public abstract class TaskService : FeeServiceBase, ITaskService
{
const long PERMISSION_ID = 1815294400855674880;
/// <summary>
/// 任务管理服务
/// </summary>
protected ITaskManageService ManagerService { get; private set; }
/// <summary>
/// 工作流服务
/// </summary>
protected Lazy<IClientFlowInstanceService> FlowService { get; private set; }
/// <summary>
/// 初始化
/// </summary>
/// <param name="provider"></param>
protected TaskService(IServiceProvider provider) : base(provider)
{
ManagerService = provider.GetRequiredService<ITaskManageService>();
FlowService = new Lazy<IClientFlowInstanceService>(provider.GetRequiredService<IClientFlowInstanceService>());
}
/// <summary>
/// 确保任务交互模块已授权
/// </summary>
/// <returns></returns>
protected virtual async Task<bool> EnsureModuleAuthorized()
{
//if (!await Db.Queryable<SysPermissionTenant>().AnyAsync(x => x.PermissionId == PERMISSION_ID))
// return false;
long tid = long.Parse(User.TenantId);
var authStr = await Db.Queryable<SysTenantPermissionAuth>().Where(x => x.PermissionId == PERMISSION_ID && x.TenantId == tid &&
SqlFunc.Subqueryable<SysPermissionTenant>().Where(spt => spt.PermissionId == x.PermissionId).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 async Task<DataResult> CreateTaskAsync(TaskCreationRequest request, bool useTransaction = true)
{
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));
long tenatId = long.Parse(User.TenantId);
string tenatName = Db.Queryable<SysTenant>().Where(x => x.Id == tenatId).Select(x => x.Name).First();
var info = new TaskManageOrderMessageInfo
{
Head = new TaskManageOrderMessageHeadInfo
{
GID = Guid.NewGuid().ToString(),
BSNO = request.BusinessId,
MessageType = "WORK_FLOW_TASK",
SenderId = "WorkFlow",
SenderName = "工作流平台",
ReceiverId = "TaskManage",
ReceiverName = "任务管理平台",
Version = "1.0",
RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
RequestAction = "Add"
},
Main = new TaskManageOrderMessageMainInfo
{
TaskType = request.TaskType,
TaskSource = TaskSourceEnum.WORK_FLOW,
TaskTitle = request.TaskTitle,
TaskDesp = request.TaskDescription,
TaskUserId = User.UserId,
TaskUserName = User.UserName,
TaskTenatId = tenatId,
TaskTenatName = tenatName
}
};
if (request.RecvUserIdList == null || request.RecvUserIdList.Length == 0)
{
info.Main.RecvUserInfoList = [new RecvUserInfo { RecvUserId = long.Parse(User.UserId), RecvUserName = User.UserName }];
}
else
{
info.Main.RecvUserInfoList = await GetRecvUsers(request.RecvUserIdList);
}
if (info.Main.TaskTitle.IsNullOrEmpty())
{
var biz = await TenantDb.Queryable<SeaExport>().Select(x => new
{
x.Id,
x.MBLNO,
x.Vessel,
x.Voyno,
x.ETD,
}).FirstAsync(x => x.Id == request.BusinessId);
info.Main.TaskDesp = info.Main.TaskTitle = $"{request.TaskType.GetDescription()} {biz.Vessel} {biz.Voyno} ETD:{biz.ETD?.ToString("yyyy-MM-dd")} BLNo:{biz.MBLNO}";
}
if (useTransaction)
await TenantDb.Ado.BeginTranAsync();
try
{
var result = await ManagerService.InitTaskJob(info);
if (!result.Succeeded)
return result;
task = new BusinessTask
{
BusinessId = request.BusinessId,
BusinessType = request.BusinessType,
TaskType = request.TaskType,
TaskStatus = TaskStatusEnum.Create,
RecvUsers = string.Join(',', info.Main.RecvUserInfoList.Select(x => x.RecvUserId)),
CreateBy = long.Parse(User.UserId),
CreateTime = DateTime.Now
};
task.NextType = GetNextType(task);
await TenantDb.Insertable(task).ExecuteCommandAsync();
//待审核,需创建工作流
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 OnTaskCreated(task);
if (!result.Succeeded)
return result;
if (useTransaction)
await TenantDb.Ado.CommitTranAsync();
return result;
}
catch (Exception ex)
{
if (useTransaction)
await TenantDb.Ado.RollbackTranAsync();
await ex.LogAsync(Db);
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
}
/// <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 async Task<DataResult> SetTaskStatusAsync(TaskUpdateRequest request, bool useTransaction = true)
{
if (!await EnsureModuleAuthorized())
return DataResult.SuccessedWithDesc(nameof(MultiLanguageConst.ModuleUnauthorized));
if (useTransaction)
await TenantDb.Ado.BeginTranAsync();
try
{
var result = await ManagerService.SetTaskStatus(request.BusinessId, request.TaskType, request.TaskStatus, DateTime.Now);
if (!result.Succeeded)
return result;
//更新当前任务状态
BusinessTask task = await GetTaskAsync(request.BusinessId, request.BusinessType, request.TaskType);
if (task == null)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
if (task.TaskStatus != request.TaskStatus)
await OnTaskStatusChanged(request);
task.TaskStatus = request.TaskStatus;
if (task.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT)
task.FlowId = null;
await TenantDb.Updateable(task).UpdateColumns(x => new { x.TaskStatus, x.FlowId }).ExecuteCommandAsync();
if (task.TaskStatus == TaskStatusEnum.Complete)
{
//若存在下一任务,则继续创建
if (task.NextType.HasValue && request.AutoCreateNext)
{
var req = new TaskCreationRequest
{
BusinessId = request.BusinessId,
BusinessType = request.BusinessType,
TaskType = task.NextType.Value,
RecvUserIdList = task.RecvUserIdArray,
};
await CreateTaskAsync(req, false);
}
}
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="callback">回调信息</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"><paramref name="callback"/>为null时引发</exception>
public virtual async Task UpdateReceiverAsync(MakerChangedCallback callback)
{
ArgumentNullException.ThrowIfNull(callback, nameof(callback));
}
/// <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));
//更新任务状态为完成
await SetTaskStatusAsync(new TaskUpdateRequest
{
BusinessId = callback.BusinessId,
BusinessType = callback.BusinessType.GetValueOrDefault(),
TaskType = TaskBaseTypeEnum.WAIT_ORDER_AUDIT,
TaskStatus = TaskStatusEnum.Complete
});
if (callback.FlowStatus == FlowStatusEnum.Reject)
{
//创建审单驳回任务以进行通知
var task = await GetTaskAsync(callback.BusinessId, callback.BusinessType.GetValueOrDefault(), TaskBaseTypeEnum.WAIT_ORDER_AUDIT);
await CreateTaskAsync(new TaskCreationRequest
{
BusinessId = callback.BusinessId,
BusinessType = callback.BusinessType.GetValueOrDefault(),
TaskType = TaskBaseTypeEnum.ORDER_AUDIT_REJECTED,
RecvUserIdList = task.RecvUserIdArray
});
}
}
/// <summary>
/// 获取指定类型的业务关联任务
/// </summary>
/// <param name="id">业务ID</param>
/// <param name="businessType">业务类型</param>
/// <param name="taskType">任务类型</param>
/// <returns></returns>
protected internal async Task<BusinessTask> GetTaskAsync(long id, BusinessType businessType, TaskBaseTypeEnum taskType)
{
return await TenantDb.Queryable<BusinessTask>().FirstAsync(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>
/// <param name="ids">用户ID</param>
/// <returns></returns>
protected internal async Task<List<RecvUserInfo>> GetRecvUsers(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();
}
}
}