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/TaskTransPlanHasChangeServi...

1148 lines
51 KiB
C#

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
{
/// <summary>
/// 货物运输计划已变更
/// </summary>
[ApiDescriptionSettings("Application", Name = "TaskTransPlanHasChange", Order = 10)]
public class TaskTransPlanHasChangeService : ITaskTransPlanHasChangeService, IDynamicApiController, ITransient
{
private readonly ISysCacheService _cache;
private readonly ILogger<TaskTransPlanHasChangeService> _logger;
private readonly SqlSugarRepository<TaskBaseInfo> _taskBaseRepository;
private readonly SqlSugarRepository<TaskTransPlanHasChangeInfo> _taskTransPlanHasChangeInfoRepository;
private readonly SqlSugarRepository<TaskTransPlanHasChangeDetailInfo> _taskTransPlanHasChangeDetailInfoRepository;
private readonly SqlSugarRepository<DjyUserMailAccount> _djyUserMailAccount;
private readonly SqlSugarRepository<BookingOrder> _bookingOrderRepository;
private readonly SqlSugarRepository<BookingOrderContact> _bookingOrderContactRepository;
private readonly SqlSugarRepository<SysUser> _sysUserRepository;
private readonly SqlSugarRepository<BookingPrintTemplate> _repPrintTemplate;
private readonly SqlSugarRepository<TaskFileInfo> _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<TaskTransPlanHasChangeService> logger,
SqlSugarRepository<TaskBaseInfo> taskBaseRepository,
SqlSugarRepository<TaskTransPlanHasChangeInfo> taskTransPlanHasChangeInfoRepository,
SqlSugarRepository<TaskTransPlanHasChangeDetailInfo> taskTransPlanHasChangeDetailInfoRepository,
SqlSugarRepository<DjyUserMailAccount> djyUserMailAccount,
SqlSugarRepository<BookingOrderContact> bookingOrderContactRepository,
SqlSugarRepository<SysUser> sysUserRepository,
SqlSugarRepository<BookingPrintTemplate> repPrintTemplate,
SqlSugarRepository<TaskFileInfo> taskFileRepository,
IDjyTenantParamService djyTenantParamService,
SqlSugarRepository<BookingOrder> 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 获取货物运输计划已变更详情
/// <summary>
/// 获取货物运输计划已变更详情
/// </summary>
/// <param name="taskPkId">货物运输计划已变更任务主键</param>
/// <returns>返回详情</returns>
[HttpGet("/TaskTransPlanHasChange/GetInfoByTaskId")]
public async Task<TaskTransPlanHasChangeShowDto> GetInfoByTaskId(string taskPkId)
{
return InnerGetInfo(taskPkId);
}
#endregion
#region 获取货物运输计划已变更详情(内部方法)
/// <summary>
/// 获取货物运输计划已变更详情(内部方法)
/// </summary>
/// <param name="taskPkId">货物运输计划已变更任务主键</param>
/// <returns></returns>
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<TaskTransPlanHasChangePortShow>(),
dateList = new List<TaskTransPlanHasChangeDateShow>(),
vesselList = new List<TaskTransPlanHasChangeVesselShow>()
};
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<TaskTransPlanHasChangePortShow>(),
dateList = new List<TaskTransPlanHasChangeDateShow>(),
vesselList = new List<TaskTransPlanHasChangeVesselShow>()
};
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 自动转发货物运输计划已变更
/// <summary>
/// 自动转发货物运输计划已变更
/// </summary>
/// <param name="taskPKId">货物运输计划已变更任务主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskTransPlanHasChange/AutoTransferNotice")]
public async Task<TaskManageOrderResultDto> 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 按照列表批次号提取同批次货物运输计划已变更记录
/// <summary>
/// 按照列表批次号提取同批次货物运输计划已变更记录
/// </summary>
/// <param name="groupBatchNo">列表批次号</param>
/// <returns></returns>
[NonAction]
private List<TaskTransPlanHasChangeShowDto> GetListByGroupBatchNo(string groupBatchNo)
{
List<TaskTransPlanHasChangeShowDto> list = new List<TaskTransPlanHasChangeShowDto>();
var dataList = _taskTransPlanHasChangeInfoRepository.AsQueryable().Filter(null, true)
.InnerJoin<TaskTransPlanHasChangeDetailInfo>((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<TaskTransPlanHasChangePortShow>(),
dateList = new List<TaskTransPlanHasChangeDateShow>(),
vesselList = new List<TaskTransPlanHasChangeVesselShow>()
};
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<TaskTransPlanHasChangePortShow>(),
dateList = new List<TaskTransPlanHasChangeDateShow>(),
vesselList = new List<TaskTransPlanHasChangeVesselShow>()
};
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 检索对应的订舱订单
/// <summary>
/// 检索对应的订舱订单
/// </summary>
/// <param name="taskPKId">货物运输计划已变更任务主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskTransPlanHasChange/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 = _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 发送邮件通知给客户
/// <summary>
/// 发送邮件通知给客户
/// </summary>
/// <param name="taskPKId">货物运输计划已变更主键</param>
/// <returns>返回回执</returns>
[HttpGet("/TaskTransPlanHasChange/taskPKId")]
public async Task<TaskManageOrderResultDto> 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 生成并转发通知邮件
/// <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(TaskTransPlanHasChangeShowDto model, 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.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<AttachesInfo>()
};
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.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
/// <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(TaskTransPlanHasChangeShowDto model, 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.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("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" >");
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("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: rgb(157 157 157);") + "margin: 0; padding: 0;\">" + (string.Concat(x.PortName, ",", x.CountryCode, ",", x.TerminalName)) + "</p></td></tr>");
}
else
{
portBuilder.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: green;") + "margin: 0; padding: 0;\">" + (string.Concat(x.PortName, ",", x.CountryCode, ",", x.TerminalName)) + "</p></td></tr>");
}
});
if (model.From.portList.Count < maxLens)
{
for (int p = 0; p < (maxLens - model.From.portList.Count); p++)
{
portBuilder.Append("<tr><td><p style=\"margin: 0; padding: 0;\"></td></tr>");
}
}
portBuilder.Append("</table>");
//生成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("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" >");
model.From.dateList.ForEach(x => {
if (model.From.dateList.Count == 1)
{
dateBuilder.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: rgb(157 157 157);") + "margin: 0; padding: 0;\">" + (x.DateVal.HasValue ? x.DateVal.Value.ToString("yyyy-MM-dd HH:mm:ss") : "") + "</p></td></tr>");
}
else
{
dateBuilder.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: green;") + "margin: 0; padding: 0;\">" + (x.DateVal.HasValue ? x.DateVal.Value.ToString("yyyy-MM-dd HH:mm:ss") : "") + "</p></td></tr>");
}
});
if (model.From.dateList.Count < maxLens)
{
for (int p = 0; p < (maxLens - model.From.dateList.Count); p++)
{
dateBuilder.Append("<tr><td></td></tr>");
}
}
dateBuilder.Append("</table>");
//生成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("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" >");
model.From.vesselList.ForEach(x => {
if (model.From.vesselList.Count == 1)
{
vesselBuilder.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: rgb(157 157 157);") + "margin: 0; padding: 0;\">" + (string.Concat(x.Vessel, ",", x.Voyno, ",", x.Flag)) + "</p></td></tr>");
}
else
{
vesselBuilder.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: green;") + "margin: 0; padding: 0;\">" + (string.Concat(x.Vessel, ",", x.Voyno, ",", x.Flag)) + "</p></td></tr>");
}
});
if (model.From.vesselList.Count < maxLens)
{
for (int p = 0; p < (maxLens - model.From.vesselList.Count); p++)
{
vesselBuilder.Append("<tr><td></td></tr>");
}
}
vesselBuilder.Append("</table>");
//生成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("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" >");
model.To.portList.ForEach(x => {
if(model.To.portList.Count == 1)
{
portBuilder2.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: rgb(157 157 157);") + "margin: 0; padding: 0;\">" + (string.Concat(x.PortName, ",", x.CountryCode, ",", x.TerminalName)) + "</p></td></tr>");
}
else
{
portBuilder2.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: green;") + "margin: 0; padding: 0;\">" + (string.Concat(x.PortName, ",", x.CountryCode, ",", x.TerminalName)) + "</p></td></tr>");
}
});
if (model.To.portList.Count < maxLens2)
{
for (int p = 0; p < (maxLens2 - model.To.portList.Count); p++)
{
portBuilder2.Append("<tr><td></td></tr>");
}
}
portBuilder2.Append("</table>");
//生成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("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" >");
model.To.dateList.ForEach(x => {
if (model.To.dateList.Count == 1)
{
dateBuilder2.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: rgb(157 157 157);") + "margin: 0; padding: 0;\">" + (x.DateVal.HasValue ? x.DateVal.Value.ToString("yyyy-MM-dd HH:mm:ss") : "") + "</p></td></tr>");
}
else
{
dateBuilder2.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: green;") + "margin: 0; padding: 0;\">" + (x.DateVal.HasValue ? x.DateVal.Value.ToString("yyyy-MM-dd HH:mm:ss") : "") + "</p></td></tr>");
}
});
if (model.To.dateList.Count < maxLens)
{
for (int p = 0; p < (maxLens2 - model.To.dateList.Count); p++)
{
dateBuilder2.Append("<tr><td></td></tr>");
}
}
dateBuilder2.Append("</table>");
//生成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("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" >");
model.To.vesselList.ForEach(x => {
if (model.To.vesselList.Count == 1)
{
vesselBuilder2.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: rgb(157 157 157);") + "margin: 0; padding: 0;\">" + (string.Concat(x.Vessel, ",", x.Voyno, ",", x.Flag)) + "</p></td></tr>");
}
else
{
vesselBuilder2.Append("<tr><td><p style=\"" + (x.IsRemoved ? "text-decoration: line-through;color: #f70f0f;" : "color: green;") + "margin: 0; padding: 0;\">" + (string.Concat(x.Vessel, ",", x.Voyno, ",", x.Flag)) + "</p></td></tr>");
}
});
if (model.To.vesselList.Count < maxLens)
{
for (int p = 0; p < (maxLens2 - model.To.vesselList.Count); p++)
{
vesselBuilder2.Append("<tr><td></td></tr>");
}
}
vesselBuilder2.Append("</table>");
//生成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 推送邮件
/// <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
}
}