using System.Threading.Tasks;
using XYY.Core.Standard.AliYun;
using XYY.Core.Standard.ExcelHelper.MSExcelHelper;
using XYY.TaskTrack.Standard.TaskModel;
using System.Linq;
using System.Collections.Generic;
using XYY.Data.Standard.First;
using XYY.TaskTrack.Standard;
using System;
using XYY.Core.Standard.Data.Infrastructure;
using XYY.Model.Standard.Task;
using XYY.Data.Standard.Tasks;
using XYY.Data.Standard.Order;
using Dapper;
using XYY.Data.Model.Standard.Tracking;
using XYY.Service.Standard.First.Model;
using XYY.Model.Standard.First;
using RestSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using XYY.Service.Standard.First.DB;
using XYY.Common.Standard;
using System.Diagnostics;
using XYY.Service.Standard.First.Mapping;
using System.Threading;
using XYY.Service.Standard.First.Mail;
namespace XYY.Service.Standard.First
{
public class LadingTrackingService : ILadingTrackingService
{
private IAliYunPostFileSerivce _aliYunPostFileSerivce;
private IExcelHelper _excelHelper;
private ILogistics_LadingBillRepository _logistics_LadingBillRepository;
private ITaskTrackDataRepository _taskTrackData;
private IOrderRepository _orderRepository;
private IUnitOfWork _unitOfWork;
private IMQManager _MQManager;
private IFirstDB _firstDB;
private IOrderMailService _orderMailService;
public LadingTrackingService(IExcelHelper excelHelper,
IAliYunPostFileSerivce aliYunPostFileSerivce,
ILogistics_LadingBillRepository logistics_LadingBillRepository,
ITaskTrackDataRepository taskTrackData,
IMQManager MQManager,
IOrderRepository orderRepository,
IUnitOfWork unitOfWork,
IFirstDB firstDB,
IOrderMailService orderMailService)
{
_excelHelper = excelHelper;
_aliYunPostFileSerivce = aliYunPostFileSerivce;
_logistics_LadingBillRepository = logistics_LadingBillRepository;
_taskTrackData = taskTrackData;
_MQManager = MQManager;
_orderRepository = orderRepository;
_unitOfWork = unitOfWork;
_firstDB = firstDB;
_orderMailService = orderMailService;
}
///
/// 添加批量上传的任务
///
///
///
public async Task AddBatchJob(System.IO.Stream formFile)
{
BatchJobResult batchJobResult = new BatchJobResult();
var list = _excelHelper.LoadDataAsStream(formFile);
list = list.Where(x => !string.IsNullOrEmpty(x.LadingBillNumber)).ToList();
var ladingBillNumbers = list.Select(x => x.LadingBillNumber).ToArray();
list =
list.GroupBy(x => x.LadingBillNumber).Select(x =>
x.OrderByDescending(y => y.DepartTime).ThenByDescending(y => y.ClearanceTime).ThenByDescending(y => y.ArrivalTime)
.First()).ToList();
var waitLaddingBills = await _logistics_LadingBillRepository.QueryBill(ladingBillNumbers);
var notFinds = ladingBillNumbers.Where(x => !waitLaddingBills.Any(y => y.LadingBillNumber.Trim() == x)).Select(x => new Job_LadingBillLogisticsItem { LadingBillNumber = x }).ToList();
if (notFinds.Count > 0)
{
//未找到的提单号,生成一个Excel文件返回
string url = _excelHelper.OutData(notFinds);
batchJobResult.ErrorFileUrl = url;
}
//提前循环,判断起飞和到达时间
foreach (var i in list)
{
var tempWaitBills = waitLaddingBills.Where(x => x.LadingBillNumber == i.LadingBillNumber && x.IsDeleted == false).FirstOrDefault();
if (tempWaitBills == null) { continue; }
//始终更新创建时间
i.CreateTime = tempWaitBills.CreateTime.Value;
//赋值轨迹抓取的数据
if (tempWaitBills.DepartTime.HasValue && !string.IsNullOrEmpty(tempWaitBills.DepartRemark) && tempWaitBills.DepartRemark.Contains("轨迹抓取更新"))
{
i.DepartTime = tempWaitBills.DepartTime;
}
if (tempWaitBills.ArrivalTime.HasValue && !string.IsNullOrEmpty(tempWaitBills.ArrivalRemark) && tempWaitBills.ArrivalRemark.Contains("轨迹抓取更新"))
{
i.ArrivalTime = tempWaitBills.ArrivalTime;
}
//如果清关时间和起飞时间一样的话,起飞轨迹会比清关轨迹排在前边,导致轨迹顺序混乱,
//所以要加100毫秒。加100毫秒的目的保证正确排序,但两者时分秒显示能保持一致
if (i.ClearanceTime.HasValue && i.DepartTime.HasValue && i.ClearanceTime.Value == i.DepartTime.Value)
{
i.ClearanceTime = i.ClearanceTime.Value.AddMilliseconds(100);
}
}
list = list.Where(x => waitLaddingBills.Any(y => y.LadingBillNumber == x.LadingBillNumber && (
x.CustomsClearanceTime != y.CustomsClearanceTime ||
x.ArrivalTime != y.ArrivalTime
|| x.ClearanceTime != y.ClearanceTime
|| x.DepartTime != y.DepartTime
|| x.LeaveWarehouseTime != y.LeaveWarehouseTime
|| x.TrafficTime != y.TrafficTime))).ToList();
List list2 = new List();
//判断是否是补数据
foreach (var f in list)
{
var item = waitLaddingBills.Where(x => x.LadingBillNumber == f.LadingBillNumber).FirstOrDefault();
//系统存在提单
//if (
// (!item.ArrivalTime.HasValue && f.ArrivalTime.HasValue && f.ArrivalTime < DateTime.Now) ||
// (!item.ClearanceTime.HasValue && f.ClearanceTime.HasValue && f.ClearanceTime < DateTime.Now) ||
// (!item.DepartTime.HasValue && f.DepartTime.HasValue && f.DepartTime.Value < DateTime.Now) ||
// (!item.TrafficTime.HasValue && f.TrafficTime.HasValue && f.TrafficTime.Value < DateTime.Now)
// )
//{
bool isAdd = false;
//增加更新节点判断
if (!item.ArrivalTime.HasValue && f.ArrivalTime.HasValue && f.ArrivalTime < DateTime.Now) { f.updatedNode.Add("ArrivalTime"); isAdd = true; }
if (!item.ClearanceTime.HasValue && f.ClearanceTime.HasValue && f.ClearanceTime < DateTime.Now) { f.updatedNode.Add("ClearanceTime"); isAdd = true; }
if (!item.DepartTime.HasValue && f.DepartTime.HasValue && f.DepartTime.Value < DateTime.Now) { f.updatedNode.Add("DepartTime"); isAdd = true; }
if (!item.TrafficTime.HasValue && f.TrafficTime.HasValue && f.TrafficTime.Value < DateTime.Now) { f.updatedNode.Add("TrafficTime"); isAdd = true; }
//如果提单时间离港小于当前时间,我们不再推送
if (isAdd) { list2.Add(f); }
//}
}
//校验数据时间,只校验需要补的数据
var verify = await LadingTimeVerify(waitLaddingBills, list);
if (!verify.Item1) { return verify.Item2; }
//邮件数据记录
await _orderMailService.AddClearanceMail(list);
//待上传列表
TaskTrackModel taskTrackModel = new TaskTrackModel()
{
WaitQty = list.Count,
Name = "batchTrace" + Guid.NewGuid().ToString(),
Summary = list.Count
};
batchJobResult.JobId = taskTrackModel.Name;
await _taskTrackData.InitTaskTrack(taskTrackModel);
//内部数据更新
await _MQManager.Publish(new Job_LadingBillLogistics { Jobs = list });
//通知第三方Api数据更新
await _MQManager.Publish(new Job_Customer_FristLog { Jobs = list2 });
return batchJobResult;
}
public async Task> LadingTimeVerify(List waitLaddingBills, List jobs)
{
List error = new List();
foreach (var item in jobs)
{
var tempWaitBills = waitLaddingBills.Where(x => x.LadingBillNumber == item.LadingBillNumber).FirstOrDefault();
if (item.CustomsClearanceTime.HasValue && item.CustomsClearanceTime < tempWaitBills.CreateTime)
{
error.Add(new LadingTimeError() { LadingBillNumber = item.LadingBillNumber, ErrorMessage = "国内报关时间不应小于提单创建时间" });
}
else if (item.DeliveryTime.HasValue && item.CustomsClearanceTime.HasValue && item.DeliveryTime < item.CustomsClearanceTime)
{
error.Add(new LadingTimeError() { LadingBillNumber = item.LadingBillNumber, ErrorMessage = "交航时间不应小于国内报关时间" });
}
else if (item.DeliveryTime.HasValue && item.DepartTime.HasValue && item.DepartTime < item.DeliveryTime)
{
error.Add(new LadingTimeError() { LadingBillNumber = item.LadingBillNumber, ErrorMessage = "离港时间不应小于交航时间" });
}
else if (item.ArrivalTime.HasValue && item.DepartTime.HasValue && item.ArrivalTime < item.DepartTime)
{
error.Add(new LadingTimeError() { LadingBillNumber = item.LadingBillNumber, ErrorMessage = "到港时间不应小于离港时间" });
}
else if (item.ArrivalTime.HasValue && item.ClearanceTime.HasValue && item.ClearanceTime < item.ArrivalTime)
{
error.Add(new LadingTimeError() { LadingBillNumber = item.LadingBillNumber, ErrorMessage = "清关时间不应小于到港时间" });
}
}
if (error != null && error.Count > 0)
{
BatchJobResult batchJobResult = new BatchJobResult();
string url = _excelHelper.OutData(error);
batchJobResult.ErrorFileUrl = url;
return Tuple.Create(false, batchJobResult);
}
else
{
return Tuple.Create(true, new BatchJobResult());
}
}
public async Task TestPublic()
{
await _MQManager.Publish(new Job_Customer_FristLog
{
Jobs = new List{new Job_LadingBillLogisticsItem{
LadingBillNumber="test111",
ClearanceTime =DateTime.Parse("2021-08-19 14:22:09"),
ArrivalTime=DateTime.Now,
DepartTime=DateTime.Now
} }
});
}
public async Task TestSendLog(Frist_Log fristLog)
{
await _MQManager.Publish(fristLog);
}
public async Task TrackSupplement(TrackSupplementRequest param)
{
await _MQManager.Publish(param);
}
public async Task SendInitHKXiKeOrders()
{
//上网轨迹
string sql = @" select a.CustomerOrderNo from order_order(nolock)a join Logistics_Trace(nolock)b on a.TrackingNumber = b.TrackingNumber
where a.CustomerId = 691 and b.OnlineTime is not null";
var orders = await _orderRepository.QueryBySqlAsync(sql);
var log = new Frist_Log
{
Groups = new List()
};
foreach (var order in orders)
{
var group = new Data.Model.Standard.Tracking.Logistics_TraceGroup
{
CustomerOrderNo = order.CustomerOrderNo,
List = new List
{
}
};
log.Groups.Add(group);
if (order.ReceiveTime.HasValue)
{
group.List.Add(new Data.Model.Standard.Tracking.EsLogisticsTrackingLog
{
TriggerTime = order.ReceiveTime.Value,
Location = "guangzhou",
Status = 8,
StatusString = "Item inbound in sorting center."
});
}
}
//XiKeApi xiKeApi = new XiKeApi();
//var erros = await xiKeApi.Send(log.Groups);
//await AddErrors(erros, "称重");
//装箱数据
//foreach (var order in orders)
//{
// var group = new Data.Model.Standard.Tracking.Logistics_TraceGroup
// {
// CustomerOrderNo = order.CustomerOrderNo,
// List = new List
// {
// }
// };
// log.Groups.Add(group);
// if (order.ReceiveTime.HasValue)
// {
// group.List.Add(new Data.Model.Standard.Tracking.EsLogisticsTrackingLog
// {
// TriggerTime = order.ReceiveTime.Value,
// Location = "guangzhou",
// Status = 2,
// StatusString = "Item inbound in sorting center."
// });
// }
// if (order.SendOutTime.HasValue)
// {
// group.List.Add(new Data.Model.Standard.Tracking.EsLogisticsTrackingLog
// {
// TriggerTime = order.SendOutTime.Value,
// Location = "guangzhou",
// Status = 3,
// StatusString = "Item outbound in sorting center."
// });
// }
//}
//头程推送、称重、装箱
//string sql = @"select * from order_order(nolock) where customerid = 691 and orderStatus>1";
//var orders = await _orderRepository.QueryBySqlAsync(sql);
//var log = new Frist_Log
//{
// Groups = new List()
//};
////装箱数据
//foreach (var order in orders)
//{
// var group = new Data.Model.Standard.Tracking.Logistics_TraceGroup
// {
// CustomerOrderNo = order.CustomerOrderNo,
// List = new List
// {
// }
// };
// log.Groups.Add(group);
// if (order.ReceiveTime.HasValue)
// {
// group.List.Add(new Data.Model.Standard.Tracking.EsLogisticsTrackingLog
// {
// TriggerTime = order.ReceiveTime.Value,
// Location = "guangzhou",
// Status = 2,
// StatusString = "Item inbound in sorting center."
// });
// }
// if (order.SendOutTime.HasValue)
// {
// group.List.Add(new Data.Model.Standard.Tracking.EsLogisticsTrackingLog
// {
// TriggerTime = order.SendOutTime.Value,
// Location = "guangzhou",
// Status = 3,
// StatusString = "Item outbound in sorting center."
// });
// }
//}
//XiKeApi xiKeApi = new XiKeApi();
//var erros = await xiKeApi.Send(log.Groups);
//await AddErrors(erros, "称重");
////头程轨迹
//string fristSql = @"select c.LadingBillNumber,a.TrackingNumber,a.Id,a.ReceiverCountryCode,d.DepartTime,d.ArrivalTime,d.ClearanceTime,a.CustomerOrderNo from Order_Order(nolock) a
// join Logistics_Boxdetail(nolock) b on a.id = b.orderid join logistics_box(nolock) c on b.boxid=c.id
// join Logistics_LadingBill(nolock) d on d.LadingBillNumber = c.LadingBillNumber
// where d.IsDeleted=0
// and (a.CustomerId = 691)";
//List firstTrackings = new List();
//using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(_unitOfWork.ConnectionAddress))
//{
// connection.Open();
// firstTrackings = (await connection.QueryAsync(fristSql, null, null, null, null)).ToList();
//}
//var groups = firstTrackings.GroupBy(x => new Job_LadingBillLogisticsItem
//{
// LadingBillNumber = x.LadingBillNumber,
// ArrivalTime = x.ArrivalTime,
// DepartTime = x.DepartTime,
// ClearanceTime = x.ClearanceTime
//});
//foreach (var ladingBillNumber
// in groups)
//{
// if (ladingBillNumber.ToList().Count > 0)
// {
// var logs =
// JobSubscribe.JobSubscribe.GetLogs2(ladingBillNumber.ToList(), ladingBillNumber.Key);
// xiKeApi = new XiKeApi();
// erros = await xiKeApi.Send(logs);
// await AddErrors(erros, "头程");
// }
//}
}
public async Task AddErrors(List erros, string target)
{
if (erros.Count > 0)
{
Frist_Log log = new Frist_Log();
log.Groups = erros;
//持久化
await _unitOfWork.InsertAsync(new ErroJobLog
{
ActionUrl = "http://120.24.149.148:9520/api/BatchTracking/TestSendLog",
IsExecute = true,
Request = Newtonsoft.Json.JsonConvert.SerializeObject(log),
Target = target,
CreateTime = DateTime.Now
});
}
}
#region 对接51Track 航空订单
public async Task> Lading51TrackService(List ladingNumber, bool IsTest = false)
{
List trackResults = new List();
List dbData = await GetWaitToQueryTrack(ladingNumber);
if (dbData == null || dbData.Count == 0) { throw new Exception("51Track 航空订单,无提单数据可查询"); }
var groupData = dbData.GroupBy(x => new { x.LadingBillNumber }).ToList();
//取出数据逻辑的条件
List rules = await GetLading51TrackRules();
Stopwatch stopWatch = new Stopwatch();
double TotalMilliseconds = 3000;//默认不停,执行过快会重复赋值
//mq数据
List list2 = new List() { };
foreach (var item in groupData)
{
try
{
if (1000 - TotalMilliseconds > 0)
{
System.Threading.Thread.Sleep(2000 - (int)TotalMilliseconds);
TotalMilliseconds = 0;
}
stopWatch.Start();
var trackResult = await QueryBy51Track(IsTest ? "618-62659726" : item.Key.LadingBillNumber);//用测试提单测,会默认一个提单的轨迹去更
var esModel = await ConvertToEsModel(trackResult, item.ToList(), rules);
if (esModel.Count == 0)
{
TimeSpan ts = stopWatch.Elapsed;
TotalMilliseconds = ts.TotalMilliseconds;
stopWatch.Reset();
continue;
}
var waitUpdate = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(esModel));
await EsTrackUpdate(waitUpdate);
await ExecuteUpdateLadingTrackTime(trackResult, item.ToList());
//添加mq任务
#region 添加mq任务
var tempLadingInfo = item.FirstOrDefault();
var tempEsInfo = waitUpdate.FirstOrDefault();
//这里只会添加4和5两种轨迹
Job_LadingBillLogisticsItem job = new Job_LadingBillLogisticsItem();
bool isAdd = false;
if (tempEsInfo.List.Any(y => y.Status == 4))
{
//起飞时间
job.LadingBillNumber = tempLadingInfo.LadingBillNumber;
job.DepartTime = tempEsInfo.List.Where(x => x.Status == 4).OrderByDescending(x => x.TriggerTime).FirstOrDefault().TriggerTime;
job.updatedNode.Add("DepartTime"); isAdd = true;
}
if (tempEsInfo.List.Any(y => y.Status == 5))
{
//到达时间
job.LadingBillNumber = tempLadingInfo.LadingBillNumber;
job.ArrivalTime = tempEsInfo.List.Where(x => x.Status == 5).OrderByDescending(x => x.TriggerTime).FirstOrDefault().TriggerTime;
job.updatedNode.Add("ArrivalTime"); isAdd = true;
}
if (isAdd) { list2.Add(job); }
#endregion
//ExecuteSendLogs(esModel, dbData.Where(x => x.CustomerId == 7 || x.CustomerId == 691).ToList());//写死判断,只有细刻需要发送此api
//判断时间
TimeSpan ts1 = stopWatch.Elapsed;
TotalMilliseconds = ts1.TotalMilliseconds;
stopWatch.Reset();
}
catch (Exception ex)
{
trackResults.Add(new Lading51TrackResult() { LadingBillNumber = item.Key.LadingBillNumber, errorMessage = ex.Message });
TimeSpan ts = stopWatch.Elapsed;
TotalMilliseconds = ts.TotalMilliseconds;
stopWatch.Reset();
}
}
if (list2.Count > 0) { await _MQManager.Publish(new Job_Customer_FristLog { Jobs = list2 }); }
return trackResults;
}
public async Task testDez()
{
string json = @"{
""meta"": {
""code"": 200,
""type"": ""Success"",
""message"": ""Request Success""
},
""data"": {
""618-62659726"": {
""track_number"": ""618-62659726"",
""return_data"": {
""status_number"": 4,
""origin"": ""CAN"",
""destination"": ""CDG"",
""piece"": ""36"",
""weight"": ""628.0"",
""track_info"": [
{
""plan_date"": ""2023-06-28 15:36:00"",
""actual_date"": ""2023-06-28 15:36:00"",
""event"": ""Shipment Delivered"",
""station"": ""CDG"",
""flight_number"": ""-"",
""status"": ""DLV"",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-28 11:03:00"",
""actual_date"": ""2023-06-28 11:03:00"",
""event"": ""Shipment Ready for Pick-up"",
""station"": ""CDG"",
""flight_number"": ""-"",
""status"": ""NFD"",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-28 11:03:00"",
""actual_date"": ""2023-06-28 11:03:00"",
""event"": ""Shipment Checked Into Warehouse"",
""station"": ""CDG"",
""flight_number"": ""SQ0336"",
""status"": """",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-28 09:40:00"",
""actual_date"": ""2023-06-28 09:40:00"",
""event"": ""Document Delivered"",
""station"": ""CDG"",
""flight_number"": ""-"",
""status"": ""AWD"",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-28 07:40:00"",
""actual_date"": ""2023-06-28 07:40:00"",
""event"": ""Cleared By Customs"",
""station"": ""CDG"",
""flight_number"": ""-"",
""status"": """",
""piece"": ""36"",
""weight"": ""-""
},
{
""plan_date"": ""2023-06-28 07:28:00"",
""actual_date"": ""2023-06-28 07:28:00"",
""event"": ""Flight Arrived"",
""station"": ""CDG"",
""flight_number"": ""SQ0336"",
""status"": ""ARR"",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-28 00:17:00"",
""actual_date"": ""2023-06-28 00:17:00"",
""event"": ""Flight Departed"",
""station"": ""SIN"",
""flight_number"": ""SQ0336"",
""status"": ""DEP"",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-27 12:15:00"",
""actual_date"": ""2023-06-27 12:15:00"",
""event"": ""Shipment Checked Into Warehouse"",
""station"": ""SIN"",
""flight_number"": ""SQ7821"",
""status"": """",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-27 11:55:00"",
""actual_date"": ""2023-06-27 11:55:00"",
""event"": ""Flight Arrived"",
""station"": ""SIN"",
""flight_number"": ""SQ7821"",
""status"": ""ARR"",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-27 05:11:00"",
""actual_date"": ""2023-06-27 05:11:00"",
""event"": ""Flight Departed"",
""station"": ""CAN"",
""flight_number"": ""SQ7821"",
""status"": ""DEP"",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-26 10:40:00"",
""actual_date"": ""2023-06-26 10:40:00"",
""event"": ""Freight On Hand"",
""station"": ""CAN"",
""flight_number"": ""-"",
""status"": ""FOH"",
""piece"": ""36"",
""weight"": ""628.0""
},
{
""plan_date"": ""2023-06-26 10:40:00"",
""actual_date"": ""2023-06-26 10:40:00"",
""event"": ""Shipment Received"",
""station"": ""CAN"",
""flight_number"": ""-"",
""status"": ""RCF"",
""piece"": ""36"",
""weight"": ""628.0""
}
],
""flight_info"": {
""SQ7821"": {
""depart_station"": ""CAN"",
""arrival_station"": ""SIN"",
""plan_depart_time"": ""2023-06-27 05:55:00"",
""depart_time"": null,
""plan_arrival_time"": ""2023-06-27 09:50:00"",
""arrival_time"": null
},
""SQ0336"": {
""depart_station"": ""SIN"",
""arrival_station"": ""CDG"",
""plan_depart_time"": ""2023-06-28 00:15:00"",
""depart_time"": null,
""plan_arrival_time"": ""2023-06-28 07:35:00"",
""arrival_time"": null
}
},
""flight_info_new"": [
{
""plan_arrival_time"": ""2023-06-27 09:50:00"",
""plan_depart_time"": ""2023-06-27 05:55:00"",
""depart_station"": ""CAN"",
""arrival_station"": ""SIN"",
""flight_number"": ""SQ7821"",
""status"": ""Confirmed""
},
{
""plan_arrival_time"": ""2023-06-28 07:35:00"",
""plan_depart_time"": ""2023-06-28 00:15:00"",
""depart_station"": ""SIN"",
""arrival_station"": ""CDG"",
""flight_number"": ""SQ0336"",
""status"": ""Confirmed""
}
],
""flight_way_station"": [
""CAN"",
""SIN"",
""CDG""
],
""last_event"": ""2023-06-28 15:36:00, Shipment Delivered, CDG, -""
},
""airline_info"": {
""name"": ""新加坡"",
""url"": ""http://www.siacargo.com/ccn/ShipmentTrack.aspx"",
""track_url"": ""http://www.siacargo.com/ccn/ShipmentTrack.aspx"",
""trackpage_url"": ""https://www.51tracking.com/aircargo/cn/618-62659726""
}
}
}
}";
var data = TrackDeserializeObject("618-62659726", json);
}
#region db数据处理
///
/// 获取待查数据
/// 过滤非快线渠道
///
///
///
private async Task> GetWaitToQueryTrack(List ladingNumber)
{
string ladingNumberWhere = string.Empty;
if (ladingNumber != null && ladingNumber.Count > 0) { ladingNumberWhere = " and t.LadingBillNumber in @param "; }
List ladingNumber3 = new List() { "784", "180", "205", "160", "880", "235", "057", "618" };
string sql = @" select t.LadingBillNumber,t.OriginPort,t.Destination,t.ServiceName,b.TrackingNumber,b.OrderId,c.CustomerOrderNo,c.ReceiverCountryCode,c.CustomerId
,t.DepartTime,t.TrafficTime
from Logistics_LadingBill(nolock) t
left join Logistics_Box(nolock) a on a.LadingBillNumber=t.LadingBillNumber
left join Logistics_BoxDetail(nolock) b on b.BoxId=a.Id
left join Order_Order(nolock) c on c.Id=b.OrderId
where t.CreateTime>='2023-03-01' and t.IsDeleted=0 and ''=ISNULL(t.ArrivalTime,'') and ''!=ISNULL(b.TrackingNumber,'') and ''!=ISNULL(t.ServiceName,'')
and ''!=ISNULL(t.OriginPort,'') and ''!=ISNULL(t.Destination,'') and left(t.LadingBillNumber,3) in @ladingNumber3 " + ladingNumberWhere;
var result = (await _unitOfWork.QueryBySqlAsync(sql, 300, new { ladingNumber3 = ladingNumber3, param = ladingNumber })).ToList();
return result;
}
///
/// 更新提单轨迹时间
/// 起飞、到达、
///
///
private async Task ExecuteUpdateLadingTrackTime(TrackResult trackResult, List dbData)
{
if (dbData == null || dbData.Count == 0) { return false; }
var prot1 = dbData.FirstOrDefault()?.Destination;
var prot2 = dbData.FirstOrDefault()?.OriginPort;
var track_infos = trackResult.data.ladingInfo.return_data.flight_Infos;
if (track_infos == null || track_infos.Count == 0) { return false; }
var OriginPortTrack = track_infos.Where(x => prot2 == x.depart_station)?.OrderBy(x => Convert.ToDateTime(x.depart_time))?.FirstOrDefault();
var DestinationTrack = track_infos.Where(x => prot1 == x.arrival_station)?.OrderBy(x => Convert.ToDateTime(x.arrival_time))?.FirstOrDefault();
string sql = string.Empty;
if (OriginPortTrack != null && !string.IsNullOrEmpty(OriginPortTrack.depart_time))
{
string updateTrafficTime = string.Empty;
if (!dbData.FirstOrDefault().TrafficTime.HasValue)
{
updateTrafficTime = $",TrafficTime='{Convert.ToDateTime(OriginPortTrack.depart_time).AddHours(-8)}' ";
}
sql = $"update Logistics_LadingBill set DepartTime='{OriginPortTrack.depart_time}',DepartRemark='51轨迹抓取更新,{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}'{updateTrafficTime} where LadingBillNumber='{dbData.FirstOrDefault().LadingBillNumber}' and ISNULL(DepartTime,'')='';";
}
if (DestinationTrack != null && !string.IsNullOrEmpty(DestinationTrack.arrival_time))
{
sql += $"update Logistics_LadingBill set ArrivalTime='{DestinationTrack.arrival_time}',ArrivalRemark='51轨迹抓取更新,{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}' where LadingBillNumber='{dbData.FirstOrDefault().LadingBillNumber}' and ISNULL(ArrivalTime,'')='';";
}
if (!string.IsNullOrEmpty(sql)) { await _unitOfWork.ExecuteAsync(sql); }
return false;
}
private async Task> GetLading51TrackRules()
{
string sql = " select * from Logistics_Lading51TrackRules ";
var data = await _unitOfWork.QueryBySqlAsync(sql);
return data.ToList();
}
#endregion
#region 51API对接
public async Task QueryBy51Track(string ladingNumber)
{
var client = new RestClient("http://api.51tracking.com");
var request = new RestRequest("/v2/trackings/aircargo", Method.POST);
request.AddHeader("Tracking-Api-Key", "e0febb2a-eef1-45a3-b534-3dda7465fb4e");
request.AddHeader("Content-Type", "application/json");
TrackRequestBody body = new TrackRequestBody() { track_number = ladingNumber };
request.AddJsonBody(body);
var response = await client.ExecuteAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var MetaStatus = JsonConvert.DeserializeObject(response.Content);
if (MetaStatus.meta.code == 200)
{
//进一步解析
var result = JsonConvert.DeserializeObject(response.Content);
result.data.ladingInfo = TrackDeserializeObject(ladingNumber, response.Content);
return result;
}
else
{
throw new Exception($"51Track查询航空订单错误:{MetaStatus.meta.message}");
}
}
else
{
throw new Exception($"51TrackApi请求错误:{response.StatusCode},{response.Content}");
}
}
private ladingInfo TrackDeserializeObject(string ladingNumber, string Content)
{
var jo = JsonConvert.DeserializeObject(Content);
var data = (jo["data"] as JObject).GetValue(ladingNumber);
var ladingInfo = JsonConvert.DeserializeObject(data.ToString());
List flight_numbers = ladingInfo.return_data.flight_info_new?.Select(x => x.flight_number)?.Distinct()?.ToList();
if (flight_numbers == null) { return ladingInfo; }
List infos = new List();
foreach (var item in flight_numbers)
{
var info = (data["return_data"]["flight_info"] as JObject).GetValue(item);
if (info != null)
{
flight_info _info = JsonConvert.DeserializeObject(info.ToString());
infos.Add(_info);
}
}
ladingInfo.return_data.flight_Infos = infos;
return ladingInfo;
}
#endregion
#region 轨迹处理
private async Task> ConvertToEsModel(TrackResult trackResult, List dbData, List rules)
{
List tracks = new List();
List insertLogs = new List();
var track_infos = trackResult.data.ladingInfo.return_data.flight_Infos;
var trackInfos = trackResult.data.ladingInfo.return_data.track_info;
Time51Value OriginPortTrack = null;
Time51Value DestinationTrack = null;
if (trackInfos != null && trackInfos.Count > 0
&& rules.Any(x => dbData.FirstOrDefault().LadingBillNumber.StartsWith(x.LadingNumber3)))
{
//一个单号只能有一种逻辑
var rule = rules.Where(x => dbData.FirstOrDefault().LadingBillNumber.StartsWith(x.LadingNumber3)).FirstOrDefault();
var tempOriginPortTrack = trackInfos
.Where(x => dbData.FirstOrDefault().OriginPort?.Trim() == x.station?.Trim())
?.OrderBy(x => Convert.ToDateTime(x.actual_date?.Trim()))?.FirstOrDefault();
OriginPortTrack = new Time51Value() { dateTime = tempOriginPortTrack?.actual_date };
var tempDestinationTrack = trackInfos
.Where(x => dbData.FirstOrDefault().Destination?.Trim() == x.station?.Trim())
?.OrderBy(x => Convert.ToDateTime(x.actual_date?.Trim()))?.FirstOrDefault();
DestinationTrack = new Time51Value() { dateTime = tempDestinationTrack?.actual_date };
}
else if (track_infos != null && track_infos.Count > 0)
{
var tempOriginPortTrack = track_infos.Where(x => dbData.FirstOrDefault().OriginPort?.Trim() == x.depart_station?.Trim() && !string.IsNullOrEmpty(x?.depart_time?.Trim()))?.OrderBy(x => Convert.ToDateTime(x?.depart_time?.Trim()))?.FirstOrDefault();
OriginPortTrack = new Time51Value() { dateTime = tempOriginPortTrack?.depart_time };
var tempDestinationTrack = track_infos.Where(x => dbData.FirstOrDefault().Destination?.Trim() == x.arrival_station?.Trim()&&!string.IsNullOrEmpty(x?.arrival_time?.Trim()))?.OrderBy(x => Convert.ToDateTime(x?.arrival_time?.Trim()))?.FirstOrDefault();
DestinationTrack = new Time51Value() { dateTime = tempDestinationTrack?.arrival_time };
}
//判断是否有时间数据,无则跳过 两者皆空
if ((OriginPortTrack == null && DestinationTrack == null) || (string.IsNullOrEmpty(OriginPortTrack?.dateTime) && string.IsNullOrEmpty(DestinationTrack?.dateTime)))
{
return insertLogs;
}
else
{
//有则判断时间,是否符合,不符合发送微信通知
var temp = dbData.FirstOrDefault();
if (temp.TrafficTime.HasValue && !string.IsNullOrEmpty(OriginPortTrack?.dateTime) && Convert.ToDateTime(OriginPortTrack.dateTime) < temp.TrafficTime)
{
sendMessageToWeChat("51提单轨迹同步", $"提单号:【{temp.LadingBillNumber}】,交航时间大于起飞时间,异常!", new List() { "LiuZhengKai", "fanlihang" });
}
else if (temp.DepartTime.HasValue && !string.IsNullOrEmpty(DestinationTrack?.dateTime) && Convert.ToDateTime(DestinationTrack.dateTime) < temp.DepartTime)
{
sendMessageToWeChat("51提单轨迹同步", $"提单号:【{temp.LadingBillNumber}】,起飞时间大于到达时间,异常!", new List() { "LiuZhengKai", "fanlihang" });
}
}
foreach (var tn in dbData)
{
var g = new Logistics_TraceGroup
{
TrackingNumber = tn.TrackingNumber,
CustomerOrderNo = tn.CustomerOrderNo,
List = new List()
};
if (OriginPortTrack != null && !string.IsNullOrEmpty(OriginPortTrack.dateTime) && !tn.DepartTime.HasValue)
{
//没有交航时间,额外补一条轨迹,补一条
if (!tn.TrafficTime.HasValue)
{
g.List.Add(new EsLogisticsTrackingLog
{
CreateTime = DateTime.Now,
TriggerTime = Convert.ToDateTime(OriginPortTrack.dateTime).AddHours(-8),
Status = 4,
Location = "广州",
OrderId = tn.OrderId,
ChannelId = 0,
TrackingNumber = tn.TrackingNumber,
StatusString = "Arrived Export Airport.",//写死轨迹信息
Uid = Guid.NewGuid().ToString()
});
}
g.List.Add(new EsLogisticsTrackingLog
{
CreateTime = DateTime.Now,
TriggerTime = Convert.ToDateTime(OriginPortTrack.dateTime),
Status = 4,
Location = "广州",
OrderId = tn.OrderId,
ChannelId = 0,
TrackingNumber = tn.TrackingNumber,
StatusString = "Item is ready for departure.",//写死轨迹信息
Uid = Guid.NewGuid().ToString()
});
}
if (DestinationTrack != null && !string.IsNullOrEmpty(DestinationTrack.dateTime))
{
g.List.Add(new EsLogisticsTrackingLog
{
CreateTime = DateTime.Now,
TriggerTime = Convert.ToDateTime(DestinationTrack.dateTime),
Status = 5,
Location = tn.ReceiverCountryCode,
OrderId = tn.OrderId,
ChannelId = 0,
TrackingNumber = tn.TrackingNumber,
StatusString = "Item is being presented to customs.",//写死轨迹信息
Uid = Guid.NewGuid().ToString()
});
}
if (g.List.Count > 0) { insertLogs.Add(g); }
}
return insertLogs;
}
private async Task EsTrackUpdate(List logistics)
{
bool isSuccess = await _firstDB.InsertAndUpdate(logistics);
}
//发送轨迹日志
private TrackingEventType ToEventCode(int code)
{
switch (code)
{
case 5:
return TrackingEventType.Arrive;
case 4:
return TrackingEventType.Departure;
case 6:
return TrackingEventType.Clearance;
default:
throw new Exception("转换失败");
}
}
private void ExecuteSendLogs(List logistics, List queryDatas)
{
if (queryDatas.Count > 0)
{
List CustomerOrderNoS = queryDatas.Select(x => x.CustomerOrderNo).Distinct().ToList();
var apiData = logistics.Where(x => CustomerOrderNoS.Contains(x.CustomerOrderNo)).ToList();
var logs2 = apiData.SelectMany(x => x.List.Select(y => new
{
CustomerNo = x.CustomerOrderNo,
TrackingEventType = ToEventCode(y.Status),
Key = x.CustomerOrderNo + "_" + ToEventCode(y.Status),
EventLoaction = y.Location,
EventContent = y.StatusString,
EventTime = y.TriggerTime,
GetTime = DateTime.Now.ToString_yyyyMMddHHmmss()
}));
for (int i = 0; i < Math.Ceiling(logs2.Count() / 120.0); i++)
{
var logs3 = logs2.Skip(120 * i).Take(120).ToList();
SendXiKeLogsApi(logs3);
}
}
}
private static void SendXiKeLogsApi(dynamic dynamic)
{
RestSharp.RestClient rc = new RestSharp.RestClient("http://120.24.149.148:9520/");
RestSharp.RestRequest rq = new RestSharp.RestRequest("/api/TrackingLog/AddLog", RestSharp.Method.POST);
rq.AddHeader("Authorization", "token 132A7468DE079C6CEB59F383A661E612");
if (dynamic.Count > 0)
{
rq.AddJsonBody(dynamic);
//最长30秒超时
rq.Timeout = 30 * 1000;
var res = rc.Execute(rq);
if (res.StatusCode == System.Net.HttpStatusCode.OK)
{
}
else
{
throw new Exception(res.ErrorMessage ?? res.Content);
}
}
}
#endregion
#endregion
#region 头程轨迹匹配规则
public async Task AddFirstTrackMatchRule(Logistics_FirstTrackMatch dto)
{
if ((await _unitOfWork.IsExistsAsync(x => x.LadingCode == dto.LadingCode && x.status == dto.status))) { throw new Exception("已存在相同提单号与状态的规则,不能重复添加"); }
long Id = await _unitOfWork.InsertAsync(dto);
return Id;
}
public async Task DeleteFirstTrackMatchRule(int Id)
{
bool result = await _unitOfWork.DeleteByIdAsync(Id);
return result;
}
public async Task UpdateFirstTrackMatchRule(Logistics_FirstTrackMatch dto)
{
if ((await _unitOfWork.IsExistsAsync(x => x.LadingCode == dto.LadingCode && x.status == dto.status && x.Id != dto.Id))) { throw new Exception("已存在相同提单号与状态的规则,不能重复添加"); }
bool result = await _unitOfWork.UpdateAsync(dto);
return result;
}
public async Task> GetFirstTrackMatchRules(QueryModel queryModel)
{
var pageResult = await _unitOfWork.GetPagingListAsync(queryModel);
return pageResult;
}
public async Task> GetAllFirstTrackMatchRules(List LadingCode)
{
string sqlWhere = string.Empty;
if (LadingCode != null && LadingCode.Count > 0) { sqlWhere = $" and LadingCode in @LadingCode "; }
string sql = "select *from Logistics_FirstTrackMatch where 1=1 " + sqlWhere;
var data = await _unitOfWork.QueryBySqlAsync(sql, null, new { LadingCode = LadingCode });
return data.ToList();
}
public async Task GetNodeTime(NodeTimeData data)
{
var dbData = (await _unitOfWork.QueryAsync(x => x.LadingBillNumber == data.LadingBillNumber));
var trackData = await QueryBy51Track(data.LadingBillNumber);
var prot1 = dbData?.FirstOrDefault()?.Destination;
var prot2 = dbData?.FirstOrDefault()?.OriginPort;
var track_infos = trackData.data.ladingInfo.return_data.flight_Infos;
if (string.IsNullOrEmpty(prot1) || string.IsNullOrEmpty(prot2)) { throw new Exception("提单号不正确,或提单口岸信息不全,无法匹配查询!"); }
if (track_infos == null || track_infos.Count == 0) { throw new Exception("提单起飞落地时间尚未更新,请过段时间再查!"); }
var OriginPortTrack = track_infos.Where(x => prot2.Trim() == x.depart_station.Trim())?.OrderBy(x => Convert.ToDateTime(x?.depart_time?.Trim()))?.FirstOrDefault();
var DestinationTrack = track_infos.Where(x => prot1.Trim() == x.arrival_station.Trim())?.OrderBy(x => Convert.ToDateTime(x?.arrival_time?.Trim()))?.FirstOrDefault();
if (OriginPortTrack != null && !string.IsNullOrEmpty(OriginPortTrack.depart_time))
{
data.Code1Time = OriginPortTrack.depart_time;
}
if (DestinationTrack != null && !string.IsNullOrEmpty(DestinationTrack.arrival_time))
{
data.Code2Time = DestinationTrack.arrival_time;
}
return data;
}
#endregion
#region 企微发送消息
public static void sendMessageToWeChat(string jobName, string message, List WeChatId)
{
int count = 0; bool isSucess = false;
do
{
try
{
var client = new RestClient("http://120.24.149.148:9505/WarningNotice/NoticeTextToUser");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
var weChatModel = new
{
ServiceType = "微信",
TargetName = jobName,
Content = "【" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "】 " + (!string.IsNullOrEmpty(message) ? "执行结果," + message : "定时任务完成"),
UserId = WeChatId,
};
var body = JsonConvert.SerializeObject(weChatModel);
request.AddParameter("application/json", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
isSucess = true;
}
else
{
count++;
}
}
catch (Exception ex)
{
count++;
}
Console.WriteLine($"【{jobName}】企微消息发送:{(isSucess ? "成功" : "失败")}");
//睡眠再继续
if (count <= 3 && !isSucess) { Thread.Sleep(TimeSpan.FromSeconds(30)); }
}
while (count <= 3 && !isSucess);
}
#endregion
}
}