|
|
using Furion;
|
|
|
using Furion.DependencyInjection;
|
|
|
using Furion.DistributedIDGenerator;
|
|
|
using Furion.DynamicApiController;
|
|
|
using Furion.Extensions;
|
|
|
using Furion.FriendlyException;
|
|
|
using Furion.JsonSerialization;
|
|
|
using Furion.RemoteRequest.Extensions;
|
|
|
using Mapster;
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
using Myshipping.Application.ConfigOption;
|
|
|
using Myshipping.Application.Entity;
|
|
|
using Myshipping.Application.Service.BookingOrder.Dto;
|
|
|
using Myshipping.Core;
|
|
|
using Myshipping.Core.Entity;
|
|
|
using Myshipping.Core.Service;
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
using SqlSugar;
|
|
|
using StackExchange.Profiling.Internal;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Net.Http;
|
|
|
using System.Runtime.InteropServices;
|
|
|
using System.Text;
|
|
|
using System.Text.Json;
|
|
|
using System.Text.RegularExpressions;
|
|
|
using System.Threading.Tasks;
|
|
|
using System.Web;
|
|
|
using Yitter.IdGenerator;
|
|
|
|
|
|
namespace Myshipping.Application
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 订舱增值类服务
|
|
|
/// </summary>
|
|
|
[ApiDescriptionSettings("Application", Name = "BookingValueAdded", Order = 9)]
|
|
|
public class BookingValueAddedService : IBookingValueAddedService, IDynamicApiController, ITransient
|
|
|
{
|
|
|
private readonly ISysCacheService _cache;
|
|
|
//private readonly IBookingOrderService _bookingOrderService;
|
|
|
private readonly ILogger<BookingTruckService> _logger;
|
|
|
private readonly SqlSugarRepository<BookingOrder> _bookingOrderRepository;
|
|
|
private readonly SqlSugarRepository<BookingFile> _bookingFileRepository;
|
|
|
private readonly SqlSugarRepository<DjyWebsiteAccountConfig> _djyWebsiteAccountConfigRepository;
|
|
|
private readonly SqlSugarRepository<SysUser> _sysUserRepository;
|
|
|
private readonly SqlSugarRepository<BookingLetteryard> _bookingLetteryardRepository;
|
|
|
private readonly SqlSugarRepository<TaskBCInfo> _taskBCInfoRepository;
|
|
|
private readonly SqlSugarRepository<BookingStatusLog> _statuslogRepository;
|
|
|
private readonly SqlSugarRepository<BookingStatusLogDetail> _statuslogdetailRepository;
|
|
|
private readonly SqlSugarRepository<BookingLog> _bookinglogRepository;
|
|
|
private readonly SqlSugarRepository<BookingLogDetail> _bookinglogdetailRepository;
|
|
|
private readonly SqlSugarRepository<BookingRemark> _bookingRemarkRepository;
|
|
|
private readonly SqlSugarRepository<BookingCtnVGM> _bookingCtnVGMRepository;
|
|
|
|
|
|
private readonly IServiceWorkFlowBaseService _serviceWorkFlowBaseService;
|
|
|
private readonly IServiceWorkFlowManageService _serviceWorkFlowManageService;
|
|
|
private readonly IDjyWebsiteAccountConfigService _webAccountConfigService;
|
|
|
private readonly INamedServiceProvider<IBookingOrderService> _namedBookingOrderServiceProvider;
|
|
|
|
|
|
const string CONST_MAPPING_BC_MODULE_ROUTE = "BC_DOWN_RT";
|
|
|
const string CONST_MAPPING_DRAFT_MODULE_ROUTE = "DRAFT_DOWN_RT";
|
|
|
const string CONST_MAPPING_MANIALLO_CHK_MODULE_ROUTE = "MANI_ALLOC_CHK_RT";
|
|
|
|
|
|
const string CONST_FORMAT_BC_URL = "{0}_bc_down_url";
|
|
|
const string CONST_FORMAT_DRAFT_URL = "{0}_draft_down_url";
|
|
|
const string CONST_FORMAT_MANIALLO_CHK_URL = "{0}_manialloc_chk_url";
|
|
|
|
|
|
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<DjyWebsiteAccountConfig> djyWebsiteAccountConfigRepository, SqlSugarRepository<SysUser> sysUserRepository,
|
|
|
SqlSugarRepository<BookingLetteryard> bookingLetteryardRepository//,// IBookingOrderService bookingOrderService
|
|
|
, SqlSugarRepository<TaskBCInfo> taskBCInfoRepository, IServiceWorkFlowBaseService serviceWorkFlowBaseService,
|
|
|
SqlSugarRepository<BookingStatusLog> statuslogRepository, SqlSugarRepository<BookingStatusLogDetail> statuslogdetailRepository,
|
|
|
SqlSugarRepository<BookingLog> bookinglogRepository, SqlSugarRepository<BookingLogDetail> bookinglogdetailRepository,
|
|
|
SqlSugarRepository<BookingRemark> bookingRemarkRepository, SqlSugarRepository<BookingFile> bookingFileRepository,
|
|
|
INamedServiceProvider<IBookingOrderService> namedBookingOrderServiceProvider,
|
|
|
IServiceWorkFlowManageService serviceWorkFlowManageService, SqlSugarRepository<BookingCtnVGM> bookingCtnVGMRepository, IDjyWebsiteAccountConfigService webAccountConfigService)
|
|
|
{
|
|
|
_cache = cache;
|
|
|
_logger = logger;
|
|
|
|
|
|
_bookingOrderRepository = bookingOrderRepository;
|
|
|
|
|
|
_djyWebsiteAccountConfigRepository = djyWebsiteAccountConfigRepository;
|
|
|
_sysUserRepository = sysUserRepository;
|
|
|
_bookingLetteryardRepository = bookingLetteryardRepository;
|
|
|
//_bookingOrderService = bookingOrderService;
|
|
|
_taskBCInfoRepository = taskBCInfoRepository;
|
|
|
|
|
|
_serviceWorkFlowBaseService = serviceWorkFlowBaseService;
|
|
|
_statuslogRepository = statuslogRepository;
|
|
|
_statuslogdetailRepository = statuslogdetailRepository;
|
|
|
_bookinglogRepository = bookinglogRepository;
|
|
|
_bookinglogdetailRepository = bookinglogdetailRepository;
|
|
|
_bookingRemarkRepository = bookingRemarkRepository;
|
|
|
_bookingFileRepository = bookingFileRepository;
|
|
|
_bookingCtnVGMRepository = bookingCtnVGMRepository;
|
|
|
|
|
|
_serviceWorkFlowManageService = serviceWorkFlowManageService;
|
|
|
_namedBookingOrderServiceProvider = namedBookingOrderServiceProvider;
|
|
|
_webAccountConfigService = webAccountConfigService;
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 批量BC下载
|
|
|
/// </summary>
|
|
|
/// <param name="bookingIds">订舱主键数组</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/DownloadBookingConfirm")]
|
|
|
public async Task<TaskManageOrderResultDto> DownloadBookingConfirm([FromBody] long[] bookingIds)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
List<Task<TaskManageOrderResultDto>> taskList = new List<Task<TaskManageOrderResultDto>>();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
try
|
|
|
{
|
|
|
/*
|
|
|
1、订舱主键提取提单号、订舱编号,优先去提单号,其次订舱编号
|
|
|
2、根据不同的船公司调取单独的配置账户。
|
|
|
3、不同船公司对应不同的接口。
|
|
|
4、轮询异步调取接口等待返回接口。
|
|
|
5、成功后将文件链接存入附件表。
|
|
|
6、等待所有请求完成返回统计结果。
|
|
|
*/
|
|
|
|
|
|
var list = _bookingOrderRepository.AsQueryable()
|
|
|
.Where(a => bookingIds.Contains(a.Id)).ToList();
|
|
|
|
|
|
if (list.Count != bookingIds.Length)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
var noList = bookingIds.Select((a, idx) => new { no = idx + 1, id = a }).ToList();
|
|
|
|
|
|
foreach (var bk in list)
|
|
|
{
|
|
|
var sortNo = noList.FirstOrDefault(a => a.id == bk.Id).no;
|
|
|
taskList.Add(Task.Run(() => InnerDownloadBookingConfirm(bk, batchNo, sortNo)));
|
|
|
}
|
|
|
|
|
|
Task.WaitAll(taskList.ToArray());
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "批量下载BC成功";
|
|
|
|
|
|
var downResultList = taskList.Select(x => x.Result).ToList();
|
|
|
|
|
|
if (downResultList.Any(x => !x.succ))
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = "BC下载失败";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = downResultList.FirstOrDefault().msg;
|
|
|
}
|
|
|
|
|
|
result.ext = downResultList;
|
|
|
|
|
|
var succ = downResultList.Count(x => x.succ);
|
|
|
var fail = downResultList.Count(x => !x.succ);
|
|
|
|
|
|
if (succ > 0)
|
|
|
{
|
|
|
result.batchTotal = succ.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.batchTotal = "- ";
|
|
|
}
|
|
|
|
|
|
if (fail > 0)
|
|
|
{
|
|
|
result.batchTotal += "/" + fail.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.batchTotal += " -";
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"批量BC下载异常,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
#region 单票下载BC
|
|
|
/// <summary>
|
|
|
/// 单票下载BC
|
|
|
/// </summary>
|
|
|
/// <param name="bookingOrder">订舱详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <param name="sortNo">请求顺序号</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
private async Task<TaskManageOrderResultDto> InnerDownloadBookingConfirm(BookingOrder bookingOrder, string batchNo, int sortNo)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
result.bno = bookingOrder.MBLNO;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
/*
|
|
|
1、根据船公司代码匹配船公司映射。
|
|
|
2、BC和DRAFT是分别2个请求地址。
|
|
|
3、生成请求报文。
|
|
|
4、请求相应的链接。
|
|
|
5、返回成功写入附件。
|
|
|
*/
|
|
|
if (string.IsNullOrWhiteSpace(bookingOrder.MBLNO))
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(bookingOrder.CUSTNO))
|
|
|
{
|
|
|
result.bno = $"订 {bookingOrder.CUSTNO}";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.bno = $"NO.{sortNo}";
|
|
|
}
|
|
|
|
|
|
throw Oops.Bah($"主提单号不能为空");
|
|
|
}
|
|
|
|
|
|
var bcOrDraftRouteCfg = _cache.GetAllMappingCarrier().GetAwaiter().GetResult()
|
|
|
.FirstOrDefault(t => t.Module.Equals(CONST_MAPPING_BC_MODULE_ROUTE, StringComparison.OrdinalIgnoreCase)
|
|
|
&& t.Code.Equals(bookingOrder.CARRIERID?.Trim(), StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
|
_logger.LogInformation("提单号【{mbl}】根据订舱的船公司代码{ca} 提取船公司映射完成,结果={rlt}",
|
|
|
bookingOrder.MBLNO, bookingOrder.CARRIERID, bcOrDraftRouteCfg);
|
|
|
|
|
|
if (bcOrDraftRouteCfg == null)
|
|
|
{
|
|
|
_logger.LogInformation("提单号{mbl} 根据订舱的船公司代码{ca} 提取船公司映射失败",
|
|
|
bookingOrder.MBLNO, bookingOrder.CARRIERID);
|
|
|
|
|
|
throw Oops.Bah($"船公司={bookingOrder.CARRIERID} 暂不支持BC下载");
|
|
|
}
|
|
|
|
|
|
string urlKey = string.Format(CONST_FORMAT_BC_URL, bcOrDraftRouteCfg.MapCode.ToLower());
|
|
|
|
|
|
var bcUrl = _cache.GetAllDictData().GetAwaiter().GetResult()
|
|
|
.FirstOrDefault(x => x.TypeCode == "url_set" && x.Code.Equals(urlKey, StringComparison.OrdinalIgnoreCase))?.Value;
|
|
|
|
|
|
_logger.LogInformation("提单号{mbl} 根据订舱的船公司代码{ca} 提取BC下载URL完成,结果={rlt}",
|
|
|
bookingOrder.MBLNO, bookingOrder.CARRIERID, bcUrl);
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(bcUrl))
|
|
|
{
|
|
|
_logger.LogInformation("提单号{0} 根据订舱的船公司代码{1} 提取BC下载URL失败,未取到配置key={key}",
|
|
|
bookingOrder.MBLNO, bookingOrder.CARRIERID, urlKey);
|
|
|
|
|
|
throw Oops.Bah($"船公司={bookingOrder.CARRIERID} 未配置请求地址{urlKey} 请联系管理员");
|
|
|
}
|
|
|
|
|
|
string webKey = string.Format(CONST_FORMAT_WEB, bcOrDraftRouteCfg.MapCode);
|
|
|
|
|
|
//获取个人对应的账户,这里GetAccountConfig逻辑优先取个人,个人没有配置取公司对应配置
|
|
|
var userWebAccountConfig = GetAccountConfig(webKey, UserManager.UserId, UserManager.TENANT_ID).GetAwaiter()
|
|
|
.GetResult();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 获取获取网站的账户完成,result={Num}", batchNo, JSON.Serialize(userWebAccountConfig));
|
|
|
|
|
|
if (userWebAccountConfig == null)
|
|
|
throw Oops.Oh($" 未配置个人或公司网站账户,网站{webKey}");
|
|
|
|
|
|
BCOrDraftRequestDto requestDto = new BCOrDraftRequestDto
|
|
|
{
|
|
|
user_key = App.Configuration["BCOrDraftUserKey"],
|
|
|
user_secret = App.Configuration["BCOrDraftUserSecret"],
|
|
|
web_user = userWebAccountConfig.Account?.Trim(),
|
|
|
web_psw = userWebAccountConfig.Password?.Trim(),
|
|
|
bno = bookingOrder.MBLNO,
|
|
|
is_parse = false
|
|
|
};
|
|
|
|
|
|
_logger.LogInformation("批次={no} json={json} 请求BC远端下载开始", batchNo, JSON.Serialize(requestDto));
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
//开始请求BC
|
|
|
var rlt = await ExcuteBCDownload(bcUrl, requestDto, batchNo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} result={result} 请求BC远端下载结束 耗时:{timeDiff}ms. ", batchNo,
|
|
|
JSON.Serialize(rlt), timeDiff);
|
|
|
|
|
|
if (rlt.code == 200)
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} 下载文件成功,转存本地", batchNo);
|
|
|
|
|
|
string currFilePath = rlt.data.FirstOrDefault().path;
|
|
|
|
|
|
string fileTypeCode = "bc";
|
|
|
string fileTypeName = "Booking Confirmation";
|
|
|
|
|
|
//读取文件配置
|
|
|
var fileCfg = App.GetOptions<BookingAttachOptions>();
|
|
|
|
|
|
string relativePath = $"{fileCfg.relativePath}\\bcfiles\\{bookingOrder.Id}";
|
|
|
string filePath = $"{(!string.IsNullOrWhiteSpace(fileCfg.basePath) ? fileCfg.basePath : App.WebHostEnvironment.WebRootPath)}\\{relativePath}";
|
|
|
|
|
|
string fileFullName = $"{filePath}\\{new System.IO.FileInfo(currFilePath).Name}";
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
{
|
|
|
relativePath = relativePath.Replace("\\", "/");
|
|
|
filePath = filePath.Replace("\\", "/");
|
|
|
|
|
|
fileFullName = fileFullName.Replace("\\", "/");
|
|
|
}
|
|
|
|
|
|
_logger.LogInformation("批次={no} 生成文件保存路径完成 路由={filePath} 服务器系统={system}", batchNo, filePath, RuntimeInformation.OSDescription);
|
|
|
//预先创建目录
|
|
|
if (!Directory.Exists(filePath))
|
|
|
{
|
|
|
Directory.CreateDirectory(filePath);
|
|
|
}
|
|
|
|
|
|
var bcStream = await currFilePath.GetAsStreamAsync();
|
|
|
|
|
|
using (var fileStream = File.Create(fileFullName))
|
|
|
{
|
|
|
await bcStream.CopyToAsync(fileStream);
|
|
|
}
|
|
|
|
|
|
_logger.LogInformation("批次={no} 完成文件保存 filepath={path}", batchNo, fileFullName);
|
|
|
|
|
|
string bookFilePath = string.Empty;
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
{
|
|
|
bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("/", "\\/") + ".*").Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("\\", "\\\\") + ".*").Value;
|
|
|
}
|
|
|
|
|
|
//这里先写入附件表
|
|
|
await SaveEDIFile(bookingOrder.Id, bookFilePath, new System.IO.FileInfo(currFilePath).Name,
|
|
|
fileTypeCode, fileTypeName);
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "BC下载成功";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"BC下载失败,{rlt.msg}";
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"BC下载失败,{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 异步写入订舱附件表
|
|
|
/// <summary>
|
|
|
/// 异步写入订舱附件表
|
|
|
/// </summary>
|
|
|
/// <param name="boookId">订舱ID</param>
|
|
|
/// <param name="FilePath">文件路径</param>
|
|
|
/// <param name="fileName">文件名</param>
|
|
|
/// <param name="fileTypeCode">附件类型代码</param>
|
|
|
/// <param name="fileTypeName">附件类型名称</param>
|
|
|
/// <returns></returns>
|
|
|
[NonAction]
|
|
|
private async Task SaveEDIFile(long boookId, string FilePath, string fileName, string fileTypeCode = "bc", string fileTypeName = "Booking Confirmation")
|
|
|
{
|
|
|
/*
|
|
|
直接将附件信息写入附件表
|
|
|
*/
|
|
|
//EDI文件
|
|
|
var bookFile = new BookingFile
|
|
|
{
|
|
|
Id = YitIdHelper.NextId(),
|
|
|
FileName = fileName,
|
|
|
FilePath = FilePath,
|
|
|
TypeCode = fileTypeCode,
|
|
|
TypeName = fileTypeName,
|
|
|
BookingId = boookId,
|
|
|
};
|
|
|
|
|
|
await _bookingFileRepository.InsertAsync(bookFile);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 批量Draft下载
|
|
|
/// </summary>
|
|
|
/// <param name="bookingIds">订舱主键数组</param>
|
|
|
/// <returns></returns>
|
|
|
[HttpPost("/BookingValueAdded/DownloadDraft")]
|
|
|
public async Task<TaskManageOrderResultDto> DownloadDraft([FromBody] long[] bookingIds)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
List<Task<TaskManageOrderResultDto>> taskList = new List<Task<TaskManageOrderResultDto>>();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
/*
|
|
|
1、订舱主键提取提单号、订舱编号,优先去提单号,其次订舱编号
|
|
|
2、根据不同的船公司调取单独的配置账户。
|
|
|
3、不同船公司对应不同的接口。
|
|
|
4、轮询异步调取接口等待返回接口。
|
|
|
5、成功后将文件链接存入附件表。
|
|
|
6、等待所有请求完成返回统计结果。
|
|
|
*/
|
|
|
|
|
|
var list = _bookingOrderRepository.AsQueryable()
|
|
|
.Where(a => bookingIds.Contains(a.Id)).ToList();
|
|
|
|
|
|
if (list.Count != bookingIds.Length)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
var noList = bookingIds.Select((a, idx) => new { no = idx + 1, id = a }).ToList();
|
|
|
foreach (var bk in list)
|
|
|
{
|
|
|
var sortNo = noList.FirstOrDefault(a => a.id == bk.Id).no;
|
|
|
taskList.Add(Task.Run(() => InnerDownloadDraft(bk, batchNo, sortNo)));
|
|
|
}
|
|
|
|
|
|
Task.WaitAll(taskList.ToArray());
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "下载Draft成功";
|
|
|
|
|
|
var downResultList = taskList.Select(x => x.Result).ToList();
|
|
|
|
|
|
if (downResultList.Any(x => !x.succ))
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = "Draft下载失败";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = downResultList.FirstOrDefault().msg;
|
|
|
}
|
|
|
|
|
|
result.ext = downResultList;
|
|
|
|
|
|
var succ = downResultList.Count(x => x.succ);
|
|
|
var fail = downResultList.Count(x => !x.succ);
|
|
|
|
|
|
if (succ > 0)
|
|
|
{
|
|
|
result.batchTotal = succ.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.batchTotal = "- ";
|
|
|
}
|
|
|
|
|
|
if (fail > 0)
|
|
|
{
|
|
|
result.batchTotal += "/" + fail.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.batchTotal += " -";
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"下载Draft异常,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
#region 单票下载BC
|
|
|
/// <summary>
|
|
|
/// 单票下载BC
|
|
|
/// </summary>
|
|
|
/// <param name="bookingOrder">订舱详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <param name="sortNo">请求顺序号</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
private async Task<TaskManageOrderResultDto> InnerDownloadDraft(BookingOrder bookingOrder, string batchNo, int sortNo)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
result.bno = bookingOrder.MBLNO;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
/*
|
|
|
1、根据船公司代码匹配船公司映射。
|
|
|
2、BC和DRAFT是分别2个请求地址。
|
|
|
3、生成请求报文。
|
|
|
4、请求相应的链接。
|
|
|
5、返回成功写入附件。
|
|
|
*/
|
|
|
if (bookingOrder.CARRIERID.Equals("ESL", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace(bookingOrder.TMBLNO))
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(bookingOrder.CUSTNO))
|
|
|
{
|
|
|
result.bno = $"订 {bookingOrder.CUSTNO}";
|
|
|
}
|
|
|
else if (string.IsNullOrWhiteSpace(bookingOrder.MBLNO))
|
|
|
{
|
|
|
result.bno = $"NO.{sortNo}";
|
|
|
}
|
|
|
|
|
|
throw Oops.Bah($"EP号不能为空");
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace(bookingOrder.MBLNO))
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(bookingOrder.CUSTNO))
|
|
|
{
|
|
|
result.bno = $"订 {bookingOrder.CUSTNO}";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.bno = $"NO.{sortNo}";
|
|
|
}
|
|
|
|
|
|
throw Oops.Bah($"主提单号不能为空");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var bcOrDraftRouteCfg = _cache.GetAllMappingCarrier().GetAwaiter().GetResult()
|
|
|
.FirstOrDefault(t => t.Module.Equals(CONST_MAPPING_DRAFT_MODULE_ROUTE, StringComparison.OrdinalIgnoreCase)
|
|
|
&& t.Code.Equals(bookingOrder.CARRIERID?.Trim(), StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
|
_logger.LogInformation("提单号{mbl} 根据订舱的船公司代码{ca} 提取船公司映射完成,结果={rlt}",
|
|
|
bookingOrder.MBLNO, bookingOrder.CARRIERID, bcOrDraftRouteCfg);
|
|
|
|
|
|
if (bcOrDraftRouteCfg == null)
|
|
|
{
|
|
|
_logger.LogInformation("提单号{0} 根据订舱的船公司代码{1} 提取船公司映射失败",
|
|
|
bookingOrder.MBLNO, bookingOrder.CARRIERID);
|
|
|
|
|
|
throw Oops.Bah($"船公司={bookingOrder.CARRIERID} 暂不支持Draft下载");
|
|
|
}
|
|
|
|
|
|
string urlKey = string.Format(CONST_FORMAT_DRAFT_URL, bcOrDraftRouteCfg.MapCode.ToLower());
|
|
|
|
|
|
var bcUrl = _cache.GetAllDictData().GetAwaiter().GetResult()
|
|
|
.FirstOrDefault(x => x.TypeCode == "url_set" && x.Code.Equals(urlKey, StringComparison.OrdinalIgnoreCase))?.Value;
|
|
|
|
|
|
_logger.LogInformation("提单号{mbl} 根据订舱的船公司代码{ca} 提取DRAFT下载URL完成,结果={rlt}",
|
|
|
bookingOrder.MBLNO, bookingOrder.CARRIERID, bcUrl);
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(bcUrl))
|
|
|
{
|
|
|
_logger.LogInformation("提单号{0} 根据订舱的船公司代码{1} 提取BC下载URL失败,未取到配置key={key}",
|
|
|
bookingOrder.MBLNO, bookingOrder.CARRIERID, urlKey);
|
|
|
|
|
|
throw Oops.Bah($"船公司={bookingOrder.CARRIERID} 未配置请求地址{urlKey} 请联系管理员");
|
|
|
}
|
|
|
|
|
|
string webKey = string.Format(CONST_FORMAT_WEB, bcOrDraftRouteCfg.MapCode);
|
|
|
|
|
|
//获取个人对应的账户,这里GetAccountConfig逻辑优先取个人,个人没有配置取公司对应配置
|
|
|
var userWebAccountConfig = GetAccountConfig(webKey, UserManager.UserId, UserManager.TENANT_ID).GetAwaiter()
|
|
|
.GetResult();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 获取获取网站的账户完成,result={Num}", batchNo, JSON.Serialize(userWebAccountConfig));
|
|
|
|
|
|
if (userWebAccountConfig == null)
|
|
|
throw Oops.Oh($" 未配置个人或公司网站账户,网站{webKey}");
|
|
|
|
|
|
string downloadFilePathRlt = string.Empty;
|
|
|
string erroMsg = string.Empty;
|
|
|
|
|
|
if (bcOrDraftRouteCfg.MapCode.Trim().Equals("ESL", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
ESLDraftRequestDto requestDto = new ESLDraftRequestDto
|
|
|
{
|
|
|
u = userWebAccountConfig.Account?.Trim(),
|
|
|
p = userWebAccountConfig.Password?.Trim(),
|
|
|
ep_code = bookingOrder.TMBLNO?.Trim().ToUpper(),
|
|
|
};
|
|
|
|
|
|
_logger.LogInformation("批次={no} json={json} 请求Draft远端下载开始", batchNo, JSON.Serialize(requestDto));
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
//开始请求BC
|
|
|
var rlt = await ExcuteESLDraftDownload(bcUrl, requestDto, batchNo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} result={result} 请求Draft远端下载结束 耗时:{timeDiff}ms. ", batchNo,
|
|
|
JSON.Serialize(rlt), timeDiff);
|
|
|
|
|
|
if (rlt.status == 1)
|
|
|
{
|
|
|
downloadFilePathRlt = rlt.data.api_path;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
erroMsg = rlt.message;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
BCOrDraftRequestDto requestDto = new BCOrDraftRequestDto
|
|
|
{
|
|
|
user_key = App.Configuration["BCOrDraftUserKey"],
|
|
|
user_secret = App.Configuration["BCOrDraftUserSecret"],
|
|
|
web_user = userWebAccountConfig.Account?.Trim(),
|
|
|
web_psw = userWebAccountConfig.Password?.Trim(),
|
|
|
bno = bookingOrder.MBLNO,
|
|
|
is_parse = false
|
|
|
};
|
|
|
|
|
|
_logger.LogInformation("批次={no} json={json} 请求Draft远端下载开始", batchNo, JSON.Serialize(requestDto));
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
//开始请求BC
|
|
|
var rlt = await ExcuteDraftDownload(bcUrl, requestDto, batchNo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} result={result} 请求Draft远端下载结束 耗时:{timeDiff}ms. ", batchNo,
|
|
|
JSON.Serialize(rlt), timeDiff);
|
|
|
|
|
|
if (rlt.code == 200)
|
|
|
{
|
|
|
downloadFilePathRlt = rlt.data.FirstOrDefault().path;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
erroMsg = rlt.msg;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(downloadFilePathRlt))
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} 下载文件成功,转存本地", batchNo);
|
|
|
|
|
|
string currFilePath = downloadFilePathRlt;
|
|
|
|
|
|
string fileTypeCode = "draft";
|
|
|
string fileTypeName = "Draft";
|
|
|
|
|
|
//读取文件配置
|
|
|
var fileCfg = App.GetOptions<BookingAttachOptions>();
|
|
|
|
|
|
string relativePath = $"{fileCfg.relativePath}\\draftfiles\\{bookingOrder.Id}";
|
|
|
string filePath = $"{(!string.IsNullOrWhiteSpace(fileCfg.basePath) ? fileCfg.basePath : App.WebHostEnvironment.WebRootPath)}\\{relativePath}";
|
|
|
|
|
|
string fileFullName = $"{filePath}\\{new System.IO.FileInfo(currFilePath).Name}";
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
{
|
|
|
relativePath = relativePath.Replace("\\", "/");
|
|
|
filePath = filePath.Replace("\\", "/");
|
|
|
|
|
|
fileFullName = fileFullName.Replace("\\", "/");
|
|
|
}
|
|
|
|
|
|
_logger.LogInformation("批次={no} 生成文件保存路径完成 路由={filePath} 服务器系统={system}", batchNo, filePath, RuntimeInformation.OSDescription);
|
|
|
//预先创建目录
|
|
|
if (!Directory.Exists(filePath))
|
|
|
{
|
|
|
Directory.CreateDirectory(filePath);
|
|
|
}
|
|
|
|
|
|
var bcStream = await currFilePath.GetAsStreamAsync();
|
|
|
|
|
|
using (var fileStream = File.Create(fileFullName))
|
|
|
{
|
|
|
await bcStream.CopyToAsync(fileStream);
|
|
|
}
|
|
|
|
|
|
_logger.LogInformation("批次={no} 完成文件保存 filepath={path}", batchNo, fileFullName);
|
|
|
|
|
|
string bookFilePath = string.Empty;
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
{
|
|
|
bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("/", "\\/") + ".*").Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("\\", "\\\\") + ".*").Value;
|
|
|
}
|
|
|
|
|
|
//这里先写入附件表
|
|
|
await SaveEDIFile(bookingOrder.Id, bookFilePath, new System.IO.FileInfo(currFilePath).Name,
|
|
|
fileTypeCode, fileTypeName);
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "Draft下载成功";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"Draft下载失败,原因={erroMsg}";
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"Draft下载失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region BC请求远端下载
|
|
|
/// <summary>
|
|
|
/// BC请求远端下载
|
|
|
/// </summary>
|
|
|
/// <param name="url">请求URL</param>
|
|
|
/// <param name="info">请求详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <returns>返回结果</returns>
|
|
|
[NonAction]
|
|
|
private async Task<BCAPIBaseResult> ExcuteBCDownload(string url, BCOrDraftRequestDto info, string batchNo)
|
|
|
{
|
|
|
BCAPIBaseResult model = null;
|
|
|
/*
|
|
|
1、填充请求的类,并生成JSON报文
|
|
|
2、POST请求接口,并记录回执。
|
|
|
3、返回信息。
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} 对应请求报文 request={res}", batchNo, JSON.Serialize(info));
|
|
|
|
|
|
var res = await url.OnClientCreating(client =>
|
|
|
{
|
|
|
// client 为 HttpClient 对象
|
|
|
client.Timeout = TimeSpan.FromMinutes(15); // 设置超时时间 15分钟
|
|
|
}).SetHttpMethod(HttpMethod.Post)
|
|
|
.SetBody(JSON.Serialize(info), "application/json")
|
|
|
.SetContentEncoding(Encoding.UTF8)
|
|
|
.PostAsync();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 对应请求报文完成 res={res}", batchNo, JSON.Serialize(res));
|
|
|
|
|
|
if (res.StatusCode == System.Net.HttpStatusCode.OK)
|
|
|
{
|
|
|
var userResult = await res.Content.ReadAsStringAsync();
|
|
|
|
|
|
System.Text.Json.JsonSerializerOptions jsonOptions = new JsonSerializerOptions();
|
|
|
jsonOptions.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
|
model = JSON.Deserialize<BCAPIBaseResult>(userResult, jsonOptions);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
//写日志
|
|
|
if (ex is HttpRequestException)
|
|
|
throw Oops.Oh(10000002);
|
|
|
}
|
|
|
|
|
|
return model;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Draft请求远端下载
|
|
|
/// <summary>
|
|
|
/// Draft请求远端下载
|
|
|
/// </summary>
|
|
|
/// <param name="url">请求URL</param>
|
|
|
/// <param name="info">请求详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <returns>返回结果</returns>
|
|
|
[NonAction]
|
|
|
private async Task<DraftAPIBaseResult> ExcuteDraftDownload(string url, BCOrDraftRequestDto info, string batchNo)
|
|
|
{
|
|
|
DraftAPIBaseResult model = null;
|
|
|
/*
|
|
|
1、填充请求的类,并生成JSON报文
|
|
|
2、POST请求接口,并记录回执。
|
|
|
3、返回信息。
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} 对应请求报文 request={res}", batchNo, JSON.Serialize(info));
|
|
|
|
|
|
var res = await url.OnClientCreating(client =>
|
|
|
{
|
|
|
// client 为 HttpClient 对象
|
|
|
client.Timeout = TimeSpan.FromMinutes(15); // 设置超时时间 15分钟
|
|
|
}).SetHttpMethod(HttpMethod.Post)
|
|
|
.SetBody(JSON.Serialize(info), "application/json")
|
|
|
.SetContentEncoding(Encoding.UTF8)
|
|
|
.PostAsync();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 对应请求报文完成 res={res}", batchNo, JSON.Serialize(res));
|
|
|
|
|
|
if (res.StatusCode == System.Net.HttpStatusCode.OK)
|
|
|
{
|
|
|
var userResult = await res.Content.ReadAsStringAsync();
|
|
|
|
|
|
System.Text.Json.JsonSerializerOptions jsonOptions = new JsonSerializerOptions();
|
|
|
jsonOptions.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
|
model = JSON.Deserialize<DraftAPIBaseResult>(userResult, jsonOptions);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
//写日志
|
|
|
if (ex is HttpRequestException)
|
|
|
throw Oops.Oh(10000002);
|
|
|
}
|
|
|
|
|
|
return model;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region ESL Draft请求远端下载
|
|
|
/// <summary>
|
|
|
/// ESL Draft请求远端下载
|
|
|
/// 由于现有的ESL和TSL接口不一致,需要提供单独的POST方法
|
|
|
/// </summary>
|
|
|
/// <param name="url">请求URL</param>
|
|
|
/// <param name="info">请求详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <returns>返回结果</returns>
|
|
|
[NonAction]
|
|
|
private async Task<ESLDraftAPIBaseResult> ExcuteESLDraftDownload(string url, ESLDraftRequestDto info, string batchNo)
|
|
|
{
|
|
|
ESLDraftAPIBaseResult model = null;
|
|
|
/*
|
|
|
1、填充请求的类,并生成JSON报文
|
|
|
2、POST请求接口,并记录回执。
|
|
|
3、返回信息。
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} 对应请求报文 request={res}", batchNo, JSON.Serialize(info));
|
|
|
|
|
|
var res = await url.OnClientCreating(client =>
|
|
|
{
|
|
|
// client 为 HttpClient 对象
|
|
|
client.Timeout = TimeSpan.FromMinutes(15); // 设置超时时间 15分钟
|
|
|
}).SetHttpMethod(HttpMethod.Post)
|
|
|
.SetBody(JSON.Serialize(info), "application/json")
|
|
|
.SetContentEncoding(Encoding.UTF8)
|
|
|
.PostAsync();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 对应请求报文完成 res={res}", batchNo, JSON.Serialize(res));
|
|
|
|
|
|
if (res.StatusCode == System.Net.HttpStatusCode.OK)
|
|
|
{
|
|
|
var userResult = await res.Content.ReadAsStringAsync();
|
|
|
|
|
|
model = JSON.Deserialize<ESLDraftAPIBaseResult>(userResult);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
//写日志
|
|
|
if (ex is HttpRequestException)
|
|
|
throw Oops.Oh(10000002);
|
|
|
}
|
|
|
|
|
|
return model;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region ESL SO Ref.No搜索ESL号查询
|
|
|
/// <summary>
|
|
|
/// ESL SO Ref.No搜索ESL号查询
|
|
|
/// </summary>
|
|
|
/// <param name="url">请求URL</param>
|
|
|
/// <param name="info">请求详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <returns>返回结果</returns>
|
|
|
[NonAction]
|
|
|
private async Task<ESLManiAlloChkAPIBaseResult> ExcuteManiAllocCheckDownload(string url, ESLManiAlloChkRequestDto info, string batchNo)
|
|
|
{
|
|
|
ESLManiAlloChkAPIBaseResult model = null;
|
|
|
/*
|
|
|
1、填充请求的类,并生成JSON报文
|
|
|
2、POST请求接口,并记录回执。
|
|
|
3、返回信息。
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} 对应请求报文 request={res}", batchNo, JSON.Serialize(info));
|
|
|
|
|
|
var res = await url.OnClientCreating(client =>
|
|
|
{
|
|
|
// client 为 HttpClient 对象
|
|
|
client.Timeout = TimeSpan.FromMinutes(15); // 设置超时时间 15分钟
|
|
|
}).SetHttpMethod(HttpMethod.Post)
|
|
|
.SetBody(JSON.Serialize(info), "application/json")
|
|
|
.SetContentEncoding(Encoding.UTF8)
|
|
|
.PostAsync();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 对应请求报文完成 res={res}", batchNo, JSON.Serialize(res));
|
|
|
|
|
|
if (res.StatusCode == System.Net.HttpStatusCode.OK)
|
|
|
{
|
|
|
var userResult = await res.Content.ReadAsStringAsync();
|
|
|
model = JSON.Deserialize<ESLManiAlloChkAPIBaseResult>(userResult);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
//写日志
|
|
|
if (ex is HttpRequestException)
|
|
|
throw Oops.Oh(10000002);
|
|
|
}
|
|
|
|
|
|
return model;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 舱位分配查询
|
|
|
/// </summary>
|
|
|
/// <param name="bookingIds">订舱主键数组</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/CheckUpdateManifestNo")]
|
|
|
public async Task<TaskManageOrderResultDto> CheckUpdateManifestNo([FromBody] long[] bookingIds)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
List<Task<TaskManageOrderResultDto>> taskList = new List<Task<TaskManageOrderResultDto>>();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
/*
|
|
|
现在只有ESL支持舱位分配查询
|
|
|
|
|
|
1、订舱主键提取提单号,判断提单号如果不是ESL开头的,需要启动流程
|
|
|
2、异步调取ESL接口。
|
|
|
3、返回结果后提取esl_no号
|
|
|
4、将参考号写入订舱编号。
|
|
|
5、将esl_no号写入主提单号。
|
|
|
6、等待所有请求完成返回统计结果。
|
|
|
*/
|
|
|
|
|
|
var list = _bookingOrderRepository.AsQueryable()
|
|
|
.Where(a => bookingIds.Contains(a.Id)).ToList();
|
|
|
|
|
|
if (list.Count != bookingIds.Length)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
var noList = bookingIds.Select((a, idx) => new { no = idx + 1, id = a }).ToList();
|
|
|
foreach (var bk in list)
|
|
|
{
|
|
|
var sortNo = noList.FirstOrDefault(a => a.id == bk.Id).no;
|
|
|
taskList.Add(Task.Run(() => InnerCheckUpdateManifestNo(bk, batchNo, sortNo)));
|
|
|
}
|
|
|
|
|
|
Task.WaitAll(taskList.ToArray());
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "批量执行成功";
|
|
|
|
|
|
var downResultList = taskList.Select(x => x.Result).ToList();
|
|
|
|
|
|
if (downResultList.Any(x => !x.succ))
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = "批量执行失败";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = downResultList.FirstOrDefault().msg;
|
|
|
}
|
|
|
|
|
|
result.ext = downResultList;
|
|
|
|
|
|
var succ = downResultList.Count(x => x.succ);
|
|
|
var fail = downResultList.Count(x => !x.succ);
|
|
|
|
|
|
if (succ > 0)
|
|
|
{
|
|
|
result.batchTotal = succ.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.batchTotal = "- ";
|
|
|
}
|
|
|
|
|
|
if (fail > 0)
|
|
|
{
|
|
|
result.batchTotal += "/" + fail.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.batchTotal += " -";
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"批量执行失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
#region 单票舱位分配查询
|
|
|
/// <summary>
|
|
|
/// 单票舱位分配查询
|
|
|
/// </summary>
|
|
|
/// <param name="bookingOrder">订舱详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <param name="sortNo">请求顺序号</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
private async Task<TaskManageOrderResultDto> InnerCheckUpdateManifestNo(BookingOrder bookingOrder, string batchNo, int sortNo)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
result.bno = bookingOrder.MBLNO;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
/*
|
|
|
1、根据船公司代码匹配船公司映射。
|
|
|
2、BC和DRAFT是分别2个请求地址。
|
|
|
3、生成请求报文。
|
|
|
4、请求相应的链接。
|
|
|
5、返回成功写入附件。
|
|
|
*/
|
|
|
|
|
|
//2023-07-06 按照最新要求,从订舱编号取单号
|
|
|
if (string.IsNullOrWhiteSpace(bookingOrder.CUSTNO))
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(bookingOrder.MBLNO))
|
|
|
{
|
|
|
result.bno = $"订 {bookingOrder.MBLNO}";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.bno = $"NO.{sortNo}";
|
|
|
}
|
|
|
|
|
|
throw Oops.Bah($"订舱编号不能为空");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (Regex.IsMatch(bookingOrder.CUSTNO, "\\bESL\\w+"))
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 订舱编号没填写参考号,无法继续", batchNo, bookingOrder.Id);
|
|
|
|
|
|
throw Oops.Oh($"订舱编号不是有效的参考号");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var bcOrDraftRouteCfg = _cache.GetAllMappingCarrier().GetAwaiter().GetResult()
|
|
|
.FirstOrDefault(t => t.Module.Equals(CONST_MAPPING_MANIALLO_CHK_MODULE_ROUTE, StringComparison.OrdinalIgnoreCase)
|
|
|
&& t.Code.Equals(bookingOrder.CARRIERID?.Trim(), StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
|
_logger.LogInformation("订舱编号【{mbl}】根据订舱的船公司代码{ca} 提取船公司映射完成,结果={rlt}",
|
|
|
bookingOrder.CUSTNO, bookingOrder.CARRIERID, bcOrDraftRouteCfg);
|
|
|
|
|
|
if (bcOrDraftRouteCfg == null)
|
|
|
{
|
|
|
_logger.LogInformation("订舱编号{mbl} 根据订舱的船公司代码{ca} 提取船公司映射失败",
|
|
|
bookingOrder.CUSTNO, bookingOrder.CARRIERID);
|
|
|
|
|
|
throw Oops.Bah($"船公司={bookingOrder.CARRIERID} 暂不支持舱位分配查询");
|
|
|
}
|
|
|
|
|
|
string urlKey = string.Format(CONST_FORMAT_MANIALLO_CHK_URL, bcOrDraftRouteCfg.MapCode.ToLower());
|
|
|
|
|
|
var bcUrl = _cache.GetAllDictData().GetAwaiter().GetResult()
|
|
|
.FirstOrDefault(x => x.TypeCode == "url_set" && x.Code.Equals(urlKey, StringComparison.OrdinalIgnoreCase))?.Value;
|
|
|
|
|
|
_logger.LogInformation("订舱编号{mbl} 根据订舱的船公司代码{ca} 提取舱位分配查询URL完成,结果={rlt}",
|
|
|
bookingOrder.CUSTNO, bookingOrder.CARRIERID, bcUrl);
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(bcUrl))
|
|
|
{
|
|
|
_logger.LogInformation("订舱编号{0} 根据订舱的船公司代码{1} 提取舱位分配查询URL失败,未取到配置key={key}",
|
|
|
bookingOrder.CUSTNO, bookingOrder.CARRIERID, urlKey);
|
|
|
|
|
|
throw Oops.Bah($"船公司={bookingOrder.CARRIERID} 未配置请求地址{urlKey} 请联系管理员");
|
|
|
}
|
|
|
|
|
|
string webKey = string.Format(CONST_FORMAT_WEB, bcOrDraftRouteCfg.MapCode);
|
|
|
|
|
|
//获取个人对应的账户,这里GetAccountConfig逻辑优先取个人,个人没有配置取公司对应配置
|
|
|
var userWebAccountConfig = GetAccountConfig(webKey, UserManager.UserId, UserManager.TENANT_ID).GetAwaiter()
|
|
|
.GetResult();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 获取获取网站的账户完成,result={Num}", batchNo, JSON.Serialize(userWebAccountConfig));
|
|
|
|
|
|
if (userWebAccountConfig == null)
|
|
|
throw Oops.Oh($" 未配置个人或公司网站账户,网站{webKey}");
|
|
|
|
|
|
ESLManiAlloChkRequestDto requestDto = new ESLManiAlloChkRequestDto
|
|
|
{
|
|
|
u = userWebAccountConfig.Account?.Trim(),
|
|
|
p = userWebAccountConfig.Password?.Trim(),
|
|
|
so_no = bookingOrder.CUSTNO,
|
|
|
};
|
|
|
|
|
|
_logger.LogInformation("批次={no} json={json} 请求舱位分配查询远端下载开始", batchNo, JSON.Serialize(requestDto));
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
//开始请求BC
|
|
|
var rlt = await ExcuteManiAllocCheckDownload(bcUrl, requestDto, batchNo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} result={result} 请求舱位分配查询远端下载结束 耗时:{timeDiff}ms. ", batchNo,
|
|
|
JSON.Serialize(rlt), timeDiff);
|
|
|
|
|
|
if (rlt.status == 1)
|
|
|
{
|
|
|
if (rlt.data == null || string.IsNullOrWhiteSpace(rlt.data.esl_no))
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} 舱位分配查询失败,ESL号不存在", batchNo);
|
|
|
|
|
|
throw Oops.Oh($"查询ESL号失败");
|
|
|
}
|
|
|
_logger.LogInformation("批次={no} 舱位分配查询成功", batchNo);
|
|
|
|
|
|
/*
|
|
|
提单号写入订舱编号,并把esl_no写入主提单号
|
|
|
*/
|
|
|
var bkInfo = _bookingOrderRepository.AsQueryable().First(a => a.Id == bookingOrder.Id);
|
|
|
|
|
|
if (bkInfo == null)
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 订舱信息获取失败,无法更新", batchNo, bookingOrder.Id);
|
|
|
|
|
|
throw Oops.Oh($"订舱信息获取失败,无法更新");
|
|
|
}
|
|
|
var oldBkInfo = bkInfo.Adapt<BookingOrder>();
|
|
|
|
|
|
/* //2023-07-06 按照最新要求,从订舱编号取单号,所以这里不判断了
|
|
|
if(Regex.IsMatch(bkInfo.MBLNO,"\\bESL\\w+"))
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 主提单号已变更,无法更新", batchNo, bookingOrder.Id);
|
|
|
|
|
|
throw Oops.Oh($"主提单号已变更,无法更新");
|
|
|
}*/
|
|
|
|
|
|
_logger.LogInformation("批次={no} 变更前记录 id={id} MBLNO={MBLNO} CUSTNO={CUSTNO} esl_no={eslno}",
|
|
|
batchNo, bookingOrder.Id, bkInfo.MBLNO, bkInfo.CUSTNO, rlt.data.esl_no);
|
|
|
|
|
|
//bkInfo.CUSTNO = bkInfo.MBLNO;
|
|
|
bkInfo.MBLNO = rlt.data.esl_no.Trim().ToUpper();
|
|
|
bkInfo.UpdatedTime = DateTime.Now;
|
|
|
bkInfo.UpdatedUserId = UserManager.UserId;
|
|
|
bkInfo.UpdatedUserName = UserManager.Name;
|
|
|
|
|
|
await _bookingOrderRepository.AsUpdateable(bkInfo).UpdateColumns(it => new
|
|
|
{
|
|
|
it.MBLNO,
|
|
|
it.UpdatedTime,
|
|
|
it.UpdatedUserId,
|
|
|
it.UpdatedUserName
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
|
var _bookingOrderService = _namedBookingOrderServiceProvider.GetService<ITransient>(nameof(BookingOrderService));
|
|
|
// 记录日志
|
|
|
await _bookingOrderService.SaveLog(bkInfo, oldBkInfo, $"{bookingOrder.CARRIERID}舱位分配查询回写提单号");
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "舱位分配查询成功";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"舱位分配查询失败,{rlt.message}";
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"舱位分配查询失败,{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 提交规则意见
|
|
|
/// </summary>
|
|
|
/// <param name="model">规则意见详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/SubmitRuleOpinion")]
|
|
|
public async Task<TaskManageOrderResultDto> SubmitRuleOpinion([FromBody] RulesEngineUserFeedBackDto model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
try
|
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace(model.ruleName) && model.opinionType == "MODIFY")
|
|
|
throw Oops.Oh($"规则名称不能为空");
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(model.opinionType))
|
|
|
throw Oops.Oh($"意见类型不能为空");
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(model.opinionContent))
|
|
|
throw Oops.Oh($"意见内容不能为空");
|
|
|
|
|
|
RulesEngineUserFeedBackMessageInfo msgModel = new RulesEngineUserFeedBackMessageInfo();
|
|
|
|
|
|
msgModel.Head = new RulesEngineUserFeedBackHead
|
|
|
{
|
|
|
GID = batchNo,
|
|
|
MessageType = "BUSI_RULE",
|
|
|
SenderId = App.Configuration["RulesEngineSender"],
|
|
|
SenderName = App.Configuration["RulesEngineSenderName"],
|
|
|
SenderKey = App.Configuration["RulesEngineAuthKey"],
|
|
|
ReceiverId = "RulesEngine",
|
|
|
ReceiverName = "大简云规则引擎",
|
|
|
Version = "1.0",
|
|
|
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
|
|
|
RequestAction = "Add",
|
|
|
};
|
|
|
|
|
|
msgModel.Main = new RulesEngineUserFeedBackMain
|
|
|
{
|
|
|
ruleName = model.ruleName,
|
|
|
opinionType = model.opinionType,
|
|
|
opinionContent = model.opinionContent,
|
|
|
ruleNotice = model.ruleNotice,
|
|
|
submitUser = UserManager.Name
|
|
|
};
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
var rlt = await ExcuteRuleOpinion(App.Configuration["RulesEngineOpinionUrl"], msgModel, batchNo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg}", batchNo, timeDiff, rlt.succ ? "成功" : "失败");
|
|
|
|
|
|
|
|
|
if (!rlt.succ)
|
|
|
{
|
|
|
throw Oops.Oh($"请求失败,原因={rlt.msg}");
|
|
|
}
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "提交成功";
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"提交规则意见失败,{ex.Message}";
|
|
|
|
|
|
_logger.LogInformation("批次={no} 异常,{msg}", batchNo, ex.Message);
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 查询规则意见历史
|
|
|
/// </summary>
|
|
|
/// <param name="model">规则意见详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/GetRuleOpinionLog")]
|
|
|
public async Task<TaskManageOrderResultDto> GetRuleOpinionLog([FromBody] RulesEngineUserFeedBackDto model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
try
|
|
|
{
|
|
|
RulesEngineUserFeedBackMessageInfo msgModel = new RulesEngineUserFeedBackMessageInfo();
|
|
|
|
|
|
msgModel.Head = new RulesEngineUserFeedBackHead
|
|
|
{
|
|
|
GID = batchNo,
|
|
|
MessageType = "BUSI_RULE",
|
|
|
SenderId = App.Configuration["RulesEngineSender"],
|
|
|
SenderName = App.Configuration["RulesEngineSenderName"],
|
|
|
SenderKey = App.Configuration["RulesEngineAuthKey"],
|
|
|
ReceiverId = "RulesEngine",
|
|
|
ReceiverName = "大简云规则引擎",
|
|
|
Version = "1.0",
|
|
|
RequestDate = nowDate.ToString("yyyy-MM-dd HH:mm:ss"),
|
|
|
RequestAction = "Add",
|
|
|
};
|
|
|
|
|
|
msgModel.Main = new RulesEngineUserFeedBackMain
|
|
|
{
|
|
|
ruleName = model.ruleName,
|
|
|
opinionType = model.opinionType,
|
|
|
opinionContent = model.opinionContent,
|
|
|
ruleNotice = model.ruleNotice,
|
|
|
submitUser = UserManager.Name
|
|
|
};
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
var rlt = await ExcuteRuleOpinion(App.Configuration["RulesEngineQueryOpinionUrl"], msgModel, batchNo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg}", batchNo, timeDiff, rlt.succ ? "成功" : "失败");
|
|
|
|
|
|
|
|
|
if (!rlt.succ)
|
|
|
{
|
|
|
throw Oops.Oh($"请求失败,原因={rlt.msg}");
|
|
|
}
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "查询成功";
|
|
|
|
|
|
if (rlt.rows != null)
|
|
|
result.rows = JSON.Deserialize<List<RulesEngineUserFeedBackCollectionLogShowDto>>(JSON.Serialize(rlt.rows));
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"查询规则意见历史失败,{ex.Message}";
|
|
|
|
|
|
_logger.LogInformation("批次={no} 异常,{msg}", batchNo, ex.Message);
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
#region 规则用户反馈请求远端
|
|
|
/// <summary>
|
|
|
/// 规则用户反馈请求远端
|
|
|
/// </summary>
|
|
|
/// <param name="url">请求URL</param>
|
|
|
/// <param name="info">请求详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <returns>返回结果</returns>
|
|
|
[NonAction]
|
|
|
private async Task<RulesEngineWebApiResult> ExcuteRuleOpinion(string url, RulesEngineUserFeedBackMessageInfo info, string batchNo)
|
|
|
{
|
|
|
RulesEngineWebApiResult model = null;
|
|
|
/*
|
|
|
1、填充请求的类,并生成JSON报文
|
|
|
2、POST请求接口,并记录回执。
|
|
|
3、返回信息。
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} 对应请求报文 request={res}", batchNo, JSON.Serialize(info));
|
|
|
|
|
|
var res = await url.OnClientCreating(client =>
|
|
|
{
|
|
|
// client 为 HttpClient 对象
|
|
|
client.Timeout = TimeSpan.FromMinutes(15); // 设置超时时间 15分钟
|
|
|
}).SetHttpMethod(HttpMethod.Post)
|
|
|
.SetBody(JSON.Serialize(info), "application/json")
|
|
|
.SetContentEncoding(Encoding.UTF8)
|
|
|
.PostAsync();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 对应请求报文完成 res={res}", batchNo, JSON.Serialize(res));
|
|
|
|
|
|
if (res.StatusCode == System.Net.HttpStatusCode.OK)
|
|
|
{
|
|
|
var userResult = await res.Content.ReadAsStringAsync();
|
|
|
|
|
|
_logger.LogInformation("批次={no} 对应请求报文完成 userResult={userResult}", batchNo, userResult);
|
|
|
model = JSON.Deserialize<RulesEngineWebApiResult>(userResult);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
//写日志
|
|
|
if (ex is HttpRequestException)
|
|
|
throw Oops.Oh(10000002);
|
|
|
}
|
|
|
|
|
|
return model;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取个人或公司网站账户配置
|
|
|
/// </summary>
|
|
|
/// <param name="typeCode">账户类型代码</param>
|
|
|
/// <param name="userId">用户ID</param>
|
|
|
/// <param name="tendId">租户ID</param>
|
|
|
/// <returns>返回账户配置</returns>
|
|
|
private async Task<DjyWebsiteAccountConfig> GetAccountConfig(string typeCode, long userId, long tendId)
|
|
|
{
|
|
|
DjyWebsiteAccountConfig accountConfig = new DjyWebsiteAccountConfig();
|
|
|
accountConfig = await _djyWebsiteAccountConfigRepository.EntityContext.CopyNew().Queryable<DjyWebsiteAccountConfig>()
|
|
|
.FirstAsync(x => x.TypeCode == typeCode && x.CreatedUserId == userId);
|
|
|
|
|
|
if (accountConfig == null)
|
|
|
{
|
|
|
accountConfig = await _djyWebsiteAccountConfigRepository.EntityContext.CopyNew().Queryable<DjyWebsiteAccountConfig>()
|
|
|
.FirstAsync(x => x.TypeCode == typeCode && x.TenantId == tendId && x.IsTenant == true);
|
|
|
}
|
|
|
|
|
|
return accountConfig;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 单票BC文件解析
|
|
|
/// </summary>
|
|
|
/// <param name="file">上传文件</param>
|
|
|
/// <param name="bookingOrderId">订舱主键</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/SingleBCFileRead")]
|
|
|
public async Task<TaskManageOrderResultDto> SingleBCFileRead(IFormFile file, [FromForm] long bookingOrderId)
|
|
|
{
|
|
|
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();
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(currBC.Vessel) && Regex.IsMatch(currBC.Vessel, "\\(|(|\\)|)|\\n"))
|
|
|
{
|
|
|
if (Regex.IsMatch(currBC.Vessel, "\\(|(|\\)|)"))
|
|
|
{
|
|
|
currBC.Vessel = Regex.Match(currBC.Vessel, "\\w+\\s?\\n?\\s?\\w+(?=\\()").Value;
|
|
|
}
|
|
|
|
|
|
if (Regex.IsMatch(currBC.Vessel, "\\n"))
|
|
|
{
|
|
|
currBC.Vessel = Regex.Replace(Regex.Replace(currBC.Vessel, "\\n", " "), "\\s{2,}", " ");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
singleBCDto = new SingleBCDto
|
|
|
{
|
|
|
BookingOrderId = bookingOrderId,
|
|
|
BLNo = currBC.BLNo?.Trim().ToUpper(),
|
|
|
Vessel = currBC.Vessel?.Trim().ToUpper(),
|
|
|
Voyage = currBC.Voyage?.Trim().ToUpper(),
|
|
|
ClosingDate = currBC.CutSingleTime,
|
|
|
CYCutOffTime = currBC.CYCutOffTime,
|
|
|
VGMCutOffTime = currBC.VGMCutOffTime,
|
|
|
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,
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
这里考虑后面会有将文件写入附件表的动作,在识别成功后将文件写入暂存路径,后续完成放舱讲文件写入正式链接
|
|
|
*/
|
|
|
//读取文件配置
|
|
|
|
|
|
var fileFullName = await FileAttachHelper.TempSaveWebFile(bookingOrder.Id.ToString(), file, batchNo);
|
|
|
|
|
|
_logger.LogInformation("批次={no} 完成文件保存 filepath={path}", batchNo, fileFullName);
|
|
|
|
|
|
singleBCDto.FileTempPath = fileFullName;
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
#region 请求BC解析
|
|
|
/// <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, HttpUtility.UrlEncode(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;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 单票BC更新订舱
|
|
|
/// <summary>
|
|
|
/// 单票BC更新订舱
|
|
|
/// </summary>
|
|
|
/// <param name="model">单票BC详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/SingleBCUpdateBookingOrder")]
|
|
|
public async Task<TaskManageOrderResultDto> SingleBCUpdateBookingOrder(SingleBCDto model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
/*
|
|
|
1、根据BC的数据更新订舱相关信息(提单号、截港时间、截单时间、船名航次、开船日期)
|
|
|
2、如果选择了转为入货通知,则先保存入货通知。
|
|
|
3、调取入货通知的发送。
|
|
|
*/
|
|
|
var bookingOrder = _bookingOrderRepository.AsQueryable().First(a => a.Id == model.BookingOrderId);
|
|
|
|
|
|
if (bookingOrder == null)
|
|
|
throw Oops.Bah($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
var updateRlt = InnerBCUpdateBookingOrder(model, bookingOrder, batchNo, 1).GetAwaiter().GetResult();
|
|
|
|
|
|
if (!updateRlt.succ)
|
|
|
throw Oops.Bah($"订舱信息更新失败,{updateRlt.msg}");
|
|
|
|
|
|
if (model.IsLetterYard)
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 单票BC更新订舱后,用户选择转为入货通知,开始执行入货通知", batchNo
|
|
|
, bookingOrder.Id);
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(model.FileTempPath))
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 未提交文件路径,请求失败", batchNo
|
|
|
, bookingOrder.Id);
|
|
|
|
|
|
throw Oops.Bah($"未提交文件路径,执行放舱失败");
|
|
|
}
|
|
|
|
|
|
var letterYardDto = new UpdateBookingLetteryardInput();
|
|
|
|
|
|
letterYardDto = model.LetteryardDto.Adapt<UpdateBookingLetteryardInput>();
|
|
|
|
|
|
if (model.LetterYardId.HasValue && model.LetterYardId.Value > 0)
|
|
|
{
|
|
|
letterYardDto.Id = model.LetterYardId.Value;
|
|
|
|
|
|
_logger.LogInformation("批次={no} id={id} 单票BC更新订舱后,存在放舱记录 LetterYardId={LetterYardId}", batchNo
|
|
|
, bookingOrder.Id, letterYardDto.Id);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var letterYardModel = _bookingLetteryardRepository.AsQueryable()
|
|
|
.First(x => x.BookingId == model.BookingOrderId);
|
|
|
|
|
|
if (letterYardModel != null)
|
|
|
letterYardDto.Id = letterYardModel.Id;
|
|
|
}
|
|
|
var _bookingOrderService = _namedBookingOrderServiceProvider.GetService<ITransient>(nameof(BookingOrderService));
|
|
|
//放舱保存
|
|
|
var letterYardId = await _bookingOrderService.LetteryardSave(letterYardDto);
|
|
|
|
|
|
_logger.LogInformation("批次={no} id={id} 已完放舱记录保存 返回结果{rlt}", batchNo
|
|
|
, bookingOrder.Id, letterYardId);
|
|
|
|
|
|
_logger.LogInformation("批次={no} id={id} templateid={tempid} 开始发送放舱", batchNo
|
|
|
, bookingOrder.Id, model.TemplateId);
|
|
|
|
|
|
//发送放舱
|
|
|
await _bookingOrderService.SendLetterYard(model.BookingOrderId, model.TemplateId);
|
|
|
|
|
|
_logger.LogInformation("批次={no} id={id} templateid={tempid} 完成发送放舱", batchNo
|
|
|
, bookingOrder.Id, model.TemplateId);
|
|
|
|
|
|
string fileTypeCode = "bc";
|
|
|
string fileTypeName = "Booking Confirmation";
|
|
|
|
|
|
//重新将暂存文件写入正式路径
|
|
|
|
|
|
//读取文件配置
|
|
|
var bookFilePath = await FileAttachHelper.MoveFile(bookingOrder.Id.ToString(), model.FileTempPath, batchNo);
|
|
|
|
|
|
//将BC引入的文件写入订舱的附件
|
|
|
await SaveEDIFile(bookingOrder.Id, bookFilePath, new System.IO.FileInfo(bookFilePath).Name,
|
|
|
fileTypeCode, fileTypeName);
|
|
|
|
|
|
_logger.LogInformation("批次={no} id={id} 完成写入附件表 {filepath}", batchNo
|
|
|
, bookingOrder.Id, model.FileTempPath);
|
|
|
}
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "执行成功";
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = ex.Message;
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 单票BC更新订舱信息
|
|
|
/// <summary>
|
|
|
/// 单票BC更新订舱信息
|
|
|
/// </summary>
|
|
|
/// <param name="model">BC详情</param>
|
|
|
/// <param name="bookingOrder">订舱详情</param>
|
|
|
/// <param name="batchNo">批次号</param>
|
|
|
/// <param name="sortNo">顺序号</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
private async Task<TaskManageOrderResultDto> InnerBCUpdateBookingOrder(SingleBCDto model, BookingOrder bookingOrder,
|
|
|
string batchNo, int sortNo)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
result.bno = bookingOrder.MBLNO;
|
|
|
|
|
|
var oldBookingOrder = bookingOrder.Adapt<BookingOrder>();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace(result.bno))
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(bookingOrder.CUSTNO))
|
|
|
{
|
|
|
result.bno = $"订 {bookingOrder.CUSTNO}";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.bno = $"NO.{sortNo}";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//截单日期
|
|
|
if (model.ClosingDate.HasValue)
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 更新截单日期 原:{date1} 变更为 {date2}", batchNo, bookingOrder.Id,
|
|
|
bookingOrder.CLOSEDOCDATE, model.ClosingDate);
|
|
|
|
|
|
bookingOrder.CLOSEDOCDATE = model.ClosingDate;
|
|
|
}
|
|
|
//截VGM时间
|
|
|
if (model.VGMCutOffTime.HasValue)
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 更新截VGM日期 原:{date1} 变更为 {date2}", batchNo, bookingOrder.Id,
|
|
|
bookingOrder.CLOSEVGMDATE, model.VGMCutOffTime);
|
|
|
|
|
|
bookingOrder.CLOSEVGMDATE = model.VGMCutOffTime;
|
|
|
}
|
|
|
|
|
|
//截港日期
|
|
|
if (model.CYCutOffTime.HasValue)
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 更新截港日期 原:{date1} 变更为 {date2}", batchNo, bookingOrder.Id,
|
|
|
bookingOrder.CLOSINGDATE, model.CYCutOffTime);
|
|
|
|
|
|
bookingOrder.CLOSINGDATE = model.CYCutOffTime;
|
|
|
}
|
|
|
//开船日期
|
|
|
if (model.ETD.HasValue)
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 更新截港日期 原:{date1} 变更为 {date2}", batchNo, bookingOrder.Id,
|
|
|
bookingOrder.ETD, model.ETD);
|
|
|
|
|
|
bookingOrder.ETD = model.ETD;
|
|
|
}
|
|
|
|
|
|
//船名
|
|
|
if (!string.IsNullOrWhiteSpace(model.Vessel))
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 更新船名 原:{date1} 变更为 {date2}", batchNo, bookingOrder.Id,
|
|
|
bookingOrder.VESSEL, model.Vessel);
|
|
|
|
|
|
bookingOrder.VESSEL = model.Vessel;
|
|
|
}
|
|
|
|
|
|
//航次
|
|
|
if (!string.IsNullOrWhiteSpace(model.Voyage))
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 更新航次 原:{date1} 变更为 {date2}", batchNo, bookingOrder.Id,
|
|
|
bookingOrder.VOYNO, model.Voyage);
|
|
|
|
|
|
bookingOrder.VOYNO = model.Voyage;
|
|
|
}
|
|
|
|
|
|
//提单号
|
|
|
if (!string.IsNullOrWhiteSpace(model.BLNo))
|
|
|
{
|
|
|
_logger.LogInformation("批次={no} id={id} 更新提单号 原:{date1} 变更为 {date2}", batchNo, bookingOrder.Id,
|
|
|
bookingOrder.MBLNO, model.BLNo);
|
|
|
|
|
|
bookingOrder.MBLNO = model.BLNo;
|
|
|
}
|
|
|
|
|
|
bookingOrder.UpdatedTime = DateTime.Now;
|
|
|
bookingOrder.UpdatedUserId = UserManager.UserId;
|
|
|
bookingOrder.UpdatedUserName = UserManager.Name;
|
|
|
|
|
|
await _bookingOrderRepository.AsUpdateable(bookingOrder).UpdateColumns(it => new
|
|
|
{
|
|
|
it.UpdatedTime,
|
|
|
it.UpdatedUserId,
|
|
|
it.UpdatedUserName,
|
|
|
it.CLOSEDOCDATE,
|
|
|
it.CLOSEVGMDATE,
|
|
|
it.CLOSINGDATE,
|
|
|
it.ETD,
|
|
|
it.VESSEL,
|
|
|
it.VOYNO,
|
|
|
it.MBLNO
|
|
|
}).ExecuteCommandAsync();
|
|
|
var _bookingOrderService = _namedBookingOrderServiceProvider.GetService<ITransient>(nameof(BookingOrderService));
|
|
|
// 记录日志
|
|
|
await _bookingOrderService.SaveLog(bookingOrder, oldBookingOrder, "引入BC更新订舱信息");
|
|
|
|
|
|
_logger.LogInformation("批次={no} id={id} BC引入更新订舱完成", batchNo, bookingOrder.Id);
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "执行成功";
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = ex.Message;
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 批量BC更新订舱
|
|
|
/// <summary>
|
|
|
/// 批量BC更新订舱
|
|
|
/// </summary>
|
|
|
/// <param name="batchBCList">批量BC更新列表</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/BatchBCUpdate")]
|
|
|
public async Task<TaskManageOrderResultDto> BatchBCUpdate([FromBody] List<BatchBCDto> batchBCList)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
List<Task<TaskManageOrderResultDto>> taskList = new List<Task<TaskManageOrderResultDto>>();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var bcTaskList = batchBCList.Select(a => a.bcPKId).Distinct().ToList();
|
|
|
var bkOrderList = batchBCList.Select(a => a.bkOrderId.Value).Distinct().ToList();
|
|
|
|
|
|
var bklist = _bookingOrderRepository.AsQueryable()
|
|
|
.Where(a => bkOrderList.Contains(a.Id)).ToList();
|
|
|
|
|
|
var bclist = _taskBCInfoRepository.AsQueryable()
|
|
|
.Where(a => bcTaskList.Contains(a.PK_ID)).ToList();
|
|
|
|
|
|
if (bklist.Count != bkOrderList.Count)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
var noList = bklist.Select((a, idx) => new { no = idx + 1, id = a.Id }).ToList();
|
|
|
foreach (var bk in bklist)
|
|
|
{
|
|
|
var sortNo = noList.FirstOrDefault(a => a.id == bk.Id).no;
|
|
|
|
|
|
var currBC = batchBCList.Join(bclist, l => l.bcPKId, r => r.PK_ID, (l, r) =>
|
|
|
{
|
|
|
return r;
|
|
|
}).FirstOrDefault();
|
|
|
|
|
|
SingleBCDto singleBCDto = new SingleBCDto
|
|
|
{
|
|
|
BLNo = currBC.MBL_NO,
|
|
|
Vessel = currBC.VESSEL,
|
|
|
Voyage = currBC.VOYNO,
|
|
|
ETD = currBC.ETD,
|
|
|
CYCutOffTime = currBC.CY_CUTOFF_TIME,
|
|
|
VGMCutOffTime = currBC.VGM_CUTOFF_TIME,
|
|
|
ClosingDate = currBC.CUT_SINGLE_TIME
|
|
|
};
|
|
|
taskList.Add(Task.Run(() => InnerBCUpdateBookingOrder(singleBCDto, bk, batchNo, sortNo)));
|
|
|
}
|
|
|
|
|
|
Task.WaitAll(taskList.ToArray());
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = "批量执行成功";
|
|
|
|
|
|
var downResultList = taskList.Select(x => x.Result).ToList();
|
|
|
|
|
|
if (downResultList.Any(x => !x.succ))
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = "批量执行失败";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = downResultList.FirstOrDefault().msg;
|
|
|
}
|
|
|
|
|
|
result.ext = downResultList;
|
|
|
|
|
|
var succ = downResultList.Count(x => x.succ);
|
|
|
var fail = downResultList.Count(x => !x.succ);
|
|
|
|
|
|
if (succ > 0)
|
|
|
{
|
|
|
result.batchTotal = succ.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.batchTotal = "- ";
|
|
|
}
|
|
|
|
|
|
if (fail > 0)
|
|
|
{
|
|
|
result.batchTotal += "/" + fail.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.batchTotal += " -";
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"批量执行失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取订舱数据接口 备注 、 文件 、服务项目
|
|
|
/// </summary>
|
|
|
/// <param name="bookingId">订舱ID</param>
|
|
|
/// <returns>返回服务状态列表</returns>
|
|
|
[HttpGet("/BookingValueAdded/GetAllDataVNTWO")]
|
|
|
public async Task<BookingAttachedDataDto> GetAllDataVNTWO([FromQuery] long bookingId)
|
|
|
{
|
|
|
BookingAttachedDataDto resultDto = new BookingAttachedDataDto();
|
|
|
|
|
|
if (bookingId == 0)
|
|
|
{
|
|
|
throw Oops.Oh($"订舱ID不能为空");
|
|
|
}
|
|
|
|
|
|
var orderInfo = _bookingOrderRepository.AsQueryable().Filter(null, true).First(a => a.Id == bookingId);
|
|
|
|
|
|
//订舱备注列表
|
|
|
var remarklist = await _bookingRemarkRepository.AsQueryable().Where(u => u.PId == bookingId)
|
|
|
.ToListAsync();
|
|
|
|
|
|
resultDto.remark = remarklist;
|
|
|
|
|
|
//订舱附件列表
|
|
|
var filelist = await _bookingFileRepository.AsQueryable().Filter(null, true)
|
|
|
.Where(u => u.BookingId == bookingId).ToListAsync();
|
|
|
|
|
|
resultDto.file = filelist;
|
|
|
|
|
|
var projectList = await _serviceWorkFlowBaseService.GetEnableProjectList(orderInfo.TenantId.Value.ToString());
|
|
|
|
|
|
if (projectList != null && projectList.Count > 0)
|
|
|
{
|
|
|
//resultDto = BookingServiceItem
|
|
|
}
|
|
|
|
|
|
return resultDto;
|
|
|
}
|
|
|
|
|
|
#region 获取订舱数据接口 日志、状态日志
|
|
|
/// <summary>
|
|
|
/// 获取订舱数据接口 日志、状态日志
|
|
|
/// </summary>
|
|
|
/// <param name="bookingId">订舱ID</param>
|
|
|
/// <returns>返回日志详情</returns>
|
|
|
[HttpGet("/BookingValueAdded/GetAllLogDataVNTWO")]
|
|
|
public async Task<BookingLogDataDto> GetAllLogDataVNTWO([FromQuery] long bookingId)
|
|
|
{
|
|
|
BookingLogDataDto resultDto = new BookingLogDataDto();
|
|
|
|
|
|
var statusLogList = _statuslogRepository.AsQueryable().Filter(null, true)
|
|
|
.LeftJoin<BookingStatusLogDetail>((a, b) => a.Id == b.PId)
|
|
|
.Where((a, b) => a.BookingId == bookingId)
|
|
|
.Select((a, b) => new { Base = a, Detail = b })
|
|
|
.ToList();
|
|
|
|
|
|
if (statusLogList.Count > 0)
|
|
|
{
|
|
|
resultDto.statuslog = statusLogList.OrderByDescending(a => a.Base.OpTime)
|
|
|
.GroupBy(a => a.Base.Id)
|
|
|
.Select(a =>
|
|
|
{
|
|
|
var currList = a.ToList();
|
|
|
|
|
|
var baseDto = currList.FirstOrDefault().Base.Adapt<BookingStatusLogDto>();
|
|
|
|
|
|
if (currList.Any(b => b.Detail != null))
|
|
|
{
|
|
|
baseDto.detail = currList.Where(b => b.Detail != null)
|
|
|
.Select(b => b.Detail.Adapt<BookingStatusLogDetailDto>()).ToList();
|
|
|
}
|
|
|
|
|
|
return baseDto;
|
|
|
}).ToList();
|
|
|
}
|
|
|
|
|
|
var logList = _bookinglogRepository.AsQueryable()
|
|
|
.LeftJoin<BookingLogDetail>((a, b) => a.Id == b.PId)
|
|
|
.Where((a, b) => a.BookingId == bookingId)
|
|
|
.Select((a, b) => new { Base = a, Detail = b })
|
|
|
.ToList();
|
|
|
|
|
|
if (logList.Count > 0)
|
|
|
{
|
|
|
resultDto.log = logList.GroupBy(a => a.Base.Id)
|
|
|
.Select(a =>
|
|
|
{
|
|
|
var currList = a.ToList();
|
|
|
|
|
|
var baseDto = currList.FirstOrDefault().Base.Adapt<BookingLogDto>();
|
|
|
|
|
|
if (currList.Any(b => b.Detail != null))
|
|
|
{
|
|
|
baseDto.details = currList.Where(b => b.Detail != null)
|
|
|
.Select(b => b.Detail).ToList();
|
|
|
}
|
|
|
|
|
|
return baseDto;
|
|
|
}).ToList();
|
|
|
}
|
|
|
|
|
|
return resultDto;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 保存服务项目
|
|
|
/// <summary>
|
|
|
/// 保存服务项目
|
|
|
/// </summary>
|
|
|
/// <param name="model">修改服务项目详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/SaveServiceProject")]
|
|
|
public async Task<TaskManageOrderResultDto> SaveServiceProject([FromBody] ModifyServiceProjectDto model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true)
|
|
|
.First(a => a.Id == model.BookingId);
|
|
|
|
|
|
if (bookingOrder == null)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求保存服务项目 modifyjson={msg}", batchNo, JSON.Serialize(model));
|
|
|
|
|
|
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 = model.BookingId.ToString(),
|
|
|
BusiSystemCode = "BOOKING_ORDER",
|
|
|
MBlNo = bookingOrder.MBLNO,
|
|
|
VesselVoyno = $"{bookingOrder.VESSEL}/{bookingOrder.VOYNO}",
|
|
|
OrderNo = bookingOrder.BSNO,
|
|
|
PushType = TrackingPushTypeEnum.Project,
|
|
|
OperTenantId = bookingOrder.TenantId.Value,
|
|
|
OperTenantName = bookingOrder.TenantName,
|
|
|
OpertType = TrackingOperTypeEnum.MANUAL,
|
|
|
OperUserId = UserManager.UserId.ToString(),
|
|
|
OperUserName = UserManager.Name,
|
|
|
SourceType = TrackingSourceTypeEnum.MANUAL,
|
|
|
ProjectList = model.ProjectCodes.Select(a => new TrackingMessageMainProjectInfo
|
|
|
{
|
|
|
ServiceProjectCode = a,
|
|
|
}).ToList()
|
|
|
}
|
|
|
};
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 推送保存服务项目 msg={msg}", batchNo, JSON.Serialize(msgInfo));
|
|
|
|
|
|
var rlt = await _serviceWorkFlowManageService.PushStatus(msgInfo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg} result={rlt}", batchNo, timeDiff, (rlt.succ ? "成功" : "失败")
|
|
|
, JSON.Serialize(rlt));
|
|
|
|
|
|
if (!rlt.succ)
|
|
|
{
|
|
|
result = rlt;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = "保存成功";
|
|
|
}
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"服务项目保存失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 取消服务项目
|
|
|
/// <summary>
|
|
|
/// 取消服务项目
|
|
|
/// </summary>
|
|
|
/// <param name="model">修改服务项目详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/CancelServiceProject")]
|
|
|
public async Task<TaskManageOrderResultDto> CancelServiceProject([FromBody] ModifyServiceProjectDto model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true)
|
|
|
.First(a => a.Id == model.BookingId);
|
|
|
|
|
|
if (bookingOrder == null)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求保存服务项目 modifyjson={msg}", batchNo, JSON.Serialize(model));
|
|
|
|
|
|
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 = model.BookingId.ToString(),
|
|
|
BusiSystemCode = "BOOKING_ORDER",
|
|
|
MBlNo = bookingOrder.MBLNO,
|
|
|
VesselVoyno = $"{bookingOrder.VESSEL}/{bookingOrder.VOYNO}",
|
|
|
OrderNo = bookingOrder.BSNO,
|
|
|
PushType = TrackingPushTypeEnum.Project,
|
|
|
OperTenantId = bookingOrder.TenantId.Value,
|
|
|
OperTenantName = bookingOrder.TenantName,
|
|
|
OpertType = TrackingOperTypeEnum.MANUAL,
|
|
|
OperUserId = UserManager.UserId.ToString(),
|
|
|
OperUserName = UserManager.Name,
|
|
|
SourceType = TrackingSourceTypeEnum.MANUAL,
|
|
|
ProjectList = model.ProjectCodes.Select(a => new TrackingMessageMainProjectInfo
|
|
|
{
|
|
|
ServiceProjectCode = a,
|
|
|
}).ToList()
|
|
|
}
|
|
|
};
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 推送取消服务项目 msg={msg}", batchNo, JSON.Serialize(msgInfo));
|
|
|
|
|
|
var rlt = await _serviceWorkFlowManageService.CancelStatus(msgInfo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg} result={rlt}", batchNo, timeDiff, (rlt.succ ? "成功" : "失败")
|
|
|
, JSON.Serialize(rlt));
|
|
|
|
|
|
if (!rlt.succ)
|
|
|
{
|
|
|
result = rlt;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = "取消成功";
|
|
|
}
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"服务项目取消失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 保存服务状态
|
|
|
/// </summary>
|
|
|
/// <param name="model">修改服务状态详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/SaveServiceStatus")]
|
|
|
public async Task<TaskManageOrderResultDto> SaveServiceStatus([FromBody] ModifyServiceProjectStatusDto model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true)
|
|
|
.First(a => a.Id == model.BookingId);
|
|
|
|
|
|
if (bookingOrder == null)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求保存服务项目 modifyjson={msg}", batchNo, JSON.Serialize(model));
|
|
|
|
|
|
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 = model.BookingId.ToString(),
|
|
|
BusiSystemCode = "BOOKING_ORDER",
|
|
|
MBlNo = bookingOrder.MBLNO,
|
|
|
VesselVoyno = $"{bookingOrder.VESSEL}/{bookingOrder.VOYNO}",
|
|
|
OrderNo = bookingOrder.CUSTNO,
|
|
|
PushType = TrackingPushTypeEnum.Status,
|
|
|
OperTenantId = bookingOrder.TenantId.Value,
|
|
|
OperTenantName = bookingOrder.TenantName,
|
|
|
OpertType = TrackingOperTypeEnum.MANUAL,
|
|
|
OperUserId = UserManager.UserId.ToString(),
|
|
|
OperUserName = UserManager.Name,
|
|
|
SourceType = model.SourceType,
|
|
|
StatusList = model.StatusCodes.Select(a => new TrackingMessageMainStatusInfo
|
|
|
{
|
|
|
StatusCode = a.StatusCode,
|
|
|
StatusDate = a.SetActDate,
|
|
|
StatusVal = a.SetActVal,
|
|
|
Remark = a.ActRemark
|
|
|
}).ToList()
|
|
|
}
|
|
|
};
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 推送保存服务项目 msg={msg}", batchNo, JSON.Serialize(msgInfo));
|
|
|
|
|
|
var rlt = await _serviceWorkFlowManageService.PushStatus(msgInfo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg} result={rlt}", batchNo, timeDiff, (rlt.succ ? "成功" : "失败")
|
|
|
, JSON.Serialize(rlt));
|
|
|
|
|
|
if (!rlt.succ)
|
|
|
{
|
|
|
result = rlt;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = "推送成功";
|
|
|
var _bookingOrderService = _namedBookingOrderServiceProvider.GetService<ITransient>(nameof(BookingOrderService));
|
|
|
await _bookingOrderService.SetBookingGoodsStatus(bookingOrder.Id, true, "手动更新货物状态");
|
|
|
}
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"服务项目状态推送失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 取消服务状态
|
|
|
/// </summary>
|
|
|
/// <param name="model">修改服务状态详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/CancelServiceStatus")]
|
|
|
public async Task<TaskManageOrderResultDto> CancelServiceStatus([FromBody] ModifyServiceProjectStatusDto model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true)
|
|
|
.First(a => a.Id == model.BookingId);
|
|
|
|
|
|
if (bookingOrder == null)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求保存服务项目 modifyjson={msg}", batchNo, JSON.Serialize(model));
|
|
|
|
|
|
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 = model.BookingId.ToString(),
|
|
|
BusiSystemCode = "BOOKING_ORDER",
|
|
|
MBlNo = bookingOrder.MBLNO,
|
|
|
VesselVoyno = $"{bookingOrder.VESSEL}/{bookingOrder.VOYNO}",
|
|
|
OrderNo = bookingOrder.BSNO,
|
|
|
PushType = TrackingPushTypeEnum.Status,
|
|
|
OperTenantId = bookingOrder.TenantId.Value,
|
|
|
OperTenantName = bookingOrder.TenantName,
|
|
|
OpertType = TrackingOperTypeEnum.MANUAL,
|
|
|
OperUserId = UserManager.UserId.ToString(),
|
|
|
OperUserName = UserManager.Name,
|
|
|
SourceType = model.SourceType,
|
|
|
StatusList = model.StatusCodes.Select(a => new TrackingMessageMainStatusInfo
|
|
|
{
|
|
|
StatusCode = a.StatusCode,
|
|
|
StatusDate = a.SetActDate,
|
|
|
StatusVal = a.SetActVal,
|
|
|
Remark = a.ActRemark
|
|
|
}).ToList()
|
|
|
}
|
|
|
};
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 推送保存服务项目 msg={msg}", batchNo, JSON.Serialize(msgInfo));
|
|
|
|
|
|
var rlt = await _serviceWorkFlowManageService.CancelStatus(msgInfo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} 请求完成,耗时:{timeDiff}ms. 结果{msg} result={rlt}", batchNo, timeDiff, (rlt.succ ? "成功" : "失败")
|
|
|
, JSON.Serialize(rlt));
|
|
|
|
|
|
if (!rlt.succ)
|
|
|
{
|
|
|
result = rlt;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = "推送成功";
|
|
|
var _bookingOrderService = _namedBookingOrderServiceProvider.GetService<ITransient>(nameof(BookingOrderService));
|
|
|
await _bookingOrderService.SetBookingGoodsStatus(bookingOrder.Id, true, "手动取消货物状态");
|
|
|
}
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"服务项目状态推送失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
#region 获取服务项目列表
|
|
|
/// <summary>
|
|
|
/// 获取服务项目列表
|
|
|
/// </summary>
|
|
|
/// <param name="model">查询服务项目和状态详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/GetServiceProjectList")]
|
|
|
public async Task<TaskManageOrderResultDto> GetServiceProjectList([FromBody] QueryServiceProjectWithStatus model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true)
|
|
|
.First(a => a.Id == model.BookingId);
|
|
|
|
|
|
if (bookingOrder == null)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
QueryServiceProjectWithStatus queryInfo = new QueryServiceProjectWithStatus
|
|
|
{
|
|
|
BookingId = model.BookingId,
|
|
|
QueryType = TrackingQueryTypeEnum.QUERY_SERVICE_PROJECT,
|
|
|
TenantId = bookingOrder.TenantId.Value
|
|
|
};
|
|
|
|
|
|
result = await _serviceWorkFlowManageService.GetEnableProjectList(queryInfo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} id={id} 单票请求服务项目结果 耗时:{timeDiff}ms. ", batchNo, model.BookingId, timeDiff);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"获取服务项目列表失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取服务项目下的状态列表
|
|
|
/// </summary>
|
|
|
/// <param name="model">查询服务项目和状态详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/GetServiceStatusList")]
|
|
|
public async Task<TaskManageOrderResultDto> GetServiceStatusList([FromBody] QueryServiceProjectWithStatus model)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
//查询所有服务服务项目和状态时,需要先获取订舱详情
|
|
|
if (model.QueryType == TrackingQueryTypeEnum.QUERY_SERVICE_ALL)
|
|
|
{
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
var bookingOrder = _bookingOrderRepository.AsQueryable().Filter(null, true)
|
|
|
.First(a => a.Id == model.BookingId);
|
|
|
|
|
|
if (bookingOrder == null)
|
|
|
throw Oops.Oh($"订舱信息获取失败,订舱信息不存在或已作废");
|
|
|
|
|
|
QueryServiceProjectWithStatus queryInfo = new QueryServiceProjectWithStatus
|
|
|
{
|
|
|
BookingId = model.BookingId,
|
|
|
QueryType = TrackingQueryTypeEnum.QUERY_SERVICE_PROJECT,
|
|
|
TenantId = bookingOrder.TenantId.Value
|
|
|
};
|
|
|
|
|
|
result = await _serviceWorkFlowManageService.GetEnableStatusListByBusiness(queryInfo);
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("批次={no} id={id} 单票请求服务状态结果 耗时:{timeDiff}ms. ", batchNo, model.BookingId, timeDiff);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (model.ProjectCodes == null || (model.ProjectCodes != null && model.ProjectCodes.Length == 0))
|
|
|
throw Oops.Oh($"服务项目代码不能为空");
|
|
|
|
|
|
model.TenantId = UserManager.TENANT_ID;
|
|
|
result = await _serviceWorkFlowManageService.GetEnableStatusListByProject(model);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"获取服务项目下的状态列表失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
#region 推送东胜同步
|
|
|
/// <summary>
|
|
|
/// 推送东胜同步
|
|
|
/// </summary>
|
|
|
/// <param name="ids">订舱主键组</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
[HttpPost("/BookingValueAdded/SinglePushBKOrderSyncDS")]
|
|
|
public async Task<TaskManageOrderResultDto> SinglePushBKOrderSyncDS([FromBody] long[] ids)
|
|
|
{
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
string batchNo = IDGen.NextID().ToString();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var _bookingOrderService = _namedBookingOrderServiceProvider.GetService<ITransient>(nameof(BookingOrderService));
|
|
|
var rlt = await _bookingOrderService.SendBookingOrder(ids);
|
|
|
|
|
|
if (rlt != null)
|
|
|
{
|
|
|
result.succ = true;
|
|
|
result.msg = "同步完成";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = "同步失败";
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"推送东胜同步失败,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 获取订舱对应的集装箱VGM回执详情
|
|
|
/// <summary>
|
|
|
/// 获取订舱对应的集装箱VGM回执详情
|
|
|
/// </summary>
|
|
|
/// <param name="id">订舱ID</param>
|
|
|
/// <returns>返回VGM明细</returns>
|
|
|
[HttpGet("/BookingValueAdded/GetBookingVGMResult")]
|
|
|
public async Task<List<BookingCtnVGMDto>> GetBookingVGMResult(long id)
|
|
|
{
|
|
|
List<BookingCtnVGMDto> list = new List<BookingCtnVGMDto>();
|
|
|
|
|
|
if (id < 1)
|
|
|
throw Oops.Oh($"订舱ID为空");
|
|
|
|
|
|
var vgmList = _bookingCtnVGMRepository.AsQueryable().Where(t => t.BILLID == id).ToList();
|
|
|
|
|
|
if (vgmList.Count > 0)
|
|
|
list = vgmList.Select(t => new BookingCtnVGMDto
|
|
|
{
|
|
|
id = t.Id,
|
|
|
cntrNo = t.CNTRNO,
|
|
|
vgmWeight = t.VGM_WEIGHT,
|
|
|
vgmWeightMethod = t.VGM_METHOD,
|
|
|
vgmWeightUnit = t.VGM_WEIGHT_UNIT,
|
|
|
recvDate = t.REC_TIME,
|
|
|
isMatch = t.IS_MATCH,
|
|
|
isMissing = t.IS_MISSING,
|
|
|
submissionDeadLine = t.SUBMISSION_DEADLINE
|
|
|
}).ToList();
|
|
|
|
|
|
return list;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 单票正本下载
|
|
|
/// <paramref name="downloadType">1=正本下载 2=副本下载</paramref>
|
|
|
/// </summary>
|
|
|
[HttpGet("/BookingValueAdded/DownloadOriginal")]
|
|
|
public async Task<TaskManageOrderResultDto> DownloadOriginal(long id, bool? isCheck, int downloadType = 1)
|
|
|
{
|
|
|
string fileTypeCode = downloadType switch
|
|
|
{
|
|
|
1 => "zhengben",
|
|
|
2 => "fuben",
|
|
|
_ => throw new NotImplementedException()
|
|
|
};
|
|
|
string fileTypeName = downloadType switch
|
|
|
{
|
|
|
1 => "正本",
|
|
|
2 => "副本",
|
|
|
_ => throw new NotImplementedException()
|
|
|
};
|
|
|
|
|
|
TaskManageOrderResultDto result = new TaskManageOrderResultDto();
|
|
|
|
|
|
if (isCheck == true)
|
|
|
{
|
|
|
if (await _bookingFileRepository.IsExistsAsync(x => x.BookingId == id && x.TypeCode == fileTypeCode))
|
|
|
{
|
|
|
result.status = -1;
|
|
|
result.succ = false;
|
|
|
result.msg = "文件已存在";
|
|
|
return result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
try
|
|
|
{
|
|
|
if (id <= 0)
|
|
|
throw Oops.Oh($"订舱ID为空");
|
|
|
|
|
|
var order = await _bookingOrderRepository.AsQueryable().FirstAsync(a => a.Id == id);
|
|
|
|
|
|
if (order == null)
|
|
|
throw Oops.Oh($"订舱信息获取失败(订舱信息不存在或已作废)");
|
|
|
|
|
|
|
|
|
|
|
|
result.bno = order.MBLNO;
|
|
|
|
|
|
var allSysConfig = _cache.GetAllSysConfig().Result;
|
|
|
var url = allSysConfig.FirstOrDefault(x => x.Code == "DraftDownloadServiceUrl")?.Value;
|
|
|
var key = allSysConfig.FirstOrDefault(x => x.Code == "DraftDownloadServiceKey")?.Value;
|
|
|
var token = allSysConfig.FirstOrDefault(x => x.Code == "DraftDownloadServiceToken")?.Value;
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(url))
|
|
|
{
|
|
|
throw Oops.Bah("单据下载服务接口地址未配置,请联系管理员");
|
|
|
}
|
|
|
if (string.IsNullOrWhiteSpace(key))
|
|
|
{
|
|
|
throw Oops.Bah("单据下载服务接口Key未配置,请联系管理员");
|
|
|
}
|
|
|
if (string.IsNullOrWhiteSpace(token))
|
|
|
{
|
|
|
throw Oops.Bah("单据下载服务接口Token未配置,请联系管理员");
|
|
|
}
|
|
|
|
|
|
var webAccount = _webAccountConfigService.GetAccountConfig("MSKWeb", UserManager.UserId).Result;
|
|
|
if (webAccount == null)
|
|
|
{
|
|
|
throw Oops.Bah("未配置网站账户,类型:MSKWeb");
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(order.ISSUETYPE))
|
|
|
{
|
|
|
throw Oops.Bah("签单方式为空");
|
|
|
}
|
|
|
if (string.IsNullOrWhiteSpace(order.CARRIERID))
|
|
|
{
|
|
|
throw Oops.Bah("船公司为空");
|
|
|
}
|
|
|
|
|
|
var mappingCarrier = _cache.GetAllMappingCarrier().Result;
|
|
|
var mappingIssueType = _cache.GetAllMappingIssueType().Result;
|
|
|
|
|
|
// 判断船公司是否符合条件
|
|
|
string carrierId = mappingCarrier.FirstOrDefault(x => x.Module == "ORIGINAL_DOWN_RT" && x.Code == order.CARRIERID)?.MapCode;
|
|
|
carrierId = (carrierId ?? order.CARRIERID).ToUpper();
|
|
|
if (carrierId != "MSK")
|
|
|
{
|
|
|
throw Oops.Bah($"船公司=[{order.CARRIER}]暂不支持{fileTypeName}下载");
|
|
|
}
|
|
|
|
|
|
// 判断签单方式是否符合条件
|
|
|
string issueType = mappingIssueType.FirstOrDefault(x => x.Module == "ORIGINAL_DOWN_RT" && x.Code == order.ISSUETYPE)?.MapCode;
|
|
|
issueType = issueType ?? order.ISSUETYPE;
|
|
|
if (!issueType.Equals("original", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
throw Oops.Bah($"此单签单方式非[正本],无法下载");
|
|
|
}
|
|
|
|
|
|
// 实时下载接口
|
|
|
url += downloadType switch
|
|
|
{
|
|
|
1 => "/documents_server/api/bill_lading/v1/download_realtime",
|
|
|
2 => "/documents_server/api/copy/v1/download_realtime",
|
|
|
_ => throw new NotImplementedException()
|
|
|
};
|
|
|
var body = new
|
|
|
{
|
|
|
web_code = carrierId,
|
|
|
web_user = webAccount.Account,
|
|
|
web_pwd = webAccount.Password,
|
|
|
bill_no = order.MBLNO,
|
|
|
consumer_key = key,
|
|
|
iscontent = false,
|
|
|
};
|
|
|
var header = new Dictionary<string, object>()
|
|
|
{
|
|
|
{ "Token",token }, { "Content-Type", "application/json" }
|
|
|
};
|
|
|
_logger.LogInformation("请求fileTypeName={fileTypeName}下载接口开始,mblno={mblno}, url={url}, body={body}", fileTypeName, order.MBLNO, url, body);
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
var rtn = await url.OnClientCreating(client =>
|
|
|
{
|
|
|
client.Timeout = TimeSpan.FromMinutes(3); // 设置超时时间 3分钟
|
|
|
}).SetBody(body).SetHeaders(header).PostAsStringAsync();
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
_logger.LogInformation("请求fileTypeName={fileTypeName}下载接口结束,mblno={mblno}, rtn={rtn}, 耗时:{timeDiff}ms", fileTypeName, order.MBLNO, rtn, timeDiff);
|
|
|
|
|
|
var jsonRtn = JObject.Parse(rtn);
|
|
|
if (jsonRtn.GetIntValue("status") == 1)
|
|
|
{
|
|
|
_logger.LogInformation("请求fileTypeName={fileTypeName}下载接口成功,转存本地,mblno={mblno}", fileTypeName, order.MBLNO);
|
|
|
|
|
|
var data = jsonRtn.GetJObjectValue("data");
|
|
|
|
|
|
// 远程文件路径
|
|
|
var remoteFilePath = data.GetStringValue("proxy_path");
|
|
|
// 真实文件名
|
|
|
var reallyFileName = data.GetStringValue("file_name");
|
|
|
|
|
|
// 读取文件保存配置
|
|
|
var fileCfg = App.GetOptions<BookingAttachOptions>();
|
|
|
|
|
|
// 实时下载接口
|
|
|
string floderName = downloadType switch
|
|
|
{
|
|
|
1 => "originalfiles",
|
|
|
2 => "copyfiles",
|
|
|
_ => throw new NotImplementedException()
|
|
|
};
|
|
|
|
|
|
string relativePath = $"{fileCfg.relativePath}\\{floderName}\\{order.Id}";
|
|
|
string relativeDic = $"{(!string.IsNullOrWhiteSpace(fileCfg.basePath) ? fileCfg.basePath : App.WebHostEnvironment.WebRootPath)}\\{relativePath}";
|
|
|
|
|
|
string fileSavePath = $"{relativeDic}\\{new System.IO.FileInfo(remoteFilePath).Name}";
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
{
|
|
|
relativePath = relativePath.Replace("\\", "/");
|
|
|
relativeDic = relativeDic.Replace("\\", "/");
|
|
|
|
|
|
fileSavePath = fileSavePath.Replace("\\", "/");
|
|
|
}
|
|
|
|
|
|
_logger.LogInformation("mblno={mblno}, 生成文件保存路径完成 路由={relativeDic} 服务器系统={system}", order.MBLNO, relativeDic, RuntimeInformation.OSDescription);
|
|
|
//预先创建目录
|
|
|
if (!Directory.Exists(relativeDic))
|
|
|
{
|
|
|
Directory.CreateDirectory(relativeDic);
|
|
|
}
|
|
|
|
|
|
var bcStream = await remoteFilePath.GetAsStreamAsync();
|
|
|
|
|
|
using (var fileStream = File.Create(fileSavePath))
|
|
|
{
|
|
|
await bcStream.CopyToAsync(fileStream);
|
|
|
}
|
|
|
|
|
|
_logger.LogInformation("mblno={mblno} 完成文件保存 filepath={path}", order.MBLNO, fileSavePath);
|
|
|
|
|
|
string bookFilePath = string.Empty;
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
{
|
|
|
bookFilePath = System.Text.RegularExpressions.Regex.Match(fileSavePath, relativePath.Replace("/", "\\/") + ".*").Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
bookFilePath = System.Text.RegularExpressions.Regex.Match(fileSavePath, relativePath.Replace("\\", "\\\\") + ".*").Value;
|
|
|
}
|
|
|
|
|
|
result.succ = true;
|
|
|
result.msg = $"{fileTypeName}下载成功";
|
|
|
|
|
|
await _bookingFileRepository.DeleteAsync(x => x.TypeCode == fileTypeCode && x.BookingId == order.Id);
|
|
|
await SaveEDIFile(order.Id, bookFilePath, reallyFileName, fileTypeCode, fileTypeName);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var msg = jsonRtn.GetStringValue("message")?.Replace("爬虫", "");
|
|
|
_logger.LogInformation("请求fileTypeName={fileTypeName}下载接口失败,mblno={mblno}, 服务返回:{msg}", fileTypeName, order.MBLNO, msg);
|
|
|
throw Oops.Bah(msg);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.status = -2;
|
|
|
result.msg = $"{fileTypeName}下载失败,{ex.Message}";
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public class DateTimeJsonConverter : System.Text.Json.Serialization.JsonConverter<Nullable<DateTime>>
|
|
|
{
|
|
|
private readonly string _dateFormatString;
|
|
|
public DateTimeJsonConverter()
|
|
|
{
|
|
|
_dateFormatString = "yyyy-MM-dd HH:mm:ss";
|
|
|
}
|
|
|
|
|
|
public DateTimeJsonConverter(string dateFormatString)
|
|
|
{
|
|
|
_dateFormatString = dateFormatString;
|
|
|
}
|
|
|
|
|
|
public override Nullable<DateTime> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
|
|
{
|
|
|
DateTime currDate = DateTime.MinValue;
|
|
|
if (DateTime.TryParse(reader.GetString(), out currDate))
|
|
|
return currDate;
|
|
|
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
public override void Write(Utf8JsonWriter writer, Nullable<DateTime> value, JsonSerializerOptions options)
|
|
|
{
|
|
|
if (value.HasValue)
|
|
|
writer.WriteStringValue(value.Value.ToUniversalTime().ToString(_dateFormatString));
|
|
|
else
|
|
|
writer.WriteNullValue();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|