using Furion; using Furion.DependencyInjection; using Furion.DistributedIDGenerator; using Furion.DynamicApiController; using Furion.Extensions; using Furion.FriendlyException; using Furion.JsonSerialization; using Furion.RemoteRequest.Extensions; using Mapster; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Myshipping.Application.Entity; using Myshipping.Application.Entity.DraftCompare; using Myshipping.Application.Service; using Myshipping.Core; using Myshipping.Core.Entity; using Myshipping.Core.Service; using NPOI.SS.Formula.Functions; using Org.BouncyCastle.Asn1.X9; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using System.Web; using Yitter.IdGenerator; namespace Myshipping.Application { /// /// 请求Draft比对 /// [ApiDescriptionSettings("Application", Name = "TaskDraftCompare", Order = 10)] public class TaskDraftCompareService : ITaskDraftCompareService, IDynamicApiController, ITransient { private readonly ISysCacheService _cache; private readonly ILogger _logger; private readonly SqlSugarRepository _bookingOrderRepository; private readonly SqlSugarRepository _bookingOrderContaRepository; private readonly SqlSugarRepository _bookingFileRepository; private readonly SqlSugarRepository _sysUserRepository; private readonly IBookingOrderService _bookingOrderService; private readonly SqlSugarRepository _draftCompareFeedBackRecordRepository; private readonly IBookingValueAddedService _bookingValueAddedService; const string CONST_DRAFT_FILE_CODE = "draft"; const string CONST_DRAFT_FILE_NAME = "格式单"; public TaskDraftCompareService(ISysCacheService cache, ILogger logger, SqlSugarRepository bookingOrderRepository, SqlSugarRepository bookingOrderContaRepository, SqlSugarRepository bookingFileRepository, SqlSugarRepository sysUserRepository, IBookingOrderService bookingOrderService, SqlSugarRepository draftCompareFeedBackRecordRepository, IBookingValueAddedService bookingValueAddedService) { _cache = cache; _logger = logger; _bookingOrderRepository = bookingOrderRepository; _bookingOrderContaRepository = bookingOrderContaRepository; _bookingFileRepository = bookingFileRepository; _sysUserRepository = sysUserRepository; _bookingOrderService = bookingOrderService; _draftCompareFeedBackRecordRepository = draftCompareFeedBackRecordRepository; _bookingValueAddedService = bookingValueAddedService; } #region 执行邮件Draft比对 /// /// 执行邮件Draft比对 /// /// 请求文件 /// 邮件Draft比对请求报文 /// 返回回执 [AllowAnonymous, HttpPost("/TaskDraftCompare/ExcuteEmailDraftCompare"), ApiUser(ApiCode = "BCTaskManage")] public async Task ExcuteEmailDraftCompareAsync(IFormFile file, [FromForm] string jsonData) { string batchNo = IDGen.NextID().ToString(); 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 = App.Configuration["RulesEngineSender"], SenderName = App.Configuration["RulesEngineSenderName"], ReceiverId = "RulesEngine", ReceiverName = "大简云规则引擎", Version = "1.0", RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"), RequestAction = "Compare", } }; //附件暂存 var fileFullName = await FileAttachHelper.TempSaveWebFile(model.Head.GID, file, batchNo, CONST_DRAFT_FILE_CODE); //Draft文件解析 NameValueCollection par = new NameValueCollection(); par.Add("jsonMessage", JSON.Serialize(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.LogInformation("批次={no} 请求Draft文件解析完成,耗时:{timeDiff}ms. 结果{msg} 报文={message}", batchNo, timeDiff, readResult.succ ? "成功" : "失败", JSON.Serialize(readResult)); if (!readResult.succ) { _logger.LogInformation("批次={no} 请求Draft文件解析失败 原因={reason}", batchNo, readResult.msg); throw Oops.Oh($"请求Draft文件解析失败 原因={readResult.msg}"); } //通过解析提单号匹配订舱的详情 var readModel = JSON.Deserialize(JSON.Serialize(readResult.extra)); string billNo = string.Empty; if (!string.IsNullOrWhiteSpace(readModel.MasterBlNo)) { billNo = readModel.MasterBlNo; } if (string.IsNullOrWhiteSpace(billNo)) { _logger.LogInformation("批次={no} 请求Draft文件解析未获取到有效提单号", batchNo); throw Oops.Oh($"请求Draft文件解析未获取到有效提单号"); } var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true) .First(a => a.MBLNO.Equals(billNo) && !a.IsDeleted && a.TenantId == UserManager.TENANT_ID); if (bookingOrder == null) { _logger.LogInformation("批次={no} 提单号{billNo}无法获取业务信息", batchNo, billNo); throw Oops.Oh($"提单号{billNo}无法获取业务信息"); } _logger.LogInformation("批次={no}获取订舱数据完成", batchNo); TaskDraftCompareMessageInfo msgModel = new TaskDraftCompareMessageInfo { Head = new TaskMessageHead { GID = batchNo, MessageType = "DRAFT_COMPARE", SenderId = App.Configuration["RulesEngineSender"], SenderName = App.Configuration["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(); var userInfo = _sysUserRepository.AsQueryable().First(a => a.Id == bookingOrder.CreatedUserId); mainInfo.BusiPKId = bookingOrder.Id.ToString(); mainInfo.UserId = UserManager.UserId.ToString(); mainInfo.UserName = UserManager.Name; mainInfo.UserEmail = UserManager.Email; var contaList = _bookingOrderContaRepository.AsQueryable().Filter(null, true) .Where(x => x.BILLID == bookingOrder.Id && !x.IsDeleted && x.TenantId == UserManager.TENANT_ID).ToList(); _logger.LogInformation("批次={no} 提取箱完成 数量={total}", batchNo, contaList.Count); if (contaList.Count > 0) { mainInfo.ContaList = contaList.Adapt>(); } 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.LogInformation("批次={no} 请求Draft比对完成,耗时:{timeDiff}ms. 结果{msg} 报文={message}", batchNo, timeDiffCompare, compareResult.succ ? "成功" : "失败", JSON.Serialize(compareResult)); _logger.LogInformation("批次={no} 对应请求报文完成 msg={msg}", batchNo, JSON.Serialize(msgModel)); var entity = _bookingOrderRepository.AsQueryable().Filter(null, true) .First(a => a.Id == bookingOrder.Id && !a.IsDeleted && a.TenantId == UserManager.TENANT_ID); var oldEntity = entity.Adapt(); entity.LstDraftCompareRlt = compareResult.extra2.Any(a => a.IsDiff) ? "DIFF" : "NO DIFF"; entity.LstDraftCompareDate = nowDate; //更新订舱相关 await _bookingOrderRepository.AsUpdateable(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); //写日志 _logger.LogInformation("批次={no} 推送状态 HDGSD-核对格式单 id={id}", batchNo, bookingOrder.Id); } //如果确认文件读取成功 var bookFilePath = await FileAttachHelper.MoveFile(bookingOrder.Id.ToString(), fileFullName, batchNo, false, "draftfiles"); //将格式单附件写入订舱的附件 await SaveEDIFile(bookingOrder.Id, bookFilePath, new System.IO.FileInfo(fileFullName).Name, entity.TenantId.Value, 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 反序列化请求参数报文 /// /// 反序列化请求参数报文 /// /// 请求参数报文 /// 批次号 /// 返回反序列化结果 private TaskEmailDraftCompareMessageInfo GetJsonMessageInfo(string jsonMessage, string batchNo) { try { return JSON.Deserialize(jsonMessage); } catch { _logger.LogInformation("批次号{0} jsonMessage请求参数转换失败", batchNo); throw Oops.Oh($"jsonMessage请求参数转换失败"); } } #endregion #region 解析格式单文件 /// /// 解析格式单文件 /// /// 请求参数 /// 文件 /// 附页文件 /// 请求类型 /// 返回回执 [NonAction] private async Task 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(App.Configuration["DraftReadUrl"], reduceAttach).Result; result = response.Content.ReadAsStringAsync().Result; model = JSON.Deserialize(result); } } catch (Exception ex) { _logger.LogInformation("请求Draft比对异常,原因:{error}", ex.Message); throw Oops.Oh($"请求Draft比对异常,原因:{ex.Message}"); } } return model; } #endregion #region 请求Draft的PDF解析 /// /// 请求Draft的PDF解析 /// /// 请求地址 /// 文件详情 /// 返回BC解析详情 private async Task 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(); if (response.StatusCode == System.Net.HttpStatusCode.OK) { var result = response.Content.ReadAsStringAsync().Result; if (string.IsNullOrWhiteSpace(result)) { throw Oops.Bah($"请求格式单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 = JSON.Deserialize(result); } } catch (Exception ex) { //_logger.LogInformation("{name} 发送BC文件解析请求 url={url} 异常,原因={error}", nameof(TransmitFile), //requestUrl, ex.Message); throw Oops.Bah($"{nameof(TransmitFile)} {requestUrl} 请求格式单PDF文件解析异常,{ex.Message}"); } return model; } #endregion #region 请求格式单比对 /// /// 请求格式单比对 /// /// 请求报文 /// private async Task 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(); _logger.LogInformation("批次={no} 对应请求报文完成 res={res}", info.Head.GID, JSON.Serialize(res)); if (res.StatusCode == System.Net.HttpStatusCode.OK) { var userResult = await res.Content.ReadAsStringAsync(); _logger.LogInformation("对应请求报文 userResult={userResult}", userResult); model = JSON.Deserialize(userResult); } } catch (Exception ex) { //写日志 if (ex is HttpRequestException) throw Oops.Oh(10000002); } return model; } #endregion #region 异步写入订舱附件表 /// /// 异步写入订舱附件表 /// /// 订舱ID /// 文件路径 /// 文件名 /// 租户ID /// 附件类型代码 /// 附件类型名称 /// [NonAction] private async Task SaveEDIFile(long boookId, string FilePath, string fileName, long tenantId, string fileTypeCode = "bc", string fileTypeName = "Booking Confirmation") { /* 直接将附件信息写入附件表 */ //EDI文件 var bookFile = new BookingFile { Id = YitIdHelper.NextId(), FileName = fileName, FilePath = FilePath, TypeCode = fileTypeCode, TypeName = fileTypeName, BookingId = boookId, TenantId = tenantId }; await _bookingFileRepository.InsertAsync(bookFile); } #endregion #region 获取Draft比对结果详情 /// /// 获取Draft比对结果详情 /// /// 订舱主键 /// 返回回执 [HttpPost("/TaskDraftCompare/GetDraftCompareResultInfo")] public async Task GetDraftCompareResultInfo([FromQuery] long bookingId) { string batchNo = IDGen.NextID().ToString(); TaskManageExcuteResultDto result = new TaskManageExcuteResultDto(); try { DateTime nowDate = DateTime.Now; TaskDraftCompareMessageInfo msgModel = new TaskDraftCompareMessageInfo { Head = new TaskMessageHead { GID = batchNo, MessageType = "DRAFT_COMPARE", SenderId = App.Configuration["RulesEngineSender"], SenderName = App.Configuration["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.LogInformation($"开始请求查询 msg={JSON.Serialize(msgModel)}"); result = await GetDraftCompareResult(msgModel); var lastFileInfo = _bookingFileRepository.AsQueryable().Filter(null, true).Where(a => a.BookingId == bookingId && a.TypeCode.Equals(CONST_DRAFT_FILE_CODE)) .OrderByDescending(a => a.CreatedTime).First(); if (lastFileInfo != null) result.extra3 = lastFileInfo.Id; if (result != null && result.extra != null && !string.IsNullOrWhiteSpace(result.extra.TaskCompareId)) { var feedBack = _draftCompareFeedBackRecordRepository.AsQueryable().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.CreatedTime.Value, OperUser = feedBack.CreatedUserName, Reason = (feedBack.IS_OCR_ERROR?"识别问题 ":"")+ (feedBack.IS_EDIT_ERROR ? "录入问题 " : "")+ (feedBack.IS_AGENT_ERROR ? "代理录入问题 " : "") }; } } } catch (Exception ex) { _logger.LogInformation("获取Draft比对结果异常,原因:{error}", ex.Message); throw Oops.Oh($"获取Draft比对结果异常,原因:{ex.Message}"); } return result; } #endregion #region 获取Draft比对结果 /// /// 获取Draft比对结果 /// /// 请求报文 /// 返回回执 [NonAction] private async Task 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(); _logger.LogInformation("批次={no} 对应请求报文完成 res={res}", info.Head.GID, JSON.Serialize(res)); if (res.StatusCode == System.Net.HttpStatusCode.OK) { var userResult = await res.Content.ReadAsStringAsync(); _logger.LogInformation("对应请求报文 userResult={userResult}", userResult); model = JSON.Deserialize(userResult); } } catch (Exception ex) { //写日志 if (ex is HttpRequestException) throw Oops.Oh(10000002); } return model; } #endregion #region 执行邮件Draft比对(含有附件文件-针对TSL货描附件处理) /// /// 执行邮件Draft比对(含有附件文件-针对TSL货描附件处理) /// /// 请求文件 /// 请求附件文件 /// 邮件Draft比对请求报文 /// 返回回执 [AllowAnonymous, HttpPost("/TaskDraftCompare/ExcuteEmailAttachedSheetDraftCompare"), ApiUser(ApiCode = "BCTaskManage")] public async Task ExcuteEmailAttachedSheetDraftCompareAsync(IFormFile file, IFormFile fileAttach, string jsonData) { string batchNo = IDGen.NextID().ToString(); 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 = App.Configuration["RulesEngineSender"], SenderName = App.Configuration["RulesEngineSenderName"], ReceiverId = "RulesEngine", ReceiverName = "大简云规则引擎", Version = "1.0", RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"), RequestAction = "Compare", } }; //附件暂存 var fileFullName = await FileAttachHelper.TempSaveWebFile(model.Head.GID, file, batchNo, CONST_DRAFT_FILE_CODE); string fileAttchedFullName = string.Empty; if (fileAttach != null) { fileAttchedFullName = await FileAttachHelper.TempSaveWebFile(model.Head.GID, fileAttach, batchNo, CONST_DRAFT_FILE_CODE); } //Draft文件解析 NameValueCollection par = new NameValueCollection(); par.Add("jsonMessage", JSON.Serialize(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.LogInformation("批次={no} 请求Draft文件解析完成,耗时:{timeDiff}ms. 结果{msg} 报文={message}", batchNo, timeDiff, readResult.succ ? "成功" : "失败", JSON.Serialize(readResult)); if (!readResult.succ) { _logger.LogInformation("批次={no} 请求Draft文件解析失败 原因={reason}", batchNo, readResult.msg); throw Oops.Oh($"请求Draft文件解析失败 原因={readResult.msg}"); } //通过解析提单号匹配订舱的详情 var readModel = JSON.Deserialize(JSON.Serialize(readResult.extra)); string billNo = string.Empty; if (!string.IsNullOrWhiteSpace(readModel.MasterBlNo)) { billNo = readModel.MasterBlNo; } if (string.IsNullOrWhiteSpace(billNo)) { _logger.LogInformation("批次={no} 请求Draft文件解析未获取到有效提单号", batchNo); throw Oops.Oh($"请求Draft文件解析未获取到有效提单号"); } var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true) .First(a => a.MBLNO.Equals(billNo) && !a.IsDeleted && a.TenantId == long.Parse(model.Main.TenantId)); if (bookingOrder == null) { _logger.LogInformation("批次={no} 提单号{billNo}无法获取业务信息", batchNo, billNo); throw Oops.Oh($"提单号{billNo}无法获取业务信息"); } _logger.LogInformation("批次={no}获取订舱数据完成", batchNo); TaskDraftCompareMessageInfo msgModel = new TaskDraftCompareMessageInfo { Head = new TaskMessageHead { GID = batchNo, MessageType = "DRAFT_COMPARE", SenderId = App.Configuration["RulesEngineSender"], SenderName = App.Configuration["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(); var userInfo = _sysUserRepository.AsQueryable().First(a => a.Id == bookingOrder.CreatedUserId); mainInfo.BusiPKId = bookingOrder.Id.ToString(); mainInfo.UserId = UserManager.UserId.ToString(); mainInfo.UserName = UserManager.Name; mainInfo.UserEmail = UserManager.Email; var contaList = _bookingOrderContaRepository.AsQueryable().Filter(null, true) .Where(x => x.BILLID == bookingOrder.Id && !x.IsDeleted && x.TenantId == UserManager.TENANT_ID) .ToList(); _logger.LogInformation("批次={no} 提取箱完成 数量={total}", batchNo, contaList.Count); if (contaList.Count > 0) { mainInfo.ContaList = contaList.Adapt>(); } 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.LogInformation("批次={no} 请求Draft比对完成,耗时:{timeDiff}ms. 结果{msg} 报文={message}", batchNo, timeDiffCompare, compareResult.succ ? "成功" : "失败", JSON.Serialize(compareResult)); _logger.LogInformation("批次={no} 对应请求报文完成 msg={msg}", batchNo, JSON.Serialize(msgModel)); var entity = _bookingOrderRepository.AsQueryable().Filter(null, true) .First(a => a.Id == bookingOrder.Id && !a.IsDeleted && a.TenantId == UserManager.TENANT_ID); var oldEntity = entity.Adapt(); entity.LstDraftCompareRlt = compareResult.extra2.Any(a => a.IsDiff) ? "DIFF" : "NO DIFF"; entity.LstDraftCompareDate = nowDate; //更新订舱相关 await _bookingOrderRepository.AsUpdateable(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); //写日志 _logger.LogInformation("批次={no} 推送状态 HDGSD-核对格式单 id={id}", batchNo, bookingOrder.Id); } //如果确认文件读取成功 var bookFilePath = await FileAttachHelper.MoveFile(bookingOrder.Id.ToString(), fileFullName, batchNo); //将格式单附件写入订舱的附件 await SaveEDIFile(bookingOrder.Id, bookFilePath, new System.IO.FileInfo(fileFullName).Name, entity.TenantId.Value, CONST_DRAFT_FILE_CODE, CONST_DRAFT_FILE_NAME); if (!string.IsNullOrWhiteSpace(fileAttchedFullName)) { var currBookFilePath = await FileAttachHelper.MoveFile(bookingOrder.Id.ToString(), fileAttchedFullName, batchNo); //将格式单附件写入订舱的附件 await SaveEDIFile(bookingOrder.Id, currBookFilePath, new System.IO.FileInfo(fileAttchedFullName).Name, entity.TenantId.Value, 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 保存格式单比对反馈 /// /// 保存格式单比对反馈 /// /// 请求详情 /// 返回回执 [HttpPost("/TaskDraftCompare/SaveDraftCompareManual")] public async Task SaveDraftCompareManual(TaskDraftCompareFeedBackDto model) { if (model.bookingId <= 0) throw Oops.Oh($"订舱ID不能为空"); var order = _bookingOrderRepository.AsQueryable().First(a => a.Id == model.bookingId); if (order == null) throw Oops.Oh($"订舱详情获取失败,订舱信息不存在或已作废"); if (!model.isOCRError && !model.isEditError && !model.isAgentError) { throw Oops.Oh($"至少选择一个原因"); } _logger.LogInformation("请求比对反馈,model={msg}", JSON.Serialize(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, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, CreatedTime = nowDate, UpdatedTime = nowDate }; //新增完记录 await _draftCompareFeedBackRecordRepository.InsertAsync(entity); _logger.LogInformation("请求比对反馈写入表完成,id={id}", model.bookingId); var oldOrder = _bookingOrderRepository.AsQueryable().First(a => a.Id == model.bookingId); //更新订舱相关的格式单比对状态 if (model.compareType.Equals("DRAFT", StringComparison.OrdinalIgnoreCase)) { _logger.LogInformation("请求比对反馈选择修正 compareType={compare},id={id}", model.compareType, model.bookingId); order.LstDraftCompareRlt = "NO DIFF"; order.UpdatedTime = nowDate; order.UpdatedUserId = UserManager.UserId; order.UpdatedUserName = UserManager.Name; await _bookingOrderRepository.AsUpdateable(order).UpdateColumns(t => new { t.LstDraftCompareRlt, t.UpdatedUserId, t.UpdatedUserName, t.UpdatedTime, }).ExecuteCommandAsync(); _logger.LogInformation("请求比对反馈更新订舱状态完成,id={id}", model.bookingId); // 保存日志 await _bookingOrderService.SaveLog(order, oldOrder, "格式单比对反馈回写"); } else if (model.compareType.Equals("SHIPORDER", StringComparison.OrdinalIgnoreCase)) { _logger.LogInformation("请求比对反馈选择修正 compareType={compare},id={id}", model.compareType, model.bookingId); order.LstShipOrderCompareRlt = "NO_DIFF"; order.LstShipOrderCompareRltName = "正常"; order.UpdatedTime = nowDate; order.UpdatedUserId = UserManager.UserId; order.UpdatedUserName = UserManager.Name; await _bookingOrderRepository.AsUpdateable(order).UpdateColumns(t => new { t.LstShipOrderCompareRlt, t.LstShipOrderCompareRltName, t.UpdatedUserId, t.UpdatedUserName, t.UpdatedTime, }).ExecuteCommandAsync(); // 保存日志 await _bookingOrderService.SaveLog(order, oldOrder, "格式单比对反馈回写"); _logger.LogInformation("请求比对反馈更新订舱状态完成,id={id}", model.bookingId); //比对成功后触发下货纸比对状态 var saveStatusRlt = await _bookingValueAddedService.SaveServiceStatus(new ModifyServiceProjectStatusDto { BookingId = model.bookingId, SourceType = TrackingSourceTypeEnum.AUTO, StatusCodes = new List { new ModifyServiceProjectStatusDetailDto { StatusCode = "XHZBDCHG" } } }); _logger.LogInformation("异步推送下货纸比对状态完成,结果={rlt}", JSON.Serialize(saveStatusRlt)); } } #endregion } }