You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
BookingHeChuan/Myshipping.Application/Service/TaskManagePlat/TaskManageCutDateChangeServ...

1099 lines
47 KiB
C#

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Furion;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.RemoteRequest.Extensions;
using HtmlAgilityPack;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Myshipping.Application;
using Myshipping.Application.ConfigOption;
using Myshipping.Application.Entity;
using Myshipping.Application.Enum;
using Myshipping.Application.Helper;
using Myshipping.Application.Service.BookingSlot.Dto;
using Myshipping.Core;
using Myshipping.Core.Entity;
using Myshipping.Core.Helper;
using Myshipping.Core.Service;
using Newtonsoft.Json;
using Npoi.Mapper;
using NPOI.OpenXmlFormats.Wordprocessing;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Asn1.Tsp;
using Org.BouncyCastle.Crypto;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Myshipping.Application
{
/// <summary>
/// 截止时间变更
/// </summary>
[ApiDescriptionSettings("Application", Name = "TaskManageCutDateChange", Order = 10)]
public class TaskManageCutDateChangeService : ITaskManageCutDateChangeService, IDynamicApiController, ITransient
{
private readonly SqlSugarRepository<TaskCutDateChangeInfo> _taskCutDateChangeInfoRepository;
private readonly SqlSugarRepository<TaskCutDateChangeDetailInfo> _taskCutDateChangeDetailInfoRepository;
private readonly SqlSugarRepository<TaskBaseInfo> _taskBaseRepository;
private readonly SqlSugarRepository<BookingOrder> _bookingOrderRepository;
private readonly ILogger<TaskManageCutDateChangeService> _logger;
private readonly SqlSugarRepository<BookingOrderContact> _bookingOrderContactRepository;
private readonly SqlSugarRepository<SysUser> _sysUserRepository;
private readonly SqlSugarRepository<DjyUserMailAccount> _djyUserMailAccount;
private readonly SqlSugarRepository<BookingPrintTemplate> _repPrintTemplate;
private readonly ISysCacheService _cache;
private readonly INamedServiceProvider<IBookingOrderService> _namedBookingOrderServiceProvider;
private readonly SqlSugarRepository<BookingSlotBase> _bookingSlotBaseRepository;
public TaskManageCutDateChangeService(SqlSugarRepository<TaskCutDateChangeInfo> taskCutDateChangeInfoRepository,
SqlSugarRepository<TaskCutDateChangeDetailInfo> taskCutDateChangeDetailInfoRepository,
SqlSugarRepository<BookingOrderContact> bookingOrderContactRepository,
SqlSugarRepository<TaskBaseInfo> taskBaseRepository,
SqlSugarRepository<SysUser> sysUserRepository,
SqlSugarRepository<DjyUserMailAccount> djyUserMailAccount,
SqlSugarRepository<BookingPrintTemplate> repPrintTemplate,
ILogger<TaskManageCutDateChangeService> logger,
ISysCacheService cache,
INamedServiceProvider<IBookingOrderService> namedBookingOrderServiceProvider,
SqlSugarRepository<BookingSlotBase> bookingSlotBaseRepository,
SqlSugarRepository<BookingOrder> bookingOrderRepository)
{
_taskCutDateChangeInfoRepository = taskCutDateChangeInfoRepository;
_taskCutDateChangeDetailInfoRepository = taskCutDateChangeDetailInfoRepository;
_taskBaseRepository = taskBaseRepository;
_bookingOrderRepository = bookingOrderRepository;
_bookingOrderContactRepository = bookingOrderContactRepository;
_sysUserRepository = sysUserRepository;
_djyUserMailAccount = djyUserMailAccount;
_repPrintTemplate = repPrintTemplate;
_namedBookingOrderServiceProvider = namedBookingOrderServiceProvider;
_bookingSlotBaseRepository = bookingSlotBaseRepository;
_logger = logger;
_cache = cache;
}
#region 获取截止时间变更详情
/// <summary>
/// 获取截止时间变更详情
/// </summary>
/// <param name="pkId">截止时间变更主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageCutDate/GetInfo")]
public async Task<List<TaskCutDateChangeShowDto>> GetInfo(string pkId)
{
List<TaskCutDateChangeShowDto> list = new List<TaskCutDateChangeShowDto>();
var cutChangeOrder = _taskCutDateChangeInfoRepository.AsQueryable().First(a => a.PK_ID == pkId);
if (cutChangeOrder == null)
throw Oops.Oh($"截止时间变更主键{pkId}无法获取业务信息");
var detailList = _taskCutDateChangeDetailInfoRepository.AsQueryable()
.Where(a => a.P_ID == pkId).ToList();
if (detailList.Count > 0)
{
list = detailList.OrderBy(p => p.MBL_NO).Select(p =>
{
TaskCutDateChangeShowDto model = p.Adapt<TaskCutDateChangeShowDto>();
model.NoticeDate = cutChangeOrder.NOTICE_DATE;
model.Carrier = cutChangeOrder.CARRIER;
return model;
}).ToList();
}
return list;
}
#endregion
#region 通过任务主键获取截止时间变更详情
/// <summary>
/// 通过任务主键获取截止时间变更详情
/// </summary>
/// <param name="taskPkId">截止时间变更任务主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageCutDate/GetInfoByTaskId")]
public async Task<List<TaskCutDateChangeShowDto>> GetInfoByTaskId(string taskPkId)
{
List<TaskCutDateChangeShowDto> list = new List<TaskCutDateChangeShowDto>();
var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId);
if (taskBase == null)
throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息");
var cutChangeOrder = _taskCutDateChangeInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID);
if (cutChangeOrder == null)
throw Oops.Oh($"截止时间变更主键{taskPkId}无法获取业务信息");
var detailList = _taskCutDateChangeDetailInfoRepository.AsQueryable()
.Where(a => a.P_ID == cutChangeOrder.PK_ID).ToList();
if (detailList.Count > 0)
{
list = detailList.OrderBy(p => p.MBL_NO).Select(p =>
{
TaskCutDateChangeShowDto model = p.Adapt<TaskCutDateChangeShowDto>();
model.NoticeDate = cutChangeOrder.NOTICE_DATE;
model.Carrier = cutChangeOrder.CARRIER;
return model;
}).ToList();
}
return list;
}
#endregion
#region 重新处理截止时间变更任务
/// <summary>
/// 重新处理截止时间变更任务
/// 对未匹配订舱订单的任务记录,重新对应订单订单
/// </summary>
/// <param name="taskPkId">截止时间变更任务主键</param>
/// <returns>返回回执</returns>
public async Task<TaskManageOrderResultDto> SearchAndConnectBookingInfo(string taskPkId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId);
if (taskBase == null)
throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息");
var cutDateChange = _taskCutDateChangeInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID);
if (cutDateChange == null)
throw Oops.Oh($"截止时间变更主键{taskPkId}无法获取业务信息");
var detailList = _taskCutDateChangeDetailInfoRepository.AsQueryable()
.Where(a => a.P_ID == cutDateChange.PK_ID).ToList();
//如果都有订单订单记录,则提示错误不进行对应
if (!detailList.Any(t => !t.BOOKING_ID.HasValue))
{
throw Oops.Oh($"当前截止时间变更已有匹配的订舱订单,不能执行操作");
}
var mblList = detailList.Select(a => a.MBL_NO).Distinct().ToList();
var bookingList = _bookingOrderRepository.AsQueryable().Filter(null, true)
.Where(a => mblList.Contains(a.MBLNO) && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0)).ToList();
if (bookingList.Count == 0)
throw Oops.Oh($"提单号未提取有效的订舱订单");
List<string> msgList = new List<string>();
detailList.ForEach(async t =>
{
//只处理没有订舱ID的记录
if (!t.BOOKING_ID.HasValue)
{
var currBook = bookingList.FirstOrDefault(p => p.MBLNO == t.MBL_NO);
if (currBook != null)
{
t.BOOKING_ID = currBook.Id;
t.UpdatedUserId = UserManager.UserId;
t.UpdatedUserName = UserManager.Name;
//更新任务BC
await _taskCutDateChangeDetailInfoRepository.AsUpdateable(t).UpdateColumns(it => new
{
it.BOOKING_ID,
it.UpdatedTime,
it.UpdatedUserId,
it.UpdatedUserName
}).ExecuteCommandAsync();
}
else
{
msgList.Add(t.MBL_NO);
}
}
});
if (msgList.Count > 0)
throw Oops.Oh($"提单号{(string.Join(",", msgList.ToArray()))}未提取有效的订舱订单");
result.succ = true;
result.msg = "成功";
return result;
}
#endregion
#region 推送及时消息
/// <summary>
/// 推送及时消息
/// </summary>
/// <param name="taskPkId">截止时间任务主键</param>
/// <returns>返回回执</returns>
public async Task<TaskManageOrderResultDto> SendInstantMessage(string taskPkId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId);
if (taskBase == null)
throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息");
var cutDateChange = _taskCutDateChangeInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID);
if (cutDateChange == null)
throw Oops.Oh($"截止时间变更主键{taskPkId}无法获取业务信息");
var detailList = _taskCutDateChangeDetailInfoRepository.AsQueryable()
.Where(a => a.P_ID == cutDateChange.PK_ID).ToList();
//如果都有订单订单记录,则提示错误不进行对应
if (!detailList.Any(t => t.BOOKING_ID.HasValue))
{
throw Oops.Oh($"当前截止时间变更没有匹配的订舱订单,不能执行操作");
}
var ids = detailList.Where(a => a.BOOKING_ID.HasValue).Select(a => a.BOOKING_ID.Value).ToList();
var bookingList = _bookingOrderRepository.AsQueryable().Filter(null, true)
.Where(a => ids.Contains(a.Id) && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0)).ToList();
if (bookingList.Count == 0)
throw Oops.Oh($"提单号未提取有效的订舱订单");
Dictionary<string, List<string>> msgList = new Dictionary<string, List<string>>();
msgList = bookingList.GroupBy(a => a.OP).Select(a =>
{
var currList = a.ToList();
return new { Key = a.Key, list = currList.Select(a => a.MBLNO).ToList() };
}).ToDictionary(a => a.Key, b => b.list);
if (msgList.Count > 0)
{
msgList.ForEach(t =>
{
DingTalkGroupHelper.SendDingTalkGroupMessage("KangqianNotify", "截止时间变更消息", $"@{t.Key} 收到如下提单号{(string.Join(",", t.Value.ToArray()))}的截止时间变更消息");
});
}
if (detailList.Any(t => !t.BOOKING_ID.HasValue))
throw Oops.Oh($"提单号{(string.Join(",", detailList.Where(t => !t.BOOKING_ID.HasValue).Select(t => t.MBL_NO).ToArray()))}未提取有效的订舱订单");
result.succ = true;
result.msg = "成功";
return result;
}
#endregion
#region 自动转发截止时间变更通知
/// <summary>
/// 自动转发截止时间变更通知
/// </summary>
/// <param name="taskPKId">截止时间变更通知任务主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageCutDate/AutoTransferNotice")]
public async Task<TaskManageOrderResultDto> AutoTransferNotice(string taskPKId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var queryRlt = await QueryBookingOrder(taskPKId);
_logger.LogInformation($"taskPKId={taskPKId} 检索对应的订舱记录完成,结果:{JSON.Serialize(queryRlt)}");
if (queryRlt.succ)
{
_logger.LogInformation($"taskPKId={taskPKId} 检索对应的订舱记录成功,触发订舱的截止时间更新");
//更新订舱的截单时间
await UpdateBookingOrderCutDate(taskPKId);
}
await UpdateBookingSlotCutDate(taskPKId);
//如果没有配置批量,则按单票发送邮件
var rlt = await 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 检索对应的订舱订单
/// <summary>
/// 检索对应的订舱订单
/// </summary>
/// <param name="taskPKId">截止时间变更任务主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageCutDate/QueryBookingOrder")]
public async Task<TaskManageOrderResultDto> 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 = _taskCutDateChangeInfoRepository.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 _taskCutDateChangeInfoRepository.AsUpdateable(entityInfo).UpdateColumns(x => new
{
x.BOOKING_ID,
x.UpdatedTime,
x.UpdatedUserId,
x.UpdatedUserName
}).ExecuteCommandAsync();
var list = _taskCutDateChangeDetailInfoRepository.AsQueryable().Filter(null, true).Where(a => a.P_ID == entityInfo.PK_ID).ToList();
if (list != null && list.Count > 0)
{
list.ForEach(async p =>
{
if (p.MBL_NO.Equals(entityInfo.MBL_NO, StringComparison.OrdinalIgnoreCase))
{
p.BOOKING_ID = bookingInfo.Id;
p.UpdatedTime = DateTime.Now;
p.UpdatedUserId = UserManager.UserId;
p.UpdatedUserName = UserManager.Name;
await _taskCutDateChangeDetailInfoRepository.AsUpdateable(p).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 发送邮件通知给客户
/// <summary>
/// 发送邮件通知给客户
/// </summary>
/// <param name="taskPKId">起运港未提箱通知主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskManageCutDate/SendEmailToCustomer")]
public async Task<TaskManageOrderResultDto> SendEmailToCustomer(string taskPKId)
{
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
try
{
var entityInfo = _taskCutDateChangeInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskPKId);
var list = _taskCutDateChangeDetailInfoRepository.AsQueryable().Filter(null, true).Where(a => a.P_ID == entityInfo.PK_ID).ToList();
if (!entityInfo.BOOKING_ID.HasValue)
{
new EmailNoticeHelper().SendEmailNotice($"taskid={taskPKId} mblno={entityInfo.MBL_NO} 截止时间变更 转发通知邮件失败", $"taskid={taskPKId} mblno={entityInfo.MBL_NO} 当前任务没有对应的订舱订单,不能转发邮件,请先检索对应的订舱订单", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList());
throw Oops.Oh($"当前任务没有对应的订舱订单,不能转发邮件,请先检索对应的订舱订单");
}
var bookingOrderList = _bookingOrderRepository.AsQueryable().Filter(null, true).Where(a => a.Id == entityInfo.BOOKING_ID.Value && a.IsDeleted == false && a.TenantId == UserManager.TENANT_ID).ToList();
if (bookingOrderList.Count == 0)
{
new EmailNoticeHelper().SendEmailNotice($"taskid={taskPKId} mblno={entityInfo.MBL_NO} 截止时间变更 转发通知邮件失败", $"taskid={taskPKId} mblno={entityInfo.MBL_NO} 当前任务对应的订舱订单不存在或已作废", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList());
throw Oops.Oh($"当前任务对应的订舱订单不存在或已作废");
}
var bookingId = entityInfo.BOOKING_ID.Value;
var bookingContactList = _bookingOrderContactRepository.AsQueryable().Filter(null, true)
.Where(a => bookingId == a.BookingId.Value && a.IsDeleted == false).ToList();
result = await GenerateSendEmail(entityInfo, list, bookingOrderList, bookingContactList);
list.ForEach(async p =>
{
var model = _taskCutDateChangeDetailInfoRepository.AsQueryable().Filter(null, true).First(a => a.PK_ID == p.PK_ID);
if (model != null)
{
model.IS_NOTICE = true;
model.STATUS = result.succ ? "SUCC" : "FAILURE";
model.STATUS_NAME = result.succ ? "成功" : "失败";
model.NOTICE_DATE = DateTime.Now;
await _taskCutDateChangeDetailInfoRepository.AsUpdateable(model).UpdateColumns(x => new
{
x.IS_NOTICE,
x.STATUS,
x.STATUS_NAME,
x.NOTICE_DATE,
}).ExecuteCommandAsync();
}
});
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"发送邮件失败,原因:{ex.Message}";
}
return result;
}
#endregion
#region 生成并转发通知邮件
/// <summary>
/// 生成并转发通知邮件
/// </summary>
/// <param name="model"></param>
/// <param name="bookingOrderList"></param>
/// <param name="bookingContactList"></param>
/// <param name="taskBaskInfo"></param>
/// <returns></returns>
[NonAction]
private async Task<TaskManageOrderResultDto> GenerateSendEmail(TaskCutDateChangeInfo model, List<TaskCutDateChangeDetailInfo> rowList, List<BookingOrder> bookingOrderList, List<BookingOrderContact> 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<string> opEmailList = new List<string>();
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.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.LogInformation($"提取当前公共邮箱的配置完成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"));
if (printTemplate == null)
{
throw Oops.Bah(BookingErrorCode.BOOK115);
}
//读取邮件模板并填充数据
string emailHtml = GenerateSendEmailHtml(model, rowList, 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<AttachesInfo>()
};
_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.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
/// <summary>
/// 通过邮件模板生成HTML
/// </summary>
/// <param name="model"></param>
/// <param name="bookingOrderList"></param>
/// <param name="filePath"></param>
/// <param name="opUserInfo"></param>
/// <param name="tenantName"></param>
/// <returns></returns>
[NonAction]
private async Task<string> GenerateSendEmailHtml(TaskCutDateChangeInfo model, List<TaskCutDateChangeDetailInfo> rowList, List<BookingOrder> bookingOrderList,
string filePath, SysUser opUserInfo, string tenantName)
{
string result = string.Empty;
string baseHtml = string.Empty;
try
{
var opt = App.GetOptions<PrintTemplateOptions>();
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.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($"<tr><td>{rowList[i].MBL_NO}</td><td>{rowList[i].CONTA_NO}</td><td>{rowList[i].LOAD_PORT}</td><td>{(rowList[i].ETB.HasValue ? rowList[i].ETB.Value.ToString("yyyy-MM-dd HH:mm") : "")}</td><td>{(rowList[i].ETD.HasValue ? rowList[i].ETD.Value.ToString("yyyy-MM-dd HH:mm") : "")}</td></tr>");
}
//生成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($"<tr><th style=\"text-align: left;\">{(string.Join("</th><th style=\"text-align: left;\">",colArg))}</th></tr>"));
StringBuilder tableBuilder = new StringBuilder();
for (int i = 0; i < rowList.Count; i++)
{
tableBuilder.Append($"<tr><td>{rowList[i].MBL_NO}</td>");
tableBuilder.Append($"<td>{($"{rowList[i].VESSEL}/{rowList[i].VOYNO}")}</td>");
tableBuilder.Append($"<td>{(rowList[i].SI_CUTOFF.HasValue ? rowList[i].SI_CUTOFF.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].SI_CUTOFF_TXT)}</td>");
tableBuilder.Append($"<td>{(rowList[i].CY_OPEN.HasValue ? rowList[i].CY_OPEN.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].CY_OPEN_TXT)}</td>");
tableBuilder.Append($"<td>{(rowList[i].CY_CUTOFF.HasValue ? rowList[i].CY_CUTOFF.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].CY_CUTOFF_TXT)}</td>");
tableBuilder.Append($"<td>{(rowList[i].MANIFEST_CUT.HasValue ? rowList[i].MANIFEST_CUT.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].MANIFEST_CUT_TXT)}</td>");
tableBuilder.Append($"<td>{(rowList[i].MDGF_CUT.HasValue ? rowList[i].MDGF_CUT.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].MDGF_CUT_TXT)}</td>");
tableBuilder.Append($"<td>{(rowList[i].VGM_CUT.HasValue ? rowList[i].VGM_CUT.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].VGM_CUT_TXT)}</td>");
tableBuilder.Append($"<td>{(rowList[i].CLOSING_DATE.HasValue ? rowList[i].CLOSING_DATE.Value.ToString("yyyy-MM-dd HH:mm") : rowList[i].CLOSING_DATE_TXT)}</td>");
tableBuilder.Append("</tr>");
}
//生成From Vessel的table列表
tableNode.ChildNodes.Add(HtmlNode.CreateNode(tableBuilder.ToString()));
}
result = html.DocumentNode.OuterHtml;
}
catch (Exception ex)
{
_logger.LogInformation($"生成截止时间变更正文失败,原因:{ex.Message}");
throw Oops.Bah($"生成截止时间变更正文失败,原因:{ex.Message}");
}
return result;
}
#endregion
#region 推送邮件
/// <summary>
/// 推送邮件
/// </summary>
/// <param name="emailApiUserDefinedDto">自定义邮件详情</param>
/// <param name="filePath">文件路径</param>
/// <returns>返回回执</returns>
[NonAction]
private async Task<CommonWebApiResult> PushEmail(EmailApiUserDefinedDto emailApiUserDefinedDto)
{
CommonWebApiResult result = new CommonWebApiResult { succ = true };
List<EmailApiUserDefinedDto> emailList = new List<EmailApiUserDefinedDto>();
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
#region 更新订舱截止时间
/// <summary>
/// 更新订舱截止时间
/// </summary>
/// <param name="taskPKId">截止时间变更任务主键</param>
/// <returns></returns>
private async Task UpdateBookingOrderCutDate(string taskPKId)
{
try
{
var taskBase = _taskBaseRepository.AsQueryable().Filter(null, true).First(a => a.PK_ID == taskPKId);
if (taskBase == null)
throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息");
var entityInfo = _taskCutDateChangeInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskBase.PK_ID);
if (entityInfo == null)
throw Oops.Oh($"截止时间变更主键{taskPKId}无法获取业务信息");
if (!entityInfo.BOOKING_ID.HasValue)
throw Oops.Oh($"截止时间变更主键{taskPKId} mblno={entityInfo.MBL_NO} 没有匹配的订舱记录,更新截止时间失败");
var bookingId = entityInfo.BOOKING_ID.Value;
//通过船名航次取是主单的订舱记录列表
var bookingInfo = _bookingOrderRepository.AsQueryable().Filter(null, true).First(a => a.Id == bookingId);
var detailInfo = _taskCutDateChangeDetailInfoRepository.AsQueryable().Filter(null, true).First(a => a.P_ID == entityInfo.PK_ID);
var oldOrder = bookingInfo.Adapt<BookingOrder>();
_logger.LogInformation($"更新订舱相关的截单时间 JSON={JSON.Serialize(detailInfo)}");
if (detailInfo.VGM_CUT.HasValue)
bookingInfo.CLOSEVGMDATE = detailInfo.VGM_CUT.Value;
if (detailInfo.CY_CUTOFF.HasValue)
bookingInfo.CLOSINGDATE = detailInfo.CY_CUTOFF.Value;
if (detailInfo.SI_CUTOFF.HasValue)
bookingInfo.CLOSEDOCDATE = detailInfo.SI_CUTOFF.Value;
_bookingOrderRepository.AsUpdateable(bookingInfo).UpdateColumns(it => new
{
it.CLOSEVGMDATE,
it.CLOSINGDATE,
it.CLOSEDOCDATE
}).ExecuteCommand();
// 保存日志
var bookingOrderService = _namedBookingOrderServiceProvider.GetService<ITransient>(nameof(BookingOrderService));
bookingOrderService.SaveLog(bookingInfo, oldOrder, "截止时间变更");
_logger.LogInformation($"截止时间变更主键{taskPKId} mblno={entityInfo.MBL_NO} 更新订舱完毕");
}
catch (Exception ex)
{
_logger.LogInformation($"taskid={taskPKId} 截止时间变更更新订舱失败");
new EmailNoticeHelper().SendEmailNotice($"taskid={taskPKId} 截止时间变更更新订舱失败", $"taskid={taskPKId} 截止时间变更更新订舱失败,原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList());
}
}
#endregion
#region 更新舱位截止时间
/// <summary>
/// 更新舱位截止时间
/// </summary>
/// <param name="taskPKId">截止时间变更任务主键</param>
/// <returns></returns>
private async Task UpdateBookingSlotCutDate(string taskPKId)
{
try
{
var taskBase = _taskBaseRepository.AsQueryable().Filter(null, true).First(a => a.PK_ID == taskPKId);
if (taskBase == null)
throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息");
var entityInfo = _taskCutDateChangeInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskBase.PK_ID);
if (entityInfo == null)
throw Oops.Oh($"截止时间变更主键{taskPKId}无法获取业务信息");
var detailInfo = _taskCutDateChangeDetailInfoRepository.AsQueryable().Filter(null, true).First(a => a.P_ID == entityInfo.PK_ID);
//判断是否有舱位,需要更新舱位
var slotOrder = _bookingSlotBaseRepository.AsQueryable().Filter(null, true)
.First(x => entityInfo.MBL_NO.Equals(x.SLOT_BOOKING_NO)
&& x.IsDeleted == false && x.TenantId == UserManager.TENANT_ID);
var oldOrder = slotOrder.Adapt<BookingSlotBaseApiSaveDto>();
_logger.LogInformation($"更新订舱相关的截单时间 JSON={JSON.Serialize(entityInfo)}");
if (detailInfo.VGM_CUT.HasValue)
slotOrder.VGM_SUBMISSION_CUT_DATE = detailInfo.VGM_CUT.Value;
if (detailInfo.CY_CUTOFF.HasValue)
slotOrder.CY_CUT_DATE = detailInfo.CY_CUTOFF;
if (detailInfo.SI_CUTOFF.HasValue)
slotOrder.SI_CUT_DATE = detailInfo.SI_CUTOFF;
if (detailInfo.MDGF_CUT.HasValue)
slotOrder.MDGF_CUT_DATE = detailInfo.MDGF_CUT;
if (detailInfo.MANIFEST_CUT.HasValue)
slotOrder.MANIFEST_CUT_DATE = detailInfo.MANIFEST_CUT;
_bookingSlotBaseRepository.AsUpdateable(slotOrder).UpdateColumns(it => new
{
it.VGM_SUBMISSION_CUT_DATE,
it.CY_CUT_DATE,
it.SI_CUT_DATE,
it.MDGF_CUT_DATE,
it.MANIFEST_CUT_DATE
}).ExecuteCommand();
_logger.LogInformation($"截止时间变更主键{taskPKId} mblno={entityInfo.MBL_NO} 更新舱位完毕");
}
catch (Exception ex)
{
_logger.LogInformation($"taskid={taskPKId} 截止时间变更更新舱位失败");
new EmailNoticeHelper().SendEmailNotice($"taskid={taskPKId} 截止时间变更更新舱位失败", $"taskid={taskPKId} 截止时间变更更新舱位失败,原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList());
}
}
#endregion
}
}