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(); user = _serviceProvider.GetRequiredService(); saasService = _serviceProvider.GetRequiredService(); _djyServiceStatusService = _serviceProvider.GetRequiredService(); _sysFileService = _serviceProvider.GetRequiredService(); _mappingYardService = _serviceProvider.GetRequiredService(); _mappingCarrierService = _serviceProvider.GetRequiredService(); _codePortService = _serviceProvider.GetRequiredService(); draftReadUrl = AppSetting.app(new string[] { "DraftCompare", "ReadUrl" }); draftCompareUrl = AppSetting.app(new string[] { "DraftCompare", "Url" }); draftResultUrl = AppSetting.app(new string[] { "DraftCompare", "ResultUrl" }); } #region 执行邮件Draft比对 /// /// 执行邮件Draft比对 /// /// 请求文件 /// 邮件Draft比对请求报文 /// 返回回执 public async Task 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(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().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(); //这里需要对场站进行映射翻译 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() .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>(); } 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() .First(a => a.Id == bookingOrder.Id); var oldEntity = entity.Adapt(); 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 { 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 反序列化请求参数报文 /// /// 反序列化请求参数报文 /// /// 请求参数报文 /// 批次号 /// 返回反序列化结果 private TaskEmailDraftCompareMessageInfo GetJsonMessageInfo(string jsonMessage, string batchNo) { try { return JsonConvert.DeserializeObject(jsonMessage); } catch { Logger.Log(NLog.LogLevel.Info, "批次号{0} jsonMessage请求参数转换失败", batchNo); throw new Exception($"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(draftReadUrl, reduceAttach).Result; result = response.Content.ReadAsStringAsync().Result; model = JsonConvert.DeserializeObject(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解析 /// /// 请求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(); 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(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 请求格式单比对 /// /// 请求格式单比对 /// /// 请求报文 /// 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(); 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(res); } } catch (Exception ex) { //写日志 if (ex is HttpRequestException) throw new Exception("查询失败"); } return model; } #endregion #region 异步写入订舱附件表 /// /// 异步写入订舱附件表 /// /// 订舱ID /// 文件路径 /// 文件名 /// 租户ID /// 附件类型代码 /// 附件类型名称 /// private async Task> 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(newFile).ExecuteCommandAsync(); return DataResult.Success(string.Empty); } #endregion #region 获取Draft比对结果详情 /// /// 获取Draft比对结果详情 /// /// 订舱主键 /// 返回回执 public async Task 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().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().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比对结果 /// /// 获取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(); 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(res); } } catch (Exception ex) { //写日志 if (ex is HttpRequestException) throw new Exception("查询失败"); } return model; } #endregion #region 执行邮件Draft比对(含有附件文件-针对TSL货描附件处理) /// /// 执行邮件Draft比对(含有附件文件-针对TSL货描附件处理) /// /// 请求文件 /// 请求附件文件 /// 邮件Draft比对请求报文 /// 返回回执 public async Task 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(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().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(); //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() .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>(); } 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() .First(a => a.Id == bookingOrder.Id); var oldEntity = entity.Adapt(); 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 { 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 保存格式单比对反馈 /// /// 保存格式单比对反馈 /// /// 请求详情 /// 返回回执 [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().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(entity).ExecuteCommandAsync(); Logger.Log(NLog.LogLevel.Info, "请求比对反馈写入表完成,id={id}", model.bookingId); var oldOrder = tenantDb.Queryable().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(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(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 { // new ModifyServiceProjectStatusDetailDto { StatusCode = "XHZBDCHG" } } //}); var pushModel = new EmbedServiceProjectStatusDto { businessId = model.bookingId.ToString(), SourceType = 1, StatusCodes = new List { new EmbedServiceProjectStatusDetailDto{ StatusCode = "XHZBDCHG" } } }; var saveStatusRlt = await _djyServiceStatusService.SaveServiceStatus(pushModel); Logger.Log(NLog.LogLevel.Info, "异步推送下货纸比对状态完成,结果={rlt}", JsonConvert.SerializeObject(saveStatusRlt)); } } #endregion } }