修改VOLTA 发送截单功能

optimize
jianghaiqing 1 year ago
parent 91abf2969e
commit 2078b17d74

@ -129,6 +129,16 @@ namespace Myshipping.Application
/// 文件路径
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 船名
/// </summary>
public string Vessel { get; set; }
/// <summary>
/// 航次号
/// </summary>
public string VoyNo { get; set; }
}
/// <summary>

@ -16,7 +16,7 @@ namespace Myshipping.Application.EDI.VOLTA
/// <summary>
/// VOLTA EDI帮助类
/// </summary>
public class VOLTAEdiHelper
public static class VOLTAEdiHelper
{
#region 生成VOLTA申报报文截单
/// <summary>
@ -37,7 +37,15 @@ namespace Myshipping.Application.EDI.VOLTA
string bno = model.BookingId;
string filename = model.FilePath + "\\" + bno + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".txt";
string filePath = model.FilePath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmssfff");
//预先创建目录
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
string filename = filePath + "\\" + bno + ".txt";
//如果是部署linux需要修改路径
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
@ -54,15 +62,21 @@ namespace Myshipping.Application.EDI.VOLTA
//发货人
r.WriteLine("<spr>" + model.ShpperName + "</spr>");
//发货人地址
r.WriteLine("<sad>" + model.ShpperAddr + "</sad>");
r.WriteLine("<sad>");
r.WriteLine(model.ShpperAddr);
r.WriteLine("</sad>");
//收货人
r.WriteLine("<cne>" + model.ConsigneeName + "</cne>");
//收货人地址
r.WriteLine("<cad>" + model.ConsigneeAddr + "</cad>");
r.WriteLine("<cad>");
r.WriteLine(model.ConsigneeAddr);
r.WriteLine("</cad>");
//通知人
r.WriteLine("<nfy>" + model.NotifyName + "</nfy>");
//通知人地址
r.WriteLine("<nad>" + model.NotifyAddr + "</nad>");
r.WriteLine("<nad>");
r.WriteLine(model.NotifyAddr);
r.WriteLine("</nad>");
//通知人1
if (!string.IsNullOrWhiteSpace(model.NotifySecondName))
{
@ -75,7 +89,9 @@ namespace Myshipping.Application.EDI.VOLTA
//通知人1地址
if (!string.IsNullOrWhiteSpace(model.NotifySecondName))
{
r.WriteLine("<na1>" + model.ConsigneeAddr + "</na1>");
r.WriteLine("<na1>");
r.WriteLine(model.ConsigneeAddr);
r.WriteLine("</na1>");
}
else
{
@ -107,19 +123,28 @@ namespace Myshipping.Application.EDI.VOLTA
//EDNumber
r.WriteLine("<edn></edn>");
//货描
r.WriteLine("<des>" + model.CargoDescription + "</des>");
r.WriteLine("<des>");
r.WriteLine(model.CargoDescription);
r.WriteLine("</des>");
//唛头
r.WriteLine("<cmn>" + model.Marks + "</cmn>");
r.WriteLine("<cmn>");
r.WriteLine(model.Marks);
r.WriteLine("</cmn>");
//模板版本号
r.WriteLine("<ver>" + model.TemplateVersion + "</ver>");
r.WriteLine("<ver>");
r.WriteLine(model.TemplateVersion);
r.WriteLine("</ver>");
//箱明细
r.WriteLine("<cnt>"+ GetContaInfo(model.ContaList) + "</cnt>");
r.WriteLine("<cnt>");
r.Write(GetContaInfo(model.ContaList));
r.WriteLine("</cnt>");
r.Close();
f.Close();
result.succ = true;
result.extra = filename;
result.extra2 = $"样本提单:{model.Vessel} {model.VoyNo} {model.BookingId}";
}
catch(Exception ex)
{
@ -149,7 +174,7 @@ namespace Myshipping.Application.EDI.VOLTA
contaList.ForEach(ctn =>
{
//箱拼接格式:序号~箱号~铅封号~Custom Seal No~毛重~净重~尺码~重量单位~~件数~~~包装
txtBuilder.AppendLine($"{ctn.SNo}~{ctn.ContaNo}~{ctn.SealNo}~~{ctn.GWt.Value.ToString("0.###")}~{(ctn.NWt.HasValue ? ctn.NWt.Value.ToString("0.###") : "")}~{ctn.CBM.Value.ToString("0.###")}~{ctn.WTUnit}~{ctn.Qty.Value.ToString("#.###")}~~~{ctn.Pkgs}");
txtBuilder.AppendLine($"{ctn.SNo}~{ctn.ContaNo}~{ctn.SealNo}~~{ctn.GWt.Value.ToString("0.###")}~{(ctn.NWt.HasValue ? ctn.NWt.Value.ToString("0.###") : "")}~{ctn.CBM.Value.ToString("0.###")}~{ctn.WTUnit}~{ctn.Qty.Value.ToString("#.###")}~~~{ctn.EdiPkgs}");
});
}
@ -244,7 +269,7 @@ namespace Myshipping.Application.EDI.VOLTA
if (!string.IsNullOrEmpty(model.CargoDescription))
{
if (model.NotifySecondAddr.Length > 3000)
if (model.CargoDescription.Length > 3000)
msgBuilder.AppendLine("品名不能大于3000个字符");
}
@ -286,11 +311,6 @@ namespace Myshipping.Application.EDI.VOLTA
ctnMsgBuilder.Append("毛重不能为空;");
}
if (!ctn.NWt.HasValue)
{
ctnMsgBuilder.Append("净重不能为空;");
}
if (!ctn.CBM.HasValue)
{
ctnMsgBuilder.Append("尺寸不能为空;");
@ -301,7 +321,7 @@ namespace Myshipping.Application.EDI.VOLTA
ctnMsgBuilder.Append("件数不能为空;");
}
if (string.IsNullOrWhiteSpace(ctn.Pkgs))
if (string.IsNullOrWhiteSpace(ctn.EdiPkgs))
{
ctnMsgBuilder.Append("包装不能为空;");
}

@ -79,6 +79,7 @@ using System.Collections;
using System.Security.Principal;
using Myshipping.Core.Const;
using ICSharpCode.SharpZipLib.BZip2;
using Myshipping.Application.EDI.VOLTA;
namespace Myshipping.Application
{
@ -9940,7 +9941,7 @@ namespace Myshipping.Application
*/
string batchNo = IDGen.NextID().ToString();
_logger.LogInformation("批次={no}获取请求VOLTA截单EDI {msg}", batchNo, JSON.Serialize(model));
_logger.LogInformation("批次={no}获取请求VOLTA截单详情 {msg}", batchNo, JSON.Serialize(model));
if (!model.sendType.Equals("E", StringComparison.OrdinalIgnoreCase))
{
@ -10001,12 +10002,62 @@ namespace Myshipping.Application
}
#endregion
if (voltaModel.CargoDescription.EndsWith("\n"))
voltaModel.CargoDescription = voltaModel.CargoDescription.Substring(0, voltaModel.CargoDescription.Length - 1);
if (voltaModel != null)
voltaModel.ContaList = contaList.Adapt<List<VOLTAEDIContaModel>>();
StringBuilder pkgsBuilder = new StringBuilder();
//还需要翻译箱明细的包装
if (voltaModel.ContaList != null && voltaModel.ContaList.Count > 0)
{
List<string> origPkgsList = voltaModel.ContaList.Select(x => x.Pkgs).Distinct().ToList();
//包装基础数据
var basePkgsList = _cache.GetAllCodePackage().GetAwaiter().GetResult();
var ediPkgsList = _cache.GetAllMappingPackage().GetAwaiter().GetResult()
.Where(t => t.Module.Equals(CONST_MAPPING_MODULE_VOLTA, StringComparison.OrdinalIgnoreCase)
&& !string.IsNullOrWhiteSpace(t.CarrierCode) && t.CarrierCode.Equals(order.CARRIERID, StringComparison.OrdinalIgnoreCase))
.ToList();
int startNo = 1;
voltaModel.ContaList.ForEach(x =>
{
x.SNo = startNo;
var curBasePkgs = basePkgsList.FirstOrDefault(p => p.Name.Equals(x.Pkgs, StringComparison.OrdinalIgnoreCase));
if (curBasePkgs == null)
pkgsBuilder.Append($"包装{x.Pkgs}的基础数据代码未找到");
if (curBasePkgs != null)
{
var ediPkgs = ediPkgsList.FirstOrDefault(x => x.Code.Equals(curBasePkgs.Code, StringComparison.OrdinalIgnoreCase));
if (ediPkgs == null || string.IsNullOrWhiteSpace(ediPkgs.MapCode))
pkgsBuilder.AppendLine($"包装{x.Pkgs}的EDI代码未找到");
if(ediPkgs != null)
{
x.EdiPkgs = ediPkgs.MapCode?.Trim();
}
}
if (!string.IsNullOrWhiteSpace(x.EdiPkgs))
x.EdiPkgs = string.Empty;
startNo++;
});
}
if(pkgsBuilder.Length > 0)
{
_logger.LogInformation("批次={no}获取请求VOLTA截单详情有错误 {msg}", batchNo, JSON.Serialize(model));
result.msg = pkgsBuilder.ToString();
}
result.succ = true;
result.extra = voltaModel;
@ -10023,11 +10074,7 @@ namespace Myshipping.Application
[HttpPost("/BookingOrder/SendVOLTAEdiSI")]
public async Task<dynamic> SendVOLTAEdiSI(VOLTAEDIBaseModel model)
{
CommonWebApiResult result = new CommonWebApiResult();
return result;
return await InnerVOLTAEDI(model, true);
}
#endregion
@ -10054,9 +10101,10 @@ namespace Myshipping.Application
/// 生成VOLTA报文内部方法
/// </summary>
/// <param name="model">请求截单详情</param>
/// <param name="isSend">是否直接发送VOLTA申报截单</param>
/// <returns>返回回执</returns>
[NonAction]
public async Task<dynamic> InnerVOLTAEDI(VOLTAEDIBaseModel model)
public async Task<dynamic> InnerVOLTAEDI(VOLTAEDIBaseModel model,bool isSend = false)
{
CommonWebApiResult result = new CommonWebApiResult();
@ -10087,7 +10135,137 @@ namespace Myshipping.Application
if (ediRouteEnum == EDIRouteEnum.NULL)
throw Oops.Bah($"当前船公司没有对应的请求路由配置");
return result;
var ftpSet = _cache.GetAllEdiSetting().GetAwaiter().GetResult()
.FirstOrDefault(a => a.EDICODE.Equals(ediRouteEnum.ToString(), StringComparison.OrdinalIgnoreCase)
&& a.TenantId == order.TenantId && !string.IsNullOrWhiteSpace(a.CARRIERID)
&& a.CARRIERID.Equals(order.CARRIERID, StringComparison.OrdinalIgnoreCase)
&& a.EnableFlag
&& (string.IsNullOrWhiteSpace(a.SendType) ||
(!string.IsNullOrWhiteSpace(a.SendType) && a.SendType == "SI")));
if (ftpSet == null)
throw Oops.Bah($"获取EDICODE={ediRouteEnum.ToString()}的EDI参数设置失败");
//读取文件配置
var fileCfg = App.GetOptions<BookingAttachOptions>();
string filePath = String.Empty;
string relativePath = string.Empty;
if (!isSend)
{
var opt = App.GetOptions<TempFileOptions>().Path;
filePath = $"{Path.Combine(App.WebHostEnvironment.WebRootPath, opt)}\\{order.BOOKINGNO}";//服务器路径
}
else
{
relativePath = $"{fileCfg.relativePath}\\edifiles\\{order.BOOKINGNO}";
filePath = $"{(!string.IsNullOrWhiteSpace(fileCfg.basePath) ? fileCfg.basePath : App.WebHostEnvironment.WebRootPath)}\\{relativePath}";
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
relativePath = relativePath.Replace("\\", "/");
filePath = filePath.Replace("\\", "/");
}
_logger.LogInformation("批次={no} 生成文件保存路径完成 路由={filePath} 服务器系统={system}", batchNo, filePath, RuntimeInformation.OSDescription);
//预先创建目录
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
model.FilePath = filePath;
//调用帮助类
result = VOLTAEdiHelper.CreateEdiVOLTA(model);
_logger.LogInformation("批次={no} 生成EDI文件完成 结果={result}", batchNo, JSON.Serialize(result));
if (!result.succ)
{
throw Oops.Bah(result.msg);
}
if (isSend)
{
string currFilePath = string.Empty;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
currFilePath = System.Text.RegularExpressions.Regex.Match(result.extra.ToString(), relativePath.Replace("/", "\\/") + ".*").Value;
}
else
{
currFilePath = System.Text.RegularExpressions.Regex.Match(result.extra.ToString(), relativePath.Replace("\\", "\\\\") + ".*").Value;
}
string fileTypeCode = "esi";
string fileTypeName = "ESI文件";
//这里先写入附件表
await SaveEDIFile(model.id, currFilePath, new System.IO.FileInfo(currFilePath).Name, fileTypeCode, fileTypeName);
_logger.LogInformation("批次={no} 直接发送FTP 文件访问地址={filepath}", batchNo, result.extra.ToString());
DateTime bDate = DateTime.Now;
bool isSendEmail = false;
if (ftpSet.SendType.Equals("SI", StringComparison.OrdinalIgnoreCase)
&& !string.IsNullOrWhiteSpace(ftpSet.RECEIVEEMAIL))
{
isSendEmail = true;
}
CommonWebApiResult sendStatus = null;
if (isSendEmail)
{
//推送订舱邮件
sendStatus = await InnerSendBookingOrClosingEDIToEmail(order, result.extra.ToString(),"E", result.extra2.ToString(), ftpSet);
}
DateTime eDate = DateTime.Now;
TimeSpan ts = eDate.Subtract(bDate);
var timeDiff = ts.TotalMilliseconds;
_logger.LogInformation("批次={no} 发送完成,耗时:{timeDiff}ms. 结果{msg}", batchNo, timeDiff, sendStatus.succ ? "成功" : "失败");
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 = "邮件";
await _bookinglogdetail.InsertReturnSnowflakeIdAsync(new BookingLogDetail
{
PId = logId,
Field = String.Empty,
OldValue = String.Empty,
NewValue = $"发送 {order.CARRIERID} EDI 类型=E 通过{sendTypeName} {(sendStatus.succ ? "" : "")}",
});
if (!sendStatus.succ)
{
throw Oops.Bah($"发送失败,原因:{sendStatus.msg}");
}
//如果是截单需最后推送货物状态
await SetGoodsStatus("JD", model.id);
await SendBookingOrder(new long[] { model.id });
}
return result.extra.ToString();
}
#endregion
@ -10098,7 +10276,8 @@ namespace Myshipping.Application
/// <param name="name">收、发、通信息</param>
/// <param name="location">内容定位name-名称addr-地址)</param>
/// <returns>返回截取字符</returns>
public string GetShipCneeNotifyDetail(string name,string location = "name")
[NonAction]
private string GetShipCneeNotifyDetail(string name,string location = "name")
{
string result = string.Empty;

@ -25,6 +25,8 @@ namespace Myshipping.Application
.Map(dest => dest.PlaceOfDelivery, src => src.PLACEDELIVERY)
.Map(dest => dest.CargoDescription, src => src.DESCRIPTION)
.Map(dest => dest.Marks, src => src.MARKS)
.Map(dest => dest.Vessel, src => src.VESSEL)
.Map(dest => dest.VoyNo, src => src.VOYNO)
.Map(dest => dest.TotalGWt, src => src.KGS.HasValue ? src.KGS.Value : 0)
.Map(dest => dest.TotalCBM, src => src.CBM.HasValue ? src.CBM.Value : 0);

@ -134,7 +134,8 @@ namespace Myshipping.Application
/// 生成VOLTA报文内部方法
/// </summary>
/// <param name="model">请求截单详情</param>
/// <param name="isSend">是否直接发送VOLTA申报截单</param>
/// <returns>返回回执</returns>
Task<dynamic> InnerVOLTAEDI(VOLTAEDIBaseModel model);
Task<dynamic> InnerVOLTAEDI(VOLTAEDIBaseModel model, bool isSend = false);
}
}
Loading…
Cancel
Save