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

2729 lines
104 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 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;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
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();
//service1.SyncServiceProjectRecord5();
service1.SyncServiceProjectRecord6();
Console.ReadKey();
public interface ISyncHisRecord
{
void SyncServiceProjectRecord4();
void SyncServiceProjectRecord5();
void SyncServiceProjectRecord6();
//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" };
/*
单票触发推送状态
1、取状态是null的并且每次取前100个订舱记录。
2、按订舱记录取所有的状态记录。
3、生成触发脚本推送PUSH状态。部分状态自动不执行
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;
/*
1、读取配置文件中的规则引擎URL
2、填充请求的类并生成JSON报文
3、POST请求接口并记录回执。
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++)
{
}
}
public void SyncServiceProjectRecord4()
{
/*
批量更新SI 截止时间
1、更新任务台
2、更新舱位的截止时间记录
*/
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}");
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);
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)}");
StringBuilder msgBuilder = new StringBuilder();
if (BCReadInfo != null)
{
//SI_CUT_DATE
if (BCReadInfo.SICutDate.HasValue)
{
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
{
msgBuilder.Append($"SI_CUT_DATE org={task.SI_CUT_DATE} tar=null");
task.SI_CUT_DATE = null;
}
//VGM_CUTOFF_TIME
if (BCReadInfo.VGMCutoffTime.HasValue)
{
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
{
msgBuilder.Append($"VGM_CUTOFF_TIME org={task.VGM_CUTOFF_TIME} tar=null##");
task.VGM_CUTOFF_TIME = null;
}
//MANIFEST_CUT_DATE
if (BCReadInfo.ManifestCutDate.HasValue)
{
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
{
msgBuilder.Append($"MANIFEST_CUT_DATE org={task.MANIFEST_CUT_DATE} tar=null##");
task.MANIFEST_CUT_DATE = null;
}
//CY_CUTOFF_TIME
if (BCReadInfo.CYCutoffTime.HasValue)
{
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
{
msgBuilder.Append($"CY_CUTOFF_TIME org={task.CY_CUTOFF_TIME} tar=null##");
task.CY_CUTOFF_TIME = null;
}
//MDGF_CUT_DATE
if (BCReadInfo.MDGFCutDate.HasValue)
{
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
{
msgBuilder.Append($"MDGF_CUT_DATE org={task.MDGF_CUT_DATE} tar=null##");
task.MDGF_CUT_DATE = null;
}
//CLOSING_DATE
if (BCReadInfo.ClosingDate.HasValue)
{
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
{
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();
}
_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);
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();
StringBuilder msgBuilder = new StringBuilder();
if (BCReadInfo != null)
{
//SI_CUT_DATE
if (BCReadInfo.SICutDate.HasValue)
{
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
{
msgBuilder.Append($"SI_CUT_DATE org={task.SI_CUT_DATE} tar=null");
task.SI_CUT_DATE = null;
}
//VGM_CUTOFF_TIME
if (BCReadInfo.VGMCutoffTime.HasValue)
{
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
{
msgBuilder.Append($"VGM_CUTOFF_TIME org={task.VGM_CUTOFF_TIME} tar=null##");
task.VGM_CUTOFF_TIME = null;
}
//MANIFEST_CUT_DATE
if (BCReadInfo.ManifestCutDate.HasValue)
{
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
{
msgBuilder.Append($"MANIFEST_CUT_DATE org={task.MANIFEST_CUT_DATE} tar=null##");
task.MANIFEST_CUT_DATE = null;
}
//CY_CUTOFF_TIME
if (BCReadInfo.CYCutoffTime.HasValue)
{
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
{
msgBuilder.Append($"CY_CUTOFF_TIME org={task.CY_CUTOFF_TIME} tar=null##");
task.CY_CUTOFF_TIME = null;
}
//MDGF_CUT_DATE
if (BCReadInfo.MDGFCutDate.HasValue)
{
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
{
msgBuilder.Append($"MDGF_CUT_DATE org={task.MDGF_CUT_DATE} tar=null##");
task.MDGF_CUT_DATE = null;
}
//CLOSING_DATE
if (BCReadInfo.ClosingDate.HasValue)
{
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
{
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();
}
_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
}
}
}
}
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");
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;
}
}
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
{
}
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; }
}
/// <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;
}
}