using DS.Module.Core; using DS.Module.RedisModule; using DS.Module.SqlSugar; using DS.Module.UserModule; using DS.WMS.Core.Code.Interface; using DS.WMS.Core.Code.Method; using DS.WMS.Core.Map.Interface; using DS.WMS.Core.Map.Method; using DS.WMS.Core.Sys.Interface; using DS.WMS.Core.Sys.Method; using DS.WMS.Core.TaskPlat.Dtos; using DS.WMS.Core.TaskPlat.Entity; using DS.WMS.Core.TaskPlat.Interface; using Microsoft.Extensions.DependencyInjection; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Mapster; using DS.Module.DjyServiceStatus; using Microsoft.AspNetCore.Identity; using DS.WMS.Core.Op.Interface; using Masuit.Tools; using DS.WMS.Core.Op.Dtos; using DS.WMS.Core.Sys.Entity; using HtmlAgilityPack; using Microsoft.AspNetCore.Mvc; using Amazon.Runtime.Internal.Util; using Newtonsoft.Json; using NLog; using DS.Module.Core.Helpers; using System.Text.Json.Nodes; using LanguageExt.Pipes; using DS.WMS.Core.Op.Entity; using Org.BouncyCastle.Asn1.X9; using DS.WMS.Core.Op.EDI; using DS.WMS.Core.Sys.Dtos; using DS.WMS.Core.Code.Dtos; using DS.Module.Core.Data; namespace DS.WMS.Core.TaskPlat.Method { /// /// 截止时间变更 /// public class TaskManageCutDateChangeService: ITaskManageCutDateChangeService { private readonly IServiceProvider _serviceProvider; private readonly ISqlSugarClient db; private readonly IUser user; private readonly ISaasDbService saasService; private readonly ISeaExportService _seaExportService; private readonly IConfigService _configService; private readonly IUserService _userService; private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger(); const string EMAIL_API_URL = "email_api_url"; public TaskManageCutDateChangeService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; db = _serviceProvider.GetRequiredService(); user = _serviceProvider.GetRequiredService(); saasService = _serviceProvider.GetRequiredService(); _seaExportService = _serviceProvider.GetRequiredService(); _configService = _serviceProvider.GetRequiredService(); _userService = _serviceProvider.GetRequiredService(); } #region 通过任务主键获取截止时间变更详情 /// /// 通过任务主键获取截止时间变更详情 /// /// 截止时间变更任务主键 /// 返回回执 public async Task>> GetInfoByTaskId(long taskPKId) { List list = new List(); var tenantDb = saasService.GetBizDbScopeById(user.TenantId); //任务不考虑OrgId,这里去掉 tenantDb.QueryFilter.Clear(); var queryList = await tenantDb.Queryable() .InnerJoin((a, b) => a.Id == b.TASK_ID) .Where((a, b) => a.Id == taskPKId) .Select((a, b) => new { Base = a, Cut = b }) .ToListAsync(); //任务主键{taskPkId}无法获取业务信息 if (queryList.Count == 0) throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBaseInfoFromTaskIdNull)), taskPKId)); var parentIdList = queryList.Select(a => a.Cut.Id).ToList(); var detailList = await tenantDb.Queryable() .Where(a => parentIdList.Contains(a.P_ID)).ToListAsync(); if (detailList.Count > 0) { list = detailList.OrderBy(p => p.MBL_NO).Select(p => { TaskCutDateChangeShowDto model = p.Adapt(); model.NoticeDate = queryList.FirstOrDefault().Cut.NOTICE_DATE; model.Carrier = queryList.FirstOrDefault().Cut.CARRIER; return model; }).ToList(); } return DataResult>.Success(list); } #endregion #region 检索对应的订舱订单并保存订舱ID /// /// 检索对应的订舱订单并保存订舱ID /// /// 截止时间变更任务主键 /// 返回回执 public async Task> SearchAndMarkBookingOrder(long taskPKId) { SeaExportOrderExtension orderInfo = null; try { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); //任务不考虑OrgId,这里去掉 tenantDb.QueryFilter.Clear(); var queryList = await tenantDb.Queryable() .InnerJoin((a, b) => a.Id == b.TASK_ID) .Where((a, b) => a.Id == taskPKId) .Select((a, b) => new { Base = a, Cut = b }) .ToListAsync(); //任务主键{taskPkId}无法获取业务信息 if (queryList.Count == 0) throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBaseInfoFromTaskIdNull)), taskPKId)); string mblNo = queryList.FirstOrDefault().Base.MBL_NO; var orderRlt = await _seaExportService.SearchOrderInfo(mblNo); if (!orderRlt.Succeeded) { // 提单号 {0} 检索海运出口订单失败 throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBaseSearchOrderFailMBLNo)), mblNo)); } orderInfo = orderRlt.Data; foreach (var item in queryList.Select(a => a.Cut).ToList()) { item.BOOKING_ID = orderInfo.currOrder.Id; item.UpdateTime = DateTime.Now; item.UpdateBy = long.Parse(user.UserId); item.UpdateUserName = user.UserName; tenantDb.Updateable(item).UpdateColumns(x => new { x.BOOKING_ID, x.UpdateTime, x.UpdateBy, x.UpdateUserName }).ExecuteCommand(); var list = tenantDb.Queryable().Where(a => a.P_ID == item.Id).ToList(); if (list != null && list.Count > 0) { list.ForEach(async p => { if (p.MBL_NO.Equals(item.MBL_NO, StringComparison.OrdinalIgnoreCase)) { p.BOOKING_ID = orderInfo.currOrder.Id; p.UpdateTime = DateTime.Now; p.UpdateBy = long.Parse(user.UserId); p.UpdateUserName = user.UserName; await tenantDb.Updateable(p).UpdateColumns(x => new { x.BOOKING_ID, x.UpdateTime, x.UpdateBy, x.UpdateUserName }).ExecuteCommandAsync(); } }); } } } catch (Exception ex) { Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 检索截止时间变更订舱记录 处理异常,原因:{ex.Message}"); return DataResult.FailedData(orderInfo,$"检索失败,原因:{ex.Message}", MultiLanguageConst.Operation_Failed); } return DataResult.Success(orderInfo); } #endregion #region 自动更新订单的截单日期并转发 /// /// 自动更新订单的截单日期并转发 /// /// 截止时间变更任务主键 /// 返回回执 public async Task AutoUpdateOrderCutDateAndTranmitToCustomer(long taskPKId) { SeaExportOrderExtension orderInfo = null; try { var queryRlt = await SearchAndMarkBookingOrder(taskPKId); if (!queryRlt.Succeeded) { throw new Exception(queryRlt.Message); } orderInfo = queryRlt.Data; //更新海运出口截单时间 var orderRlt = UpdateBookingOrderCutDate(taskPKId, orderInfo); //更新舱位的截单时间 var slotRlt = UpdateBookingSlotCutDate(taskPKId, orderInfo); //如果没有配置批量,则按单票发送邮件 var rlt = await SendEmailToCustomer(taskPKId); Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 推送邮件完成,结果:{JsonConvert.SerializeObject(rlt)}"); } catch(Exception ex) { Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 自动更新订单的截单日期并转发失败异常,原因:{ex.Message}"); return DataResult.Failed( $"自动更新订单的截单日期并转发失败,原因:{ex.Message}", MultiLanguageConst.Operation_Failed); } return DataResult.Successed(string.Empty, MultiLanguageConst.OperationSuccess); } #endregion #region 更新订舱截单时间 /// /// 更新订舱截单时间 /// /// 任务主键 /// 相关海运出口订舱详情 /// 返回回执 private async Task UpdateBookingOrderCutDate(long taskPKId, SeaExportOrderExtension orderInfo) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); //任务不考虑OrgId,这里去掉 tenantDb.QueryFilter.Clear(); try { var queryList = await tenantDb.Queryable() .InnerJoin((a, b) => a.Id == b.TASK_ID) .Where((a, b) => a.Id == taskPKId) .Select((a, b) => new { Base = a, Cut = b }) .ToListAsync(); //任务主键{taskPkId}无法获取业务信息 if (queryList.Count == 0) throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBaseInfoFromTaskIdNull)), taskPKId)); List ids = new List { orderInfo.currOrder.Id }; var cutBase = queryList.FirstOrDefault().Cut; var cutDetail = await tenantDb.Queryable().FirstAsync(a => a.P_ID == cutBase.Id); if (orderInfo.splitOrMergeFlag == 1) { if (orderInfo.otherOrderList.Count > 0) ids.AddRange(orderInfo.otherOrderList.Select(a => a.Id).ToList()); Logger.Log(NLog.LogLevel.Info, $"截止时间变更主键{taskPKId} MBLNO={cutDetail.MBL_NO} 检索海运出口订单匹配到拆票信息 ids={string.Join(",", ids.ToArray())}"); } foreach (var id in ids) { StringBuilder doBuilder = new StringBuilder(); var bookingInfo = await tenantDb.Queryable().FirstAsync(a => a.Id == id); if (bookingInfo != null) { if (cutDetail.VGM_CUT.HasValue) { doBuilder.Append($"VGM CUT 原:{bookingInfo.VGMCloseDate} 新:{cutDetail.VGM_CUT.Value}"); bookingInfo.VGMCloseDate = cutDetail.VGM_CUT.Value; } if (cutDetail.CY_CUTOFF.HasValue) { doBuilder.Append($"CY CUT 原:{bookingInfo.ClosingDate} 新:{cutDetail.CY_CUTOFF.Value}"); bookingInfo.ClosingDate = cutDetail.CY_CUTOFF.Value; } if (cutDetail.SI_CUTOFF.HasValue) { doBuilder.Append($"SI CUT 原:{bookingInfo.CloseDocDate} 新:{cutDetail.SI_CUTOFF.Value}"); bookingInfo.CloseDocDate = cutDetail.SI_CUTOFF.Value; } tenantDb.Updateable(bookingInfo).UpdateColumns(it => new { it.VGMCloseDate, it.ClosingDate, it.CloseDocDate }).ExecuteCommand(); Logger.Log(NLog.LogLevel.Info, $"截止时间变更主键{taskPKId} id={id} mblno={bookingInfo.MBLNO} 更新订舱完毕 详情 {doBuilder.ToString()}"); } } } catch(Exception ex) { Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 自动更新订单的截单日期更新订舱异常,原因:{ex.Message}"); return DataResult.Failed($"自动更新订单的截单日期更新订舱,原因:{ex.Message}", MultiLanguageConst.Operation_Failed); } return DataResult.Successed(string.Empty, MultiLanguageConst.OperationSuccess); } #endregion #region 更新舱位的截止时间 /// /// 更新舱位的截止时间 /// /// 任务主键 /// 相关海运出口订舱详情 /// 返回回执 private async Task UpdateBookingSlotCutDate(long taskPKId, SeaExportOrderExtension orderInfo) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); //任务不考虑OrgId,这里去掉 tenantDb.QueryFilter.Clear(); try { var queryList = await tenantDb.Queryable() .InnerJoin((a, b) => a.Id == b.TASK_ID) .Where((a, b) => a.Id == taskPKId) .Select((a, b) => new { Base = a, Cut = b }) .ToListAsync(); //任务主键{taskPkId}无法获取业务信息 if (queryList.Count == 0) throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBaseInfoFromTaskIdNull)), taskPKId)); var cutBase = queryList.FirstOrDefault().Cut; var cutDetail = await tenantDb.Queryable().FirstAsync(a => a.P_ID == cutBase.Id); var slotOrder = await tenantDb.Queryable().FirstAsync(a => a.SlotBookingNo == cutBase.MBL_NO); StringBuilder doBuilder = new StringBuilder(); if (slotOrder != null) { if (cutDetail.VGM_CUT.HasValue) { doBuilder.Append($"VGM CUT 原:{slotOrder.VGMSubmissionCutDate} 新:{cutDetail.VGM_CUT.Value}"); slotOrder.VGMSubmissionCutDate = cutDetail.VGM_CUT.Value; } if (cutDetail.CY_CUTOFF.HasValue) { doBuilder.Append($"CY CUT 原:{slotOrder.CYCutDate} 新:{cutDetail.CY_CUTOFF.Value}"); slotOrder.CYCutDate = cutDetail.CY_CUTOFF.Value; } if (cutDetail.SI_CUTOFF.HasValue) { doBuilder.Append($"SI CUT 原:{slotOrder.SICutDate} 新:{cutDetail.SI_CUTOFF.Value}"); slotOrder.SICutDate = cutDetail.SI_CUTOFF.Value; } if (cutDetail.MANIFEST_CUT.HasValue) { doBuilder.Append($"MANIFEST CUT 原:{slotOrder.ManifestCutDate} 新:{cutDetail.MANIFEST_CUT.Value}"); slotOrder.ManifestCutDate = cutDetail.MANIFEST_CUT.Value; } tenantDb.Updateable(slotOrder).UpdateColumns(it => new { it.VGMSubmissionCutDate, it.CYCutDate, it.SICutDate, it.ManifestCutDate }).ExecuteCommand(); Logger.Log(NLog.LogLevel.Info, $"截止时间变更主键{taskPKId} id={cutBase.Id} mblno={slotOrder.SlotBookingNo} 更新舱位完毕 详情 {doBuilder.ToString()}"); } } catch (Exception ex) { Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 自动更新订单的截单日期更新舱位异常,原因:{ex.Message}"); return DataResult.Failed($"自动更新订单的截单日期更新舱位,原因:{ex.Message}", MultiLanguageConst.Operation_Failed); } return DataResult.Successed(string.Empty, MultiLanguageConst.OperationSuccess); } #endregion #region 发送邮件通知给客户 /// /// 发送邮件通知给客户 /// /// 截止时间变更主键 /// 返回回执 public async Task SendEmailToCustomer(long taskPKId) { return null; } #endregion #region 生成并转发通知邮件 /// /// 生成并转发通知邮件 /// /// /// /// /// /// [NonAction] private async Task GenerateSendEmail(TaskCutDateChangeInfo model, List rowList, 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(); UserViewModel opUserInfo = null; bookingOrderList.ForEach(bk => { //获取操作OP的邮箱 if (bk.OperatorId > 0) { var opUser = _userService.GetUserInfo(bk.OperatorId.ToString()); if (opUser.Succeeded && opUser.Data != null) { if (opUserInfo == null) opUserInfo = opUser.Data; if (!string.IsNullOrWhiteSpace(opUserInfo.Email)) { opEmailList.Add(opUserInfo.Email.Trim()); Logger.Log(NLog.LogLevel.Info, $"id={bk.Id} mblno={bk.MBLNO} 获取操作OP的邮箱,opEmail={opEmail} opid={bk.OperatorId} name={opUserInfo.UserName}"); } else { Logger.Log(NLog.LogLevel.Info, $"id={bk.Id} mblno={bk.MBLNO} 获取操作OP的邮箱失败,opEmail={opUserInfo.Email} opid={bk.OperatorId} name={opUserInfo.UserName}"); } } else { Logger.Log(NLog.LogLevel.Info, $"id={bk.Id} mblno={bk.MBLNO} 检索操作OP信息失败,opid={bk.OperatorId} name={opUserInfo.UserName}"); } } //获取客服的邮箱 if (bk.CustomerService > 0) { var opUser = _userService.GetUserInfo(bk.CustomerService.ToString()); if (opUser.Succeeded && opUser.Data != null) { if (!string.IsNullOrWhiteSpace(opUser.Data.Email)) { opEmailList.Add(opUser.Data.Email.Trim()); Logger.Log(NLog.LogLevel.Info, $"id={bk.Id} mblno={bk.MBLNO} 获取客服的邮箱,opEmail={opEmail} opid={bk.CustomerService} name={opUser.Data.UserName}"); } else { Logger.Log(NLog.LogLevel.Info, $"id={bk.Id} mblno={bk.MBLNO} 获取客服的邮箱失败,opEmail={opUser.Data.Email} opid={bk.CustomerService} name={opUser.Data.UserName}"); } } else { Logger.Log(NLog.LogLevel.Info, $"id={bk.Id} mblno={bk.MBLNO} 检索客服信息失败,opid={bk.CustomerService} name={opUser.Data.UserName}"); } } }); if (opEmailList.Count > 0) opEmail = string.Join(";", opEmailList.Distinct().ToArray()); string emailTitle = $"{model.MBL_NO} Cut-off Details {model.VESSEL}/{model.VOYNO}/"; if (model.PORTLOAD_AREA.Equals("NORTH_PORT", StringComparison.OrdinalIgnoreCase)) { emailTitle = $"{model.MBL_NO} 截止时间变更 {model.VESSEL}/{model.VOYNO}/"; } ////提取当前公共邮箱的配置 //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.Log(NLog.LogLevel.Info, $"提取当前公共邮箱的配置完成,id={publicMailAccount.Id}"); //if (publicMailAccount == null) //{ // throw Oops.Oh($"提取公共邮箱配置失败,请在用户邮箱账号管理增加配置显示名为PublicSend或者配置个人邮箱"); //} ////获取邮件模板 //var printTemplate = _repPrintTemplate.AsQueryable().Filter(null, true).First(x => x.CateCode.Contains("for_information_cutoff_detail") && x.TenantId == UserManager.TENANT_ID); //if (printTemplate == null) //{ // throw Oops.Bah(BookingErrorCode.BOOK115); //} CodeUserEmailRes publicMailAccount = new CodeUserEmailRes(); //读取邮件模板并填充数据 string emailHtml = "";//await GenerateSendEmailHtml(model, rowList, bookingOrderList, "", opUserInfo, user.TenantName).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() }; //如果配置了租户参数(AUTO_TRANS_EMAIL_OP_CCTO-自动转发是否默认抄送操作=ENABLE)发送邮件时自动抄送操作 //DjyTenantParamValueOutput paramConfig = _djyTenantParamService.GetParaCodeWithValue(new[] { "AUTO_TRANS_EMAIL_OP_CCTO" }).GetAwaiter().GetResult().FirstOrDefault(); //if (paramConfig != null && paramConfig.ParaValue.Equals("ENABLE", StringComparison.OrdinalIgnoreCase)) //{ // emailApiUserDefinedDto.CCTo = opEmail; //} Logger.Log(NLog.LogLevel.Info, $"生成请求邮件参数,结果:{JsonConvert.SerializeObject(emailApiUserDefinedDto)}"); //推送邮件 var emailRlt = await PushEmail(emailApiUserDefinedDto); Logger.Log(NLog.LogLevel.Info, $"推送邮件完成,结果:{JsonConvert.SerializeObject(emailRlt)}"); if (emailRlt.Succeeded) { result.succ = true; result.msg = "成功"; } else { result.succ = false; result.msg = emailRlt.Message; //new EmailNoticeHelper().SendEmailNotice($"taskid={model.TASK_ID} 截止时间变更 转发通知邮件失败", $"taskid={model.TASK_ID} 转发通知邮件失败,原因:{emailRlt.msg}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } } catch (Exception ex) { result.succ = false; result.msg = $"失败,原因:{ex.Message}"; //new EmailNoticeHelper().SendEmailNotice($"taskid={model.TASK_ID} 截止时间变更 转发通知邮件失败", $"taskid={model.TASK_ID} 转发通知邮件失败,原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } return result; } #endregion #region 通过邮件模板生成HTML /// /// 通过邮件模板生成HTML /// /// 截止时间变更详情 /// 海运出口详情 /// 文件路径 /// 相关操作OP /// 租户全称 /// 返回HTML字符串(邮件正文) [NonAction] private async Task GenerateSendEmailHtml(TaskCutDateChangeInfo model, List rowList, SeaExportRes seaExportRes, string filePath, SysUser opUserInfo, string tenantName,string fileAbsPath) { 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.UserName)) { baseHtml = baseHtml.Replace("#opname#", opUserInfo.UserName); } 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.MBL_NO)) { baseHtml = baseHtml.Replace("#BillNo#", model.MBL_NO); } else { baseHtml = baseHtml.Replace("#BillNo#", ""); } if (!string.IsNullOrWhiteSpace(model.VESSEL)) { string s = $"{model.VESSEL}/{model.VOYNO}"; baseHtml = baseHtml.Replace("#VesselVoyno#", s); } else { baseHtml = baseHtml.Replace("#VesselVoyno#", ""); } var detailInfo = rowList.FirstOrDefault(); if (detailInfo.SI_CUTOFF.HasValue) { baseHtml = baseHtml.Replace("#SICutDate#", detailInfo.SI_CUTOFF.Value.ToString("yyyy-MM-dd HH:mm")); } else { baseHtml = baseHtml.Replace("#SICutDate#", ""); } if (detailInfo.VGM_CUT.HasValue) { baseHtml = baseHtml.Replace("#VGMCutDate#", detailInfo.VGM_CUT.Value.ToString("yyyy-MM-dd HH:mm")); } else { baseHtml = baseHtml.Replace("#VGMCutDate#", ""); } if (detailInfo.CY_CUTOFF.HasValue) { baseHtml = baseHtml.Replace("#CYCutDate#", detailInfo.CY_CUTOFF.Value.ToString("yyyy-MM-dd HH:mm")); } else { baseHtml = baseHtml.Replace("#CYCutDate#", ""); } if (detailInfo.VOUCHER_CUT_DATE.HasValue) { baseHtml = baseHtml.Replace("#VoucherCutDate#", detailInfo.VOUCHER_CUT_DATE.Value.ToString("yyyy-MM-dd HH:mm")); } else { baseHtml = baseHtml.Replace("#VoucherCutDate#", ""); } if (detailInfo.CY_OPEN.HasValue) { baseHtml = baseHtml.Replace("#CYOpenDate#", detailInfo.CY_OPEN.Value.ToString("yyyy-MM-dd")); } else { baseHtml = baseHtml.Replace("#CYOpenDate#", ""); } if (!string.IsNullOrWhiteSpace(detailInfo.REASON)) { baseHtml = baseHtml.Replace("#Reason#", model.REASON); } 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); var tableNode = html.DocumentNode.SelectSingleNode(".//table[@id='show-table']"); if (model.PORTLOAD_AREA.Equals("SOUTH_PORT", StringComparison.OrdinalIgnoreCase)) { if (tableNode != null) { StringBuilder tableBuilder = new StringBuilder(); for (int i = 0; i < rowList.Count; i++) { tableBuilder.Append($"{rowList[i].MBL_NO}{rowList[i].CONTA_NO}{rowList[i].LOAD_PORT}{(rowList[i].ETB.HasValue ? rowList[i].ETB.Value.ToString("yyyy-MM-dd HH:mm") : "")}{(rowList[i].ETD.HasValue ? rowList[i].ETD.Value.ToString("yyyy-MM-dd HH:mm") : "")}"); } //生成From Vessel的table列表 tableNode.ChildNodes.Add(HtmlNode.CreateNode(tableBuilder.ToString())); } } else { var southPNodes = html.DocumentNode.SelectNodes(".//p[@class='south_port']"); foreach (var node in southPNodes) { node.Remove(); } tableNode.RemoveAllChildren(); var colArg = new string[] { "Shipment Number", "Vessel - voyage", "样单截止时间 SI Cut Off", "开港时间 CY Open", "截港时间 CY cut off", "舱单-入港清单截止时间", "MDGF提交截止时间 - 危险品货物", "船代VGM截止时间", "海关放行截止时间(Customs Clearance Deadline)" }; tableNode.ChildNodes.Add(HtmlNode.CreateNode($"{(string.Join("", colArg))}")); StringBuilder tableBuilder = new StringBuilder(); for (int i = 0; i < rowList.Count; i++) { tableBuilder.Append($"{rowList[i].MBL_NO}"); tableBuilder.Append($"{($"{rowList[i].VESSEL}/{rowList[i].VOYNO}")}"); tableBuilder.Append($"{(rowList[i].SI_CUTOFF.HasValue ? rowList[i].SI_CUTOFF.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].SI_CUTOFF_TXT)}"); tableBuilder.Append($"{(rowList[i].CY_OPEN.HasValue ? rowList[i].CY_OPEN.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].CY_OPEN_TXT)}"); tableBuilder.Append($"{(rowList[i].CY_CUTOFF.HasValue ? rowList[i].CY_CUTOFF.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].CY_CUTOFF_TXT)}"); tableBuilder.Append($"{(rowList[i].MANIFEST_CUT.HasValue ? rowList[i].MANIFEST_CUT.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].MANIFEST_CUT_TXT)}"); tableBuilder.Append($"{(rowList[i].MDGF_CUT.HasValue ? rowList[i].MDGF_CUT.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].MDGF_CUT_TXT)}"); tableBuilder.Append($"{(rowList[i].VGM_CUT.HasValue ? rowList[i].VGM_CUT.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].VGM_CUT_TXT)}"); tableBuilder.Append($"{(rowList[i].CLOSING_DATE.HasValue ? rowList[i].CLOSING_DATE.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].CLOSING_DATE_TXT)}"); tableBuilder.Append(""); } //生成From Vessel的table列表 tableNode.ChildNodes.Add(HtmlNode.CreateNode(tableBuilder.ToString())); } result = html.DocumentNode.OuterHtml; } catch (Exception ex) { Logger.Log(NLog.LogLevel.Info, $"生成截止时间变更转发邮件正文失败,原因:{ex.Message}"); //提单号 {0} 生成截止时间变更转发邮件正文失败,原因:{1} throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBaseCutDateTransmitGenerateEmailFail)), model.MBL_NO, ex.Message)); } return result; } #endregion #region 推送邮件 /// /// 推送邮件 /// /// 自定义邮件详情 /// 返回回执 private async Task> PushEmail(EmailApiUserDefinedDto emailApiUserDefinedDto) { List emailList = new List(); var emailUrl = _configService.GetConfig(EMAIL_API_URL, long.Parse(user.TenantId), false).GetAwaiter().GetResult()?.Data?.Value; if (emailUrl == null) throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.CurrTenantEmailApiUrlNull))); emailList.Add(emailApiUserDefinedDto); DateTime bDate = DateTime.Now; string res = string.Empty; var jsonBody = JsonConvert.SerializeObject(emailList, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); Logger.Log(NLog.LogLevel.Info, $"发送邮件请求:{jsonBody}"); try { res = RequestHelper.Post(jsonBody, emailUrl); } catch (Exception ex) { Logger.Log(NLog.LogLevel.Info, $"发送邮件异常:{ex.Message}"); return DataResult.Failed(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TransmitEmailFail)), ex.Message)); } DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; Logger.Log(NLog.LogLevel.Info, $"发送邮件返回:{res}"); if (!string.IsNullOrWhiteSpace(res)) { var respObj = JsonConvert.DeserializeAnonymousType(res, new { Success = false, Message = string.Empty, Code = -9999, }); if(respObj.Success) { return DataResult.Success(respObj.Message); } return DataResult.Failed(respObj.Message); } return DataResult.Failed(res); } #endregion } }