|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
using Furion.DependencyInjection;
|
|
|
|
|
using Furion.DistributedIDGenerator;
|
|
|
|
|
using Furion.DynamicApiController;
|
|
|
|
|
using Furion.Extensions;
|
|
|
|
|
using Furion.FriendlyException;
|
|
|
|
|
using Furion.JsonSerialization;
|
|
|
|
|
using Furion.RemoteRequest.Extensions;
|
|
|
|
@ -15,10 +16,12 @@ using Myshipping.Core;
|
|
|
|
|
using Myshipping.Core.Entity;
|
|
|
|
|
using Myshipping.Core.Service;
|
|
|
|
|
using Org.BouncyCastle.Crypto;
|
|
|
|
|
using Org.BouncyCastle.Utilities;
|
|
|
|
|
using SqlSugar;
|
|
|
|
|
using StackExchange.Profiling.Internal;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.Specialized;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
@ -31,6 +34,8 @@ using System.Text.Json;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Web;
|
|
|
|
|
using Ubiety.Dns.Core;
|
|
|
|
|
using Yitter.IdGenerator;
|
|
|
|
|
|
|
|
|
|
namespace Myshipping.Application
|
|
|
|
@ -48,6 +53,7 @@ namespace Myshipping.Application
|
|
|
|
|
private readonly SqlSugarRepository<BookingFile> _bookingfile;
|
|
|
|
|
private readonly SqlSugarRepository<DjyWebsiteAccountConfig> _djyWebsiteAccountConfigRepository;
|
|
|
|
|
private readonly SqlSugarRepository<SysUser> _sysUserRepository;
|
|
|
|
|
private readonly SqlSugarRepository<BookingLetteryard> _bookingLetteryardRepository;
|
|
|
|
|
|
|
|
|
|
const string CONST_MAPPING_BC_MODULE_ROUTE = "BC_DOWN_RT";
|
|
|
|
|
const string CONST_MAPPING_DRAFT_MODULE_ROUTE = "DRAFT_DOWN_RT";
|
|
|
|
@ -59,9 +65,13 @@ namespace Myshipping.Application
|
|
|
|
|
|
|
|
|
|
const string CONST_FORMAT_WEB = "{0}Web";
|
|
|
|
|
|
|
|
|
|
const string CONST_BC_FILE_PARSE_URL = "bc_file_parse_url";
|
|
|
|
|
const string CONST_BC_FILE_READ_URL = "bc_file_pdf_read_url";
|
|
|
|
|
|
|
|
|
|
public BookingValueAddedService(ISysCacheService cache, ILogger<BookingTruckService> logger,
|
|
|
|
|
SqlSugarRepository<BookingOrder> bookingOrderRepository, SqlSugarRepository<BookingFile> bookingfile,
|
|
|
|
|
SqlSugarRepository<DjyWebsiteAccountConfig> djyWebsiteAccountConfigRepository, SqlSugarRepository<SysUser> sysUserRepository)
|
|
|
|
|
SqlSugarRepository<DjyWebsiteAccountConfig> djyWebsiteAccountConfigRepository, SqlSugarRepository<SysUser> sysUserRepository,
|
|
|
|
|
SqlSugarRepository<BookingLetteryard> bookingLetteryardRepository)
|
|
|
|
|
{
|
|
|
|
|
_cache = cache;
|
|
|
|
|
_logger = logger;
|
|
|
|
@ -71,6 +81,7 @@ namespace Myshipping.Application
|
|
|
|
|
|
|
|
|
|
_djyWebsiteAccountConfigRepository = djyWebsiteAccountConfigRepository;
|
|
|
|
|
_sysUserRepository = sysUserRepository;
|
|
|
|
|
_bookingLetteryardRepository = bookingLetteryardRepository;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1191,10 +1202,153 @@ namespace Myshipping.Application
|
|
|
|
|
/// 单票BC文件解析
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="file">上传文件</param>
|
|
|
|
|
/// <param name="bookingOrderId">订舱主键</param>
|
|
|
|
|
/// <returns>返回回执</returns>
|
|
|
|
|
public async Task<TaskManageOrderResultDto> SingleBCFileRead(IFormFile file)
|
|
|
|
|
[HttpPost("/BookingValueAdded/SingleBCFileRead")]
|
|
|
|
|
public async Task<TaskManageOrderResultDto> SingleBCFileRead(IFormFile file, long bookingOrderId)
|
|
|
|
|
{
|
|
|
|
|
return new TaskManageOrderResultDto();
|
|
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
|
|
|
|
SingleBCDto singleBCDto = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
1、推送附件到识别接口,等待识别结果。
|
|
|
|
|
2、解析识别结果,并返回BC的解析明细。
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if(bookingOrderId < 0)
|
|
|
|
|
throw Oops.Oh($"订舱主键不能为空");
|
|
|
|
|
|
|
|
|
|
var bookingOrder = _bookingOrderRepository.AsQueryable().First(a => a.Id == bookingOrderId);
|
|
|
|
|
|
|
|
|
|
if(bookingOrder == null)
|
|
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
|
|
|
|
//获取解析BC文件链接
|
|
|
|
|
var bcUrl = _cache.GetAllDictData().GetAwaiter().GetResult()
|
|
|
|
|
.FirstOrDefault(x => x.TypeCode == "url_set" && x.Code.Equals(CONST_BC_FILE_PARSE_URL, StringComparison.OrdinalIgnoreCase))?.Value;
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation("提单号{mbl} 获取解析BC文件URL完成,结果={rlt}",
|
|
|
|
|
bookingOrder.MBLNO, bcUrl);
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(bcUrl))
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation("提单号{0} 获取解析BC文件URL失败,未取到配置key={key}",
|
|
|
|
|
bookingOrder.MBLNO, CONST_BC_FILE_PARSE_URL);
|
|
|
|
|
|
|
|
|
|
throw Oops.Bah($"未配置请求地址{CONST_BC_FILE_PARSE_URL} 请联系管理员");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] bytes = file.ToByteArray();
|
|
|
|
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
//请求BC解析
|
|
|
|
|
var bcParseRlt = await TransmitFile(bcUrl, new
|
|
|
|
|
{
|
|
|
|
|
file = "file",
|
|
|
|
|
fileName = file.FileName,
|
|
|
|
|
fileBytes = bytes
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation("批次={no} result={result} 获取解析BC文件URL结束 耗时:{timeDiff}ms. ", batchNo,
|
|
|
|
|
JSON.Serialize(bcParseRlt), timeDiff);
|
|
|
|
|
|
|
|
|
|
if (bcParseRlt.status == 1)
|
|
|
|
|
{
|
|
|
|
|
var currBC = bcParseRlt.data.BCList.FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
singleBCDto = new SingleBCDto
|
|
|
|
|
{
|
|
|
|
|
BookingOrderId = bookingOrderId,
|
|
|
|
|
BLNo = currBC.BLNo?.Trim().ToUpper(),
|
|
|
|
|
Vessel = currBC.Vessel?.Trim().ToUpper(),
|
|
|
|
|
Voyage = currBC.Voyage?.Trim().ToUpper(),
|
|
|
|
|
ClosingDate = currBC.ClosingDate,
|
|
|
|
|
CYCutOffTime = currBC.CYCutOffTime,
|
|
|
|
|
ETD = currBC.ETD
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
singleBCDto.BookingOrderBCDto = new BookingOrderBCDto {
|
|
|
|
|
MBLNO = bookingOrder.MBLNO,
|
|
|
|
|
CUSTNO = bookingOrder.CUSTNO,
|
|
|
|
|
CLOSEDOCDATE = bookingOrder.CLOSEDOCDATE,
|
|
|
|
|
CLOSEVGMDATE = bookingOrder.CLOSEVGMDATE,
|
|
|
|
|
CLOSINGDATE = bookingOrder.CLOSINGDATE,
|
|
|
|
|
ETD = bookingOrder.ETD,
|
|
|
|
|
VESSEL = bookingOrder.VESSEL,
|
|
|
|
|
VOYNO = bookingOrder.VOYNO,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
result.succ = true;
|
|
|
|
|
result.ext = singleBCDto;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result.succ = false;
|
|
|
|
|
result.msg = $"解析BC失败,原因:{bcParseRlt.message}";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation("批次={no} 解析BC异常,原因:{error} ", batchNo, ex.Message);
|
|
|
|
|
|
|
|
|
|
result.succ = false;
|
|
|
|
|
result.msg = $"解析BC异常,原因:{ex.Message}";
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 请求BC解析
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="requestUrl">请求地址</param>
|
|
|
|
|
/// <param name="fileInfo">文件详情</param>
|
|
|
|
|
/// <returns>返回BC解析详情</returns>
|
|
|
|
|
private async Task<BCAPIBaseDataParse> TransmitFile(string requestUrl, dynamic fileInfo)
|
|
|
|
|
{
|
|
|
|
|
BCAPIBaseDataParse model = null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var response = await requestUrl.SetContentType("multipart/form-data")
|
|
|
|
|
.SetBodyBytes((fileInfo.file.ToString(), fileInfo.fileBytes, fileInfo.fileName.ToString()))
|
|
|
|
|
.PostAsync();
|
|
|
|
|
|
|
|
|
|
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
|
|
|
|
{
|
|
|
|
|
var result = response.Content.ReadAsStringAsync().Result;
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(result))
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Bah($"获取解析BC文件失败,未获取到有效信息");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.Text.Json.JsonSerializerOptions jsonOptions = new JsonSerializerOptions();
|
|
|
|
|
jsonOptions.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
jsonOptions.Converters.Add(new IntegerJsonConverter());
|
|
|
|
|
jsonOptions.Converters.Add(new DecimalJsonConverter());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model = JSON.Deserialize<BCAPIBaseDataParse>(result, jsonOptions);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation("{name} 发送BC文件解析请求 url={url} 异常,原因={error}", nameof(TransmitFile),
|
|
|
|
|
requestUrl, ex.Message);
|
|
|
|
|
|
|
|
|
|
throw Oops.Bah($"{nameof(TransmitFile)} {requestUrl} 发送BC文件解析请求异常,{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
return model;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -1231,5 +1385,59 @@ namespace Myshipping.Application
|
|
|
|
|
writer.WriteStringValue(value.ToUniversalTime().ToString(_dateFormatString));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class IntegerJsonConverter : System.Text.Json.Serialization.JsonConverter<Int32>
|
|
|
|
|
{
|
|
|
|
|
public IntegerJsonConverter()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Int32 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
|
|
|
|
{
|
|
|
|
|
if (reader.TokenType == JsonTokenType.String)
|
|
|
|
|
{
|
|
|
|
|
var curStr = reader.GetString();
|
|
|
|
|
Int32 curVal = 0;
|
|
|
|
|
Int32.TryParse(curStr, out curVal);
|
|
|
|
|
return curVal;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return reader.GetInt32();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Write(Utf8JsonWriter writer, Int32 value, JsonSerializerOptions options)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteNumberValue(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class DecimalJsonConverter : System.Text.Json.Serialization.JsonConverter<decimal>
|
|
|
|
|
{
|
|
|
|
|
public DecimalJsonConverter()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override decimal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
|
|
|
|
{
|
|
|
|
|
if (reader.TokenType == JsonTokenType.String)
|
|
|
|
|
{
|
|
|
|
|
var curStr = reader.GetString();
|
|
|
|
|
decimal curVal = 0;
|
|
|
|
|
decimal.TryParse(curStr, out curVal);
|
|
|
|
|
return curVal;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return reader.GetDecimal();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteNumberValue(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|