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.

1118 lines
48 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 DS.Module.Core;
using DS.Module.Core.Attributes;
using DS.Module.Core.Helpers;
using DS.Module.DjyServiceStatus;
using DS.Module.SqlSugar;
using DS.Module.UserModule;
using DS.WMS.Core.Op.Dtos;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.TaskPlat.Dtos;
using DS.WMS.Core.TaskPlat.Entity;
using DS.WMS.Core.TaskPlat.Interface;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using NLog;
using NPOI.SS.Formula.Functions;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Mapster;
using System.Net.Http.Headers;
using DS.Module.Core.Extensions;
using Microsoft.Extensions.DependencyInjection;
using DS.WMS.Core.Sys.Interface;
using DS.WMS.Core.Sys.Method;
using NPOI.HPSF;
using DS.WMS.Core.Code.Interface;
using DS.WMS.Core.Map.Interface;
namespace DS.WMS.Core.TaskPlat.Method
{
public class TaskDraftCompareService : ITaskDraftCompareService
{
private readonly IServiceProvider _serviceProvider;
private readonly ISqlSugarClient db;
private readonly IUser user;
private readonly ISaasDbService saasService;
private readonly IDjyServiceStatusService _djyServiceStatusService;
private readonly ISysFileService _sysFileService;
private readonly IMappingYardService _mappingYardService;
private readonly IMappingCarrierService _mappingCarrierService;
private readonly ICodePortService _codePortService;
private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger();
private readonly string draftReadUrl;
private readonly string draftCompareUrl;
private readonly string draftResultUrl;
const string CONST_DRAFT_FILE_CODE = "draft";
const string CONST_DRAFT_FILE_NAME = "格式单";
const string CONST_MAPPING_YARD_MODULE = "BillTrace";
const string CONST_MAPPING_CARRIER_MODULE = "CarrierBaseMapping";
public TaskDraftCompareService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
db = _serviceProvider.GetRequiredService<ISqlSugarClient>();
user = _serviceProvider.GetRequiredService<IUser>();
saasService = _serviceProvider.GetRequiredService<ISaasDbService>();
_djyServiceStatusService = _serviceProvider.GetRequiredService<IDjyServiceStatusService>();
_sysFileService = _serviceProvider.GetRequiredService<ISysFileService>();
_mappingYardService = _serviceProvider.GetRequiredService<IMappingYardService>();
_mappingCarrierService = _serviceProvider.GetRequiredService<IMappingCarrierService>();
_codePortService = _serviceProvider.GetRequiredService<ICodePortService>();
draftReadUrl = AppSetting.app(new string[] { "DraftCompare", "ReadUrl" });
draftCompareUrl = AppSetting.app(new string[] { "DraftCompare", "Url" });
draftResultUrl = AppSetting.app(new string[] { "DraftCompare", "ResultUrl" });
}
#region 执行邮件Draft比对
/// <summary>
/// 执行邮件Draft比对
/// </summary>
/// <param name="file">请求文件</param>
/// <param name="jsonData">邮件Draft比对请求报文</param>
/// <returns>返回回执</returns>
public async Task<TaskManageExcuteResultDto> ExcuteEmailDraftCompareAsync(IFormFile file, [FromForm] string jsonData)
{
string batchNo = GuidHelper.GetSnowflakeId();
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
TaskManageExcuteResultDto result = new TaskManageExcuteResultDto();
DateTime nowDate = DateTime.Now;
/*
1、接收报文里的文件信息优先写入本地文件暂存。
2、请求解析Draft文件解析并等待解析结果。
3、判断对应的订舱提单号。如果没有对应的订舱提单号则写入任务表失败记录。
4、写入任务表。
5、异步请求格式单比对接口。
6、接收比对结果更新任务表。
7、更新订舱表并更新状态。
*/
try
{
var model = GetJsonMessageInfo(jsonData, batchNo);
TaskDraftCompareMessageInfo readFileMessageInfo = new TaskDraftCompareMessageInfo
{
Head = new TaskMessageHead
{
GID = batchNo,
MessageType = "DRAFT_COMPARE",
SenderId = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSender" }),
SenderName = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSenderName" }),
ReceiverId = "RulesEngine",
ReceiverName = "大简云规则引擎",
Version = "1.0",
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
RequestAction = "Compare",
}
};
var fileRlt = await _sysFileService.SaveFileDirect(model.Head.GID, file.ToByteArray(), batchNo, file.FileName, "bcfiles");
var fileFullName = fileRlt.Data.Item1;
//附件暂存
//var fileFullName = "";//await FileAttachHelper.TempSaveWebFile(model.Head.GID, file, batchNo, CONST_DRAFT_FILE_CODE);
//Draft文件解析
NameValueCollection par = new NameValueCollection();
par.Add("jsonMessage", JsonConvert.SerializeObject(readFileMessageInfo));
byte[] bytes = file.ToByteArray();
DateTime bDate = DateTime.Now;
var readResult = await ExcuteReadPDF(par, new
{
file = "file",
fileName = file.FileName,
fileBytes = bytes
}, null);
DateTime eDate = DateTime.Now;
TimeSpan ts = eDate.Subtract(bDate);
var timeDiff = ts.TotalMilliseconds;
Logger.Log(NLog.LogLevel.Info, string.Format("批次={0} 请求Draft文件解析完成,耗时:{1}ms. 结果{2} 报文={3}", batchNo, timeDiff,
readResult.succ ? "成功" : "失败",
JsonConvert.SerializeObject(readResult)));
if (!readResult.succ)
{
Logger.Log(NLog.LogLevel.Info, "批次={no} 请求Draft文件解析失败 原因={reason}", batchNo, readResult.msg);
throw new Exception($"请求Draft文件解析失败 原因={readResult.msg}");
}
//通过解析提单号匹配订舱的详情
var readModel = JsonConvert.DeserializeObject<CompareDraftDataInfo>(JsonConvert.SerializeObject(readResult.extra));
string billNo = string.Empty;
if (!string.IsNullOrWhiteSpace(readModel.MasterBlNo))
{
billNo = readModel.MasterBlNo;
}
if (string.IsNullOrWhiteSpace(billNo))
{
Logger.Log(NLog.LogLevel.Info, "批次={no} 请求Draft文件解析未获取到有效提单号", batchNo);
throw new Exception($"请求Draft文件解析未获取到有效提单号");
}
var bookingOrder = tenantDb.Queryable<SeaExport>().First(a => a.MBLNO.Equals(billNo));
if (bookingOrder == null)
{
Logger.Log(NLog.LogLevel.Info, "批次={no} 提单号{billNo}无法获取业务信息", batchNo, billNo);
throw new Exception($"提单号{billNo}无法获取业务信息");
}
Logger.Log(NLog.LogLevel.Info, "批次={no}获取订舱数据完成", batchNo);
TaskDraftCompareMessageInfo msgModel = new TaskDraftCompareMessageInfo
{
Head = new TaskMessageHead
{
GID = batchNo,
MessageType = "DRAFT_COMPARE",
SenderId = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSender" }),
SenderName = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSenderName" }),
ReceiverId = "RulesEngine",
ReceiverName = "大简云规则引擎",
Version = "1.0",
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
RequestAction = "Compare",
},
Main = new TaskDraftMessageMainInfo()
};
//请求格式单比对接口
var mainInfo = bookingOrder.Adapt<BusinessInfo>();
//这里需要对场站进行映射翻译
var mapYardList = _mappingYardService.GetAllList().GetAwaiter().GetResult().Data;
if (mapYardList.Count > 0)
mapYardList = mapYardList.Where(a => a.Module.Equals(CONST_MAPPING_YARD_MODULE, StringComparison.OrdinalIgnoreCase)).ToList();
if (mapYardList.Any(a => a.LinkId == bookingOrder.YardId))
{
mainInfo.YardCode = mapYardList.FirstOrDefault(a => a.LinkId == bookingOrder.YardId).MapCode;
}
var codePortList = _codePortService.GetAllList().GetAwaiter().GetResult().Data;
if (codePortList.Any(a => a.Id == bookingOrder.LoadPortId))
mainInfo.PortLoadId = codePortList.FirstOrDefault(a => a.Id == bookingOrder.LoadPortId).EdiCode;
if (codePortList.Any(a => a.Id == bookingOrder.DischargePortId))
mainInfo.PortDischargeId = codePortList.FirstOrDefault(a => a.Id == bookingOrder.DischargePortId).EdiCode;
if (codePortList.Any(a => a.Id == bookingOrder.DeliveryPlaceId))
mainInfo.PlaceDeliveryId = codePortList.FirstOrDefault(a => a.Id == bookingOrder.DeliveryPlaceId).EdiCode;
if (codePortList.Any(a => a.Id == bookingOrder.DestinationId))
mainInfo.DestinationId = codePortList.FirstOrDefault(a => a.Id == bookingOrder.DestinationId).EdiCode;
//var mapCarrierList = _mappingCarrierService.GetAllList().GetAwaiter().GetResult().Data;
//if (mapCarrierList.Count > 0)
// mapCarrierList = mapCarrierList.Where(a => a.Module.Equals(CONST_MAPPING_CARRIER_MODULE, StringComparison.OrdinalIgnoreCase)).ToList();
//if (mapYardList.Any(a => a.LinkId == bookingOrder.CarrierId))
//{
// mainInfo.CarrierCode = mapYardList.FirstOrDefault(a => a.LinkId == model.CarrierId).MapCode;
//}
//var userInfo = _sysUserRepository.AsQueryable().First(a => a.Id == bookingOrder.CreatedUserId);
mainInfo.BusiPKId = bookingOrder.Id.ToString();
mainInfo.UserId = user.UserId;
mainInfo.UserName = user.UserName;
//mainInfo.UserEmail = UserManager.Email;
var contaList = tenantDb.Queryable<OpCtn>()
.Where(x => long.Parse(x.BSNO) == bookingOrder.Id).ToList();
Logger.Log(NLog.LogLevel.Info, "批次={no} 提取箱完成 数量={total}", batchNo, contaList.Count);
if (contaList.Count > 0)
{
mainInfo.ContaList = contaList.Adapt<List<TaskDraftMessageCtnInfo>>();
}
msgModel.Main.BusinessInfo = mainInfo;
msgModel.Main.DraftInfo = readModel;
//推送Draft比对
DateTime bCompareDate = DateTime.Now;
var compareResult = await ExcuteDraftCompare(msgModel);
DateTime eCompareDate = DateTime.Now;
TimeSpan tsCompare = bCompareDate.Subtract(eCompareDate);
var timeDiffCompare = tsCompare.TotalMilliseconds;
Logger.Log(NLog.LogLevel.Info, string.Format("批次={0} 请求Draft比对完成,耗时:{1}ms. 结果{2} 报文={3}", batchNo, timeDiffCompare,
compareResult.succ ? "成功" : "失败",
JsonConvert.SerializeObject(compareResult)));
Logger.Log(NLog.LogLevel.Info, "批次={no} 对应请求报文完成 msg={msg}", batchNo, JsonConvert.SerializeObject(msgModel));
var entity = tenantDb.Queryable<SeaExport>()
.First(a => a.Id == bookingOrder.Id);
var oldEntity = entity.Adapt<SeaExport>();
entity.LstDraftCompareRlt = compareResult.extra2.Any(a => a.IsDiff) ? "DIFF" : "NO DIFF";
entity.LstDraftCompareDate = nowDate;
//更新订舱相关
await tenantDb.Updateable(entity).UpdateColumns(it => new
{
it.LstDraftCompareDate,
it.LstDraftCompareRlt
}).ExecuteCommandAsync();
// 保存日志
//await _bookingOrderService.SaveLog(entity, oldEntity, "核对格式单");
if (entity.LstDraftCompareRlt == "NO DIFF")
{
//推送状态 HDGSD-核对格式单
//await _bookingOrderService.SetGoodsStatusPush("HDGSD", bookingOrder.Id, true);
//比对成功后触发下货纸比对状态
var pushModel = new EmbedServiceProjectStatusDto
{
businessId = bookingOrder.Id.ToString(),
SourceType = 1,
StatusCodes = new List<EmbedServiceProjectStatusDetailDto> {
new EmbedServiceProjectStatusDetailDto{
StatusCode = "HDGSD"
}
}
};
var saveStatusRlt = await _djyServiceStatusService.SaveServiceStatus(pushModel);
//写日志
Logger.Log(NLog.LogLevel.Info, "批次={no} 推送状态 HDGSD-核对格式单 id={id}", batchNo, bookingOrder.Id);
}
//如果确认文件读取成功
var bookFilePath = await _sysFileService.MoveFile(bookingOrder.Id.ToString(), fileFullName, batchNo, false, "draftfiles");
//将格式单附件写入订舱的附件
await SaveEDIFile(bookingOrder.Id, bookFilePath.Data.Item2, new System.IO.FileInfo(fileFullName).Name, long.Parse(user.TenantId), bookFilePath.Data.Item4,
CONST_DRAFT_FILE_CODE, CONST_DRAFT_FILE_NAME);
result = compareResult;
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"请求Draft比对异常,{ex.Message}";
}
return result;
}
#endregion
#region 反序列化请求参数报文
/// <summary>
/// 反序列化请求参数报文
/// </summary>
/// <param name="jsonMessage">请求参数报文</param>
/// <param name="batchNo">批次号</param>
/// <returns>返回反序列化结果</returns>
private TaskEmailDraftCompareMessageInfo GetJsonMessageInfo(string jsonMessage, string batchNo)
{
try
{
return JsonConvert.DeserializeObject<TaskEmailDraftCompareMessageInfo>(jsonMessage);
}
catch
{
Logger.Log(NLog.LogLevel.Info, "批次号{0} jsonMessage请求参数转换失败", batchNo);
throw new Exception($"jsonMessage请求参数转换失败");
}
}
#endregion
#region 解析格式单文件
/// <summary>
/// 解析格式单文件
/// </summary>
/// <param name="nameValueCollection">请求参数</param>
/// <param name="fileInfo">文件</param>
/// <param name="fileAttach">附页文件</param>
/// <param name="contentType">请求类型</param>
/// <returns>返回回执</returns>
[NonAction]
private async Task<TaskManageExcuteCommonResultDto> ExcuteReadPDF(NameValueCollection nameValueCollection, dynamic fileInfo,
dynamic fileAttach, string contentType = "application/json")
{
TaskManageExcuteCommonResultDto model = null;
var result = string.Empty;
using (var httpClient = new HttpClient())
{
try
{
using (var reduceAttach = new MultipartFormDataContent())
{
string[] allKeys = nameValueCollection.AllKeys;
foreach (string key in allKeys)
{
var dataContent = new ByteArrayContent(Encoding.UTF8.GetBytes(nameValueCollection[key]));
dataContent.Headers.ContentDisposition = new ContentDispositionHeaderValue($"form-data")
{
Name = key
};
reduceAttach.Add(dataContent);
}
#region 文件参数
if (fileInfo != null)
{
var Content = new ByteArrayContent(fileInfo.fileBytes);
Content.Headers.Add("Content-Type", contentType);
reduceAttach.Add(Content, fileInfo.file.ToString(), HttpUtility.UrlEncode(fileInfo.fileName.ToString()));
if (fileAttach != null)
{
var Content2 = new ByteArrayContent(fileAttach.fileBytes);
Content2.Headers.Add("Content-Type", contentType);
reduceAttach.Add(Content2, fileAttach.file.ToString(), HttpUtility.UrlEncode(fileAttach.fileName.ToString()));
}
}
#endregion
//请求
var response = httpClient.PostAsync(draftReadUrl, reduceAttach).Result;
result = response.Content.ReadAsStringAsync().Result;
model = JsonConvert.DeserializeObject<TaskManageExcuteCommonResultDto>(result);
}
}
catch (Exception ex)
{
Logger.Log(NLog.LogLevel.Info, "请求Draft比对异常原因{error}", ex.Message);
throw new Exception($"请求Draft比对异常原因{ex.Message}");
//model = new TaskManageExcuteCommonResultDto
//{
// succ = false,
// msg = $"请求Draft比对异常原因{ex.Message}"
//};
}
}
return model;
}
#endregion
#region 请求Draft的PDF解析
/// <summary>
/// 请求Draft的PDF解析
/// </summary>
/// <param name="requestUrl">请求地址</param>
/// <param name="fileInfo">文件详情</param>
/// <returns>返回BC解析详情</returns>
private async Task<PDFReadFileResultDto> TransmitFile(string requestUrl, dynamic fileInfo)
{
PDFReadFileResultDto model = null;
try
{
//var response = await requestUrl.SetContentType("multipart/form-data")
//.SetBodyBytes(fileInfo.file.ToString(),
// fileInfo.fileBytes,
// HttpUtility.UrlEncode(fileInfo.fileName.ToString()))
//.PostAsync();
string res = string.Empty;
if (!string.IsNullOrWhiteSpace(res))
{
//var result = response.Content.ReadAsStringAsync().Result;
//if (string.IsNullOrWhiteSpace(result))
//{
// throw new Exception($"请求格式单PDF文件解析失败未获取到有效信息");
//}
/*
System.Text.Json.JsonSerializerOptions jsonOptions = new JsonSerializerOptions();
jsonOptions.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
jsonOptions.Converters.Add(new IntegerJsonConverter());
jsonOptions.Converters.Add(new DecimalJsonConverter());
*/
model = JsonConvert.DeserializeObject<PDFReadFileResultDto>(res);
}
}
catch (Exception ex)
{
//_logger.LogInformation("{name} 发送BC文件解析请求 url={url} 异常,原因={error}", nameof(TransmitFile),
//requestUrl, ex.Message);
throw new Exception($"{nameof(TransmitFile)} {requestUrl} 请求格式单PDF文件解析异常{ex.Message}");
}
return model;
}
#endregion
#region 请求格式单比对
/// <summary>
/// 请求格式单比对
/// </summary>
/// <param name="info">请求报文</param>
/// <returns></returns>
private async Task<TaskManageExcuteResultDto> ExcuteDraftCompare(TaskDraftCompareMessageInfo info)
{
TaskManageExcuteResultDto model = null;
//var url = App.Configuration["DraftCompareUrl"];
try
{
//var res = await url.SetHttpMethod(HttpMethod.Post)
// .SetBody(JSON.Serialize(info), "application/json")
// .SetContentEncoding(Encoding.UTF8)
//.PostAsync();
var jsonBody = JsonConvert.SerializeObject(info);
var res = RequestHelper.Post(jsonBody, draftCompareUrl);
Logger.Log(NLog.LogLevel.Info, "批次={no} 对应请求报文完成 res={res}", info.Head.GID, res);
if (!string.IsNullOrWhiteSpace(res))
{
//var userResult = await res.Content.ReadAsStringAsync();
//_logger.LogInformation("对应请求报文 userResult={userResult}", userResult);
model = JsonConvert.DeserializeObject<TaskManageExcuteResultDto>(res);
}
}
catch (Exception ex)
{
//写日志
if (ex is HttpRequestException)
throw new Exception("查询失败");
}
return model;
}
#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>
/// <returns></returns>
private async Task<DataResult<string>> SaveEDIFile(long boookId, string FilePath, string fileName, long tenantId, int fileSize,
string fileTypeCode = "bc", string fileTypeName = "Booking Confirmation")
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var newFile = new OpFile
{
//Id = SnowFlakeSingle.Instance.NextId(),
FileName = fileName,
FilePath = FilePath,
TypeCode = fileTypeCode,
TypeName = fileTypeName,
LinkId = boookId,
FileSize = fileSize,
FileType = Path.GetExtension(fileName),
Extension = Path.GetExtension(fileName),
OrgId = user.OrgId
};
await tenantDb.Insertable<OpFile>(newFile).ExecuteCommandAsync();
return DataResult<string>.Success(string.Empty);
}
#endregion
#region 获取Draft比对结果详情
/// <summary>
/// 获取Draft比对结果详情
/// </summary>
/// <param name="bookingId">订舱主键</param>
/// <returns>返回回执</returns>
public async Task<TaskManageExcuteResultDto> GetDraftCompareResultInfo([FromQuery] long bookingId)
{
string batchNo = GuidHelper.GetSnowflakeId();
TaskManageExcuteResultDto result = new TaskManageExcuteResultDto();
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
try
{
DateTime nowDate = DateTime.Now;
TaskDraftCompareMessageInfo msgModel = new TaskDraftCompareMessageInfo
{
Head = new TaskMessageHead
{
GID = batchNo,
MessageType = "DRAFT_COMPARE",
SenderId = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSender" }),
SenderName = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSenderName" }),
ReceiverId = "RulesEngine",
ReceiverName = "大简云规则引擎",
Version = "1.0",
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
RequestAction = "Compare",
},
Main = new TaskDraftMessageMainInfo
{
BusinessInfo = new BusinessInfo
{
BusiPKId = bookingId.ToString()
}
}
};
Logger.Log(NLog.LogLevel.Info, $"开始请求查询 msg={JsonConvert.SerializeObject
(msgModel)}");
result = await GetDraftCompareResult(msgModel);
Logger.Log(NLog.LogLevel.Info, "获取用户信息 userid={uid} userid={username} tendid={tid} OrgId={OrgId}", user.UserId,user.UserName,user.TenantId,user.OrgId);
var lastFileInfo = tenantDb.Queryable<OpFile>().Where(a => a.LinkId == bookingId &&
a.TypeCode.Equals(CONST_DRAFT_FILE_CODE))
.OrderByDescending(a => a.CreateTime).First();
if (lastFileInfo != null)
result.extra3 = lastFileInfo.Id;
if (result != null && result.extra != null && !string.IsNullOrWhiteSpace(result.extra.TaskCompareId))
{
var feedBack = tenantDb.Queryable<DraftCompareFeedBackRecord>().First(a => a.BOOKING_ID == bookingId
&& a.TASK_COMPARE_ID == result.extra.TaskCompareId);
if (feedBack != null)
{
result.extra.ManualFeedBackResult = new FeedBackResult
{
OperNote = feedBack.NOTES,
OperTime = feedBack.CreateTime,
OperUser = feedBack.CreateUserName,
Reason = (feedBack.IS_OCR_ERROR ? "识别问题 " : "") + (feedBack.IS_EDIT_ERROR ? "录入问题 " : "") + (feedBack.IS_AGENT_ERROR ? "代理录入问题 " : "")
};
}
}
}
catch (Exception ex)
{
Logger.Log(NLog.LogLevel.Info, "获取Draft比对结果异常原因{error}", ex.Message);
throw new Exception($"获取Draft比对结果异常原因{ex.Message}");
}
return result;
}
#endregion
#region 获取Draft比对结果
/// <summary>
/// 获取Draft比对结果
/// </summary>
/// <param name="info">请求报文</param>
/// <returns>返回回执</returns>
[NonAction]
private async Task<TaskManageExcuteResultDto> GetDraftCompareResult(TaskDraftCompareMessageInfo info)
{
TaskManageExcuteResultDto model = null;
//var url = App.Configuration["GetDraftCompareUrl"];
try
{
//var res = await url.SetHttpMethod(HttpMethod.Post)
// .SetBody(JSON.Serialize(info), "application/json")
// .SetContentEncoding(Encoding.UTF8)
//.PostAsync();
var jsonBody = JsonConvert.SerializeObject(info);
var res = RequestHelper.Post(jsonBody, draftResultUrl);
Logger.Log(NLog.LogLevel.Info, "批次={no} 对应请求报文完成 res={res}", info.Head.GID, res);
if (!string.IsNullOrWhiteSpace(res))
{
//var userResult = await res.Content.ReadAsStringAsync();
//_logger.LogInformation("对应请求报文 userResult={userResult}", userResult);
model = JsonConvert.DeserializeObject<TaskManageExcuteResultDto>(res);
}
}
catch (Exception ex)
{
//写日志
if (ex is HttpRequestException)
throw new Exception("查询失败");
}
return model;
}
#endregion
#region 执行邮件Draft比对含有附件文件-针对TSL货描附件处理
/// <summary>
/// 执行邮件Draft比对含有附件文件-针对TSL货描附件处理
/// </summary>
/// <param name="file">请求文件</param>
/// <param name="fileAttach">请求附件文件</param>
/// <param name="jsonData">邮件Draft比对请求报文</param>
/// <returns>返回回执</returns>
public async Task<TaskManageExcuteResultDto> ExcuteEmailAttachedSheetDraftCompareAsync(IFormFile file, IFormFile fileAttach, string jsonData)
{
string batchNo = GuidHelper.GetSnowflakeId();
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
TaskManageExcuteResultDto result = new TaskManageExcuteResultDto();
DateTime nowDate = DateTime.Now;
/*
1、接收报文里的文件信息优先写入本地文件暂存。
2、请求解析Draft文件解析并等待解析结果。
3、判断对应的订舱提单号。如果没有对应的订舱提单号则写入任务表失败记录。
4、写入任务表。
5、异步请求格式单比对接口。
6、接收比对结果更新任务表。
7、更新订舱表并更新状态。
*/
try
{
var model = GetJsonMessageInfo(jsonData, batchNo);
TaskDraftCompareMessageInfo readFileMessageInfo = new TaskDraftCompareMessageInfo
{
Head = new TaskMessageHead
{
GID = batchNo,
MessageType = "DRAFT_COMPARE",
SenderId = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSender" }),
SenderName = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSenderName" }),
ReceiverId = "RulesEngine",
ReceiverName = "大简云规则引擎",
Version = "1.0",
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
RequestAction = "Compare",
}
};
var fileRlt = await _sysFileService.SaveFileDirect(model.Head.GID, file.ToByteArray(), batchNo, file.FileName, "bcfiles");
var fileFullName = fileRlt.Data.Item1;
//附件暂存
string fileAttchedFullName = string.Empty;
if (fileAttach != null)
{
var fileAttachRlt = await _sysFileService.SaveFileDirect(model.Head.GID, fileAttach.ToByteArray(), batchNo, file.FileName, "bcfiles");
fileAttchedFullName = fileAttachRlt.Data.Item1;
}
//Draft文件解析
NameValueCollection par = new NameValueCollection();
par.Add("jsonMessage", JsonConvert.SerializeObject(readFileMessageInfo));
byte[] bytes = file.ToByteArray();
DateTime bDate = DateTime.Now;
TaskManageExcuteCommonResultDto readResult = null;
if (fileAttach != null)
{
byte[] bytesAttach = fileAttach.ToByteArray();
readResult = await ExcuteReadPDF(par, new
{
file = "file",
fileName = file.FileName,
fileBytes = bytes
},
new
{
file = "fileAttach",
fileName = fileAttach.FileName,
fileBytes = bytesAttach
});
}
else
{
readResult = await ExcuteReadPDF(par, new
{
file = "file",
fileName = file.FileName,
fileBytes = bytes
}, null);
}
DateTime eDate = DateTime.Now;
TimeSpan ts = eDate.Subtract(bDate);
var timeDiff = ts.TotalMilliseconds;
Logger.Log(NLog.LogLevel.Info, "批次={no} 请求Draft文件解析完成,耗时:{timeDiff}ms. 结果{msg} 报文={message}", batchNo, timeDiff,
readResult.succ ? "成功" : "失败",
JsonConvert.SerializeObject(readResult));
if (!readResult.succ)
{
Logger.Log(NLog.LogLevel.Info, "批次={no} 请求Draft文件解析失败 原因={reason}", batchNo, readResult.msg);
throw new Exception($"请求Draft文件解析失败 原因={readResult.msg}");
}
//通过解析提单号匹配订舱的详情
var readModel = JsonConvert.DeserializeObject<CompareDraftDataInfo>(JsonConvert.SerializeObject(readResult.extra));
string billNo = string.Empty;
if (!string.IsNullOrWhiteSpace(readModel.MasterBlNo))
{
billNo = readModel.MasterBlNo;
}
if (string.IsNullOrWhiteSpace(billNo))
{
Logger.Log(NLog.LogLevel.Info, "批次={no} 请求Draft文件解析未获取到有效提单号", batchNo);
throw new Exception($"请求Draft文件解析未获取到有效提单号");
}
var bookingOrder = tenantDb.Queryable<SeaExport>().First(a => a.MBLNO.Equals(billNo));
if (bookingOrder == null)
{
Logger.Log(NLog.LogLevel.Info, "批次={no} 提单号{billNo}无法获取业务信息", batchNo, billNo);
throw new Exception($"提单号{billNo}无法获取业务信息");
}
Logger.Log(NLog.LogLevel.Info, "批次={no}获取订舱数据完成", batchNo);
TaskDraftCompareMessageInfo msgModel = new TaskDraftCompareMessageInfo
{
Head = new TaskMessageHead
{
GID = batchNo,
MessageType = "DRAFT_COMPARE",
SenderId = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSender" }),
SenderName = AppSetting.app(new string[] { "ExcuteRuleService", "RulesEngineSenderName" }),
ReceiverId = "RulesEngine",
ReceiverName = "大简云规则引擎",
Version = "1.0",
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
RequestAction = "Compare",
},
Main = new TaskDraftMessageMainInfo()
};
//请求格式单比对接口
var mainInfo = bookingOrder.Adapt<BusinessInfo>();
//var userInfo = _sysUserRepository.AsQueryable().First(a => a.Id == bookingOrder.CreatedUserId);
//这里需要对场站进行映射翻译
var mapYardList = _mappingYardService.GetAllList().GetAwaiter().GetResult().Data;
if (mapYardList.Count > 0)
mapYardList = mapYardList.Where(a => a.Module.Equals(CONST_MAPPING_YARD_MODULE, StringComparison.OrdinalIgnoreCase)).ToList();
if (mapYardList.Any(a => a.LinkId == bookingOrder.YardId))
{
mainInfo.YardCode = mapYardList.FirstOrDefault(a => a.LinkId == bookingOrder.YardId).MapCode;
}
var codePortList = _codePortService.GetAllList().GetAwaiter().GetResult().Data;
if (codePortList.Any(a => a.Id == bookingOrder.LoadPortId))
mainInfo.PortLoadId = codePortList.FirstOrDefault(a => a.Id == bookingOrder.LoadPortId).EdiCode;
if (codePortList.Any(a => a.Id == bookingOrder.DischargePortId))
mainInfo.PortDischargeId = codePortList.FirstOrDefault(a => a.Id == bookingOrder.DischargePortId).EdiCode;
if (codePortList.Any(a => a.Id == bookingOrder.DeliveryPlaceId))
mainInfo.PlaceDeliveryId = codePortList.FirstOrDefault(a => a.Id == bookingOrder.DeliveryPlaceId).EdiCode;
if (codePortList.Any(a => a.Id == bookingOrder.DestinationId))
mainInfo.DestinationId = codePortList.FirstOrDefault(a => a.Id == bookingOrder.DestinationId).EdiCode;
mainInfo.BusiPKId = bookingOrder.Id.ToString();
mainInfo.UserId = user.UserId;
mainInfo.UserName = user.UserName;
//mainInfo.UserEmail = UserManager.Email;
var contaList = tenantDb.Queryable<OpCtn>()
.Where(x => long.Parse(x.BSNO) == bookingOrder.Id)
.ToList();
Logger.Log(NLog.LogLevel.Info, "批次={no} 提取箱完成 数量={total}", batchNo, contaList.Count);
if (contaList.Count > 0)
{
mainInfo.ContaList = contaList.Adapt<List<TaskDraftMessageCtnInfo>>();
}
msgModel.Main.BusinessInfo = mainInfo;
msgModel.Main.DraftInfo = readModel;
//推送Draft比对
DateTime bCompareDate = DateTime.Now;
var compareResult = await ExcuteDraftCompare(msgModel);
DateTime eCompareDate = DateTime.Now;
TimeSpan tsCompare = bCompareDate.Subtract(eCompareDate);
var timeDiffCompare = tsCompare.TotalMilliseconds;
Logger.Log(NLog.LogLevel.Info, "批次={no} 请求Draft比对完成,耗时:{timeDiff}ms. 结果{msg} 报文={message}", batchNo, timeDiffCompare,
compareResult.succ ? "成功" : "失败",
JsonConvert.SerializeObject(compareResult));
Logger.Log(NLog.LogLevel.Info, "批次={no} 对应请求报文完成 msg={msg}", batchNo, JsonConvert.SerializeObject(msgModel));
var entity = tenantDb.Queryable<SeaExport>()
.First(a => a.Id == bookingOrder.Id);
var oldEntity = entity.Adapt<SeaExport>();
entity.LstDraftCompareRlt = compareResult.extra2.Any(a => a.IsDiff) ? "DIFF" : "NO DIFF";
entity.LstDraftCompareDate = nowDate;
//更新订舱相关
await tenantDb.Updateable(entity).UpdateColumns(it => new
{
it.LstDraftCompareDate,
it.LstDraftCompareRlt
}).ExecuteCommandAsync();
// 添加日志
//await _bookingOrderService.SaveLog(entity, oldEntity, "核对格式单");
if (entity.LstDraftCompareRlt == "NO DIFF")
{
//推送状态 HDGSD-核对格式单
//await _bookingOrderService.SetGoodsStatusPush("HDGSD", bookingOrder.Id, true);
var pushModel = new EmbedServiceProjectStatusDto
{
businessId = bookingOrder.Id.ToString(),
SourceType = 1,
StatusCodes = new List<EmbedServiceProjectStatusDetailDto> {
new EmbedServiceProjectStatusDetailDto{
StatusCode = "HDGSD"
}
}
};
var saveStatusRlt = await _djyServiceStatusService.SaveServiceStatus(pushModel);
//写日志
Logger.Log(NLog.LogLevel.Info, "批次={no} 推送状态 HDGSD-核对格式单 id={id}", batchNo, bookingOrder.Id);
}
//如果确认文件读取成功
var bookFilePath = await _sysFileService.MoveFile(bookingOrder.Id.ToString(), fileFullName, batchNo);
//将格式单附件写入订舱的附件
await SaveEDIFile(bookingOrder.Id, bookFilePath.Data.Item2, new System.IO.FileInfo(fileFullName).Name, long.Parse(user.TenantId), bookFilePath.Data.Item4,
CONST_DRAFT_FILE_CODE, CONST_DRAFT_FILE_NAME);
if (!string.IsNullOrWhiteSpace(fileAttchedFullName))
{
var currBookFilePath = await _sysFileService.MoveFile(bookingOrder.Id.ToString(), fileAttchedFullName, batchNo);
//将格式单附件写入订舱的附件
await SaveEDIFile(bookingOrder.Id, currBookFilePath.Data.Item2, new System.IO.FileInfo(fileAttchedFullName).Name, long.Parse(user.TenantId), currBookFilePath.Data.Item4,
CONST_DRAFT_FILE_CODE, CONST_DRAFT_FILE_NAME);
}
result = compareResult;
}
catch (Exception ex)
{
result.succ = false;
result.msg = $"请求Draft比对异常,{ex.Message}";
}
return result;
}
#endregion
#region 保存格式单比对反馈
/// <summary>
/// 保存格式单比对反馈
/// </summary>
/// <param name="model">请求详情</param>
/// <returns>返回回执</returns>
[HttpPost("/TaskDraftCompare/SaveDraftCompareManual")]
public async Task SaveDraftCompareManual(TaskDraftCompareFeedBackDto model)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
if (model.bookingId <= 0)
throw new Exception($"订舱ID不能为空");
var order = tenantDb.Queryable<SeaExport>().First(a => a.Id == model.bookingId);
if (order == null)
throw new Exception($"订舱详情获取失败,订舱信息不存在或已作废");
if (!model.isOCRError && !model.isEditError && !model.isAgentError)
{
throw new Exception($"至少选择一个原因");
}
Logger.Log(NLog.LogLevel.Info, "请求比对反馈model={msg}", JsonConvert.SerializeObject(model));
DateTime nowDate = DateTime.Now;
DraftCompareFeedBackRecord entity = new DraftCompareFeedBackRecord
{
BOOKING_ID = model.bookingId,
IS_AGENT_ERROR = model.isAgentError,
IS_OCR_ERROR = model.isOCRError,
IS_EDIT_ERROR = model.isEditError,
NOTES = model.notes,
COMPARE_TYPE = model.compareType,
COMPARE_TIME = model.compareTime,
TASK_COMPARE_ID = model.taskCompareId,
CreateBy = long.Parse(user.UserId),
CreateUserName = user.UserName,
CreateTime = nowDate,
UpdateTime = nowDate
};
//新增完记录
await tenantDb.Insertable<DraftCompareFeedBackRecord>(entity).ExecuteCommandAsync();
Logger.Log(NLog.LogLevel.Info, "请求比对反馈写入表完成id={id}", model.bookingId);
var oldOrder = tenantDb.Queryable<SeaExport>().First(a => a.Id == model.bookingId);
//更新订舱相关的格式单比对状态
if (model.compareType.Equals("DRAFT", StringComparison.OrdinalIgnoreCase))
{
Logger.Log(NLog.LogLevel.Info, "请求比对反馈选择修正 compareType={compare}id={id}", model.compareType, model.bookingId);
order.LstDraftCompareRlt = "NO DIFF";
order.UpdateTime = nowDate;
order.UpdateBy = long.Parse(user.UserId);
order.UpdateUserName = user.UserName;
await tenantDb.Updateable<SeaExport>(order).UpdateColumns(t => new
{
t.LstDraftCompareRlt,
t.UpdateBy,
t.UpdateUserName,
t.UpdateTime,
}).ExecuteCommandAsync();
Logger.Log(NLog.LogLevel.Info, "请求比对反馈更新订舱状态完成id={id}", model.bookingId);
// 保存日志
//await _bookingOrderService.SaveLog(order, oldOrder, "格式单比对反馈回写");
}
else if (model.compareType.Equals("SHIPORDER", StringComparison.OrdinalIgnoreCase))
{
Logger.Log(NLog.LogLevel.Info, "请求比对反馈选择修正 compareType={compare}id={id}", model.compareType, model.bookingId);
order.LstShipOrderCompareRlt = "NO_DIFF";
order.LstShipOrderCompareRltName = "正常";
order.UpdateTime = nowDate;
order.UpdateBy = long.Parse(user.UserId);
order.UpdateUserName = user.UserName;
await tenantDb.Updateable<SeaExport>(order).UpdateColumns(t => new
{
t.LstShipOrderCompareRlt,
t.LstShipOrderCompareRltName,
t.UpdateBy,
t.UpdateUserName,
t.UpdateTime,
}).ExecuteCommandAsync();
// 保存日志
//await _bookingOrderService.SaveLog(order, oldOrder, "格式单比对反馈回写");
Logger.Log(NLog.LogLevel.Info, "请求比对反馈更新订舱状态完成id={id}", model.bookingId);
////比对成功后触发下货纸比对状态
//var saveStatusRlt = await _bookingValueAddedService.SaveServiceStatus(new ModifyServiceProjectStatusDto
//{
// BookingId = model.bookingId,
// SourceType = TrackingSourceTypeEnum.AUTO,
// StatusCodes = new List<ModifyServiceProjectStatusDetailDto> {
// new ModifyServiceProjectStatusDetailDto { StatusCode = "XHZBDCHG" } }
//});
var pushModel = new EmbedServiceProjectStatusDto
{
businessId = model.bookingId.ToString(),
SourceType = 1,
StatusCodes = new List<EmbedServiceProjectStatusDetailDto> {
new EmbedServiceProjectStatusDetailDto{
StatusCode = "XHZBDCHG"
}
}
};
var saveStatusRlt = await _djyServiceStatusService.SaveServiceStatus(pushModel);
Logger.Log(NLog.LogLevel.Info, "异步推送下货纸比对状态完成,结果={rlt}", JsonConvert.SerializeObject(saveStatusRlt));
}
}
#endregion
}
}