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.
BookingHeChuan/ServiceProjectSyncWin/Program.cs

2742 lines
105 KiB
C#

using Furion;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.RemoteRequest.Extensions;
using HtmlAgilityPack;
using Microsoft.AspNetCore.Mvc;
8 months ago
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
5 months ago
using MimeKit;
using ServiceProjectSyncWin;
using ServiceProjectSyncWin.Entities;
using SqlSugar;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel.DataAnnotations;
using System.Net.Http.Headers;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using static System.Net.Mime.MediaTypeNames;
Serve.RunGeneric(additional: services =>
{
services.AddRemoteRequest();
services.AddSqlsugarSetup(App.Configuration);
}, true, true);
Console.WriteLine("开始准备同步历史服务状态数据");
var service1 = App.GetService<ISyncHisRecord>();
//service1.SyncServiceProjectRecord();
5 months ago
//service1.SyncServiceProjectRecord5();
service1.SyncServiceProjectRecord6();
Console.ReadKey();
public interface ISyncHisRecord
{
11 months ago
void SyncServiceProjectRecord4();
void SyncServiceProjectRecord5();
5 months ago
void SyncServiceProjectRecord6();
11 months ago
//void SyncServiceProjectRecord2();
//void SyncServiceProjectRecord3();
}
public class SyncHisRecord: ISyncHisRecord,ITransient
{
SqlSugar.ISqlSugarClient _db;
private readonly ILogger<SyncHisRecord> _logger;
public SyncHisRecord(ISqlSugarClient db, ILogger<SyncHisRecord> logger)
{
_db = db;
_logger = logger;
}
public void SyncServiceProjectRecord()
{
int totalSyncNum = 0;
int succSyncNum = 0;
long maxId = 0;
//349708986646597/中集世联达领鲜物流科技(山东)有限公司
long tenantId = 349708986646597;
string batchNo = Guid.NewGuid().ToString();
_logger.LogInformation("批次={no} 触发同步货物状态 tenantId={tenantId}", batchNo, tenantId);
try
{
var tenantInfo = _db.Queryable<SysTenant>().First(a => a.Id == tenantId);
/*
1
2
3
4
*/
maxId = _db.Queryable<ServiceStatusBookingSyncHisInfo>().Max(a => a.ORG_STATUS_ID);
_logger.LogInformation("批次={no} 获取最后同步服务状态的ID={maxId}", batchNo, maxId);
int takeNum = 1000;
while (true)
{
var takeList = _db.Queryable<BookingGoodsStatus>()
.InnerJoin<BookingGoodsStatusConfig>((gs, cfg) => gs.ConfigId == cfg.Id)
.InnerJoin<BookingOrder>((gs, cfg, bk) => gs.bookingId == bk.Id)
.Where((gs, cfg, bk) =>
gs.FinishTime.HasValue && gs.TenantId == tenantId
&& !bk.IsDeleted && gs.FinishUserId != 142307070910551
&& (maxId == 0 || gs.Id > maxId))
.OrderBy((gs, cfg, bk) => gs.Id)
.Select((gs, cfg, bk) => new { GS = gs, CFG = cfg, BK = bk })
.Take(takeNum).ToList();
totalSyncNum += takeList.Count;
Console.WriteLine($"批次={batchNo} 同步待处理任务 totalSyncNum={totalSyncNum}");
_logger.LogInformation("批次={no} 同步待处理任务 totalSyncNum={totalSyncNum}", batchNo, totalSyncNum);
//没有记录跳出循环
if (takeList.Count == 0)
{
Console.WriteLine($"没有记录跳出循环 total={succSyncNum}");
break;
}
maxId = takeList.Max(a => a.GS.Id);
_logger.LogInformation("批次={no} 获取最后同步服务状态的 maxId={maxId}", batchNo, maxId);
//写入记录表
takeList.ForEach(async record =>
{
var entity = new ServiceStatusBookingSyncHisInfo
{
PK_ID = Guid.NewGuid().ToString(),
ORG_STATUS_ID = record.GS.Id,
BOOKING_ID = record.BK.Id,
FINISH_TIME = record.GS.FinishTime.Value,
FINISH_USER_ID = record.GS.FinishUserId.Value,
FINISH_USER_NAME = record.GS.FinishUser,
MBL_NO = record.BK.MBLNO,
SORT_NO = record.CFG.Sort,
STATUS_SKU_CODE = record.CFG.SystemCode,
STATUS_SKU_NAME = record.CFG.StatusName,
STATUS_REMARK = record.GS.Remark,
STATUS_VAL = record.GS.ExtData,
TENANT_ID = record.GS.TenantId.Value,
TENANT_NAME = tenantInfo.Name,
VESSEL = record.BK.VESSEL,
VOYNO = record.BK.VOYNO,
};
_db.Insertable<ServiceStatusBookingSyncHisInfo>(entity).ExecuteCommand();
//await _serviceStatusBookingSyncHisInfoRepository.InsertAsync(entity);
succSyncNum++;
Console.WriteLine($"ORG_STATUS_ID={record.GS.Id} 写入成功 total={succSyncNum}");
Thread.Sleep(300);
});
Console.WriteLine($"等待500毫秒");
Thread.Sleep(500);
}
//停用的状态(接受委托、放箱指令、已发账单、账单确认、账单已回传)
string[] deletedStatusCodeArg = new string[] { "JSWTUO", "FXZLING", "YFZD", "ZDQR", "ZDYHC" };
/*
1null100
2
3PUSH
4
*/
Console.WriteLine($"开始推送记录 succ={succSyncNum}");
while (true)
{
var bookingList = _db.Queryable<ServiceStatusBookingSyncHisInfo>()
.Where(a => a.TENANT_ID == tenantId && a.STATUS == null)
.Take(100).Select(a => a.BOOKING_ID).Distinct().ToList();
//无数据跳出
if (bookingList.Count == 0)
{
Console.WriteLine($"没有待推送记录跳出循环 succ={succSyncNum}");
break;
}
var taskList = _db.Queryable<ServiceStatusBookingSyncHisInfo>()
.Where(a => a.TENANT_ID == tenantId && bookingList.Contains(a.BOOKING_ID)).ToList();
taskList.GroupBy(a => a.BOOKING_ID).ToList().ForEach(a =>
{
DateTime currDate = DateTime.Now;
var currStatusList = a.ToList();
var groupCheckList = currStatusList
.Where(b => !deletedStatusCodeArg.Contains(b.STATUS_SKU_CODE))
.GroupBy(b => b.STATUS_SKU_CODE).Select(b =>
{
var currList = b.ToList();
if (currList.Count == 1)
return currList.FirstOrDefault();
return currList.OrderByDescending(c => c.ORG_STATUS_ID).FirstOrDefault();
}).ToList();
if (groupCheckList.Count > 0)
{
var firstInfo = groupCheckList.FirstOrDefault();
TrackingMessageInfo msgInfo = new TrackingMessageInfo
{
Head = new TrackingMessageHeadInfo
{
GID = IDGen.NextID().ToString(),
MessageType = "PROJECT",
ReceiverId = "ServiceProjectStatus",
ReceiverName = "服务项目和状态",
SenderId = "BookingOrder",
SenderName = "海运订舱",
RequestDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
Version = "2.0",
RequestAction = "AddOrModify",
},
Main = new TrackingMessageMainInfo
{
BusiId = firstInfo.BOOKING_ID.ToString(),
BusiSystemCode = "BOOKING_ORDER",
MBlNo = firstInfo.MBL_NO,
VesselVoyno = $"{firstInfo.VESSEL}/{firstInfo.VOYNO}",
OrderNo = "",
PushType = TrackingPushTypeEnum.Status,
OperTenantId = firstInfo.TENANT_ID,
OperTenantName = firstInfo.TENANT_NAME,
OpertType = TrackingOperTypeEnum.AUTO,
OperUserId = firstInfo.FINISH_USER_ID.ToString(),
OperUserName = firstInfo.FINISH_USER_NAME,
SourceType = TrackingSourceTypeEnum.AUTO,
StatusList = groupCheckList.Select(a => new TrackingMessageMainStatusInfo
{
StatusCode = a.STATUS_SKU_CODE,
StatusDate = a.FINISH_TIME,
StatusVal = a.STATUS_VAL,
Remark = a.STATUS_REMARK
}).ToList()
}
};
Console.WriteLine($"准备PUSH状态 msg={JSON.Serialize(msgInfo.Main)}");
//推送状态
var pushRlt = PushStatus(msgInfo).GetAwaiter().GetResult();
Console.WriteLine($"PUSH返回结果 rlt={JSON.Serialize(pushRlt)}");
groupCheckList.ForEach(async t => {
t.STATUS = pushRlt.succ ? "SUCC" : "FAILURE";
t.SYNC_TIME = currDate;
t.SYNC_RESULT = pushRlt.msg;
if (deletedStatusCodeArg.Contains(t.STATUS_SKU_CODE))
{
t.STATUS = "FAILURE";
t.SYNC_RESULT = "状态已取消不再同步";
}
await _db.Updateable<ServiceStatusBookingSyncHisInfo>(t)
.UpdateColumns(it => new
{
it.STATUS,
it.SYNC_TIME,
it.SYNC_RESULT
}).ExecuteCommandAsync();
});
var undoList = currStatusList.GroupJoin(groupCheckList, l => l.ORG_STATUS_ID,
r => r.ORG_STATUS_ID, (l, r) =>
{
var currList = r.ToList();
if (currList.Count == 0)
return new { IsUpdate = true, Obj = l };
return new { IsUpdate = false, Obj = l };
}).Where(c => c.IsUpdate)
.Select(c => c.Obj).ToList();
if (undoList.Count > 0)
{
undoList.ForEach(async t => {
t.STATUS = "FAILURE";
t.SYNC_RESULT = "状态已取最后触发记录";
t.SYNC_TIME = currDate;
if (deletedStatusCodeArg.Contains(t.STATUS_SKU_CODE))
{
t.SYNC_RESULT = "状态已取消不再同步";
}
await _db.Updateable<ServiceStatusBookingSyncHisInfo>(t)
.UpdateColumns(it => new
{
it.STATUS,
it.SYNC_TIME,
it.SYNC_RESULT
}).ExecuteCommandAsync();
});
}
Console.WriteLine($"更新表结束");
}
else
{
Console.WriteLine($"没有可用记录");
}
Thread.Sleep(300);
});
Thread.Sleep(500);
}
}
catch(Exception ex)
{
_logger.LogInformation("批次={no} 同步异常ex={ex}", batchNo, maxId);
}
}
public async Task<TaskManageOrderResultDto> PushStatus(TrackingMessageInfo info)
{
TaskManageOrderResultDto model = null;
/*
1URL
2JSON
3POST
4
*/
var url = App.Configuration["ServiceStatusPushUrl"];
try
{
var res = await url.SetHttpMethod(HttpMethod.Post)
.SetBody(JSON.Serialize(info), "application/json")
.SetContentEncoding(Encoding.UTF8)
.PostAsync();
_logger.LogInformation("批次={no} 对应请求报文完成 res={res}", info.Head.GID, JSON.Serialize(res));
if (res.StatusCode == System.Net.HttpStatusCode.OK)
{
var userResult = await res.Content.ReadAsStringAsync();
var cmRlt = JSON.Deserialize<CommonRlt>(userResult);
if(cmRlt.success)
model = JSON.Deserialize<TaskManageOrderResultDto>(JSON.Serialize(cmRlt.data));
}
}
catch (Exception ex)
{
//写日志
if (ex is HttpRequestException)
throw Oops.Oh(10000002);
}
return model;
}
public void SyncServiceProjectRecord2()
{
/*
string fmt = "(16)PortofDischarge(17)PlaceofDelivery";
var fmtList = fmt.Select(a => a).ToList();
string name = "(1P6)E PNorAt oNf GDi,scMhaArgLeA YSIA P(1E7)N PAlaNceG o,f DMeAlivLerAy YSIA";
List<char> array = new List<char>();
List<char> array2 = new List<char>();
for (var i=0;i< name.Length;i++)
{
bool isExists = false;
if(fmtList.Count > 0)
{
if (name[i] == fmtList.First())
{
array.Add(name[i]);
fmtList.Remove(fmtList[0]);
isExists = true;
}
}
if (!isExists)
array2.Add(name[i]);
}
string s1 = string.Join("", array);
string s2 = string.Join("", array2);
*/
string Consignee = "LOT 13/3,KAWASAN PERINDUSTRIAN, K AMPUNG KOLAM PADANG BESAR,02100 P ADANG BESAR,PERLIS. T EL;04-949 0507 FAX 94-949 2888";
string NotifyParty = "SHUN EE TRADING SDN BHD (1183208 U) LOT 13/3,KAWASAN PERINDUSTRIAN, K AMPUNG KOLAM PADANG BESAR,02100 P ADANG BESAR,PERLIS. T EL;04-949 0507 FAX 94-949 2888";
if (Regex.IsMatch(Consignee, "\\b[a-zA-Z]{1}\\b\\s+\\b[a-zA-Z]+\\b"))
{
Consignee = Regex.Replace(Consignee, "\\b[a-zA-Z]{1}\\b\\s+\\b[a-zA-Z]+\\b", m => Regex.Replace(m.Value, "\\s+", ""));
}
if (Regex.IsMatch(NotifyParty, "\\b[a-zA-Z]{1}\\b\\s+\\b[a-zA-Z]+\\b"))
{
NotifyParty = Regex.Replace(NotifyParty, "\\b[a-zA-Z]{1}\\b\\s+\\b[a-zA-Z]+\\b", m => Regex.Replace(m.Value, "\\s+", ""));
}
decimal similarity = 100;
for (int i = 0; i < NotifyParty.Length; i++)
{
}
}
11 months ago
public void SyncServiceProjectRecord4()
{
/*
SI
1
2
*/
8 months ago
var taskList = _db.Queryable<TaskBCEntity>().Where(a => (a.BUSI_TYPE == "BookingConfirmation" || a.BUSI_TYPE == "BookingAmendment"))
.OrderBy(t=>t.CreatedTime)
.ToList();
string batchNo = Guid.NewGuid().ToString();
_logger.LogInformation($"批次={batchNo} 提取待处理任务 num={taskList.Count}");
8 months ago
string bcReadUrl = "http://47.104.73.97:7115/api/TaskBCParser/ExcuteBCFileRead";
string amendReadUrl = "http://47.104.73.97:7115/api/TaskBookingAmendmentParser/ExcuteBookingAmendmentRead";
//foreach (var task in taskList)
for(int i=0;i<taskList.Count;i++)
{
var task = taskList[i];
//BookingConfirmation、BookingAmendment
if (task.BUSI_TYPE == "BookingConfirmation")
{
_logger.LogInformation($"批次={batchNo} 处理任务 No={i} MBLNO={task.MBL_NO} 开始");
var fileInfo = _db.Queryable<TaskFileEntities>().Where(a => a.TASK_PKID == task.TASK_ID && a.FILE_CATEGORY == "BC").First();
if (fileInfo != null)
{
_logger.LogInformation($"批次={batchNo} 提取待处理任务 MBLNO={task.MBL_NO} 取到文件");
string bcFileFullPath = $"D:\\djy\\backend\\wwwroot\\{fileInfo.FILE_PATH}";
var bcFileName = Path.GetFileName(bcFileFullPath);
8 months ago
if(!File.Exists(bcFileFullPath))
{
_logger.LogInformation($"批次={batchNo} 提取待处理任务 MBLNO={task.MBL_NO} 取到文件不存在 path={bcFileFullPath}");
continue;
}
TaskBCInfoReadDto BCReadInfo = GetBCReaderInfo(bcFileFullPath, bcFileName, task.TenantId.Value, task.TASK_ID, bcReadUrl).GetAwaiter().GetResult();
_logger.LogInformation($"批次={batchNo} 提取待处理任务 MBLNO={task.MBL_NO} 识别完文件 BCReadInfo={JSON.Serialize(BCReadInfo)}");
8 months ago
StringBuilder msgBuilder = new StringBuilder();
if (BCReadInfo != null)
{
//SI_CUT_DATE
if (BCReadInfo.SICutDate.HasValue)
{
8 months ago
if (!task.SI_CUT_DATE.HasValue || task.SI_CUT_DATE.Value != BCReadInfo.SICutDate.Value)
{
8 months ago
msgBuilder.Append($"SI_CUT_DATE org={task.SI_CUT_DATE} tar={BCReadInfo.SICutDate.Value}##");
8 months ago
task.SI_CUT_DATE = BCReadInfo.SICutDate.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"SI_CUT_DATE org={task.SI_CUT_DATE} tar=null");
task.SI_CUT_DATE = null;
}
//VGM_CUTOFF_TIME
if (BCReadInfo.VGMCutoffTime.HasValue)
{
8 months ago
if (!task.VGM_CUTOFF_TIME.HasValue || task.VGM_CUTOFF_TIME.Value != BCReadInfo.VGMCutoffTime.Value)
{
msgBuilder.Append($"VGM_CUTOFF_TIME org={task.VGM_CUTOFF_TIME} tar={BCReadInfo.VGMCutoffTime.Value}##");
task.VGM_CUTOFF_TIME = BCReadInfo.VGMCutoffTime.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"VGM_CUTOFF_TIME org={task.VGM_CUTOFF_TIME} tar=null##");
task.VGM_CUTOFF_TIME = null;
}
8 months ago
//MANIFEST_CUT_DATE
if (BCReadInfo.ManifestCutDate.HasValue)
{
8 months ago
if (!task.MANIFEST_CUT_DATE.HasValue || task.MANIFEST_CUT_DATE.Value != BCReadInfo.ManifestCutDate.Value)
{
msgBuilder.Append($"MANIFEST_CUT_DATE org={task.MANIFEST_CUT_DATE} tar={BCReadInfo.ManifestCutDate.Value}##");
task.MANIFEST_CUT_DATE = BCReadInfo.ManifestCutDate.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"MANIFEST_CUT_DATE org={task.MANIFEST_CUT_DATE} tar=null##");
task.MANIFEST_CUT_DATE = null;
}
//CY_CUTOFF_TIME
if (BCReadInfo.CYCutoffTime.HasValue)
{
8 months ago
if (!task.MANIFEST_CUT_DATE.HasValue || task.MANIFEST_CUT_DATE.Value != BCReadInfo.CYCutoffTime.Value)
{
msgBuilder.Append($"CY_CUTOFF_TIME org={task.CY_CUTOFF_TIME} tar={BCReadInfo.CYCutoffTime.Value}##");
task.CY_CUTOFF_TIME = BCReadInfo.CYCutoffTime.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"CY_CUTOFF_TIME org={task.CY_CUTOFF_TIME} tar=null##");
task.CY_CUTOFF_TIME = null;
}
8 months ago
//MDGF_CUT_DATE
if (BCReadInfo.MDGFCutDate.HasValue)
{
8 months ago
if (!task.MDGF_CUT_DATE.HasValue || task.MDGF_CUT_DATE.Value != BCReadInfo.MDGFCutDate.Value)
{
msgBuilder.Append($"MDGF_CUT_DATE org={task.MDGF_CUT_DATE} tar={BCReadInfo.MDGFCutDate.Value}##");
task.MDGF_CUT_DATE = BCReadInfo.MDGFCutDate.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"MDGF_CUT_DATE org={task.MDGF_CUT_DATE} tar=null##");
task.MDGF_CUT_DATE = null;
}
//CLOSING_DATE
if (BCReadInfo.ClosingDate.HasValue)
{
8 months ago
if (!task.CLOSING_DATE.HasValue || task.CLOSING_DATE.Value != BCReadInfo.ClosingDate.Value)
{
msgBuilder.Append($"CLOSING_DATE org={task.CLOSING_DATE} tar={BCReadInfo.ClosingDate.Value}##");
task.CLOSING_DATE = BCReadInfo.ClosingDate.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"CLOSING_DATE org={task.CLOSING_DATE} tar=null##");
task.CLOSING_DATE = null;
}
//CLOSING_DATE
if (BCReadInfo.CustomSICutDate.HasValue)
{
if (!task.CUSTOM_SI_CUT_DATE.HasValue || task.CUSTOM_SI_CUT_DATE.Value != BCReadInfo.CustomSICutDate.Value)
{
msgBuilder.Append($"CUSTOM_SI_CUT_DATE org={task.CUSTOM_SI_CUT_DATE} tar={BCReadInfo.CustomSICutDate.Value}##");
task.CUSTOM_SI_CUT_DATE = BCReadInfo.CustomSICutDate.Value;
}
}
else
{
msgBuilder.Append($"CUSTOM_SI_CUT_DATE org={task.CUSTOM_SI_CUT_DATE} tar=null##");
task.CUSTOM_SI_CUT_DATE = null;
}
_db.Updateable<TaskBCEntity>(task).UpdateColumns(it => new
{
it.SI_CUT_DATE,
it.CUSTOM_SI_CUT_DATE,
it.VGM_CUTOFF_TIME,
it.MANIFEST_CUT_DATE,
it.CY_CUTOFF_TIME,
it.MDGF_CUT_DATE,
it.CLOSING_DATE
}).ExecuteCommand();
}
8 months ago
_logger.LogInformation($"批次={batchNo} 提取待处理任务 MBLNO={task.MBL_NO} 识别完文件 有变更 结果={msgBuilder.ToString()}");
}
}
else if (task.BUSI_TYPE == "BookingAmendment")
{
var fileInfo = _db.Queryable<TaskFileEntities>().Where(a => a.TASK_PKID == task.TASK_ID && a.FILE_CATEGORY == "BC_MODIFY").First();
if (fileInfo != null)
{
string bcFileFullPath = $"D:\\djy\\backend\\wwwroot\\{fileInfo.FILE_PATH}";
var bcFileName = Path.GetFileName(bcFileFullPath);
8 months ago
if (!File.Exists(bcFileFullPath))
{
_logger.LogInformation($"批次={batchNo} 提取待处理任务 MBLNO={task.MBL_NO} 取到文件不存在 path={bcFileFullPath}");
continue;
}
TaskBCInfoReadDto BCReadInfo = GetBCReaderInfo(bcFileFullPath, bcFileName, task.TenantId.Value, task.TASK_ID, amendReadUrl).GetAwaiter().GetResult();
8 months ago
StringBuilder msgBuilder = new StringBuilder();
if (BCReadInfo != null)
{
//SI_CUT_DATE
if (BCReadInfo.SICutDate.HasValue)
{
8 months ago
if (!task.SI_CUT_DATE.HasValue || task.SI_CUT_DATE.Value != BCReadInfo.SICutDate.Value)
{
msgBuilder.Append($"SI_CUT_DATE org={task.SI_CUT_DATE} tar={BCReadInfo.SICutDate.Value}##");
task.SI_CUT_DATE = BCReadInfo.SICutDate.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"SI_CUT_DATE org={task.SI_CUT_DATE} tar=null");
task.SI_CUT_DATE = null;
}
//VGM_CUTOFF_TIME
if (BCReadInfo.VGMCutoffTime.HasValue)
{
8 months ago
if (!task.VGM_CUTOFF_TIME.HasValue || task.VGM_CUTOFF_TIME.Value != BCReadInfo.VGMCutoffTime.Value)
{
msgBuilder.Append($"VGM_CUTOFF_TIME org={task.VGM_CUTOFF_TIME} tar={BCReadInfo.VGMCutoffTime.Value}##");
task.VGM_CUTOFF_TIME = BCReadInfo.VGMCutoffTime.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"VGM_CUTOFF_TIME org={task.VGM_CUTOFF_TIME} tar=null##");
task.VGM_CUTOFF_TIME = null;
}
8 months ago
//MANIFEST_CUT_DATE
if (BCReadInfo.ManifestCutDate.HasValue)
{
8 months ago
if (!task.MANIFEST_CUT_DATE.HasValue || task.MANIFEST_CUT_DATE.Value != BCReadInfo.ManifestCutDate.Value)
{
msgBuilder.Append($"MANIFEST_CUT_DATE org={task.MANIFEST_CUT_DATE} tar={BCReadInfo.ManifestCutDate.Value}##");
task.MANIFEST_CUT_DATE = BCReadInfo.ManifestCutDate.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"MANIFEST_CUT_DATE org={task.MANIFEST_CUT_DATE} tar=null##");
task.MANIFEST_CUT_DATE = null;
}
//CY_CUTOFF_TIME
if (BCReadInfo.CYCutoffTime.HasValue)
{
8 months ago
if (!task.MANIFEST_CUT_DATE.HasValue || task.MANIFEST_CUT_DATE.Value != BCReadInfo.CYCutoffTime.Value)
{
msgBuilder.Append($"CY_CUTOFF_TIME org={task.CY_CUTOFF_TIME} tar={BCReadInfo.CYCutoffTime.Value}##");
task.CY_CUTOFF_TIME = BCReadInfo.CYCutoffTime.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"CY_CUTOFF_TIME org={task.CY_CUTOFF_TIME} tar=null##");
task.CY_CUTOFF_TIME = null;
}
8 months ago
//MDGF_CUT_DATE
if (BCReadInfo.MDGFCutDate.HasValue)
{
8 months ago
if (!task.MDGF_CUT_DATE.HasValue || task.MDGF_CUT_DATE.Value != BCReadInfo.MDGFCutDate.Value)
{
msgBuilder.Append($"MDGF_CUT_DATE org={task.MDGF_CUT_DATE} tar={BCReadInfo.MDGFCutDate.Value}##");
task.MDGF_CUT_DATE = BCReadInfo.MDGFCutDate.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"MDGF_CUT_DATE org={task.MDGF_CUT_DATE} tar=null##");
task.MDGF_CUT_DATE = null;
}
//CLOSING_DATE
if (BCReadInfo.ClosingDate.HasValue)
{
8 months ago
if (!task.CLOSING_DATE.HasValue || task.CLOSING_DATE.Value != BCReadInfo.ClosingDate.Value)
{
msgBuilder.Append($"CLOSING_DATE org={task.CLOSING_DATE} tar={BCReadInfo.ClosingDate.Value}##");
task.CLOSING_DATE = BCReadInfo.ClosingDate.Value;
}
}
else
{
8 months ago
msgBuilder.Append($"CLOSING_DATE org={task.CLOSING_DATE} tar=null##");
task.CLOSING_DATE = null;
}
//CLOSING_DATE
if (BCReadInfo.CustomSICutDate.HasValue)
{
if (!task.CUSTOM_SI_CUT_DATE.HasValue || task.CUSTOM_SI_CUT_DATE.Value != BCReadInfo.CustomSICutDate.Value)
{
msgBuilder.Append($"CUSTOM_SI_CUT_DATE org={task.CUSTOM_SI_CUT_DATE} tar={BCReadInfo.CustomSICutDate.Value}##");
task.CUSTOM_SI_CUT_DATE = BCReadInfo.CustomSICutDate.Value;
}
}
else
{
msgBuilder.Append($"CUSTOM_SI_CUT_DATE org={task.CUSTOM_SI_CUT_DATE} tar=null##");
task.CUSTOM_SI_CUT_DATE = null;
}
_db.Updateable<TaskBCEntity>(task).UpdateColumns(it => new
{
it.SI_CUT_DATE,
it.CUSTOM_SI_CUT_DATE,
it.VGM_CUTOFF_TIME,
it.MANIFEST_CUT_DATE,
it.CY_CUTOFF_TIME,
it.MDGF_CUT_DATE,
it.CLOSING_DATE
}).ExecuteCommand();
}
8 months ago
_logger.LogInformation($"批次={batchNo} 提取待处理任务 MBLNO={task.MBL_NO} 识别完文件 有变更 结果={msgBuilder.ToString()}");
}
}
Thread.Sleep(500);
}
}
public void SyncServiceProjectRecord5()
{
string strBody = File.ReadAllText("C:\\Users\\Administrator\\Desktop\\测试HTML.txt", Encoding.UTF8);
//FileStream f = new FileStream("C:\\Users\\Administrator\\Desktop\\测试HTML.txt", FileMode.Create);
//StreamWriter r = new StreamWriter(f, Encoding.Default);
//r.WriteLine(strBody);
HtmlDocument html = new HtmlDocument();
html.LoadHtml(strBody);
List<TransPlanHasChangeDto> list = new List<TransPlanHasChangeDto>();
var divTopList = html.DocumentNode.SelectSingleNode("//div[@class='data__top']");
if (divTopList == null)
return;
//先获取第一层的div
var rootDivNode = divTopList.ParentNode.ChildNodes.Where(a => a.Name.Equals("div", StringComparison.OrdinalIgnoreCase)
&& a.Attributes.Contains("class") && (a.Attributes["class"].Value.Equals("data__top") || a.Attributes["class"].Value.Equals("data")))
.ToList();
//先遍历第一层子节点
for (int i = 0; i < rootDivNode.Count; i++)
{
//先取top
if (rootDivNode[i].Attributes["class"].Value.Equals("data__top", StringComparison.OrdinalIgnoreCase))
{
TransPlanHasChangeDto dto = new TransPlanHasChangeDto
{
From = new TransPlanHasChangeDetailDto
{
portList = new List<TransPlanHasChangePortDto>(),
dateList = new List<TransPlanHasChangeDateDto>(),
vesselList = new List<TransPlanHasChangeVesselVoynoDto>()
},
To = new TransPlanHasChangeDetailDto
{
portList = new List<TransPlanHasChangePortDto>(),
dateList = new List<TransPlanHasChangeDateDto>(),
vesselList = new List<TransPlanHasChangeVesselVoynoDto>()
},
Carrier = "MSK",
ContaNoList = new List<string>()
};
if (i == rootDivNode.Count - 1)
{
var innerList = GetChildList(rootDivNode[i]);
if (innerList != null && innerList.Count > 0)
{
list.AddRange(innerList);
}
}
else
{
#region 解析TOP
var ctnNode = rootDivNode[i].SelectSingleNode("./table[not(contains(@class,'reason'))]/tbody/tr[1]/th[contains(@class,'last')]");
if (ctnNode != null)
{
string s = ctnNode.SelectSingleNode("./table/tr/th/table/tbody/tr/th/table/tr/th").InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(s) && (Regex.IsMatch(s, "集装箱号码") || Regex.IsMatch(s, "Container\\(s\\)")))
{
string ctnStr = Regex.Match(s, "(?<=集装箱号码).*").Value?.Trim();
if (string.IsNullOrWhiteSpace(ctnStr))
{
ctnStr = Regex.Match(s, "(?<=Container\\(s\\)).*").Value?.Trim();
}
if (ctnStr.IndexOf(",") >= 0)
{
dto.ContaNoList = ctnStr.Split(new char[] { ',' }).Select(a => a.Trim()).ToList();
}
else
{
if (!string.IsNullOrWhiteSpace(ctnStr))
dto.ContaNoList.Add(ctnStr.Trim());
}
}
}
Dictionary<int, string> labelDict = new Dictionary<int, string>();
Dictionary<int, string> valDict = new Dictionary<int, string>();
Dictionary<int, Tuple<string, string>> reasonDict = new Dictionary<int, Tuple<string, string>>();
string lableXpath = "./table[not(contains(@class,'reason'))]/tbody/tr[1]/th[1]/table/tr[1]/";
var currLabel1 = rootDivNode[i].SelectSingleNode($"{lableXpath}/th[1]/table/tbody/tr[1]/th[1]/table/tr[1]/th[1]").InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(currLabel1))
{
labelDict.Add(1, currLabel1);
}
var currLabel2Node = rootDivNode[i].SelectSingleNode($"{lableXpath}/th[1]/table/tbody/tr[1]/th[1]/table/tr[2]/th[1]");
if (currLabel2Node != null)
{
var currLabel2 = currLabel2Node.InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(currLabel2))
{
labelDict.Add(2, currLabel2);
}
}
var currValue1 = rootDivNode[i].SelectSingleNode($"{lableXpath}/th[2]/table/tr[1]/th[1]").InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(currValue1))
{
valDict.Add(1, currValue1);
}
var currValue2Node = rootDivNode[i].SelectSingleNode($"{lableXpath}/th[2]/table/tr[2]/th[1]");
if (currValue2Node != null)
{
var currValue2 = currValue2Node.InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(currValue2))
{
valDict.Add(2, currValue2);
}
}
foreach (KeyValuePair<int, string> kvp in labelDict)
{
if (kvp.Value.Equals("订舱号") || Regex.IsMatch(kvp.Value, "Booking\\s+Number", RegexOptions.IgnoreCase))
{
dto.BookingNo = valDict[kvp.Key];
}
else if (kvp.Value.Equals("提单号码") || Regex.IsMatch(kvp.Value, "Bill\\s+of\\s+Lading", RegexOptions.IgnoreCase))
{
dto.BillNo = valDict[kvp.Key];
}
}
string reason1 = string.Empty;
string reason2 = string.Empty;
bool isReasonNote = false;
var reasonTables = rootDivNode[i].SelectNodes("./table[contains(@class,'reason')]");
if (reasonTables.Count > 0)
{
for (int k = 0; k < reasonTables.Count; k++)
{
var thFirstNode = rootDivNode[i].SelectSingleNode("./table[contains(@class,'reason')][" + (k + 1) + "]/tbody/tr/th[contains(@class,'columns first')]");
if (thFirstNode != null)
{
isReasonNote = true;
}
if (!isReasonNote)
{
string s = rootDivNode[i].SelectSingleNode("./table[contains(@class,'reason')][" + (k + 1) + "]/tr/th").InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(s) && s.IndexOf("此订舱号派生自原单号") >= 0)
{
reasonDict.Add(k + 1, new Tuple<string, string>(s, Regex.Match(s, "(?<=此订舱号派生自原单号\\:)\\?\\w+").Value?.Trim()));
}
}
else
{
var labelNode = rootDivNode[i].SelectSingleNode("./table[contains(@class,'reason')][" + (k + 1) + "]/tbody/tr/th[contains(@class,'columns first')]");
var notesNode = rootDivNode[i].SelectSingleNode("./table[contains(@class,'reason')][" + (k + 1) + "]/tbody/tr/th[contains(@class,'columns last')]");
string label = string.Empty;
string notes = string.Empty;
if (labelNode != null)
{
label = labelNode.InnerText.ReplaceHtmlStr();
}
if (notesNode != null)
{
notes = notesNode.InnerText.ReplaceHtmlStr();
}
if (!string.IsNullOrWhiteSpace(notes))
{
reasonDict.Add(k + 1, new Tuple<string, string>(label, notes));
}
}
}
}
foreach (KeyValuePair<int, Tuple<string, string>> kvp in reasonDict)
{
if (Regex.IsMatch(kvp.Value.Item1, "此订舱号派生自原单号", RegexOptions.IgnoreCase))
{
dto.OrigBillNo = kvp.Value.Item2;
}
else if (Regex.IsMatch(kvp.Value.Item1, "((变更原因)|(Reason))", RegexOptions.IgnoreCase))
{
dto.ChangeReasonNotes = kvp.Value.Item2;
}
}
#endregion
#region 解析DATA
//如果下一个节点是data表示后面是详情
if (rootDivNode[i + 1].Attributes["class"].Value.Equals("data", StringComparison.OrdinalIgnoreCase))
{
var title = rootDivNode[i + 1].SelectSingleNode("./table[1]/tbody/tr/th[1]/table/tr/th").InnerText.ReplaceHtmlStr();
var title2 = rootDivNode[i + 1].SelectSingleNode("./table[2]/tbody/tr/th[1]/table/tr/th").InnerText.ReplaceHtmlStr();
var title3 = rootDivNode[i + 1].SelectSingleNode(".//b[1]");
if (title3 != null)
{
dto.PleaseNotes = title3.InnerText.ReplaceHtmlStr();
}
//From
if (Regex.IsMatch(title, "((出运计划)|(From))", RegexOptions.IgnoreCase))
{
//port
var portNodes = rootDivNode[i + 1].SelectNodes("./table[1]/tbody/tr/th[2]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (portNodes.Count == 1)
{
string s = portNodes.FirstOrDefault().InnerText;
var currArg = s.Split(new char[] { ',' });
dto.From.portList.Add(new TransPlanHasChangePortDto
{
Indx = 1,
PortName = currArg[0].Trim(),
IsRemoved = portNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
CountryCode = currArg[1].Trim(),
TerminalName = currArg[2].Trim(),
});
}
else if (portNodes.Count > 1)
{
for (int t = 0; t < portNodes.Count; t++)
{
string s = portNodes[t].InnerText;
var currArg = s.Split(new char[] { ',' });
dto.From.portList.Add(new TransPlanHasChangePortDto
{
Indx = t + 1,
PortName = currArg[0].Trim(),
IsRemoved = portNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
CountryCode = currArg[1].Trim(),
TerminalName = currArg[2].Trim(),
});
}
}
//date
var dateNodes = rootDivNode[i + 1].SelectNodes("./table[1]/tbody/tr/th[3]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (dateNodes.Count == 1)
{
string s = dateNodes.FirstOrDefault().InnerText;
var currInfo = new TransPlanHasChangeDateDto
{
Indx = 1,
OrigDateTxt = s,
IsRemoved = dateNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
};
DateTime currDate = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(s))
{
if (DateTime.TryParse(s, out currDate))
currInfo.DateVal = currDate;
}
dto.From.dateList.Add(currInfo);
}
else if (dateNodes.Count > 1)
{
for (int t = 0; t < dateNodes.Count; t++)
{
string s = dateNodes[t].InnerText;
var currInfo = new TransPlanHasChangeDateDto
{
Indx = t + 1,
OrigDateTxt = s,
IsRemoved = dateNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
};
DateTime currDate = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(s))
{
if (DateTime.TryParse(s, out currDate))
currInfo.DateVal = currDate;
}
dto.From.dateList.Add(currInfo);
}
}
//vessel
var vesselNodes = rootDivNode[i + 1].SelectNodes("./table[1]/tbody/tr/th[4]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (vesselNodes.Count == 1)
{
string s = vesselNodes.FirstOrDefault().InnerText;
var currArg = s.Split(new char[] { ',' });
dto.From.vesselList.Add(new TransPlanHasChangeVesselVoynoDto
{
Indx = 1,
Vessel = currArg[0].Trim(),
IsRemoved = vesselNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
Voyno = currArg[1].Trim(),
Flag = currArg[2].Trim(),
});
}
else if (vesselNodes.Count > 1)
{
for (int t = 0; t < vesselNodes.Count; t++)
{
string s = vesselNodes[t].InnerText;
var currArg = s.Split(new char[] { ',' });
dto.From.vesselList.Add(new TransPlanHasChangeVesselVoynoDto
{
Indx = t + 1,
Vessel = currArg[0].Trim(),
IsRemoved = vesselNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
Voyno = currArg[1].Trim(),
Flag = currArg[2].Trim(),
});
}
}
}
if (Regex.IsMatch(title2, "((到达计划)|(To))", RegexOptions.IgnoreCase))
{
//to
//port
var portNodes = rootDivNode[i + 1].SelectNodes("./table[2]/tbody/tr/th[2]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (portNodes.Count == 1)
{
string s = portNodes.FirstOrDefault().InnerText;
var currArg = s.Split(new char[] { ',' });
dto.To.portList.Add(new TransPlanHasChangePortDto
{
Indx = 1,
PortName = currArg[0].Trim(),
IsRemoved = portNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
CountryCode = currArg[1].Trim(),
TerminalName = currArg[2].Trim(),
});
}
else if (portNodes.Count > 1)
{
for (int t = 0; t < portNodes.Count; t++)
{
string s = portNodes[t].InnerText;
var currArg = s.Split(new char[] { ',' });
dto.To.portList.Add(new TransPlanHasChangePortDto
{
Indx = t + 1,
PortName = currArg[0].Trim(),
IsRemoved = portNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
CountryCode = currArg[1].Trim(),
TerminalName = currArg[2].Trim(),
});
}
}
//date
var dateNodes = rootDivNode[i + 1].SelectNodes("./table[2]/tbody/tr/th[3]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (dateNodes.Count == 1)
{
string s = dateNodes.FirstOrDefault().InnerText;
var currInfo = new TransPlanHasChangeDateDto
{
Indx = 1,
OrigDateTxt = s,
IsRemoved = dateNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
};
DateTime currDate = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(s))
{
if (DateTime.TryParse(s, out currDate))
currInfo.DateVal = currDate;
}
dto.To.dateList.Add(currInfo);
}
else if (dateNodes.Count > 1)
{
for (int t = 0; t < dateNodes.Count; t++)
{
string s = dateNodes[t].InnerText;
var currInfo = new TransPlanHasChangeDateDto
{
Indx = t + 1,
OrigDateTxt = s,
IsRemoved = dateNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
};
DateTime currDate = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(s))
{
if (DateTime.TryParse(s, out currDate))
currInfo.DateVal = currDate;
}
dto.To.dateList.Add(currInfo);
}
}
//vessel
var vesselNodes = rootDivNode[i + 1].SelectNodes("./table[2]/tbody/tr/th[4]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (vesselNodes.Count == 1)
{
string s = vesselNodes.FirstOrDefault().InnerText;
var currArg = s.Split(new char[] { ',' });
dto.To.vesselList.Add(new TransPlanHasChangeVesselVoynoDto
{
Indx = 1,
Vessel = currArg[0].Trim(),
IsRemoved = vesselNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
Voyno = currArg[1].Trim(),
Flag = currArg[2].Trim(),
});
}
else if (vesselNodes.Count > 1)
{
for (int t = 0; t < vesselNodes.Count; t++)
{
string s = vesselNodes[t].InnerText;
var currArg = s.Split(new char[] { ',' });
dto.To.vesselList.Add(new TransPlanHasChangeVesselVoynoDto
{
Indx = t + 1,
Vessel = currArg[0].Trim(),
IsRemoved = vesselNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
Voyno = currArg[1].Trim(),
Flag = currArg[2].Trim(),
});
}
}
}
list.Add(dto);
}
#endregion
}
}
}
}
5 months ago
public void SyncServiceProjectRecord6()
{
string mailFilePath = "C:\\Users\\Administrator\\Desktop\\日志\\For Information - Shipment # 234581255.eml";
//读取邮件,解析邮件正文
MimeMessage mimeMsg = MimeMessage.Load(mailFilePath);
var strBody = mimeMsg.HtmlBody;
HtmlDocument html = new HtmlDocument();
html.LoadHtml(strBody);
//获取第一个font节点的内容
var baseNode = html.DocumentNode.SelectSingleNode("//font[1]");
5 months ago
var s = baseNode.InnerText;
string billNo = string.Empty;
//提取单号
if(Regex.IsMatch(s,"(?<=订舱号)[a-zA-Z0-9]+"))
{
billNo = Regex.Match(s, "(?<=订舱号)[a-zA-Z0-9]+").Value;
}
var baseNodes = baseNode.SelectNodes("./b");
5 months ago
}
5 months ago
public class ForInformationShipmentNotice
{
/// <summary>
/// 提单号
/// </summary>
public string BillNo { get; set; }
/// <summary>
/// 通知内容
/// </summary>
public string Notice { get; set; }
5 months ago
}
private List<TransPlanHasChangeDto> GetChildList(HtmlNode node)
{
List<TransPlanHasChangeDto> list = new List<TransPlanHasChangeDto>();
string firstBillNo = string.Empty;
string firstBookingNo = string.Empty;
//string firstCtnNo = string.Empty;
bool isDiv = false;
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (node.ChildNodes[i].Name.Equals("table", StringComparison.OrdinalIgnoreCase))
{
var currLabel1 = node.ChildNodes[i].SelectSingleNode($"./tbody/tr[1]/th[1]/table/tr[1]/th[1]/table/tbody/tr[1]/th[1]").InnerText.ReplaceHtmlStr();
var currValue2Node = node.ChildNodes[i].SelectSingleNode("./tbody/tr[1]/th[1]/table/tr[1]/th[1]/table/tbody/tr[1]/th[2]");
if (!string.IsNullOrWhiteSpace(currLabel1))
{
if (currLabel1.Equals("订舱号") || Regex.IsMatch(currLabel1, "Booking\\s+Number", RegexOptions.IgnoreCase))
{
if(currValue2Node != null)
{
firstBookingNo = currValue2Node.InnerText.ReplaceHtmlStr();
}
}
else if (currLabel1.Equals("提单号码") || Regex.IsMatch(currLabel1, "Bill\\s+of\\s+Lading", RegexOptions.IgnoreCase))
{
if (currValue2Node != null)
{
firstBillNo = currValue2Node.InnerText.ReplaceHtmlStr();
}
}
}
break;
}
else
{
if (node.ChildNodes[i].Name.Equals("div", StringComparison.OrdinalIgnoreCase))
isDiv = true;
}
}
//先获取第一层的div
var rootDivNode = node.ChildNodes.Where(a => a.Name.Equals("div", StringComparison.OrdinalIgnoreCase)
&& a.Attributes.Contains("class") && (a.Attributes["class"].Value.Equals("data__top") || a.Attributes["class"].Value.Equals("data")))
.ToList();
for (int i = 0; i < rootDivNode.Count; i++)
{
//先取top
if (rootDivNode[i].Attributes["class"].Value.Equals("data__top", StringComparison.OrdinalIgnoreCase))
{
TransPlanHasChangeDto dto = new TransPlanHasChangeDto
{
From = new TransPlanHasChangeDetailDto
{
portList = new List<TransPlanHasChangePortDto>(),
dateList = new List<TransPlanHasChangeDateDto>(),
vesselList = new List<TransPlanHasChangeVesselVoynoDto>()
},
To = new TransPlanHasChangeDetailDto
{
portList = new List<TransPlanHasChangePortDto>(),
dateList = new List<TransPlanHasChangeDateDto>(),
vesselList = new List<TransPlanHasChangeVesselVoynoDto>()
},
Carrier = "MSK",
ContaNoList = new List<string>()
};
if (i == rootDivNode.Count - 1)
{
var innerList = GetChildList(rootDivNode[i]);
if (innerList != null && innerList.Count > 0)
{
list.AddRange(innerList);
}
}
else
{
#region 解析TOP
var ctnNode = rootDivNode[i].SelectSingleNode("./table[not(contains(@class,'reason'))]/tbody/tr[1]/th[contains(@class,'last')]");
if (ctnNode != null)
{
string s = ctnNode.SelectSingleNode("./table/tr/th/table/tbody/tr/th/table/tr/th").InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(s) && (Regex.IsMatch(s, "集装箱号码") || Regex.IsMatch(s, "Container\\(s\\)")))
{
string ctnStr = Regex.Match(s, "(?<=集装箱号码).*").Value?.Trim();
if (string.IsNullOrWhiteSpace(ctnStr))
{
ctnStr = Regex.Match(s, "(?<=Container\\(s\\)).*").Value?.Trim();
}
if (ctnStr.IndexOf(",") >= 0)
{
dto.ContaNoList = ctnStr.Split(new char[] { ',' }).Select(a => a.Trim()).ToList();
}
else
{
if (!string.IsNullOrWhiteSpace(ctnStr))
dto.ContaNoList.Add(ctnStr.Trim());
}
}
}
Dictionary<int, string> labelDict = new Dictionary<int, string>();
Dictionary<int, string> valDict = new Dictionary<int, string>();
Dictionary<int, Tuple<string, string>> reasonDict = new Dictionary<int, Tuple<string, string>>();
string lableXpath = "./table[not(contains(@class,'reason'))]/tbody/tr[1]/th[1]/table/tr[1]/";
var currLabel1 = rootDivNode[i].SelectSingleNode($"{lableXpath}/th[1]/table/tbody/tr[1]/th[1]").InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(currLabel1))
{
labelDict.Add(1, currLabel1);
}
var currLabel2Node = rootDivNode[i].SelectSingleNode("./table[not(contains(@class,'reason'))]/tbody/tr[1]/th[1]/table/tbody/tr[1]/th[1]/table/tr[2]/th[1]");
if (currLabel2Node != null)
{
var currLabel2 = currLabel2Node.InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(currLabel2))
{
labelDict.Add(2, currLabel2);
}
}
var currValue1 = rootDivNode[i].SelectSingleNode($"{lableXpath}/th[2]/table/tr[1]/th[1]").InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(currValue1))
{
valDict.Add(1, currValue1);
}
var currValue2Node = rootDivNode[i].SelectSingleNode("./table[not(contains(@class,'reason'))]/tbody/tr[1]/th[1]/table/tbody/tr[1]/th[2]/table/tr[2]/th[1]");
if (currValue2Node != null)
{
var currValue2 = currValue2Node.InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(currValue2))
{
valDict.Add(2, currValue2);
}
}
foreach (KeyValuePair<int, string> kvp in labelDict)
{
if (kvp.Value.Equals("订舱号") || Regex.IsMatch(kvp.Value, "Booking\\s+Number", RegexOptions.IgnoreCase))
{
dto.BookingNo = valDict[kvp.Key];
}
else if (kvp.Value.Equals("提单号码") || Regex.IsMatch(kvp.Value, "Bill\\s+of\\s+Lading", RegexOptions.IgnoreCase))
{
if (Regex.IsMatch(valDict[kvp.Key], "BL\\s+number\\s+not\\s+yet\\s+generated", RegexOptions.IgnoreCase))
{
dto.BillNotes = valDict[kvp.Key];
if(i ==0)
{
dto.BillNo = firstBillNo;
}
}
else
{
dto.BillNo = valDict[kvp.Key];
}
}
}
string reason1 = string.Empty;
string reason2 = string.Empty;
bool isReasonNote = false;
var reasonTables = rootDivNode[i].SelectNodes("./table[contains(@class,'reason')]");
if (reasonTables.Count > 0)
{
for (int k = 0; k < reasonTables.Count; k++)
{
var thFirstNode = rootDivNode[i].SelectSingleNode("./table[contains(@class,'reason')][" + (k + 1) + "]/tbody/tr/th[contains(@class,'columns first')]");
if (thFirstNode != null)
{
isReasonNote = true;
}
if (!isReasonNote)
{
string s = rootDivNode[i].SelectSingleNode("./table[contains(@class,'reason')][" + (k + 1) + "]/tr/th").InnerText.ReplaceHtmlStr();
if (!string.IsNullOrWhiteSpace(s) && s.IndexOf("此订舱号派生自原单号") >= 0)
{
reasonDict.Add(k + 1, new Tuple<string, string>(s, Regex.Match(s, "(?<=此订舱号派生自原单号\\:)\\?\\w+").Value?.Trim()));
}
}
else
{
var labelNode = rootDivNode[i].SelectSingleNode("./table[contains(@class,'reason')][" + (k + 1) + "]/tbody/tr/th[contains(@class,'columns first')]");
var notesNode = rootDivNode[i].SelectSingleNode("./table[contains(@class,'reason')][" + (k + 1) + "]/tbody/tr/th[contains(@class,'columns last')]");
string label = string.Empty;
string notes = string.Empty;
if (labelNode != null)
{
label = labelNode.InnerText.ReplaceHtmlStr();
}
if (notesNode != null)
{
notes = notesNode.InnerText.ReplaceHtmlStr();
}
if (!string.IsNullOrWhiteSpace(notes))
{
reasonDict.Add(k + 1, new Tuple<string, string>(label, notes));
}
}
}
}
foreach (KeyValuePair<int, Tuple<string, string>> kvp in reasonDict)
{
if (Regex.IsMatch(kvp.Value.Item1, "此订舱号派生自原单号", RegexOptions.IgnoreCase))
{
dto.OrigBillNo = kvp.Value.Item2;
}
else if (Regex.IsMatch(kvp.Value.Item1, "((变更原因)|(Reason))", RegexOptions.IgnoreCase))
{
dto.ChangeReasonNotes = kvp.Value.Item2;
}
}
#endregion
#region 解析DATA
//如果下一个节点是data表示后面是详情
if (rootDivNode[i + 1].Attributes["class"].Value.Equals("data", StringComparison.OrdinalIgnoreCase))
{
var title = rootDivNode[i + 1].SelectSingleNode("./table[1]/tbody/tr/th[1]/table/tr/th").InnerText.ReplaceHtmlStr();
var title2 = rootDivNode[i + 1].SelectSingleNode("./table[2]/tbody/tr/th[1]/table/tr/th").InnerText.ReplaceHtmlStr();
var title3 = rootDivNode[i + 1].SelectSingleNode(".//b[1]");
if (title3 != null)
{
dto.PleaseNotes = title3.InnerText.ReplaceHtmlStr();
}
//From
if (Regex.IsMatch(title, "((出运计划)|(From))", RegexOptions.IgnoreCase))
{
//port
var portNodes = rootDivNode[i + 1].SelectNodes("./table[1]/tbody/tr/th[2]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (portNodes.Count == 1)
{
string s = portNodes.FirstOrDefault().InnerText;
var currArg = s.Split(new char[] { ',' });
dto.From.portList.Add(new TransPlanHasChangePortDto
{
Indx = 1,
PortName = currArg[0].Trim(),
IsRemoved = portNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
CountryCode = currArg[1].Trim(),
TerminalName = currArg[2].Trim(),
});
}
else if (portNodes.Count > 1)
{
for (int t = 0; t < portNodes.Count; t++)
{
string s = portNodes[t].InnerText;
var currArg = s.Split(new char[] { ',' });
dto.From.portList.Add(new TransPlanHasChangePortDto
{
Indx = t + 1,
PortName = currArg[0].Trim(),
IsRemoved = portNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
CountryCode = currArg[1].Trim(),
TerminalName = currArg[2].Trim(),
});
}
}
//date
var dateNodes = rootDivNode[i + 1].SelectNodes("./table[1]/tbody/tr/th[3]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (dateNodes.Count == 1)
{
string s = dateNodes.FirstOrDefault().InnerText;
var currInfo = new TransPlanHasChangeDateDto
{
Indx = 1,
OrigDateTxt = s,
IsRemoved = dateNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
};
DateTime currDate = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(s))
{
if (DateTime.TryParse(s, out currDate))
currInfo.DateVal = currDate;
}
dto.From.dateList.Add(currInfo);
}
else if (dateNodes.Count > 1)
{
for (int t = 0; t < dateNodes.Count; t++)
{
string s = dateNodes[t].InnerText;
var currInfo = new TransPlanHasChangeDateDto
{
Indx = t + 1,
OrigDateTxt = s,
IsRemoved = dateNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
};
DateTime currDate = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(s))
{
if (DateTime.TryParse(s, out currDate))
currInfo.DateVal = currDate;
}
dto.From.dateList.Add(currInfo);
}
}
//vessel
var vesselNodes = rootDivNode[i + 1].SelectNodes("./table[1]/tbody/tr/th[4]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (vesselNodes.Count == 1)
{
string s = vesselNodes.FirstOrDefault().InnerText;
var currArg = s.Split(new char[] { ',' });
dto.From.vesselList.Add(new TransPlanHasChangeVesselVoynoDto
{
Indx = 1,
Vessel = currArg[0].Trim(),
IsRemoved = vesselNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
Voyno = currArg[1].Trim(),
Flag = currArg[2].Trim(),
});
}
else if (vesselNodes.Count > 1)
{
for (int t = 0; t < vesselNodes.Count; t++)
{
string s = vesselNodes[t].InnerText;
var currArg = s.Split(new char[] { ',' });
dto.From.vesselList.Add(new TransPlanHasChangeVesselVoynoDto
{
Indx = t + 1,
Vessel = currArg[0].Trim(),
IsRemoved = vesselNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
Voyno = currArg[1].Trim(),
Flag = currArg[2].Trim(),
});
}
}
}
if (Regex.IsMatch(title2, "((到达计划)|(To))", RegexOptions.IgnoreCase))
{
//to
//port
var portNodes = rootDivNode[i + 1].SelectNodes("./table[2]/tbody/tr/th[2]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (portNodes.Count == 1)
{
string s = portNodes.FirstOrDefault().InnerText;
var currArg = s.Split(new char[] { ',' });
dto.To.portList.Add(new TransPlanHasChangePortDto
{
Indx = 1,
PortName = currArg[0].Trim(),
IsRemoved = portNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
CountryCode = currArg[1].Trim(),
TerminalName = currArg[2].Trim(),
});
}
else if (portNodes.Count > 1)
{
for (int t = 0; t < portNodes.Count; t++)
{
string s = portNodes[t].InnerText;
var currArg = s.Split(new char[] { ',' });
dto.To.portList.Add(new TransPlanHasChangePortDto
{
Indx = t + 1,
PortName = currArg[0].Trim(),
IsRemoved = portNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
CountryCode = currArg[1].Trim(),
TerminalName = currArg[2].Trim(),
});
}
}
//date
var dateNodes = rootDivNode[i + 1].SelectNodes("./table[2]/tbody/tr/th[3]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (dateNodes.Count == 1)
{
string s = dateNodes.FirstOrDefault().InnerText;
var currInfo = new TransPlanHasChangeDateDto
{
Indx = 1,
OrigDateTxt = s,
IsRemoved = dateNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
};
DateTime currDate = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(s))
{
if (DateTime.TryParse(s, out currDate))
currInfo.DateVal = currDate;
}
dto.To.dateList.Add(currInfo);
}
else if (dateNodes.Count > 1)
{
for (int t = 0; t < dateNodes.Count; t++)
{
string s = dateNodes[t].InnerText;
var currInfo = new TransPlanHasChangeDateDto
{
Indx = t + 1,
OrigDateTxt = s,
IsRemoved = dateNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
};
DateTime currDate = DateTime.MinValue;
if (!string.IsNullOrWhiteSpace(s))
{
if (DateTime.TryParse(s, out currDate))
currInfo.DateVal = currDate;
}
dto.To.dateList.Add(currInfo);
}
}
//vessel
var vesselNodes = rootDivNode[i + 1].SelectNodes("./table[2]/tbody/tr/th[4]/table/tr/th//div[contains(@class,'remove') or contains(@class,'updated') or contains(@class,'no-change')]");
if (vesselNodes.Count == 1)
{
string s = vesselNodes.FirstOrDefault().InnerText;
var currArg = s.Split(new char[] { ',' });
dto.To.vesselList.Add(new TransPlanHasChangeVesselVoynoDto
{
Indx = 1,
Vessel = currArg[0].Trim(),
IsRemoved = vesselNodes[0].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
Voyno = currArg[1].Trim(),
Flag = currArg[2].Trim(),
});
}
else if (vesselNodes.Count > 1)
{
for (int t = 0; t < vesselNodes.Count; t++)
{
string s = vesselNodes[t].InnerText;
var currArg = s.Split(new char[] { ',' });
dto.To.vesselList.Add(new TransPlanHasChangeVesselVoynoDto
{
Indx = t + 1,
Vessel = currArg[0].Trim(),
IsRemoved = vesselNodes[t].Attributes["class"].Value.Equals("remove", StringComparison.OrdinalIgnoreCase),
Voyno = currArg[1].Trim(),
Flag = currArg[2].Trim(),
});
}
}
}
list.Add(dto);
}
#endregion
}
}
}
return list;
}
#region 读BC详情详情
/// <summary>
/// 读BC详情详情
/// </summary>
/// <param name="attachFullName">文件完整路径</param>
/// <param name="fileName">文件名称</param>
/// <param name="tenantId">所属租户</param>
/// <param name="taskPKId">任务ID</param>
/// <param name="url">请求URL</param>
/// <returns></returns>
private async Task<TaskBCInfoReadDto> GetBCReaderInfo(string attachFullName, string fileName, long tenantId, string taskPKId, string url)
{
TaskBCInfoReadDto taskBCInfoReadDto = null;
try
{
DateTime nowDate = DateTime.Now;
EmailBCReadMessageInfo messageInfo = new EmailBCReadMessageInfo
{
Head = new TaskMessageHead
{
GID = IDGen.NextID().ToString(),
MessageType = "BOOKING_AMENDMENT",
SenderId = "DJY",
SenderName = "新大简云",
ReceiverId = "RulesEngine",
ReceiverName = "大简云规则引擎",
Version = "1.0",
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
RequestAction = "ReadFile",
},
Main = new EmailBCReadMessageMainInfo
{
TenantId = tenantId > 0 ? tenantId.ToString() : ""
}
};
NameValueCollection par = new NameValueCollection();
par.Add("jsonData", JSON.Serialize(messageInfo));
//解析BookingAmendment
var compareRlt = await ExcuteReadFile(par, url, new
{
file = "file",
fileName = fileName,
fileBytes = File.ReadAllBytes(attachFullName)
});
_logger.LogInformation($"读取BC附件详情 taskPKId={taskPKId}compareRlt={JSON.Serialize(compareRlt)}");
if (compareRlt.succ)
{
taskBCInfoReadDto = JSON.Deserialize<TaskBCInfoReadDto>(JSON.Serialize(compareRlt.extra));
}
}
catch (Exception ex)
{
_logger.LogError($"读取BC附件详情异常原因{ex.Message}");
}
return taskBCInfoReadDto;
}
#endregion
#region 请求BookingAmendment解析
/// <summary>
/// 请求BookingAmendment解析
/// </summary>
/// <param name="nameValueCollection">请求参数</param>
/// <param name="url">请求url</param>
/// <param name="fileInfo">文件</param>
/// <param name="contentType">请求类型</param>
/// <returns>返回回执</returns>
[NonAction]
private async Task<ParserReaderExcuteResultDto> ExcuteReadFile(NameValueCollection nameValueCollection, string url, dynamic fileInfo,
string contentType = "application/json")
{
ParserReaderExcuteResultDto 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.ContentDisposition = new ContentDispositionHeaderValue("form-data")
//{
// Name = fileInfo.file.ToString(),
// FileName = fileInfo.fileName.ToString(),
//};
Content.Headers.Add("Content-Type", contentType);
reduceAttach.Add(Content, fileInfo.file.ToString(), HttpUtility.UrlEncode(fileInfo.fileName.ToString()));
}
#endregion
//httpClient.DefaultRequestHeaders.Add("USER_KEY", App.Configuration["ApiUserKey"]);
//httpClient.DefaultRequestHeaders.Add("USER_SECRET", App.Configuration["ApiUserSecret"]);
//请求
var response = httpClient.PostAsync(url, reduceAttach).Result;
result = response.Content.ReadAsStringAsync().Result;
model = JSON.Deserialize<ParserReaderExcuteResultDto>(result);
}
}
catch (Exception ex)
{
_logger.LogInformation("请求读取BC附件详情读取详情异常原因{error}", ex.Message);
throw Oops.Oh($"请求读取BC附件详情读取详情异常原因{ex.Message}");
}
}
return model;
}
#endregion
public class EmailBCReadMessageInfo
{
/// <summary>
/// 表头
/// </summary>
public TaskMessageHead Head { get; set; }
/// <summary>
/// 表体
/// </summary>
public EmailBCReadMessageMainInfo Main { get; set; }
}
public class EmailBCReadMessageMainInfo
{
/// <summary>
/// 所属租户ID
/// </summary>
public string TenantId { get; set; }
}
public class TaskMessageHead : WebAPIHeadBase
{
11 months ago
}
public class WebAPIHeadBase
{
/// <summary>
/// 报文惟一主键
/// </summary>
/// <example>08dab66c-96a1-4f90-8606-2626e06202ad</example>
[Required(ErrorMessage = "必填")]
public string GID { get; set; }
/// <summary>
/// 报文类型 BUSI_RULE-业务规则校验
/// </summary>
/// <example>BUSI_RULE</example>
[Required(ErrorMessage = "必填")]
public string MessageType { get; set; }
/// <summary>
/// 发送方代码
/// </summary>
/// <example>CUSTOMER1</example>
[Required(ErrorMessage = "必填")]
public string SenderId { get; set; }
/// <summary>
/// 发送方名称
/// </summary>
/// <example>企业A</example>
[Required(ErrorMessage = "必填")]
public string SenderName { get; set; }
/// <summary>
/// 接收方代码
/// </summary>
/// <example>RulesEngine</example>
[Required(ErrorMessage = "必填")]
public string ReceiverId { get; set; }
/// <summary>
/// 接收方名称
/// </summary>
/// <example>大简云规则引擎</example>
[Required(ErrorMessage = "必填")]
public string ReceiverName { get; set; }
/// <summary>
/// 请求方登录TOKEN可以是真实的登录人TOKEN或者是服务模拟登录人TOKEN
/// </summary>
/// <example>eyJhbGciOiJSUzI1NiIsImtpZCI6IkQ1RTkxMDI5OUU0RURFNUZEM0EwNTJBMEFDRDUzMUQzIiwidHlwIjoiYXQrand0In0</example>
public string Token { get; set; }
/// <summary>
/// 版本号 默认1.0
/// </summary>
/// <example>1.0</example>
[Required(ErrorMessage = "必填")]
public string Version { get; set; } = "1.0";
/// <summary>
/// 请求时间
/// </summary>
/// <example>2022-10-10 10:00:00</example>
public string RequestDate { get; set; }
/// <summary>
/// 请求操作类型
/// </summary>
/// <example>Add</example>
[Required(ErrorMessage = "必填")]
public string RequestAction { get; set; } = "Add";
}
}
public class ParserReaderExcuteResultDto
{
/// <summary>
/// 是否成功 true=成功 false=失败
/// </summary>
public bool succ { get; set; } = false;
/// <summary>
/// 状态 0-成功
/// </summary>
public int status { get; set; } = 0;
/// <summary>
/// 返回消息
/// </summary>
public string msg { get; set; }
/// <summary>
/// 总记录数
/// </summary>
public int total { get; set; }
/// <summary>
/// 当前页列表数据
/// </summary>
public object rows { get; set; }
/// <summary>
/// 合计信息
/// </summary>
public object summary { get; set; }
/// <summary>
/// 扩展信息
/// </summary>
public object extra { get; set; }
/// <summary>
/// 扩展信息2
/// </summary>
public object extra2 { get; set; }
/// <summary>
/// 扩展信息场站统计
/// </summary>
public object yardStatInfo { get; set; }
/// <summary>
/// 是否异常
/// </summary>
public bool exceptionflag { get; set; }
/// <summary>
/// 生成HTML
/// </summary>
public string ResultHtml { get; set; }
}
/// <summary>
///
/// </summary>
public class TaskBCInfoReadDto
{
/// <summary>
/// 订舱单位
/// </summary>
public string BookingParty { get; set; }
/// <summary>
/// 发货人
/// </summary>
public string Shipper { get; set; }
/// <summary>
/// 收货人
/// </summary>
public string Consignee { get; set; }
/// <summary>
/// 通知人
/// </summary>
public string NotifyParty { get; set; }
/// <summary>
/// BC更新次数
/// </summary>
public Nullable<int> BCModifyTimes { get; set; }
/// <summary>
/// BC更新时间
/// </summary>
public Nullable<DateTime> BCModifyDate { get; set; }
/// <summary>
/// 主单号
/// </summary>
public string MBLNo { get; set; }
/// <summary>
/// 船名
/// </summary>
public string Vessel { get; set; }
/// <summary>
/// 航次
/// </summary>
public string VoyNo { get; set; }
/// <summary>
/// 船公司
/// </summary>
public string Carrier { get; set; }
/// <summary>
/// 收货地
/// </summary>
public string PlaceReceipt { get; set; }
/// <summary>
/// 装货港
/// </summary>
public string Portload { get; set; }
/// <summary>
/// 截关时间
/// </summary>
public Nullable<DateTime> ClosingDate { get; set; }
/// <summary>
/// 截VGM时间
/// </summary>
public Nullable<DateTime> VGMCutoffTime { get; set; }
/// <summary>
/// ETA(预计到港时间)
/// </summary>
public Nullable<DateTime> ETA { get; set; }
/// <summary>
/// ETD(预计离港时间)
/// </summary>
public Nullable<DateTime> ETD { get; set; }
/// <summary>
/// 目的港ETA
/// </summary>
public Nullable<DateTime> PODETA { get; set; }
/// <summary>
/// 截单时间
/// </summary>
public Nullable<DateTime> CutSingleTime { get; set; }
/// <summary>
/// 卸货港
/// </summary>
public string PortDischarge { get; set; }
/// <summary>
/// 交货地
/// </summary>
public string PlaceDelivery { get; set; }
/// <summary>
/// 装运方式
/// </summary>
public string ShippingMethod { get; set; }
/// <summary>
/// 运输条款
/// </summary>
public string Service { get; set; }
/// <summary>
/// 港前运输形态
/// </summary>
public string PreTransMode { get; set; }
/// <summary>
/// 品名
/// </summary>
public string Description { get; set; }
/// <summary>
/// 签单地点
/// </summary>
public string IssuePlace { get; set; }
/// <summary>
/// 集港码头
/// </summary>
public string CollectionTerminal { get; set; }
/// <summary>
/// 约号
/// </summary>
public string ContractNo { get; set; }
/// <summary>
/// 预付地点
/// </summary>
public string PrepardAT { get; set; }
/// <summary>
/// 船代
/// </summary>
public string ShipAgent { get; set; }
/// <summary>
/// 场站
/// </summary>
public string Yard { get; set; }
/// <summary>
/// 场站联系人
/// </summary>
public string YardContactUserName { get; set; }
/// <summary>
/// 场站联系电话
/// </summary>
public string YardContactTel { get; set; }
/// <summary>
/// 一代客服姓名
/// </summary>
public string FstCustomerSerUserName { get; set; }
/// <summary>
/// 一代客服电话
/// </summary>
public string FstCustomerSerUserTel { get; set; }
/// <summary>
/// 一代客服邮箱
/// </summary>
public string FstCustomerSerUserEmail { get; set; }
/// <summary>
/// 备注1
/// </summary>
public string Remark1 { get; set; }
/// <summary>
/// 截港时间
/// </summary>
public Nullable<DateTime> CYCutoffTime { get; set; }
/// <summary>
/// 状态 TEMP-暂存 SUCC-已对应 ERROR-异常
/// </summary>
public string Status { get; set; }
/// <summary>
/// 文件MD5
/// </summary>
public string FileMD5 { get; set; }
/// <summary>
/// 最后对应时间,最后关联到订舱日期
/// </summary>
public Nullable<DateTime> LastToBookingDate { get; set; }
/// <summary>
/// 来源邮箱
/// </summary>
public string FromEmail { get; set; }
/// <summary>
/// 接收邮箱
/// </summary>
public string RecvEmail { get; set; }
/// <summary>
/// 订舱ID对应成功后订舱ID写入
/// </summary>
public Nullable<long> BookingOrderId { get; set; }
/// <summary>
/// 集装箱列表
/// </summary>
public List<TaskBCInfoReadCtnDto> CtnList { get; set; }
/// <summary>
/// 顺序号
/// </summary>
public int Indx { get; set; }
/// <summary>
/// 对应订舱序号
/// </summary>
public int BKOrderIndx { get; set; }
/// <summary>
/// 舱位主键
/// </summary>
public Nullable<long> BookingSlotId { get; set; }
/// <summary>
/// 船公司代号
/// </summary>
public string CarrierId { get; set; }
/// <summary>
/// 航线代码(船公司)
/// </summary>
public string LaneCode { get; set; }
/// <summary>
/// 航线名称(船公司)
/// </summary>
public string LaneName { get; set; }
/// <summary>
/// 承运方式 DIRECT_SHIP-直达TRANSFER_SHIP-中转
/// </summary>
public string CarriageType { get; set; }
/// <summary>
/// 承运方式名称 DIRECT_SHIP-直达TRANSFER_SHIP-中转
/// </summary>
public string CarriageTypeName { get; set; }
/// <summary>
/// 订舱方式 CONTRACT_ORDER-合约订舱SPOT_ORDER-SPOT订舱
/// </summary>
public string BookingSlotType { get; set; }
/// <summary>
/// 订舱方式名称 CONTRACT_ORDER-合约订舱SPOT_ORDER-SPOT订舱
/// </summary>
public string BookingSlotTypeName { get; set; }
/// <summary>
/// 箱型箱量
/// </summary>
public string CtnStat { get; set; }
/// <summary>
/// 所在周数
/// </summary>
public string WeekAt { get; set; }
/// <summary>
/// 箱使天数
/// </summary>
public int DetensionFreeDays { get; set; }
/// <summary>
/// 样单截止日期
/// </summary>
public Nullable<DateTime> SICutDate { get; set; }
/// <summary>
/// 舱单截止时间
/// </summary>
public Nullable<DateTime> ManifestCutDate { get; set; }
/// <summary>
/// MDGF提交截止时间
/// </summary>
public Nullable<DateTime> MDGFCutDate { get; set; }
/// <summary>
/// 中转港1
/// </summary>
public string TransferPort1 { get; set; }
/// <summary>
/// 中转港2
/// </summary>
public string TransferPort2 { get; set; }
/// <summary>
/// 二程船名
/// </summary>
public string SecondVessel { get; set; }
/// <summary>
/// 二程航次
/// </summary>
public string SecondVoyno { get; set; }
/// <summary>
/// 二程ETD
/// </summary>
public Nullable<DateTime> SecondETD { get; set; }
/// <summary>
/// 二程ETA
/// </summary>
public Nullable<DateTime> SecondETA { get; set; }
/// <summary>
/// 订舱确认时间
/// </summary>
public Nullable<DateTime> BookingConfirmDate { get; set; }
/// <summary>
/// 客户样单截止日期
/// </summary>
public Nullable<DateTime> CustomSICutDate { get; set; }
}
11 months ago
/// <summary>
/// 任务BC集装箱
/// </summary>
public class TaskBCInfoReadCtnDto
{
/// <summary>
/// 箱型代码
/// </summary>
public string CtnCode { get; set; }
/// <summary>
/// 箱型
/// </summary>
public string CtnALL { get; set; }
/// <summary>
/// 箱量
/// </summary>
public Nullable<int> CTNNUM { get; set; }
/// <summary>
/// 件数
/// </summary>
public Nullable<int> PKGS { get; set; }
/// <summary>
/// 尺码
/// </summary>
public Nullable<decimal> CBM { get; set; }
/// <summary>
/// 毛重
/// </summary>
public Nullable<decimal> KGS { get; set; }
/// <summary>
/// 皮重
/// </summary>
public Nullable<decimal> TareWeight { get; set; }
/// <summary>
/// 危品票标示
/// </summary>
public string IODGT { get; set; }
/// <summary>
/// 特殊装载需求
/// </summary>
public string SpecialLoadingRequire { get; set; }
/// <summary>
/// 提箱场站
/// </summary>
public string TakeCTNYard { get; set; }
/// <summary>
/// 提箱时间
/// </summary>
public Nullable<DateTime> TakeCTNTime { get; set; }
/// <summary>
/// 还箱场站
/// </summary>
public string ReturnCTNYard { get; set; }
}
/// <summary>
/// MSK 您的货物运输计划已变更
/// </summary>
public class TransPlanHasChangeDto
{
/// <summary>
/// 订舱编号
/// </summary>
public string BookingNo { get; set; }
/// <summary>
/// 船公司代码
/// </summary>
public string Carrier { get; set; }
/// <summary>
/// 提单号码
/// </summary>
public string BillNo { get; set; }
/// <summary>
/// 派生自原单号
/// </summary>
public string OrigBillNo { get; set; }
/// <summary>
/// 集装箱号列表
/// </summary>
public List<string> ContaNoList { get; set; }
/// <summary>
/// 变更原因
/// </summary>
public string ChangeReasonNotes { get; set; }
/// <summary>
/// 出运计划
/// </summary>
public TransPlanHasChangeDetailDto From { get; set; }
/// <summary>
/// 到达计划
/// </summary>
public TransPlanHasChangeDetailDto To { get; set; }
/// <summary>
/// 特别提示
/// </summary>
public string PleaseNotes { get; set; }
/// <summary>
/// 提单号特殊提示
/// </summary>
public string BillNotes { get; set; }
}
/// <summary>
/// 您的货物运输计划已变更明细
/// </summary>
public class TransPlanHasChangeDetailDto
{
/// <summary>
/// 港口变更明细
/// </summary>
public List<TransPlanHasChangePortDto> portList { get; set; }
/// <summary>
/// 日期变更明细ETD或者ATD
/// </summary>
public List<TransPlanHasChangeDateDto> dateList { get; set; }
/// <summary>
/// 船名航次变更
/// </summary>
public List<TransPlanHasChangeVesselVoynoDto> vesselList { get; set; }
}
/// <summary>
/// 您的货物运输计划已变更-港口
/// </summary>
public class TransPlanHasChangePortDto
{
/// <summary>
/// 顺序号
/// </summary>
public int Indx { get; set; }
/// <summary>
/// 港口名
/// </summary>
public string PortName { get; set; }
/// <summary>
/// 国家
/// </summary>
public string CountryCode { get; set; }
/// <summary>
/// 码头
/// </summary>
public string TerminalName { get; set; }
/// <summary>
/// 是否被作废掉了
/// </summary>
public bool IsRemoved { get; set; } = false;
}
/// <summary>
/// 您的货物运输计划已变更-日期
/// </summary>
public class TransPlanHasChangeDateDto
{
/// <summary>
/// 顺序号
/// </summary>
public int Indx { get; set; }
/// <summary>
/// 提取日期文本
/// </summary>
public string OrigDateTxt { get; set; }
/// <summary>
/// 日期
/// </summary>
public DateTime DateVal { get; set; }
/// <summary>
/// 是否被作废掉了
/// </summary>
public bool IsRemoved { get; set; } = false;
}
/// <summary>
/// 您的货物运输计划已变更-船名航次
/// </summary>
public class TransPlanHasChangeVesselVoynoDto
{
/// <summary>
/// 顺序号
/// </summary>
public int Indx { get; set; }
/// <summary>
/// 船名
/// </summary>
public string Vessel { get; set; }
/// <summary>
/// 航次
/// </summary>
public string Voyno { get; set; }
/// <summary>
/// 船旗
/// </summary>
public string Flag { get; set; }
/// <summary>
/// 是否被作废掉了
/// </summary>
public bool IsRemoved { get; set; } = false;
}
public static class StringUtilsExtension
{
/// <summary>
/// 格式化文件名,去掉非法字符
/// </summary>
/// <param name="inputVal">请求参数</param>
/// <returns>返回格式化表达式值</returns>
public static string FormatFileName(this string inputVal)
{
if (!string.IsNullOrWhiteSpace(inputVal))
return Regex.Replace(inputVal, "\\|\\/|\\:|\\*|\\?|\\\"|\\<|\\>|\\|", "_");
return inputVal;
}
/// <summary>
/// 清理HTML字符
/// </summary>
/// <param name="inputVal">请求参数</param>
/// <returns>返回格式化表达式值</returns>
public static string ReplaceHtmlStr(this string inputVal)
{
if (!string.IsNullOrWhiteSpace(inputVal))
return Regex.Replace(Regex.Replace(inputVal, "\\&nbsp\\;", " "), "\\s{2,}", " ")?.Trim();
return inputVal;
}
}