diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/BookingActionExecutor.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/BookingActionExecutor.cs index 01f2c8f6..823cf605 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/BookingActionExecutor.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/BookingActionExecutor.cs @@ -10,36 +10,41 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor { internal const TaskBaseTypeEnum Booking_TaskType = TaskBaseTypeEnum.WAIT_BOOKING; - protected ISeaExportTaskService taskService; - protected ITaskLogService logService; + /// + /// 任务服务 + /// + protected ISeaExportTaskService TaskService; + /// + /// 日志服务 + /// + protected ITaskLogService LogService; public override Task ExecuteAsync(ActionExecutionContext context) { - taskService = context.ServiceProvider.GetRequiredService(); - logService = context.ServiceProvider.GetRequiredService(); + TaskService = context.ServiceProvider.GetRequiredService(); + LogService = context.ServiceProvider.GetRequiredService(); return Task.CompletedTask; } protected async Task CreateTask(ActionExecutionContext context) { - var result1 = await taskService.Exists(context.TaskInfo.BusinessId, context.TaskInfo.BusinessType, Booking_TaskType); - if (!result1.Data) - { - return await taskService.CreateTaskAsync(new TaskCreationRequest - { - BusinessId = context.TaskInfo.BusinessId, - BusinessType = context.TaskInfo.BusinessType, - TaskTypeName = Booking_TaskType.ToString() - }); - } + var result = await TaskService.Exists(context.TaskInfo.BusinessId, context.TaskInfo.BusinessType, Booking_TaskType); + //任务已存在,跳过创建步骤 + if (result.Data) + return DataResult.Success; - return DataResult.Success; + return await TaskService.CreateTaskAsync(new TaskCreationRequest + { + BusinessId = context.TaskInfo.BusinessId, + BusinessType = context.TaskInfo.BusinessType, + TaskTypeName = Booking_TaskType.ToString() + }); } - protected async Task CompleteTask(ActionExecutionContext context) + protected async Task SetTaskComplete(ActionExecutionContext context) { - var result = await taskService.SetTaskStatusAsync(new TaskUpdateRequest + var result = await TaskService.SetTaskStatusAsync(new TaskUpdateRequest { BusinessId = context.TaskInfo.BusinessId, BusinessType = context.TaskInfo.BusinessType, @@ -48,7 +53,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor AutoCreateNext = true }); if (!result.Succeeded) - await logService.WriteLogAsync(context.TaskInfo, $"未能设置任务【{Booking_TaskType.GetDescription()}】完成,返回结果:{result.Message}"); + await LogService.WriteLogAsync(context.TaskInfo, $"未能设置任务【{Booking_TaskType.GetDescription()}】完成,返回结果:{result.Message}"); } } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/EDIActionExecutor.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/EDIActionExecutor.cs index 0504a118..75a2ab97 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/EDIActionExecutor.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/EDIActionExecutor.cs @@ -19,7 +19,7 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor var result = await CreateTask(context); if (!result.Succeeded) { - await logService.WriteLogAsync(context.TaskInfo, $"创建任务【{Booking_TaskType.GetDescription()}】失败,返回结果:{result.Message}"); + await LogService.WriteLogAsync(context.TaskInfo, $"创建任务【{Booking_TaskType.GetDescription()}】失败,返回结果:{result.Message}"); return; } @@ -38,11 +38,11 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor //订舱未成功 if (!result2.Succeeded) { - await logService.WriteLogAsync(context.TaskInfo, "EDI返回结果失败,自动订舱未成功"); + await LogService.WriteLogAsync(context.TaskInfo, "EDI返回结果失败,自动订舱未成功"); return; } - await CompleteTask(context); + await SetTaskComplete(context); } } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/MailActionExecutor.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/MailActionExecutor.cs index 975ef44f..3c6506a6 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/MailActionExecutor.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/ActionExecutor/MailActionExecutor.cs @@ -1,21 +1,9 @@ -using DS.Module.PrintModule; -using DS.Module.SqlSugar; -using DS.Module.UserModule; -using DS.WMS.Core.Code.Entity; -using DS.WMS.Core.Info.Entity; -using DS.WMS.Core.Op.Dtos.TaskInteraction; +using DS.WMS.Core.Op.Dtos.TaskInteraction; using DS.WMS.Core.Op.Entity.TaskInteraction; -using DS.WMS.Core.Op.Interface; using DS.WMS.Core.Op.Interface.TaskInteraction; -using DS.WMS.Core.Sys.Entity; -using HtmlAgilityPack; -using Mapster; using Masuit.Tools; using Masuit.Tools.Systems; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; -using RazorEngineCore; using SqlSugar; namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor @@ -32,210 +20,52 @@ namespace DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor /// public async override Task ExecuteAsync(ActionExecutionContext context) { - var db = context.ServiceProvider.GetRequiredService(); - var saasService = context.ServiceProvider.GetRequiredService(); - var user = context.ServiceProvider.GetRequiredService(); - var tenantDb = saasService.GetBizDbScopeById(user.TenantId); - - var service = context.ServiceProvider.GetRequiredService(); - var logService = context.ServiceProvider.GetRequiredService(); - var seService = context.ServiceProvider.GetRequiredService(); - - var config = context.ServiceProvider.GetRequiredService(); + await base.ExecuteAsync(context); + var result = await CreateTask(context); + if (!result.Succeeded) + { + await LogService.WriteLogAsync(context.TaskInfo, $"创建任务【{Booking_TaskType.GetDescription()}】失败,返回结果:{result.Message}"); + return; + } + var taskMailService = context.ServiceProvider.GetRequiredService(); + MailService mailService = new(context.ServiceProvider); BusinessTaskMail? mailConfig = null; if (context.AdditionalData.TryGetValue(nameof(BusinessTaskMail.Id), out var id)) { if (id == null) { - await logService.WriteLogAsync(context.TaskInfo, $"未配置【{context.TaskInfo.TaskType.GetDescription()}】任务的邮件设置"); + await LogService.WriteLogAsync(context.TaskInfo, $"未配置【{context.TaskInfo.TaskType.GetDescription()}】任务的邮件设置"); return; } var idVal = (long)Convert.ChangeType(id, typeof(long)); - mailConfig = (await service.GetAsync(idVal)).Data; + mailConfig = (await taskMailService.GetAsync(idVal)).Data; } else if (context.AdditionalData.TryGetValue(nameof(BusinessTaskMail.Name), out var name)) { var mailName = name as string; if (mailName.IsNullOrEmpty()) { - await logService.WriteLogAsync(context.TaskInfo, $"未配置【{context.TaskInfo.TaskType.GetDescription()}】任务的邮件设置"); + await LogService.WriteLogAsync(context.TaskInfo, $"未配置【{context.TaskInfo.TaskType.GetDescription()}】任务的邮件设置"); return; } - mailConfig = await service.GetAsync(mailName); + mailConfig = await taskMailService.GetAsync(mailName); } if (mailConfig == null) { - await logService.WriteLogAsync(context.TaskInfo, $"未能根据任务配置值获取邮件模板设置"); + await LogService.WriteLogAsync(context.TaskInfo, $"未能根据任务配置值获取邮件模板设置"); return; } - var result = seService.GetSeaExportInfo(context.TaskInfo.BusinessId.ToString()); - if (!result.Succeeded || result.Data == null) + result = await mailService.SendAsync(mailConfig, context.TaskInfo.BusinessId, context.TaskInfo.BusinessType); + if (!result.Succeeded) { - await logService.WriteLogAsync(context.TaskInfo, $"未能获取Id={context.TaskInfo.BusinessId}的{context.TaskInfo.BusinessType.GetDescription()}数据"); + await LogService.WriteLogAsync(context.TaskInfo, result.Message); return; } - string title, content = string.Empty; - var templateModel = new MailTemplateModel { Primary = result.Data.Adapt() }; - IRazorEngine razorEngine = new RazorEngine(); - try - { - var titleTemplate = razorEngine.Compile>>(mailConfig.Title); - title = await titleTemplate.RunAsync(x => - { - x.Model = templateModel; - }); - - var contentTemplate = razorEngine.Compile>>(mailConfig.Content); - content = await contentTemplate.RunAsync(x => - { - x.Model = templateModel; - }); - } - catch (Exception ex) - { - await ex.LogAsync(db); - await logService.WriteLogAsync(context.TaskInfo, $"渲染邮件模板({mailConfig.Id})时出错,请检查模板是否有语法错误"); - return; - } - - //设置发件人 - long senderId = 0; - if (mailConfig.Sender.IsSale) - senderId = templateModel.Primary.SaleId; - else if (mailConfig.Sender.IsOperator) - senderId = templateModel.Primary.OperatorId; - else if (mailConfig.Sender.IsCustomerService) - senderId = templateModel.Primary.CustomerService; - else if (mailConfig.Sender.IsVouchingClerk) - senderId = templateModel.Primary.Doc; - - var sender = await db.Queryable().Where(x => x.Id == senderId).Select( - x => new { x.UserName, x.SignatureHtml }).FirstAsync(); - if (sender == null) - { - await logService.WriteLogAsync(context.TaskInfo, "未设置发件人"); - return; - } - var senderConfig = await tenantDb.Queryable().FirstAsync(x => x.CreateBy == senderId); - if (senderConfig == null) - { - await logService.WriteLogAsync(context.TaskInfo, $"发件人用户:{sender.UserName} 未设置SMTP发件信息"); - return; - } - - //插入发件人签名 - var htmlDoc = new HtmlDocument(); - htmlDoc.LoadHtml(content); - var node = htmlDoc.GetElementbyId("sign"); - if (node != null) - node.InnerHtml = sender.SignatureHtml; - - StringWriter writer = new(); - htmlDoc.Save(writer); - content = writer.ToString(); - writer.Close(); - - //设置收件人 - List receiverIds = []; - if (mailConfig.Receiver.IsCarrier) - receiverIds.Add(templateModel.Primary.CarrierId); - - if (mailConfig.Receiver.IsBooking) - receiverIds.Add(templateModel.Primary.ForwarderId); - - if (mailConfig.Receiver.IsYard) - receiverIds.Add(templateModel.Primary.YardId); - - if (mailConfig.Receiver.IsTruck) - receiverIds.Add(templateModel.Primary.TruckerId); - - if (mailConfig.Receiver.IsController) - receiverIds.Add(templateModel.Primary.CustomerId); - - var receiverList = await tenantDb.Queryable().Where(x => receiverIds.Contains(x.Id) && x.Email != null && x.Email != string.Empty) - .Select(x => new { x.ShortName, x.EnShortName, x.Email }).ToListAsync(); - - var attachmentList = mailConfig.Attachments == null ? [] : new List>(mailConfig.Attachments.Count); - try - { - //需要上传附件 - if (mailConfig.Attachments?.Count > 0) - { - if (Api.DefaultHeaders.Contains("Authorization")) - Api.DefaultHeaders.Remove("Authorization"); - - Api.DefaultHeaders.Add("Authorization", "Bearer " + user.GetToken()); - - long tenantId = long.Parse(user.TenantId); - string requestUrl = config["TaskMail:FileBaseUrl"] + config["TaskMail:SQLPrint"]; - foreach (var item in mailConfig.Attachments) - { - var req = new OpenPrintReq - { - ParamJsonStr = JsonConvert.SerializeObject(new { Id = context.TaskInfo.BusinessId }), - PrintType = ((int)FileFormat.PDF).ToString(), - TemplateId = item.TemplateId, - TenantId = tenantId - }; - var reqResult = await Api.PostAsync(requestUrl, req); - if (!reqResult.Succeeded) - { - await logService.WriteLogAsync(context.TaskInfo, $"未能获取打印API生成的文件,请求地址:{requestUrl}"); - return; - } - - string url = config["TaskMail:FileBaseUrl"] + @"/PrintTempFile/" + reqResult.Data.Data; - var fileResult = await Api.SendRequestAsync(HttpMethod.Get, url); - if (!fileResult.Succeeded) - { - await logService.WriteLogAsync(context.TaskInfo, $"未能获取打印API生成的文件,附件地址:{url}"); - return; - } - - string fileName = item.FileName.IsNullOrEmpty() ? Path.GetFileName(reqResult.Data.Data) : item.FileName; - var bytes = await fileResult.Data.Content.ReadAsByteArrayAsync(); - string base64Str = Convert.ToBase64String(bytes); - attachmentList.Add(new Tuple(fileName, base64Str)); - } - } - - dynamic[] mailParams = [new - { - SendTo = string.Join(",", receiverList.Select(x => x.Email)), - Title = title, - Body = content, - ShowName = senderConfig.ShowName.IsNullOrEmpty() ? sender.UserName : senderConfig.ShowName, - Account = senderConfig.MailAccount, - senderConfig.Password, - Server = senderConfig.SmtpServer, - Port = senderConfig.SmtpPort.GetValueOrDefault(), - UseSSL = senderConfig.SmtpSSL.GetValueOrDefault(), - Attaches = attachmentList.Select(x => new - { - AttachName = x.Item1, - AttachContent = x.Item2 - }).ToList() - }]; - var mailResult = await Api.SendRequestAsync(HttpMethod.Post, config["TaskMail:MailApiUrl"], mailParams); - if (mailResult.Data.IsSuccessStatusCode) - { - await logService.WriteLogAsync(context.TaskInfo, $"已发邮件(委托单:{templateModel.Primary.CustomerNo}),收件人:" - + string.Join(",", receiverList.Select(x => x.Email)) + "发件人:" + senderConfig.MailAccount); - } - else - { - await logService.WriteLogAsync(context.TaskInfo, $"邮件发送失败(委托单:{templateModel.Primary.CustomerNo}),收件人:" - + string.Join(",", receiverList.Select(x => x.Email)) + "发件人:" + senderConfig.MailAccount); - } - } - catch (Exception ex) - { - await ex.LogAsync(db); - } + await SetTaskComplete(context); } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/MailService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/MailService.cs new file mode 100644 index 00000000..76e9dbee --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Method/TaskInteraction/MailService.cs @@ -0,0 +1,208 @@ +using DS.Module.PrintModule; +using DS.WMS.Core.Code.Entity; +using DS.WMS.Core.Info.Entity; +using DS.WMS.Core.Op.Dtos.TaskInteraction; +using DS.WMS.Core.Op.Entity.TaskInteraction; +using DS.WMS.Core.Op.Interface.TaskInteraction; +using DS.WMS.Core.Op.Interface; +using DS.WMS.Core.Op.Method.TaskInteraction.ActionExecutor; +using DS.WMS.Core.Sys.Entity; +using HtmlAgilityPack; +using Newtonsoft.Json; +using RazorEngineCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Mapster; +using DS.Module.Core; +using Masuit.Tools; +using Masuit.Tools.Systems; +using DS.WMS.Core.Op.Entity; + +namespace DS.WMS.Core.Op.Method.TaskInteraction +{ + /// + /// 业务邮件发送服务 + /// + public class MailService : ServiceBase + { + ITaskMailService service; + ISeaExportService seService; + IConfiguration config; + ApiFox Api = DefaultActionExecutor.Api; + + /// + /// 初始化 + /// + /// + public MailService(IServiceProvider provider) : base(provider) + { + service = provider.GetRequiredService(); + seService = provider.GetRequiredService(); + config = provider.GetRequiredService(); + } + + /// + /// 发送业务邮件 + /// + /// 邮件配置 + /// 业务ID + /// 业务类型 + /// + public async Task SendAsync(BusinessTaskMail mailConfig, + long businessId, BusinessType businessType = BusinessType.OceanShippingExport) + { + ArgumentNullException.ThrowIfNull(mailConfig, nameof(mailConfig)); + + var result = seService.GetSeaExportInfo(businessId.ToString()); + if (!result.Succeeded || result.Data == null) + return DataResult.Failed($"未能获取Id={businessId}的{businessType.GetDescription()}数据"); + + string title, content = string.Empty; + var templateModel = new MailTemplateModel { Primary = result.Data.Adapt() }; + IRazorEngine razorEngine = new RazorEngine(); + try + { + var titleTemplate = razorEngine.Compile>>(mailConfig.Title); + title = await titleTemplate.RunAsync(x => + { + x.Model = templateModel; + }); + + var contentTemplate = razorEngine.Compile>>(mailConfig.Content); + content = await contentTemplate.RunAsync(x => + { + x.Model = templateModel; + }); + } + catch (Exception ex) + { + await ex.LogAsync(Db); + return DataResult.Failed($"渲染邮件模板({mailConfig.Id})时出错,请检查模板是否有语法错误"); + } + + //设置发件人 + long senderId = 0; + if (mailConfig.Sender.IsSale) + senderId = templateModel.Primary.SaleId; + else if (mailConfig.Sender.IsOperator) + senderId = templateModel.Primary.OperatorId; + else if (mailConfig.Sender.IsCustomerService) + senderId = templateModel.Primary.CustomerService; + else if (mailConfig.Sender.IsVouchingClerk) + senderId = templateModel.Primary.Doc; + + var sender = await Db.Queryable().Where(x => x.Id == senderId).Select(x => new { x.UserName, x.SignatureHtml }).FirstAsync(); + if (sender == null) + return DataResult.Failed("未设置发件人"); + + var senderConfig = await TenantDb.Queryable().FirstAsync(x => x.CreateBy == senderId); + if (senderConfig == null) + return DataResult.Failed($"发件人用户:{sender.UserName} 未设置SMTP发件信息"); + + //插入发件人签名 + var htmlDoc = new HtmlDocument(); + htmlDoc.LoadHtml(content); + var node = htmlDoc.GetElementbyId("sign"); + if (node != null) + node.InnerHtml = sender.SignatureHtml; + + StringWriter writer = new(); + htmlDoc.Save(writer); + content = writer.ToString(); + writer.Close(); + + //设置收件人 + List receiverIds = []; + if (mailConfig.Receiver.IsCarrier) + receiverIds.Add(templateModel.Primary.CarrierId); + + if (mailConfig.Receiver.IsBooking) + receiverIds.Add(templateModel.Primary.ForwarderId); + if (mailConfig.Receiver.IsYard) + receiverIds.Add(templateModel.Primary.YardId); + + if (mailConfig.Receiver.IsTruck) + receiverIds.Add(templateModel.Primary.TruckerId); + + if (mailConfig.Receiver.IsController) + receiverIds.Add(templateModel.Primary.CustomerId); + + var receiverList = await TenantDb.Queryable().Where(x => receiverIds.Contains(x.Id) && x.Email != null && x.Email != string.Empty) + .Select(x => new { x.ShortName, x.EnShortName, x.Email }).ToListAsync(); + + var attachmentList = mailConfig.Attachments == null ? [] : new List>(mailConfig.Attachments.Count); + try + { + //需要上传附件 + if (mailConfig.Attachments?.Count > 0) + { + if (Api.DefaultHeaders.Contains("Authorization")) + Api.DefaultHeaders.Remove("Authorization"); + + Api.DefaultHeaders.Add("Authorization", "Bearer " + User.GetToken()); + + long tenantId = long.Parse(User.TenantId); + string requestUrl = config["TaskMail:FileBaseUrl"] + config["TaskMail:SQLPrint"]; + foreach (var item in mailConfig.Attachments) + { + var req = new OpenPrintReq + { + ParamJsonStr = JsonConvert.SerializeObject(new { Id = businessId }), + PrintType = ((int)FileFormat.PDF).ToString(), + TemplateId = item.TemplateId, + TenantId = tenantId + }; + var reqResult = await Api.PostAsync(requestUrl, req); + if (!reqResult.Succeeded) + return DataResult.Failed($"未能获取打印API生成的文件,请求地址:{requestUrl}"); + + string url = config["TaskMail:FileBaseUrl"] + @"/PrintTempFile/" + reqResult.Data.Data; + var fileResult = await Api.SendRequestAsync(HttpMethod.Get, url); + if (!fileResult.Succeeded) + return DataResult.Failed($"未能获取打印API生成的文件,附件地址:{url}"); + + string fileName = item.FileName.IsNullOrEmpty() ? Path.GetFileName(reqResult.Data.Data) : item.FileName; + var bytes = await fileResult.Data.Content.ReadAsByteArrayAsync(); + string base64Str = Convert.ToBase64String(bytes); + attachmentList.Add(new Tuple(fileName, base64Str)); + } + } + + dynamic[] mailParams = [new + { + SendTo = string.Join(",", receiverList.Select(x => x.Email)), + Title = title, + Body = content, + ShowName = senderConfig.ShowName.IsNullOrEmpty() ? sender.UserName : senderConfig.ShowName, + Account = senderConfig.MailAccount, + senderConfig.Password, + Server = senderConfig.SmtpServer, + Port = senderConfig.SmtpPort.GetValueOrDefault(), + UseSSL = senderConfig.SmtpSSL.GetValueOrDefault(), + Attaches = attachmentList.Select(x => new + { + AttachName = x.Item1, + AttachContent = x.Item2 + }).ToList() + }]; + var mailResult = await Api.SendRequestAsync(HttpMethod.Post, config["TaskMail:MailApiUrl"], mailParams); + + if (mailResult.Data.IsSuccessStatusCode) + { + return DataResult.Successed($"已发邮件(委托单:{templateModel.Primary.CustomerNo}),收件人:" + + string.Join(",", receiverList.Select(x => x.Email)) + "发件人:" + senderConfig.MailAccount); + } + + return DataResult.Failed($"邮件发送失败,API返回状态为:{(int)mailResult.Data.StatusCode} {mailResult.Data.StatusCode}" + +"(委托单:{templateModel.Primary.CustomerNo}),收件人:" + + string.Join(",", receiverList.Select(x => x.Email)) + + "发件人:" + senderConfig.MailAccount); + } + catch (Exception ex) + { + await ex.LogAsync(Db); + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.HttpRequestFailed)); + } + } + } +}