You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
12 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using DS.Module.Core;
using DS.WMS.Core.Op.Dtos;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Logger = NLog.Logger;
using NLog;
namespace DS.WMS.Core.Op.EDI
{
/// <summary>
/// VOLTA EDI帮助类
/// </summary>
public static class VOLTAEdiHelper
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
#region 生成VOLTA申报报文截单
/// <summary>
/// 生成VOLTA申报报文截单
/// </summary>
/// <param name="model">VOLTA申报详情</param>
/// <returns>返回回执</returns>
public static EdiDataResult CreateEdiVOLTA(VOLTAEDIBaseModel model)
{
var result = new EdiDataResult { Succeeded = false };
//日志
//var logger = Log.CreateLogger(nameof(VOLTAEdiHelper));
try
{
ValidateInput(model);
string bno = model.BookingId;
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))
filename = filename.Replace("\\", "/");
FileStream f = new FileStream(filename, FileMode.Create);
StreamWriter r = new StreamWriter(f, Encoding.Default);
DateTime nowDate = DateTime.Now;
r.WriteLine("<FROMSHIPPER>FROMSHIPPER</FROMSHIPPER>");
//订舱号
r.WriteLine("<bok>" + model.BookingId + "</bok>");
//发货人
r.WriteLine("<spr>" + model.ShpperName + "</spr>");
//发货人地址
r.WriteLine("<sad>");
r.WriteLine(model.ShpperAddr);
r.WriteLine("</sad>");
//收货人
r.WriteLine("<cne>" + model.ConsigneeName + "</cne>");
//收货人地址
r.WriteLine("<cad>");
r.WriteLine(model.ConsigneeAddr);
r.WriteLine("</cad>");
//通知人
r.WriteLine("<nfy>" + model.NotifyName + "</nfy>");
//通知人地址
r.WriteLine("<nad>");
r.WriteLine(model.NotifyAddr);
r.WriteLine("</nad>");
//通知人1
if (!string.IsNullOrWhiteSpace(model.NotifySecondName))
{
r.WriteLine("<nf1>" + model.NotifySecondName + "</nf1>");
}
else
{
r.WriteLine("<nf1></nf1>");
}
//通知人1地址
if (!string.IsNullOrWhiteSpace(model.NotifySecondName))
{
r.WriteLine("<na1>");
r.WriteLine(model.ConsigneeAddr);
r.WriteLine("</na1>");
}
else
{
r.WriteLine("<na1>");
r.WriteLine("");
r.WriteLine("</na1>");
}
//发货地
r.WriteLine("<Poo>" + model.PlaceOfOrigin + "</Poo>");
//起运港
r.WriteLine("<pol>" + model.LoadPort + "</pol>");
//卸货港
r.WriteLine("<pod>" + model.DischargePort + "</pod>");
//最终目的港
r.WriteLine("<fpd>" + model.FinalDestination + "</fpd>");
//最终交货地
r.WriteLine("<pdy>" + model.PlaceOfDelivery + "</pdy>");
//PlaceOfReceipt
r.WriteLine("<por></por>");
//提单正本份数默认3
r.WriteLine("<nob>3</nob>");
//提单状态(默认S) S-SHIPPED ON BOARD;R-RECEIVED FOR SHIPMENT;T-THRO BL
r.WriteLine("<blt>S</blt>");
//重量单位默认1 1-KGS2-TON3-QUINTAL4-MT5-CENTIMETER6-METER7-INCH
r.WriteLine("<uom>1</uom>");
//Payable At
r.WriteLine("<pat></pat>");
//Prepaid / Collect(默认P) P-PREPAIDC-COLLECT
r.WriteLine("<fst>P</fst>");
//EDNumber
r.WriteLine("<edn></edn>");
//货描
r.WriteLine("<des>");
r.WriteLine(model.CargoDescription);
r.WriteLine("</des>");
//唛头
r.WriteLine("<cmn>");
r.WriteLine(model.Marks);
r.WriteLine("</cmn>");
//模板版本号
r.WriteLine("<ver>");
r.WriteLine(model.TemplateVersion);
r.WriteLine("</ver>");
//箱明细
r.WriteLine("<cnt>");
r.Write(GetContaInfo(model.ContaList));
r.WriteLine("</cnt>");
r.Close();
f.Close();
result.Succeeded = true;
result.ExtraData1 = filename;
result.ExtraData2 = $"截单样本:{model.Vessel} {model.VoyNo} {model.BookingId}";
return result;
}
catch (Exception ex)
{
result.Succeeded = false;
result.Message = ex.Message;
return result;
}
//return result;
}
#endregion
#region 拼接箱明细报文
/// <summary>
/// 拼接箱明细报文
/// </summary>
/// <param name="contaList">箱明细</param>
/// <returns>返回拼接后字符</returns>
private static string GetContaInfo(List<VOLTAEDIContaModel> contaList)
{
StringBuilder txtBuilder = new StringBuilder();
////日志
//var logger = Log.CreateLogger(nameof(VOLTAEdiHelper));
try
{
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.EdiPkgs}");
});
}
catch (Exception ex)
{
logger.Info("VOLTA拼接箱明细异常,原因:{0}", ex.Message);
throw ex;
}
return txtBuilder.ToString();
}
#endregion
#region 校验VOLTA请求参数s
/// <summary>
/// 校验VOLTA请求参数
/// </summary>
/// <param name="model">VOLTA请求参数</param>
public static void ValidateInput(VOLTAEDIBaseModel model)
{
StringBuilder msgBuilder = new StringBuilder();
if (string.IsNullOrEmpty(model.BookingId))
msgBuilder.AppendLine("提单号不能为空");
if (string.IsNullOrEmpty(model.ShpperName))
msgBuilder.AppendLine("发货人名称不能为空");
if (string.IsNullOrEmpty(model.ShpperAddr))
msgBuilder.AppendLine("发货人地址不能为空");
if (!string.IsNullOrEmpty(model.ShpperAddr))
{
if (model.ShpperAddr.Length > 450)
msgBuilder.AppendLine("发货人地址不能大于450个字符");
}
if (string.IsNullOrEmpty(model.ConsigneeName))
msgBuilder.AppendLine("收货人名称不能为空");
if (string.IsNullOrEmpty(model.ConsigneeAddr))
msgBuilder.AppendLine("收货人地址不能为空");
if (!string.IsNullOrEmpty(model.ConsigneeAddr))
{
if (model.ConsigneeAddr.Length > 450)
msgBuilder.AppendLine("收货人地址不能大于450个字符");
}
if (string.IsNullOrEmpty(model.NotifyName))
msgBuilder.AppendLine("通知人名称不能为空");
if (string.IsNullOrEmpty(model.NotifyAddr))
msgBuilder.AppendLine("通知人地址不能为空");
if (!string.IsNullOrEmpty(model.NotifyAddr))
{
if (model.NotifyAddr.Length > 450)
msgBuilder.AppendLine("通知人地址不能大于450个字符");
}
if (!string.IsNullOrEmpty(model.NotifySecondName) && string.IsNullOrEmpty(model.NotifySecondAddr))
msgBuilder.AppendLine("通知人1地址不能为空");
if (string.IsNullOrEmpty(model.NotifySecondName) && !string.IsNullOrEmpty(model.NotifySecondAddr))
msgBuilder.AppendLine("通知人1名称不能为空");
if (!string.IsNullOrEmpty(model.NotifySecondAddr))
{
if (model.NotifySecondAddr.Length > 450)
msgBuilder.AppendLine("通知人1地址不能大于450个字符");
}
if (string.IsNullOrEmpty(model.PlaceOfOrigin))
msgBuilder.AppendLine("发货地不能为空");
if (string.IsNullOrEmpty(model.LoadPort))
msgBuilder.AppendLine("起运港不能为空");
if (string.IsNullOrEmpty(model.DischargePort))
msgBuilder.AppendLine("卸货港不能为空");
if (string.IsNullOrEmpty(model.FinalDestination))
msgBuilder.AppendLine("最终目的港不能为空");
if (string.IsNullOrEmpty(model.PlaceOfDelivery))
msgBuilder.AppendLine("最终交货地不能为空");
if (string.IsNullOrEmpty(model.CargoDescription))
msgBuilder.AppendLine("品名不能为空");
if (!string.IsNullOrEmpty(model.CargoDescription))
{
if (model.CargoDescription.Length > 3000)
msgBuilder.AppendLine("品名不能大于3000个字符");
}
if (string.IsNullOrEmpty(model.Marks))
msgBuilder.AppendLine("唛头不能为空");
if (!string.IsNullOrEmpty(model.Marks))
{
if (model.Marks.Length > 1000)
msgBuilder.AppendLine("唛头不能大于1000个字符");
}
if (model.ContaList == null || model.ContaList.Count == 0)
msgBuilder.AppendLine("箱明细不能为空");
model.ContaList.ForEach(ctn =>
{
StringBuilder ctnMsgBuilder = new StringBuilder();
if (string.IsNullOrWhiteSpace(ctn.ContaNo))
{
ctnMsgBuilder.Append("箱号不能为空;");
}
else
{
if (ctn.ContaNo.Length > 11)
{
ctnMsgBuilder.Append("箱号长度不能大于11");
}
}
if (string.IsNullOrWhiteSpace(ctn.SealNo))
{
ctnMsgBuilder.Append("铅封号不能为空;");
}
if (!ctn.GWt.HasValue)
{
ctnMsgBuilder.Append("毛重不能为空;");
}
if (!ctn.CBM.HasValue)
{
ctnMsgBuilder.Append("尺寸不能为空;");
}
if (!ctn.Qty.HasValue)
{
ctnMsgBuilder.Append("件数不能为空;");
}
if (string.IsNullOrWhiteSpace(ctn.EdiPkgs))
{
ctnMsgBuilder.Append("包装不能为空;");
}
if (ctnMsgBuilder.Length > 0)
{
msgBuilder.AppendLine($"箱【{ctn.SNo}】{ctnMsgBuilder.ToString()}");
}
});
if (msgBuilder.Length > 0)
throw new Exception(msgBuilder.ToString());
}
#endregion
}
}