using Furion.DependencyInjection; using Furion.DynamicApiController; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Myshipping.Application.Entity; using Myshipping.Core.Entity; using Myshipping.Core.Service; using Myshipping.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Furion.FriendlyException; using NPOI.POIFS.Storage; using Yitter.IdGenerator; using Furion.DistributedIDGenerator; using System.Text.RegularExpressions; using Furion; using Myshipping.Application.Helper; using HtmlAgilityPack; using Myshipping.Application.ConfigOption; using Myshipping.Application.Enum; using System.IO; using StackExchange.Profiling.Internal; using Furion.JsonSerialization; using MySqlX.XDevAPI.Common; using Furion.RemoteRequest.Extensions; using Newtonsoft.Json; using System.Net.Http; using NPOI.Util; using System.Numerics; using SqlSugar; using System.Reflection.Metadata.Ecma335; using Microsoft.Extensions.Primitives; namespace Myshipping.Application { /// /// 货物运输计划已变更 /// [ApiDescriptionSettings("Application", Name = "TaskTransPlanHasChange", Order = 10)] public class TaskTransPlanHasChangeService : ITaskTransPlanHasChangeService, IDynamicApiController, ITransient { private readonly ISysCacheService _cache; private readonly ILogger _logger; private readonly SqlSugarRepository _taskBaseRepository; private readonly SqlSugarRepository _taskTransPlanHasChangeInfoRepository; private readonly SqlSugarRepository _taskTransPlanHasChangeDetailInfoRepository; private readonly SqlSugarRepository _djyUserMailAccount; private readonly SqlSugarRepository _bookingOrderRepository; private readonly SqlSugarRepository _bookingOrderContactRepository; private readonly SqlSugarRepository _sysUserRepository; private readonly SqlSugarRepository _repPrintTemplate; private readonly SqlSugarRepository _taskFileRepository; private readonly IDjyTenantParamService _djyTenantParamService; const string CONST_TRANS_PLAN_HAS_CHANGE_GROUP_CLIENT_EMAIL = "TRANS_PLAN_HAS_CHANGE_GROUP_CLIENT_EMAIL"; public TaskTransPlanHasChangeService(ISysCacheService cache, ILogger logger, SqlSugarRepository taskBaseRepository, SqlSugarRepository taskTransPlanHasChangeInfoRepository, SqlSugarRepository taskTransPlanHasChangeDetailInfoRepository, SqlSugarRepository djyUserMailAccount, SqlSugarRepository bookingOrderContactRepository, SqlSugarRepository sysUserRepository, SqlSugarRepository repPrintTemplate, SqlSugarRepository taskFileRepository, IDjyTenantParamService djyTenantParamService, SqlSugarRepository bookingOrderRepository) { _cache = cache; _logger = logger; _taskBaseRepository = taskBaseRepository; _taskTransPlanHasChangeInfoRepository = taskTransPlanHasChangeInfoRepository; _taskTransPlanHasChangeDetailInfoRepository = taskTransPlanHasChangeDetailInfoRepository; _djyUserMailAccount = djyUserMailAccount; _bookingOrderRepository = bookingOrderRepository; _bookingOrderContactRepository = bookingOrderContactRepository; _sysUserRepository = sysUserRepository; _repPrintTemplate = repPrintTemplate; _taskFileRepository = taskFileRepository; _djyTenantParamService = djyTenantParamService; } #region 获取货物运输计划已变更详情 /// /// 获取货物运输计划已变更详情 /// /// 货物运输计划已变更任务主键 /// 返回详情 [HttpGet("/TaskTransPlanHasChange/GetInfoByTaskId")] public async Task GetInfoByTaskId(string taskPkId) { return InnerGetInfo(taskPkId); } #endregion #region 获取货物运输计划已变更详情(内部方法) /// /// 获取货物运输计划已变更详情(内部方法) /// /// 货物运输计划已变更任务主键 /// private TaskTransPlanHasChangeShowDto InnerGetInfo(string taskPkId) { TaskTransPlanHasChangeShowDto dto = new TaskTransPlanHasChangeShowDto(); var taskBase = _taskBaseRepository.AsQueryable().Filter(null, true).First(a => a.PK_ID == taskPkId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息"); var entityInfo = _taskTransPlanHasChangeInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskBase.PK_ID); if (entityInfo == null) throw Oops.Oh($"货物运输计划已变更主键{taskPkId}无法获取业务信息"); dto.BillNo = entityInfo.MBL_NO; dto.BookingNo = entityInfo.BOOKING_NO; dto.Carrier = entityInfo.CARRIER; dto.OrigBillNo = entityInfo.ORIG_MBL_NO; dto.TaskPkId = entityInfo.TASK_ID; dto.PKId = entityInfo.PK_ID; dto.BookingId = entityInfo.BOOKING_ID; dto.ChangeReasonNotes = entityInfo.CHANGE_REASON; dto.GroupBatchNo = entityInfo.GROUP_BATCH_NO; dto.IsLast = entityInfo.IS_LAST; var detailList = _taskTransPlanHasChangeDetailInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.P_ID == entityInfo.PK_ID).ToList(); if (detailList.Count > 0) { var ctnList = detailList.Where(a => a.COLUMN_TYPE.Equals("CTN", StringComparison.OrdinalIgnoreCase)).ToList(); dto.ContaNoList = ctnList.Select(a => a.CONTA_NO).ToList(); var fromList = detailList.Where(a => !string.IsNullOrWhiteSpace(a.PLAN_TYPE) && a.PLAN_TYPE.Equals("FROM", StringComparison.OrdinalIgnoreCase)).ToList(); dto.From = new TaskTransportPlanHasChangeDetailShow { portList = new List(), dateList = new List(), vesselList = new List() }; dto.From.portList = fromList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("PORT", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangePortShow { Indx = a.SORT_NO, PortName = a.PORTLOAD, CountryCode = a.PORTLOAD_COUNTRY, TerminalName = a.PORTLOAD_TERMINAL, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); dto.From.dateList = fromList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("EATD", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangeDateShow { Indx = a.SORT_NO, DateVal = a.ETD, IsRemoved = a.IS_REMOVED, }; }).OrderBy(a => a.Indx).ToList(); dto.From.vesselList = fromList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("VESSEL", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangeVesselShow { Indx = a.SORT_NO, Vessel = a.VESSEL, Voyno = a.VOYNO, Flag = a.SHIP_FLAG, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); var toList = detailList.Where(a => !string.IsNullOrWhiteSpace(a.PLAN_TYPE) && a.PLAN_TYPE.Equals("TO", StringComparison.OrdinalIgnoreCase)).ToList(); dto.To = new TaskTransportPlanHasChangeDetailShow { portList = new List(), dateList = new List(), vesselList = new List() }; dto.To.portList = toList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("PORT", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangePortShow { Indx = a.SORT_NO, PortName = a.PORTDISCHARGE, CountryCode = a.PORTDISCHARGE_COUNTRY, TerminalName = a.PORTDISCHARGE_TERMINAL, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); dto.To.dateList = toList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("EATD", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangeDateShow { Indx = a.SORT_NO, DateVal = a.ETA, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); dto.To.vesselList = toList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("VESSEL", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangeVesselShow { Indx = a.SORT_NO, Vessel = a.VESSEL, Voyno = a.VOYNO, Flag = a.SHIP_FLAG, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); } return dto; } #endregion #region 自动转发货物运输计划已变更 /// /// 自动转发货物运输计划已变更 /// /// 货物运输计划已变更任务主键 /// 返回回执 [HttpGet("/TaskTransPlanHasChange/AutoTransferNotice")] public async Task AutoTransferNotice(string taskPKId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var queryRlt = QueryBookingOrder(taskPKId); _logger.LogInformation($"taskPKId={taskPKId} 检索对应的订舱记录完成,结果:{JSON.Serialize(queryRlt)}"); //_logger.LogInformation($"taskPKId={taskPKId} 当前租户未开启货物运输计划已变更是否同批次同客户合并邮件通知,按照单票推送邮件处理"); //如果没有配置批量,则按单票发送邮件 var rlt = SendEmailToCustomer(taskPKId); _logger.LogInformation($"taskPKId={taskPKId} 推送邮件完成,结果:{JSON.Serialize(rlt)}"); } catch (Exception ex) { result.succ = false; result.msg = $"自动转发货物运输计划已变更失败,原因:{ex.Message}"; _logger.LogInformation($"taskPKId={taskPKId} 自动转发货物运输计划已变更失败,原因:{ex.Message}"); } return result; } #endregion #region 按照列表批次号提取同批次货物运输计划已变更记录 /// /// 按照列表批次号提取同批次货物运输计划已变更记录 /// /// 列表批次号 /// [NonAction] private List GetListByGroupBatchNo(string groupBatchNo) { List list = new List(); var dataList = _taskTransPlanHasChangeInfoRepository.AsQueryable().Filter(null, true) .InnerJoin((plan, detail) => plan.PK_ID == detail.P_ID) .Where((plan, detail) => plan.GROUP_BATCH_NO == groupBatchNo && plan.IsDeleted == false) .Select((plan, detail) => new { Plan = plan, Detail = detail }).ToList(); if (dataList.Count > 0) { list = dataList.GroupBy(a => a.Plan.PK_ID).Select(a => { var currList = a.ToList(); var entityInfo = a.FirstOrDefault().Plan; var detailList = a.Select(b => b.Detail).ToList(); TaskTransPlanHasChangeShowDto dto = new TaskTransPlanHasChangeShowDto(); dto.BillNo = entityInfo.MBL_NO; dto.BookingNo = entityInfo.BOOKING_NO; dto.Carrier = entityInfo.CARRIER; dto.OrigBillNo = entityInfo.ORIG_MBL_NO; dto.TaskPkId = entityInfo.TASK_ID; dto.PKId = entityInfo.PK_ID; dto.BookingId = entityInfo.BOOKING_ID; dto.ChangeReasonNotes = entityInfo.CHANGE_REASON; dto.GroupBatchNo = entityInfo.GROUP_BATCH_NO; dto.IsLast = entityInfo.IS_LAST; var ctnList = detailList.Where(a => a.COLUMN_TYPE.Equals("CTN", StringComparison.OrdinalIgnoreCase)).ToList(); dto.ContaNoList = ctnList.Select(a => a.CONTA_NO).ToList(); var fromList = detailList.Where(a => !string.IsNullOrWhiteSpace(a.PLAN_TYPE) && a.PLAN_TYPE.Equals("FROM", StringComparison.OrdinalIgnoreCase)).ToList(); dto.From = new TaskTransportPlanHasChangeDetailShow { portList = new List(), dateList = new List(), vesselList = new List() }; dto.From.portList = fromList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("PORT", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangePortShow { Indx = a.SORT_NO, PortName = a.PORTLOAD, CountryCode = a.PORTLOAD_COUNTRY, TerminalName = a.PORTLOAD_TERMINAL, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); dto.From.dateList = fromList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("EATD", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangeDateShow { Indx = a.SORT_NO, DateVal = a.ETD, IsRemoved = a.IS_REMOVED, }; }).OrderBy(a => a.Indx).ToList(); dto.From.vesselList = fromList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("VESSEL", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangeVesselShow { Indx = a.SORT_NO, Vessel = a.VESSEL, Voyno = a.VOYNO, Flag = a.SHIP_FLAG, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); var toList = detailList.Where(a => !string.IsNullOrWhiteSpace(a.PLAN_TYPE) && a.PLAN_TYPE.Equals("TO", StringComparison.OrdinalIgnoreCase)).ToList(); dto.To = new TaskTransportPlanHasChangeDetailShow { portList = new List(), dateList = new List(), vesselList = new List() }; dto.To.portList = toList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("PORT", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangePortShow { Indx = a.SORT_NO, PortName = a.PORTDISCHARGE, CountryCode = a.PORTDISCHARGE_COUNTRY, TerminalName = a.PORTDISCHARGE_TERMINAL, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); dto.To.dateList = toList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("EATD", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangeDateShow { Indx = a.SORT_NO, DateVal = a.ETA, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); dto.To.vesselList = toList.Where(a => !string.IsNullOrWhiteSpace(a.COLUMN_TYPE) && a.COLUMN_TYPE.Equals("VESSEL", StringComparison.OrdinalIgnoreCase)) .Select(a => { return new TaskTransPlanHasChangeVesselShow { Indx = a.SORT_NO, Vessel = a.VESSEL, Voyno = a.VOYNO, Flag = a.SHIP_FLAG, IsRemoved = a.IS_REMOVED }; }).OrderBy(a => a.Indx).ToList(); return dto; }).ToList(); } return list; } #endregion #region 检索对应的订舱订单 /// /// 检索对应的订舱订单 /// /// 货物运输计划已变更任务主键 /// 返回回执 [HttpGet("/TaskTransPlanHasChange/QueryBookingOrder")] public async Task QueryBookingOrder(string taskPKId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var taskBase = _taskBaseRepository.AsQueryable().Filter(null,true).First(a => a.PK_ID == taskPKId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息"); var entityInfo = _taskTransPlanHasChangeInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskBase.PK_ID); if (entityInfo == null) throw Oops.Oh($"货物运输计划已变更主键{taskPKId}无法获取业务信息"); //通过船名航次取是主单的订舱记录列表 var bookingInfo = _bookingOrderRepository.AsQueryable().Filter(null, true).First(a => a.MBLNO == entityInfo.MBL_NO && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0) && a.TenantId == UserManager.TENANT_ID); if (bookingInfo != null) { entityInfo.BOOKING_ID = bookingInfo.Id; entityInfo.UpdatedTime = DateTime.Now; entityInfo.UpdatedUserId = UserManager.UserId; entityInfo.UpdatedUserName = UserManager.Name; await _taskTransPlanHasChangeInfoRepository.AsUpdateable(entityInfo).UpdateColumns(x=>new { x.BOOKING_ID, x.UpdatedTime, x.UpdatedUserId, x.UpdatedUserName }).ExecuteCommandAsync(); result.succ = true; result.msg = "检索对应成功"; } else { result.succ = false; result.msg = $"检索对应失败,提单号:{entityInfo.MBL_NO} 没有对应的订舱记录"; } } catch (Exception ex) { result.succ = false; result.msg = $"检索失败,原因:{ex.Message}"; _logger.LogInformation($"taskPKId={taskPKId} 检索货物运输计划已变更订舱记录 处理异常,原因:{ex.Message}"); } return result; } #endregion #region 发送邮件通知给客户 /// /// 发送邮件通知给客户 /// /// 货物运输计划已变更主键 /// 返回回执 [HttpGet("/TaskTransPlanHasChange/taskPKId")] public async Task SendEmailToCustomer(string taskPKId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { TaskTransPlanHasChangeShowDto dto = InnerGetInfo(taskPKId); if (!dto.BookingId.HasValue) { //new EmailNoticeHelper().SendEmailNotice($"taskid={taskPKId} mblno={dto.BillNo} 货物运输计划已变更 转发通知邮件失败", $"taskid={taskPKId} mblno={dto.BillNo} 当前任务没有对应的订舱订单,不能转发邮件,请先检索对应的订舱订单", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); throw Oops.Oh($"当前任务没有对应的订舱订单,不能转发邮件,请先检索对应的订舱订单"); } var bookingOrderList = _bookingOrderRepository.AsQueryable().Filter(null, true).Where(a => a.Id == dto.BookingId.Value && a.IsDeleted == false && a.TenantId == UserManager.TENANT_ID).ToList(); if (bookingOrderList.Count == 0) { new EmailNoticeHelper().SendEmailNotice($"taskid={taskPKId} mblno={dto.BillNo} 货物运输计划已变更 转发通知邮件失败", $"taskid={taskPKId} mblno={dto.BillNo} 当前任务对应的订舱订单不存在或已作废", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); throw Oops.Oh($"当前任务对应的订舱订单不存在或已作废"); } var bookingId = dto.BookingId.Value; var bookingContactList = _bookingOrderContactRepository.AsQueryable().Filter(null, true) .Where(a => bookingId == a.BookingId.Value && a.IsDeleted == false).ToList(); result = await GenerateSendEmail(dto, bookingOrderList, bookingContactList); var model = _taskTransPlanHasChangeInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskPKId); if (model != null) { model.IS_TRANSFER_USER = true; model.LST_STATUS = result.succ ? "SUCC" : "FAILURE"; model.LST_STATUS_NAME = result.succ ? "成功" : "失败"; model.LST_TRANSFER_USER_DATE = DateTime.Now; model.LST_TRANSFER_NOTES = result.msg; await _taskTransPlanHasChangeInfoRepository.AsUpdateable(model).UpdateColumns(x => new { x.LST_TRANSFER_NOTES, x.LST_TRANSFER_USER_DATE, x.LST_STATUS, x.LST_STATUS_NAME, x.IS_TRANSFER_USER }).ExecuteCommandAsync(); } } catch (Exception ex) { result.succ = false; result.msg = $"发送邮件失败,原因:{ex.Message}"; } return result; } #endregion #region 生成并转发通知邮件 /// /// 生成并转发通知邮件 /// /// /// /// /// /// [NonAction] private async Task GenerateSendEmail(TaskTransPlanHasChangeShowDto model, List bookingOrderList, List bookingContactList) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { //TO 邮件接收人 string toEmail = string.Empty; //订舱OP的邮箱 string opEmail = string.Empty; //去重客户联系人的邮箱 toEmail = string.Join(";", bookingContactList.Select(x => x.Email.Trim()).Distinct().ToArray()); List opEmailList = new List(); SysUser opUserInfo = null; bookingOrderList.ForEach(bk => { //获取操作OP的邮箱 if (!string.IsNullOrWhiteSpace(bk.OPID)) { var opId = long.Parse(bk.OPID); var opUser = _sysUserRepository.AsQueryable().Filter(null, true).First(a => a.Id == opId); if (opUser != null) { if (opUserInfo == null) opUserInfo = opUser; if (!string.IsNullOrWhiteSpace(opUser.Email)) { opEmailList.Add(opUser.Email.Trim()); _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 获取操作OP的邮箱,opEmail={opEmail} opid={opId} name={opUser.Name}"); } else { _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 获取操作OP的邮箱失败,opEmail={opUser.Email} opid={opId} name={opUser.Name}"); } } else { _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 检索操作OP信息失败,opid={opId} name={opUser.Name}"); } } //获取客服的邮箱 if (!string.IsNullOrWhiteSpace(bk.CUSTSERVICEID)) { var opId = long.Parse(bk.CUSTSERVICEID); var opUser = _sysUserRepository.AsQueryable().Filter(null, true).First(a => a.Id == opId); if (opUser != null) { if (!string.IsNullOrWhiteSpace(opUser.Email)) { opEmailList.Add(opUser.Email.Trim()); _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 获取客服的邮箱,opEmail={opEmail} opid={opId} name={opUser.Name}"); } else { _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 获取客服的邮箱失败,opEmail={opUser.Email} opid={opId} name={opUser.Name}"); } } else { _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 检索客服信息失败,opid={opId} name={opUser.Name}"); } } }); if (opEmailList.Count > 0) opEmail = string.Join(";", opEmailList.Distinct().ToArray()); string emailTitle = $"您的货物运输计划已变更:{model.BillNo}"; //提取当前公共邮箱的配置 DjyUserMailAccount publicMailAccount = _djyUserMailAccount.AsQueryable().Filter(null, true).First(x => x.TenantId == UserManager.TENANT_ID && x.ShowName == "PublicSend" && x.SmtpPort > 0 && x.SmtpServer != null && x.SmtpServer != ""); _logger.LogInformation($"提取当前公共邮箱的配置完成,id={publicMailAccount.Id}"); if (publicMailAccount == null) { throw Oops.Oh($"提取公共邮箱配置失败,请在用户邮箱账号管理增加配置显示名为PublicSend或者配置个人邮箱"); } //获取邮件模板 var printTemplate = _repPrintTemplate.AsQueryable().Filter(null, true).First(x => x.CateCode.Contains("trans_plan_has_change") && x.TenantId == UserManager.TENANT_ID); if (printTemplate == null) { throw Oops.Bah(BookingErrorCode.BOOK115); } //读取邮件模板并填充数据 string emailHtml = GenerateSendEmailHtml(model, bookingOrderList, printTemplate.FilePath, opUserInfo, UserManager.TENANT_NAME).GetAwaiter().GetResult(); EmailApiUserDefinedDto emailApiUserDefinedDto = new EmailApiUserDefinedDto { SendTo = toEmail, //CCTo = opEmail, Title = emailTitle, Body = emailHtml, Account = publicMailAccount.MailAccount?.Trim(), Password = publicMailAccount.Password?.Trim(), Server = publicMailAccount.SmtpServer?.Trim(), Port = publicMailAccount.SmtpPort.HasValue ? publicMailAccount.SmtpPort.Value : 465, UseSSL = publicMailAccount.SmtpSSL.HasValue ? publicMailAccount.SmtpSSL.Value : true, Attaches = new List() }; _logger.LogInformation($"生成请求邮件参数,结果:{JSON.Serialize(emailApiUserDefinedDto)}"); //推送邮件 var emailRlt = await PushEmail(emailApiUserDefinedDto); _logger.LogInformation($"推送邮件完成,结果:{JSON.Serialize(emailRlt)}"); if (emailRlt.succ) { result.succ = true; result.msg = "成功"; } else { result.succ = false; result.msg = emailRlt.msg; new EmailNoticeHelper().SendEmailNotice($"taskid={model.TaskPkId} 货物运输计划已变更 转发通知邮件失败", $"taskid={model.TaskPkId} 转发通知邮件失败,原因:{emailRlt.msg}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } } catch (Exception ex) { result.succ = false; result.msg = $"失败,原因:{ex.Message}"; new EmailNoticeHelper().SendEmailNotice($"taskid={model.TaskPkId} 货物运输计划已变更 转发通知邮件失败", $"taskid={model.TaskPkId} 转发通知邮件失败,原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } return result; } #endregion #region 通过邮件模板生成HTML /// /// 通过邮件模板生成HTML /// /// /// /// /// /// /// [NonAction] private async Task GenerateSendEmailHtml(TaskTransPlanHasChangeShowDto model, List bookingOrderList, string filePath, SysUser opUserInfo, string tenantName) { string result = string.Empty; string baseHtml = string.Empty; try { var opt = App.GetOptions(); var dirAbs = opt.basePath; if (string.IsNullOrEmpty(dirAbs)) { dirAbs = App.WebHostEnvironment.WebRootPath; } var fileAbsPath = Path.Combine(dirAbs, filePath); _logger.LogInformation($"查找模板文件:{fileAbsPath}"); if (!File.Exists(fileAbsPath)) { throw Oops.Bah(BookingErrorCode.BOOK115); } baseHtml = File.ReadAllText(fileAbsPath); if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Name)) { baseHtml = baseHtml.Replace("#opname#", opUserInfo.Name); } else { baseHtml = baseHtml.Replace("#opname#", "操作"); } if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Email)) { baseHtml = baseHtml.Replace("#opemail#", opUserInfo.Email); } else { baseHtml = baseHtml.Replace("#opemail#", ""); } if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Phone)) { baseHtml = baseHtml.Replace("#optel#", opUserInfo.Phone); } else if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Tel)) { baseHtml = baseHtml.Replace("#optel#", opUserInfo.Tel); } else { baseHtml = baseHtml.Replace("#optel#", ""); } if (!string.IsNullOrWhiteSpace(model.BillNo)) { baseHtml = baseHtml.Replace("#BillNo#", model.BillNo); } else { baseHtml = baseHtml.Replace("#BillNo#", ""); } if (!string.IsNullOrWhiteSpace(model.BookingNo)) { baseHtml = baseHtml.Replace("#BookingNo#", model.BookingNo); } else { baseHtml = baseHtml.Replace("#BookingNo#", ""); } if (model.ContaNoList != null && model.ContaNoList.Count > 0) { baseHtml = baseHtml.Replace("#ContaNo#", string.Join(",", model.ContaNoList.ToArray())); } else { baseHtml = baseHtml.Replace("#ContaNo#", ""); } if (!string.IsNullOrWhiteSpace(model.OrigBillNo)) { baseHtml = baseHtml.Replace("#OrigBillName#", "此订舱号派生自原单号"); baseHtml = baseHtml.Replace("#OrigBillNo#", model.OrigBillNo); } else { baseHtml = baseHtml.Replace("#OrigBillName#", ""); baseHtml = baseHtml.Replace("#OrigBillNo#", ""); } if (!string.IsNullOrWhiteSpace(model.ChangeReasonNotes)) { baseHtml = baseHtml.Replace("#Reason#", model.ChangeReasonNotes); } else { baseHtml = baseHtml.Replace("#Reason#", ""); } if (!string.IsNullOrWhiteSpace(tenantName)) { baseHtml = baseHtml.Replace("#TenantCompanyName#", tenantName); } else { baseHtml = baseHtml.Replace("#TenantCompanyName#", ""); } HtmlDocument html = new HtmlDocument(); html.LoadHtml(baseHtml); //From Port Start HtmlNode tdPortNode = html.DocumentNode.SelectSingleNode("//td[@id='FromPort']"); if (tdPortNode == null) throw Oops.Oh($"读取邮件模板格式错误,定位id='FromPort'失败"); StringBuilder portBuilder = new StringBuilder(); portBuilder.Append(""); int maxLens = (new int[] { model.From.portList.Count, model.From.dateList.Count, model.From.vesselList.Count }).Max(); model.From.portList.ForEach(x => { if (model.From.dateList.Count == 1) { portBuilder.Append(""); } else { portBuilder.Append(""); } }); if (model.From.portList.Count < maxLens) { for (int p = 0; p < (maxLens - model.From.portList.Count); p++) { portBuilder.Append(""); } } portBuilder.Append("

" + (string.Concat(x.PortName, ",", x.CountryCode, ",", x.TerminalName)) + "

" + (string.Concat(x.PortName, ",", x.CountryCode, ",", x.TerminalName)) + "

"); //生成From Date的table列表 tdPortNode.ChildNodes.Add(HtmlNode.CreateNode(portBuilder.ToString())); //From Port End //From ETD Start HtmlNode tdDateNode = html.DocumentNode.SelectSingleNode("//td[@id='FromEADate']"); if (tdDateNode == null) throw Oops.Oh($"读取邮件模板格式错误,定位id='FromEADate'失败"); StringBuilder dateBuilder = new StringBuilder(); dateBuilder.Append(""); model.From.dateList.ForEach(x => { if (model.From.dateList.Count == 1) { dateBuilder.Append(""); } else { dateBuilder.Append(""); } }); if (model.From.dateList.Count < maxLens) { for (int p = 0; p < (maxLens - model.From.dateList.Count); p++) { dateBuilder.Append(""); } } dateBuilder.Append("

" + (x.DateVal.HasValue ? x.DateVal.Value.ToString("yyyy-MM-dd HH:mm:ss") : "") + "

" + (x.DateVal.HasValue ? x.DateVal.Value.ToString("yyyy-MM-dd HH:mm:ss") : "") + "

"); //生成From Port的table列表 tdDateNode.ChildNodes.Add(HtmlNode.CreateNode(dateBuilder.ToString())); //From ETD End //From Vessel Start HtmlNode tdVesselNode = html.DocumentNode.SelectSingleNode("//td[@id='FromVessel']"); if (tdVesselNode == null) throw Oops.Oh($"读取邮件模板格式错误,定位id='FromVessel'失败"); StringBuilder vesselBuilder = new StringBuilder(); vesselBuilder.Append(""); model.From.vesselList.ForEach(x => { if (model.From.vesselList.Count == 1) { vesselBuilder.Append(""); } else { vesselBuilder.Append(""); } }); if (model.From.vesselList.Count < maxLens) { for (int p = 0; p < (maxLens - model.From.vesselList.Count); p++) { vesselBuilder.Append(""); } } vesselBuilder.Append("

" + (string.Concat(x.Vessel, ",", x.Voyno, ",", x.Flag)) + "

" + (string.Concat(x.Vessel, ",", x.Voyno, ",", x.Flag)) + "

"); //生成From Port的table列表 tdVesselNode.ChildNodes.Add(HtmlNode.CreateNode(vesselBuilder.ToString())); //From Vessel Start //To Port Start HtmlNode tdPortNode2 = html.DocumentNode.SelectSingleNode("//td[@id='ToPort']"); if (tdPortNode2 == null) throw Oops.Oh($"读取邮件模板格式错误,定位id='ToPort'失败"); int maxLens2 = (new int[] { model.To.portList.Count, model.To.dateList.Count, model.To.vesselList.Count }).Max(); StringBuilder portBuilder2 = new StringBuilder(); portBuilder2.Append(""); model.To.portList.ForEach(x => { if(model.To.portList.Count == 1) { portBuilder2.Append(""); } else { portBuilder2.Append(""); } }); if (model.To.portList.Count < maxLens2) { for (int p = 0; p < (maxLens2 - model.To.portList.Count); p++) { portBuilder2.Append(""); } } portBuilder2.Append("

" + (string.Concat(x.PortName, ",", x.CountryCode, ",", x.TerminalName)) + "

" + (string.Concat(x.PortName, ",", x.CountryCode, ",", x.TerminalName)) + "

"); //生成To Port的table列表 tdPortNode2.ChildNodes.Add(HtmlNode.CreateNode(portBuilder2.ToString())); //To Port End //To ETD Start HtmlNode tdDateNode2 = html.DocumentNode.SelectSingleNode("//td[@id='ToEADate']"); if (tdDateNode2 == null) throw Oops.Oh($"读取邮件模板格式错误,定位id='ToEADate'失败"); StringBuilder dateBuilder2 = new StringBuilder(); dateBuilder2.Append(""); model.To.dateList.ForEach(x => { if (model.To.dateList.Count == 1) { dateBuilder2.Append(""); } else { dateBuilder2.Append(""); } }); if (model.To.dateList.Count < maxLens) { for (int p = 0; p < (maxLens2 - model.To.dateList.Count); p++) { dateBuilder2.Append(""); } } dateBuilder2.Append("

" + (x.DateVal.HasValue ? x.DateVal.Value.ToString("yyyy-MM-dd HH:mm:ss") : "") + "

" + (x.DateVal.HasValue ? x.DateVal.Value.ToString("yyyy-MM-dd HH:mm:ss") : "") + "

"); //生成From Date的table列表 tdDateNode2.ChildNodes.Add(HtmlNode.CreateNode(dateBuilder2.ToString())); //To ETD End //To Vessel Start HtmlNode tdVesselNode2 = html.DocumentNode.SelectSingleNode("//td[@id='ToVessel']"); if (tdVesselNode2 == null) throw Oops.Oh($"读取邮件模板格式错误,定位id='FromVessel'失败"); StringBuilder vesselBuilder2 = new StringBuilder(); vesselBuilder2.Append(""); model.To.vesselList.ForEach(x => { if (model.To.vesselList.Count == 1) { vesselBuilder2.Append(""); } else { vesselBuilder2.Append(""); } }); if (model.To.vesselList.Count < maxLens) { for (int p = 0; p < (maxLens2 - model.To.vesselList.Count); p++) { vesselBuilder2.Append(""); } } vesselBuilder2.Append("

" + (string.Concat(x.Vessel, ",", x.Voyno, ",", x.Flag)) + "

" + (string.Concat(x.Vessel, ",", x.Voyno, ",", x.Flag)) + "

"); //生成From Vessel的table列表 tdVesselNode2.ChildNodes.Add(HtmlNode.CreateNode(vesselBuilder2.ToString())); //To Vessel Start result = html.DocumentNode.OuterHtml; } catch (Exception ex) { _logger.LogInformation($"生成货物运输计划已变更正文失败,原因:{ex.Message}"); throw Oops.Bah($"生成货物运输计划已变更正文失败,原因:{ex.Message}"); } return result; } #endregion #region 推送邮件 /// /// 推送邮件 /// /// 自定义邮件详情 /// 文件路径 /// 返回回执 [NonAction] private async Task PushEmail(EmailApiUserDefinedDto emailApiUserDefinedDto) { CommonWebApiResult result = new CommonWebApiResult { succ = true }; List emailList = new List(); var emailUrl = _cache.GetAllDictData().GetAwaiter().GetResult() .FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == "email_api_url")?.Value; if (emailUrl == null) throw Oops.Bah("字典未配置 url_set->email_api_url 请联系管理员"); emailList.Add(emailApiUserDefinedDto); //string strJoin = System.IO.File.ReadAllText(filePath); DateTime bDate = DateTime.Now; HttpResponseMessage res = null; try { res = await emailUrl.SetBody(emailList, "application/json").PostAsync(); } catch (Exception ex) { _logger.LogInformation($"发送邮件异常:{ex.Message}"); } DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.LogInformation($"发送邮件返回:{JSON.Serialize(res)}"); if (res != null && res.StatusCode == System.Net.HttpStatusCode.OK) { var userResult = await res.Content.ReadAsStringAsync(); var respObj = JsonConvert.DeserializeAnonymousType(userResult, new { Success = false, Message = string.Empty, Code = -9999, }); result.succ = respObj.Success; result.msg = respObj.Message; } return result; } #endregion } }