|
|
|
|
using Furion;
|
|
|
|
|
using Furion.DynamicApiController;
|
|
|
|
|
using Furion.FriendlyException;
|
|
|
|
|
using Furion.JsonSerialization;
|
|
|
|
|
using Furion.RemoteRequest.Extensions;
|
|
|
|
|
using HtmlAgilityPack;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Myshipping.Application.ConfigOption;
|
|
|
|
|
using Myshipping.Application.Entity;
|
|
|
|
|
using Myshipping.Core;
|
|
|
|
|
using Myshipping.Core.Entity;
|
|
|
|
|
using Myshipping.Core.Service;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Web;
|
|
|
|
|
|
|
|
|
|
namespace Myshipping.Application
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// DRAFT任务
|
|
|
|
|
/// </summary>
|
|
|
|
|
[ApiDescriptionSettings("Application", Name = "TaskManageDRAFT", Order = 10)]
|
|
|
|
|
public class TaskManageDRAFTService: ITaskManageDRAFTService, IDynamicApiController
|
|
|
|
|
{
|
|
|
|
|
private readonly ISysCacheService _cache;
|
|
|
|
|
private readonly ILogger<TaskManageDRAFTService> _logger;
|
|
|
|
|
private readonly SqlSugarRepository<TaskBaseInfo> _taskBaseRepository;
|
|
|
|
|
private readonly SqlSugarRepository<TaskFileInfo> _taskFileRepository;
|
|
|
|
|
private readonly SqlSugarRepository<TaskDraftInfo> _taskDraftInfoRepository;
|
|
|
|
|
private readonly SqlSugarRepository<DjyUserMailAccount> _djyUserMailAccount;
|
|
|
|
|
private readonly SqlSugarRepository<BookingOrderContact> _bookingOrderContactRepository;
|
|
|
|
|
private readonly SqlSugarRepository<BookingOrder> _bookingOrderRepository;
|
|
|
|
|
private readonly SqlSugarRepository<SysUser> _sysUserRepository;
|
|
|
|
|
private readonly IDjyCustomerService _djyCustomerService;
|
|
|
|
|
|
|
|
|
|
public TaskManageDRAFTService(SqlSugarRepository<TaskBaseInfo> taskBaseRepository,
|
|
|
|
|
SqlSugarRepository<TaskFileInfo> taskFileRepository,
|
|
|
|
|
SqlSugarRepository<TaskDraftInfo> taskDraftInfoRepository,
|
|
|
|
|
SqlSugarRepository<DjyUserMailAccount> djyUserMailAccount,
|
|
|
|
|
SqlSugarRepository<BookingOrderContact> bookingOrderContactRepository,
|
|
|
|
|
SqlSugarRepository<BookingOrder> bookingOrderRepository,
|
|
|
|
|
SqlSugarRepository<SysUser> sysUserRepository,
|
|
|
|
|
IDjyCustomerService djyCustomerService,
|
|
|
|
|
ISysCacheService cache,
|
|
|
|
|
ILogger<TaskManageDRAFTService> logger)
|
|
|
|
|
{
|
|
|
|
|
_taskBaseRepository = taskBaseRepository;
|
|
|
|
|
_taskFileRepository = taskFileRepository;
|
|
|
|
|
_taskDraftInfoRepository = taskDraftInfoRepository;
|
|
|
|
|
_bookingOrderRepository = bookingOrderRepository;
|
|
|
|
|
_bookingOrderContactRepository = bookingOrderContactRepository;
|
|
|
|
|
_djyUserMailAccount = djyUserMailAccount;
|
|
|
|
|
|
|
|
|
|
_djyCustomerService = djyCustomerService;
|
|
|
|
|
_sysUserRepository = sysUserRepository;
|
|
|
|
|
|
|
|
|
|
_logger = logger;
|
|
|
|
|
_cache = cache;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region 获取DRAFT详情
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取DRAFT详情
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="pkId">DRAFT主键</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
[HttpGet("/TaskManageDRAFT/GetInfo")]
|
|
|
|
|
public async Task<TaskDraftShowDto> GetInfo(string pkId)
|
|
|
|
|
{
|
|
|
|
|
TaskDraftShowDto dto = new TaskDraftShowDto();
|
|
|
|
|
|
|
|
|
|
var draft = _taskDraftInfoRepository.AsQueryable().First(a => a.PK_ID == pkId);
|
|
|
|
|
|
|
|
|
|
if (draft == null)
|
|
|
|
|
throw Oops.Oh($"DRAFT主键{pkId}无法获取业务信息");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == draft.TASK_ID);
|
|
|
|
|
|
|
|
|
|
if (taskBase == null)
|
|
|
|
|
throw Oops.Oh($"任务主键无法获取业务信息");
|
|
|
|
|
|
|
|
|
|
dto = new TaskDraftShowDto
|
|
|
|
|
{
|
|
|
|
|
PKId = draft.PK_ID,
|
|
|
|
|
TaskId = draft.TASK_ID,
|
|
|
|
|
Carrier = draft.CARRIER,
|
|
|
|
|
BookingId = draft.BOOKING_ID,
|
|
|
|
|
MBlNo = draft.MBL_NO,
|
|
|
|
|
NoticeDate = draft.NOTICE_DATE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (dto != null)
|
|
|
|
|
{
|
|
|
|
|
dto.IsComplete = taskBase.IS_COMPLETE == 1 ? true : false;
|
|
|
|
|
dto.CompleteTime = taskBase.COMPLETE_DATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dto;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 通过任务主键获取DRAFT详情
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过任务主键获取DRAFT详情
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="taskPkId">DRAFT任务主键</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
[HttpGet("/TaskManageDRAFT/GetInfoByTaskId")]
|
|
|
|
|
public async Task<TaskDraftShowDto> GetInfoByTaskId(string taskPkId)
|
|
|
|
|
{
|
|
|
|
|
TaskDraftShowDto dto = new TaskDraftShowDto();
|
|
|
|
|
|
|
|
|
|
var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId);
|
|
|
|
|
|
|
|
|
|
if (taskBase == null)
|
|
|
|
|
throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息");
|
|
|
|
|
|
|
|
|
|
var draft = _taskDraftInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID);
|
|
|
|
|
|
|
|
|
|
if (draft == null)
|
|
|
|
|
throw Oops.Oh($"DRAFT主键{taskPkId}无法获取业务信息");
|
|
|
|
|
|
|
|
|
|
dto = new TaskDraftShowDto
|
|
|
|
|
{
|
|
|
|
|
PKId = draft.PK_ID,
|
|
|
|
|
TaskId = draft.TASK_ID,
|
|
|
|
|
Carrier = draft.CARRIER,
|
|
|
|
|
BookingId = draft.BOOKING_ID,
|
|
|
|
|
MBlNo = draft.MBL_NO,
|
|
|
|
|
NoticeDate = draft.NOTICE_DATE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (dto != null)
|
|
|
|
|
{
|
|
|
|
|
dto.IsComplete = taskBase.IS_COMPLETE == 1 ? true : false;
|
|
|
|
|
dto.CompleteTime = taskBase.COMPLETE_DATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dto;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 任务ID下载附件
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 任务ID下载附件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="taskPKId">DRAFT任务主键</param>
|
|
|
|
|
/// <param name="fileCategory">附件分类代码</param>
|
|
|
|
|
/// <returns>返回数据流</returns>
|
|
|
|
|
[HttpGet("/TaskManageDRAFT/DownloadFile")]
|
|
|
|
|
public async Task<IActionResult> DownloadFile([FromQuery] string taskPKId, [FromQuery] string fileCategory = "DRAFT")
|
|
|
|
|
{
|
|
|
|
|
var bcTaskInfo = await _taskBaseRepository.AsQueryable().FirstAsync(u => u.PK_ID == taskPKId);
|
|
|
|
|
if (bcTaskInfo == null)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TaskFileCategoryEnum fileCategoryEnum = TaskFileCategoryEnum.NONE;
|
|
|
|
|
|
|
|
|
|
System.Enum.TryParse(fileCategory, out fileCategoryEnum);
|
|
|
|
|
|
|
|
|
|
if (fileCategoryEnum == TaskFileCategoryEnum.NONE)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"附件分类代码错误,请提供正确的分类代码");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string name = fileCategoryEnum.ToString();
|
|
|
|
|
|
|
|
|
|
var fileInfo = await _taskFileRepository.AsQueryable().FirstAsync(u => u.TASK_PKID == taskPKId && u.FILE_CATEGORY == name);
|
|
|
|
|
|
|
|
|
|
if (fileInfo == null)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"任务主键{taskPKId}没有可下载的附件");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var opt = App.GetOptions<BookingAttachOptions>();
|
|
|
|
|
var dirAbs = opt.basePath;
|
|
|
|
|
if (string.IsNullOrEmpty(dirAbs))
|
|
|
|
|
{
|
|
|
|
|
dirAbs = App.WebHostEnvironment.WebRootPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var fileFullPath = Path.Combine(dirAbs, fileInfo.FILE_PATH);
|
|
|
|
|
if (!File.Exists(fileFullPath))
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"任务主键{taskPKId} 附件下载请求失败,请确认文件是否存在");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"taskPKId={taskPKId} 下载文件完整路径 fileFullPath={fileFullPath}");
|
|
|
|
|
|
|
|
|
|
var fileName = HttpUtility.UrlEncode(fileInfo.FILE_NAME, Encoding.GetEncoding("UTF-8"));
|
|
|
|
|
var result = new FileStreamResult(new FileStream(fileFullPath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 发送邮件
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 发送邮件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="taskPKId">DRAFT任务主键</param>
|
|
|
|
|
/// <param name="usePersonalEmailSend">是否使用个人邮箱发送</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
[HttpGet("/TaskManageDRAFT/SendEmail")]
|
|
|
|
|
public async Task<TaskManageOrderResultDto> SendEmail(string taskPKId, bool usePersonalEmailSend = false)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(taskPKId))
|
|
|
|
|
throw Oops.Oh($"DRAFT任务主键不能为空");
|
|
|
|
|
|
|
|
|
|
var bcTaskInfo = await _taskBaseRepository.AsQueryable().FirstAsync(u => u.PK_ID == taskPKId);
|
|
|
|
|
if (bcTaskInfo == null)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var draft = _taskDraftInfoRepository.AsQueryable().First(a => a.TASK_ID == bcTaskInfo.PK_ID);
|
|
|
|
|
|
|
|
|
|
if (draft == null)
|
|
|
|
|
throw Oops.Oh($"任务主键{taskPKId}无法获取DRAFT业务信息");
|
|
|
|
|
|
|
|
|
|
return await GenerateSendEmail(draft, usePersonalEmailSend);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 生成并推送邮件
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 生成并推送邮件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="taskDraftInfo">DRAFT任务详情</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
private async Task<TaskManageOrderResultDto> GenerateSendEmail(TaskDraftInfo taskDraftInfo, bool usePersonalEmailSend = false)
|
|
|
|
|
{
|
|
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
1、提取邮件接收人、通过订舱的委托客户获取联系人信息(提取联系人中备注是BCNotice的邮箱)
|
|
|
|
|
2、提取当票订舱对应的操作人邮箱、通过订舱的委托客户获取操作OP的邮箱
|
|
|
|
|
3、读取用户邮箱配置,主要提取显示名称BCNotice的邮箱,用来作为公共邮箱来发送邮件。
|
|
|
|
|
4、读取邮件模板,填充详情。
|
|
|
|
|
5、推送邮件给邮件接收人
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
//读取订舱数据
|
|
|
|
|
var bookingOrderEntity = _bookingOrderRepository.AsQueryable()
|
|
|
|
|
.First(a => a.Id == taskDraftInfo.BOOKING_ID);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bookingOrderEntity == null)
|
|
|
|
|
{
|
|
|
|
|
var checkInfo = _bookingOrderRepository.AsQueryable().Filter(null, true)
|
|
|
|
|
.First(a => a.MBLNO == taskDraftInfo.MBL_NO && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0));
|
|
|
|
|
|
|
|
|
|
if (checkInfo != null)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"订舱详情获取失败,用提单号能检索到,但是没有ID关系,需要人工看看问题");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"订舱详情获取失败,请确认订舱是否存在或已删除");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"获取订舱详情完成,bookid={bookingOrderEntity.Id}");
|
|
|
|
|
|
|
|
|
|
if (!bookingOrderEntity.CUSTOMERID.HasValue || (bookingOrderEntity.CUSTOMERID.HasValue && bookingOrderEntity.CUSTOMERID.Value == 0))
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"订舱的委托客户不能为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var djyCustomerInfo = _djyCustomerService.Detail(new GetDjyCustomerInput { Id = bookingOrderEntity.CUSTOMERID.Value })
|
|
|
|
|
.GetAwaiter().GetResult();
|
|
|
|
|
|
|
|
|
|
if (djyCustomerInfo == null)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"委托单位详情获取失败,请确认委托单位是否存在或已删除");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"获取委托单位详情完成,djyCustomerId={djyCustomerInfo.Id}");
|
|
|
|
|
|
|
|
|
|
//DjyCustomerContactOutput djyCustomerContactMan = null;
|
|
|
|
|
|
|
|
|
|
//TO 邮件接收人
|
|
|
|
|
string toEmail = string.Empty;
|
|
|
|
|
//订舱OP的邮箱
|
|
|
|
|
string opEmail = string.Empty;
|
|
|
|
|
|
|
|
|
|
var bookingContactList = _bookingOrderContactRepository.AsQueryable()
|
|
|
|
|
.Where(a => a.BookingId == taskDraftInfo.BOOKING_ID).ToList();
|
|
|
|
|
|
|
|
|
|
if (bookingContactList == null || bookingContactList.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation($"当前订舱未指定的联系人,toEmail={toEmail}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
toEmail = string.Join(";", bookingContactList.Select(x => x.Email.Trim()).Distinct().ToArray());
|
|
|
|
|
|
|
|
|
|
//获取操作OP的邮箱
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(bookingOrderEntity.OPID))
|
|
|
|
|
{
|
|
|
|
|
var opId = long.Parse(bookingOrderEntity.OPID);
|
|
|
|
|
var opUser = _sysUserRepository.AsQueryable().First(a => a.Id == opId);
|
|
|
|
|
|
|
|
|
|
if (opUser != null && !string.IsNullOrWhiteSpace(opUser.Email))
|
|
|
|
|
{
|
|
|
|
|
opEmail = opUser.Email.Trim();
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"获取操作OP的邮箱,opEmail={opEmail} id={opId} name={opUser.Name}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//提取当前公共邮箱的配置
|
|
|
|
|
var publicMailAccount = _djyUserMailAccount.FirstOrDefault(x => x.CreatedUserId == UserManager.UserId
|
|
|
|
|
&& x.SmtpPort > 0 && x.SmtpServer != null && x.SmtpServer != "");
|
|
|
|
|
|
|
|
|
|
if (publicMailAccount == null)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"提取公共邮箱配置失败,请在用户邮箱账号管理增加配置显示名为BCNotice");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"提取当前公共邮箱的配置完成,id={publicMailAccount.Id}");
|
|
|
|
|
|
|
|
|
|
string emailTitle = $"Draft : {taskDraftInfo.MBL_NO}";
|
|
|
|
|
|
|
|
|
|
string filePath = string.Empty;
|
|
|
|
|
|
|
|
|
|
SysUser opUserInfo = null;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(bookingOrderEntity.OPID) && Regex.IsMatch(bookingOrderEntity.OPID, "[0-9]+"))
|
|
|
|
|
opUserInfo = _sysUserRepository.AsQueryable().First(u => u.Id == long.Parse(bookingOrderEntity.OPID));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//读取邮件模板并填充数据
|
|
|
|
|
string emailHtml = GenerateSendEmailHtml(taskDraftInfo, opUserInfo, UserManager.TENANT_NAME).GetAwaiter().GetResult();
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"生成邮件BODY,结果:{emailHtml}");
|
|
|
|
|
|
|
|
|
|
var fileInfo = _taskFileRepository.AsQueryable().Where(a => a.TASK_PKID == taskDraftInfo.TASK_ID && a.FILE_CATEGORY.Contains("draft_notice"))
|
|
|
|
|
.OrderByDescending(a => a.CreatedTime).First();
|
|
|
|
|
|
|
|
|
|
if (fileInfo == null)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Oh($"提取DRAFT的文件失败,不能发送邮件");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"获取订舱附件地址,结果:{fileInfo.FILE_PATH}");
|
|
|
|
|
|
|
|
|
|
var opt = App.GetOptions<BookingAttachOptions>();
|
|
|
|
|
var dirAbs = opt.basePath;
|
|
|
|
|
if (string.IsNullOrEmpty(dirAbs))
|
|
|
|
|
{
|
|
|
|
|
dirAbs = App.WebHostEnvironment.WebRootPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filePath = Path.Combine(dirAbs, fileInfo.FILE_PATH);
|
|
|
|
|
|
|
|
|
|
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, filePath);
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"推送邮件完成,结果:{JSON.Serialize(emailRlt)}");
|
|
|
|
|
|
|
|
|
|
result.succ = true;
|
|
|
|
|
result.msg = "成功";
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation($"推送邮件失败,异常:{ex.Message}");
|
|
|
|
|
|
|
|
|
|
result.succ = false;
|
|
|
|
|
result.msg = $"推送邮件失败,{ex.Message}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 通过邮件模板生成HTML
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过邮件模板生成HTML
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="taskBCInfo">BC任务详情</param>
|
|
|
|
|
/// <param name="opUserInfo">订舱OP详情</param>
|
|
|
|
|
/// <param name="tenantName">当前租户全称</param>
|
|
|
|
|
/// <returns>返回生成的HTML</returns>
|
|
|
|
|
private async Task<string> GenerateSendEmailHtml(TaskDraftInfo taskDraftInfo, SysUser opUserInfo, string tenantName)
|
|
|
|
|
{
|
|
|
|
|
string result = string.Empty;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
1、加载模板文件,读取HTML
|
|
|
|
|
2、读取main、conta的tr行,替换业务数据
|
|
|
|
|
3、返回HTML的文本信息。
|
|
|
|
|
*/
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
string templatePath = App.Configuration["EmailTemplateFilePath"];
|
|
|
|
|
|
|
|
|
|
var opt = App.GetOptions<BookingAttachOptions>();
|
|
|
|
|
var dirAbs = opt.basePath;
|
|
|
|
|
if (string.IsNullOrEmpty(dirAbs))
|
|
|
|
|
{
|
|
|
|
|
dirAbs = App.WebHostEnvironment.WebRootPath;
|
|
|
|
|
}
|
|
|
|
|
templatePath = $"{dirAbs}{templatePath}\\DraftEmailTemplate.html";
|
|
|
|
|
|
|
|
|
|
string baseHtml = File.ReadAllText(templatePath);
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(baseHtml))
|
|
|
|
|
throw Oops.Oh($"读取邮件模板失败");
|
|
|
|
|
|
|
|
|
|
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#", "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HtmlDocument html = new HtmlDocument();
|
|
|
|
|
html.LoadHtml(baseHtml);
|
|
|
|
|
|
|
|
|
|
HtmlNode baseTable = html.DocumentNode.SelectNodes("//table[@class='base-table']").FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
if (baseTable == null)
|
|
|
|
|
throw Oops.Oh($"读取邮件模板格式错误,定位base-table失败");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var baseTrList = baseTable.SelectNodes(".//tr");
|
|
|
|
|
|
|
|
|
|
foreach (var baseTr in baseTrList)
|
|
|
|
|
{
|
|
|
|
|
var tdList = baseTr.SelectNodes(".//td");
|
|
|
|
|
|
|
|
|
|
foreach (var baseTd in tdList)
|
|
|
|
|
{
|
|
|
|
|
if (baseTd.Attributes["class"].Value == "billno-val")
|
|
|
|
|
{
|
|
|
|
|
baseTd.InnerHtml = taskDraftInfo.MBL_NO;
|
|
|
|
|
}
|
|
|
|
|
else if (baseTd.Attributes["class"].Value == "carrier-val")
|
|
|
|
|
{
|
|
|
|
|
baseTd.InnerHtml = taskDraftInfo.CARRIER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var noreplyTr = html.DocumentNode.SelectNodes("//tr[@class='email-noreply']").FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
if (noreplyTr != null)
|
|
|
|
|
{
|
|
|
|
|
var currTd = noreplyTr.SelectNodes(".//td").FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
if (currTd != null)
|
|
|
|
|
{
|
|
|
|
|
var currPList = currTd.SelectNodes(".//p");
|
|
|
|
|
|
|
|
|
|
foreach (var baseP in currPList)
|
|
|
|
|
{
|
|
|
|
|
if (baseP.Attributes["class"].Value == "notice-comp-val")
|
|
|
|
|
{
|
|
|
|
|
baseP.InnerHtml = tenantName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = html.DocumentNode.OuterHtml;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation($"通过邮件模板生成HTML异常,原因={ex.Message}");
|
|
|
|
|
|
|
|
|
|
throw ex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 推送邮件
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 推送邮件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="emailApiUserDefinedDto">自定义邮件详情</param>
|
|
|
|
|
/// <param name="filePath">文件路径</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
private async Task<CommonWebApiResult> PushEmail(EmailApiUserDefinedDto emailApiUserDefinedDto, string filePath)
|
|
|
|
|
{
|
|
|
|
|
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 请联系管理员");
|
|
|
|
|
|
|
|
|
|
System.IO.FileStream file = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read);
|
|
|
|
|
int SplitSize = 5242880;//5M分片长度
|
|
|
|
|
int index = 1; //序号 第几片
|
|
|
|
|
long StartPosition = 5242880 * (index - 1);
|
|
|
|
|
long lastLens = file.Length - StartPosition;//真不知道怎么起命了,就这样吧
|
|
|
|
|
if (lastLens < 5242880)
|
|
|
|
|
{
|
|
|
|
|
SplitSize = (int)lastLens;
|
|
|
|
|
}
|
|
|
|
|
byte[] heByte = new byte[SplitSize];
|
|
|
|
|
file.Seek(StartPosition, SeekOrigin.Begin);
|
|
|
|
|
//第一个参数是 起始位置
|
|
|
|
|
file.Read(heByte, 0, SplitSize);
|
|
|
|
|
//第三个参数是 读取长度(剩余长度)
|
|
|
|
|
file.Close();
|
|
|
|
|
|
|
|
|
|
string base64Str = Convert.ToBase64String(heByte);
|
|
|
|
|
|
|
|
|
|
emailApiUserDefinedDto.Attaches.Add(new AttachesInfo
|
|
|
|
|
{
|
|
|
|
|
AttachName = Path.GetFileName(filePath),
|
|
|
|
|
AttachContent = base64Str
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
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($"邮件上传完成 上传文件大小:{heByte.Length} 用时:{timeDiff}ms.,{strJoin}");
|
|
|
|
|
|
|
|
|
|
_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 重新处理DRAFT任务
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 重新处理DRAFT任务
|
|
|
|
|
/// 对未匹配订舱订单的任务记录重新对应订舱订单
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="taskPkId">DRAFT任务主键</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpGet("/TaskManageDRAFT/SearchAndConnectBookingInfo")]
|
|
|
|
|
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 draft = _taskDraftInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID);
|
|
|
|
|
|
|
|
|
|
if (draft == null)
|
|
|
|
|
throw Oops.Oh($"DRAFT主键{taskPkId}无法获取业务信息");
|
|
|
|
|
|
|
|
|
|
if (draft.BOOKING_ID.HasValue)
|
|
|
|
|
throw Oops.Oh($"当前DRAFT已有匹配的订舱订单");
|
|
|
|
|
|
|
|
|
|
string mblNo = draft.MBL_NO.ToUpper().Trim();
|
|
|
|
|
|
|
|
|
|
var bookingInfo = _bookingOrderRepository.AsQueryable().Filter(null, true)
|
|
|
|
|
.First(a => a.MBLNO == mblNo && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0));
|
|
|
|
|
|
|
|
|
|
if (bookingInfo == null)
|
|
|
|
|
throw Oops.Oh($"提单号{mblNo}未提取有效的订舱订单");
|
|
|
|
|
|
|
|
|
|
draft.BOOKING_ID = bookingInfo.Id;
|
|
|
|
|
draft.UpdatedUserId = UserManager.UserId;
|
|
|
|
|
draft.UpdatedUserName = UserManager.Name;
|
|
|
|
|
|
|
|
|
|
//更新任务
|
|
|
|
|
await _taskDraftInfoRepository.AsUpdateable(draft).UpdateColumns(it => new
|
|
|
|
|
{
|
|
|
|
|
it.BOOKING_ID,
|
|
|
|
|
it.UpdatedTime,
|
|
|
|
|
it.UpdatedUserId,
|
|
|
|
|
it.UpdatedUserName
|
|
|
|
|
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
result.succ = true;
|
|
|
|
|
result.msg = "成功";
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|