|
|
|
@ -20,6 +20,18 @@ using SqlSugar.IOC;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using NLog;
|
|
|
|
|
using DS.WMS.Core.Sys.Interface;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using LanguageExt.Common;
|
|
|
|
|
using DS.Module.Core.Helpers;
|
|
|
|
|
using NPOI.SS.Formula.Functions;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using DS.WMS.Core.Sys.Method;
|
|
|
|
|
using DS.WMS.Core.Map.Dtos;
|
|
|
|
|
using Org.BouncyCastle.Ocsp;
|
|
|
|
|
using DS.WMS.Core.Code.Entity;
|
|
|
|
|
using DS.WMS.Core.Map.Entity;
|
|
|
|
|
using DS.WMS.Core.Code.Dtos;
|
|
|
|
|
using System.Net.Http.Headers;
|
|
|
|
|
|
|
|
|
|
namespace DS.WMS.Core.Op.Method
|
|
|
|
|
{
|
|
|
|
@ -32,9 +44,33 @@ namespace DS.WMS.Core.Op.Method
|
|
|
|
|
private readonly ISeaExportService _seaExportService;
|
|
|
|
|
private readonly IBookingLabelService _bookingLabelService;
|
|
|
|
|
private readonly ILogAuditService _logAuditService;
|
|
|
|
|
private readonly ISysCacheService _sysCacheService;
|
|
|
|
|
private readonly ISysFileService _sysFileService;
|
|
|
|
|
private readonly IBookingSlotStockService _bookingSlotStockService;
|
|
|
|
|
private readonly string bcCompareUrl;
|
|
|
|
|
|
|
|
|
|
private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger();
|
|
|
|
|
|
|
|
|
|
const string CONST_BC_FILE_CODE = "bc";
|
|
|
|
|
const string CONST_BC_FILE_NAME = "Booking Confirmation";
|
|
|
|
|
|
|
|
|
|
const string CONST_BC_NOTICE_FILE_CODE = "bc_notice";
|
|
|
|
|
const string CONST_BC_NOTICE_FILE_NAME = "Booking Confirmation Notice";
|
|
|
|
|
|
|
|
|
|
const string CONST_BC_MODIFY_FILE_CODE = "bc_modify";
|
|
|
|
|
const string CONST_BC_MODIFY_FILE_NAME = "Booking Amendment";
|
|
|
|
|
|
|
|
|
|
const string CONST_BC_MODIFY_NOTICE_FILE_CODE = "bc_modifynotice";
|
|
|
|
|
const string CONST_BC_MODIFY_NOTICE_FILE_NAME = "Booking Amendment Notice";
|
|
|
|
|
|
|
|
|
|
//收货地名称解析装货港港口
|
|
|
|
|
const string RECEIPT_TO_PORTLOAD = "ReceiptToPortLoad";
|
|
|
|
|
|
|
|
|
|
//交货地名称解析卸货港港口
|
|
|
|
|
const string DELIVERY_TO_PORT = "DeliveryToPort";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public BookingSlotService(IServiceProvider serviceProvider)
|
|
|
|
|
{
|
|
|
|
|
_serviceProvider = serviceProvider;
|
|
|
|
@ -44,6 +80,11 @@ namespace DS.WMS.Core.Op.Method
|
|
|
|
|
_seaExportService = _serviceProvider.GetRequiredService<ISeaExportService>();
|
|
|
|
|
_bookingLabelService = _serviceProvider.GetRequiredService<IBookingLabelService>();
|
|
|
|
|
_logAuditService = _serviceProvider.GetRequiredService<ILogAuditService>();
|
|
|
|
|
_sysCacheService = _serviceProvider.GetRequiredService<ISysCacheService>();
|
|
|
|
|
_sysFileService = _serviceProvider.GetRequiredService<ISysFileService>();
|
|
|
|
|
_bookingSlotStockService = _serviceProvider.GetRequiredService<IBookingSlotStockService>();
|
|
|
|
|
|
|
|
|
|
bcCompareUrl = AppSetting.app(new string[] { "BCCompare", "Url" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region 保存舱位
|
|
|
|
@ -660,5 +701,864 @@ namespace DS.WMS.Core.Op.Method
|
|
|
|
|
return DataResult<BookingSlotBaseSaveOutput>.Success(rtn);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 舱位接收保存、取消接口
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 舱位接收保存、取消接口
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="jsonData">请求详情(JSON)</param>
|
|
|
|
|
/// <param name="file">BC附件</param>
|
|
|
|
|
/// <param name="modifyFile">BC修改附件</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
public async Task<DataResult<long>> ApiReceive(string jsonData, IFormFile file = null, IFormFile modifyFile = null)
|
|
|
|
|
{
|
|
|
|
|
long id = 0;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"jsonData={jsonData} 接收请求舱位报文");
|
|
|
|
|
|
|
|
|
|
BookingSlotBaseApiDto dto = JsonConvert.DeserializeObject<BookingSlotBaseApiDto>(jsonData);
|
|
|
|
|
|
|
|
|
|
DynameFileInfo bcFile = null;
|
|
|
|
|
DynameFileInfo bcNoticeFile = null;
|
|
|
|
|
|
|
|
|
|
if (file != null)
|
|
|
|
|
{
|
|
|
|
|
bcFile = new DynameFileInfo
|
|
|
|
|
{
|
|
|
|
|
FileBytes = file.ToByteArray(),
|
|
|
|
|
FileName = file.FileName
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (modifyFile != null)
|
|
|
|
|
{
|
|
|
|
|
bcNoticeFile = new DynameFileInfo
|
|
|
|
|
{
|
|
|
|
|
FileBytes = modifyFile.ToByteArray(),
|
|
|
|
|
FileName = modifyFile.FileName
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var rlt = await InnerApiReceive(dto, bcFile, bcNoticeFile);
|
|
|
|
|
|
|
|
|
|
id = rlt.Data;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Error, $"执行舱位失败,原因:{ex.Message}");
|
|
|
|
|
|
|
|
|
|
return DataResult<long>.FailedData(id, string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotApiReceiveError)), ex.Message));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (id == 0)
|
|
|
|
|
return DataResult<long>.FailedData(id);
|
|
|
|
|
|
|
|
|
|
return DataResult<long>.Success(id);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 舱位接收保存、取消接口(内部接口)
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 舱位接收保存、取消接口(内部接口)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="dto">舱位详情</param>
|
|
|
|
|
/// <param name="file">原文件</param>
|
|
|
|
|
/// <param name="modifyFile">修改文件</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
public async Task<DataResult<long>> InnerApiReceive(BookingSlotBaseApiDto dto, DynameFileInfo file = null, DynameFileInfo modifyFile = null)
|
|
|
|
|
{
|
|
|
|
|
long id = 0;
|
|
|
|
|
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
|
|
|
|
//接口方法直接调用save、delete等方法会报错,可能因为非token授权登录导致,故重写一遍保存、删除代码
|
|
|
|
|
if (dto.OpType == "add" || dto.OpType == "update" || dto.OpType == "del" || dto.OpType == "cancellation")
|
|
|
|
|
{
|
|
|
|
|
//翻译船公司
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.DataObj.CarrierCode) && string.IsNullOrWhiteSpace(dto.DataObj.CarrierCode))
|
|
|
|
|
{
|
|
|
|
|
var allCarrierList = await _sysCacheService.GetAllCommonCodeFromCache<MappingCarrierRes>(SysCacheKeyEnum.CommonMappingCarrier);
|
|
|
|
|
|
|
|
|
|
if (allCarrierList.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
var carrierInfo = allCarrierList.Data.Where(t => t.Code.Equals(dto.DataObj.CarrierCode, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
if (carrierInfo != null)
|
|
|
|
|
{
|
|
|
|
|
dto.DataObj.Carrier = carrierInfo.MapName?.Trim();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//翻译箱型代码
|
|
|
|
|
if (dto.DataObj.CtnList != null && dto.DataObj.CtnList.Count > 0 &&
|
|
|
|
|
dto.DataObj.CtnList.Any(t => string.IsNullOrWhiteSpace(t.CtnCode)))
|
|
|
|
|
{
|
|
|
|
|
List<CodeCtnRes> ctnCodeList = new List<CodeCtnRes>();
|
|
|
|
|
|
|
|
|
|
var allCtnCodeList = await _sysCacheService.GetAllCommonCodeFromCache<CodeCtnRes>(SysCacheKeyEnum.CommonMappingCarrier);
|
|
|
|
|
|
|
|
|
|
if (allCtnCodeList.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
ctnCodeList = allCtnCodeList.Data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dto.DataObj.CtnList.ForEach(t =>
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(t.CtnAll) && string.IsNullOrWhiteSpace(t.CtnCode))
|
|
|
|
|
{
|
|
|
|
|
var ctnCode = ctnCodeList.FirstOrDefault(a => !string.IsNullOrWhiteSpace(a.CtnName) &&
|
|
|
|
|
a.CtnName.Equals(t.CtnAll, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
|
|
|
|
|
if (ctnCode != null)
|
|
|
|
|
t.CtnCode = $"{ctnCode.CtnSize}{ctnCode.CtnType}";
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<CodePortRes> portCodeList = new List<CodePortRes>();
|
|
|
|
|
|
|
|
|
|
// 解析收货地,得到装货港名称及五字码
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.DataObj.PlaceReceipt))
|
|
|
|
|
{
|
|
|
|
|
var portEnName = dto.DataObj.PlaceReceipt.Split(',')[0]?.Trim();
|
|
|
|
|
|
|
|
|
|
//这里CMA的收货地全称放在了括号里面
|
|
|
|
|
if (dto.DataObj.CarrierCode.Equals("CMA", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.DataObj.PlaceReceipt))
|
|
|
|
|
dto.DataObj.PlaceReceipt = dto.DataObj.PlaceReceipt.Replace("(", "(").Replace(")", ")");
|
|
|
|
|
|
|
|
|
|
if (dto.DataObj.PlaceReceipt.IndexOf("(") >= 0)
|
|
|
|
|
{
|
|
|
|
|
string currStr = Regex.Match(dto.DataObj.PlaceReceipt, "(?<=\\().*(?=\\))").Value?.Trim();
|
|
|
|
|
|
|
|
|
|
portEnName = currStr.Split(',')[0]?.Trim();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(portEnName))
|
|
|
|
|
{
|
|
|
|
|
var allPortCodeList = await _sysCacheService.GetAllCommonCodeFromCache<CodePortRes>(SysCacheKeyEnum.CommonCodePort);
|
|
|
|
|
|
|
|
|
|
if (allPortCodeList.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
portCodeList = allPortCodeList.Data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//var cachePortLoad = await _cache.GetAllCodePortLoad();
|
|
|
|
|
var portInfo = await PlaceReceiptToPortload(portEnName, portCodeList, () => _sysCacheService.GetAllCommonCodeFromCache<MappingPortRes>(SysCacheKeyEnum.CommonCodePort));
|
|
|
|
|
|
|
|
|
|
if (!portInfo.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"通过收货地城市名称未匹配到港口信息,订舱编号:{dto.DataObj.SlotBookingNo}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
dto.DataObj.PortLoad = portInfo.Data.PortName;
|
|
|
|
|
dto.DataObj.PortLoadId = portInfo.Data.EdiCode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"收货地分割后得到的城市名称为空,订舱编号:{dto.DataObj.SlotBookingNo}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"收货地为空,订舱编号:{dto.DataObj.SlotBookingNo}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 解析交货地,得到为卸货港名称及五字码, 以及国家信息
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.DataObj.PlaceDelivery))
|
|
|
|
|
{
|
|
|
|
|
var portEnName = dto.DataObj.PlaceDelivery.Split(',')[0]?.Trim();
|
|
|
|
|
|
|
|
|
|
//这里CMA的收货地全称放在了括号里面
|
|
|
|
|
if (dto.DataObj.CarrierCode.Equals("CMA", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.DataObj.PlaceDelivery))
|
|
|
|
|
dto.DataObj.PlaceDelivery = dto.DataObj.PlaceDelivery.Replace("(", "(").Replace(")", ")");
|
|
|
|
|
|
|
|
|
|
if (dto.DataObj.PlaceDelivery.IndexOf("(") >= 0)
|
|
|
|
|
{
|
|
|
|
|
string currStr = Regex.Match(dto.DataObj.PlaceDelivery, "(?<=\\().*(?=\\))").Value?.Trim();
|
|
|
|
|
|
|
|
|
|
portEnName = currStr.Split(',')[0]?.Trim();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(portEnName))
|
|
|
|
|
{
|
|
|
|
|
if (portCodeList.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
var allPortCodeList = await _sysCacheService.GetAllCommonCodeFromCache<CodePortRes>(SysCacheKeyEnum.CommonCodePort);
|
|
|
|
|
|
|
|
|
|
if (allPortCodeList.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
portCodeList = allPortCodeList.Data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var portInfo = await PlaceDeliveryToPort(portEnName, portCodeList, () => _sysCacheService.GetAllCommonCodeFromCache<MappingPortRes>(SysCacheKeyEnum.CommonCodePort));
|
|
|
|
|
|
|
|
|
|
if (portInfo.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"通过交货地城市名称未匹配到港口信息,订舱编号:{dto.DataObj.SlotBookingNo}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var allCountryCodeList = await _sysCacheService.GetAllCommonCodeFromCache<CodeCountryRes>(SysCacheKeyEnum.CommonCodeCountry);
|
|
|
|
|
|
|
|
|
|
if(allCountryCodeList.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
var countryInfo = allCountryCodeList.Data.FirstOrDefault(p => p.Id == portInfo.Data.CountryId);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dto.DataObj.PortDischargeCountry = countryInfo?.CountryEnName;
|
|
|
|
|
dto.DataObj.PortDischargeCountryCode = countryInfo?.CountryCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dto.DataObj.PortDischarge = portInfo.Data.PortName;
|
|
|
|
|
dto.DataObj.PortDischargeId = portInfo.Data.EdiCode;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"交货地分割后得到的城市名称为空,订舱编号:{ dto.DataObj.SlotBookingNo}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"交货地为空,订舱编号:{dto.DataObj.SlotBookingNo}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(dto.DataObj.CtnStat))
|
|
|
|
|
{
|
|
|
|
|
if (dto.DataObj.CtnList != null && dto.DataObj.CtnList.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
dto.DataObj.CtnStat = string.Join(",", dto.DataObj.CtnList.GroupBy(a => a.CtnAll).Select(a =>
|
|
|
|
|
$"{a.Key}*{a.Select(b => b.CtnNum).Sum()}").ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//自动转换对应标签
|
|
|
|
|
|
|
|
|
|
BookingSlotBase model = null;
|
|
|
|
|
if (dto.OpType == "add")
|
|
|
|
|
{
|
|
|
|
|
var c = tenantDb.Queryable<BookingSlotBase>().Where(x => x.SlotBookingNo == dto.DataObj.SlotBookingNo).Count();
|
|
|
|
|
if (c > 0)
|
|
|
|
|
{
|
|
|
|
|
//订舱提单号已存在
|
|
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotSlotBookingNoExists)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model = dto.DataObj.Adapt<BookingSlotBase>();
|
|
|
|
|
await tenantDb.Insertable<BookingSlotBase>(model).ExecuteReturnEntityAsync();
|
|
|
|
|
|
|
|
|
|
id = model.Id;
|
|
|
|
|
|
|
|
|
|
foreach (var ctn in dto.DataObj.CtnList)
|
|
|
|
|
{
|
|
|
|
|
var newCtn = ctn.Adapt<BookingSlotCtn>();
|
|
|
|
|
newCtn.SlotId = model.Id;
|
|
|
|
|
await tenantDb.Insertable<BookingSlotCtn>(newCtn).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//await InsLog("Add", model.Id, "新增舱位");
|
|
|
|
|
|
|
|
|
|
string batchNo = GuidHelper.GetSnowflakeId();
|
|
|
|
|
|
|
|
|
|
//处理附件
|
|
|
|
|
if (file != null)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求文件名:{file.FileName}");
|
|
|
|
|
|
|
|
|
|
var fileRlt = await _sysFileService.SaveFileDirect(model.Id.ToString(), file.FileBytes, batchNo, file.FileName, "bcfiles");
|
|
|
|
|
|
|
|
|
|
var fileFullPath = fileRlt.Data;
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"保存文件路径:{fileFullPath}");
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(fileFullPath))
|
|
|
|
|
{
|
|
|
|
|
//将格式单附件写入订舱的附件
|
|
|
|
|
SaveEDIFile(id, fileFullPath, file.FileName, long.Parse(user.TenantId),
|
|
|
|
|
CONST_BC_FILE_CODE, CONST_BC_FILE_NAME).GetAwaiter();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (modifyFile != null)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求文件名(变更文件):{modifyFile.FileName}");
|
|
|
|
|
|
|
|
|
|
var fileRlt = await _sysFileService.SaveFileDirect(model.Id.ToString(), modifyFile.FileBytes, batchNo, modifyFile.FileName, "bcnoticefiles");
|
|
|
|
|
|
|
|
|
|
var fileFullPath = fileRlt.Data;
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"保存文件路径(变更文件):{fileFullPath}");
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(fileFullPath))
|
|
|
|
|
{
|
|
|
|
|
//将格式单附件写入订舱的附件
|
|
|
|
|
SaveEDIFile(id, fileFullPath, modifyFile.FileName, long.Parse(user.TenantId),
|
|
|
|
|
CONST_BC_NOTICE_FILE_CODE, CONST_BC_NOTICE_FILE_NAME).GetAwaiter();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//触发标签自动绑定
|
|
|
|
|
await GenerateSlotLabel(dto, id);
|
|
|
|
|
}
|
|
|
|
|
else if (dto.OpType == "update")
|
|
|
|
|
{
|
|
|
|
|
model = await tenantDb.Queryable<BookingSlotBase>().FirstAsync(x => x.SlotBookingNo == dto.DataObj.SlotBookingNo);
|
|
|
|
|
if (model == null)
|
|
|
|
|
{
|
|
|
|
|
//throw Oops.Bah($"未找到订舱编号为 {dto.DataObj.SlotBookingNo} 的数据");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
id = model.Id;
|
|
|
|
|
|
|
|
|
|
//生成待比对详情
|
|
|
|
|
ParserBCInfoDto bcSrcDto = new ParserBCInfoDto();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
bcSrcDto = model.Adapt<ParserBCInfoDto>();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"slotId={model.Id} 映射数据库对象请求对应异常,原因:{ex.Message}");
|
|
|
|
|
|
|
|
|
|
//throw Oops.Bah($"slotId={model.Id} 映射数据库对象请求对应异常,原因:{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ParserBCInfoDto bcTargetDto = new ParserBCInfoDto();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
bcTargetDto = dto.DataObj.Adapt<ParserBCInfoDto>();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"slotId={model.Id} 映射推送的舱位请求对应异常,原因:{ex.Message}");
|
|
|
|
|
|
|
|
|
|
//throw Oops.Bah($"slotId={model.Id} 映射推送的舱位请求对应异常,原因:{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"slotId={model.Id} 开始处理重要提醒");
|
|
|
|
|
//执行差异重要提醒
|
|
|
|
|
//await MeasureDiffCautionTask(bcSrcDto, bcTargetDto, model.Id);
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"slotId={model.Id} 处理重要提醒结束");
|
|
|
|
|
|
|
|
|
|
//提取箱信息
|
|
|
|
|
var ctnList = tenantDb.Queryable<BookingSlotCtn>()
|
|
|
|
|
.Where(x => x.SlotId == model.Id).ToList();
|
|
|
|
|
|
|
|
|
|
if (ctnList != null)
|
|
|
|
|
{
|
|
|
|
|
bcSrcDto.CtnList = ctnList.GroupBy(x => x.CtnAll)
|
|
|
|
|
.Select(x =>
|
|
|
|
|
{
|
|
|
|
|
return new ParserBCCTNInfoDto
|
|
|
|
|
{
|
|
|
|
|
CtnALL = x.Key,
|
|
|
|
|
CtnNum = x.ToList()
|
|
|
|
|
.Sum(a => a.CtnNum)
|
|
|
|
|
};
|
|
|
|
|
}).ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dto.DataObj.CtnList != null && dto.DataObj.CtnList.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
bcTargetDto.CtnList = dto.DataObj.CtnList.GroupBy(x => x.CtnAll)
|
|
|
|
|
.Select(x =>
|
|
|
|
|
{
|
|
|
|
|
return new ParserBCCTNInfoDto
|
|
|
|
|
{
|
|
|
|
|
CtnALL = x.Key,
|
|
|
|
|
CtnNum = x.ToList()
|
|
|
|
|
.Sum(a => a.CtnNum)
|
|
|
|
|
};
|
|
|
|
|
}).ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var oldObj = model.Adapt<BookingSlotBaseApiSaveDto>();
|
|
|
|
|
|
|
|
|
|
dto.DataObj.Adapt(model);
|
|
|
|
|
|
|
|
|
|
// 1.判断新的舱位信息的7个库存统计维度是否发生变化
|
|
|
|
|
// 2.如果有变化,则需要更新旧的库存信息
|
|
|
|
|
bool isNeedUpdateOldStock = false;
|
|
|
|
|
if (oldObj.Vessel != model.Vessel
|
|
|
|
|
|| oldObj.Voyno != model.Voyno
|
|
|
|
|
|| oldObj.BookingSlotType != model.BookingSlotType
|
|
|
|
|
|| oldObj.CarrierId != model.CarrierId
|
|
|
|
|
|| oldObj.PortLoadId != model.PortLoadId
|
|
|
|
|
|| oldObj.PortDischargeId != model.PortDischargeId)
|
|
|
|
|
{
|
|
|
|
|
isNeedUpdateOldStock = true;
|
|
|
|
|
}
|
|
|
|
|
await tenantDb.Updateable<BookingSlotBase>(model).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
if (isNeedUpdateOldStock)
|
|
|
|
|
{
|
|
|
|
|
//BookingSlotStock:Update
|
|
|
|
|
await _bookingSlotStockService.BookingSlotStock(new BookingSlotStockUpdateModel
|
|
|
|
|
{
|
|
|
|
|
BookingSlotType = oldObj.BookingSlotType,
|
|
|
|
|
CarrierCode = oldObj.CarrierCode,
|
|
|
|
|
ContractNo = oldObj.ContractNo,
|
|
|
|
|
Vessel = oldObj.Vessel,
|
|
|
|
|
Voyno = oldObj.Voyno,
|
|
|
|
|
PortLoadId = oldObj.PortLoadId,
|
|
|
|
|
PortDischargeId = oldObj.PortDischargeId,
|
|
|
|
|
TenantId = long.Parse(user.TenantId)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var currCtnList = await tenantDb.Queryable<BookingSlotCtn>().Where(p => p.SlotId == model.Id).ToListAsync();
|
|
|
|
|
|
|
|
|
|
if (currCtnList.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
currCtnList.ForEach(async p =>
|
|
|
|
|
{
|
|
|
|
|
await tenantDb.Deleteable<BookingSlotCtn>(p).ExecuteCommandAsync();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var ctn in dto.DataObj.CtnList)
|
|
|
|
|
{
|
|
|
|
|
var newCtn = ctn.Adapt<BookingSlotCtn>();
|
|
|
|
|
newCtn.SlotId = model.Id;
|
|
|
|
|
await tenantDb.Insertable<BookingSlotCtn>(newCtn).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//await InsLog("Update", model.Id, typeof(BookingSlotBaseApiSaveDto), oldObj, dto.DataObj, nameof(BookingSlotBaseApiSaveDto.CtnList), nameof(BookingSlotBaseApiSaveDto.BookingSlotSaleInfoList));
|
|
|
|
|
|
|
|
|
|
string batchNo = GuidHelper.GetSnowflakeId();
|
|
|
|
|
|
|
|
|
|
//处理附件
|
|
|
|
|
if (file != null)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求文件名:{file.FileName}");
|
|
|
|
|
|
|
|
|
|
var fileRlt = await _sysFileService.SaveFileDirect(model.Id.ToString(), file.FileBytes, batchNo, file.FileName, "bcmoidfyfiles");
|
|
|
|
|
|
|
|
|
|
var fileFullPath = fileRlt.Data;
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"保存文件路径:{fileFullPath}");
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(fileFullPath))
|
|
|
|
|
{
|
|
|
|
|
//将格式单附件写入订舱的附件
|
|
|
|
|
SaveEDIFile(id, fileFullPath, file.FileName, long.Parse(user.TenantId),
|
|
|
|
|
CONST_BC_MODIFY_FILE_CODE, CONST_BC_MODIFY_FILE_NAME).GetAwaiter();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (modifyFile != null)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求文件名(变更文件):{modifyFile.FileName}");
|
|
|
|
|
|
|
|
|
|
var fileRlt = await _sysFileService.SaveFileDirect(model.Id.ToString(), modifyFile.FileBytes, batchNo, modifyFile.FileName, "bcmodifynoticefiles");
|
|
|
|
|
|
|
|
|
|
var fileFullPath = fileRlt.Data;
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"保存文件路径(变更文件):{fileFullPath}");
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(fileFullPath))
|
|
|
|
|
{
|
|
|
|
|
//将格式单附件写入订舱的附件
|
|
|
|
|
SaveEDIFile(id, fileFullPath, modifyFile.FileName, long.Parse(user.TenantId),
|
|
|
|
|
CONST_BC_MODIFY_NOTICE_FILE_CODE, CONST_BC_MODIFY_NOTICE_FILE_NAME).GetAwaiter();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//一般更新数据指的是Booking Amendment,需要与舱位进行数据比对
|
|
|
|
|
await PushCompareBCInfo(bcSrcDto, bcTargetDto, id, dto.BatchNo);
|
|
|
|
|
|
|
|
|
|
//触发标签自动绑定
|
|
|
|
|
await GenerateSlotLabel(dto, id);
|
|
|
|
|
}
|
|
|
|
|
else if (dto.OpType == "del")
|
|
|
|
|
{
|
|
|
|
|
var slotNO = dto.DataObj.SlotBookingNo;
|
|
|
|
|
model = await tenantDb.Queryable<BookingSlotBase>().FirstAsync(x => x.SlotBookingNo == slotNO);
|
|
|
|
|
if (model == null)
|
|
|
|
|
{
|
|
|
|
|
//throw Oops.Bah($"未找到订舱编号为 {slotNO} 的数据");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
id = model.Id;
|
|
|
|
|
|
|
|
|
|
model.Deleted = true;
|
|
|
|
|
await tenantDb.Updateable<BookingSlotBase>(model).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
var ctns = await tenantDb.Queryable<BookingSlotCtn>().Where(x => x.SlotId == model.Id).ToListAsync();
|
|
|
|
|
foreach (var ctn in ctns)
|
|
|
|
|
{
|
|
|
|
|
ctn.Deleted = true;
|
|
|
|
|
await tenantDb.Updateable<BookingSlotCtn>(ctn).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//await InsLog("Del", model.Id, "取消舱位");
|
|
|
|
|
}
|
|
|
|
|
else if (dto.OpType == "cancellation")
|
|
|
|
|
{
|
|
|
|
|
// 更新标志
|
|
|
|
|
var slotNO = dto.DataObj.SlotBookingNo;
|
|
|
|
|
model = await tenantDb.Queryable<BookingSlotBase>().FirstAsync(x => x.SlotBookingNo == slotNO);
|
|
|
|
|
if (model == null)
|
|
|
|
|
{
|
|
|
|
|
//throw Oops.Bah($"未找到订舱编号为 {slotNO} 的数据");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
id = model.Id;
|
|
|
|
|
model.IsCancellation = true;
|
|
|
|
|
model.CancellationDate = DateTime.Now;
|
|
|
|
|
await tenantDb.Updateable<BookingSlotBase>(model).EnableDiffLogEvent().ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
// 删除该舱位相关的订舱关联关系
|
|
|
|
|
var slotList = await tenantDb.Queryable<BookingSlotAllocation>().Where(a => a.BookingSlotId == id).ToListAsync();
|
|
|
|
|
var slotIdList = slotList.Select(s => s.Id);
|
|
|
|
|
|
|
|
|
|
await tenantDb.Updateable<BookingSlotAllocation>()
|
|
|
|
|
.SetColumns(a => a.Deleted == true)
|
|
|
|
|
.SetColumns(a => a.UpdateTime == DateTime.Now)
|
|
|
|
|
.SetColumns(a => a.UpdateBy == long.Parse(user.UserId))
|
|
|
|
|
//.SetColumns(a => a.UpdatedUserName == UserManager.Name)
|
|
|
|
|
.Where(a => slotIdList.Contains(a.Id))
|
|
|
|
|
.ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
await tenantDb.Updateable<BookingSlotAllocationCtn>()
|
|
|
|
|
.SetColumns(a => a.Deleted == true)
|
|
|
|
|
.SetColumns(a => a.UpdateTime == DateTime.Now)
|
|
|
|
|
.SetColumns(a => a.UpdateBy == long.Parse(user.UserId))
|
|
|
|
|
//.SetColumns(a => a.UpdatedUserName == UserManager.Name)
|
|
|
|
|
.Where(a => slotIdList.Contains(a.SlotAllocId))
|
|
|
|
|
.ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
//await InsLog("Cancellation", model.Id, "取消舱位");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//更新库存
|
|
|
|
|
await _bookingSlotStockService.BookingSlotStock(new BookingSlotStockUpdateModel
|
|
|
|
|
{
|
|
|
|
|
BookingSlotType = model.BookingSlotType,
|
|
|
|
|
CarrierCode = model.CarrierCode,
|
|
|
|
|
ContractNo = model.ContractNo,
|
|
|
|
|
Vessel = model.Vessel,
|
|
|
|
|
Voyno = model.Voyno,
|
|
|
|
|
PortLoadId = model.PortLoadId,
|
|
|
|
|
PortDischargeId = model.PortDischargeId,
|
|
|
|
|
TenantId = long.Parse(user.TenantId)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//throw Oops.Bah("操作类型参数有误");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(id == 0)
|
|
|
|
|
return DataResult<long>.FailedData(id);
|
|
|
|
|
|
|
|
|
|
return DataResult<long>.Success(id);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region 异步写入附件表
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 异步写入附件表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="boookId">订舱ID</param>
|
|
|
|
|
/// <param name="FilePath">文件路径</param>
|
|
|
|
|
/// <param name="fileName">文件名</param>
|
|
|
|
|
/// <param name="tenantId">租户ID</param>
|
|
|
|
|
/// <param name="fileTypeCode">附件类型代码</param>
|
|
|
|
|
/// <param name="fileTypeName">附件类型名称</param>
|
|
|
|
|
/// <param name="moudle">附件模块代码</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[NonAction]
|
|
|
|
|
private async Task SaveEDIFile(long boookId, string FilePath, string fileName, long tenantId,
|
|
|
|
|
string fileTypeCode = "bc", string fileTypeName = "Booking Confirmation", string moudle = "BookingSlot")
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
直接将附件信息写入附件表
|
|
|
|
|
*/
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
|
|
|
|
var newFile = new OpFile
|
|
|
|
|
{
|
|
|
|
|
Id = SnowFlakeSingle.Instance.NextId(),
|
|
|
|
|
FileName = fileName,
|
|
|
|
|
FilePath = FilePath,
|
|
|
|
|
TypeCode = fileTypeCode,
|
|
|
|
|
TypeName = fileTypeName,
|
|
|
|
|
LinkId = boookId,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await tenantDb.Insertable(newFile).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 根据收货地港口英文名解析出起始港对象
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据收货地港口英文名解析出起始港对象
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="portEnName">收货地港口英文名</param>
|
|
|
|
|
/// <param name="cachePortLoad">起始港缓存</param>
|
|
|
|
|
/// <param name="cacheMapPortLoadFunc">起始港缓存映射</param>
|
|
|
|
|
/// <returns>起始港对象</returns>
|
|
|
|
|
private async Task<DataResult<CodePortRes>> PlaceReceiptToPortload(string portEnName, List<CodePortRes> cachePortLoad, Func<Task<DataResult<List<MappingPortRes>>>> cacheMapPortLoadFunc)
|
|
|
|
|
{
|
|
|
|
|
CodePortRes portInfo = null;
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(portEnName))
|
|
|
|
|
{
|
|
|
|
|
return DataResult<CodePortRes>.FailedData(portInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 匹配方式1:精准匹配
|
|
|
|
|
portInfo = cachePortLoad.FirstOrDefault(x => x.PortName.Equals(portEnName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
if (portInfo != null) return DataResult<CodePortRes>.Success(portInfo);
|
|
|
|
|
|
|
|
|
|
// 匹配方式2:起始模糊匹配
|
|
|
|
|
portInfo = cachePortLoad.FirstOrDefault(x => x.PortName.StartsWith(portEnName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
if (portInfo != null) return DataResult<CodePortRes>.Success(portInfo);
|
|
|
|
|
|
|
|
|
|
// 匹配方式3:完整模糊匹配
|
|
|
|
|
portInfo = cachePortLoad.FirstOrDefault(x => x.PortName.Contains(portEnName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
if (portInfo != null) return DataResult<CodePortRes>.Success(portInfo);
|
|
|
|
|
|
|
|
|
|
// 匹配方式4:精准映射匹配
|
|
|
|
|
var mapCachePortLoad = await cacheMapPortLoadFunc();
|
|
|
|
|
var map = mapCachePortLoad.Data.FirstOrDefault(x => x.Module == RECEIPT_TO_PORTLOAD
|
|
|
|
|
&& x.MapName.Equals(portEnName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
|
|
|
|
|
if (map != null)
|
|
|
|
|
{
|
|
|
|
|
portInfo = cachePortLoad.FirstOrDefault(x => x.Id == map.LinkId);
|
|
|
|
|
|
|
|
|
|
if (portInfo != null) return DataResult<CodePortRes>.Success(portInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DataResult<CodePortRes>.FailedData(portInfo);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 根据交货地港口英文名解析出目的港对象
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据交货地港口英文名解析出目的港对象
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="portEnName">交货地港口英文名</param>
|
|
|
|
|
/// <param name="cachePort">目的港缓存</param>
|
|
|
|
|
/// <param name="cacheMapPortFunc">目的港缓存映射</param>
|
|
|
|
|
/// <returns>目的港对象</returns>
|
|
|
|
|
private async Task<DataResult<CodePortRes>> PlaceDeliveryToPort(string portEnName, List<CodePortRes> cachePort, Func<Task<DataResult<List<MappingPortRes>>>> cacheMapPortFunc)
|
|
|
|
|
{
|
|
|
|
|
CodePortRes portInfo = null;
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(portEnName))
|
|
|
|
|
{
|
|
|
|
|
return DataResult<CodePortRes>.FailedData(portInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 匹配方式1:精准匹配
|
|
|
|
|
portInfo = cachePort.FirstOrDefault(x => x.PortName.Equals(portEnName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
if (portInfo != null) return DataResult<CodePortRes>.Success(portInfo);
|
|
|
|
|
|
|
|
|
|
// 匹配方式2:起始模糊匹配
|
|
|
|
|
portInfo = cachePort.FirstOrDefault(x => x.PortName.StartsWith(portEnName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
if (portInfo != null) return DataResult<CodePortRes>.Success(portInfo);
|
|
|
|
|
|
|
|
|
|
// 匹配方式3:完整模糊匹配
|
|
|
|
|
portInfo = cachePort.FirstOrDefault(x => x.PortName.Contains(portEnName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
if (portInfo != null) return DataResult<CodePortRes>.Success(portInfo);
|
|
|
|
|
|
|
|
|
|
// 匹配方式4:精准映射匹配
|
|
|
|
|
var mapCachePort = await cacheMapPortFunc();
|
|
|
|
|
var map = mapCachePort.Data.FirstOrDefault(x => x.Module == DELIVERY_TO_PORT
|
|
|
|
|
&& x.MapName.Equals(portEnName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
|
|
|
|
|
if (map != null)
|
|
|
|
|
{
|
|
|
|
|
portInfo = cachePort.FirstOrDefault(x => x.Id == map.LinkId);
|
|
|
|
|
|
|
|
|
|
if (portInfo != null) return DataResult<CodePortRes>.Success(portInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DataResult<CodePortRes>.FailedData(portInfo);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 推送BC变更比对
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 推送BC变更比对
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="bcSrcDto">原舱位详情</param>
|
|
|
|
|
/// <param name="bcTargetDto">变更后舱位详情</param>
|
|
|
|
|
/// <param name="slotId">舱位主键</param>
|
|
|
|
|
/// <param name="reqBatchNo">请求批次号用来区分对应的哪个批次任务</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[NonAction]
|
|
|
|
|
public async Task PushCompareBCInfo(ParserBCInfoDto bcSrcDto, ParserBCInfoDto bcTargetDto, long slotId, string reqBatchNo)
|
|
|
|
|
{
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
|
|
|
|
string batchNo = GuidHelper.GetSnowflakeId();
|
|
|
|
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} slotId={slotId} 开始请求比对结果");
|
|
|
|
|
|
|
|
|
|
var compareResult = await ExcuteCompare(bcSrcDto, bcTargetDto);
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} slotId={slotId} 请求比对结果完成,结果={JsonConvert.SerializeObject(compareResult)}");
|
|
|
|
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
|
|
|
|
if (compareResult != null)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, "批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg}", batchNo, timeDiff, compareResult.succ ? "成功" : "失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (compareResult != null)
|
|
|
|
|
{
|
|
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
var hisInfo = tenantDb.Queryable<BookingSlotCompare>().First(a => a.CompareBatchNo == reqBatchNo);
|
|
|
|
|
|
|
|
|
|
if (hisInfo == null)
|
|
|
|
|
{
|
|
|
|
|
BookingSlotCompare entity = new BookingSlotCompare
|
|
|
|
|
{
|
|
|
|
|
SlotId = slotId,
|
|
|
|
|
CompareBatchNo = reqBatchNo,
|
|
|
|
|
CompareDiffNum = compareResult.extra.IsExistsDiff ? compareResult.extra.ShowDetailList.Count : 0,
|
|
|
|
|
CreateTime = nowDate,
|
|
|
|
|
UpdateTime = nowDate,
|
|
|
|
|
CreateBy = long.Parse(user.UserId),
|
|
|
|
|
//CreatedUserName = UserManager.Name,
|
|
|
|
|
UpdateBy = long.Parse(user.UserId),
|
|
|
|
|
//UpdatedUserName = UserManager.Name,
|
|
|
|
|
CompareType = "BC_MODIFY",
|
|
|
|
|
CompareRlt = JsonConvert.SerializeObject(compareResult.extra.ShowDetailList),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await tenantDb.Insertable<BookingSlotCompare>(entity).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
hisInfo.CompareDiffNum = compareResult.extra.IsExistsDiff ? compareResult.extra.ShowDetailList.Count : 0;
|
|
|
|
|
hisInfo.UpdateTime = nowDate;
|
|
|
|
|
hisInfo.UpdateBy = long.Parse(user.UserId);
|
|
|
|
|
//hisInfo.UpdatedUserName = user.UserName;
|
|
|
|
|
|
|
|
|
|
hisInfo.CompareRlt = JsonConvert.SerializeObject(compareResult.extra.ShowDetailList);
|
|
|
|
|
|
|
|
|
|
await tenantDb.Updateable<BookingSlotCompare>(hisInfo).UpdateColumns(it =>
|
|
|
|
|
new
|
|
|
|
|
{
|
|
|
|
|
it.CompareDiffNum,
|
|
|
|
|
it.CompareRlt,
|
|
|
|
|
it.UpdateTime,
|
|
|
|
|
it.UpdateBy,
|
|
|
|
|
//it.UpdatedUserName
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
//throw Oops.Oh($"舱位主键{slotId}请求BC比对失败,返回为空");
|
|
|
|
|
|
|
|
|
|
//if (compareResult.extra.ShowDetailList == null || compareResult.extra.ShowDetailList.Count == 0)
|
|
|
|
|
//{
|
|
|
|
|
// new EmailNoticeHelper().SendEmailNotice($"MBLNO={bcSrcDto.MBLNo} 与舱位比对差异失败,比对结果为0", $"MBLNO={bcSrcDto.MBLNo} 与舱位比对差异失败,比对结果为0", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList());
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//new EmailNoticeHelper().SendEmailNotice($"MBLNO={bcSrcDto.MBLNo} 与舱位比对差异失败,未获取到比对结果", $"MBLNO={bcSrcDto.MBLNo} 与舱位比对差异失败,未获取到比对结果", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 请求BC比对
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 请求BC比对
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="bcSrcDto">BC详情</param>
|
|
|
|
|
/// <param name="bcTargetDto">BC变更后详情</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
[NonAction]
|
|
|
|
|
public async Task<TaskManageExcuteResultDto> ExcuteCompare(ParserBCInfoDto bcSrcDto, ParserBCInfoDto bcTargetDto)
|
|
|
|
|
{
|
|
|
|
|
TaskManageExcuteResultDto model = null;
|
|
|
|
|
/*
|
|
|
|
|
1、读取配置文件中的规则引擎URL
|
|
|
|
|
2、填充请求的类,并生成JSON报文
|
|
|
|
|
3、POST请求接口,并记录回执。
|
|
|
|
|
4、返回信息。
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
var url = bcCompareUrl; //App.Configuration["BCCompareUrl"];
|
|
|
|
|
|
|
|
|
|
using (var httpClient = new HttpClient())
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (var reduceAttach = new MultipartFormDataContent())
|
|
|
|
|
{
|
|
|
|
|
var dataContent = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(bcSrcDto)));
|
|
|
|
|
|
|
|
|
|
dataContent.Headers.ContentDisposition = new ContentDispositionHeaderValue($"form-data")
|
|
|
|
|
{
|
|
|
|
|
Name = "srcJson"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
reduceAttach.Add(dataContent);
|
|
|
|
|
|
|
|
|
|
var dataContent2 = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(bcTargetDto)));
|
|
|
|
|
|
|
|
|
|
dataContent2.Headers.ContentDisposition = new ContentDispositionHeaderValue($"form-data")
|
|
|
|
|
{
|
|
|
|
|
Name = "destJson"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
reduceAttach.Add(dataContent2);
|
|
|
|
|
|
|
|
|
|
//请求
|
|
|
|
|
var response = httpClient.PostAsync(url, reduceAttach).Result;
|
|
|
|
|
|
|
|
|
|
var result = response.Content.ReadAsStringAsync().Result;
|
|
|
|
|
|
|
|
|
|
model = JsonConvert.DeserializeObject<TaskManageExcuteResultDto>(result);
|
|
|
|
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"推送BC比返回结果:{JsonConvert.SerializeObject(model)}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log(NLog.LogLevel.Error, "推送BC比对异常,原因:{error}", ex.Message);
|
|
|
|
|
|
|
|
|
|
// throw Oops.Oh($"推送BC比对异常,原因:{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return model;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|