using DS.Module.Core; using DS.Module.Core.Extensions; using DS.Module.Core.Helpers; using DS.WMS.Core.Code.Entity; using DS.WMS.Core.Info.Entity; using DS.WMS.Core.Map.Entity; using DS.WMS.Core.Op.Dtos; using DS.WMS.Core.Op.EDI; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Sys.Entity; using Mapster; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using System.Collections.Specialized; using System.Runtime.InteropServices; using System.Text.RegularExpressions; namespace DS.WMS.Core.Op.Method { /// /// 海运出口提箱小票相关接口 /// public partial class SeaExportService { #region 订舱、截单EDI /// /// 发送订舱、截单EDI /// /// 订舱、截单EDI请求 /// 返回回执 public async Task> SendBookingOrClosingEDI(BookingOrClosingEDIOrderReq req) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); var dictValue = db.Queryable() .InnerJoin((a, b) => a.TypeId == b.Id).Where((a, b) => b.Code == "XiangManCang") .Select((a, b) => new { Value = a.Value, Name = a.Name }).First(); var order = tenantDb.Queryable().First(x => x.Id == req.Id); var Forwarder = order.Forwarder; if (!string.IsNullOrEmpty(Forwarder) && dictValue.Value == Forwarder) { return await XMCEXCEL(req.Id); } else { return await InnerBookingOrClosingEDI(req); } } #endregion /// /// 箱满仓生成excel文件 /// /// /// /// public async Task XMCEXCEL(long Id, bool flag = false) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); var order = tenantDb.Queryable().First(x => x.Id == Id); var edi = tenantDb.Queryable().First(x => x.BusinessId == Id); var ctn = tenantDb.Queryable().Where(x => x.BSNO == order.Id.ToString()).ToList(); #region 箱满仓生成excel文件 string fileName = String.Empty; //var opt = App.GetOptions(); var dirAbs = AppSetting.app(new string[] { "PrintTemplate", "BasePath" }); var relativePath = AppSetting.app(new string[] { "PrintTemplate", "RelativePath" }); if (string.IsNullOrEmpty(dirAbs)) { dirAbs = _environment.WebRootPath; } var fPath = "upload/printtemplate/箱满舱上传Excel模板.xls"; var fileAbsPath = Path.Combine(dirAbs, fPath); _logger.Info($"准备调用EXCEL"); var file = new FileStream(fileAbsPath, FileMode.Open); var excelwork = new HSSFWorkbook(file); var sheet = excelwork.GetSheetAt(0); for (int i = 0; i < sheet.LastRowNum; i++) { ////获取行 var row = sheet.GetRow(i); if (i == 0) { //委托编号 ICell cell = row.GetCell(5); if (cell != null) { row.Cells[5].SetCellValue(order.CustomerNo); } else { row.CreateCell(5).SetCellValue(order.CustomerNo); } } if (i == 1) { //场站 var yardid = order.Yard; if (!string.IsNullOrEmpty(yardid)) { ICell cell = row.GetCell(5); var yard = tenantDb.Queryable() .Where(x => x.Status == StatusEnum.Enable && x.Module == "XiangManCangEDI" && x.Code == yardid) .Select(x => x.MapCode).First(); if (cell != null) { row.Cells[5].SetCellValue(yard); } else { row.CreateCell(5).SetCellValue(yard); } } } if (i == 2) { //指定业务员 ICell cell = row.GetCell(5); if (cell != null) { row.Cells[5].SetCellValue(edi.XMCYWY); } else { row.CreateCell(5).SetCellValue(edi.XMCYWY); } } if (i == 3) { //提单号 ICell cell = row.GetCell(5); if (cell != null) { if (string.IsNullOrEmpty(order.MBLNO)) { row.Cells[5].SetCellValue(order.CustomerNo); } else { row.Cells[5].SetCellValue(order.MBLNO); } } else { if (string.IsNullOrEmpty(order.MBLNO)) { row.CreateCell(5).SetCellValue(order.CustomerNo); } else { row.CreateCell(5).SetCellValue(order.MBLNO); } } } if (i == 8) { //发货人 ICell cell = row.GetCell(1); var shipper = tenantDb.Queryable() .Where(x => x.Status == 0 && x.Id == order.ShipperId).First(); if (cell != null) { row.Cells[1].SetCellValue(shipper.ShortName); } else { row.CreateCell(1).SetCellValue(shipper.ShortName); } } if (i == 10) { //发货人代码 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.Shipper); } else { row.CreateCell(1).SetCellValue(order.Shipper); } } if (i == 11) { //收货人 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.Consignee); } else { row.CreateCell(1).SetCellValue(order.Consignee); } } if (i == 14) { //通知人 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.NotifyParty); } else { row.CreateCell(1).SetCellValue(order.NotifyParty); } } if (i == 17) { //第二通知人 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.SecondNotifyParty); } else { row.CreateCell(1).SetCellValue(order.SecondNotifyParty); } } if (i == 18) { //起运港国际五字代码 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.LoadPort); } else { row.CreateCell(1).SetCellValue(order.LoadPort); } var service = order.Service; //运输方式 ICell cell5 = row.GetCell(5); var serviceMap = tenantDb.Queryable() .Where(x => x.Status == StatusEnum.Enable && x.Module == "XiangManCangEDI" && x.Code == service).Select(x => x.MapCode).First(); if (cell5 != null) { row.Cells[5].SetCellValue(serviceMap); } else { row.CreateCell(5).SetCellValue(serviceMap); } } if (i == 19) { //卸货港国际五字代码 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.DischargePort); } else { row.CreateCell(1).SetCellValue(order.DischargePort); } } if (i == 20) { //交货地国际五字代码 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.Destination); } else { row.CreateCell(1).SetCellValue(order.Destination); } } if (i == 21) { //ETD if (order.ETD != null) { ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(Convert.ToDateTime(order.ETD).ToString("yyyy-MM-dd")); } else { row.CreateCell(1).SetCellValue(Convert.ToDateTime(order.ETD).ToString("yyyy-MM-dd")); } } //船名 ICell cell4 = row.GetCell(4); if (cell4 != null) { row.Cells[4].SetCellValue(order.Vessel); } else { row.CreateCell(4).SetCellValue(order.Vessel); } } if (i == 22) { //客户协约号 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.ContractNo); } else { row.CreateCell(1).SetCellValue(order.ContractNo); } } if (i == 23) { //航次 ICell cell = row.GetCell(4); if (cell != null) { row.Cells[4].SetCellValue(order.InnerVoyno); } else { row.CreateCell(4).SetCellValue(order.InnerVoyno); } } if (i == 26) { //唛头 ICell cell = row.GetCell(0); if (cell != null) { row.Cells[0].SetCellValue(order.Marks); } else { row.CreateCell(0).SetCellValue(order.Marks); } if (order.PKGS != null) { //件数 ICell cell1 = row.GetCell(1); if (cell1 != null) { row.Cells[1].SetCellValue(order.PKGS.ToString()); } else { row.CreateCell(1).SetCellValue(order.PKGS.ToString()); } } //包装 ICell cell2 = row.GetCell(2); if (cell2 != null) { row.Cells[2].SetCellValue(order.KindPkgs); } else { row.CreateCell(2).SetCellValue(order.KindPkgs); } //品名 ICell cell3 = row.GetCell(3); if (cell3 != null) { row.Cells[3].SetCellValue(order.Description); } else { row.CreateCell(3).SetCellValue(order.Description); } if (order.KGS != null) { //重量 ICell cell4 = row.GetCell(4); if (cell3 != null) { row.Cells[4].SetCellValue(order.KGS.ToString()); } else { row.CreateCell(4).SetCellValue(order.KGS.ToString()); } } if (order.CBM != null) { //尺码 ICell cell5 = row.GetCell(5); if (cell5 != null) { row.Cells[5].SetCellValue(order.CBM.ToString()); } else { row.CreateCell(5).SetCellValue(order.CBM.ToString()); } } } if (i == 39) { var c = ctn.DistinctBy(x => x.CtnAll).ToList(); var ctnAll = string.Empty; foreach (var item in c) { var ctnMap = tenantDb.Queryable() .Where(x => x.Status == StatusEnum.Enable && x.Module == "XiangManCangEDI" && x.Code == item.CtnCode).Select(x => x.MapCode).First(); ctnAll += $"{ctn.Where(x => x.CtnAll == item.CtnAll).Count()}*{ctnMap}+"; } ctnAll = ctnAll.Substring(0, ctnAll.Length - 1); //箱型箱量 ICell cell = row.GetCell(0); if (cell != null) { row.Cells[0].SetCellValue(ctnAll); } else { row.CreateCell(0).SetCellValue(ctnAll); } } if (i == 42) { //运费支付方式 var BLFRTCode = tenantDb.Queryable() .Where(x => x.Status == StatusEnum.Enable && x.FrtName == order.MBLFrt).Select(x => x.EdiCode).First(); var bl = string.Empty; if (!string.IsNullOrEmpty(BLFRTCode)) { bl = tenantDb.Queryable() .Where(x => x.Status == StatusEnum.Enable && x.Module == "XiangManCangEDI" && x.Code == BLFRTCode).Select(x => x.MapCode).First(); } ICell cell = row.GetCell(0); if (cell != null) { row.Cells[0].SetCellValue(bl); } else { row.CreateCell(0).SetCellValue(bl); } } if (i == 43) { //hscode ICell cell = row.GetCell(3); if (cell != null) { row.Cells[3].SetCellValue(order.HSCode); } else { row.CreateCell(3).SetCellValue(order.HSCode); } } if (i == 44) { var BLFRTCode = tenantDb.Queryable() .Where(x => x.Status == StatusEnum.Enable && x.FrtName == order.MBLFrt).Select(x => x.EdiCode).First(); var bl = string.Empty; if (!string.IsNullOrEmpty(BLFRTCode)) { bl = tenantDb.Queryable() .Where(x => x.Status == StatusEnum.Enable && x.Module == "XiangManCangEDI" && x.Code == BLFRTCode).Select(x => x.MapCode).First(); } if (bl == "预付") { //预付地点 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.PrepareAt); } else { row.CreateCell(1).SetCellValue(order.PrepareAt); } } else if ((bl == "到付")) { //预付地点 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.PayableAt); } else { row.CreateCell(1).SetCellValue(order.PayableAt); } } } if (i == 45) { //Name accout ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(edi.EmcNameAccount); } else { row.CreateCell(1).SetCellValue(edi.EmcNameAccount); } ICell _cell = row.GetCell(4); if (_cell != null) { row.Cells[4].SetCellValue(edi.EmcNameAccount); } else { row.CreateCell(4).SetCellValue(edi.EmcNameAccount); } } if (i == 47) { //Name accout ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.TemperatureSet); } else { row.CreateCell(1).SetCellValue(order.TemperatureSet); } //温度 ICell cell2 = row.GetCell(2); if (cell2 != null) { row.Cells[2].SetCellValue(order.ReeferQuantity); } else { row.CreateCell(2).SetCellValue(order.ReeferQuantity); } //湿度 ICell cell3 = row.GetCell(3); if (cell2 != null) { row.Cells[3].SetCellValue(order.Humidity); } else { row.CreateCell(3).SetCellValue(order.Humidity); } } if (i == 49) { //危险品编号 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.DangerNo); } else { row.CreateCell(1).SetCellValue(order.DangerNo); } } if (i == 50) { //订舱备注 ICell cell = row.GetCell(1); if (cell != null) { row.Cells[1].SetCellValue(order.BookingRemark); } else { row.CreateCell(1).SetCellValue(order.BookingRemark); } } } var fileFullPath = Path.Combine(_environment.WebRootPath, AppSetting.app(new string[] { "TempFile", "Path" }));//服务器路径 if (!Directory.Exists(fileFullPath)) { Directory.CreateDirectory(fileFullPath); } //2023-4-3,根据合川操作要求,文件名只带提单号 if (!string.IsNullOrEmpty(order.MBLNO)) { fileName = $"{DateTime.Now.Ticks}_{order.MBLNO}.xls";//名称 } else { fileName = $"{DateTime.Now.Ticks}_{order.MBLNO}.xls";//名称 } _logger.Info("导出excel:" + Path.Combine(fileFullPath, fileName)); var filestream = new FileStream(Path.Combine(fileFullPath, fileName), FileMode.OpenOrCreate, FileAccess.ReadWrite); excelwork.Write(filestream); #endregion if (flag) { filestream.Close(); filestream.Dispose(); var fpath = Path.Combine(fileFullPath, fileName); var fInfo = new FileInfo(fpath); _logger.Info("箱满仓文件地址:" + fpath + " " + fInfo); return new FileStreamResult(new FileStream(fpath, FileMode.Open), "application/octet-stream") { FileDownloadName = fInfo.Name }; } #region 调用爬虫接口 var url = db.Queryable().Filter(null, true).Where(x => x.Code == "xiangManCangPostUrl" && x.TenantId == 1288018625843826688).Select(x => x.Value).First(); if (string.IsNullOrEmpty(url)) { return await Task.FromResult(DataResult.Failed("未配置箱满仓请求地址,请联系管理员!")); } var account = tenantDb.Queryable().First(x => x.CustomerId == order.CarrierId && x.AccountType == "XiangManCang"); if (account == null) { return await Task.FromResult(DataResult.Failed("未配置箱满仓账号!")); } var key = db.Queryable().Filter(null, true).Where(x => x.Code == "billTraceNewUserKey" && x.TenantId == 1288018625843826688).Select(x => x.Value).First(); if (string.IsNullOrEmpty(key)) { return await Task.FromResult(DataResult.Failed("未获取到相关KEY,请联系管理员!")); } var secret = db.Queryable().Filter(null, true).Where(x => x.Code == "billTraceNewUserSecret" && x.TenantId == 1288018625843826688).Select(x => x.Value).First(); if (string.IsNullOrEmpty(secret)) { return await Task.FromResult(DataResult.Failed("未获取到相关SECRET,请联系管理员!")); } ////使用HttpClient方式上传文件 var carrier_code = db.Queryable().Where(x => x.Module == "HeChuan" && x.MapCode == order.Carrier).Select(x => x.Code).First(); string fn = string.Empty; using (var httpClient = new HttpClient()) { using (var request = new HttpRequestMessage(new HttpMethod("Post"), url)) { //request.Headers.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded"); var multipartContent = new MultipartFormDataContent(); multipartContent.Add(new StringContent("user_key"), key); multipartContent.Add(new StringContent("user_secret"), secret); multipartContent.Add(new StringContent("web_user"), account.AppKey); multipartContent.Add(new StringContent("web_psw"), account.AppSecret); multipartContent.Add(new StringContent("carrier_code"), carrier_code); multipartContent.Add(new StreamContent(filestream, (int)filestream.Length), "file", fileName); request.Content = multipartContent; var response = await httpClient.SendAsync(request); if (response.IsSuccessStatusCode) { var strRtn = response.Content.ReadAsStringAsync().Result; var jobj = strRtn.ToJObject(); if (jobj.GetIntValue("code") == 200) { fn = jobj.GetStringValue("msg"); } else { return await Task.FromResult(DataResult.Failed(jobj.GetStringValue("msg"))); } } } } //return fn; return await Task.FromResult(DataResult.Success(fn)); #endregion } #region 根据船公司ID获取EDI的路由枚举 /// /// 根据船公司ID获取EDI的路由枚举 /// /// 船公司ID /// /// 返回适用的路由枚举 private EDIRouteEnum GetEDIRoute(string carrierId, MappingCarrier ediRouteCfg) { EDIRouteEnum routeEnum = EDIRouteEnum.NULL; var tenantDb = saasService.GetBizDbScopeById(user.TenantId); //var ediRouteCfg = _cache.GetAllMappingCarrier().GetAwaiter().GetResult() // .FirstOrDefault(t => t.Module.Equals("BOOK_OR_CLOSING_RT", StringComparison.OrdinalIgnoreCase) // && t.Code.Equals(carrierId, StringComparison.OrdinalIgnoreCase)); if (ediRouteCfg != null && !string.IsNullOrWhiteSpace(ediRouteCfg.MapCode)) routeEnum = (EDIRouteEnum)System.Enum.Parse(typeof(EDIRouteEnum), ediRouteCfg.MapCode); //switch (carrierId.ToUpper()) //{ // case "PIL": // routeEnum = EDIRouteEnum.PIL; // break; // case "ONE": // routeEnum = EDIRouteEnum.YT; // break; // case "TSL": // routeEnum = EDIRouteEnum.TSL; // break; // case "YML": // routeEnum = EDIRouteEnum.YML; // break; // case "WY": // routeEnum = EDIRouteEnum.WY; // break; //} return routeEnum; } #endregion public async Task> InnerBookingOrClosingEDI(BookingOrClosingEDIOrderReq req) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); string batchNo = GuidHelper.NewGuidFormatN(); _logger.Info("批次={no}获取请求订舱、截单EDI {msg}", batchNo, JsonConvert.SerializeObject(req)); /* 发送订舱和截单EDI的流程 1、通过订单号获取订单信息。 2、检查订单的必填信息。 3、根据船公司ID获取对应的路由枚举。 4、获取EDI转换参数。(集装箱型号、包装方式) 5、读取EDI的配置信息,获取船公司相关的EDI配置。 6、检查详细信息。 7、生成订舱或者截单EDI报文,并返回文件保存绝对路径。 */ if (req.Id == 0) return DataResult.Failed($"订单Id不能为空"); var order = tenantDb.Queryable().First(x => x.Id == req.Id); if (order == null) return DataResult.Failed($"获取订单信息失败"); if (order.ParentId == 0) return DataResult.Failed($"获取当前订单为分单不能生成EDI信息"); var orderEDI = tenantDb.Queryable().First(x => x.BusinessId == req.Id); _logger.Info("批次={no}提取订单信息完成", batchNo); var ediExtModel = tenantDb.Queryable().First(x => x.BusinessId == req.Id); if (ediExtModel == null) return DataResult.Failed($"获取EDI信息失败"); _logger.Info("批次={no}提取订单EDI信息完成", batchNo); //箱信息 var contaList = tenantDb.Queryable().Where(x => x.BSNO == order.Id.ToString()).ToList(); var check = CheckBookingOrClosingEDI(order, contaList); if (!check.Succeeded) { return DataResult.Failed(check.Message); } var carrMap = tenantDb.Queryable().Where(t => t.Module.Equals("BOOK_OR_CLOSING_RT", StringComparison.OrdinalIgnoreCase) && t.LinkId == order.CarrierId) .First(); EDIRouteEnum ediRouteEnum = GetEDIRoute(order.Carrier, carrMap); if (ediRouteEnum == EDIRouteEnum.YT) { if (string.IsNullOrWhiteSpace(order.NoBill)) { return DataResult.Failed($"当前船公司{order.Carrier} EDI={ediRouteEnum.ToString()} 提单份数必填"); } } //部分船公司EDI需要填写操作英文名称,这里预先预警,其他船公司如果也需要可以再此追加 if (ediRouteEnum == EDIRouteEnum.TSL) { if (string.IsNullOrWhiteSpace(ediExtModel.OpEName)) return DataResult.Failed($"未填写(EDI并补充信息)操作英文名称"); } _logger.Info("批次={no} 获取EDI路由完成 路由={route}", batchNo, ediRouteEnum.ToString()); if (ediRouteEnum == EDIRouteEnum.NULL) return DataResult.Failed($"当前船公司没有对应的请求路由配置"); //这里船公司VOL的单子不能走此通道发送 if (ediRouteEnum == EDIRouteEnum.VOL) return DataResult.Failed($"当前船公司VOL不能执行标准发送"); //集装箱型 var ediCtnList = tenantDb.Queryable() .Where(t => t.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase) && t.CarrierId == order.CarrierId).ToList(); //包装 var ediPkgsList = tenantDb.Queryable() .Where(t => t.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase) && t.CarrierId == order.CarrierId).ToList(); //包装基础数据 var basePkgsList = tenantDb.Queryable().Where(x => x.Status == StatusEnum.Enable).ToList(); //EDI SO\SI代码 var ediSOSICfg = tenantDb.Queryable().First(t => t.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase) && t.LinkId == order.CarrierId); if (ediSOSICfg == null || string.IsNullOrWhiteSpace(ediSOSICfg.MapCode)) return DataResult.Failed($"CARRIERID={order.Carrier} 发送SO(SI)的船公司EDI代码未找到"); string postSpiderUrl = string.Empty; CodeThirdParty userWebAccountConfig = null; if (ediRouteEnum == EDIRouteEnum.TSL && req.Send) { if (req.SendType.Equals("E", StringComparison.OrdinalIgnoreCase)) return DataResult.Failed($"暂未提供TSL的截单发送"); postSpiderUrl = db.Queryable().Filter(null, true).Where(x => x.Code == CONST_TSL_EDI_URL && x.TenantId == 1288018625843826688).First().Value; if (string.IsNullOrWhiteSpace(postSpiderUrl)) return DataResult.Failed($"字典未配置 url_set->{CONST_TSL_EDI_URL} 请联系管理员"); //获取个人对应的账户,这里GetAccountConfig逻辑优先取个人,个人没有配置取公司对应配置 userWebAccountConfig = await tenantDb.Queryable().FirstAsync(x => x.AccountType == CONST_TSL_TYPE_CODE); _logger.Info("批次={no} 获取获取网站的账户完成,result={Num}", batchNo, JsonConvert.SerializeObject(userWebAccountConfig)); if (userWebAccountConfig == null) return DataResult.Failed($"未配置个人或公司网站账户,网站{CONST_TSL_TYPE_CODE}"); } var ediModel = new EDIBaseModel(); //2023-03-06 修改读取EDI配置方法,所有提取配置必须是已启用的EnableFlag=true,并且要根据SendType匹配发送类型,SendType=""表示使用订舱和截单,SO-订舱 SI-截单 var ftpSet = tenantDb.Queryable() .First(a => a.EdiTypeCode.Equals(ediRouteEnum.ToString(), StringComparison.OrdinalIgnoreCase) && a.CarrierId == order.CarrierId && a.Status == StatusEnum.Enable && (string.IsNullOrWhiteSpace(a.SendType) || (!string.IsNullOrWhiteSpace(a.SendType) && ((req.SendType == "B" && a.SendType == "SO") || (req.SendType == "E" && a.SendType == "SI"))))); if (ftpSet == null) return DataResult.Failed($"获取EDICODE={ediRouteEnum.ToString()}的EDI参数设置失败"); _logger.Info("批次={no} 获取EDI配置完成 路由={set}", batchNo, JsonConvert.SerializeObject(ftpSet)); ediModel.SENDCODE = ftpSet.SendCode; ediModel.SENDNAME = ftpSet.SendName; ediModel.RECEIVECODE = ftpSet.ReceiveCode; ediModel.SENDCOMPANYCODE = ftpSet.SendCompanyCode; ediModel.SENDSUBCOMPANYCODE = ftpSet.SendCompanyCode; ediModel.ALIASSENDCODE = ftpSet.AliasSendCode; ediModel.SENDSHIPPERCODE = ftpSet.SendShipperCode; ediModel.filetype = req.SendType; //订舱 ediModel.filerole = req.FileRole; //读取文件配置 //var fileCfg = App.GetOptions(); var basePath = AppSetting.app(new string[] { "FileSettings", "BasePath" }); string filePath = String.Empty; string relativePath = string.Empty; if (!req.Send) { var opt = AppSetting.app(new string[] { "TempFile", "Path" }); filePath = $"{Path.Combine(_environment.WebRootPath, opt)}\\{order.CustomerNo}";//服务器路径 } else { var cfgPath = AppSetting.app(new string[] { "FileSettings", "RelativePath" }); relativePath = $"{cfgPath}\\edifiles\\{order.CustomerNo}"; filePath = $"{(!string.IsNullOrWhiteSpace(basePath) ? basePath : _environment.WebRootPath)}\\{relativePath}"; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { relativePath = relativePath.Replace("\\", "/"); filePath = filePath.Replace("\\", "/"); } _logger.Info("批次={no} 生成文件保存路径完成 路由={filePath} 服务器系统={system}", batchNo, filePath, RuntimeInformation.OSDescription); //预先创建目录 if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } ediModel.filerpath = filePath; /* * 2023-03-08 这里根据最新的要求,不通过前台读取了,直接从配置读取 ediModel.UseForWarderCode = model.useForwarderCode; ediModel.ForWarderCode = model.forwarderCode; ediModel.ForWarderName = model.forwarderName; */ ediModel.ForWarderCode = ftpSet.SendCode; ediModel.ForWarderName = ftpSet.SendName; ediModel.BSLIST = new List(); //TODO 数据映射 var primaryModel = order.Adapt(); primaryModel = orderEDI.Adapt(); //航次取内部航次号 2023-04-03 合川操作确认这样调整 primaryModel.VOYNO = order.InnerVoyno; //航线信息直接取的航司航线(ESL用) primaryModel.ESLLINECODE = order.Lane; //起始港映射 var ediLoadPortList = tenantDb.Queryable() .Where(a => a.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase) && a.CarrierId == order.CarrierId).ToList(); //收货地 if (!string.IsNullOrWhiteSpace(primaryModel.PLACERECEIPTID)) { var currPortInfo = ediLoadPortList.FirstOrDefault(a => a.Code.Equals(primaryModel.PLACERECEIPTID, StringComparison.OrdinalIgnoreCase)); if (currPortInfo == null) return DataResult.Failed($"收货地{primaryModel.PLACERECEIPTID}的EDI代码未找到"); primaryModel.PLACERECEIPTID = currPortInfo.MapCode?.Trim(); } //装货港 if (!string.IsNullOrWhiteSpace(primaryModel.PORTLOADID)) { var currPortInfo = ediLoadPortList.FirstOrDefault(a => a.Code.Equals(primaryModel.PORTLOADID, StringComparison.OrdinalIgnoreCase)); if (currPortInfo == null) return DataResult.Failed($"装货港{primaryModel.PORTLOADID}的EDI代码未找到"); primaryModel.PORTLOADID = currPortInfo.MapCode?.Trim(); } //签单地点 if (!string.IsNullOrWhiteSpace(primaryModel.ISSUEPLACEID)) { var currPortInfo = ediLoadPortList.FirstOrDefault(a => a.Code.Equals(primaryModel.ISSUEPLACEID, StringComparison.OrdinalIgnoreCase)); if (currPortInfo == null) return DataResult.Failed($"签单地点{primaryModel.ISSUEPLACEID}的EDI代码未找到"); primaryModel.ISSUEPLACEID = currPortInfo.MapCode?.Trim(); } //预付地点 if (!string.IsNullOrWhiteSpace(primaryModel.PREPARDATID)) { var currPortInfo = ediLoadPortList.FirstOrDefault(a => a.Code.Equals(primaryModel.PREPARDATID, StringComparison.OrdinalIgnoreCase)); if (currPortInfo == null) return DataResult.Failed($"预付地点{primaryModel.PREPARDATID}的EDI代码未找到"); primaryModel.PREPARDATID = currPortInfo.MapCode?.Trim(); } //目的港基础 var portList = tenantDb.Queryable().Where(x => x.Status == StatusEnum.Enable).ToList(); //目的港映射 var ediPortList = tenantDb.Queryable() .Where(t => t.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase) && t.CarrierId == order.CarrierId).ToList(); //卸货港 if (!string.IsNullOrWhiteSpace(primaryModel.PORTDISCHARGEID)) { var sameList = portList.Where(a => !string.IsNullOrWhiteSpace(a.EdiCode) && a.EdiCode.Equals(primaryModel.PORTDISCHARGEID, StringComparison.OrdinalIgnoreCase)) .Select(a => a.PortName).ToList(); if (sameList == null || sameList.Count == 0) return DataResult.Failed($"卸货港{primaryModel.PORTDISCHARGEID}基础港口代码未找到"); var currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code) && a.CarrierId == order.CarrierId); if (currPortInfo == null) { currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code)); } if (currPortInfo == null) return DataResult.Failed($"卸货港{primaryModel.PORTDISCHARGEID}的EDI代码未找到"); primaryModel.PORTDISCHARGEID = currPortInfo.MapCode?.Trim(); } //中转港 if (!string.IsNullOrWhiteSpace(primaryModel.TRANSPORTID)) { var sameList = portList.Where(a => !string.IsNullOrWhiteSpace(a.EdiCode) && a.EdiCode.Equals(primaryModel.TRANSPORTID, StringComparison.OrdinalIgnoreCase)) .Select(a => a.PortName).ToList(); if (sameList == null || sameList.Count == 0) return DataResult.Failed($"中转港{primaryModel.TRANSPORTID}基础港口代码未找到"); var currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code) && a.CarrierId == order.CarrierId); if (currPortInfo == null) { currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code)); } if (currPortInfo == null) return DataResult.Failed($"中转港{primaryModel.TRANSPORTID}的EDI代码未找到"); primaryModel.TRANSPORTID = currPortInfo.MapCode?.Trim(); } //目的地 if (!string.IsNullOrWhiteSpace(primaryModel.DESTINATIONID)) { var sameList = portList.Where(a => !string.IsNullOrWhiteSpace(a.EdiCode) && a.EdiCode.Equals(primaryModel.DESTINATIONID, StringComparison.OrdinalIgnoreCase)) .Select(a => a.PortName?.Trim()).ToList(); if (sameList == null || sameList.Count == 0) return DataResult.Failed($"目的地{primaryModel.DESTINATIONID}基础港口代码未找到"); var currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code) && a.CarrierId == order.CarrierId); if (currPortInfo == null) { currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code)); } if (currPortInfo == null) return DataResult.Failed($"目的地{primaryModel.DESTINATIONID}的EDI代码未找到"); primaryModel.DESTINATIONID = currPortInfo.MapCode?.Trim(); } //交货地 if (!string.IsNullOrWhiteSpace(primaryModel.PLACEDELIVERYID)) { var sameList = portList.Where(a => !string.IsNullOrWhiteSpace(a.EdiCode) && a.EdiCode.Equals(primaryModel.PLACEDELIVERYID, StringComparison.OrdinalIgnoreCase)) .Select(a => a.PortName).ToList(); if (sameList == null || sameList.Count == 0) return DataResult.Failed($"交货地{primaryModel.PLACEDELIVERYID}基础港口代码未找到"); var currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code) && a.CarrierId == order.CarrierId); if (currPortInfo == null) { currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code)); } if (currPortInfo == null) return DataResult.Failed($"交货地{primaryModel.PLACEDELIVERYID}的EDI代码未找到"); primaryModel.PLACEDELIVERYID = currPortInfo.MapCode?.Trim(); } //到付地点 if (!string.IsNullOrWhiteSpace(primaryModel.PAYABLEATID)) { var sameList = portList.Where(a => !string.IsNullOrWhiteSpace(a.EdiCode) && a.EdiCode.Equals(primaryModel.PAYABLEATID, StringComparison.OrdinalIgnoreCase)) .Select(a => a.PortName).ToList(); if (sameList == null || sameList.Count == 0) return DataResult.Failed($"到付地点{primaryModel.PAYABLEATID}基础港口代码未找到"); var currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code) && a.CarrierId == order.CarrierId); if (currPortInfo == null) { currPortInfo = ediPortList.FirstOrDefault(a => sameList.Contains(a.Code)); } if (currPortInfo == null) return DataResult.Failed($"到付地点{primaryModel.PAYABLEATID}的EDI代码未找到"); primaryModel.PAYABLEATID = currPortInfo.MapCode?.Trim(); } //起运港是CNTAO并且船公司是太平需要判断场站EDI if (ediRouteEnum == EDIRouteEnum.WY) { //场站 var ediYardList = tenantDb.Queryable() .Where(t => t.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase)).ToList(); if (!string.IsNullOrWhiteSpace(order.Yard)) { var currYardInfo = ediYardList.FirstOrDefault(t => t.Code.Equals(order.Yard, StringComparison.OrdinalIgnoreCase)); if (currYardInfo == null) return DataResult.Failed($"场站{order.Yard}的EDI代码未找到"); primaryModel.YARDEDICODE = currYardInfo.MapCode?.Trim(); primaryModel.YARD = currYardInfo.MapName?.Trim(); } } //ESL、PIL、WY、YML、YT 需要付费方式映射EDI代码 if (ediRouteEnum == EDIRouteEnum.ESL || ediRouteEnum == EDIRouteEnum.PIL || ediRouteEnum == EDIRouteEnum.WY || ediRouteEnum == EDIRouteEnum.YML || ediRouteEnum == EDIRouteEnum.YT || ediRouteEnum == EDIRouteEnum.INTTRA) { //付费方式基础数据 var baseFrtList = tenantDb.Queryable().Where(x => x.Status == StatusEnum.Enable).ToList(); var baseFrtInfo = baseFrtList.FirstOrDefault(t => t.EdiCode.Equals(order.MBLFrt, StringComparison.OrdinalIgnoreCase)); if (baseFrtInfo == null) return DataResult.Failed($"付费方式{order.MBLFrt}的基础代码未找到"); //付费方式映射 var ediFrtList = tenantDb.Queryable() .Where(t => t.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase) && t.CarrierId == order.CarrierId).ToList(); if (!string.IsNullOrWhiteSpace(order.MBLFrt)) { var currFrtInfo = ediFrtList.FirstOrDefault(t => t.Code.Equals(baseFrtInfo.EdiCode, StringComparison.OrdinalIgnoreCase)); if (currFrtInfo == null) return DataResult.Failed($"付费方式{order.MBLFrt}的EDI代码未找到"); primaryModel.BLFRTEDICODE = currFrtInfo.MapCode?.Trim(); } } if (!string.IsNullOrWhiteSpace(order.Service)) { //运输条款EDI var baseServiceList = tenantDb.Queryable().Where(x => x.Status == StatusEnum.Enable).ToList(); var baseServiceInfo = baseServiceList.FirstOrDefault(t => t.EdiCode.Equals(order.Service, StringComparison.OrdinalIgnoreCase)); if (baseServiceInfo == null) return DataResult.Failed($"运输条款{order.Service}的基础代码未找到"); //运输条款映射 var ediServiceList = tenantDb.Queryable() .Where(t => t.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase) && t.CarrierId == order.CarrierId).ToList(); var currServiceInfo = ediServiceList.FirstOrDefault(t => t.Code.Equals(baseServiceInfo.EdiCode, StringComparison.OrdinalIgnoreCase)); if (currServiceInfo == null) return DataResult.Failed($"运输条款{order.Service}的EDI代码未找到"); primaryModel.SERVICEEDICODE = currServiceInfo.MapCode?.Trim(); } if (!string.IsNullOrWhiteSpace(order.IssueType)) { //签单方式EDI var baseIssueTypeList = tenantDb.Queryable().Where(x => x.Status == StatusEnum.Enable).ToList(); var baseIssueTypeInfo = baseIssueTypeList.FirstOrDefault(t => t.EnName.Equals(order.IssueType, StringComparison.OrdinalIgnoreCase)); if (baseIssueTypeInfo == null) return DataResult.Failed($"签单方式{order.IssueType}的基础代码未找到"); //签单方式映射 var ediIssueTypeList = tenantDb.Queryable() .Where(t => t.Module.Equals(CONST_MAPPING_MODULE, StringComparison.OrdinalIgnoreCase) ).ToList(); var currIssueTypeInfo = ediIssueTypeList.FirstOrDefault(t => t.CarrierId == order.CarrierId && t.Code.Equals(baseIssueTypeInfo.EdiCode, StringComparison.OrdinalIgnoreCase)); if (currIssueTypeInfo == null) { //如果没有对应的船司记录,则取默认的第一个代码对应的记录 currIssueTypeInfo = ediIssueTypeList.FirstOrDefault(t => t.Code.Equals(baseIssueTypeInfo.EdiCode, StringComparison.OrdinalIgnoreCase)); } if (currIssueTypeInfo == null) return DataResult.Failed($"签单方式{order.IssueType}的EDI代码未找到"); primaryModel.ISSUETYPE = currIssueTypeInfo.MapCode?.Trim().ToUpper(); } primaryModel.CARRIEREDICODE = ediSOSICfg.MapCode; //这里除了TSL,订舱编号默认都对应到业务编号(订舱保存时自动生成) if (ediRouteEnum == EDIRouteEnum.TSL) { if (string.IsNullOrWhiteSpace(order.CustomerNo)) return DataResult.Failed($"船公司是{order.CustomerNo} 订舱编号不能为空"); primaryModel.ORDERNO = order.CustomerNo; } else { primaryModel.ORDERNO = order.BookingNo; } //2023-06-15 按照沟通要求,如果主提单号为空,并且订舱编号不为空,可以去订舱编号填入主提单号 if (string.IsNullOrWhiteSpace(primaryModel.MBLNO)) { if (!string.IsNullOrWhiteSpace(order.CustomerNo)) { _logger.Info("批次={no} 主题单号为空 MBLNO={mblno} 取订舱编号补到主提单号 custno={custno}", batchNo, primaryModel.MBLNO, order.CustomerNo); if (req.SendType.Equals("B", StringComparison.OrdinalIgnoreCase)) { primaryModel.MBLNO = order.CustomerNo; } } } var curBasePkgs = basePkgsList.FirstOrDefault(p => p.PackageName.Equals(order.KindPkgs, StringComparison.OrdinalIgnoreCase)); if (curBasePkgs == null) return DataResult.Failed($"包装{order.KindPkgs}的基础数据代码未找到"); var ediPkgs = ediPkgsList.FirstOrDefault(x => x.Code.Equals(curBasePkgs.EdiCode, StringComparison.OrdinalIgnoreCase)); if (ediPkgs == null || string.IsNullOrWhiteSpace(ediPkgs.MapCode)) return DataResult.Failed($"包装{order.KindPkgs}的EDI代码未找到"); primaryModel.KINDPKGS_EDI_CODE = ediPkgs.MapCode?.Trim(); //这里是订舱时,默认取SOREMARK赋值到EDIREMARK if (req.SendType == "B") { primaryModel.EDIREMARK = order.EdiRemark; } primaryModel.S0CC0C = ediExtModel.S0CC0C; primaryModel.ACIHBL = ediExtModel.ACIHBL; primaryModel.MasterBOLIndicator = ediExtModel.MasterBolIndicator; primaryModel.ConsigneeEdiCode = ediExtModel.ConsigneeEdiCode; primaryModel.ShipperEdiCode = ediExtModel.ShipperEdiCode; primaryModel.SalesRepCode = ediExtModel.SalerCode; primaryModel.CNPTNo = ediExtModel.CNPTNo; //优先取订舱的EDI附属信息,为空取FTP配置 primaryModel.EDIATTN = ediExtModel.EDIAttn; if (string.IsNullOrWhiteSpace(primaryModel.EDIATTN)) { primaryModel.EDIATTN = ftpSet.SendAttn; } primaryModel.EDIATTNTEL = ediExtModel.EDIAttnTel; if (string.IsNullOrWhiteSpace(primaryModel.EDIATTNTEL)) { primaryModel.EDIATTNTEL = ftpSet.SendTel; } primaryModel.EDIATTNEMAIL = ediExtModel.EDIAttnMail; if (string.IsNullOrWhiteSpace(primaryModel.EDIATTNEMAIL)) { primaryModel.EDIATTNEMAIL = ftpSet.SendEmail; } primaryModel.AMSCONSIGNEE = ediExtModel.AMSConsignee; primaryModel.AMSNOTIFYPARTY = ediExtModel.AMSNotifyParty; primaryModel.OpEName = ediExtModel.OpEName; primaryModel.OpTel = ediExtModel.OpTel; primaryModel.OpEmail = ediExtModel.OpEmail; /* 2023-04-14 确认东胜流程后,这里调整商品名称取值,不从EDI扩展信息取,改为从主表的GOODS_CODE取代码经过品名翻译英文填写 注:仅限PIL //primaryModel.GOODSNAME = ediExtModel.GoodsName; */ if (ediRouteEnum == EDIRouteEnum.PIL) { if (req.SendType.Equals("E", StringComparison.OrdinalIgnoreCase)) { if (!string.IsNullOrWhiteSpace(order.GoodsName)) { if (order.GoodsId == 0) { return DataResult.Failed($"海运出口商品Id未回填!"); } var pGoods = tenantDb.Queryable().First(x => x.Id == order.GoodsId); if (pGoods == null) { _logger.Info("批次={no} 提取商品名称失败 GoodsName={code}", batchNo, order.GoodsName); return DataResult.Failed($"商品Id对应商品名称未找到!"); } else { primaryModel.GOODSNAME = pGoods.EnName; _logger.Info("批次={no} 提取商品名称失败 name={name}", batchNo, pGoods.GoodName); } } } else if (req.SendType.Equals("B", StringComparison.OrdinalIgnoreCase)) { //2023-05-17 PIL订舱时不提供GOODSNAME,这里默认赋空 primaryModel.GOODSNAME = string.Empty; } } primaryModel.cKHI = ediExtModel.CKHI; primaryModel.cNCM = ediExtModel.CNCM; primaryModel.wNCM = ediExtModel.WNCM; primaryModel.ORDERREMARK = ediExtModel.OrderRemark; //2023-05-10 (PIL)订舱的预抵日期不提供输入框,按照和川操作要求取开船日期填写到预抵日期 if (string.IsNullOrWhiteSpace(primaryModel.ETA) && !string.IsNullOrWhiteSpace(primaryModel.ETD) && ediRouteEnum == EDIRouteEnum.PIL) { primaryModel.ETA = primaryModel.ETD; } primaryModel.KINGTAREWEIGHT = ediExtModel.KingTareweight.HasValue ? ediExtModel.KingTareweight.Value : 0; _logger.Info("批次={no} 提取箱完成 数量={total}", batchNo, contaList.Count); primaryModel.CTNLIST = new List(); //集装箱 foreach (var conta in contaList) { //TODO 转换 var contaModel = conta.Adapt(); //EDI箱型 var currConta = ediCtnList.FirstOrDefault(x => x.Code.Equals(conta.CtnCode, StringComparison.OrdinalIgnoreCase)); if (currConta == null) return DataResult.Failed($"箱型{conta.CtnCode}的EDI代码未找到!"); contaModel.CTNALLCODE = currConta.MapCode; if (string.IsNullOrWhiteSpace(conta.KindPkgs)) return DataResult.Failed($"集装箱包装不能为空!"); var curContaBasePkgs = basePkgsList.FirstOrDefault(p => p.PackageName.Equals(conta.KindPkgs, StringComparison.OrdinalIgnoreCase)); if (curContaBasePkgs == null) return DataResult.Failed($"包装{conta.KindPkgs}的基础数据代码未找到!"); //EDI包装 var ediContaPkgs = ediPkgsList.FirstOrDefault(x => x.Code.Equals(curContaBasePkgs.EdiCode, StringComparison.OrdinalIgnoreCase)); if (currConta == null) return DataResult.Failed($"包装{conta.KindPkgs}的EDI代码未找到!"); contaModel.KINDPKGS_EDI_CODE = ediContaPkgs.MapCode?.Trim(); primaryModel.CTNLIST.Add(contaModel); } //多品名 var cargoList = tenantDb.Queryable().Where(t => contaList.Select(a => a.Id).ToArray().Contains(t.CtnId)).ToList(); _logger.Info("批次={no} 提取多品名完成 数量={total}", batchNo, cargoList.Count); primaryModel.CTNGOODSLIST = new List(); foreach (var cargo in cargoList) { //TODO 映射 var cargoModel = cargo.Adapt(); cargoModel.CNTRNO = contaList.FirstOrDefault(a => a.Id == cargo.CtnId).CntrNo; if (string.IsNullOrWhiteSpace(cargo.KindPkgs)) return DataResult.Failed($"多品名包装不能为空!"); var curCargoBasePkgs = basePkgsList.FirstOrDefault(p => p.PackageName.Equals(cargo.KindPkgs, StringComparison.OrdinalIgnoreCase)); if (curCargoBasePkgs == null) return DataResult.Failed($"包装{cargo.KindPkgs}的基础数据代码未找到"); var ediDetailPkgs = ediPkgsList.FirstOrDefault(x => x.Code.Equals(curCargoBasePkgs.EdiCode, StringComparison.OrdinalIgnoreCase)); if (ediDetailPkgs == null) return DataResult.Failed($"货明细的包装{cargo.KindPkgs}的EDI代码未找到"); cargoModel.KINDPKGS_EDI_CODE = ediDetailPkgs.MapCode?.Trim(); primaryModel.CTNGOODSLIST.Add(cargoModel); } ediModel.BSLIST.Add(primaryModel); var result = await InnerSendBookingOrClosingEDI(req, ediModel, ediRouteEnum); _logger.Info("批次={no} 生成EDI文件完成 结果={result}", batchNo, JsonConvert.SerializeObject(result)); if (!result.Succeeded) { return DataResult.Failed(result.Message); } if (order.Carrier.Equals("ONE", StringComparison.OrdinalIgnoreCase)) { //await PrintCarrierOneSOFileAsync(order); } if (req.Send) { /* 2023-05-24 这里新增TSL的判断,如果是走TSL则默认走吴广的外挂,需要提供个人账户 */ string currFilePath = string.Empty; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { currFilePath = System.Text.RegularExpressions.Regex.Match(result.ExtraData1.ToString(), relativePath.Replace("/", "\\/") + ".*").Value; } else { currFilePath = System.Text.RegularExpressions.Regex.Match(result.ExtraData1.ToString(), relativePath.Replace("\\", "\\\\") + ".*").Value; } string fileTypeCode = "edi"; string fileTypeName = "EDI文件"; if (req.SendType.Equals("E", StringComparison.OrdinalIgnoreCase)) { fileTypeCode = "esi"; fileTypeName = "ESI文件"; } //这里先写入附件表 await SaveEDIFile(req.Id, currFilePath, new System.IO.FileInfo(currFilePath).Name, fileTypeCode, fileTypeName); _logger.Info("批次={no} 直接发送FTP 文件访问地址={filepath}", batchNo, result.ExtraData1.ToString()); DateTime bDate = DateTime.Now; //是否发送邮件,EDI这里主要分2种通道发送 默认是FTP,如果配置里指定了接收接收邮箱,就需要推送邮件 bool isSendEmail = false; //上传FTP EdiDataResult sendStatus = null; //TSL单独走接口 if (ediRouteEnum == EDIRouteEnum.TSL) { sendStatus = await InnerSendBookingOrClosingEDIToPOST(result.ExtraData1.ToString(), postSpiderUrl, userWebAccountConfig); } else { //是订舱并且FTP配置了订舱接收邮箱则触发邮箱发送 if (ftpSet.SendType.Equals("SO", StringComparison.OrdinalIgnoreCase) && req.SendType.Equals("B", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(ftpSet.ReceiveEmail)) { isSendEmail = true; } else if (ftpSet.SendType.Equals("SI", StringComparison.OrdinalIgnoreCase) && req.SendType.Equals("E", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(ftpSet.ReceiveEmail)) { isSendEmail = true; } else if (string.IsNullOrWhiteSpace(ftpSet.SendType) && !string.IsNullOrWhiteSpace(ftpSet.ReceiveEmail)) { isSendEmail = true; } if (isSendEmail) { //推送订舱邮件 sendStatus = await InnerSendBookingOrClosingEDIToEmail(order, result.ExtraData1.ToString(), req.SendType, result.ExtraData2.ToString(), ftpSet); } else { sendStatus = await InnerSendBookingOrClosingEDIToFTP(result.ExtraData1.ToString(), ftpSet); } } DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.Info("批次={no} 发送完成,耗时:{timeDiff}ms. 结果{msg}", batchNo, timeDiff, sendStatus.Succeeded ? "成功" : "失败"); //var logId = await _bookinglog.InsertReturnSnowflakeIdAsync(new BookingLog //{ // Type = "Trace", // BookingId = model.Id, // TenantId = Convert.ToInt64(UserManager.TENANT_ID), // CreatedTime = DateTime.Now, // CreatedUserId = UserManager.UserId, // CreatedUserName = UserManager.Name //}); string sendTypeName = "FTP"; if (isSendEmail) { sendTypeName = "邮件"; } else if (ediRouteEnum == EDIRouteEnum.TSL) { sendTypeName = "POST"; } //await _bookinglogdetail.InsertReturnSnowflakeIdAsync(new BookingLogDetail //{ // PId = logId, // Field = String.Empty, // OldValue = String.Empty, // NewValue = $"发送 {order.CARRIERID} EDI 类型={model.sendType} 通过{sendTypeName} {(sendStatus.succ ? "成功" : "失败")}", //}); if (!sendStatus.Succeeded) { return DataResult.Failed($"发送失败,原因:{sendStatus.Message}"); } //截单 if (req.SendType.Equals("E", StringComparison.OrdinalIgnoreCase)) { //如果是截单需最后推送货物状态 await seaComService.SetGoodsStatus("JD", req.Id); //await SendBookingOrder(new long[] { req.Id }); } } return await Task.FromResult(DataResult.Success(result.ExtraData1.ToString())); //return result.ExtraData1.ToString(); } private async Task SaveEDIFile(long boookId, string FilePath, string fileName, string fileTypeCode = "edi", string fileTypeName = "EDI文件") { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); /* 直接将附件信息写入附件表 */ //EDI文件 var bookFile = new OpFile { FileName = fileName, FilePath = FilePath, TypeCode = fileTypeCode, TypeName = fileTypeName, LinkId = boookId, }; await tenantDb.Insertable(bookFile).ExecuteCommandAsync(); } #region 下载订舱、截单EDI /// /// 下载订舱、截单EDI /// /// /// public async Task DownloadBookingOrClosingEDI(BookingOrClosingEDIOrderReq req) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); var order = tenantDb.Queryable().First(x => x.Id == req.Id); var FORWARDER = order.Forwarder; var dictvalue = db.Queryable().InnerJoin((a, b) => a.TypeId == b.Id) .Where((a, b) => b.Code == "XiangManCang").Select((a, b) => a.Value).First(); _logger.Info("FORWARDER:" + FORWARDER + "dictvalue:" + dictvalue); if (!string.IsNullOrEmpty(FORWARDER) && dictvalue == FORWARDER) { return await XMCEXCEL(req.Id, true); } var filePath = InnerBookingOrClosingEDI(req).GetAwaiter().GetResult().Data; var fileInfo = new FileInfo(filePath); var result = new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileInfo.Name }; return result; } #endregion #region 检查订舱、截单EDI订单信息 /// /// 检查订舱、截单EDI订单信息 /// /// /// private DataResult CheckBookingOrClosingEDI(SeaExport order, List ctnList) { if (string.IsNullOrWhiteSpace(order.Carrier)) return DataResult.Failed("船公司必须填写!"); //if (string.IsNullOrWhiteSpace(order.OPID)) // throw Oops.Bah("未填写操作人"); if (string.IsNullOrWhiteSpace(order.KindPkgs)) return DataResult.Failed("包装种类未填写!"); //增加箱包装和主信息的包装是否一致校验 if (ctnList.Any(a => a.KindPkgs != order.KindPkgs)) { return DataResult.Failed("集装箱包装和订舱包装不一致,请修改!"); } //如果合同协议号不为空需要判断是否字符前、后有空格,不允许字符前后有空格,需要提示修改 if (!string.IsNullOrWhiteSpace(order.ContractNo)) { if (order.ContractNo.StartsWith(" ")) return DataResult.Failed("运费协议号前含有空格,请修改!"); if (order.ContractNo.EndsWith(" ")) return DataResult.Failed("运费协议号后含有空格,请修改!"); } //增加件、重、尺比对 if (ctnList != null && ctnList.Count > 0) { if (ctnList.Sum(a => a.PKGS.HasValue ? a.PKGS.Value : 0) != (order.PKGS.HasValue ? order.PKGS.Value : 0)) { return DataResult.Failed("集装箱件数合计和订舱件数不一致,请修改!"); } if (ctnList.Sum(a => a.KGS.HasValue ? a.KGS.Value : 0) != (order.KGS.HasValue ? order.KGS.Value : 0)) { return DataResult.Failed("集装箱重量合计和订舱重量不一致,请修改!"); } if (ctnList.Sum(a => a.CBM.HasValue ? a.CBM.Value : 0) != (order.CBM.HasValue ? order.CBM.Value : 0)) { return DataResult.Failed("集装箱尺码合计和订舱尺码不一致,请修改!"); } } return DataResult.Success("验证成功!"); } #endregion #region 上传邮件 /// /// 上传邮件 /// /// 订舱详情 /// 文件路径 /// 请求类型 /// EDI配置 /// 返回回执 private async Task InnerSendBookingOrClosingEDIToEmail(SeaExport bookingOrder, string filePath, string sendType, string emailTopic, CodeEdiSet ediCfg) { var result = new EdiDataResult { Succeeded = true }; var emailUrl = db.Queryable().Filter(null, true).Where(x => x.Code == "email_api_url" && x.TenantId == 1288018625843826688).First().Value; //var emailUrl = _cache.GetAllDictData().GetAwaiter().GetResult() // .FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == "email_api_url")?.Value; if (emailUrl == null) { result.Succeeded = false; result.Message = "系统参数配置email_api_url 请联系管理员"; return await Task.FromResult(result); } List emailList = new List(); EmailApiDto emailApiDto = new EmailApiDto { SendTo = ediCfg.ReceiveEmail, Title = emailTopic, Attaches = new List(), Body = emailTopic, }; System.IO.FileStream file = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read); int SplitSize = 5242880;//5M分片长度 int index = 1; //序号 第几片 long StartPosition = 5242880 * (index - 1); long lastLens = file.Length - StartPosition;//真不知道怎么起命了,就这样吧 if (lastLens < 5242880) { SplitSize = (int)lastLens; } byte[] heByte = new byte[SplitSize]; file.Seek(StartPosition, SeekOrigin.Begin); //第一个参数是 起始位置 file.Read(heByte, 0, SplitSize); //第三个参数是 读取长度(剩余长度) file.Close(); string base64Str = Convert.ToBase64String(heByte); emailApiDto.Attaches.Add(new AttachesInfo { AttachName = Path.GetFileName(filePath), AttachContent = base64Str }); emailList.Add(emailApiDto); string strJoin = System.IO.File.ReadAllText(filePath); DateTime bDate = DateTime.Now; string res = null; try { res = RequestHelper.Post(JsonConvert.SerializeObject(emailList), emailUrl); //res = await emailUrl.SetBody(emailList, "application/json").PostAsync(); } catch (Exception ex) { _logger.Info($"发送邮件异常:{ex.Message}"); } DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.Info($"邮件上传完成 上传文件大小:{heByte.Length} 用时:{timeDiff}ms.,{strJoin}"); _logger.Info($"发送邮件返回:{JsonConvert.SerializeObject(res)}"); //if (res != null && res.StatusCode == System.Net.HttpStatusCode.OK) //{ // var userResult = await res.Content.ReadAsStringAsync(); // var respObj = JsonConvert.DeserializeAnonymousType(userResult, new // { // Success = false, // Message = string.Empty, // Code = -9999, // }); // result.Succeeded = respObj.Success; // result.Message = respObj.Message; //} if (res != null) { var respObj = JsonConvert.DeserializeAnonymousType(res, new { Success = false, Message = string.Empty, Code = -9999, }); result.Succeeded = respObj.Success; result.Message = respObj.Message; } return await Task.FromResult(result); //return result; } #endregion #region 上传FTP /// /// 上传FTP /// /// EDI文件路径 /// FTP配置 /// 返回回执 private async Task InnerSendBookingOrClosingEDIToFTP(string filePath, CodeEdiSet ediCfg) { EdiDataResult result = new EdiDataResult { Succeeded = true }; CancellationTokenSource cts = new CancellationTokenSource(); string host = string.Empty; string port = string.Empty; if (ediCfg.ServerIp.IndexOf(":") >= 0) { host = ediCfg.ServerIp.Split(new char[] { ':' }).FirstOrDefault().Trim(); port = ediCfg.ServerIp.Split(new char[] { ':' }).Last()?.Trim(); } NameValueCollection par = new NameValueCollection(); par.Add("host", host); //这里如果配置没有指定端口号默认是21端口 par.Add("port", string.IsNullOrWhiteSpace(port) ? "21" : port); par.Add("username", ediCfg.UserName); par.Add("pwd", ediCfg.Password); par.Add("path", ediCfg.FolderName); var ftpSpiderUrl = db.Queryable().Filter(null, true).Where(x => x.Code == "booking_edi_ftp_server" && x.TenantId == 1288018625843826688).First().Value; if (ftpSpiderUrl == null) return await Task.FromResult(EdiDataResult.Failed("系统未配置booking_edi_ftp_server 请联系管理员!")); //var fileInfo = new FileInfo(filePath); _logger.Info($"准备请求发送ftp:{ftpSpiderUrl} ,参数:{JsonConvert.SerializeObject(par)},文件:{filePath}"); System.IO.FileStream file = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read); int SplitSize = 5242880;//5M分片长度 int index = 1; //序号 第几片 long StartPosition = 5242880 * (index - 1); long lastLens = file.Length - StartPosition;//真不知道怎么起命了,就这样吧 if (lastLens < 5242880) { SplitSize = (int)lastLens; } byte[] heByte = new byte[SplitSize]; file.Seek(StartPosition, SeekOrigin.Begin); //第一个参数是 起始位置 file.Read(heByte, 0, SplitSize); //第三个参数是 读取长度(剩余长度) file.Close(); string strJoin = System.IO.File.ReadAllText(filePath); DateTime bDate = DateTime.Now; _logger.Info("FTP 开始上传"); var res = FTPHelper.TransmitFtpFile(ftpSpiderUrl, par, new { file = "file", fileName = Path.GetFileName(filePath), fileBytes = heByte }); DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.Info($"FTP 上传完成 上传文件大小:{heByte.Length} 用时:{timeDiff}ms.,{strJoin}"); _logger.Info($"发送ftp返回:{res}"); var jobjRetn = JObject.Parse(res); if (jobjRetn.GetStringValue("status") != "1") { result.Succeeded = false; result.Message = jobjRetn.GetStringValue("message"); } return await Task.FromResult(result); //return result; } #endregion /// /// EDI发送POST请求 /// /// 文件路径 /// 请求URL /// 配置账户 /// 返回回执 private async Task InnerSendBookingOrClosingEDIToPOST(string filePath, string url, CodeThirdParty accountConfig) { CancellationTokenSource cts = new CancellationTokenSource(); var userKey = db.Queryable().Filter(null, true).Where(x => x.Code == "BCOrDraftUserKey" && x.TenantId == 1288018625843826688).First(); var userPwd = db.Queryable().Filter(null, true).Where(x => x.Code == "BCOrDraftUserSecret" && x.TenantId == 1288018625843826688).First(); if (userKey.IsNull()) { return await Task.FromResult(EdiDataResult.Failed("请配置相关账号!")); } if (userPwd.IsNull()) { return await Task.FromResult(EdiDataResult.Failed("请配置相关密钥!")); } NameValueCollection par = new NameValueCollection(); //par.Add("user_key", App.Configuration["BCOrDraftUserKey"]); //par.Add("user_secret", App.Configuration["BCOrDraftUserSecret"]); par.Add("user_key", userKey.Value); par.Add("user_secret", userPwd.Value); par.Add("web_user", accountConfig.AppKey?.Trim()); par.Add("web_psw", accountConfig.AppSecret?.Trim()); _logger.Info($"准备请求发送POST:{url} ,参数:{JsonConvert.SerializeObject(par)},文件:{filePath}"); System.IO.FileStream file = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read); int SplitSize = 5242880;//5M分片长度 int index = 1; //序号 第几片 long StartPosition = 5242880 * (index - 1); long lastLens = file.Length - StartPosition;//真不知道怎么起命了,就这样吧 if (lastLens < 5242880) { SplitSize = (int)lastLens; } byte[] heByte = new byte[SplitSize]; file.Seek(StartPosition, SeekOrigin.Begin); //第一个参数是 起始位置 file.Read(heByte, 0, SplitSize); //第三个参数是 读取长度(剩余长度) file.Close(); string strJoin = System.IO.File.ReadAllText(filePath); DateTime bDate = DateTime.Now; _logger.Info("POST 开始上传"); var res = CommonFTPHelper.TransmitFtpFile(url, par, new { file = "file", fileName = Path.GetFileName(filePath), fileBytes = heByte }); DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.Info($"请求POST 上传完成 上传文件大小:{heByte.Length} 用时:{timeDiff}ms.,{strJoin}"); _logger.Info($"发送POST返回:{res}"); var jobjRetn = JObject.Parse(res); if (jobjRetn.GetStringValue("code") != "200") { return await Task.FromResult(EdiDataResult.Failed(jobjRetn.GetStringValue("msg"))); } else { return await Task.FromResult(EdiDataResult.Success("请求成功!")); } } #region 触发订舱 /// /// 触发订舱 /// /// /// /// /// private async Task InnerSendBookingOrClosingEDI(BookingOrClosingEDIOrderReq req, EDIBaseModel ediModel, EDIRouteEnum ediRouteEnum) { var result = new EdiDataResult(); var tenantDb = saasService.GetBizDbScopeById(user.TenantId); try { if (ediRouteEnum == EDIRouteEnum.PIL) { #region PIL string strCheck = PILEdiHelper.IsCreatePILEDI(ediModel); _logger.Info($"调用SO(SI),校验:{strCheck},数据对象:{JsonConvert.SerializeObject(ediModel)}"); if (!string.IsNullOrWhiteSpace(strCheck)) { if (Regex.IsMatch(strCheck, "\\")) { strCheck = Regex.Replace(strCheck, "\\", "\n"); } throw new Exception($"发送{EDIRouteEnum.PIL.ToString()}校验失败,{strCheck}"); } var currRlt = PILEdiHelper.CreateEdiPIL(ediModel); #endregion result.Succeeded = currRlt.Succeeded; result.ExtraData1 = currRlt.Succeeded ? currRlt.ExtraData1.ToString() : ""; result.ExtraData2 = currRlt.Succeeded ? currRlt.ExtraData2.ToString() : ""; //return await Task.FromResult(currRlt); } else if (ediRouteEnum == EDIRouteEnum.TSL) { #region TSL string strCheck = TSLEdiHelper.IsCreateTSL(ediModel); _logger.Info($"调用SO(SI),校验:{strCheck},数据对象:{JsonConvert.SerializeObject(ediModel)}"); if (!string.IsNullOrWhiteSpace(strCheck)) { if (Regex.IsMatch(strCheck, "\\")) { strCheck = Regex.Replace(strCheck, "\\", "\n"); } throw new Exception($"发送{EDIRouteEnum.TSL.ToString()}校验失败,{strCheck}"); } var currRlt = new EdiDataResult(); if (req.SendType == "B") { currRlt = TSLEdiHelper.CreateEdiTSL(ediModel); } else if (req.SendType == "E") { currRlt = TSLEdiHelper.CreateEdiTSLSI(ediModel); } #endregion result.Succeeded = currRlt.Succeeded; result.ExtraData1 = currRlt.Succeeded ? currRlt.ExtraData1.ToString() : ""; } else if (ediRouteEnum == EDIRouteEnum.WY) { #region WY string strCheck = WYEdiHelper.IsCreateWYEDI(ediModel); _logger.Info($"调用SO(SI),校验:{strCheck},数据对象:{JsonConvert.SerializeObject(ediModel)}"); if (!string.IsNullOrWhiteSpace(strCheck)) { if (Regex.IsMatch(strCheck, "\\")) { strCheck = Regex.Replace(strCheck, "\\", "\n"); } throw new Exception($"发送{EDIRouteEnum.WY.ToString()}校验失败,{strCheck}"); } var currRlt = WYEdiHelper.CreateEdiWY(ediModel); #endregion result.Succeeded = currRlt.Succeeded; result.ExtraData1 = currRlt.Succeeded ? currRlt.ExtraData1.ToString() : ""; } else if (ediRouteEnum == EDIRouteEnum.YML) { #region YML string strCheck = YMLEdiHelper.IsCreateYMLEDI(ediModel); _logger.Info($"调用SO(SI),校验:{strCheck},数据对象:{JsonConvert.SerializeObject(ediModel)}"); if (!string.IsNullOrWhiteSpace(strCheck)) { if (Regex.IsMatch(strCheck, "\\")) { strCheck = Regex.Replace(strCheck, "\\", "\n"); } throw new Exception($"发送{EDIRouteEnum.YML.ToString()}校验失败,{strCheck}"); } var currRlt = new EdiDataResult(); if (req.SendType == "B") { currRlt = YMLEdiHelper.CreateEdiYML(ediModel); } else if (req.SendType == "E") { currRlt = YMLEdiHelper.CreateEdiYMLSI(ediModel); } #endregion result.Succeeded = currRlt.Succeeded; result.ExtraData1 = currRlt.Succeeded ? currRlt.ExtraData1.ToString() : ""; } else if (ediRouteEnum == EDIRouteEnum.YT) { #region YT string strCheck = YTEdiHelper.IsCreateYTEDI(ediModel); _logger.Info($"调用SO(SI),校验:{strCheck},数据对象:{JsonConvert.SerializeObject(ediModel)}"); if (!string.IsNullOrWhiteSpace(strCheck)) { if (Regex.IsMatch(strCheck, "\\")) { strCheck = Regex.Replace(strCheck, "\\", "\n"); } throw new Exception($"发送{EDIRouteEnum.YT.ToString()}校验失败,{strCheck}"); } var currRlt = YTEdiHelper.CreateEdiYT(ediModel); #endregion result.Succeeded = currRlt.Succeeded; result.ExtraData1 = currRlt.Succeeded ? currRlt.ExtraData1.ToString() : ""; } else if (ediRouteEnum == EDIRouteEnum.ESL) { #region ESL string strCheck = ESLEdiHelper.IsCreateESLEDI(ediModel); _logger.Info($"调用SO(SI),校验:{strCheck},数据对象:{JsonConvert.SerializeObject(ediModel)}"); if (!string.IsNullOrWhiteSpace(strCheck)) { if (Regex.IsMatch(strCheck, "\\")) { strCheck = Regex.Replace(strCheck, "\\", "\n"); } throw new Exception($"发送{EDIRouteEnum.ESL.ToString()}校验失败,{strCheck}"); } var currRlt = ESLEdiHelper.CreateEdiESL(ediModel); #endregion result.Succeeded = currRlt.Succeeded; result.ExtraData1 = currRlt.Succeeded ? currRlt.ExtraData1.ToString() : ""; } else if (ediRouteEnum == EDIRouteEnum.MELL) { #region MELL string strCheck = MellEdiHelper.IsCreatePILMELL(ediModel); _logger.Info($"调用SO(SI),校验:{strCheck},数据对象:{JsonConvert.SerializeObject(ediModel)}"); if (!string.IsNullOrWhiteSpace(strCheck)) { if (Regex.IsMatch(strCheck, "\\")) { strCheck = Regex.Replace(strCheck, "\\", "\n"); } throw new Exception($"发送{EDIRouteEnum.MELL.ToString()}校验失败,{strCheck}"); } var currRlt = MellEdiHelper.CreateEdiPILMELL(ediModel); #endregion result.Succeeded = currRlt.Succeeded; result.ExtraData1 = currRlt.Succeeded ? currRlt.ExtraData1.ToString() : ""; result.ExtraData2 = currRlt.Succeeded ? currRlt.ExtraData2.ToString() : ""; } else if (ediRouteEnum == EDIRouteEnum.INTTRA) { //这里INTTRA单独取了船公司 var ediSOSICfg = tenantDb.Queryable().First(t => t.Module.Equals(CONST_MAPPING_MODULE_INTTRA, StringComparison.OrdinalIgnoreCase) && t.Code == ediModel.BSLIST.FirstOrDefault().CARRIERID); if (ediSOSICfg == null || string.IsNullOrWhiteSpace(ediSOSICfg.MapCode)) throw new Exception($"CARRIERID={ediModel.BSLIST.FirstOrDefault().CARRIERID} INTTRA EDI订舱和截单 的船公司EDI代码未找到"); ediModel.BSLIST.FirstOrDefault().CARRIEREDICODE = ediSOSICfg.MapCode; #region INTTRA string strCheck = InttraEdiHelper.IsCreateINTTR(ediModel); _logger.Info($"调用SO(SI),校验:{strCheck},数据对象:{JsonConvert.SerializeObject(ediModel)}"); if (!string.IsNullOrWhiteSpace(strCheck)) { if (Regex.IsMatch(strCheck, "\\")) { strCheck = Regex.Replace(strCheck, "\\", "\n"); } throw new Exception($"发送{EDIRouteEnum.INTTRA.ToString()}校验失败,{strCheck}"); } var currRlt = new EdiDataResult(); if (req.SendType == "B") { currRlt = InttraEdiHelper.CreateEdiINTTR(ediModel); } else if (req.SendType == "E") { currRlt = InttraEdiHelper.CreateEdiINTTRSI(ediModel); } #endregion result.Succeeded = currRlt.Succeeded; result.ExtraData1 = currRlt.Succeeded ? currRlt.ExtraData1.ToString() : ""; } } catch (Exception ex) { result.Succeeded = false; result.Message = ex.Message; } return result; } #endregion } }