diff --git a/ds-wms-service/DS.WMS.Core/DS.WMS.Core.csproj b/ds-wms-service/DS.WMS.Core/DS.WMS.Core.csproj index 5249b636..29d62b37 100644 --- a/ds-wms-service/DS.WMS.Core/DS.WMS.Core.csproj +++ b/ds-wms-service/DS.WMS.Core/DS.WMS.Core.csproj @@ -25,7 +25,6 @@ - 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 eea7a61c..42448271 100644 --- a/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs +++ b/ds-wms-service/DS.WMS.Core/Flow/Method/FlowInstanceService.cs @@ -429,6 +429,9 @@ public class FlowInstanceService : IFlowInstanceService /// 运行实例 protected virtual async Task RunCallbackAsync(FlowInstance instance) { + if (instance.CallbackURL.IsNullOrEmpty()) + return; + //请求参数设置 var callback = new FlowCallback { diff --git a/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/ISeaExportTaskService.cs b/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/ISeaExportTaskService.cs new file mode 100644 index 00000000..24116fef --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/ISeaExportTaskService.cs @@ -0,0 +1,10 @@ +namespace DS.WMS.Core.Op.Interface.TaskInteraction +{ + /// + /// 海运出口交互任务 + /// + public interface ISeaExportTaskService : ITaskService + { + + } +} 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 new file mode 100644 index 00000000..c412c529 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Interface/TaskInteraction/ITaskService.cs @@ -0,0 +1,34 @@ +using DS.Module.Core; +using DS.WMS.Core.Flow.Dtos; +using DS.WMS.Core.Op.Dtos.TaskInteraction; + +namespace DS.WMS.Core.Op.Interface.TaskInteraction +{ + /// + /// 交互任务 + /// + public interface ITaskService + { + /// + /// 创建关联任务 + /// + /// + /// 是否使用事务 + /// + Task CreateTaskAsync(TaskCreationRequest request, bool useTransaction = true); + + /// + /// 设置任务状态 + /// + /// + /// + Task SetTaskStatusAsync(TaskUpdateRequest request); + + /// + /// 审批完成回调更新 + /// + /// 回调信息 + /// + Task UpdateBusinessAsync(FlowCallback callback); + } +} diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotService.cs index 17d43ad5..0d8b104a 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotService.cs @@ -1477,6 +1477,7 @@ namespace DS.WMS.Core.Op.Method TypeCode = fileTypeCode, TypeName = fileTypeName, LinkId = boookId, + OrgId = long.Parse(user.OrgId) }; await tenantDb.Insertable(newFile).ExecuteCommandAsync(); 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 96ba3f12..eb05b84a 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 @@ -1,28 +1,28 @@ using DS.Module.Core; using DS.Module.Core.Extensions; -using DS.WMS.Core.Fee.Method; +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.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; +using Newtonsoft.Json.Linq; namespace DS.WMS.Core.Op.Method.TaskInteraction { /// - /// 海运出口任务服务 + /// 海运出口任务交互服务 /// - public class SeaExportTaskService : FeeServiceBase + public class SeaExportTaskService : TaskService, ISeaExportTaskService { - ITaskManageService taskService; - Lazy flowService; + readonly Lazy djyService; + readonly Lazy flowService; /// /// 初始化 @@ -30,198 +30,193 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction /// public SeaExportTaskService(IServiceProvider provider) : base(provider) { - taskService = provider.GetRequiredService(); + djyService = new Lazy(provider.GetRequiredService()); flowService = new Lazy(provider.GetRequiredService()); } /// - /// 创建关联任务 + /// 当任务创建时调用 /// - /// + /// /// - public async Task CreateTaskAsync(TaskCreationRequest request) + protected override async Task OnTaskCreated(BusinessTask task) { - 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().Where(x => x.Id == tenatId).Select(x => x.Name).First(); - var info = new TaskManageOrderMessageInfo + if (task.TaskType == TaskBaseTypeEnum.WAIT_ORDER_AUDIT) { - Head = new TaskManageOrderMessageHeadInfo + //待审核,需创建工作流 + var template = await FindTemplateAsync(AuditType.SeaExport); + if (template == null) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TemplateNotFound)); + + var result = flowService.Value.CreateFlowInstance(new CreateFlowInstanceReq { - 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 + BusinessId = task.BusinessId, + BusinessType = BusinessType.OceanShippingExport, + TemplateId = template.Id + }); + + if (result.Succeeded) { - TaskType = request.TaskType, - TaskSource = TaskSourceEnum.WORK_FLOW, - TaskTitle = request.TaskTitle, - TaskDesp = request.TaskDescription, - TaskUserId = User.UserId, - TaskUserName = User.UserName, - RecvUserId = User.UserId, - RecvUserName = User.UserName, - TaskTenatId = tenatId, - TaskTenatName = tenatName + var instance = result.Data as FlowInstance; + task.FlowId = instance.Id; + await TenantDb.Updateable(task).UpdateColumns(x => x.FlowId).ExecuteCommandAsync(); } - }; + } + + return DataResult.Success; + } + + /// + /// 创建关联子任务 + /// + /// + /// + public async Task CreateSubTaskAsync(IEnumerable request) + { + long userId = long.Parse(User.UserId); + long tenatId = long.Parse(User.TenantId); + string tenatName = Db.Queryable().Where(x => x.Id == tenatId).Select(x => x.Name).First(); + var dt = DateTime.Now; + var taskList = new List(); - if (info.Main.TaskTitle.IsNullOrEmpty()) + var first = request.FirstOrDefault(); + var biz = await TenantDb.Queryable().Select(x => new { - var biz = await TenantDb.Queryable().Select(x => new + x.Id, + x.MBLNO, + x.Vessel, + x.Voyno, + x.ETD, + }).FirstAsync(x => x.Id == first.BusinessId); + + foreach (var item in request) + { + var info = new TaskManageOrderMessageInfo { - x.Id, - x.MBLNO, - x.Vessel, - x.Voyno, - x.ETD, - }).FirstAsync(); - - info.Main.TaskDesp = info.Main.TaskTitle = $"{request.TaskType.GetDescription()} {biz.Vessel} {biz.Voyno} ETD:{biz.ETD?.ToString("yyyy-MM-dd")} BLNo:{biz.MBLNO}"; - } + Head = new TaskManageOrderMessageHeadInfo + { + GID = Guid.NewGuid().ToString(), + BSNO = item.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 = item.TaskType, + TaskSource = TaskSourceEnum.WORK_FLOW, + TaskUserId = User.UserId, + TaskUserName = User.UserName, + RecvUserInfoList = [new RecvUserInfo { RecvUserId = long.Parse(User.UserId), RecvUserName = User.UserName }], + TaskTenatId = tenatId, + TaskTenatName = tenatName + } + }; + info.Main.TaskDesp = info.Main.TaskTitle = $"{item.TaskType.GetDescription()} {biz.Vessel} {biz.Voyno} ETD:{biz.ETD?.ToString("yyyy-MM-dd")} BLNo:{biz.MBLNO}"; - await TenantDb.Ado.BeginTranAsync(); - try - { - var result = await taskService.InitTaskJob(info); + var result = await ManagerService.InitTaskJob(info); if (!result.Succeeded) return result; - task = new BusinessTask + var task = new BusinessTask { - BusinessId = request.BusinessId, - BusinessType = request.BusinessType, - TaskType = request.TaskType, + BusinessId = item.BusinessId, + BusinessType = item.BusinessType, + TaskType = item.TaskType, TaskStatus = TaskStatusEnum.Create, - CreateBy = long.Parse(User.UserId), - CreateTime = DateTime.Now + CreateBy = userId, + CreateTime = dt }; - task.NextType = GetNextType(task); - await TenantDb.Insertable(task).ExecuteCommandAsync(); - - if (request.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 = request.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(); - } - } - - 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)); + taskList.Add(task); } + + await TenantDb.Insertable(taskList).ExecuteCommandAsync(); + return DataResult.Success; } /// - /// 设置任务状态 + /// 当任务状态发生变化时调用 /// /// /// - public async Task UpdateTaskStatusAsync(TaskUpdateRequest request) + protected override async Task OnTaskStatusChanged(TaskUpdateRequest request) { - await TenantDb.Ado.BeginTranAsync(); - try + //放舱结束,根据业务所选服务,生成子任务 + if (request.TaskType == TaskBaseTypeEnum.WAIT_SPACE_RELEASE) { - var result = await taskService.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)); - - task.TaskStatus = request.TaskStatus; - await TenantDb.Updateable(task).UpdateColumns(x => x.TaskStatus).ExecuteCommandAsync(); - - //若存在下一任务,则创建 - if (task.NextType.HasValue) - { - var req = new TaskCreationRequest - { - BusinessId = request.BusinessId, - BusinessType = request.BusinessType, - TaskType = task.NextType.Value - }; - await CreateTaskAsync(req); - } - - //放舱结束,根据业务所选服务,生成子任务 - if (request.TaskType == TaskBaseTypeEnum.WAIT_SPACE_RELEASE) - { - - } - - return DataResult.Success; + var list = await GetSubRequestAsync(request.BusinessId, request.BusinessType); + await CreateSubTaskAsync(list); } - catch (Exception ex) + } + + internal async Task GetSubRequestAsync(long id, BusinessType businessType) + { + var svcList = await GetServicesAsync(id); + var list = new TaskCreationRequest[svcList.Length]; + for (int i = 0; i < svcList.Length; i++) { - await TenantDb.Ado.RollbackTranAsync(); - await ex.LogAsync(Db); - return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); + var dto = new TaskCreationRequest { BusinessId = id, BusinessType = businessType }; + var svcName = svcList[i]; + + if (svcName == "报关") + dto.TaskType = TaskBaseTypeEnum.WAIT_BAOGUAN; + else if (svcName == "订舱") + dto.TaskType = TaskBaseTypeEnum.WAIT_CANGDAN; + else if (svcName.Equals("VGM", StringComparison.OrdinalIgnoreCase)) + dto.TaskType = TaskBaseTypeEnum.WAIT_VGM; + else if (svcName.Equals("AFR", StringComparison.OrdinalIgnoreCase)) + dto.TaskType = TaskBaseTypeEnum.WAIT_AFR; + else if (svcName.Equals("AMS", StringComparison.OrdinalIgnoreCase)) + dto.TaskType = TaskBaseTypeEnum.WAIT_AMS; + else if (svcName.Equals("ISF", StringComparison.OrdinalIgnoreCase)) + dto.TaskType = TaskBaseTypeEnum.WAIT_ISF; + else if (svcName == "熏蒸") + dto.TaskType = TaskBaseTypeEnum.WAIT_XUNZHENG; + else if (svcName == "商检") + dto.TaskType = TaskBaseTypeEnum.WAIT_SHANGJIAN; + else if (svcName.Equals("COA证书", StringComparison.OrdinalIgnoreCase)) + dto.TaskType = TaskBaseTypeEnum.WAIT_COA; + else if (svcName == "产地证") + dto.TaskType = TaskBaseTypeEnum.WAIT_CHANDIZHENG; + + list[i] = dto; } + + return list; } + internal async Task GetServicesAsync(long id) + { + var result = await djyService.Value.GetServiceProjectList( + new EmbedQueryServiceProjectWithStatus { BusinessId = id.ToString() }); + if (!result.success) + return []; - internal async Task GetTaskAsync(long id, BusinessType businessType, TaskBaseTypeEnum taskType) - { - return await TenantDb.Queryable().FirstAsync(x => - x.BusinessId == id && x.BusinessType == businessType && x.TaskType == taskType); - } + if (((JObject)result.data)["ext"] is not JArray extArray || extArray.Count == 0) + return []; - internal async Task GetCurrentTaskAsync(long id, BusinessType businessType) - { - return await TenantDb.Queryable().Where(x => x.BusinessId == id && x.BusinessType == businessType) - .OrderByDescending(x => x.CreateTime).Take(1).FirstAsync(); + return extArray.Select(x => x["projectName"]?.Value() ?? string.Empty).ToArray(); } /// - /// 获取给定任务的下一任务类型 + /// 审批完成回调更新 /// - /// 任务信息 + /// 回调信息 /// - internal static TaskBaseTypeEnum? GetNextType(BusinessTask current) + public override async Task UpdateBusinessAsync(FlowCallback callback) { - if (current.TaskType == TaskBaseTypeEnum.WAIT_CHECKOUT_BILL) - return null; + await base.UpdateBusinessAsync(callback); + + //todo:海运出口主表信息 - int currentTypeVal = (int)current.TaskType; - if (currentTypeVal >= 300) //300开始的枚举值为可选服务项目,不存在前后关联性 - return null; - return (TaskBaseTypeEnum)currentTypeVal++; } + } } 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 new file mode 100644 index 00000000..bb73f3cb --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/TaskService.cs @@ -0,0 +1,249 @@ +using DS.Module.Core; +using DS.Module.Core.Extensions; +using DS.WMS.Core.Fee.Method; +using DS.WMS.Core.Flow.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.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 +{ + /// + /// 任务交互服务 + /// + public class TaskService : FeeServiceBase, ITaskService + { + /// + /// 任务管理服务 + /// + protected ITaskManageService ManagerService { get; private set; } + + /// + /// 初始化 + /// + /// + protected TaskService(IServiceProvider provider) : base(provider) + { + ManagerService = provider.GetRequiredService(); + } + + /// + /// 创建关联任务 + /// + /// + /// 是否使用事务 + /// + public async Task CreateTaskAsync(TaskCreationRequest request, bool useTransaction = true) + { + 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().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, + RecvUserId = User.UserId, + RecvUserName = User.UserName, + TaskTenatId = tenatId, + TaskTenatName = tenatName + } + }; + + if (info.Main.TaskTitle.IsNullOrEmpty()) + { + var biz = await TenantDb.Queryable().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, + CreateBy = long.Parse(User.UserId), + CreateTime = DateTime.Now + }; + task.NextType = GetNextType(task); + await TenantDb.Insertable(task).ExecuteCommandAsync(); + + 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)); + } + } + + /// + /// 当任务创建时调用 + /// + /// + /// + protected virtual Task OnTaskCreated(BusinessTask task) + { + return Task.FromResult(DataResult.Success); + } + + /// + /// 设置任务状态 + /// + /// + /// + public async Task SetTaskStatusAsync(TaskUpdateRequest request) + { + 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; + await TenantDb.Updateable(task).UpdateColumns(x => x.TaskStatus).ExecuteCommandAsync(); + + if (task.TaskStatus == TaskStatusEnum.Complete) + { + //若存在下一任务,则继续创建 + if (task.NextType.HasValue) + { + var req = new TaskCreationRequest + { + BusinessId = request.BusinessId, + BusinessType = request.BusinessType, + TaskType = task.NextType.Value + }; + await CreateTaskAsync(req, 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)); + } + } + + /// + /// 当任务状态发生变化时调用 + /// + /// + /// + protected virtual Task OnTaskStatusChanged(TaskUpdateRequest request) + { + return Task.CompletedTask; + } + + /// + /// 审批完成回调更新 + /// + /// 回调信息 + /// + /// 为null时引发 + 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 + }); + } + + protected internal async Task GetTaskAsync(long id, BusinessType businessType, TaskBaseTypeEnum taskType) + { + return await TenantDb.Queryable().FirstAsync(x => + x.BusinessId == id && x.BusinessType == businessType && x.TaskType == taskType); + } + + /// + /// 获取给定任务的下一任务类型 + /// + /// 任务信息 + /// + 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++; + } + } +} diff --git a/ds-wms-service/DS.WMS.Core/Sys/Method/SysFileService.cs b/ds-wms-service/DS.WMS.Core/Sys/Method/SysFileService.cs index 04112267..2d87a158 100644 --- a/ds-wms-service/DS.WMS.Core/Sys/Method/SysFileService.cs +++ b/ds-wms-service/DS.WMS.Core/Sys/Method/SysFileService.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using NLog; +using NPOI.HPSF; using NPOI.SS.Formula.Functions; using SqlSugar; using System; @@ -133,6 +134,10 @@ namespace DS.WMS.Core.Sys.Method string fileRoot = AppSetting.app(new string[] { "FileSettings", "BasePath" }); string relativePath = AppSetting.app(new string[] { "FileSettings", "RelativePath" }); + /* + if (string.IsNullOrWhiteSpace(fileRoot)) + fileRoot = _environment.WebRootPath; + if (!string.IsNullOrWhiteSpace(attachFileType)) relativePath += $"\\{attachFileType}"; @@ -150,31 +155,54 @@ namespace DS.WMS.Core.Sys.Method relativePath = relativePath.Replace("\\", "/"); filePath = filePath.Replace("\\", "/"); fileFullName = fileFullName.Replace("\\", "/"); + }*/ + + var dirAbs = string.Empty; + var fileRelaPath = string.Empty; + var fileAbsPath = string.Empty; + if (string.IsNullOrEmpty(fileRoot)) + { + dirAbs = Path.Combine(_environment.WebRootPath ?? "", relativePath); + } + else + { + dirAbs = Path.Combine(fileRoot, relativePath); } - Logger.Log(NLog.LogLevel.Info, "批次={no} 生成文件保存路径完成 路由={filePath} 服务器系统={system}", batchNo, filePath, + if (!Directory.Exists(dirAbs)) + Directory.CreateDirectory(dirAbs); + // 先存库获取Id + var id = SnowFlakeSingle.Instance.NextId(); + + var fileSuffix = Path.GetExtension(fileName).ToLower(); // 文件后缀 + + var fileSaveName = $"{id}{fileSuffix}".ToLower(); + fileRelaPath = Path.Combine(relativePath, fileSaveName).ToLower(); + fileAbsPath = Path.Combine(dirAbs, fileSaveName).ToLower(); + + Logger.Log(NLog.LogLevel.Info, "批次={no} 生成文件保存路径完成 路由={filePath} 服务器系统={system}", batchNo, fileAbsPath, RuntimeInformation.OSDescription); //预先创建目录 - if (!Directory.Exists(filePath)) + if (!Directory.Exists(dirAbs)) { - Directory.CreateDirectory(filePath); + Directory.CreateDirectory(dirAbs); } - await File.WriteAllBytesAsync(fileFullName, fileBytes); + await File.WriteAllBytesAsync(fileAbsPath, fileBytes); - string bookFilePath = string.Empty; + //string bookFilePath = string.Empty; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("/", "\\/") + ".*").Value; - } - else - { - bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("\\", "\\\\") + ".*").Value; - } + //if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + //{ + // bookFilePath = System.Text.RegularExpressions.Regex.Match(dirAbs, relativePath.Replace("/", "\\/") + ".*").Value; + //} + //else + //{ + // bookFilePath = System.Text.RegularExpressions.Regex.Match(dirAbs, relativePath.Replace("\\", "\\\\") + ".*").Value; + //} - return DataResult.Success(bookFilePath); + return DataResult.Success(fileSaveName); } #region 转移文件 @@ -195,6 +223,10 @@ namespace DS.WMS.Core.Sys.Method string relativePath = AppSetting.app(new string[] { "FileSettings", "RelativePath" }); + /* + if (string.IsNullOrWhiteSpace(fileRoot)) + fileRoot = _environment.WebRootPath; + if (!string.IsNullOrWhiteSpace(attachFileType)) relativePath += $"\\{attachFileType}"; @@ -213,14 +245,37 @@ namespace DS.WMS.Core.Sys.Method filePath = filePath.Replace("\\", "/"); fileFullName = fileFullName.Replace("\\", "/"); } - - Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 生成文件保存路径完成 路由={filePath} 服务器系统={RuntimeInformation.OSDescription}"); - - //预先创建目录 - if (!Directory.Exists(filePath)) + */ + var dirAbs = string.Empty; + var fileRelaPath = string.Empty; + var fileAbsPath = string.Empty; + if (string.IsNullOrEmpty(fileRoot)) { - Directory.CreateDirectory(filePath); + dirAbs = Path.Combine(_environment.WebRootPath ?? "", relativePath); } + else + { + dirAbs = Path.Combine(fileRoot, relativePath); + } + + if (!Directory.Exists(dirAbs)) + Directory.CreateDirectory(dirAbs); + // 先存库获取Id + var id = SnowFlakeSingle.Instance.NextId(); + + var fileSuffix = Path.GetExtension(sourceFilePath).ToLower(); // 文件后缀 + + var fileSaveName = $"{id}{fileSuffix}".ToLower(); + fileRelaPath = Path.Combine(relativePath, fileSaveName).ToLower(); + fileAbsPath = Path.Combine(dirAbs, fileSaveName).ToLower(); + + Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 生成文件保存路径完成 路由={fileAbsPath} 服务器系统={RuntimeInformation.OSDescription}"); + + ////预先创建目录 + //if (!Directory.Exists(filePath)) + //{ + // Directory.CreateDirectory(filePath); + //} if (sourceFilePath.StartsWith("http", StringComparison.OrdinalIgnoreCase) || sourceFilePath.StartsWith("https", StringComparison.OrdinalIgnoreCase)) @@ -236,7 +291,7 @@ namespace DS.WMS.Core.Sys.Method { System.IO.FileStream file = new System.IO.FileStream(sourceFilePath, FileMode.Open, FileAccess.Read); - using (var fileStream = File.Create(fileFullName)) + using (var fileStream = File.Create(fileAbsPath)) { await file.CopyToAsync(fileStream); } @@ -254,24 +309,24 @@ namespace DS.WMS.Core.Sys.Method } catch (Exception delEx) { - Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 删除文件异常 filepath={fileFullName} ex={delEx.Message}"); + Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 删除文件异常 filepath={sourceFilePath} ex={delEx.Message}"); } } - Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 完成文件保存 filepath={fileFullName}"); + Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 完成文件保存 filepath={sourceFilePath}"); string bookFilePath = string.Empty; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("/", "\\/") + ".*").Value; - } - else - { - bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("\\", "\\\\") + ".*").Value; - } + //if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + //{ + // bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("/", "\\/") + ".*").Value; + //} + //else + //{ + // bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("\\", "\\\\") + ".*").Value; + //} - return DataResult.Success(bookFilePath); + return DataResult.Success(fileSaveName); } #endregion } diff --git a/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs b/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs new file mode 100644 index 00000000..0e2da99d --- /dev/null +++ b/ds-wms-service/DS.WMS.OpApi/Controllers/SeaExportTaskController.cs @@ -0,0 +1,60 @@ +using System.Net; +using DS.Module.Core; +using DS.WMS.Core.Flow.Dtos; +using DS.WMS.Core.Op.Dtos.TaskInteraction; +using DS.WMS.Core.Op.Interface.TaskInteraction; +using Microsoft.AspNetCore.Mvc; + +namespace DS.WMS.OpApi.Controllers +{ + /// + /// 海运出口任务API + /// + public class SeaExportTaskController : ApiController + { + readonly ISeaExportTaskService taskService; + + /// + /// 构造函数 + /// + /// + public SeaExportTaskController(ISeaExportTaskService service) + { + taskService = service; + } + + /// + /// 创建关联任务 + /// + /// + /// + [HttpPost, Route("CreateTask")] + public async Task CreateTaskAsync(TaskCreationRequest request) + { + return await taskService.CreateTaskAsync(request); + } + + /// + /// 设置任务状态 + /// + /// + /// + [HttpPost, Route("SetTaskStatus")] + public async Task SetTaskStatusAsync(TaskUpdateRequest request) + { + return await taskService.SetTaskStatusAsync(request); + } + + /// + /// 审批完成回调更新(无需客户端手动调用) + /// + /// 回调信息 + /// + [HttpPost, Route("UpdateBusiness")] + public async Task UpdateBusinessAsync(FlowCallback callback) + { + await taskService.UpdateBusinessAsync(callback); + return StatusCode((int)HttpStatusCode.NoContent); + } + } +} diff --git a/ds-wms-service/DS.WMS.OpApi/Logs/internal-nlog.txt b/ds-wms-service/DS.WMS.OpApi/Logs/internal-nlog.txt index f75be20e..2d301b3f 100644 --- a/ds-wms-service/DS.WMS.OpApi/Logs/internal-nlog.txt +++ b/ds-wms-service/DS.WMS.OpApi/Logs/internal-nlog.txt @@ -782,52 +782,24 @@ 2024-07-24 14:14:41.8726 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=E:\MyCode\Dongsheng8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config 2024-07-24 14:14:41.8726 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile 2024-07-24 14:14:41.8863 Info Configuration initialized. -2024-07-24 17:43:01.5160 Info Registered target NLog.Targets.FileTarget(Name=allfile) -2024-07-24 17:43:01.5361 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) -2024-07-24 17:43:01.5361 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) -2024-07-24 17:43:01.5528 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False -2024-07-24 17:43:01.5595 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=E:\MyCode\Dongsheng8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config -2024-07-24 17:43:01.5595 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile -2024-07-24 17:43:01.5595 Info Configuration initialized. -2024-07-24 17:52:22.4155 Info Registered target NLog.Targets.FileTarget(Name=allfile) -2024-07-24 17:52:22.4304 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) -2024-07-24 17:52:22.4304 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) -2024-07-24 17:52:22.4474 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False -2024-07-24 17:52:22.4474 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=E:\MyCode\Dongsheng8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config -2024-07-24 17:52:22.4592 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile -2024-07-24 17:52:22.4592 Info Configuration initialized. -2024-07-24 18:18:28.4775 Info Registered target NLog.Targets.FileTarget(Name=allfile) -2024-07-24 18:18:28.4775 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) -2024-07-24 18:18:28.4932 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) -2024-07-24 18:18:28.4932 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False -2024-07-24 18:18:28.5125 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=E:\MyCode\Dongsheng8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config -2024-07-24 18:18:28.5125 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile -2024-07-24 18:18:28.5262 Info Configuration initialized. -2024-07-24 18:26:06.2961 Info Registered target NLog.Targets.FileTarget(Name=allfile) -2024-07-24 18:26:06.2961 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) -2024-07-24 18:26:06.3125 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) -2024-07-24 18:26:06.3125 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False -2024-07-24 18:26:06.3294 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=E:\MyCode\Dongsheng8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config -2024-07-24 18:26:06.3294 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile -2024-07-24 18:26:06.3294 Info Configuration initialized. -2024-07-24 19:21:42.6540 Info Registered target NLog.Targets.FileTarget(Name=allfile) -2024-07-24 19:21:42.6670 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) -2024-07-24 19:21:42.6670 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) -2024-07-24 19:21:42.6832 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False -2024-07-24 19:21:42.6832 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=E:\MyCode\Dongsheng8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config -2024-07-24 19:21:42.6949 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile -2024-07-24 19:21:42.6949 Info Configuration initialized. -2024-07-24 19:22:50.9145 Info Registered target NLog.Targets.FileTarget(Name=allfile) -2024-07-24 19:22:50.9296 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) -2024-07-24 19:22:50.9296 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) -2024-07-24 19:22:50.9498 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False -2024-07-24 19:22:50.9610 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=E:\MyCode\Dongsheng8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config -2024-07-24 19:22:50.9610 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile -2024-07-24 19:22:50.9610 Info Configuration initialized. -2024-07-24 19:24:05.3244 Info Registered target NLog.Targets.FileTarget(Name=allfile) -2024-07-24 19:24:05.3762 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) -2024-07-24 19:24:05.3816 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) -2024-07-24 19:24:05.3816 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False -2024-07-24 19:24:05.4053 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=E:\MyCode\Dongsheng8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config -2024-07-24 19:24:05.4053 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile -2024-07-24 19:24:05.4155 Info Configuration initialized. +2024-07-25 09:55:08.3354 Info Registered target NLog.Targets.FileTarget(Name=allfile) +2024-07-25 09:55:08.3354 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) +2024-07-25 09:55:08.3515 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) +2024-07-25 09:55:08.3515 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False +2024-07-25 09:55:08.3711 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config +2024-07-25 09:55:08.3711 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile +2024-07-25 09:55:08.3711 Info Configuration initialized. +2024-07-25 09:56:52.6865 Info Registered target NLog.Targets.FileTarget(Name=allfile) +2024-07-25 09:56:52.7029 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) +2024-07-25 09:56:52.7029 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) +2024-07-25 09:56:52.7214 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False +2024-07-25 09:56:52.7280 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config +2024-07-25 09:56:52.7280 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile +2024-07-25 09:56:52.7280 Info Configuration initialized. +2024-07-25 10:04:30.5148 Info Registered target NLog.Targets.FileTarget(Name=allfile) +2024-07-25 10:04:30.5293 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) +2024-07-25 10:04:30.5293 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) +2024-07-25 10:04:30.5484 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False +2024-07-25 10:04:30.5557 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.OpApi\bin\Debug\net8.0\nlog.config +2024-07-25 10:04:30.5557 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile +2024-07-25 10:04:30.5557 Info Configuration initialized. diff --git a/ds-wms-service/DS.WMS.TaskApi/Controllers/TaskManageController.cs b/ds-wms-service/DS.WMS.TaskApi/Controllers/TaskManageController.cs index 791524a4..0c8b2e31 100644 --- a/ds-wms-service/DS.WMS.TaskApi/Controllers/TaskManageController.cs +++ b/ds-wms-service/DS.WMS.TaskApi/Controllers/TaskManageController.cs @@ -28,7 +28,7 @@ public class TaskManageController : ApiController /// 返回回执 [HttpPost("CreateTaskJob")] [ApiUser(ApiCode = "BCTaskManage"), AllowAnonymous] - public async Task CreateTaskJob(TaskManageOrderMessageInfo info) + public async Task> CreateTaskJob(TaskManageOrderMessageInfo info) { var result = await taskManageService.InitTaskJob(info); return result; @@ -43,7 +43,7 @@ public class TaskManageController : ApiController /// 返回回执 [HttpPost("CreateBCTaskJob")] [ApiUser(ApiCode = "BCTaskManage"), AllowAnonymous] - public async Task CreateBCTaskJob(IFormFile file, IFormFile modifyFile, [FromForm] string jsonData) + public async Task> CreateBCTaskJob(IFormFile file, IFormFile modifyFile, [FromForm] string jsonData) { TaskManageOrderMessageInfo? info = JsonConvert.DeserializeObject(jsonData); if (info == null)