diff --git a/ds-wms-service/DS.WMS.Core/TaskPlat/Entity/TaskCutDateChangeInfo.cs b/ds-wms-service/DS.WMS.Core/TaskPlat/Entity/TaskCutDateChangeInfo.cs index e05c85a3..1723170c 100644 --- a/ds-wms-service/DS.WMS.Core/TaskPlat/Entity/TaskCutDateChangeInfo.cs +++ b/ds-wms-service/DS.WMS.Core/TaskPlat/Entity/TaskCutDateChangeInfo.cs @@ -89,7 +89,35 @@ namespace DS.WMS.Core.TaskPlat.Entity [SugarColumn(ColumnDescription = "任务批次号", IsNullable = true, Length = 64)] public string? TASK_BATCH_NO { get; set; } + /// + /// 是否已转发客户 1-是 0-否 + /// + [SugarColumn(ColumnDescription = "是否已转发客户 1-是 0-否", IsNullable = true, Length = 1)] + public Nullable IS_TRANSFER_USER { get; set; } + /// + /// 最后转发客户邮件时间 + /// + [SugarColumn(ColumnDescription = "最后转发客户邮件时间", IsNullable = true)] + public DateTime? LST_TRANSFER_USER_DATE { get; set; } + + /// + /// 最后转发客户邮件结果 + /// + [SugarColumn(ColumnDescription = "最后转发客户邮件结果", IsNullable = true, Length = 500)] + public string? LST_TRANSFER_NOTES { get; set; } + + /// + /// 最后转发客户邮件状态 TEMP-暂存 SUCC-发送成功 FAILURE-发送失败 + /// + [SugarColumn(ColumnDescription = "最后转发客户邮件状态 TEMP-暂存 SUCC-发送成功 FAILURE-发送失败", IsNullable = true, Length = 20)] + public string? LST_STATUS { get; set; } + + /// + /// 最后转发客户邮件状态名称 + /// + [SugarColumn(ColumnDescription = "最后转发客户邮件状态名称", IsNullable = true, Length = 50)] + public string? LST_STATUS_NAME { get; set; } } } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/TaskPlat/Interface/CutDateChange/ITaskManageCutDateChangeService.cs b/ds-wms-service/DS.WMS.Core/TaskPlat/Interface/CutDateChange/ITaskManageCutDateChangeService.cs index b65a72cb..f1122bca 100644 --- a/ds-wms-service/DS.WMS.Core/TaskPlat/Interface/CutDateChange/ITaskManageCutDateChangeService.cs +++ b/ds-wms-service/DS.WMS.Core/TaskPlat/Interface/CutDateChange/ITaskManageCutDateChangeService.cs @@ -1,4 +1,5 @@ using DS.Module.Core; +using DS.Module.Core.Data; using DS.Module.DjyServiceStatus; using DS.WMS.Core.Op.Dtos; using DS.WMS.Core.TaskPlat.Dtos; @@ -36,12 +37,28 @@ namespace DS.WMS.Core.TaskPlat.Interface /// 返回回执 Task AutoUpdateOrderCutDateAndTranmitToCustomer(long taskPKId); + /// /// 发送邮件通知给客户 /// - /// 截止时间变更主键 + /// 起运港未提箱任务主键 + /// 邮件模板主键 + /// 返回回执 + Task> InnerSendEmailToCustomer(long taskPKId, long businessTaskMailId); + + /// + /// 发送邮件通知给客户(任务自动机调取) + /// + /// 数据上下文 + /// 返回回执 + Task> SendEmailToCustomerTask(TaskFlowDataContext dataContext); + + /// + /// 手工发送邮件通知给客户 + /// + /// 起运港未提箱任务主键 /// 返回回执 - Task SendEmailToCustomer(long taskPKId); + Task> ManualSendEmailToCustomer(long taskPKId); } } diff --git a/ds-wms-service/DS.WMS.Core/TaskPlat/Method/CutDateChange/TaskManageCutDateChangeService.cs b/ds-wms-service/DS.WMS.Core/TaskPlat/Method/CutDateChange/TaskManageCutDateChangeService.cs index 47fe51d4..4a2b36d5 100644 --- a/ds-wms-service/DS.WMS.Core/TaskPlat/Method/CutDateChange/TaskManageCutDateChangeService.cs +++ b/ds-wms-service/DS.WMS.Core/TaskPlat/Method/CutDateChange/TaskManageCutDateChangeService.cs @@ -39,35 +39,38 @@ using DS.WMS.Core.Op.EDI; using DS.WMS.Core.Sys.Dtos; using DS.WMS.Core.Code.Dtos; using DS.Module.Core.Data; +using DS.WMS.Core.Op.Entity.TaskInteraction; +using Microsoft.Extensions.Hosting; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Logging; +using DS.WMS.Core.Op.Interface.TaskInteraction; +using DS.WMS.Core.Op.Method.TaskInteraction; namespace DS.WMS.Core.TaskPlat.Method { /// /// 截止时间变更 /// - public class TaskManageCutDateChangeService: ITaskManageCutDateChangeService + public class TaskManageCutDateChangeService: TaskManageBaseService,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) + private readonly ITaskLogService _logService; + private readonly ITaskMailService _taskMailService; + private readonly ITaskAllocationService _taskAllocationService; + + public TaskManageCutDateChangeService(IUser user, ILogger logger, + ISaasDbService saasDbService, + IServiceProvider serviceProvider, + IWebHostEnvironment environment) : base(user, logger, saasDbService, serviceProvider, environment) { - _serviceProvider = serviceProvider; - db = _serviceProvider.GetRequiredService(); - user = _serviceProvider.GetRequiredService(); - saasService = _serviceProvider.GetRequiredService(); - _seaExportService = _serviceProvider.GetRequiredService(); - _configService = _serviceProvider.GetRequiredService(); - _userService = _serviceProvider.GetRequiredService(); + user = serviceProvider.GetRequiredService(); + _seaExportService = serviceProvider.GetRequiredService(); + _configService = serviceProvider.GetRequiredService(); + _userService = serviceProvider.GetRequiredService(); + _taskMailService = serviceProvider.GetRequiredService(); + _taskAllocationService = serviceProvider.GetRequiredService(); } #region 通过任务主键获取截止时间变更详情 @@ -80,7 +83,7 @@ namespace DS.WMS.Core.TaskPlat.Method { List list = new List(); - var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); //任务不考虑OrgId,这里去掉 tenantDb.QueryFilter.Clear(); @@ -89,7 +92,7 @@ namespace DS.WMS.Core.TaskPlat.Method .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)); @@ -99,7 +102,7 @@ namespace DS.WMS.Core.TaskPlat.Method var detailList = await tenantDb.Queryable() .Where(a => parentIdList.Contains(a.P_ID)).ToListAsync(); - if (detailList.Count > 0) + if (queryList.Count > 0) { list = detailList.OrderBy(p => p.MBL_NO).Select(p => { @@ -127,7 +130,7 @@ namespace DS.WMS.Core.TaskPlat.Method SeaExportOrderExtension orderInfo = null; try { - var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); //任务不考虑OrgId,这里去掉 tenantDb.QueryFilter.Clear(); @@ -198,7 +201,7 @@ namespace DS.WMS.Core.TaskPlat.Method } catch (Exception ex) { - Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 检索截止时间变更订舱记录 处理异常,原因:{ex.Message}"); + logger.LogError($"taskPKId={taskPKId} 检索截止时间变更订舱记录 处理异常,原因:{ex.Message}"); return DataResult.FailedData(orderInfo,$"检索失败,原因:{ex.Message}", MultiLanguageConst.Operation_Failed); } @@ -235,14 +238,14 @@ namespace DS.WMS.Core.TaskPlat.Method var slotRlt = UpdateBookingSlotCutDate(taskPKId, orderInfo); //如果没有配置批量,则按单票发送邮件 - var rlt = await SendEmailToCustomer(taskPKId); + //var rlt = await SendEmailToCustomer(taskPKId); - Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 推送邮件完成,结果:{JsonConvert.SerializeObject(rlt)}"); + //logger.LogInformation($"taskPKId={taskPKId} 推送邮件完成,结果:{JsonConvert.SerializeObject(rlt)}"); } catch(Exception ex) { - Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 自动更新订单的截单日期并转发失败异常,原因:{ex.Message}"); + //Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 自动更新订单的截单日期并转发失败异常,原因:{ex.Message}"); return DataResult.Failed( $"自动更新订单的截单日期并转发失败,原因:{ex.Message}", MultiLanguageConst.Operation_Failed); } @@ -260,7 +263,7 @@ namespace DS.WMS.Core.TaskPlat.Method /// 返回回执 private async Task UpdateBookingOrderCutDate(long taskPKId, SeaExportOrderExtension orderInfo) { - var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); //任务不考虑OrgId,这里去掉 tenantDb.QueryFilter.Clear(); @@ -287,7 +290,7 @@ namespace DS.WMS.Core.TaskPlat.Method 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())}"); + //Logger.Log(NLog.LogLevel.Info, $"截止时间变更主键{taskPKId} MBLNO={cutDetail.MBL_NO} 检索海运出口订单匹配到拆票信息 ids={string.Join(",", ids.ToArray())}"); } foreach (var id in ids) @@ -325,13 +328,13 @@ namespace DS.WMS.Core.TaskPlat.Method it.CloseDocDate }).ExecuteCommand(); - Logger.Log(NLog.LogLevel.Info, $"截止时间变更主键{taskPKId} id={id} mblno={bookingInfo.MBLNO} 更新订舱完毕 详情 {doBuilder.ToString()}"); + //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}"); + //Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 自动更新订单的截单日期更新订舱异常,原因:{ex.Message}"); return DataResult.Failed($"自动更新订单的截单日期更新订舱,原因:{ex.Message}", MultiLanguageConst.Operation_Failed); } @@ -349,7 +352,7 @@ namespace DS.WMS.Core.TaskPlat.Method /// 返回回执 private async Task UpdateBookingSlotCutDate(long taskPKId, SeaExportOrderExtension orderInfo) { - var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); //任务不考虑OrgId,这里去掉 tenantDb.QueryFilter.Clear(); @@ -410,13 +413,13 @@ namespace DS.WMS.Core.TaskPlat.Method it.ManifestCutDate }).ExecuteCommand(); - Logger.Log(NLog.LogLevel.Info, $"截止时间变更主键{taskPKId} id={cutBase.Id} mblno={slotOrder.SlotBookingNo} 更新舱位完毕 详情 {doBuilder.ToString()}"); + //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}"); + //Logger.Log(NLog.LogLevel.Info, $"taskPKId={taskPKId} 自动更新订单的截单日期更新舱位异常,原因:{ex.Message}"); return DataResult.Failed($"自动更新订单的截单日期更新舱位,原因:{ex.Message}", MultiLanguageConst.Operation_Failed); } @@ -426,475 +429,286 @@ namespace DS.WMS.Core.TaskPlat.Method #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) + public async Task> InnerSendEmailToCustomer(long taskPKId, long businessTaskMailId) { - 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}"); - } - } + /* + 1、先匹配订单。这里可能关联的是拆票订单,如果是拆票订单需要所有拆票记录都要发邮件通知) + 2、有订单,调取任务规则补全相关人(如果当票已经有了人员表记录 task_base_allocation则不再处理人员) + 3、调取发送模板。 + 4、填充模板数据。 + 5、发送邮件。 + 6、成功后置任务为完成状态。 + */ - //获取客服的邮箱 - if (bk.CustomerService > 0) - { - var opUser = _userService.GetUserInfo(bk.CustomerService.ToString()); + var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); - if (opUser.Succeeded && opUser.Data != null) - { - if (!string.IsNullOrWhiteSpace(opUser.Data.Email)) - { - opEmailList.Add(opUser.Data.Email.Trim()); + var entity = tenantDb.Queryable().Filter(null, true).First(a => a.TASK_ID == taskPKId); - 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}/"; - } + var baseInfo = tenantDb.Queryable().Filter(null, true).First(a => a.Id == taskPKId); - ////提取当前公共邮箱的配置 - //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 != ""); + var queryRlt = await _seaExportService.SearchOrderInfo(entity.MBL_NO); - //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) + if (!queryRlt.Succeeded) { - result.succ = false; - result.msg = $"失败,原因:{ex.Message}"; + logger.LogInformation($"匹配订单信息失败 mblno={entity.MBL_NO},原因:{queryRlt.Message}"); - //new EmailNoticeHelper().SendEmailNotice($"taskid={model.TASK_ID} 截止时间变更 转发通知邮件失败", $"taskid={model.TASK_ID} 转发通知邮件失败,原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); + return DataResult.Failed($"匹配订单信息失败 mblno={entity.MBL_NO},原因:{queryRlt.Message}"); } - return result; - } - #endregion + var taskInfo = entity.Adapt(); - #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; + BusinessTaskMail? mailConfig = _taskMailService.GetAsync(businessTaskMailId).GetAwaiter().GetResult().Data; - try + if (mailConfig == null) { - //var opt = App.GetOptions(); - //var dirAbs = opt.basePath; - //if (string.IsNullOrEmpty(dirAbs)) - //{ - // dirAbs = App.WebHostEnvironment.WebRootPath; - //} + await _logService.WriteLogAsync(new Op.Dtos.TaskInteraction.TaskUpdateRequest + { + BusinessId = taskPKId, + BusinessType = BusinessType.OceanShippingExport, + AutoCreateNext = true, + TaskTypeName = TaskBaseTypeEnum.CUT_MODIFY.ToString(), - //var fileAbsPath = Path.Combine(dirAbs, filePath); - //_logger.LogInformation($"查找模板文件:{fileAbsPath}"); + }, $"未能根据任务配置值获取邮件模板设置"); - //if (!File.Exists(fileAbsPath)) - //{ - // throw Oops.Bah(BookingErrorCode.BOOK115); - //} + return DataResult.Failed("未能根据任务配置值获取邮件模板设置"); + } + var orderInfo = queryRlt.Data; - baseHtml = File.ReadAllText(fileAbsPath); + logger.LogInformation($"获取订单详情成功 bookid={orderInfo.currOrder.Id}"); - if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.UserName)) - { - baseHtml = baseHtml.Replace("#opname#", opUserInfo.UserName); - } - else - { - baseHtml = baseHtml.Replace("#opname#", "操作"); - } + DateTime nowDate = DateTime.Now; - if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Email)) - { - baseHtml = baseHtml.Replace("#opemail#", opUserInfo.Email); - } - else - { - baseHtml = baseHtml.Replace("#opemail#", ""); - } + List orderIdList = new List { orderInfo.currOrder.Id }; - 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 (orderInfo.otherOrderList != null && orderInfo.otherOrderList.Count > 0) + orderIdList.AddRange(orderInfo.otherOrderList.Select(t => t.Id).ToList()); - if (!string.IsNullOrWhiteSpace(model.MBL_NO)) - { - baseHtml = baseHtml.Replace("#BillNo#", model.MBL_NO); - } - else - { - baseHtml = baseHtml.Replace("#BillNo#", ""); - } + //如果是拆票需要处理,处理所以分票记录 + if (orderInfo.currOrder.SplitOrMergeFlag == 1) + { + bool isHasAlloc = false; - if (!string.IsNullOrWhiteSpace(model.VESSEL)) + foreach (var id in orderIdList) { - string s = $"{model.VESSEL}/{model.VOYNO}"; - baseHtml = baseHtml.Replace("#VesselVoyno#", s); - } - else - { - baseHtml = baseHtml.Replace("#VesselVoyno#", ""); - } + var taskAllocList = tenantDb.Queryable().Where(a => a.TaskId == taskPKId).ToList(); - var detailInfo = rowList.FirstOrDefault(); + var searchAllotUserRlt = _taskAllocationService.GetAllotUserBySeaExportId(TaskBaseTypeEnum.CUT_MODIFY, id, new TaskFlowDataContext()).GetAwaiter().GetResult(); - 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 (searchAllotUserRlt.Succeeded && searchAllotUserRlt.Data?.Count > 0) + { + isHasAlloc = true; - if (detailInfo.CY_CUTOFF.HasValue) - { - baseHtml = baseHtml.Replace("#CYCutDate#", detailInfo.CY_CUTOFF.Value.ToString("yyyy-MM-dd HH:mm")); - } - else - { - baseHtml = baseHtml.Replace("#CYCutDate#", ""); - } + var addUserList = searchAllotUserRlt.Data.GroupJoin(taskAllocList, l => l.RecvUserId, r => r.UserId, (l, r) => + { + if (r.ToList().Count == 0) + return new { add = true, obl = l }; - 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#", ""); - } + return new { add = false, obl = l }; + }).Where(a => a.add).Select(a => a.obl).ToList(); - if (detailInfo.CY_OPEN.HasValue) - { - baseHtml = baseHtml.Replace("#CYOpenDate#", detailInfo.CY_OPEN.Value.ToString("yyyy-MM-dd")); - } - else - { - baseHtml = baseHtml.Replace("#CYOpenDate#", ""); + if (addUserList.Count > 0) + { + //写入 + addUserList.ForEach(b => + { + var alloc = new TaskBaseAllocation + { + Status = baseInfo.STATUS, + StatusName = baseInfo.STATUS_NAME, + TaskId = taskPKId, + StatusTime = nowDate, + UserId = b.RecvUserId, + UserName = b.RecvUserName + }; + + tenantDb.Insertable(alloc).ExecuteCommand(); + }); + } + } } - if (!string.IsNullOrWhiteSpace(detailInfo.REASON)) - { - baseHtml = baseHtml.Replace("#Reason#", model.REASON); - } - else + if (isHasAlloc && baseInfo.IS_PUBLIC == 1) { - baseHtml = baseHtml.Replace("#Reason#", ""); + await tenantDb.Updateable(baseInfo).UpdateColumns(x => new + { + x.IS_PUBLIC + }).ExecuteCommandAsync(); } + } + else + { + var taskAllocList = tenantDb.Queryable().Where(a => a.TaskId == taskPKId).ToList(); - if (!string.IsNullOrWhiteSpace(tenantName)) + if (taskAllocList.Count == 0) { - baseHtml = baseHtml.Replace("#TenantCompanyName#", tenantName); - } - else - { - baseHtml = baseHtml.Replace("#TenantCompanyName#", ""); - } + var searchAllotUserRlt = _taskAllocationService.GetAllotUserBySeaExportId(TaskBaseTypeEnum.CUT_MODIFY, orderInfo.currOrder.Id, new TaskFlowDataContext()).GetAwaiter().GetResult(); - 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) + if (searchAllotUserRlt.Succeeded && searchAllotUserRlt.Data?.Count > 0) { - StringBuilder tableBuilder = new StringBuilder(); + //写入 + searchAllotUserRlt.Data.ForEach(b => + { + var alloc = new TaskBaseAllocation + { + Status = baseInfo.STATUS, + StatusName = baseInfo.STATUS_NAME, + TaskId = taskPKId, + StatusTime = nowDate, + UserId = b.RecvUserId, + UserName = b.RecvUserName + }; + + tenantDb.Insertable(alloc).ExecuteCommand(); + }); - for (int i = 0; i < rowList.Count; i++) + if (baseInfo.IS_PUBLIC == 1) { - 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") : "")}"); - } + baseInfo.IS_PUBLIC = 0; - //生成From Vessel的table列表 - tableNode.ChildNodes.Add(HtmlNode.CreateNode(tableBuilder.ToString())); + await tenantDb.Updateable(baseInfo).UpdateColumns(x => new + { + x.IS_PUBLIC + }).ExecuteCommandAsync(); + } } } - else - { - var southPNodes = html.DocumentNode.SelectNodes(".//p[@class='south_port']"); + } - foreach (var node in southPNodes) - { - node.Remove(); - } + TaskTransferMsgDto resultDto = new TaskTransferMsgDto + { + ExcuteDate = nowDate, + Detail = new List() + }; - tableNode.RemoveAllChildren(); + Dictionary> dict = new Dictionary>(); - var colArg = new string[] { "Shipment Number", "Vessel - voyage", "样单截止时间 SI Cut Off", "开港时间 CY Open", "截港时间 CY cut off", "舱单-入港清单截止时间", "MDGF提交截止时间 - 危险品货物", "船代VGM截止时间", "海关放行截止时间(Customs Clearance Deadline)" }; + foreach (var id in orderIdList) + { + TaskTransferMsgDataDto detail = new TaskTransferMsgDataDto + { + BusinessId = id, + }; - tableNode.ChildNodes.Add(HtmlNode.CreateNode($"{(string.Join("", colArg))}")); + var model = new MailTemplateModel(taskInfo) + { + BusinessId = id, + BusinessType = BusinessType.OceanShippingExport, + }; - StringBuilder tableBuilder = new StringBuilder(); + MailService mailService = new MailService(serviceProvider); + var result = await mailService.SendAsync(mailConfig, model); - for (int i = 0; i < rowList.Count; i++) + if (!result.Succeeded) + { + await _logService.WriteLogAsync(new Op.Dtos.TaskInteraction.TaskUpdateRequest { - 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(""); - } + BusinessId = taskPKId, + BusinessType = BusinessType.OceanShippingExport, + AutoCreateNext = true, + TaskTypeName = TaskBaseTypeEnum.CUT_MODIFY.ToString(), - //生成From Vessel的table列表 - tableNode.ChildNodes.Add(HtmlNode.CreateNode(tableBuilder.ToString())); - } + }, result.Message); + //return DataResult.Failed(result.Message); + } - result = html.DocumentNode.OuterHtml; + detail.Status = result.Succeeded ? "SUCC" : "FAILURE"; + detail.Message = result.Message; + detail.MBlNo = entity.MBL_NO; + resultDto.Detail.Add(detail); + dict.Add(id, new Tuple(result.Succeeded, result.Message, entity.MBL_NO)); } - catch (Exception ex) + + //如果存在失败记录,不能置完成状态 + if (!dict.Any(t => !t.Value.Item1)) { - - Logger.Log(NLog.LogLevel.Info, $"生成截止时间变更转发邮件正文失败,原因:{ex.Message}"); + entity.IS_TRANSFER_USER = true; + entity.LST_TRANSFER_USER_DATE = DateTime.Now; + entity.LST_STATUS = "SUCC"; + entity.LST_STATUS_NAME = "发送成功"; - //提单号 {0} 生成截止时间变更转发邮件正文失败,原因:{1} - throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBaseCutDateTransmitGenerateEmailFail)), model.MBL_NO, ex.Message)); + await tenantDb.Updateable(entity).UpdateColumns(x => new + { + x.IS_TRANSFER_USER, + x.LST_TRANSFER_USER_DATE, + x.LST_STATUS, + x.LST_STATUS_NAME + }).ExecuteCommandAsync(); + + //发送完邮件,自动标记任务状态为完成 + await SetTaskStatus(taskPKId, TaskBaseTypeEnum.CUT_MODIFY, TaskStatusEnum.Complete, DateTime.Now, null); } - return result; + return DataResult.Success(resultDto); } #endregion - #region 推送邮件 + #region 发送邮件通知给客户(任务自动机调取) /// - /// 推送邮件 + /// 发送邮件通知给客户(任务自动机调取) /// - /// 自定义邮件详情 + /// 数据上下文 /// 返回回执 - private async Task> PushEmail(EmailApiUserDefinedDto emailApiUserDefinedDto) + public async Task> SendEmailToCustomerTask(TaskFlowDataContext dataContext) { - List emailList = new List(); - - var emailUrl = _configService.GetConfig(EMAIL_API_URL, long.Parse(user.TenantId), false).GetAwaiter().GetResult()?.Data?.Value; + var taskPKId = dataContext.Get(TaskFlowDataNameConst.TaskPKId); + if (taskPKId == 0) + throw new ArgumentException($"缺少参数:{nameof(TaskFlowDataNameConst.TaskPKId)}"); - if (emailUrl == null) - throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.CurrTenantEmailApiUrlNull))); + var businessTaskMailId = dataContext.Get($"{nameof(BusinessTaskMail)}.{nameof(BusinessTaskMail.Id)}"); + if (businessTaskMailId == 0) + throw new ArgumentException($"缺少参数:{nameof(BusinessTaskMail)}.{nameof(BusinessTaskMail.Id)}"); - emailList.Add(emailApiUserDefinedDto); - - DateTime bDate = DateTime.Now; - - string res = string.Empty; - - var jsonBody = JsonConvert.SerializeObject(emailList, Formatting.Indented, new JsonSerializerSettings + if (businessTaskMailId == 0) { - NullValueHandling = NullValueHandling.Ignore - }); + await _logService.WriteLogAsync(new Op.Dtos.TaskInteraction.TaskUpdateRequest + { + BusinessId = taskPKId, + BusinessType = BusinessType.OceanShippingExport, + AutoCreateNext = true, + TaskTypeName = TaskBaseTypeEnum.CUT_MODIFY.ToString(), - Logger.Log(NLog.LogLevel.Info, $"发送邮件请求:{jsonBody}"); + }, $"缺少参数:{nameof(BusinessTaskMail)}.{nameof(BusinessTaskMail.Id)}"); - try - { - res = RequestHelper.Post(jsonBody, emailUrl); + return DataResult.Failed($"缺少参数:{nameof(BusinessTaskMail)}.{nameof(BusinessTaskMail.Id)}"); } - catch (Exception ex) - { - Logger.Log(NLog.LogLevel.Info, $"发送邮件异常:{ex.Message}"); - return DataResult.Failed(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TransmitEmailFail)), ex.Message)); - } + return await InnerSendEmailToCustomer(taskPKId, businessTaskMailId); + } + #endregion - DateTime eDate = DateTime.Now; - TimeSpan ts = eDate.Subtract(bDate); - var timeDiff = ts.TotalMilliseconds; + #region 手工发送邮件通知给客户 + /// + /// 手工发送邮件通知给客户 + /// + /// 起运港未提箱任务主键 + /// 返回回执 + public async Task> ManualSendEmailToCustomer(long taskPKId) + { + var paramConfig = _configService.GetConfig("CutDateChangeEmailTemplateID", long.Parse(user.TenantId), false).GetAwaiter().GetResult()?.Data?.Value; - Logger.Log(NLog.LogLevel.Info, $"发送邮件返回:{res}"); + long businessTaskMailId = 0; - if (!string.IsNullOrWhiteSpace(res)) + if (!string.IsNullOrWhiteSpace(paramConfig)) { - 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); + businessTaskMailId = long.Parse(paramConfig); + } + else + { + return DataResult.Failed($"缺少系统参数参数:截止时间变更邮件模板ID-\tCutDateChangeEmailTemplateID"); } - return DataResult.Failed(res); + return await InnerSendEmailToCustomer(taskPKId, businessTaskMailId); } #endregion }