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.

300 lines
15 KiB
C#

This file contains ambiguous Unicode characters!

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

using Furion;
using Furion.EventBus;
using Furion.FriendlyException;
using Furion.RemoteRequest.Extensions;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Myshipping.Application.ConfigOption;
using Myshipping.Application.Entity;
using Myshipping.Application.Service.BookingOrder.Dto;
using Myshipping.Core;
using Myshipping.Core.Entity;
using Myshipping.Core.Service;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Myshipping.Application.Event
{
/// <summary>
/// 订舱同步给客户订舱系统
/// </summary>
public class BookingSyncSubscriber : IEventSubscriber
{
private IServiceProvider _services { get; }
private readonly ILogger<BookingSyncSubscriber> _logger;
public BookingSyncSubscriber(IServiceProvider services, ILogger<BookingSyncSubscriber> logger)
{
_services = services;
_logger = logger;
}
//发送订舱同步数据给客户订舱系统
[EventSubscribe("SendToCustomer:Book")]
public async Task SendToCustomer(EventHandlerExecutingContext context)
{
_logger.LogInformation($"收到订舱同步客户订舱系统请求:{context.Source.Payload}");
var bookId = (long)context.Source.Payload;
using var scope = _services.CreateScope();
var repoCutomerOrder = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingCustomerOrder>>();
var repoOrder = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingOrder>>();
var repoCtn = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingCtn>>();
var repoFile = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingFile>>();
var repoStaLog = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingStatusLog>>();
var repoStaLogDetail = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingStatusLogDetail>>();
var repoGoodsSta = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingGoodsStatus>>();
var repoGoodsStaCfg = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingGoodsStatusConfig>>();
var cacheService = scope.ServiceProvider.GetRequiredService<ISysCacheService>();
var custOrder = await repoCutomerOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.BookingId == bookId);
if (custOrder == null) //非客户订舱系统过来的数据
{
_logger.LogInformation($"ID为 {bookId} 的数据并非来自客户订舱系统,不继续处理数据回推");
return;
}
var order = await repoOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == bookId);
var ctns = await repoCtn.AsQueryable().Filter(null, true).Where(x => x.BILLID == bookId).ToListAsync();
var files = await repoFile.AsQueryable().Filter(null, true).Where(x => x.BookingId == bookId).ToListAsync();
var staLogs = await repoStaLog.AsQueryable().Filter(null, true).Where(x => x.BookingId == bookId).ToListAsync();
var staLogDetails = await repoStaLogDetail.AsQueryable().Filter(null, true).Where(x => staLogs.Select(y => y.Id).Contains(x.PId)).ToListAsync();
var goodsLogs = await repoGoodsSta.AsQueryable().Filter(null, true).Where(x => x.bookingId == bookId).ToListAsync();
var goodsLogConfigs = await repoGoodsStaCfg.AsQueryable().Filter(null, true).Where(x => goodsLogs.Select(y => y.ConfigId).Contains(x.Id)).ToListAsync();
//把ID还原为客户订舱系统中的ID
order.Id = Convert.ToInt64(order.BSNO);
order.BSNO = null;
ctns.ForEach(x => x.BILLID = order.Id);
files.ForEach(x => x.BookingId = order.Id);
staLogs.ForEach(x => x.BookingId = order.Id);
goodsLogs.ForEach(x => x.bookingId = order.Id);
var staLogSendList = staLogs.Adapt<List<BookingStatusLogSyncCustomerDto>>();
staLogSendList.ForEach(x =>
{
x.Details = staLogDetails.Where(y => y.PId == x.Id).Adapt<List<BookingStatusLogDetailSyncCustomerDto>>();
});
//发送对象
var sendObj = new BookingCustomerRecDataFeedbackDto()
{
Order = order.Adapt<BookingOrderSyncCustomerDto>(),
Ctns = ctns.Adapt<List<BookingCtnSyncCustomerDto>>(),
Files = files.Adapt<List<BookingFileSyncCustomerDto>>(),
StatusLogs = staLogSendList
};
//文件内容
var opt = App.GetOptions<BookingAttachOptions>();
var dirAbs = opt.basePath;
if (string.IsNullOrEmpty(dirAbs))
{
dirAbs = App.WebHostEnvironment.WebRootPath;
}
foreach (var file in files)
{
var fileFullPath = Path.Combine(dirAbs, file.FilePath);
if (File.Exists(fileFullPath))
{
sendObj.Files.First(x => x.Id == file.Id).FileContent = File.ReadAllBytes(fileFullPath);
}
}
//回推回执
var recFeedbackConfig = cacheService.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackURL");
if (recFeedbackConfig == null || string.IsNullOrEmpty(recFeedbackConfig.Value))
{
throw Oops.Bah("回推订舱数据的URL地址未配置请联系管理员");
}
var recFeedbackUserKey = cacheService.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackUserKey");
if (recFeedbackUserKey == null || string.IsNullOrEmpty(recFeedbackUserKey.Value))
{
throw Oops.Bah("回推订舱数据的用户KEY未配置请联系管理员");
}
var recFeedbackUserSecret = cacheService.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackUserSecret");
if (recFeedbackUserSecret == null || string.IsNullOrEmpty(recFeedbackUserSecret.Value))
{
throw Oops.Bah("回推订舱数据的用户秘钥未配置,请联系管理员");
}
var feedbackUrl = recFeedbackConfig.Value;
if (!feedbackUrl.EndsWith("/"))
{
feedbackUrl += "/";
}
feedbackUrl += "DataSync/RecBookingDataFeedback";
_logger.LogInformation($"准备发送客户订舱数据同步:{sendObj.ToJsonString()}URL{feedbackUrl}");
var rtn = await feedbackUrl
.SetHeaders(new Dictionary<string, object> {
{ CommonConst.API_USER_HEADER_KEY, recFeedbackUserKey.Value},
{ CommonConst.API_USER_HEADER_SECRET, recFeedbackUserSecret.Value}
})
.SetBody(sendObj)
.PostAsStringAsync();
_logger.LogInformation($"回推数据同步返回:{rtn}");
var jobjRtn = JObject.Parse(rtn);
if (jobjRtn.GetIntValue("code") != 200)
{
throw Oops.Bah(jobjRtn.GetStringValue("message"));
}
}
//推送货物状态到客户订舱系统
[EventSubscribe("SyncGoodStatus:Book")]
public async Task SyncGoodStatus(EventHandlerExecutingContext context)
{
_logger.LogInformation($"收到推送货物状态到客户订舱系统:{context.Source.Payload}");
GoodsStatusSyncDto payload = context.Source.Payload as GoodsStatusSyncDto;
using var scope = _services.CreateScope();
var repoCutomerOrder = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingCustomerOrder>>();
var repoOrder = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingOrder>>();
var cacheService = scope.ServiceProvider.GetRequiredService<ISysCacheService>();
var custOrder = await repoCutomerOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.BookingId == payload.Id);
if (custOrder == null) //非客户订舱系统过来的数据
{
_logger.LogInformation($"ID为 {payload.Id} 的数据并非来自客户订舱系统,不继续处理数据回推");
return;
}
var order = await repoOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == payload.Id);
//把ID还原为客户订舱系统中的ID
payload.Id = Convert.ToInt64(order.BSNO);
//回推回执
var recFeedbackConfig = cacheService.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackURL");
if (recFeedbackConfig == null || string.IsNullOrEmpty(recFeedbackConfig.Value))
{
throw Oops.Bah("回推订舱数据的URL地址未配置请联系管理员");
}
var recFeedbackUserKey = cacheService.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackUserKey");
if (recFeedbackUserKey == null || string.IsNullOrEmpty(recFeedbackUserKey.Value))
{
throw Oops.Bah("回推订舱数据的用户KEY未配置请联系管理员");
}
var recFeedbackUserSecret = cacheService.GetAllSysConfig().Result.FirstOrDefault(x => x.Code == "DjyBookingCustomerRecFeedbackUserSecret");
if (recFeedbackUserSecret == null || string.IsNullOrEmpty(recFeedbackUserSecret.Value))
{
throw Oops.Bah("回推订舱数据的用户秘钥未配置,请联系管理员");
}
var feedbackUrl = recFeedbackConfig.Value;
if (!feedbackUrl.EndsWith("/"))
{
feedbackUrl += "/";
}
feedbackUrl += "DataSync/RecGoodsStatusSync";
_logger.LogInformation($"准备发送货物状态数据同步:{payload.ToJsonString()}URL{feedbackUrl}");
var rtn = await feedbackUrl
.SetHeaders(new Dictionary<string, object> {
{ CommonConst.API_USER_HEADER_KEY, recFeedbackUserKey.Value},
{ CommonConst.API_USER_HEADER_SECRET, recFeedbackUserSecret.Value}
})
.SetBody(payload)
.PostAsStringAsync();
_logger.LogInformation($"回推数据同步返回:{rtn}");
var jobjRtn = JObject.Parse(rtn);
if (jobjRtn.GetIntValue("code") != 200)
{
throw Oops.Bah(jobjRtn.GetStringValue("message"));
}
}
//推送货物状态通知
[EventSubscribe("GoodsStatusSubscribeNotify:Book")]
public async Task GoodsStatusSubscribeNotify(EventHandlerExecutingContext context)
{
_logger.LogInformation($"收到推送货物状态通知请求:{context.Source.Payload}");
dynamic payload = context.Source.Payload;
long bookId = payload.BookingId;
string statusCode = payload.StatusCode;
string statusName = payload.StatusName;
using var scope = _services.CreateScope();
var cache = scope.ServiceProvider.GetRequiredService<ISysCacheService>();
var repoOrder = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingOrder>>();
var repoBookingGoodsStatusSubscribe = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<BookingGoodsStatusSubscribe>>();
var order = await repoOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == bookId);
var subList = await repoBookingGoodsStatusSubscribe.AsQueryable().Filter(null, true).Where(x => x.IsDeleted == false && x.BookingId == bookId).ToListAsync();
foreach (var sub in subList)
{
if (sub.SendMail && !string.IsNullOrEmpty(sub.Email) && sub.StatusCode.Split(',').Contains(statusCode))
{
var subject = $"大简云-货物通知:{order.MBLNO}---{order.VESSEL}/{order.VOYNO}{statusName}";
var body = $"尊敬的客户,您好:<br/><br/>您所订阅的提单号{order.MBLNO} ,船名航次{order.VESSEL}/{order.VOYNO}的业务{statusName}。<br/><br/>—— 此邮件为大简云平台自动发送,请勿回复。<br/><br/><img src='https://wechat.myshipping.net:8860/wechat_image/banner.png' style='width:300px;'/>";
var sendUrlCfg = cache.GetAllDictData().Result.FirstOrDefault(x => x.Code == "email_api_url");
if (sendUrlCfg == null)
{
_logger.LogError($"未配置邮件发送URL推送货物状态通知邮件未能发送。订舱ID{bookId},状态:{statusName}({statusCode}),邮箱:{sub.Email}");
}
var mailJson = new dynamic[]{
new
{
SendTo = sub.Email,
Title = subject,
Body = body,
SmtpConfig = "SERVICE"
}
};
var mailStr = mailJson.ToJsonString();
_logger.LogInformation($"准备推送货物状态邮件通知JSON{mailStr}订舱ID{bookId},状态:{statusName}({statusCode}),邮箱:{sub.Email}");
var rtn = await sendUrlCfg.Value
.SetBody(mailStr)
.PostAsStringAsync();
_logger.LogError($"推送货物状态通知邮件发送返回:{rtn}。订舱ID{bookId},状态:{statusName}({statusCode}),邮箱:{sub.Email}");
var jsonRtn = JObject.Parse(rtn);
if (jsonRtn.GetBooleanValue("Success"))
{
_logger.LogInformation($"推送货物状态通知邮件发送成功。订舱ID{bookId},状态:{statusName}({statusCode}),邮箱:{sub.Email}");
}
else
{
_logger.LogError($"推送货物状态通知邮件发送失败:{jsonRtn.GetStringValue("Message")}。订舱ID{bookId},状态:{statusName}({statusCode}),邮箱:{sub.Email}。");
}
}
}
}
}
}