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; namespace Myshipping.Application { /// /// 船舶相关截止时间的通知 /// [ApiDescriptionSettings("Application", Name = "RouteChangeAdvisory", Order = 10)] public class RouteChangeAdvisoryService : IRouteChangeAdvisoryService, IDynamicApiController, ITransient { private readonly ISysCacheService _cache; private readonly ILogger _logger; private readonly SqlSugarRepository _taskBaseRepository; private readonly SqlSugarRepository _taskRouteChangeAdvisoryInfoRepository; private readonly SqlSugarRepository _taskRouteChangeAdvisoryDetailInfoRepository; private readonly SqlSugarRepository _djyUserMailAccount; private readonly SqlSugarRepository _bookingOrderRepository; private readonly SqlSugarRepository _bookingOrderContactRepository; private readonly SqlSugarRepository _sysUserRepository; public RouteChangeAdvisoryService(ISysCacheService cache, ILogger logger, SqlSugarRepository taskBaseRepository, SqlSugarRepository taskRouteChangeAdvisoryInfoRepository, SqlSugarRepository taskRouteChangeAdvisoryDetailInfoRepository, SqlSugarRepository djyUserMailAccount, SqlSugarRepository bookingOrderContactRepository, SqlSugarRepository sysUserRepository, SqlSugarRepository bookingOrderRepository) { _cache = cache; _logger = logger; _taskBaseRepository = taskBaseRepository; _taskRouteChangeAdvisoryInfoRepository = taskRouteChangeAdvisoryInfoRepository; _taskRouteChangeAdvisoryDetailInfoRepository = taskRouteChangeAdvisoryDetailInfoRepository; _djyUserMailAccount = djyUserMailAccount; _bookingOrderRepository = bookingOrderRepository; _bookingOrderContactRepository = bookingOrderContactRepository; _sysUserRepository = sysUserRepository; } #region 获取船舶相关截止时间的通知详情 /// /// 获取船舶相关截止时间的通知详情 /// /// 船舶相关截止时间的通知任务主键 /// 返回详情 [HttpGet("/RouteChangeAdvisory/GetInfoByTaskId")] public async Task GetInfoByTaskId(string taskPkId) { TaskRouteChangeAdvisoryShowDto dto = new TaskRouteChangeAdvisoryShowDto(); var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息"); var advisoryInfo = _taskRouteChangeAdvisoryInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID); if (advisoryInfo == null) throw Oops.Oh($"船舶相关截止时间的通知主键{taskPkId}无法获取业务信息"); var detailList = _taskRouteChangeAdvisoryDetailInfoRepository.AsQueryable() .Where(a => a.P_ID == advisoryInfo.PK_ID).ToList(); dto = new TaskRouteChangeAdvisoryShowDto { PKId = advisoryInfo.PK_ID, TaskPKId = advisoryInfo.TASK_ID, CarrierId = advisoryInfo.CARRIER, CreateTime = advisoryInfo.CreatedTime, AdvisoryTitle = advisoryInfo.EMAIL_SUBJECT, CYCutDate = advisoryInfo.CY_CUT_DATE, ETA = advisoryInfo.ETA, ETD = advisoryInfo.ETD, MDGFCutDate = advisoryInfo.MDGF_CUT_DATE, origETD = advisoryInfo.ORIG_ETD, RouteCode = advisoryInfo.ROUTE_CODE, SICutDate = advisoryInfo.SI_CUT_DATE, Vessel = advisoryInfo.VESSEL, Voyno = advisoryInfo.VOYNO, VGMCutDate = advisoryInfo.VGM_CUTOFF_TIME, Week = advisoryInfo.WEEK, TerminalShiftCutDate = advisoryInfo.TM_SHIFT_CUT_DATE, LoadPort = advisoryInfo.READ_PORTLOAD, LoadPortId = advisoryInfo.PORTLOADID, LoadPortName = advisoryInfo.PORTLOAD, BuisList = new List() }; if (detailList.Count > 0) { var queryList = detailList.Where(a => a.BOOKING_ID.HasValue).Select(a => a.BOOKING_ID.Value).ToList(); if (queryList.Count > 0) { //查询整船的订舱订单列表 var bookList = _bookingOrderRepository.AsQueryable().Where(a => queryList.Contains(a.Id) && a.IsDeleted == false).ToList(); dto.BuisList = detailList.Select(p => { TaskRouteChangeAdvisoryBusiShowDto detail = new TaskRouteChangeAdvisoryBusiShowDto { PKId = p.PK_ID, LstTransferUserDate = p.LST_TRANSFER_USER_DATE, IsTransferUser = p.IS_TRANSFER_USER, LstTransferNote = p.LST_TRANSFER_NOTES, BookingId = p.BOOKING_ID.Value, IsEnable = p.IS_ENABLE }; var bookInfo = bookList.FirstOrDefault(x => x.Id == p.BOOKING_ID.Value); if (bookInfo != null) { detail.CustomerName = bookInfo.CUSTOMERNAME; detail.MBlNo = bookInfo.MBLNO; } else { //如果对应的订舱已被作废,只能标记不可发送 detail.IsEnable = false; } return detail; }).ToList(); } else { dto.BuisList = detailList.Select(p => { TaskRouteChangeAdvisoryBusiShowDto detail = new TaskRouteChangeAdvisoryBusiShowDto { PKId = p.PK_ID, LstTransferUserDate = p.LST_TRANSFER_USER_DATE, IsTransferUser = p.IS_TRANSFER_USER, LstTransferNote = p.LST_TRANSFER_NOTES, BookingId = p.BOOKING_ID.Value, IsEnable = false }; return detail; }).ToList(); } } return dto; } #endregion #region 自动转发船舶相关截止时间的通知 /// /// 自动转发船舶相关截止时间的通知 /// /// 船舶相关截止时间的通知任务主键 /// 返回回执 [HttpGet("/RouteChangeAdvisory/AutoTransferNotice")] public async Task AutoTransferNotice(string taskPKId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPKId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息"); var advisoryInfo = _taskRouteChangeAdvisoryInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID); if (advisoryInfo == null) throw Oops.Oh($"船舶相关截止时间的通知主键{taskPKId}无法获取业务信息"); var detailList = _taskRouteChangeAdvisoryDetailInfoRepository.AsQueryable() .Where(a => a.P_ID == advisoryInfo.PK_ID).ToList(); //通过船名航次取是主单的订舱记录列表 var bookList = _bookingOrderRepository.AsQueryable().Where(a => a.VESSEL == advisoryInfo.VESSEL && (a.VOYNO == advisoryInfo.VOYNO || a.VOYNOINNER == advisoryInfo.VOYNO) && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0)).ToList(); //用查询到的订舱列表和明细记录标做匹配,如果没有需要新增记录表 var addList = bookList.GroupJoin(detailList, l => l.Id, r => r.BOOKING_ID.Value, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) { return new { IsAdd = true, book = l }; } return new { IsAdd = false, book = l }; }).Where(t => t.IsAdd).Select(t => t.book).ToList(); DateTime nowDate = DateTime.Now; if (addList.Count > 0) { addList.ForEach(t => { TaskRouteChangeAdvisoryDetailInfo detail = new TaskRouteChangeAdvisoryDetailInfo { PK_ID = IDGen.NextID().ToString(), BOOKING_ID = t.Id, MBL_NO = t.MBLNO, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID }; }); } } catch (Exception ex) { } return result; } #endregion #region 检索同一航次对应的订舱订单(并对应记录) /// /// 检索同一航次对应的订舱订单(并对应记录) /// /// 船舶相关截止时间的通知任务主键 /// 返回回执 [HttpGet("/RouteChangeAdvisory/QueryVesselVoynoBookingOrder")] public async Task QueryVesselVoynoBookingOrder(string taskPKId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPKId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息"); var advisoryInfo = _taskRouteChangeAdvisoryInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID); if (advisoryInfo == null) throw Oops.Oh($"船舶相关截止时间的通知主键{taskPKId}无法获取业务信息"); var detailList = _taskRouteChangeAdvisoryDetailInfoRepository.AsQueryable() .Where(a => a.P_ID == advisoryInfo.PK_ID).ToList(); //通过船名航次取是主单的订舱记录列表 var bookList = _bookingOrderRepository.AsQueryable().Where(a => a.VESSEL == advisoryInfo.VESSEL && (a.VOYNO == advisoryInfo.VOYNO || a.VOYNOINNER == advisoryInfo.VOYNO) && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0)).ToList(); //用查询到的订舱列表和明细记录标做匹配,如果没有需要新增记录表 var addList = bookList.GroupJoin(detailList, l => l.Id, r => r.BOOKING_ID.Value, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) { return new { IsAdd = true, book = l }; } return new { IsAdd = false, book = l }; }).Where(t => t.IsAdd).Select(t => t.book).ToList(); DateTime nowDate = DateTime.Now; if (addList.Count > 0) { addList.ForEach(t => { TaskRouteChangeAdvisoryDetailInfo detail = new TaskRouteChangeAdvisoryDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = advisoryInfo.PK_ID, IsDeleted = false, BOOKING_ID = t.Id, MBL_NO = t.MBLNO, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID }; _taskRouteChangeAdvisoryDetailInfoRepository.Insert(detail); }); } } catch (Exception ex) { result.succ = false; result.msg = $"检索失败,原因:{ex.Message}"; _logger.LogInformation($"taskPKId={taskPKId} 检索同一航次对应的订舱订单(并对应记录) 处理异常,原因:{ex.Message}"); } return result; } #endregion #region 批量发送邮件通知给客户 /// /// 批量发送邮件通知给客户 /// /// 船舶相关截止时间的通知订舱明细记录主键组 /// 返回回执 public async Task BatchSendEmailToCustomer(string[] detailPKIds) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { if (detailPKIds == null || detailPKIds.Length == 0) throw Oops.Oh($"未选择需要发送订单明细"); var detailList = _taskRouteChangeAdvisoryDetailInfoRepository.AsQueryable() .Where(a => detailPKIds.Contains(a.PK_ID) && a.IsDeleted == false).ToList(); if (detailPKIds.Length != detailList.Count) { throw Oops.Oh($"检索明细数据失败,检索数据不存在或已作废"); } var bookIdList = detailList.Where(t => t.IS_ENABLE == true) .Select(t => t.BOOKING_ID.Value).ToList(); if (detailList.Any(a => !a.BOOKING_ID.HasValue)) { throw Oops.Oh($"明细相关的订舱数据检索失败,请确认订舱数据是否存在"); } //需要根据订单的往来单位统一推送一封邮件,里面有提单号列表 var bookList = _bookingOrderRepository.AsQueryable().Where(a => bookIdList.Contains(a.Id) && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0)).ToList(); var checkList = detailList.GroupJoin(bookList, l => l.BOOKING_ID.Value, r => r.Id, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) return new { IsNoBooking = true, MblNo = l.MBL_NO }; return new { IsNoBooking = false, MblNo = l.MBL_NO }; }).Where(a => a.IsNoBooking).Select(a => a.MblNo).ToList(); if (checkList.Count > 0) { throw Oops.Oh($"明细提单号对应订舱没有记录,{string.Join(",", checkList.ToArray())}"); } //还需要判断订舱是否录了客户联系人 var bookingContactList = _bookingOrderContactRepository.AsQueryable().Filter(null, true) .Where(a => bookIdList.Contains(a.BookingId.Value) && a.IsDeleted == false).ToList(); //按照往来单位来合并订单,一个客户一个邮件来提醒 var gList = bookList.GroupBy(a => a.CUSTOMERID).Select(a => { var currList = a.ToList(); return new { CustId = a.Key, CustName = currList.FirstOrDefault().CUSTOMERNAME, OrderList = currList }; }).ToList(); } catch (Exception ex) { result.succ = false; result.msg = $"批量发送失败,原因:{ex.Message}"; _logger.LogInformation($"detailPKIds={string.Join(",", detailPKIds)} 批量发送邮件通知给客户 处理异常,原因:{ex.Message}"); } return result; } #endregion //private void SendUser private void GenerateSendEmail(TaskRouteChangeAdvisoryInfo model,long bookingId,string mblNo) { /* //TO 邮件接收人 string toEmail = string.Empty; //订舱OP的邮箱 string opEmail = string.Empty; //读取订舱数据 var bookingOrderEntity = _bookingOrderRepository.AsQueryable().Filter(null, true) .First(a => a.Id == bookingId); if (bookingContactList == null || bookingContactList.Count == 0) { _logger.LogInformation($"当前订舱未指定的联系人,toEmail={toEmail}"); new EmailNoticeHelper().SendEmailNotice($"MBLNO={mblNo} 转发【船舶相关截止时间的通知】通知邮件失败", $"MBLNO={mblNo} 转发【船舶相关截止时间的通知】通知邮件失败,原因:当前订舱未指定的联系人", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); throw Oops.Oh($"{mblNo} 当前订舱未指定的联系人,发送通知失败"); } 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().Filter(null, true).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}"); } } //提取当前公共邮箱的配置 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 != ""); if (publicMailAccount == null) { throw Oops.Oh($"提取公共邮箱配置失败,请在用户邮箱账号管理增加配置显示名为PublicSend或者配置个人邮箱"); } _logger.LogInformation($"提取当前公共邮箱的配置完成,id={publicMailAccount.Id}"); string emailTitle = $"Advisory:{model.EMAIL_SUBJECT} : {taskBCInfo.MBL_NO}"; string filePath = string.Empty; SysUser opUserInfo = null; if (!string.IsNullOrWhiteSpace(bookingOrderEntity.OPID) && Regex.IsMatch(bookingOrderEntity.OPID, "[0-9]+")) opUserInfo = _sysUserRepository.AsQueryable().Filter(null, true).First(u => u.Id == long.Parse(bookingOrderEntity.OPID)); if (taskBCInfo.BUSI_TYPE == "BookingAmendment") { emailTitle = $"【变更】Booking Amendment : {taskBCInfo.MBL_NO}"; } //读取邮件模板并填充数据 string emailHtml = string.Empty; if (taskBCInfo.BUSI_TYPE == "BookingAmendment") { emailHtml = GenerateSendEmailHtmlAmendment(taskBCInfo, opUserInfo, UserManager.TENANT_NAME).GetAwaiter().GetResult(); } else { emailHtml = GenerateSendEmailHtml(taskBCInfo, opUserInfo, UserManager.TENANT_NAME).GetAwaiter().GetResult(); }*/ } } }