using Furion;
using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.RemoteRequest.Extensions;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Myshipping.Core;
using Myshipping.Core.Service;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
namespace Myshipping.Application
{
///
/// 内嵌运踪港后数据查询
///
[AllowAnonymous, ApiDescriptionSettings("Application", Name = "EmbedTraceProduct", Order = 20)]
public class EmbedTraceProductService : IEmbedTraceProductService, IDynamicApiController, ITransient
{
private readonly ILogger _logger;
private const string CONST_TRACE_API_URL = "embed_trace_flow_url";
private readonly ISysCacheService _cache;
private readonly IDjyWebsiteAccountConfigService _webAccountConfig;
///
///
///
///
public EmbedTraceProductService(ILogger logger, ISysCacheService cache, IDjyWebsiteAccountConfigService webAccountConfig)
{
_logger = logger;
_cache = cache;
_webAccountConfig = webAccountConfig;
}
#region 获取单票运踪流程详情
///
/// 获取单票运踪流程详情
///
/// 查询单票运踪流程详情
/// 返回回执
[AllowAnonymous, HttpPost("/EmbedTraceProduct/GetTraceFlowInfo"), ApiUser(ApiCode = "EmbedServiceTraceShow")]
public async Task GetTraceFlowInfo(EmbedQueryTraceFlowDto model)
{
/*
1、调取运踪接口。 embed_trace_flow_url
2、根据返回结果组织暂时的JSON结果。
3、返回结果
*/
EmbedTraceFlowResultDto result = null;
string batchNo = IDGen.NextID().ToString();
string sendUrl = _cache.GetAllDictData().GetAwaiter().GetResult()
.FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == CONST_TRACE_API_URL)?.Value;
if (string.IsNullOrWhiteSpace(sendUrl))
throw Oops.Oh("未配置发送订舱请求接口地址,请联系管理员");
var webAccountConfig = _webAccountConfig
.GetAccountConfigByTenantId("seae_billtraceurl", UserManager.UserId, UserManager.TENANT_ID).GetAwaiter().GetResult();
if (webAccountConfig == null)
throw Oops.Oh("未配置账户,请先配置公司或者个人账户 类型-运踪新增调用");
QueryTraceAfterPortDto queryDto = new QueryTraceAfterPortDto
{
user_key = webAccountConfig.Account,
user_secret = webAccountConfig.Password,
carriercd = model.carrier,
referenceno = model.billNo,
ctnrno = model.ctnNo
};
var queryRlt = await QueryTraceAsync(queryDto, sendUrl);
var statusDict = _cache.GetAllDictData().GetAwaiter().GetResult()
.Where(t => t.TypeCode.Equals("after_port_trace_ctn_status", StringComparison.OrdinalIgnoreCase)).ToList();
//按顺序取状态配置字典
Dictionary> statusEnumDict = statusDict.Select(a => new { Key = a.Code, Val = new Tuple(a.Value,a.Remark, a.Sort), Sort = a.Sort })
.OrderBy(a => a.Sort).ToDictionary(a => a.Key, b => b.Val);
string[] skipStatus = new string[] { "GIOI", "LOFV", "FVD", "FVA", "DFFV", "LOR", "DFR", "RA", "DIFR", "LOT", "DIFT", "ADI", "DIDI", "CGRL", "RFP" };
string[] transferStatus = new string[] { "AIP", "BIP", "ETDIP", "DIIP", "GOIP", "GIIP", "LIP", "EDIP", "DEIP" };
if (queryRlt.code == 200)
{
var queryResult = queryRlt.data.FirstOrDefault();
result = queryResult.Adapt();
if (result != null && result.resultData != null)
{
//这里需要翻译一下箱型
var ctnCodeMappingList = _cache.GetAllMappingCtn().GetAwaiter().GetResult().ToList();
Dictionary referToCtnDict = new Dictionary();
bool isTransfer = false;
if (result.resultData.containerInfoList != null && result.resultData.containerInfoList.Count > 0)
{
result.resultData.containerInfoList.ForEach(s =>
{
var ctnMapping = ctnCodeMappingList.FirstOrDefault(t => t.MapCode.Equals(s.size));
if(ctnMapping != null)
{
s.sizeName = ctnMapping.MapName?.Trim();
}
if (s.containerStatusInfoList != null && s.containerStatusInfoList.Count > 0)
{
referToCtnDict.Add(s.containerNo, s.containerStatusInfoList.Count);
s.containerStatusInfoList = s.containerStatusInfoList.Select((a, idx) =>
{
a.sortNo = idx + 1;
if (statusEnumDict.Any(p => p.Key.Equals(a.statusCd, StringComparison.OrdinalIgnoreCase)))
{
a.statusCnName = statusEnumDict[a.statusCd].Item1;
}
else
{
a.statusCnName = a.statusCd;
}
return a;
}).ToList();
}
});
}
//legType = "T" 标识当票有中转
if (result.resultData.routingInfoList.Any(t => t.legType.Equals("T", StringComparison.OrdinalIgnoreCase)))
{
isTransfer = true;
}
result.embedTraceFlowStatusList = new List();
var ctnNo = referToCtnDict.OrderByDescending(a => a.Value).FirstOrDefault().Key;
var longContainerStatusList = result.resultData.containerInfoList.FirstOrDefault(a => a.containerNo.Equals(ctnNo, StringComparison.OrdinalIgnoreCase))
.containerStatusInfoList;
var takeList = result.resultData.containerInfoList.SelectMany(p => p.containerStatusInfoList).GroupBy(a => a.statusCd).Select(a =>
{
var currArg = a.ToList();
EmbedTraceFlowStatusInfo currStatus = new EmbedTraceFlowStatusInfo
{
voy = a.FirstOrDefault().voy,
statusDescription = a.FirstOrDefault().statusDescription,
statusTime = a.FirstOrDefault().statusTime,
vslName = a.FirstOrDefault().vslName,
statusCd = a.FirstOrDefault().statusCd,
statusPlace = a.FirstOrDefault().statusPlace,
statusTerminal = a.FirstOrDefault().statusTerminal,
statusCnName = a.FirstOrDefault().statusCnName,
sortNo = a.FirstOrDefault().sortNo,
};
if (!currArg.Any(a => !a.isEst.Equals("N", StringComparison.OrdinalIgnoreCase)))
{
currStatus.isComplete = true;
currStatus.hasStatusCtnNum = currArg.Count;
currStatus.noStatusCtnNum = 0;
}
else
{
currStatus.isComplete = true;
currStatus.hasStatusCtnNum = currArg.Count(a => a.isEst.Equals("N", StringComparison.OrdinalIgnoreCase));
currStatus.noStatusCtnNum = currArg.Count(a => !a.isEst.Equals("N", StringComparison.OrdinalIgnoreCase));
}
currStatus.statusCtnStatic = $"{currStatus.hasStatusCtnNum}/{(currStatus.hasStatusCtnNum + currStatus.noStatusCtnNum)}";
return currStatus;
}).ToList();
foreach (KeyValuePair> kvp in statusEnumDict)
{
if(!skipStatus.Contains(kvp.Key))
{
//不是中转的需要把状态节点去掉
if (isTransfer || (!isTransfer && !transferStatus.Contains(kvp.Key)))
{
var currStatus = takeList.FirstOrDefault(p => p.statusCd.Equals(kvp.Key, StringComparison.OrdinalIgnoreCase));
if (currStatus == null)
{
currStatus = new EmbedTraceFlowStatusInfo
{
statusCd = kvp.Key,
statusCnName = !string.IsNullOrWhiteSpace(kvp.Value.Item2)? kvp.Value.Item2 : kvp.Value.Item1,
sortNo = kvp.Value.Item3,
statusCtnStatic = $"0/{referToCtnDict.Count}",
};
}
else
{
if (!string.IsNullOrWhiteSpace(kvp.Value.Item2))
currStatus.statusCnName = kvp.Value.Item2;
}
result.embedTraceFlowStatusList.Add(currStatus);
}
}
}
}
}
return result;
}
#endregion
#region 查询运踪
///
/// 查询运踪
///
/// 查询参数
/// 请求URL
///
public async Task QueryTraceAsync(QueryTraceAfterPortDto query,string url)
{
QueryTraceAfterPortResultDto model = null;
try
{
var res = await url.OnClientCreating(client => {
// client 为 HttpClient 对象
client.Timeout = TimeSpan.FromMinutes(15); // 设置超时时间 15分钟
}).SetHttpMethod(HttpMethod.Post)
.SetBody(JSON.Serialize(query), "application/json")
.SetContentEncoding(Encoding.UTF8)
.PostAsync();
_logger.LogInformation("单号={no} 对应请求报文完成 post={post} res={res}", query.referenceno, JSON.Serialize(query), JSON.Serialize(res));
if (res.StatusCode == System.Net.HttpStatusCode.OK)
{
var userResult = await res.Content.ReadAsStringAsync();
model = JSON.Deserialize(userResult);
}
}
catch (Exception ex)
{
_logger.LogInformation($"请求运踪查询异常,原因:{ex.Message}");
throw Oops.Oh($"请求运踪查询异常,原因:{ex.Message}");
}
return model;
}
#endregion
}
}