diff --git a/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs b/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs index 945166ed..4c891c57 100644 --- a/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs +++ b/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs @@ -1443,6 +1443,10 @@ public static class MultiLanguageConst public const string TaskCompleted = "Task_Completed"; [Description("此任务已取消")] public const string TaskCancelled = "Task_Cancelled"; + [Description("当前任务状态不支持此操作")] + public const string TaskStatusNotSupported = "Task_Status_Not_Supported"; + [Description("当前任务状态不正确,无法提交审核")] + public const string TaskAuditStatusError = "Task_Audit_Status_Error"; #endregion #region 任务台相关 diff --git a/ds-wms-service/DS.WMS.Core/Flow/Dtos/MakerChangedCallback.cs b/ds-wms-service/DS.WMS.Core/Flow/Dtos/MakerChangedCallback.cs index 8463fec3..5e2e8b1c 100644 --- a/ds-wms-service/DS.WMS.Core/Flow/Dtos/MakerChangedCallback.cs +++ b/ds-wms-service/DS.WMS.Core/Flow/Dtos/MakerChangedCallback.cs @@ -29,8 +29,8 @@ namespace DS.WMS.Core.Flow.Dtos public AuditType? Type { get; set; } /// - /// 下一执行人的用户ID + /// 变更执行人的用户ID /// - public long? NextUserId { get; set; } + public long[] NextUserId { get; set; } = []; } } diff --git a/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs b/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs index e755d0ab..1e63b372 100644 --- a/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs +++ b/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs @@ -361,11 +361,11 @@ public class FlowInstanceService : IFlowInstanceService instance.MakerList = GetForkNodeMakers(runtime, runtime.CurrentNodeId); } - string marker = GetNextMarker(instance); + var markers = GetNextMarkers(instance); //获取会签下一执行人,进行通知 - if (!marker.IsNullOrEmpty() && marker != "-1" && !instance.MakerNotifyURL.IsNullOrEmpty()) + if (markers?.Length > 0 && !instance.MakerNotifyURL.IsNullOrEmpty()) { - Task.Factory.StartNew(() => NotifyMakerChangedAsync(instance, long.Parse(marker))); + Task.Factory.StartNew(() => NotifyMakerChangedAsync(instance, markers.Select(long.Parse).ToArray())); } } @@ -430,23 +430,25 @@ public class FlowInstanceService : IFlowInstanceService } /// - /// 获取会签下一执行人 + /// 获取工作流的所有执行人;当工作流类型为会签时,仅返回首个执行人 /// /// 运行实例 /// - public static string GetNextMarker(FlowInstance instance) + public static string[] GetNextMarkers(FlowInstance instance) { - //if (instance.ActivityType != 0) - // return string.Empty; - if (instance.MakerList.IsNullOrEmpty() || instance.MakerList == "-1") - return instance.MakerList; + return []; string[] markers = instance.MakerList.Split(',', StringSplitOptions.RemoveEmptyEntries); - if (markers.Length > 0 && long.TryParse(markers[0], out long nextUserId)) - return nextUserId.ToString(); + if (instance.ActivityType == 0 && markers.Length > 0) + { + //if (markers.Length > 0 && long.TryParse(markers[0], out long nextUserId)) + // return nextUserId.ToString(); + + return [markers[0]]; + } - return instance.MakerList; + return markers; } /// @@ -455,7 +457,7 @@ public class FlowInstanceService : IFlowInstanceService /// 运行实例 /// 下一执行人ID /// - protected virtual async Task NotifyMakerChangedAsync(FlowInstance instance, long nextUserId) + protected virtual async Task NotifyMakerChangedAsync(FlowInstance instance, long[] nextUserId) { //请求参数设置 var callback = new MakerChangedCallback diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskCreationRequest.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskCreationRequest.cs index 722a5b41..2a01e03f 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskCreationRequest.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskCreationRequest.cs @@ -1,28 +1,10 @@ -using DS.Module.Core; -using DS.WMS.Core.Op.Entity; - -namespace DS.WMS.Core.Op.Dtos.TaskInteraction +namespace DS.WMS.Core.Op.Dtos.TaskInteraction { /// /// 任务台创建参数 /// - public class TaskCreationRequest + public class TaskCreationRequest : TaskRequest { - /// - /// 业务ID - /// - public long BusinessId { get; set; } - - /// - /// 业务类型 - /// - public BusinessType BusinessType { get; set; } - - /// - /// 任务类型 - /// - public TaskBaseTypeEnum TaskType { get; set; } - /// /// 任务标题 /// diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskRequest.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskRequest.cs new file mode 100644 index 00000000..23211e27 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskRequest.cs @@ -0,0 +1,26 @@ +using DS.Module.Core; +using DS.WMS.Core.Op.Entity; + +namespace DS.WMS.Core.Op.Dtos.TaskInteraction +{ + /// + /// 任务请求基类 + /// + public class TaskRequest + { + /// + /// 业务ID + /// + public long BusinessId { get; set; } + + /// + /// 业务类型 + /// + public BusinessType BusinessType { get; set; } + + /// + /// 任务类型 + /// + public TaskBaseTypeEnum TaskType { get; set; } + } +} diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskUpdateRequest.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskUpdateRequest.cs index d3d1b634..745e2bab 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskUpdateRequest.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/TaskInteraction/TaskUpdateRequest.cs @@ -1,28 +1,12 @@ using DS.Module.Core; -using DS.WMS.Core.Op.Entity; namespace DS.WMS.Core.Op.Dtos.TaskInteraction { /// /// 任务台状态更新参数 /// - public class TaskUpdateRequest + public class TaskUpdateRequest : TaskRequest { - /// - /// 业务ID - /// - public long BusinessId { get; set; } - - /// - /// 业务类型 - /// - public BusinessType BusinessType { get; set; } - - /// - /// 任务类型 - /// - public TaskBaseTypeEnum TaskType { get; set; } - /// /// 任务状态 /// diff --git a/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/ITaskService.cs b/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/ITaskService.cs index 09e1e6da..8a486b9e 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/ITaskService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/ITaskService.cs @@ -1,4 +1,5 @@ using DS.Module.Core; +using DS.WMS.Core.Fee.Dtos; using DS.WMS.Core.Flow.Dtos; using DS.WMS.Core.Op.Dtos.TaskInteraction; @@ -25,11 +26,32 @@ namespace DS.WMS.Core.Op.Interface.TaskInteraction /// Task SetTaskStatusAsync(TaskUpdateRequest request, bool useTransaction = true); + /// + /// 发起任务审核 + /// + /// + /// + Task SubmitAuditAsync(TaskRequest request); + + /// + /// 任务审核 + /// + /// + /// + Task AuditAsync(AuditRequest request); + /// /// 审批完成回调更新 /// /// 回调信息 /// Task UpdateBusinessAsync(FlowCallback callback); + + /// + /// 通知更新任务接收人 + /// + /// 回调信息 + /// + Task UpdateReceiverAsync(MakerChangedCallback callback); } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/SeaExportTaskService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/SeaExportTaskService.cs index a1eb9422..71e07a04 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/SeaExportTaskService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/SeaExportTaskService.cs @@ -30,6 +30,36 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction djyService = new Lazy(provider.GetRequiredService()); } + /// + /// 更新海运出口提单号 + /// + /// 业务ID + /// 提单号 + /// + public async Task UpdateBLNO(long id, string blNO) + { + await TenantDb.Ado.BeginTranAsync(); + try + { + await TenantDb.Updateable().SetColumns(x => x.MBLNO == blNO).Where(x => x.Id == id).ExecuteCommandAsync(); + await CreateTaskAsync(new TaskCreationRequest + { + BusinessId = id, + BusinessType = BusinessType.OceanShippingExport, + TaskType = TaskBaseTypeEnum.WAIT_BILL_CONFIRM + }, false); + + 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)); + } + } + /// /// 创建关联子任务 /// diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs index 32683e96..7a20fb22 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs @@ -61,14 +61,14 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction if (currentTypeVal >= 300) //300开始的枚举值为可选服务项目,不存在前后关联性 return null; - return (TaskBaseTypeEnum)currentTypeVal++; + return (TaskBaseTypeEnum)(currentTypeVal + 1); } /// /// 确保任务交互模块已授权 /// /// - protected virtual async Task EnsureModuleAuthorized() + protected virtual async Task EnsureModuleAuthorized() { //if (!await Db.Queryable().AnyAsync(x => x.PermissionId == PERMISSION_ID)) // return false; @@ -85,39 +85,59 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction } /// - /// 任务审核 + /// 发起任务审核 /// /// /// - public async virtual Task AuditAsync(AuditRequest request) + public async Task SubmitAuditAsync(TaskRequest request) { - long id = request.Ids[0]; - var task = await GetQuery(id, request.BusinessType.GetValueOrDefault(), TaskBaseTypeEnum.WAIT_ORDER_AUDIT).FirstAsync(); + var task = await GetQuery(request.BusinessId, request.BusinessType, 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) //二次审核 + + if (task.TaskStatus == TaskStatusEnum.Pending || task.TaskStatus == TaskStatusEnum.Create) { - //重新创建工作流 + //创建&启动工作流 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 + if (task.TaskStatus != TaskStatusEnum.Create) { - AuditNote = request.Remark, - Status = request.Result, - Instance = flow - }); + await TenantDb.Updateable().SetColumns(x => x.TaskStatus == TaskStatusEnum.Create) + .Where(x => x.BusinessId == request.BusinessId && + x.BusinessType == request.BusinessType && x.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT) + .ExecuteCommandAsync(); + } + + return result; + } + + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskStatusNotSupported)); + } + + /// + /// 任务审核 + /// + /// + /// + public async Task AuditAsync(AuditRequest request) + { + long id = request.Ids[0]; + var task = await GetQuery(id, request.BusinessType.Value, 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.Create && task.TaskStatus != TaskStatusEnum.Pending) + { + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskAuditStatusError)); } if (task.FlowId == null) @@ -253,7 +273,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction /// /// /// - protected internal async Task Create_StartWorkflow(BusinessTask task) + protected internal async Task Create_StartWorkflow(BusinessTask task) { var template = await FindTemplateAsync(AuditType.SeaExport); if (template == null) @@ -274,17 +294,18 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction result = FlowService.Value.StartFlowInstance(instance.Id.ToString()); instance = result.Data as FlowInstance; - //工作流为会签,需要更新任务接收人 - if (result.Succeeded && instance.ActivityType == 0) + + if (result.Succeeded) { - var marker = FlowInstanceService.GetNextMarker(instance); + string[] ids = FlowInstanceService.GetNextMarkers(instance); + //变更任务接收人为审批执行人 await UpdateReceiverAsync(new MakerChangedCallback { BusinessId = task.BusinessId, BusinessType = task.BusinessType, InstanceId = instance.Id, Type = instance.Type, - NextUserId = long.Parse(marker) + NextUserId = ids.Select(long.Parse).ToArray() }); } } @@ -395,16 +416,15 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction if (callback.NextUserId == null) return; - var users = await GetRecvUsers(callback.NextUserId.Value); + var users = await GetRecvUsers(callback.NextUserId); var result = await ManagerService.TransferTask(callback.BusinessId, TaskBaseTypeEnum.WAIT_ORDER_AUDIT, users); if (!result.Succeeded) { - //记录日志 - await new ApplicationException("任务API调用失败:" + result.Message).LogAsync(Db); + await new ApplicationException($"任务API({nameof(ManagerService.TransferTask)})调用失败:" + result.Message).LogAsync(Db); return; } - string recvUser = callback.NextUserId.Value.ToString(); + string recvUser = string.Join(',', callback.NextUserId); await TenantDb.Updateable().Where(x => x.BusinessId == callback.BusinessId && x.BusinessType == callback.BusinessType && x.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT) .SetColumns(x => x.RecvUsers == recvUser) @@ -425,7 +445,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction await SetTaskStatusAsync(new TaskUpdateRequest { BusinessId = callback.BusinessId, - BusinessType = callback.BusinessType.GetValueOrDefault(), + BusinessType = callback.BusinessType.Value, TaskType = TaskBaseTypeEnum.WAIT_ORDER_AUDIT, TaskStatus = callback.FlowStatus == FlowStatusEnum.Approve ? TaskStatusEnum.Complete : TaskStatusEnum.Pending, AutoCreateNext = callback.FlowStatus == FlowStatusEnum.Approve @@ -434,7 +454,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction if (callback.FlowStatus == FlowStatusEnum.Reject) { //创建审单驳回任务以进行通知 - var task = await GetQuery(callback.BusinessId, callback.BusinessType.GetValueOrDefault(), TaskBaseTypeEnum.WAIT_ORDER_AUDIT).FirstAsync(); + var task = await GetQuery(callback.BusinessId, callback.BusinessType.Value, TaskBaseTypeEnum.WAIT_ORDER_AUDIT).FirstAsync(); await CreateTaskAsync(new TaskCreationRequest { BusinessId = callback.BusinessId, diff --git a/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs b/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs index 0e2da99d..e3ac6808 100644 --- a/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs +++ b/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs @@ -1,5 +1,6 @@ using System.Net; using DS.Module.Core; +using DS.WMS.Core.Fee.Dtos; using DS.WMS.Core.Flow.Dtos; using DS.WMS.Core.Op.Dtos.TaskInteraction; using DS.WMS.Core.Op.Interface.TaskInteraction; @@ -29,7 +30,7 @@ namespace DS.WMS.OpApi.Controllers /// /// [HttpPost, Route("CreateTask")] - public async Task CreateTaskAsync(TaskCreationRequest request) + public async Task CreateTaskAsync([FromBody] TaskCreationRequest request) { return await taskService.CreateTaskAsync(request); } @@ -40,21 +41,55 @@ namespace DS.WMS.OpApi.Controllers /// /// [HttpPost, Route("SetTaskStatus")] - public async Task SetTaskStatusAsync(TaskUpdateRequest request) + public async Task SetTaskStatusAsync([FromBody] TaskUpdateRequest request) { return await taskService.SetTaskStatusAsync(request); } + /// + /// 手动发起任务审核(用于二次审核) + /// + /// + /// + [HttpPost, Route("SubmitAudit")] + public async Task SubmitAuditAsync(TaskRequest request) + { + return await taskService.SubmitAuditAsync(request); + } + + /// + /// 任务审核 + /// + /// + /// + [HttpPost, Route("Audit")] + public async virtual Task AuditAsync([FromBody] AuditRequest request) + { + return await taskService.AuditAsync(request); + } + /// /// 审批完成回调更新(无需客户端手动调用) /// /// 回调信息 /// [HttpPost, Route("UpdateBusiness")] - public async Task UpdateBusinessAsync(FlowCallback callback) + public async Task UpdateBusinessAsync([FromBody] FlowCallback callback) { await taskService.UpdateBusinessAsync(callback); return StatusCode((int)HttpStatusCode.NoContent); } + + /// + /// 通知更新任务接收人(无需客户端手动调用) + /// + /// 回调信息 + /// + [HttpPost, Route("UpdateReceiver")] + public virtual async Task UpdateReceiverAsync([FromBody] MakerChangedCallback callback) + { + await taskService.UpdateReceiverAsync(callback); + return StatusCode((int)HttpStatusCode.NoContent); + } } }