using Furion.DependencyInjection; using Furion.DynamicApiController; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Myshipping.Application.Entity; using Myshipping.Application.Service.TaskManagePlat.Interface; 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 Myshipping.Core.Entity; using Furion.JsonSerialization; using Furion.RemoteRequest.Extensions; using Newtonsoft.Json; using System.IO; using System.Net.Http; using Myshipping.Core.Helper; using NPOI.SS.Formula.Functions; using System.Reflection.Metadata; using Furion; using Myshipping.Application.Helper; using Furion.DistributedIDGenerator; namespace Myshipping.Application { /// /// 重要提醒任务 /// [ApiDescriptionSettings("Application", Name = "TaskCautionNotice", Order = 10)] public class TaskCautionNoticeService : ITaskCautionNoticeService, IDynamicApiController, ITransient { private readonly ISysCacheService _cache; private readonly ILogger _logger; private readonly SqlSugarRepository _taskBaseRepository; private readonly SqlSugarRepository _taskCautionNoticeInfoRepository; private readonly SqlSugarRepository _taskCautionNoticeDetailInfoRepository; private readonly SqlSugarRepository _djyUserMailAccount; private readonly SqlSugarRepository _taskCautionNoticeWholeShipInfoRepository; private readonly SqlSugarRepository _taskCautionNoticeWholeShipDetailInfoRepository; private readonly SqlSugarRepository _repBase; private readonly SqlSugarRepository _repCtn; private readonly SqlSugarRepository _repAllocation; private readonly SqlSugarRepository _repAllocationCtn; private readonly SqlSugarRepository _repBookingOrder; private readonly SqlSugarRepository _sysUserRepository; private readonly INamedServiceProvider _namedTaskManageServiceProvider; public TaskCautionNoticeService(ISysCacheService cache, ILogger logger, SqlSugarRepository taskBaseRepository, SqlSugarRepository taskCautionNoticeInfoRepository, SqlSugarRepository taskCautionNoticeDetailInfoRepository, SqlSugarRepository taskCautionNoticeWholeShipInfoRepository, SqlSugarRepository taskCautionNoticeWholeShipDetailInfoRepository, SqlSugarRepository djyUserMailAccount, SqlSugarRepository repBase, SqlSugarRepository repCtn, SqlSugarRepository repAllocation, SqlSugarRepository repAllocationCtn, SqlSugarRepository repBookingOrder, SqlSugarRepository sysUserRepository, INamedServiceProvider namedTaskManageServiceProvider) { _cache = cache; _logger = logger; _taskBaseRepository = taskBaseRepository; _taskCautionNoticeInfoRepository = taskCautionNoticeInfoRepository; _taskCautionNoticeDetailInfoRepository = taskCautionNoticeDetailInfoRepository; _djyUserMailAccount = djyUserMailAccount; _taskCautionNoticeWholeShipInfoRepository = taskCautionNoticeWholeShipInfoRepository; _taskCautionNoticeWholeShipDetailInfoRepository = taskCautionNoticeWholeShipDetailInfoRepository; _repBase = repBase; _repCtn = repCtn; _repAllocation = repAllocation; _repAllocationCtn = repAllocationCtn; _repBookingOrder = repBookingOrder; _sysUserRepository = sysUserRepository; _namedTaskManageServiceProvider = namedTaskManageServiceProvider; } #region 获取重要提醒任务详情 /// /// 获取重要提醒任务详情 /// /// 重要提醒任务主键 /// 返回详情 [HttpGet("/TaskCautionNotice/GetInfoByTaskId")] public async Task GetInfoByTaskId(string taskPkId) { TaskCautionNoticeShowDto dto = new TaskCautionNoticeShowDto(); var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息"); var noticeInfo = _taskCautionNoticeInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID); if (noticeInfo == null) throw Oops.Oh($"重要提醒主键{taskPkId}无法获取业务信息"); CautionNoticeTaskEnum cautionNoticeEnum = (CautionNoticeTaskEnum)System.Enum.Parse(typeof(CautionNoticeTaskEnum), noticeInfo.CAUTION_NOTICE_TYPE); dto = new TaskCautionNoticeShowDto { PKId = noticeInfo.PK_ID, taskPKId = noticeInfo.TASK_ID, carrier = noticeInfo.CARRIER, bookingId = noticeInfo.BOOKING_ID, mblNo = noticeInfo.MBL_NO, createTime = noticeInfo.CreatedTime, cautionNoticeType = noticeInfo.CAUTION_NOTICE_TYPE, cautionNoticeTypeName = cautionNoticeEnum.GetDescription(), origVal = noticeInfo.OLD_VAL, newVal = noticeInfo.NEW_VAL, IsCutDateAdvanced = noticeInfo.IS_CUT_DATE_ADVANCED, IsVesselChange = noticeInfo.IS_VESSEL_CHANGE, IsTransfer = noticeInfo.IS_TRANSFER, VesselOldVal = noticeInfo.VESSEL_OLD_VAL, VesselNewVal = noticeInfo.VESSEL_NEW_VAL, VoynoOldVal = noticeInfo.VOYNO_OLD_VAL, VoynoNewVal = noticeInfo.VOYNO_NEW_VAL, SICutOldVal = noticeInfo.SI_CUT_OLD_VAL, SICutNewVal = noticeInfo.SI_CUT_NEW_VAL, VGMCutOldVal = noticeInfo.VGM_CUT_OLD_VAL, VGMCutNewVal = noticeInfo.VGM_CUT_NEW_VAL }; return dto; } #endregion #region 触发推送消息 /// /// 触发推送消息 /// /// 重要提醒任务主键 /// 租户ID /// 返回回执 [HttpGet("/TaskCautionNotice/TriggerSendNotice")] public async Task TriggerSendNotice(string taskPKId, long tenantId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { TaskDraftShowDto dto = new TaskDraftShowDto(); var taskBase = _taskBaseRepository.AsQueryable().Filter(null, true).First(a => a.PK_ID == taskPKId && a.IsDeleted == false && a.TenantId == tenantId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息"); var noticeInfo = _taskCautionNoticeInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskBase.PK_ID && a.IsDeleted == false && a.TenantId == tenantId); var list = _taskCautionNoticeDetailInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.P_ID == noticeInfo.PK_ID && a.IsDeleted == false && a.TenantId == tenantId).ToList(); TaskBusiTypeEnum currEnum = (TaskBusiTypeEnum)System.Enum.Parse(typeof(TaskBusiTypeEnum), taskBase.TASK_TYPE); CautionNoticeTaskEnum cautionNoticeEnum = (CautionNoticeTaskEnum)System.Enum.Parse(typeof(CautionNoticeTaskEnum), noticeInfo.CAUTION_NOTICE_TYPE); if (list.Count > 0) { list.ForEach(a => { if (a.NOTIFY_METHOD == CautionNoticeMethodEnum.Email.ToString()) { if (!string.IsNullOrWhiteSpace(a.NOTIFY_EMAIL)) { //提取当前公共邮箱的配置 DjyUserMailAccount publicMailAccount = _djyUserMailAccount.AsQueryable().Filter(null, true).First(x => x.TenantId == tenantId && x.ShowName == "PublicSend" && x.SmtpPort > 0 && x.SmtpServer != null && x.SmtpServer != ""); if (publicMailAccount == null) { //throw Oops.Oh($"提取公共邮箱配置失败,请在用户邮箱账号管理增加配置显示名为PublicSend或者配置个人邮箱"); _logger.LogInformation($"准备邮件通知通知给 uid={a.NOTIFY_USER_NAME} name={a.NOTIFY_USER_NAME},但是没有配置发送邮箱"); new EmailNoticeHelper().SendEmailNotice($"MBLNO={noticeInfo.MBL_NO} {cautionNoticeEnum.GetDescription()} 需要给推送邮件但是没有配公司邮箱", $"MBLNO={noticeInfo.MBL_NO} {cautionNoticeEnum.GetDescription()} 需要给推送邮件但是没有配公司邮箱", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } EmailApiUserDefinedDto emailApiUserDefinedDto = new EmailApiUserDefinedDto { SendTo = a.NOTIFY_EMAIL, Title = $"提单号:{noticeInfo.MBL_NO} {cautionNoticeEnum.GetDescription()}", Body = $"提单号:{noticeInfo.MBL_NO} {cautionNoticeEnum.GetDescription()} {noticeInfo.NOTIFY_CONTENT}", 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() }; _logger.LogInformation($"生成请求邮件参数,结果:{JSON.Serialize(emailApiUserDefinedDto)}"); //推送邮件 var emailRlt = PushEmail(emailApiUserDefinedDto).GetAwaiter().GetResult(); _logger.LogInformation($"推送邮件完成,结果:{JSON.Serialize(emailRlt)}"); a.STATUS = emailRlt.succ ? "SUCC" : "FAILURE"; a.STATUS_NAME = emailRlt.succ ? "成功" : "失败"; _taskCautionNoticeDetailInfoRepository.AsUpdateable(a).UpdateColumns(p => new { p.STATUS, p.STATUS_NAME }).ExecuteCommand(); } } else if (a.NOTIFY_METHOD == CautionNoticeMethodEnum.DingDing.ToString()) { _logger.LogInformation($"准备钉钉通知给 uid={a.NOTIFY_USER_NAME} name={a.NOTIFY_USER_NAME},内容:\r\n{noticeInfo.NOTIFY_CONTENT}"); DingTalkGroupHelper.SendDingTalkGroupMessage($"{taskBase.TenantId}_Notify", cautionNoticeEnum.GetDescription(), $"{noticeInfo.NOTIFY_CONTENT}\r\n{a.NOTIFY_USER_NAME}", false, new string[] { a.NOTIFY_MOBILE }, null); _logger.LogInformation($"钉钉通知完毕给 uid={a.NOTIFY_USER_NAME} name={a.NOTIFY_USER_NAME},内容:\r\n{noticeInfo.NOTIFY_CONTENT}"); a.STATUS = "SUCC"; a.STATUS_NAME = "成功"; _taskCautionNoticeDetailInfoRepository.AsUpdateable(a).UpdateColumns(p => new { p.STATUS, p.STATUS_NAME }).ExecuteCommand(); } }); } } catch (Exception ex) { new EmailNoticeHelper().SendEmailNotice($"taskPKId={taskPKId} 有重要提醒任务发生异常", $"taskPKId={taskPKId} 有重要提醒任务发生异常 原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } return result; } #endregion #region 推送邮件 /// /// 推送邮件 /// /// 自定义邮件详情 /// 文件路径 /// 返回回执 private async Task PushEmail(EmailApiUserDefinedDto emailApiUserDefinedDto) { CommonWebApiResult result = new CommonWebApiResult { succ = true }; List emailList = new List(); 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($"邮件上传完成 用时:{timeDiff}ms.,"); _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 生成重要提醒整船通知 /// /// 生成重要提醒整船通知 /// /// 请求详情 /// 返回回执 public async Task GenerateWholeShipCaucation(CautionNoticeTaskWholeShipDto model, BookingSlotBase slotBaseInfo) { TaskManageOrderResultDto rlt = new TaskManageOrderResultDto(); try { /* 1、优先匹配是否已经有了整船的通知(船名、航次、SI截止时间、VGM截止时间、直达变中转、统计日期必须是当日的,注新值和旧值提交的都一致) 2、如果能匹配到,并且明细里有此单号,不做处理;没有单号记录需要写入单号,并且重新发起当票的邮件和钉钉通知 3、如果没有匹配到,重新获取整船的单号,生成明细记录。发起邮件和钉钉通知 */ DateTime nowDate = DateTime.Now; string batchNo = IDGen.NextID().ToString(); int statDay = int.Parse(nowDate.ToString("yyyyMMdd")); var shipInfo = await _taskCautionNoticeWholeShipInfoRepository.AsQueryable().Filter(null, true).Where(a => a.VESSEL_OLD_VAL == model.VesselOldVal && a.VOYNO_OLD_VAL == model.VoynoOldVal && a.STAT_DAY.Value == statDay) .WhereIF(!string.IsNullOrWhiteSpace(model.VesselNewVal),x=> x.VESSEL_NEW_VAL == model.VesselNewVal) .WhereIF(!string.IsNullOrWhiteSpace(model.VoynoNewVal), x => x.VOYNO_NEW_VAL == model.VoynoNewVal) .WhereIF(!string.IsNullOrWhiteSpace(model.SICutOldVal), x => x.SI_CUT_OLD_VAL == model.SICutOldVal) .WhereIF(!string.IsNullOrWhiteSpace(model.SICutNewVal), x => x.SI_CUT_NEW_VAL == model.SICutNewVal) .WhereIF(!string.IsNullOrWhiteSpace(model.VGMCutOldVal), x => x.VGM_CUT_OLD_VAL == model.VGMCutOldVal) .WhereIF(!string.IsNullOrWhiteSpace(model.VGMCutNewVal), x => x.VGM_CUT_NEW_VAL == model.VGMCutNewVal) .WhereIF(!string.IsNullOrWhiteSpace(model.DirectToTransOldVal), x => x.DIRECT_TO_TRANS_OLD_VAL == model.DirectToTransOldVal) .WhereIF(!string.IsNullOrWhiteSpace(model.DirectToTransNewVal), x => x.DIRECT_TO_TRANS_NEW_VAL == model.DirectToTransNewVal).FirstAsync(); var detailRecordList = new List(); List cautionList = new List(); if (shipInfo == null) { shipInfo = new TaskCautionNoticeWholeShipInfo { PK_ID = IDGen.NextID().ToString(), CARRIER = model.Carrier, IsDeleted = false, VESSEL_OLD_VAL = model.VesselOldVal, VESSEL_NEW_VAL = model.VesselNewVal, VOYNO_OLD_VAL = model.VoynoOldVal, VOYNO_NEW_VAL = model.VoynoNewVal, VGM_CUT_OLD_VAL = model.VGMCutOldVal, VGM_CUT_NEW_VAL = model.VGMCutNewVal, SI_CUT_OLD_VAL = model.SICutOldVal, SI_CUT_NEW_VAL = model.SICutNewVal, DIRECT_TO_TRANS_OLD_VAL = model.DirectToTransOldVal, DIRECT_TO_TRANS_NEW_VAL = model.DirectToTransNewVal, IS_CUT_DATE_ADVANCED = model.IsCutDateAdvanced, IS_VESSEL_CHANGE = model.IsVesselChange, IS_TRANSFER = model.IsTransfer, CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, STAT_DAY = statDay, }; await _taskCautionNoticeWholeShipInfoRepository.InsertAsync(shipInfo); //检索所有订舱记录 var bookingSlotAllocList = _repBase.AsQueryable().Filter(null, true) .LeftJoin((slot, alloc) => slot.Id == alloc.BOOKING_SLOT_ID) .Where((slot, alloc) => slot.VESSEL == model.VesselOldVal && slot.VOYNO == model.VoynoOldVal && slot.CARRIERID == model.Carrier && slot.IsDeleted == false && slot.TenantId == UserManager.TENANT_ID) .Select((slot, alloc) => new { Slot = slot, Alloc = alloc }).ToList(); bookingSlotAllocList = bookingSlotAllocList.Where(a => a.Alloc.Id == 0 || (a.Alloc.Id > 0 && a.Alloc.IsDeleted == false)).ToList(); List bookingOrderList = new List(); //先批量取一遍关联的订舱记录 if (bookingSlotAllocList.Any(t => t.Alloc.Id > 0)) { var bookingNoList = bookingSlotAllocList.Where(a => a.Alloc.Id > 0) .Select(a => a.Alloc.BOOKING_ID).ToList(); bookingOrderList = _repBookingOrder.AsQueryable().Filter(null, true) .Where(x => bookingNoList.Contains(x.Id) && x.IsDeleted == false && x.TenantId == UserManager.TENANT_ID).ToList(); } //生成完记录 bookingSlotAllocList.ForEach(t => { //舱位分配表不为空表示有对应的订舱记录 if (t.Alloc.Id > 0) { var bookingOrder = bookingOrderList.FirstOrDefault(b => b.Id == t.Alloc.BOOKING_ID); List userIds = new List(); List userList = new List(); if (!string.IsNullOrWhiteSpace(bookingOrder.OPID)) userIds.Add(long.Parse(bookingOrder.OPID)); if (!string.IsNullOrWhiteSpace(bookingOrder.CUSTSERVICEID)) userIds.Add(long.Parse(bookingOrder.CUSTSERVICEID)); //userIds.Add(bookingOrder.CreatedUserId.Value); userIds = userIds.Distinct().ToList(); userList = _sysUserRepository.AsQueryable().Filter(null, true) .Where(x => userIds.Contains(x.Id) && x.IsDeleted == false && x.TenantId == UserManager.TENANT_ID).ToList(); userList.ForEach(user => { //表示即有舱位也有订舱记录 var detailInfo = new TaskCautionNoticeWholeShipDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = shipInfo.PK_ID, BOOKING_ID = t.Alloc.BOOKING_ID, BOOKING_SLOT_ID = t.Slot.Id, BATCH_NO = batchNo, IsDeleted = false, MBL_NO = bookingOrder.MBLNO, STATUS = "TEMP", STATUS_NAME = "暂存", NOTIFY_METHOD = CautionNoticeMethodEnum.Email.ToString(), NOTIFY_USER_ID = user.Id.ToString(), NOTIFY_USER_NAME = user.Name, NOTIFY_MOBILE = user.Phone?.Trim(), NOTIFY_EMAIL = user.Email?.Trim(), CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, }; detailRecordList.Add(detailInfo); _taskCautionNoticeWholeShipDetailInfoRepository.InsertAsync(detailInfo); //表示即有舱位也有订舱记录 var detail2Info = new TaskCautionNoticeWholeShipDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = shipInfo.PK_ID, BOOKING_ID = t.Alloc.BOOKING_ID, BOOKING_SLOT_ID = t.Slot.Id, BATCH_NO = batchNo, IsDeleted = false, MBL_NO = bookingOrder.MBLNO, STATUS = "TEMP", STATUS_NAME = "暂存", NOTIFY_METHOD = CautionNoticeMethodEnum.DingDing.ToString(), NOTIFY_USER_ID = user.Id.ToString(), NOTIFY_USER_NAME = user.Name, NOTIFY_MOBILE = user.Phone?.Trim(), NOTIFY_EMAIL = user.Email?.Trim(), CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, }; detailRecordList.Add(detail2Info); _taskCautionNoticeWholeShipDetailInfoRepository.InsertAsync(detail2Info); var notice = new CautionNoticeTaskDto { createTime = DateTime.Now, origVal = "", newVal = "", tenentId = user.TenantId.Value, userId = user.Id, userName = user.Name, mblNo = t.Slot.SLOT_BOOKING_NO, carrier = t.Slot.CARRIERID, sourceSystem = "DjyBooking", sourceBusiType = "BookingSlot", sourceBusiTypeName = "舱位管理", vessel = model.VesselOldVal, voyno = model.VoynoOldVal, tenentName = UserManager.TENANT_NAME, isAutoSendNotice = false, IsCutDateAdvanced = model.IsCutDateAdvanced, IsVesselChange = model.IsVesselChange, IsTransfer = model.IsTransfer, SICutOldVal = model.SICutOldVal, SICutNewVal = model.SICutNewVal, VGMCutOldVal = model.VGMCutOldVal, VGMCutNewVal = model.VGMCutNewVal, VesselOldVal = model.VesselOldVal, VesselNewVal = model.VesselNewVal, VoynoOldVal = model.VoynoOldVal, VoynoNewVal = model.VoynoNewVal, notifyList = new List() }; if (model.IsVesselChange && (model.IsCutDateAdvanced || model.IsTransfer)) { notice.cautionNoticeType = CautionNoticeTaskEnum.VesselCutDateTransfer; } else { if (model.IsVesselChange) { notice.cautionNoticeType = CautionNoticeTaskEnum.ChangeVesselVoyno; } else if (model.IsCutDateAdvanced) { notice.cautionNoticeType = CautionNoticeTaskEnum.CutDateAdvanced; } else if (model.IsTransfer) { notice.cautionNoticeType = CautionNoticeTaskEnum.ChangeTransfer; } } notice.notifyList.Add(new CautionNoticeTaskNoitfyDto { notifyEmail = user.Email, notifyMethod = new CautionNoticeMethodEnum[] { CautionNoticeMethodEnum.Email, CautionNoticeMethodEnum.DingDing }, notifyMobile = user.Phone, notifyUserId = user.Id, notifyUserName = user.Name }); cautionList.Add(notice); }); } else { //表示只有舱位 //表示即有舱位也有订舱记录 var createUserId = t.Slot.CreatedUserId.Value; var user = _sysUserRepository.AsQueryable().Filter(null, true) .First(x => x.Id == createUserId && x.IsDeleted == false && x.TenantId == UserManager.TENANT_ID); var detailInfo = new TaskCautionNoticeWholeShipDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = shipInfo.PK_ID, BOOKING_SLOT_ID = t.Slot.Id, BATCH_NO = batchNo, IsDeleted = false, MBL_NO = t.Slot.SLOT_BOOKING_NO, STATUS = "TEMP", STATUS_NAME = "暂存", NOTIFY_METHOD = CautionNoticeMethodEnum.Email.ToString(), NOTIFY_USER_ID = user.Id.ToString(), NOTIFY_USER_NAME = user.Name, NOTIFY_MOBILE = user.Phone?.Trim(), NOTIFY_EMAIL = user.Email?.Trim(), CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, }; detailRecordList.Add(detailInfo); _taskCautionNoticeWholeShipDetailInfoRepository.InsertAsync(detailInfo); //表示即有舱位也有订舱记录 var detail2Info = new TaskCautionNoticeWholeShipDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = shipInfo.PK_ID, BOOKING_SLOT_ID = t.Slot.Id, BATCH_NO = batchNo, IsDeleted = false, MBL_NO = t.Slot.SLOT_BOOKING_NO, STATUS = "TEMP", STATUS_NAME = "暂存", NOTIFY_METHOD = CautionNoticeMethodEnum.DingDing.ToString(), NOTIFY_USER_ID = user.Id.ToString(), NOTIFY_USER_NAME = user.Name, NOTIFY_MOBILE = user.Phone?.Trim(), NOTIFY_EMAIL = user.Email?.Trim(), CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, }; detailRecordList.Add(detail2Info); _taskCautionNoticeWholeShipDetailInfoRepository.InsertAsync(detail2Info); var notice = new CautionNoticeTaskDto { createTime = DateTime.Now, origVal = "", newVal = "", tenentId = user.TenantId.Value, userId = user.Id, userName = user.Name, mblNo = t.Slot.SLOT_BOOKING_NO, carrier = t.Slot.CARRIERID, sourceSystem = "DjyBooking", sourceBusiType = "BookingSlot", sourceBusiTypeName = "舱位管理", vessel = model.VesselOldVal, voyno = model.VoynoOldVal, tenentName = UserManager.TENANT_NAME, isAutoSendNotice = false, IsCutDateAdvanced = model.IsCutDateAdvanced, IsVesselChange = model.IsVesselChange, IsTransfer = model.IsTransfer, SICutOldVal = model.SICutOldVal, SICutNewVal = model.SICutNewVal, VGMCutOldVal = model.VGMCutOldVal, VGMCutNewVal = model.VGMCutNewVal, VesselOldVal = model.VesselOldVal, VesselNewVal = model.VesselNewVal, VoynoOldVal = model.VoynoOldVal, VoynoNewVal = model.VoynoNewVal, notifyList = new List() }; if (model.IsVesselChange && (model.IsCutDateAdvanced || model.IsTransfer)) { notice.cautionNoticeType = CautionNoticeTaskEnum.VesselCutDateTransfer; } else { if (model.IsVesselChange) { notice.cautionNoticeType = CautionNoticeTaskEnum.ChangeVesselVoyno; } else if (model.IsCutDateAdvanced) { notice.cautionNoticeType = CautionNoticeTaskEnum.CutDateAdvanced; } else if (model.IsTransfer) { notice.cautionNoticeType = CautionNoticeTaskEnum.ChangeTransfer; } } notice.notifyList.Add(new CautionNoticeTaskNoitfyDto { notifyEmail = user.Email, notifyMethod = new CautionNoticeMethodEnum[] { CautionNoticeMethodEnum.Email, CautionNoticeMethodEnum.DingDing }, notifyMobile = user.Phone, notifyUserId = user.Id, notifyUserName = user.Name }); cautionList.Add(notice); } }); } else { var detailList = _taskCautionNoticeWholeShipDetailInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.P_ID == shipInfo.PK_ID).ToList(); //这里先判断一下当前的变更的舱位是否在已经通知的记录内,如果已有就不再重复通知,否则需要发送通知记录 if (!detailList.Any(p => p.MBL_NO.Equals(model.MBLNo))) { var bookingSlotAllocList = _repBase.AsQueryable().Filter(null, true) .LeftJoin((slot, alloc) => slot.Id == alloc.BOOKING_SLOT_ID) .Where((slot, alloc) => slot.SLOT_BOOKING_NO == model.MBLNo && slot.CARRIERID == model.Carrier && slot.IsDeleted == false && slot.TenantId == UserManager.TENANT_ID) .Select((slot, alloc) => new { Slot = slot, Alloc = alloc }).ToList(); bookingSlotAllocList = bookingSlotAllocList.Where(a => a.Alloc.Id == 0 || (a.Alloc.Id > 0 && a.Alloc.IsDeleted == false)).ToList(); if (bookingSlotAllocList.Any(t => t.Alloc.Id > 0)) { var bookingNoList = bookingSlotAllocList.Where(a => a.Alloc.Id > 0) .Select(a => a.Alloc.BOOKING_ID).ToList(); var lostList = bookingNoList.GroupJoin(detailList.Where(p => p.BOOKING_ID > 0).ToList(), l => l, r => r.BOOKING_ID, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) return new { Succ = false, obj = l }; return new { Succ = true, obj = l }; }).Where(p => p.Succ == false).ToList(); if (lostList.Count > 0) { var bookingOrderList = _repBookingOrder.AsQueryable().Filter(null, true) .Where(x => bookingNoList.Contains(x.Id) && x.IsDeleted == false && x.TenantId == UserManager.TENANT_ID).ToList(); _logger.LogInformation($"提单号:{model.MBLNo} 检索通知消息没有发送过,需要补发通知"); foreach (var md in lostList) { var bookingOrder = bookingOrderList.FirstOrDefault(p => p.Id == md.obj); List userIds = new List(); List userList = new List(); if (!string.IsNullOrWhiteSpace(bookingOrder.OPID)) userIds.Add(long.Parse(bookingOrder.OPID)); if (!string.IsNullOrWhiteSpace(bookingOrder.CUSTSERVICEID)) userIds.Add(long.Parse(bookingOrder.CUSTSERVICEID)); userIds.Add(bookingOrder.CreatedUserId.Value); userIds = userIds.Distinct().ToList(); userList = _sysUserRepository.AsQueryable().Filter(null, true) .Where(x => userIds.Contains(x.Id) && x.IsDeleted == false && x.TenantId == UserManager.TENANT_ID).ToList(); var slotInfo = bookingSlotAllocList .FirstOrDefault(x => x.Alloc != null && x.Alloc.BOOKING_ID == bookingOrder.Id).Slot; userList.ForEach(user => { //表示即有舱位也有订舱记录 var detailInfo = new TaskCautionNoticeWholeShipDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = shipInfo.PK_ID, BOOKING_ID = bookingOrder.Id, BOOKING_SLOT_ID = slotInfo.Id, BATCH_NO = batchNo, IsDeleted = false, MBL_NO = bookingOrder.MBLNO, STATUS = "TEMP", STATUS_NAME = "暂存", NOTIFY_METHOD = CautionNoticeMethodEnum.Email.ToString(), NOTIFY_USER_ID = user.Id.ToString(), NOTIFY_USER_NAME = user.Name, NOTIFY_MOBILE = user.Phone?.Trim(), NOTIFY_EMAIL = user.Email?.Trim(), CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, }; detailRecordList.Add(detailInfo); _taskCautionNoticeWholeShipDetailInfoRepository.InsertAsync(detailInfo); //表示即有舱位也有订舱记录 var detail2Info = new TaskCautionNoticeWholeShipDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = shipInfo.PK_ID, BOOKING_ID = bookingOrder.Id, BOOKING_SLOT_ID = slotInfo.Id, BATCH_NO = batchNo, IsDeleted = false, MBL_NO = bookingOrder.MBLNO, STATUS = "TEMP", STATUS_NAME = "暂存", NOTIFY_METHOD = CautionNoticeMethodEnum.DingDing.ToString(), NOTIFY_USER_ID = user.Id.ToString(), NOTIFY_USER_NAME = user.Name, NOTIFY_MOBILE = user.Phone?.Trim(), NOTIFY_EMAIL = user.Email?.Trim(), CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, }; detailRecordList.Add(detail2Info); _taskCautionNoticeWholeShipDetailInfoRepository.InsertAsync(detail2Info); var notice = new CautionNoticeTaskDto { createTime = DateTime.Now, origVal = "", newVal = "", tenentId = user.TenantId.Value, userId = user.Id, userName = user.Name, mblNo = bookingOrder.MBLNO, carrier = bookingOrder.CARRIERID, sourceSystem = "DjyBooking", sourceBusiType = "BookingSlot", sourceBusiTypeName = "舱位管理", vessel = model.VesselOldVal, voyno = model.VoynoOldVal, tenentName = UserManager.TENANT_NAME, isAutoSendNotice = false, IsCutDateAdvanced = model.IsCutDateAdvanced, IsVesselChange = model.IsVesselChange, IsTransfer = model.IsTransfer, SICutOldVal = model.SICutOldVal, SICutNewVal = model.SICutNewVal, VGMCutOldVal = model.VGMCutOldVal, VGMCutNewVal = model.VGMCutNewVal, VesselOldVal = model.VesselOldVal, VesselNewVal = model.VesselNewVal, VoynoOldVal = model.VoynoOldVal, VoynoNewVal = model.VoynoNewVal, notifyList = new List() }; if (model.IsVesselChange && (model.IsCutDateAdvanced || model.IsTransfer)) { notice.cautionNoticeType = CautionNoticeTaskEnum.VesselCutDateTransfer; } else { if (model.IsVesselChange) { notice.cautionNoticeType = CautionNoticeTaskEnum.ChangeVesselVoyno; } else if (model.IsCutDateAdvanced) { notice.cautionNoticeType = CautionNoticeTaskEnum.CutDateAdvanced; } else if (model.IsTransfer) { notice.cautionNoticeType = CautionNoticeTaskEnum.ChangeTransfer; } } cautionList.Add(notice); }); } } } else { bookingSlotAllocList.ForEach(t => { var slotInfo = detailList.FirstOrDefault(p => p.BOOKING_SLOT_ID == t.Slot.Id); if (slotInfo == null) { //表示只有舱位 //表示即有舱位也有订舱记录 var createUserId = t.Slot.CreatedUserId.Value; var user = _sysUserRepository.AsQueryable().Filter(null, true) .First(x => x.Id == createUserId && x.IsDeleted == false && x.TenantId == UserManager.TENANT_ID); var detailInfo = new TaskCautionNoticeWholeShipDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = shipInfo.PK_ID, BOOKING_SLOT_ID = t.Slot.Id, BATCH_NO = batchNo, IsDeleted = false, MBL_NO = t.Slot.SLOT_BOOKING_NO, STATUS = "TEMP", STATUS_NAME = "暂存", NOTIFY_METHOD = CautionNoticeMethodEnum.Email.ToString(), NOTIFY_USER_ID = user.Id.ToString(), NOTIFY_USER_NAME = user.Name, NOTIFY_MOBILE = user.Phone?.Trim(), NOTIFY_EMAIL = user.Email?.Trim(), CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, }; detailRecordList.Add(detailInfo); _taskCautionNoticeWholeShipDetailInfoRepository.InsertAsync(detailInfo); //表示即有舱位也有订舱记录 var detail2Info = new TaskCautionNoticeWholeShipDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = shipInfo.PK_ID, BOOKING_SLOT_ID = t.Slot.Id, BATCH_NO = batchNo, IsDeleted = false, MBL_NO = t.Slot.SLOT_BOOKING_NO, STATUS = "TEMP", STATUS_NAME = "暂存", NOTIFY_METHOD = CautionNoticeMethodEnum.DingDing.ToString(), NOTIFY_USER_ID = user.Id.ToString(), NOTIFY_USER_NAME = user.Name, NOTIFY_MOBILE = user.Phone?.Trim(), NOTIFY_EMAIL = user.Email?.Trim(), CreatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, TenantName = UserManager.TENANT_NAME, }; detailRecordList.Add(detail2Info); _taskCautionNoticeWholeShipDetailInfoRepository.InsertAsync(detail2Info); var notice = new CautionNoticeTaskDto { createTime = DateTime.Now, origVal = "", newVal = "", tenentId = user.TenantId.Value, userId = user.Id, userName = user.Name, mblNo = t.Slot.SLOT_BOOKING_NO, carrier = t.Slot.CARRIERID, sourceSystem = "DjyBooking", sourceBusiType = "BookingSlot", sourceBusiTypeName = "舱位管理", vessel = model.VesselOldVal, voyno = model.VoynoOldVal, tenentName = UserManager.TENANT_NAME, isAutoSendNotice = false, IsCutDateAdvanced = model.IsCutDateAdvanced, IsVesselChange = model.IsVesselChange, IsTransfer = model.IsTransfer, SICutOldVal = model.SICutOldVal, SICutNewVal = model.SICutNewVal, VGMCutOldVal = model.VGMCutOldVal, VGMCutNewVal = model.VGMCutNewVal, VesselOldVal = model.VesselOldVal, VesselNewVal = model.VesselNewVal, VoynoOldVal = model.VoynoOldVal, VoynoNewVal = model.VoynoNewVal, notifyList = new List() }; if (model.IsVesselChange && (model.IsCutDateAdvanced || model.IsTransfer)) { notice.cautionNoticeType = CautionNoticeTaskEnum.VesselCutDateTransfer; } else { if (model.IsVesselChange) { notice.cautionNoticeType = CautionNoticeTaskEnum.ChangeVesselVoyno; } else if (model.IsCutDateAdvanced) { notice.cautionNoticeType = CautionNoticeTaskEnum.CutDateAdvanced; } else if (model.IsTransfer) { notice.cautionNoticeType = CautionNoticeTaskEnum.ChangeTransfer; } } notice.notifyList.Add(new CautionNoticeTaskNoitfyDto { notifyEmail = user.Email, notifyMethod = new CautionNoticeMethodEnum[] { CautionNoticeMethodEnum.Email, CautionNoticeMethodEnum.DingDing }, notifyMobile = user.Phone, notifyUserId = user.Id, notifyUserName = user.Name }); cautionList.Add(notice); } }); } } else { new EmailNoticeHelper().SendEmailNotice($"slotid={model.SlotId} mblno={model.MBLNo} 推送重要提醒失败", $"slotid={model.SlotId} mblno={model.MBLNo} 推送重要提醒失败,原因已有整船通知记录不再重复通知", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } } if(detailRecordList.Count > 0) { //推送钉钉消息 await PushDingdingNotice(detailRecordList, shipInfo, slotBaseInfo); cautionList.ForEach(t => { SendTask(t).GetAwaiter().GetResult(); }); } } catch (Exception ex) { new EmailNoticeHelper().SendEmailNotice($"slotid={model.SlotId} 推送重要提醒整船通知异常", $"slotid={model.SlotId} 推送重要提醒整船通知异常 原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } return rlt; } #endregion private async Task PushDingdingNotice(List detailList, TaskCautionNoticeWholeShipInfo shipInfo, BookingSlotBase slotInfo) { try { var tenantId = detailList.FirstOrDefault().TenantId; StringBuilder contentBuilder = new StringBuilder(); contentBuilder.AppendLine("起运港:"+ slotInfo.PLACERECEIPT); contentBuilder.AppendLine("目的港:" + slotInfo.PLACEDELIVERY); contentBuilder.AppendLine("船名/航次:" + $"{slotInfo.VESSEL}/{slotInfo.VOYNO}"); contentBuilder.AppendLine("ETD:" + (slotInfo.ETD.HasValue ? slotInfo.ETD.Value.ToString("yyyy-MM-dd") : "")); contentBuilder.AppendLine("================="); //截止时间提前 if (shipInfo.IS_CUT_DATE_ADVANCED) { if (!string.IsNullOrWhiteSpace(shipInfo.VGM_CUT_OLD_VAL) && !string.IsNullOrWhiteSpace(shipInfo.VGM_CUT_NEW_VAL)) { if (!shipInfo.VGM_CUT_OLD_VAL.Equals(shipInfo.VGM_CUT_NEW_VAL, StringComparison.OrdinalIgnoreCase)) { contentBuilder.AppendLine("VGM截止时间提前"); contentBuilder.AppendLine("原:" + shipInfo.VGM_CUT_OLD_VAL); contentBuilder.AppendLine("新:" + shipInfo.VGM_CUT_NEW_VAL); contentBuilder.AppendLine("================="); } } if (!string.IsNullOrWhiteSpace(shipInfo.SI_CUT_OLD_VAL) && !string.IsNullOrWhiteSpace(shipInfo.SI_CUT_NEW_VAL)) { if (!shipInfo.SI_CUT_OLD_VAL.Equals(shipInfo.SI_CUT_NEW_VAL, StringComparison.OrdinalIgnoreCase)) { contentBuilder.AppendLine("SI截止时间提前"); contentBuilder.AppendLine("原:" + shipInfo.SI_CUT_OLD_VAL); contentBuilder.AppendLine("新:" + shipInfo.SI_CUT_NEW_VAL); contentBuilder.AppendLine("================="); } } } //船名航次变更 if (shipInfo.IS_VESSEL_CHANGE) { contentBuilder.AppendLine("船名航次变更"); contentBuilder.AppendLine("原:" + $"{shipInfo.VESSEL_OLD_VAL}/{shipInfo.VOYNO_OLD_VAL}"); contentBuilder.AppendLine("新:" + $"{shipInfo.VESSEL_NEW_VAL}/{shipInfo.VOYNO_NEW_VAL}"); contentBuilder.AppendLine("================="); } //直达变中转 if (shipInfo.IS_TRANSFER) { contentBuilder.AppendLine("直达变中转"); contentBuilder.AppendLine("原:" + shipInfo.DIRECT_TO_TRANS_OLD_VAL); contentBuilder.AppendLine("新:" + shipInfo.DIRECT_TO_TRANS_NEW_VAL); contentBuilder.AppendLine("================="); } contentBuilder.AppendLine("提单号 |对应操作 "); detailList.GroupBy(a => a.MBL_NO).Select(p => { return new { Key = p.Key, userList = p.ToList() }; }).ToList().ForEach(p => { if (!p.userList.FirstOrDefault().BOOKING_ID.HasValue) { contentBuilder.AppendLine($"{p.Key.PadRight(15, ' ')}|未分配操作"); } else { contentBuilder.AppendLine($"{p.Key.PadRight(15, ' ')}|{(string.Join(",", p.userList.Select(x => x.NOTIFY_USER_NAME).Distinct().ToArray()).PadRight(40, ' '))}"); } }); var mobileArg = detailList.Select(p => p.NOTIFY_MOBILE).Distinct().ToArray(); _logger.LogInformation($"准备钉钉通知,内容:\r\n{contentBuilder.ToString()}"); DingTalkGroupHelper.SendDingTalkGroupMessage($"{tenantId}_Notify", "重要通知提醒", $"{contentBuilder.ToString()}", false, mobileArg, null); _logger.LogInformation($"钉钉通知完成"); detailList.ForEach(async t => { await _taskCautionNoticeWholeShipDetailInfoRepository.AsUpdateable(t).UpdateColumns(p => new { p.STATUS, p.STATUS_NAME, }).ExecuteCommandAsync(); }); } catch(Exception ex) { _logger.LogInformation($"重要通知提醒主键shipInfo={shipInfo.PK_ID} 推送钉钉通知异常 原因:{ex.Message}"); new EmailNoticeHelper().SendEmailNotice($"重要通知提醒主键shipInfo={shipInfo.PK_ID} 推送钉钉通知异常", $"重要通知提醒主键shipInfo={shipInfo.PK_ID} 推送钉钉通知异常 原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } } #region 生成重要提醒任务 /// /// 生成重要提醒任务 /// /// 生成重要提醒任务详情 /// private async Task SendTask(CautionNoticeTaskDto dto) { TaskManageOrderMessageInfo messageInfo = new TaskManageOrderMessageInfo { Head = new TaskManageOrderMessageHeadInfo { GID = IDGen.NextID().ToString(), MessageType = "CAUTION_TASK", SenderId = "CautionNoticeTask", SenderName = "重要提醒任务生成", ReceiverId = "TaskManage", ReceiverName = "任务台", RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Version = "1.0", RequestAction = "Add" }, Main = new TaskManageOrderMessageMainInfo { TaskType = TaskBaseTypeEnum.CAUTION_NOTICE, } }; messageInfo.Main.TaskTenatId = dto.tenentId; messageInfo.Main.TaskTenatName = dto.tenentName; messageInfo.Main.VesselVoyno = $"{dto.vessel}/{dto.voyno}"; messageInfo.Main.TaskUserId = dto.userId.ToString(); messageInfo.Main.TaskUserName = dto.userName; messageInfo.Main.CarrierId = dto.carrier; messageInfo.Main.CustomerId = dto.customerId; messageInfo.Main.CustomerName = dto.customerName; messageInfo.Main.MBlNo = dto.mblNo; messageInfo.Main.ETD = dto.etd; messageInfo.Main.TaskTitle = $"重要提醒-{dto.cautionNoticeType.GetDescription()} BLNo:{dto.mblNo} {dto.vessel}/{dto.voyno} {(dto.etd.HasValue ? dto.etd.Value.ToString("yyyy-MM-dd") : "")} "; messageInfo.Main.TaskDesp = $"重要提醒-{dto.cautionNoticeType.GetDescription()} BLNo:{dto.mblNo} {dto.vessel}/{dto.voyno} {(dto.etd.HasValue ? dto.etd.Value.ToString("yyyy-MM-dd") : "")}"; messageInfo.Main.CautionNoticeInfo = new TaskManageOrderCautionNoticeInfo { BookingId = dto.bookingId, BookingSlotId = dto.bookingSlotId, CautionNoticeType = dto.cautionNoticeType, Carrier = dto.carrier, MBlNo = dto.mblNo, OrigVal = dto.origVal, NewVal = dto.newVal, NotifyContent = dto.notifyContent, SourceSystem = dto.sourceSystem, SourceBusiType = dto.sourceBusiType, SourceBusiTypeName = dto.sourceBusiTypeName, CreateTime = DateTime.Now, IsAutoSendNotice = dto.isAutoSendNotice, IsWeekDiff = dto.IsWeekDiff, IsCutDateAdvanced = dto.IsCutDateAdvanced, IsTransfer = dto.IsTransfer, IsPriceDateDiff = dto.IsPriceDateDiff, IsVesselChange = dto.IsVesselChange, SICutOldVal = dto.SICutOldVal, SICutNewVal = dto.SICutNewVal, VGMCutOldVal = dto.VGMCutOldVal, VGMCutNewVal = dto.VGMCutNewVal, VesselOldVal = dto.VesselOldVal, VesselNewVal = dto.VesselNewVal, VoynoOldVal = dto.VoynoOldVal, VoynoNewVal = dto.VoynoNewVal, DirectToTransOldVal = dto.DirectToTransOldVal, DirectToTransNewVal = dto.DirectToTransNewVal, NoticeList = new List() }; if (dto.notifyList != null && dto.notifyList.Count > 0) { dto.notifyList.ForEach(p => { foreach (var item in p.notifyMethod) { var notifyInfo = new TaskManageOrderCautionNoticeDetailInfo { CautionNoticeType = item, Email = p.notifyEmail, UserId = p.notifyUserId, UserName = p.notifyUserName, Mobile = p.notifyMobile, }; messageInfo.Main.CautionNoticeInfo.NoticeList.Add(notifyInfo); } }); } var service = _namedTaskManageServiceProvider.GetService(nameof(TaskManageService)); var rlt = await service.CreateTaskJob(messageInfo); } #endregion } }