|
|
using DS.Module.Core;
|
|
|
using DS.Module.SqlSugar;
|
|
|
using DS.Module.UserModule;
|
|
|
using DS.WMS.Core.Code.Dtos;
|
|
|
using DS.WMS.Core.Code.Entity;
|
|
|
using DS.WMS.Core.Op.Dtos;
|
|
|
using DS.WMS.Core.Sys.Entity;
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
using NPOI.SS.Formula.Functions;
|
|
|
using SqlSugar;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Threading.Tasks;
|
|
|
using DS.WMS.Core.Code.Interface;
|
|
|
using Newtonsoft.Json;
|
|
|
using DS.Module.Core.Helpers;
|
|
|
using NLog;
|
|
|
using DS.WMS.Core.Map.Interface;
|
|
|
using DS.Module.Core.Extensions;
|
|
|
using DS.WMS.Core.Sys.Dtos;
|
|
|
using DS.Module.RedisModule;
|
|
|
using System.Text.RegularExpressions;
|
|
|
using DS.WMS.Core.Sys.Interface;
|
|
|
using DS.WMS.Core.Sys.Method;
|
|
|
using DS.WMS.Core.Op.Entity;
|
|
|
using Mapster;
|
|
|
using System.Text.Json.Nodes;
|
|
|
using LanguageExt.Pipes;
|
|
|
using DS.WMS.Core.Op.Interface;
|
|
|
using DS.WMS.Core.Map.Method;
|
|
|
using Microsoft.Owin.Security.Provider;
|
|
|
using LanguageExt;
|
|
|
using DS.Module.Core.Data;
|
|
|
using DS.WMS.Core.TaskPlat.Dtos;
|
|
|
using Fasterflect;
|
|
|
using AutoMapper;
|
|
|
using System.Reflection;
|
|
|
using DS.WMS.Core.Code.Method;
|
|
|
using Microsoft.AspNetCore.Identity;
|
|
|
using Masuit.Tools.Systems;
|
|
|
using Amazon.Runtime.Internal.Util;
|
|
|
using DS.WMS.Core.Op.EDI;
|
|
|
using HtmlAgilityPack;
|
|
|
using MySqlConnector.Logging;
|
|
|
|
|
|
namespace DS.WMS.Core.Op.Method
|
|
|
{
|
|
|
public class SpaceBookingMSKAPIService : ISpaceBookingMSKAPIService
|
|
|
{
|
|
|
private readonly IServiceProvider _serviceProvider;
|
|
|
private readonly ISqlSugarClient db;
|
|
|
private readonly IUser user;
|
|
|
private readonly ISaasDbService saasService;
|
|
|
private readonly ICodeThirdPartyService codeThirdPartyService;
|
|
|
private readonly string mskAPIUserKey;
|
|
|
private readonly string mskAPIUserSecret;
|
|
|
private readonly string mskAPIEnvironment;
|
|
|
private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger();
|
|
|
private readonly IMappingCtnService mappingCtnService;
|
|
|
private readonly IRedisService redisService;
|
|
|
private readonly IConfigService configService;
|
|
|
private readonly IUserEmailService _userEmailService;
|
|
|
|
|
|
|
|
|
const string CONST_MSK_API_Poing2P_SECD_URL = "MSKApiSailingSchedulePoint2Point";
|
|
|
const string CONST_MSK_API_BOOKING_URL = "MSKApiBooking";
|
|
|
const string CONST_MSK_API_LOCATION_URL = "MSKApilocation";
|
|
|
const string CONST_MSK_API_COMMODITY_URL = "MSKApiCommodity";
|
|
|
|
|
|
const string CONST_MSK_API_MAPPING_MODULE = "BOOK_MSK_API";
|
|
|
const string CONST_MSK_API_CHANNEL_SHOW = "BOOKING_CHANNEL_SELECT_SHOW";
|
|
|
|
|
|
const long CONST_ADMIN_TENANTID = 1288018625843826688;
|
|
|
|
|
|
public SpaceBookingMSKAPIService(IServiceProvider serviceProvider)
|
|
|
{
|
|
|
_serviceProvider = serviceProvider;
|
|
|
db = _serviceProvider.GetRequiredService<ISqlSugarClient>();
|
|
|
user = _serviceProvider.GetRequiredService<IUser>();
|
|
|
saasService = _serviceProvider.GetRequiredService<ISaasDbService>();
|
|
|
codeThirdPartyService = _serviceProvider.GetRequiredService<ICodeThirdPartyService>();
|
|
|
mappingCtnService = _serviceProvider.GetRequiredService<IMappingCtnService>();
|
|
|
redisService = _serviceProvider.GetRequiredService<IRedisService>();
|
|
|
configService = _serviceProvider.GetRequiredService<IConfigService>();
|
|
|
_userEmailService = _serviceProvider.GetRequiredService<IUserEmailService>();
|
|
|
|
|
|
mskAPIUserKey = AppSetting.app(new string[] { "MSKAPIService", "UserKey" });
|
|
|
mskAPIUserSecret = AppSetting.app(new string[] { "MSKAPIService", "UserSecret" });
|
|
|
mskAPIEnvironment = AppSetting.app(new string[] { "MSKAPIService", "Environment" });
|
|
|
}
|
|
|
|
|
|
#region 检索海运船期详情
|
|
|
/// <summary>
|
|
|
/// 检索海运船期详情
|
|
|
/// </summary>
|
|
|
/// <param name="model">请求船期详情</param>
|
|
|
/// <returns>返回船期结果</returns>
|
|
|
public async Task<DataResult<List<SearchShipSailingScheduleResultDto>>> SearchShipSailingSchedule(QueryShipSailingScheduleDto model)
|
|
|
{
|
|
|
List<SearchShipSailingScheduleResultDto> list = new List<SearchShipSailingScheduleResultDto>();
|
|
|
|
|
|
/*
|
|
|
MSKApiSailingSchedulePoint2Point
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
//始发地不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.collectionOriginCityName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOriginCityNameNull)));
|
|
|
|
|
|
//目的地不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.deliveryDestinationCityName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIDestCityNameNull)));
|
|
|
|
|
|
//服务船公司不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.vesselOperatorCarrierCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIVesselCarrierCodeNull)));
|
|
|
|
|
|
//船公司代码不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.carrierCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICarrierCodeNull)));
|
|
|
|
|
|
//预计离港日期不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.startDate))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIETDNull)));
|
|
|
|
|
|
DateTime etd = DateTime.MinValue;
|
|
|
|
|
|
//预计离港日期格式错误
|
|
|
if (!DateTime.TryParse(model.startDate, out etd))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIETDFormatError)));
|
|
|
|
|
|
string queryUrl = string.Empty;
|
|
|
|
|
|
if (model.carrierCode.Equals("MSK", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
queryUrl = configService.GetConfig(CONST_MSK_API_Poing2P_SECD_URL, long.Parse(user.TenantId), false).GetAwaiter().GetResult()?.Data?.Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchShipNotSupport)), model.carrierCode));
|
|
|
}
|
|
|
|
|
|
//未配置查询船期请求接口地址,请联系管理员
|
|
|
if (string.IsNullOrWhiteSpace(queryUrl))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchShipNoConfig)));
|
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
var webAccountConfig = codeThirdPartyService.GetCodeThirdPartyInfoWithCompany("MSKApi").GetAwaiter().GetResult()?.Data;
|
|
|
|
|
|
//未配置第三方账户个人账户(MSKApi)
|
|
|
if (webAccountConfig == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIThirdPartyNull)));
|
|
|
|
|
|
MSKAPISearchPoint2PointScheduleDto queryInfo = new MSKAPISearchPoint2PointScheduleDto
|
|
|
{
|
|
|
userKey = mskAPIUserKey,
|
|
|
userSecret = mskAPIUserSecret,
|
|
|
operatingEnvironment = mskAPIEnvironment,
|
|
|
mskAppKey = webAccountConfig.AppKey,
|
|
|
cargoType = model.cargoType,
|
|
|
exportServiceMode = model.exportServiceMode,
|
|
|
importServiceMode = model.importServiceMode,
|
|
|
vesselOperatorCarrierCode = model.vesselOperatorCarrierCode,
|
|
|
startDate = etd.ToString("yyyy-MM-dd"),
|
|
|
startDateType = "D",
|
|
|
};
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(model.carrierCollectionOriginGeoID) && !string.IsNullOrWhiteSpace(model.carrierDeliveryDestinationGeoID))
|
|
|
{
|
|
|
queryInfo.carrierCollectionOriginGeoID = model.carrierCollectionOriginGeoID;
|
|
|
queryInfo.carrierDeliveryDestinationGeoID = model.carrierDeliveryDestinationGeoID;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
queryInfo.collectionOriginCityName = model.collectionOriginCityName;
|
|
|
queryInfo.collectionOriginCountryCode = model.collectionOriginCountryCode;
|
|
|
queryInfo.deliveryDestinationCityName = model.deliveryDestinationCityName;
|
|
|
queryInfo.deliveryDestinationCountryCode = model.deliveryDestinationCountryCode;
|
|
|
}
|
|
|
|
|
|
//有时候船期需要带上箱型检索
|
|
|
if (!string.IsNullOrWhiteSpace(model.ISOEquipmentCode))
|
|
|
{
|
|
|
//这里需要翻译一下箱型
|
|
|
//var ctnCodeMappingList = _cache.GetAllMappingCtn().GetAwaiter().GetResult().ToList();
|
|
|
|
|
|
//if (ctnCodeMappingList.Count > 0)
|
|
|
//ctnCodeMappingList = ctnCodeMappingList.Where(x => x.CarrierCode == "MSK" && x.Module == "BOOK_MSK_API").ToList();
|
|
|
|
|
|
//var ctnMapping = ctnCodeMappingList.FirstOrDefault(t => t.Code.Equals(model.ISOEquipmentCode));
|
|
|
var ctnMapping = mappingCtnService.QueryMappingCtn(model.carrierId, "BOOK_MSK_API", model.ISOEquipmentCode).GetAwaiter().GetResult().Data;
|
|
|
|
|
|
if (ctnMapping == null)
|
|
|
{
|
|
|
queryInfo.ISOEquipmentCode = model.ISOEquipmentCode;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
queryInfo.ISOEquipmentCode = ctnMapping.MapCode;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(model.stuffingWeight))
|
|
|
{
|
|
|
queryInfo.stuffingWeight = model.stuffingWeight;
|
|
|
}
|
|
|
|
|
|
if (model.stuffingVolume > 0)
|
|
|
{
|
|
|
queryInfo.stuffingVolume = model.stuffingVolume;
|
|
|
}
|
|
|
|
|
|
MSKAPISearchPoint2PointScheduleResultDto resultInfo = null;
|
|
|
|
|
|
var jsonBody = Newtonsoft.Json.JsonConvert.SerializeObject(queryInfo, Formatting.Indented, new JsonSerializerSettings
|
|
|
{
|
|
|
NullValueHandling = NullValueHandling.Ignore
|
|
|
});
|
|
|
|
|
|
var rlt = RequestHelper.Post(jsonBody, queryUrl);
|
|
|
//var rlt = await queryUrl.SetBody(jsonBody).PostAsStringAsync();
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求MSK API查询船期请求,{jsonBody}");
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(rlt))
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求MSK API查询船期结果,{rlt}");
|
|
|
|
|
|
resultInfo = JsonConvert.DeserializeObject<MSKAPISearchPoint2PointScheduleResultDto>(rlt);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求MSK API查询船期异常,原因:{ex.Message}");
|
|
|
|
|
|
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchShipException)), ex.Message));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (resultInfo != null && resultInfo.code == 200
|
|
|
&& resultInfo.data != null && resultInfo.data.Count > 0)
|
|
|
{
|
|
|
resultInfo.data.ForEach(t =>
|
|
|
{
|
|
|
t.transportSchedules.ForEach(a =>
|
|
|
{
|
|
|
a.originGeoId = model.carrierCollectionOriginGeoID;
|
|
|
a.originUnLocCode = model.collectionOriginUNLocationCode;
|
|
|
a.originRegionName = model.collectionOriginUNRegionName;
|
|
|
a.originCityName = model.collectionOriginCityName;
|
|
|
a.originCountryName = model.collectionOriginCountryName;
|
|
|
|
|
|
a.destinationGeoId = model.carrierDeliveryDestinationGeoID;
|
|
|
a.destinationUnLocCode = model.deliveryDestinationUNLocationCode;
|
|
|
a.destinationRegionName = model.deliveryDestinationUNRegionName;
|
|
|
a.destinationCityName = model.deliveryDestinationCityName;
|
|
|
a.destinationCountryName = model.deliveryDestinationCountryName;
|
|
|
|
|
|
CacheShipSailingSchedule(a).GetAwaiter().GetResult();
|
|
|
});
|
|
|
|
|
|
var currList = t.transportSchedules.Select(a =>
|
|
|
{
|
|
|
return GetShipScheduleShow(a);
|
|
|
}).ToList();
|
|
|
|
|
|
if (currList.Count > 0)
|
|
|
list.AddRange(currList);
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"检索海运船期详情异常,req={JsonConvert.SerializeObject(model)} 原因:{ex.Message}");
|
|
|
|
|
|
return DataResult<List<SearchShipSailingScheduleResultDto>>.FailedData(list, ex.Message);
|
|
|
}
|
|
|
|
|
|
return DataResult<List<SearchShipSailingScheduleResultDto>>.Success(list);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 组织返回船期数据
|
|
|
/// <summary>
|
|
|
/// 组织返回船期数据
|
|
|
/// </summary>
|
|
|
/// <param name="model">查询的船期详情</param>
|
|
|
/// <returns>返回显示的船期数据</returns>
|
|
|
private SearchShipSailingScheduleResultDto GetShipScheduleShow(MSKAPISearchTransportSchedules model)
|
|
|
{
|
|
|
|
|
|
SearchShipSailingScheduleResultDto showDto = new SearchShipSailingScheduleResultDto
|
|
|
{
|
|
|
PId = model.PId,
|
|
|
MD5 = model.MD5,
|
|
|
|
|
|
orignCarrierCityGeoID = model.originGeoId,
|
|
|
orignUNLocationCode = model.originUnLocCode,
|
|
|
orignCityName = model.originCityName,
|
|
|
originRegionName = model.originRegionName,
|
|
|
originCountryName = model.originCountryName,
|
|
|
|
|
|
deliveryCarrierCityGeoID = model.destinationGeoId,
|
|
|
deliveryUNLocationCode = model.destinationUnLocCode,
|
|
|
deliveryCityName = model.destinationCityName,
|
|
|
deliveryRegionName = model.destinationRegionName,
|
|
|
deliveryCountryName = model.destinationCountryName,
|
|
|
|
|
|
vesselName = model.firstDepartureVessel.vesselName,
|
|
|
carrierDepartureVoyageNumber = model.transportLegs.FirstOrDefault().transport.carrierDepartureVoyageNumber,
|
|
|
|
|
|
Legs = new List<MSKAPISPOTScheduleRateResultShowLegsDto>()
|
|
|
};
|
|
|
|
|
|
//ETD
|
|
|
if (model.departureDateTime.HasValue)
|
|
|
{
|
|
|
showDto.ETD = model.departureDateTime.Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//查询船期错误,预计离港日期查询为空
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchShipETDNull)));
|
|
|
}
|
|
|
|
|
|
//ETA
|
|
|
if (model.arrivalDateTime.HasValue)
|
|
|
{
|
|
|
showDto.ETA = model.arrivalDateTime.Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//查询船期错误,预计到港日期查询为空
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchShipETANull)));
|
|
|
}
|
|
|
|
|
|
//计算预计天数
|
|
|
if (showDto.ETD.HasValue && showDto.ETD.HasValue)
|
|
|
{
|
|
|
TimeSpan ts = showDto.ETA.Value.Subtract(showDto.ETD.Value);
|
|
|
var timeDiff = ts.TotalHours;
|
|
|
|
|
|
showDto.days = (int)Math.Ceiling(timeDiff / 24.0);
|
|
|
}
|
|
|
|
|
|
if (model.transportLegs.Count > 1)
|
|
|
showDto.isTransfer = true;
|
|
|
|
|
|
//Legs
|
|
|
if (model.facilities != null)
|
|
|
{
|
|
|
showDto.orignCountryCode = model.facilities.collectionOrigin.countryCode;
|
|
|
showDto.deliveryCountryCode = model.facilities.deliveryDestination.countryCode;
|
|
|
|
|
|
var legs = new List<MSKAPISPOTScheduleRateResultShowLegsDto>();
|
|
|
|
|
|
for (int i = 0; i < model.transportLegs.Count; i++)
|
|
|
{
|
|
|
var b = model.transportLegs[i];
|
|
|
|
|
|
MSKAPISPOTScheduleRateResultShowLegsDto leg = new MSKAPISPOTScheduleRateResultShowLegsDto
|
|
|
{
|
|
|
vesselName = b.transport.vessel.vesselName,
|
|
|
VoyageNo = b.transport.carrierDepartureVoyageNumber,
|
|
|
From = new MSKAPISPOTScheduleRateResultShowLegsLocationDto
|
|
|
{
|
|
|
CityName = b.facilities.startLocation.cityName,
|
|
|
CountryCode = b.facilities.startLocation.countryCode,
|
|
|
SiteGeoId = b.facilities.startLocation.carrierSiteGeoID,
|
|
|
LocationType = "From",
|
|
|
},
|
|
|
To = new MSKAPISPOTScheduleRateResultShowLegsLocationDto
|
|
|
{
|
|
|
CityName = b.facilities.endLocation.cityName,
|
|
|
CountryCode = b.facilities.endLocation.countryCode,
|
|
|
SiteGeoId = b.facilities.endLocation.carrierSiteGeoID,
|
|
|
LocationType = "To",
|
|
|
}
|
|
|
};
|
|
|
|
|
|
//ETD
|
|
|
if (b.departureDateTime.HasValue)
|
|
|
{
|
|
|
leg.ETD = b.departureDateTime.Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//查询船期错误,预计离港日期查询为空
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchShipETDNull)));
|
|
|
}
|
|
|
|
|
|
//ETA
|
|
|
if (b.arrivalDateTime.HasValue)
|
|
|
{
|
|
|
leg.ETA = b.arrivalDateTime.Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//查询船期错误,预计到港日期查询为空
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchShipETANull)));
|
|
|
}
|
|
|
|
|
|
leg.SortNo = i + 1;
|
|
|
leg.From.SiteGeoId = b.facilities.startLocation.carrierSiteGeoID;
|
|
|
leg.From.CityName = b.facilities.startLocation.cityName;
|
|
|
leg.From.CountryCode = b.facilities.startLocation.countryCode;
|
|
|
leg.From.UnLocCode = b.facilities.startLocation.UNLocationCode;
|
|
|
|
|
|
leg.To.SiteGeoId = b.facilities.endLocation.carrierSiteGeoID;
|
|
|
leg.To.CityName = b.facilities.endLocation.cityName;
|
|
|
leg.To.CountryCode = b.facilities.endLocation.countryCode;
|
|
|
leg.To.UnLocCode = b.facilities.endLocation.UNLocationCode;
|
|
|
|
|
|
if (i == 0 && i == model.transportLegs.Count - 1)
|
|
|
{
|
|
|
leg.From.CityGeoId = model.originGeoId;
|
|
|
leg.From.CountryName = model.originCountryName;
|
|
|
leg.From.RegionName = model.originRegionName;
|
|
|
|
|
|
leg.To.CityGeoId = model.destinationGeoId;
|
|
|
leg.To.CountryName = model.destinationCountryName;
|
|
|
leg.To.RegionName = model.destinationRegionName;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (i == 0)
|
|
|
{
|
|
|
leg.From.CityGeoId = model.originGeoId;
|
|
|
leg.From.CountryName = model.originCountryName;
|
|
|
leg.From.RegionName = model.originRegionName;
|
|
|
leg.From.UnLocCode = model.originUnLocCode;
|
|
|
}
|
|
|
else if (i == model.transportLegs.Count - 1)
|
|
|
{
|
|
|
leg.To.CityGeoId = model.destinationGeoId;
|
|
|
leg.To.CountryName = model.destinationCountryName;
|
|
|
leg.To.RegionName = model.destinationRegionName;
|
|
|
leg.To.UnLocCode = model.destinationUnLocCode;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
legs.Add(leg);
|
|
|
}
|
|
|
|
|
|
|
|
|
showDto.Legs = legs.OrderBy(t => t.ETD).Select((t, idx) =>
|
|
|
{
|
|
|
t.SortNo = idx + 1;
|
|
|
return t;
|
|
|
}).ToList();
|
|
|
}
|
|
|
|
|
|
return showDto;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 缓存船期数据
|
|
|
/// <summary>
|
|
|
/// 缓存船期数据
|
|
|
/// </summary>
|
|
|
/// <param name="model">船期查询结果明细</param>
|
|
|
/// <param name="busiType">船期类型 MSKSPOT-马士基即期</param>
|
|
|
/// <returns>返回主键ID</returns>
|
|
|
private async Task CacheShipSailingSchedule(MSKAPISearchTransportSchedules model, string busiType = "MSKCON")
|
|
|
{
|
|
|
/*
|
|
|
1、按照船期明细缓存,并把ID作为缓存的KEY
|
|
|
2、对数据进行JSON串行化的文本提取MD5
|
|
|
3、写入缓存,并返回ID
|
|
|
*/
|
|
|
var newModel = model.MapTo<MSKAPISearchTransportSchedules, MSKAPISearchTransportSchedules>();
|
|
|
|
|
|
//newModel.priceID = null;
|
|
|
|
|
|
var json = Newtonsoft.Json.JsonConvert.SerializeObject(newModel);
|
|
|
model.PId = SnowFlakeSingle.Instance.NextId();
|
|
|
|
|
|
//string md5 = json.ToMd5();
|
|
|
|
|
|
//model.MD5 = md5;
|
|
|
|
|
|
var shareKey = model.PId.ToString();
|
|
|
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
DateTime expireDateTime = DateTime.Now.AddHours(4);
|
|
|
|
|
|
var expireTimeSpan = expireDateTime.Subtract(nowDate).Duration();
|
|
|
|
|
|
if (!redisService.Exists($"{shareKey}_{busiType}"))
|
|
|
{
|
|
|
redisService.SetValue($"{shareKey}_{busiType}", Newtonsoft.Json.JsonConvert.SerializeObject(model), 4 * 3600);
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 获取缓存的船期数据
|
|
|
/// <summary>
|
|
|
/// 获取缓存的船期数据
|
|
|
/// </summary>
|
|
|
/// <param name="pid">船期Pid</param>
|
|
|
/// <param name="busiType">类型 MSKCON-合约船期</param>
|
|
|
/// <returns>返回船期详情</returns>
|
|
|
private MSKAPISearchTransportSchedules GetCacheShipSailingSchedule(long pid, string busiType = "MSKCON")
|
|
|
{
|
|
|
if (redisService.Exists($"{pid}_{busiType}"))
|
|
|
{
|
|
|
return redisService.GetEntity<MSKAPISearchTransportSchedules>($"{pid}_{busiType}");
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 发送马士基订舱请求
|
|
|
/// <summary>
|
|
|
/// 发送马士基订舱请求
|
|
|
/// </summary>
|
|
|
/// <param name="model">请求订舱详情</param>
|
|
|
/// <returns></returns>
|
|
|
public async Task<DataResult<MSKBookingResultDto>> SendMSKBooking(MSKBookingDto model)
|
|
|
{
|
|
|
return await InnerSendMSKBooking(model, 0);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 发送马士基订舱请求(内部方法)
|
|
|
/// <summary>
|
|
|
/// 发送马士基订舱请求(内部方法)
|
|
|
/// </summary>
|
|
|
/// <param name="model">请求订舱详情</param>
|
|
|
/// <param name="currId">当前马士基订舱主键</param>
|
|
|
/// <param name="isDefaultSave">是否默认保存</param>
|
|
|
/// <returns></returns>
|
|
|
private async Task<DataResult<MSKBookingResultDto>> InnerSendMSKBooking(MSKBookingDto model, long currId, bool isDefaultSave = true)
|
|
|
{
|
|
|
MSKBookingResultDto result = new MSKBookingResultDto();
|
|
|
|
|
|
/*
|
|
|
MSKApiBooking
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
//服务船公司不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.carrierCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICarrierCodeNull)));
|
|
|
|
|
|
//船公司代码不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.vesselCarrierCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIVesselCarrierCodeNull)));
|
|
|
|
|
|
string sendUrl = string.Empty;
|
|
|
|
|
|
if (model.carrierCode.Equals("MSK", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
sendUrl = configService.GetConfig(CONST_MSK_API_BOOKING_URL, long.Parse(user.TenantId), false).GetAwaiter().GetResult()?.Data?.Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//当前船公司 {model.carrierId} 未配置相应的请求接口
|
|
|
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIBookingNotSupport)), model.carrierId));
|
|
|
}
|
|
|
|
|
|
//未配置发送订舱请求接口地址,请联系管理员
|
|
|
if (string.IsNullOrWhiteSpace(sendUrl))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIBookingUrlNull)));
|
|
|
|
|
|
var webAccountConfig = codeThirdPartyService.GetCodeThirdPartyInfoWithCompany("MSKApi").GetAwaiter().GetResult()?.Data;
|
|
|
|
|
|
//未配置公司或个人的第三方账户维护(MSK API合约),请联系管理员
|
|
|
if (webAccountConfig == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIMSKConThirdPartySettingNull)));
|
|
|
|
|
|
//这里是校验必填项
|
|
|
ValidateMSKAPIData(model);
|
|
|
|
|
|
SpaceBookingOrderShipSchedule spaceBookingOrderShipSchedule = null;
|
|
|
|
|
|
MSKAPISearchTransportSchedules selectedShipSchedule = null;
|
|
|
|
|
|
//船期信息不能为空,请重新检索船期
|
|
|
if (model.PId == 0)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIShipScheduleNotNull)));
|
|
|
|
|
|
if (model.PId > 0)
|
|
|
{
|
|
|
if (model.id.HasValue && model.id.Value > 0)
|
|
|
{
|
|
|
var recordId = model.id.Value;
|
|
|
|
|
|
spaceBookingOrderShipSchedule = tenantDb.Queryable<SpaceBookingOrderShipSchedule>().First(a => a.RecordId == recordId && a.ShipRatePid != null &&
|
|
|
a.ShipRatePid.Value == model.PId && a.Deleted == false);
|
|
|
}
|
|
|
|
|
|
if (spaceBookingOrderShipSchedule == null)
|
|
|
{
|
|
|
selectedShipSchedule = GetCacheShipSailingSchedule(model.PId.Value);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
selectedShipSchedule = JsonConvert.DeserializeObject<MSKAPISearchTransportSchedules>(spaceBookingOrderShipSchedule.ShipJson);
|
|
|
}
|
|
|
|
|
|
//船期数据校验失败,请重新查询船期信息
|
|
|
if (selectedShipSchedule == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIShipScheduleCheckFailNotNull)));
|
|
|
}
|
|
|
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
|
|
|
var recordInfo = model.Adapt<SpaceBookingOrder>();
|
|
|
var recordCtnList = model.ctns.Adapt<List<SpaceBookingOrderCtn>>();
|
|
|
|
|
|
MSKAPIBookingDto bookingDto = new MSKAPIBookingDto
|
|
|
{
|
|
|
userKey = mskAPIUserKey,
|
|
|
userSecret = mskAPIUserSecret,
|
|
|
operatingEnvironment = mskAPIEnvironment,
|
|
|
mskAppKey = webAccountConfig.AppKey,
|
|
|
mskAppSecret = webAccountConfig.AppSecret,
|
|
|
bookingBody = new MSKAPIBookingBodyDto()
|
|
|
};
|
|
|
|
|
|
bookingDto.bookingBody.references = new MSKAPIBookingReferenceDto
|
|
|
{
|
|
|
priceReference = model.priceReference,
|
|
|
productCode = model.productCode,
|
|
|
sender = model.sender,
|
|
|
bookingOfficeUNLocationCode = "CNTAO"
|
|
|
};
|
|
|
|
|
|
bookingDto.bookingBody.mandatoryParties = new MSKAPIBookingMandatoryParties
|
|
|
{
|
|
|
bookedByCompanyName = model.bookedByCompanyName,
|
|
|
bookedByMaerskPartyCode = model.bookedByMaerskPartyCode,
|
|
|
bookedByPartyContact = new MSKAPIBookingMandatoryPartyContact
|
|
|
{
|
|
|
name = model.bookedByCompanyContactName,
|
|
|
email = model.bookedByCompanyContactEmail
|
|
|
},
|
|
|
priceOwnerCompanyName = model.priceOwnerCompanyName,
|
|
|
priceOwnerMaerskPartyCode = model.priceOwnerMaerskPartyCode,
|
|
|
priceOwnerPartyContact = new MSKAPIBookingMandatoryPartyContact
|
|
|
{
|
|
|
name = model.priceOwnerContactName,
|
|
|
email = model.priceOwnerContactEmail
|
|
|
},
|
|
|
};
|
|
|
|
|
|
bookingDto.bookingBody.transport = new MSKAPIBookingTransport
|
|
|
{
|
|
|
carrierCode = model.vesselCarrierCode,
|
|
|
earliestDepartureDate = model.earliestDepartureDate.Value.ToString("yyyy-MM-ddTHH:mm:ss"),
|
|
|
exportServiceMode = model.exportServiceMode,
|
|
|
importServiceMode = model.importServiceMode,
|
|
|
routeDetails = new MSKAPIBookingRouteDetails
|
|
|
{
|
|
|
placeOfReceipt = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
UNLocationCode = model.userPlaceOfReceiptUnLocCode,
|
|
|
maerskCityGeoId = selectedShipSchedule.originGeoId,
|
|
|
},
|
|
|
placeOfDelivery = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
UNLocationCode = model.userPlaceOfDeliveryUnLocCode,
|
|
|
maerskCityGeoId = selectedShipSchedule.destinationGeoId,
|
|
|
},
|
|
|
selectedRoute = new MSKAPIBookingRoute
|
|
|
{
|
|
|
bookingSchedules = new List<MSKAPIBookingSchedules>(),
|
|
|
},
|
|
|
}
|
|
|
};
|
|
|
|
|
|
//ETD
|
|
|
if (selectedShipSchedule.departureDateTime.HasValue)
|
|
|
{
|
|
|
bookingDto.bookingBody.transport.earliestDepartureDate = selectedShipSchedule.departureDateTime.Value.ToString("yyyy-MM-ddTHH:mm:ss");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new Exception($"查询船期错误,pid={model.PId} 预计离港日期departureDate 格式解析错误");
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < selectedShipSchedule.transportLegs.Count; i++)
|
|
|
{
|
|
|
var detail = selectedShipSchedule.transportLegs[i];
|
|
|
|
|
|
var currDto = new MSKAPIBookingSchedules();
|
|
|
|
|
|
//ETD
|
|
|
if (detail.departureDateTime.HasValue)
|
|
|
{
|
|
|
currDto.originDepartureDateTimeLocal = detail.departureDateTime.Value.ToString("yyyy-MM-ddTHH:mm:ss");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new Exception($"查询船期错误,pid={model.PId} 预计离港日期departureDate 格式解析错误");
|
|
|
}
|
|
|
|
|
|
//ETA
|
|
|
if (detail.arrivalDateTime.HasValue)
|
|
|
{
|
|
|
currDto.destinationArrivalDateTimeLocal = detail.arrivalDateTime.Value.ToString("yyyy-MM-ddTHH:mm:ss");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new Exception($"查询船期错误,pid={model.PId} 预计到港日期arrivalDateTime 格式解析错误");
|
|
|
}
|
|
|
|
|
|
if (detail.transport.vessel != null)
|
|
|
{
|
|
|
currDto.transportMode = new MSKAPIBookingTransportMode
|
|
|
{
|
|
|
vessel = new MSKAPIBookingTransportModeVessel
|
|
|
{
|
|
|
name = detail.transport.vessel.vesselName,
|
|
|
maerskVesselCode = detail.transport.vessel.carrierVesselCode,
|
|
|
vesselIMONumber = detail.transport.vessel.vesselIMONumber
|
|
|
},
|
|
|
exportVoyageNumber = detail.transport.carrierDepartureVoyageNumber,
|
|
|
};
|
|
|
}
|
|
|
|
|
|
currDto.serviceCode = detail.transport.carrierServiceCode;
|
|
|
currDto.transportModeCode = detail.transport.transportMode;
|
|
|
|
|
|
//首个
|
|
|
if (i == 0)
|
|
|
{
|
|
|
currDto.startLocation = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
cityName = detail.facilities.startLocation.cityName,
|
|
|
ISOcountryCode = detail.facilities.startLocation.countryCode,
|
|
|
UNLocationCode = detail.facilities.startLocation.UNLocationCode,
|
|
|
maerskCityGeoId = selectedShipSchedule.originGeoId,
|
|
|
};
|
|
|
|
|
|
if (i == selectedShipSchedule.transportLegs.Count - 1)
|
|
|
{
|
|
|
currDto.endLocation = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
cityName = detail.facilities.endLocation.cityName,
|
|
|
ISOcountryCode = detail.facilities.endLocation.countryCode,
|
|
|
UNLocationCode = detail.facilities.endLocation.UNLocationCode,
|
|
|
maerskCityGeoId = selectedShipSchedule.destinationGeoId,
|
|
|
};
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
currDto.endLocation = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
cityName = detail.facilities.endLocation.cityName,
|
|
|
ISOcountryCode = detail.facilities.endLocation.countryCode,
|
|
|
UNLocationCode = detail.facilities.endLocation.UNLocationCode,
|
|
|
maerskSiteGeoId = detail.facilities.endLocation.carrierSiteGeoID,
|
|
|
};
|
|
|
}
|
|
|
}
|
|
|
else if (i == selectedShipSchedule.transportLegs.Count - 1)
|
|
|
{
|
|
|
currDto.startLocation = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
cityName = detail.facilities.startLocation.cityName,
|
|
|
ISOcountryCode = detail.facilities.startLocation.countryCode,
|
|
|
UNLocationCode = detail.facilities.startLocation.UNLocationCode,
|
|
|
maerskSiteGeoId = detail.facilities.startLocation.carrierSiteGeoID,
|
|
|
};
|
|
|
|
|
|
currDto.endLocation = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
cityName = detail.facilities.endLocation.cityName,
|
|
|
ISOcountryCode = detail.facilities.endLocation.countryCode,
|
|
|
UNLocationCode = detail.facilities.endLocation.UNLocationCode,
|
|
|
maerskCityGeoId = selectedShipSchedule.destinationGeoId,
|
|
|
};
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
currDto.startLocation = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
cityName = detail.facilities.startLocation.cityName,
|
|
|
ISOcountryCode = detail.facilities.startLocation.countryCode,
|
|
|
UNLocationCode = detail.facilities.startLocation.UNLocationCode,
|
|
|
maerskSiteGeoId = detail.facilities.startLocation.carrierSiteGeoID,
|
|
|
};
|
|
|
|
|
|
currDto.endLocation = new MSKAPIBookingRouteDetailsBase
|
|
|
{
|
|
|
cityName = detail.facilities.endLocation.cityName,
|
|
|
ISOcountryCode = detail.facilities.endLocation.countryCode,
|
|
|
UNLocationCode = detail.facilities.endLocation.UNLocationCode,
|
|
|
maerskSiteGeoId = detail.facilities.endLocation.carrierSiteGeoID,
|
|
|
};
|
|
|
}
|
|
|
|
|
|
bookingDto.bookingBody.transport.routeDetails.selectedRoute.bookingSchedules.Add(currDto);
|
|
|
}
|
|
|
|
|
|
|
|
|
bookingDto.bookingBody.cargo = new MSKAPIBookingCargo
|
|
|
{
|
|
|
commodityCode = model.commodityCode,
|
|
|
commodityCodeType = "MaerskCode",
|
|
|
cargoType = model.cargoType,
|
|
|
totalCargoWeight = model.totalCargoWeight
|
|
|
};
|
|
|
|
|
|
//是否冷冻处理
|
|
|
if (model.isReefer)
|
|
|
{
|
|
|
bookingDto.bookingBody.cargo.reeferSettings = new MSKAPIBookingCargoReeferSettings();
|
|
|
|
|
|
bookingDto.bookingBody.cargo.reeferSettings.temperatureDetails = model.temperature;
|
|
|
bookingDto.bookingBody.cargo.reeferSettings.temperatureMeasureUnit = "C";
|
|
|
|
|
|
bookingDto.bookingBody.cargo.reeferSettings.noOfProbes = model.noOfProbes;
|
|
|
|
|
|
//每小时需要的通风量,单位为立方米(0-285)
|
|
|
bookingDto.bookingBody.cargo.reeferSettings.ventilation = model.ventilation;
|
|
|
|
|
|
bookingDto.bookingBody.cargo.reeferSettings.humidity = model.humidity;
|
|
|
}
|
|
|
|
|
|
bookingDto.bookingBody.equipmentAndHaulage = new List<MSKAPIBookingEquipmentAndHaulage>();
|
|
|
|
|
|
if (model.ctns != null && model.ctns.Count > 0)
|
|
|
{
|
|
|
model.ctns.ForEach(async ctn =>
|
|
|
{
|
|
|
var ctnMapping = mappingCtnService.QueryMappingCtn(model.carrierId.Value, CONST_MSK_API_MAPPING_MODULE, ctn.ctnCode).GetAwaiter().GetResult()?.Data;
|
|
|
//var ctnMapping = ctnCodeMappingList.FirstOrDefault(t => t.Code.Equals(ctn.ctnCode));
|
|
|
|
|
|
if (ctnMapping == null)
|
|
|
throw new Exception($"未配置相应的箱型对应{ctn.ctnName},请联系管理员");
|
|
|
|
|
|
MSKAPIBookingEquipmentAndHaulage haulage = new MSKAPIBookingEquipmentAndHaulage
|
|
|
{
|
|
|
equipmentDetails = new MSKAPIBookingEquipmentAndHaulageItem(),
|
|
|
stuffingDetails = new List<MSKAPIBookingStuffingdetails>()
|
|
|
};
|
|
|
|
|
|
if (model.isShipperOwned)
|
|
|
haulage.equipmentDetails.isShipperOwned = model.isShipperOwned;
|
|
|
|
|
|
if (model.isImportReturned)
|
|
|
haulage.equipmentDetails.isImportReturned = model.isImportReturned;
|
|
|
|
|
|
haulage.equipmentDetails.ISOEquipmentCode = ctnMapping.MapCode;
|
|
|
haulage.equipmentDetails.equipmentQuantity = ctn.ctnNum;
|
|
|
|
|
|
haulage.stuffingDetails.Add(new MSKAPIBookingStuffingdetails
|
|
|
{
|
|
|
stuffingValue = (int)ctn.ctnSufferWeight.Value,
|
|
|
stuffingMeasurementType = "WEIGHT",
|
|
|
stuffingMeasurementUnit = "KGS"
|
|
|
});
|
|
|
|
|
|
bookingDto.bookingBody.equipmentAndHaulage.Add(haulage);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
long id = 0;
|
|
|
if (isDefaultSave)
|
|
|
{
|
|
|
id = InnerSave(model, isSendApi: true).GetAwaiter().GetResult().Data;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
id = currId;
|
|
|
}
|
|
|
|
|
|
result.id = id;
|
|
|
|
|
|
MSKAPIBookingResultDto resultInfo = null;
|
|
|
|
|
|
var jsonBody = Newtonsoft.Json.JsonConvert.SerializeObject(bookingDto);
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"开始请求MSK API订舱,JSON={jsonBody}");
|
|
|
|
|
|
//var rlt = await sendUrl.SetBody(jsonBody).PostAsStringAsync();
|
|
|
|
|
|
var rlt = RequestHelper.Post(jsonBody, sendUrl);
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"开始请求MSK API订舱,返回结果 JSON={rlt}");
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(rlt))
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
resultInfo = JsonConvert.DeserializeObject<MSKAPIBookingResultDto>(rlt);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求MSK API订舱异常,原因:{ex.Message}");
|
|
|
|
|
|
throw new Exception($"请求MSK API订舱异常,原因:{ex.Message}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
MSKAPIBookingResultDataDto resultData = null;
|
|
|
|
|
|
if (resultInfo.code == 200)
|
|
|
{
|
|
|
resultData = JsonConvert.DeserializeObject<MSKAPIBookingResultDataDto>(JsonConvert.SerializeObject(resultInfo.data));
|
|
|
}
|
|
|
|
|
|
var entity = tenantDb.Queryable<SpaceBookingOrder>().First(a => a.Id == id);
|
|
|
|
|
|
if (resultInfo != null && resultInfo.code == 200
|
|
|
&& resultData != null)
|
|
|
{
|
|
|
entity.RequestAcknowledgementId = resultData.requestAcknowledgementId;
|
|
|
entity.BookingReference = resultData.bookingReference;
|
|
|
entity.Status = "SUCC";
|
|
|
entity.StatusName = "发送成功";
|
|
|
|
|
|
await tenantDb.Updateable(entity).UpdateColumns(x => new
|
|
|
{
|
|
|
x.RequestAcknowledgementId,
|
|
|
x.BookingReference,
|
|
|
x.Status,
|
|
|
x.StatusName
|
|
|
}).ExecuteCommandAsync();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
entity.Status = "FAILURE";
|
|
|
entity.StatusName = "发送失败";
|
|
|
entity.Notes = resultInfo.msg.Length > 500 ? resultInfo.msg.Substring(0, 500) : resultInfo.msg;
|
|
|
|
|
|
await tenantDb.Updateable(entity).UpdateColumns(x => new
|
|
|
{
|
|
|
x.Status,
|
|
|
x.StatusName,
|
|
|
x.Notes
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
throw new Exception(resultInfo.msg);
|
|
|
}
|
|
|
|
|
|
result.succ = true;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Error, $"MSK API订舱异常,req={JsonConvert.SerializeObject(model)} 原因:{ex.Message}");
|
|
|
|
|
|
//throw Oops.Bah($"MSK API订舱失败,{ex.Message}");
|
|
|
|
|
|
result.succ = false;
|
|
|
result.msg = $"MSK API订舱失败,{ex.Message}";
|
|
|
|
|
|
//throw Oops.Bah($"MSK API订舱失败,{ex.Message}");
|
|
|
}
|
|
|
|
|
|
return DataResult<MSKBookingResultDto>.Success(result);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 校验马士基API订舱必填项
|
|
|
/// <summary>
|
|
|
/// 校验马士基API订舱必填项
|
|
|
/// </summary>
|
|
|
/// <param name="model"></param>
|
|
|
private void ValidateMSKAPIData(MSKBookingDto model)
|
|
|
{
|
|
|
/*
|
|
|
马士基API订舱内容校验
|
|
|
1、合约号必填
|
|
|
2、请求类别必填
|
|
|
3、服务船公司必填
|
|
|
4、订舱公司名称、代码、联系人、邮箱必填
|
|
|
5、持约方公司名称、代码、联系、邮箱必填
|
|
|
6、始发地城市名称、UNLOC、国家代码、服务模式
|
|
|
7、目的地城市名称、UNLOC、国家代码、服务模式
|
|
|
8、船名、航次、ETD、ETA
|
|
|
9、商品名称、代码必填
|
|
|
10、总重必填
|
|
|
11、货物标志必填
|
|
|
12、如果选择了冷冻处理,至少要填个温度
|
|
|
13、箱型、箱量、重量必填
|
|
|
14、总重=箱量*单箱重量
|
|
|
15、预计离港日期必填
|
|
|
*/
|
|
|
|
|
|
//订舱合同惟一ID必填
|
|
|
if (string.IsNullOrWhiteSpace(model.priceReference))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIPriceReferNull)));
|
|
|
|
|
|
//订舱合同惟一ID格式错误 [a-zA-Z0-9_/,-]{1,50}
|
|
|
if (!Regex.IsMatch(model.priceReference, "[a-zA-Z0-9_/,-]{1,50}"))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIPriceReferFormatError)));
|
|
|
|
|
|
//请求类别必填
|
|
|
if (string.IsNullOrWhiteSpace(model.sender))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISenderNull)));
|
|
|
|
|
|
//服务船公司代码必填
|
|
|
if (string.IsNullOrWhiteSpace(model.carrierCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICarrierCodeNull)));
|
|
|
|
|
|
//订舱公司名称必填
|
|
|
if (string.IsNullOrWhiteSpace(model.bookedByCompanyName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIBookCompanyNameNull)));
|
|
|
|
|
|
//订舱方ID必填
|
|
|
if (string.IsNullOrWhiteSpace(model.bookedByMaerskPartyCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIBookCompanyCodeNull)));
|
|
|
|
|
|
//订舱方公司联系人必填
|
|
|
if (string.IsNullOrWhiteSpace(model.bookedByCompanyContactName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIBookCompanyContactNull)));
|
|
|
|
|
|
//订舱方公司邮箱必填
|
|
|
if (string.IsNullOrWhiteSpace(model.bookedByCompanyContactEmail))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIBookCompanyContactEmailNull)));
|
|
|
|
|
|
//持约方公司名称必填
|
|
|
if (string.IsNullOrWhiteSpace(model.priceOwnerCompanyName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIPriceOwnerCompanyNameNull)));
|
|
|
|
|
|
//持约方ID必填
|
|
|
if (string.IsNullOrWhiteSpace(model.priceOwnerMaerskPartyCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIPriceOwnerCompanyCodeNull)));
|
|
|
|
|
|
//持约方公司联系人必填
|
|
|
if (string.IsNullOrWhiteSpace(model.priceOwnerContactName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIPriceOwnerCompanyContactNull)));
|
|
|
|
|
|
//持约方公司邮箱必填
|
|
|
if (string.IsNullOrWhiteSpace(model.priceOwnerContactEmail))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIPriceOwnerCompanyContactEmailNull)));
|
|
|
|
|
|
//始发地城市名称必填
|
|
|
if (string.IsNullOrWhiteSpace(model.placeOfReceiptCityName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOriginCityNameNull)));
|
|
|
|
|
|
//始发地UN CODE必填
|
|
|
if (string.IsNullOrWhiteSpace(model.placeOfReceiptUnLocCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOriginUnCodeNull)));
|
|
|
|
|
|
//始发地国家代码必填
|
|
|
if (string.IsNullOrWhiteSpace(model.placeOfReceiptCountryCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOriginCountryCodeNull)));
|
|
|
|
|
|
//始发地服务模式必填
|
|
|
if (string.IsNullOrWhiteSpace(model.exportServiceMode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOriginServiceModeNull)));
|
|
|
|
|
|
//目的地城市名称必填
|
|
|
if (string.IsNullOrWhiteSpace(model.placeOfDeliveryCityName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIDestCityNameNull)));
|
|
|
|
|
|
//目的地UN CODE必填
|
|
|
if (string.IsNullOrWhiteSpace(model.placeOfDeliveryUnLocCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIDestUnCodeNull)));
|
|
|
|
|
|
//目的地国家代码必填
|
|
|
if (string.IsNullOrWhiteSpace(model.placeOfDeliveryCountryCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIDestCountryCodeNull)));
|
|
|
|
|
|
//目的地服务模式必填
|
|
|
if (string.IsNullOrWhiteSpace(model.importServiceMode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIDestServiceModeNull)));
|
|
|
|
|
|
//船名必填,请确认正确选择了船期
|
|
|
if (string.IsNullOrWhiteSpace(model.vesselName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIVesselNameNull)));
|
|
|
|
|
|
//航次号必填,请确认正确选择了船期
|
|
|
if (string.IsNullOrWhiteSpace(model.exportVoyageNumber))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIVoynoNull)));
|
|
|
|
|
|
//ETD必填,请确认正确选择了船期
|
|
|
if (!model.originDepartureDateTimeLocal.HasValue)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOriginDepartureDateNull)));
|
|
|
|
|
|
//ETA必填,请确认正确选择了船期
|
|
|
if (!model.destinationArrivalDateTimeLocal.HasValue)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIDestArrivalDateNull)));
|
|
|
|
|
|
//商品代码必填,请确认正确选择了商品
|
|
|
if (string.IsNullOrWhiteSpace(model.commodityCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICommodityNull)));
|
|
|
|
|
|
//商品名称必填,请确认正确选择了商品
|
|
|
if (string.IsNullOrWhiteSpace(model.commodityName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICommodityNameNull)));
|
|
|
|
|
|
//总重必填
|
|
|
if (!model.totalCargoWeight.HasValue || model.totalCargoWeight.Value < 1)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPITotalCargoWTNull)));
|
|
|
|
|
|
//货物标志必填
|
|
|
if (string.IsNullOrWhiteSpace(model.cargoType))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICargoTypeNull)));
|
|
|
|
|
|
//预计离港日期必填
|
|
|
if (!model.earliestDepartureDate.HasValue)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIEarliestDepartDateNull)));
|
|
|
|
|
|
if (model.isReefer)
|
|
|
{
|
|
|
//选择了冷冻处理,温度必填
|
|
|
if (!model.temperature.HasValue)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIIsReeferTempNull)));
|
|
|
}
|
|
|
|
|
|
//箱型箱量信息必填
|
|
|
if (model.ctns.Count == 0)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICtnAndNumNull)));
|
|
|
|
|
|
//箱型不能为空
|
|
|
if (model.ctns.Any(a => string.IsNullOrWhiteSpace(a.ctnCode)))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICtnCodeNull)));
|
|
|
|
|
|
//箱量不能为空,并且不能小于1
|
|
|
if (model.ctns.Any(a => !a.ctnNum.HasValue || a.ctnNum.Value < 1))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICtnNumLower)));
|
|
|
|
|
|
//箱内重量不能为空,并且不能小于1
|
|
|
if (model.ctns.Any(a => !a.ctnSufferWeight.HasValue || a.ctnSufferWeight.Value < 1))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICtnSufferWeightLower)));
|
|
|
|
|
|
//箱内重量合计不等于总重,请修改
|
|
|
if (model.totalCargoWeight.Value != model.ctns.Sum(b => b.ctnNum.Value * b.ctnSufferWeight.Value))
|
|
|
{
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICtnWeightUnequalTotal)));
|
|
|
}
|
|
|
|
|
|
//当前订舱合同号是非订舱方合约,持约方不能和订舱方ID信息一样,请根据实际情况填写
|
|
|
if (!model.isBookingPartOwnPrice)
|
|
|
{
|
|
|
//当前订舱合同号是非订舱方合约,持约方不能和订舱方ID信息一样,请根据实际情况填写
|
|
|
if (model.bookedByMaerskPartyCode.Equals(model.priceOwnerMaerskPartyCode))
|
|
|
{
|
|
|
throw new Exception($"当前订舱合同号是非订舱方合约,持约方不能和订舱方ID信息一样,请根据实际情况填写");
|
|
|
}
|
|
|
|
|
|
//当前订舱合同号是非订舱方合约,持约方公司名称不能和订舱方公司名称信息一样,请根据实际情况填写
|
|
|
if (model.bookedByCompanyName.Equals(model.priceOwnerCompanyName))
|
|
|
{
|
|
|
throw new Exception($"当前订舱合同号是非订舱方合约,持约方公司名称不能和订舱方公司名称信息一样,请根据实际情况填写");
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//当前订舱合同号是订舱方合约,持约方ID必需和订舱方ID信息一致,请根据实际情况填写
|
|
|
if (!model.bookedByMaerskPartyCode.Equals(model.priceOwnerMaerskPartyCode))
|
|
|
{
|
|
|
throw new Exception($"当前订舱合同号是订舱方合约,持约方ID必需和订舱方ID信息一致,请根据实际情况填写");
|
|
|
}
|
|
|
|
|
|
//当前订舱合同号是订舱方合约,持约方名称必需和订舱方名称信息一致,请根据实际情况填写
|
|
|
if (!model.bookedByCompanyName.Equals(model.priceOwnerCompanyName))
|
|
|
{
|
|
|
throw new Exception($"当前订舱合同号是订舱方合约,持约方名称必需和订舱方名称信息一致,请根据实际情况填写");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 检索商品名称
|
|
|
/// <summary>
|
|
|
/// 检索商品名称
|
|
|
/// </summary>
|
|
|
/// <param name="model">请求详情</param>
|
|
|
/// <returns>返回检索结果</returns>
|
|
|
public async Task<DataResult<List<SearchCommodityResultDto>>> SearchCommodities(QueryCommoditiesDto model)
|
|
|
{
|
|
|
List<SearchCommodityResultDto> list = new List<SearchCommodityResultDto>();
|
|
|
|
|
|
/*
|
|
|
MSKApiCommodity
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
//商品名称不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.commodityName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICommodityNameQueryNull)));
|
|
|
|
|
|
//船公司代码不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.carrierCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICommodityNameQueryNull)));
|
|
|
|
|
|
//商品名称至少输入3个以上字符
|
|
|
if (model.commodityName.Length < 3)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICommodityNameInputStrLeast3)));
|
|
|
|
|
|
string queryUrl = string.Empty;
|
|
|
|
|
|
if (model.carrierCode.Equals("MSK", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
queryUrl = configService.GetConfig(CONST_MSK_API_COMMODITY_URL, long.Parse(user.TenantId), false).GetAwaiter().GetResult()?.Data?.Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//当前船公司{0} 不支持 API 查询商品
|
|
|
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchCommodityNotSupport)), model.carrierCode));
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(queryUrl))
|
|
|
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchCommodityNoConfig)), model.carrierCode));
|
|
|
|
|
|
var webAccountConfig = codeThirdPartyService.GetCodeThirdPartyInfoWithCompany("MSKApi").GetAwaiter().GetResult()?.Data;
|
|
|
|
|
|
if (webAccountConfig == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIThirdPartyNull)));
|
|
|
|
|
|
MSKAPISearchCommodityDto queryInfo = new MSKAPISearchCommodityDto
|
|
|
{
|
|
|
userKey = mskAPIUserKey,
|
|
|
userSecret = mskAPIUserSecret,
|
|
|
operatingEnvironment = mskAPIEnvironment,
|
|
|
commodityName = model.commodityName,
|
|
|
mskAppKey = webAccountConfig.AppKey
|
|
|
};
|
|
|
|
|
|
MSKAPISearchCommodityResultDto resultInfo = null;
|
|
|
|
|
|
//var rlt = await queryUrl.SetBody(queryInfo).PostAsStringAsync();
|
|
|
|
|
|
var rlt = RequestHelper.Post(JsonConvert.SerializeObject(queryInfo), queryUrl);
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(rlt))
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
resultInfo = JsonConvert.DeserializeObject<MSKAPISearchCommodityResultDto>(rlt);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求MSK API检索商品异常,原因:{ex.Message}");
|
|
|
|
|
|
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchCommodityException)), ex.Message));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (resultInfo != null && resultInfo.code == 200
|
|
|
&& resultInfo.data != null && resultInfo.data.Count > 0)
|
|
|
{
|
|
|
list = resultInfo.data.Adapt<List<SearchCommodityResultDto>>();
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Error, $"检索商品名称异常,req={JsonConvert.SerializeObject(model)} 原因:{ex.Message}");
|
|
|
|
|
|
return DataResult<List<SearchCommodityResultDto>>.FailedData(list, ex.Message);
|
|
|
}
|
|
|
|
|
|
return DataResult<List<SearchCommodityResultDto>>.Success(list);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 检索始发地、目的港口信息
|
|
|
/// <summary>
|
|
|
/// 检索始发地、目的港口信息
|
|
|
/// </summary>
|
|
|
/// <param name="model">请求详情</param>
|
|
|
/// <returns>返回检索结果</returns>
|
|
|
public async Task<DataResult<List<QueryLocationsResultDto>>> SearchLocations(QueryLocationsDto model)
|
|
|
{
|
|
|
List<QueryLocationsResultDto> list = new List<QueryLocationsResultDto>();
|
|
|
|
|
|
/*
|
|
|
MSKApiCommodity
|
|
|
*/
|
|
|
try
|
|
|
{
|
|
|
//港口或城市名称不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.cityName))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISPOTQueryLocCityNull)));
|
|
|
|
|
|
//服务船公司不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.serviceCarrierCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIVesselCarrierCodeNull)));
|
|
|
|
|
|
//船公司代码不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.carrierCode))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICarrierCodeNull)));
|
|
|
|
|
|
//港口或城市名称至少输入3个以上字符
|
|
|
if (model.cityName.Length < 3)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIQueryLocCityLeastThreeLNull)));
|
|
|
|
|
|
|
|
|
string queryUrl = string.Empty;
|
|
|
|
|
|
if (model.carrierCode.Equals("MSK", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
queryUrl = configService.GetConfig(CONST_MSK_API_LOCATION_URL, long.Parse(user.TenantId), false).GetAwaiter().GetResult()?.Data?.Value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//当前船公司{0} 不支持 API 查询港口
|
|
|
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchLocNotSupport)), model.carrierCode));
|
|
|
}
|
|
|
|
|
|
//未配置 MSK API 查询港口请求接口地址(马士基API合约查询港口URL),请联系管理员
|
|
|
if (string.IsNullOrWhiteSpace(queryUrl))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchLocNoConfig)));
|
|
|
|
|
|
var webAccountConfig = codeThirdPartyService.GetCodeThirdPartyInfoWithCompany("MSKApi").GetAwaiter().GetResult()?.Data;
|
|
|
|
|
|
//未配置第三方账户个人或公司账户(MSKApi)
|
|
|
if (webAccountConfig == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIThirdPartyNull)));
|
|
|
|
|
|
MSKAPISearchLocationDto queryInfo = new MSKAPISearchLocationDto
|
|
|
{
|
|
|
userKey = mskAPIUserKey,
|
|
|
userSecret = mskAPIUserSecret,
|
|
|
operatingEnvironment = mskAPIEnvironment,
|
|
|
name = model.cityName,
|
|
|
mskAppKey = webAccountConfig.AppKey,
|
|
|
carrierCode = model.serviceCarrierCode
|
|
|
};
|
|
|
|
|
|
MSKAPISearchLocationResultDto resultInfo = null;
|
|
|
|
|
|
//var rlt = await queryUrl.SetBody(queryInfo).PostAsStringAsync();
|
|
|
|
|
|
var rlt = RequestHelper.Post(JsonConvert.SerializeObject(queryInfo), queryUrl);
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(rlt))
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
resultInfo = JsonConvert.DeserializeObject<MSKAPISearchLocationResultDto>(rlt);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"请求MSK API检索始发地、目的港口异常,原因:{ex.Message}");
|
|
|
|
|
|
throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchLocException)), ex.Message));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (resultInfo != null && resultInfo.code == 200
|
|
|
&& resultInfo.data != null && resultInfo.data.Count > 0)
|
|
|
{
|
|
|
list = resultInfo.data.Adapt<List<QueryLocationsResultDto>>();
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"检索始发地、目的港口异常,req={JsonConvert.SerializeObject(model)} 原因:{ex.Message}");
|
|
|
|
|
|
//throw Oops.Bah($"检索始发地、目的港口失败,{ex.Message}");
|
|
|
|
|
|
return DataResult<List<QueryLocationsResultDto>>.FailedData(list, ex.Message);
|
|
|
}
|
|
|
|
|
|
return DataResult<List<QueryLocationsResultDto>>.Success(list);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 获取马士基API订舱详情
|
|
|
/// <summary>
|
|
|
/// 获取马士基API订舱详情
|
|
|
/// </summary>
|
|
|
/// <param name="id">马士基API订舱ID</param>
|
|
|
/// <returns>返回详情</returns>
|
|
|
public async Task<DataResult<MSKBookingDto>> GetInfo(long id)
|
|
|
{
|
|
|
MSKBookingDto model = null;
|
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
var entity = await tenantDb.Queryable<SpaceBookingOrder>().FirstAsync(a => a.Id == id);
|
|
|
|
|
|
if (entity == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOrderDeletedOrNoExists)));
|
|
|
|
|
|
model = new MSKBookingDto {
|
|
|
id = entity.Id,
|
|
|
carrierCode = entity.CarrierCode,
|
|
|
vesselCarrierCode = entity.vesselCarrierCode,
|
|
|
carrierId = entity.CarrierId,
|
|
|
priceReference = entity.PriceReference,
|
|
|
productCode = entity.ProductCode,
|
|
|
sender = entity.Sender,
|
|
|
bookedByCompanyName = entity.BookedByCompanyName,
|
|
|
bookedByMaerskPartyCode = entity.BookedByCompanyPartyCode,
|
|
|
bookedByCompanyContactName = entity.BookedByCompanyContact,
|
|
|
bookedByCompanyContactEmail = entity.BookedByCompanyContactEmail,
|
|
|
isBookingPartOwnPrice = entity.IsBookingPartOwnPrice,
|
|
|
priceOwnerCompanyName = entity.PriceOwnerCompanyName,
|
|
|
priceOwnerMaerskPartyCode = entity.PriceOwnerCompanyPartyCode,
|
|
|
priceOwnerContactName = entity.PriceOwnerCompanyContact,
|
|
|
priceOwnerContactEmail = entity.PriceOwnerCompanyContactEmail,
|
|
|
earliestDepartureDate = entity.EarliestDepartureDate,
|
|
|
exportServiceMode = entity.ExportServiceMode,
|
|
|
importServiceMode = entity.ImportServiceMode,
|
|
|
placeOfReceiptCityName = entity.PlaceReceiptCity,
|
|
|
placeOfReceiptUnLocCode = entity.PlaceReceiptUnlocCode,
|
|
|
placeOfDeliveryCityName = entity.PlaceDeliveryCity,
|
|
|
placeOfDeliveryUnLocCode = entity.PlaceDeliveryUnlocCode,
|
|
|
originDepartureDateTimeLocal = entity.ETD,
|
|
|
destinationArrivalDateTimeLocal = entity.ETA,
|
|
|
vesselName = entity.Vessel,
|
|
|
carrierVesselCode = entity.VesselCode,
|
|
|
exportVoyageNumber = entity.Voyno,
|
|
|
transportMode = entity.TransportMode,
|
|
|
totalCargoWeight = entity.TotalCargoWeight,
|
|
|
noOfProbes = entity.NoOfProbes,
|
|
|
temperature = !string.IsNullOrWhiteSpace(entity.TempSet)?decimal.Parse(entity.TempSet):null,
|
|
|
ventilation = entity.Vent,
|
|
|
humidity = entity.Humidity,
|
|
|
commodityCodeType = entity.CommodityCodeType,
|
|
|
commodityCode = entity.GoodsCode,
|
|
|
commodityName = entity.GoodsName,
|
|
|
isReefer = entity.IsReefer,
|
|
|
cargoType = entity.CargoType,
|
|
|
placeOfReceiptCountryCode = entity.PlaceReceiptCountryCode,
|
|
|
placeOfDeliveryCountryCode = entity.PlaceDeliveryCountryCode,
|
|
|
EstSailingDays = entity.EstSailingDays,
|
|
|
priceReferenceId = entity.PriceReferenceId,
|
|
|
priceReferenceName = entity.PriceReferenceName,
|
|
|
priceOwnerReferenceId = entity.PriceOwnerReferenceId.HasValue? entity.PriceOwnerReferenceId.Value.ToString():"",
|
|
|
priceOwnerReference = entity.PriceOwnerReference,
|
|
|
priceOwnerReferenceName = entity.PriceOwnerReferenceName,
|
|
|
isShipperOwned = entity.IsShipperOwner,
|
|
|
isImportReturned = entity.IsImportReturned,
|
|
|
carrierProductId = entity.CarrierProductId,
|
|
|
isSendNoSchedule = entity.IsSendNoSchedule,
|
|
|
placeOfReceiptCountryName = entity.PlaceReceiptCountryName,
|
|
|
placeOfReceiptRegionName = entity.PlaceReceiptRegionName,
|
|
|
placeOfDeliveryCountryName = entity.PlaceDeliveryCountryName,
|
|
|
placeOfDeliveryRegionName = entity.PlaceDeliveryRegionName,
|
|
|
PId = entity.ShipRatePId,
|
|
|
MD5 = entity.ShipRateMD5,
|
|
|
bookingChannelTypeName = entity.BookingChannelType,
|
|
|
bookingChannelType = entity.BookingChannelTypeName,
|
|
|
carrierCollectionOriginGeoID = entity.PlaceReceiptGeoId,
|
|
|
carrierDeliveryDestinationGeoID = entity.PlaceDeliveryGeoId,
|
|
|
Status = entity.Status,
|
|
|
};
|
|
|
|
|
|
var ctnList = tenantDb.Queryable<SpaceBookingOrderCtn>().Where(a => a.RecordId == id && a.Deleted == false).ToList();
|
|
|
|
|
|
if (ctnList.Count > 0)
|
|
|
{
|
|
|
model.ctns = ctnList.Select(a => new MSKBookingCtnInfo
|
|
|
{
|
|
|
id = a.Id,
|
|
|
ctnCode = a.CtnCode,
|
|
|
carrierCtnCode = a.CarrierCtnCode,
|
|
|
ctnNum = a.CtnNum,
|
|
|
ctnName = a.CtnName,
|
|
|
ctnSufferWeight = a.CtnSufferWeight,
|
|
|
stuffingMeasurementType = a.StuffingMeasurementType,
|
|
|
stuffingMeasurementUnit = a.StuffingMeasurementUnit
|
|
|
}).ToList();
|
|
|
}
|
|
|
|
|
|
MSKAPISearchTransportSchedules selectedShipSchedule = null;
|
|
|
|
|
|
if (model.PId > 0)
|
|
|
{
|
|
|
var shipScheduleRecord = await tenantDb.Queryable<SpaceBookingOrderShipSchedule>()
|
|
|
.FirstAsync(a => a.ShipRatePid != null && a.ShipRatePid.Value == model.PId);
|
|
|
|
|
|
if (shipScheduleRecord != null)
|
|
|
{
|
|
|
selectedShipSchedule = JsonConvert.DeserializeObject<MSKAPISearchTransportSchedules>(shipScheduleRecord.ShipJson);
|
|
|
|
|
|
if (selectedShipSchedule != null)
|
|
|
{
|
|
|
model.selectedShipScheduleShow = GetShipScheduleShow(selectedShipSchedule);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return DataResult<MSKBookingDto>.Success(model);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 保存
|
|
|
/// <summary>
|
|
|
/// 保存
|
|
|
/// </summary>
|
|
|
/// <param name="model">请求订舱详情</param>
|
|
|
/// <returns>返回ID</returns>
|
|
|
public async Task<DataResult<long>> Save(MSKBookingDto model)
|
|
|
{
|
|
|
return await InnerSave(model);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 保存内部方法
|
|
|
/// <summary>
|
|
|
/// 保存内部方法
|
|
|
/// </summary>
|
|
|
/// <param name="model">API订舱详情</param>
|
|
|
/// <param name="isSendApi">是否发送API,true-发送需要校验状态;false-不校验状态</param>
|
|
|
/// <returns></returns>
|
|
|
private async Task<DataResult<long>> InnerSave(MSKBookingDto model, bool isSendApi = false)
|
|
|
{
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
|
|
|
string ctnStat = string.Empty;
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"获取请求马士基API订舱报文,JSON={JsonConvert.SerializeObject(model)}");
|
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
SpaceBookingOrderShipSchedule shipScheduleRecord = null;
|
|
|
|
|
|
MSKAPISearchTransportSchedules selectedShipSchedule = null;
|
|
|
|
|
|
if (model.PId > 0)
|
|
|
{
|
|
|
if (model.id.HasValue && model.id.Value > 0)
|
|
|
{
|
|
|
var recordId = model.id.Value;
|
|
|
|
|
|
shipScheduleRecord = await tenantDb.Queryable<SpaceBookingOrderShipSchedule>()
|
|
|
.FirstAsync(a => a.RecordId == recordId && a.ShipRatePid != null &&
|
|
|
a.ShipRatePid.Value == model.PId && a.Deleted == false);
|
|
|
}
|
|
|
|
|
|
if (shipScheduleRecord == null)
|
|
|
{
|
|
|
selectedShipSchedule = GetCacheShipSailingSchedule(model.PId.Value);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
selectedShipSchedule = JsonConvert.DeserializeObject<MSKAPISearchTransportSchedules>(shipScheduleRecord.ShipJson);
|
|
|
}
|
|
|
|
|
|
if (selectedShipSchedule == null)
|
|
|
throw new Exception("船期数据校验失败,请重新查询船期信息");
|
|
|
|
|
|
model.placeOfReceiptCountryName = selectedShipSchedule.originCountryName;
|
|
|
model.placeOfReceiptRegionName = selectedShipSchedule.originRegionName;
|
|
|
model.carrierCollectionOriginGeoID = selectedShipSchedule.originGeoId;
|
|
|
|
|
|
model.placeOfDeliveryCountryName = selectedShipSchedule.destinationCountryName;
|
|
|
model.placeOfDeliveryRegionName = selectedShipSchedule.destinationRegionName;
|
|
|
model.carrierDeliveryDestinationGeoID = selectedShipSchedule.destinationGeoId;
|
|
|
}
|
|
|
|
|
|
if (model.ctns != null && model.ctns.Count > 0)
|
|
|
{
|
|
|
ctnStat = string.Join(",", model.ctns.GroupBy(a => a.ctnName)
|
|
|
.Select(a => $"{a.Key}*{a.ToList().Sum(b => b.ctnNum.HasValue ? b.ctnNum.Value : 0)}").ToArray());
|
|
|
}
|
|
|
|
|
|
if (model.id.HasValue && model.id.Value > 0)
|
|
|
{
|
|
|
var oldInfo = tenantDb.Queryable<SpaceBookingOrder>()
|
|
|
.First(a => a.Id == model.id);
|
|
|
|
|
|
//预订舱数据不存在或已作废
|
|
|
if (oldInfo == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingRecordDeletedOrNoExists)));
|
|
|
|
|
|
if (oldInfo.Status == "SUCC")
|
|
|
{
|
|
|
//预订舱数据已发送成功,不能重复发送
|
|
|
if (isSendApi)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingBeSendNotRepeat)));
|
|
|
|
|
|
//预订舱数据已发送成功,不能修改
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingBeSendNotModify)));
|
|
|
}
|
|
|
|
|
|
|
|
|
#region 赋值
|
|
|
SpaceBookingOrder entity = new SpaceBookingOrder
|
|
|
{
|
|
|
CarrierCode = model.carrierCode,
|
|
|
vesselCarrierCode = model.vesselCarrierCode,
|
|
|
CarrierId = model.carrierId,
|
|
|
PriceReference = model.priceReference,
|
|
|
ProductCode = model.productCode,
|
|
|
Sender = model.sender,
|
|
|
BookedByCompanyName = model.bookedByCompanyName,
|
|
|
BookedByCompanyPartyCode = model.bookedByMaerskPartyCode,
|
|
|
BookedByCompanyContact = model.bookedByCompanyContactName,
|
|
|
BookedByCompanyContactEmail = model.bookedByCompanyContactEmail,
|
|
|
IsBookingPartOwnPrice = model.isBookingPartOwnPrice,
|
|
|
PriceOwnerCompanyName = model.priceOwnerCompanyName,
|
|
|
PriceOwnerCompanyPartyCode = model.priceOwnerMaerskPartyCode,
|
|
|
PriceOwnerCompanyContact = model.priceOwnerContactName,
|
|
|
PriceOwnerCompanyContactEmail = model.priceOwnerContactEmail,
|
|
|
EarliestDepartureDate = model.earliestDepartureDate,
|
|
|
ExportServiceMode = model.exportServiceMode,
|
|
|
ImportServiceMode = model.importServiceMode,
|
|
|
PlaceReceiptCity = model.placeOfReceiptCityName,
|
|
|
PlaceReceiptUnlocCode = model.placeOfReceiptUnLocCode,
|
|
|
PlaceDeliveryCity = model.placeOfDeliveryCityName,
|
|
|
PlaceDeliveryUnlocCode = model.placeOfDeliveryUnLocCode,
|
|
|
ETD = model.originDepartureDateTimeLocal,
|
|
|
ETA = model.destinationArrivalDateTimeLocal,
|
|
|
Vessel = model.vesselName,
|
|
|
VesselCode = model.carrierVesselCode,
|
|
|
Voyno = model.exportVoyageNumber,
|
|
|
TransportMode = model.transportMode,
|
|
|
TotalCargoWeight = model.totalCargoWeight,
|
|
|
NoOfProbes = model.noOfProbes,
|
|
|
TempSet = model.temperature.HasValue ? model.temperature.Value.ToString() : "",
|
|
|
Vent = model.ventilation,
|
|
|
Humidity = model.humidity,
|
|
|
CommodityCodeType = model.commodityCodeType,
|
|
|
GoodsCode = model.commodityCode,
|
|
|
GoodsName = model.commodityName,
|
|
|
CargoType = model.cargoType,
|
|
|
PlaceReceiptCountryCode = model.placeOfReceiptCountryCode,
|
|
|
PlaceDeliveryCountryCode = model.placeOfDeliveryCountryCode,
|
|
|
EstSailingDays = model.EstSailingDays,
|
|
|
PriceReferenceId = model.priceReferenceId,
|
|
|
PriceReferenceName = model.priceReferenceName,
|
|
|
PriceOwnerReferenceId = !string.IsNullOrWhiteSpace(model.priceOwnerReferenceId) ? long.Parse(model.priceOwnerReferenceId) : null,
|
|
|
PriceOwnerReference = model.priceOwnerReference,
|
|
|
PriceOwnerReferenceName = model.priceOwnerReferenceName,
|
|
|
IsReefer = model.isReefer,
|
|
|
IsShipperOwner = model.isShipperOwned,
|
|
|
IsImportReturned = model.isImportReturned,
|
|
|
CarrierProductId = model.carrierProductId,
|
|
|
IsSendNoSchedule = model.isSendNoSchedule,
|
|
|
PlaceReceiptCountryName = model.placeOfReceiptCountryName,
|
|
|
PlaceReceiptRegionName = model.placeOfReceiptRegionName,
|
|
|
PlaceDeliveryRegionName = model.placeOfDeliveryRegionName,
|
|
|
PlaceDeliveryCountryName = model.userPlaceOfDeliveryCountryName,
|
|
|
ShipRatePId = model.PId,
|
|
|
ShipRateMD5 = model.MD5,
|
|
|
PlaceReceiptGeoId = model.carrierCollectionOriginGeoID,
|
|
|
PlaceDeliveryGeoId = model.carrierDeliveryDestinationGeoID,
|
|
|
};
|
|
|
#endregion
|
|
|
|
|
|
entity.Id = model.id.Value;
|
|
|
entity.UpdateTime = nowDate;
|
|
|
entity.UpdateBy = long.Parse(user.UserId);
|
|
|
entity.UpdateUserName = user.UserName;
|
|
|
entity.CtnStat = ctnStat;
|
|
|
entity.BookingChannelType = "CON_API";
|
|
|
entity.BookingChannelTypeName = "合约订舱";
|
|
|
|
|
|
await tenantDb.Updateable<SpaceBookingOrder>(entity).IgnoreColumns(x => new
|
|
|
{
|
|
|
x.CreateTime,
|
|
|
x.CreateBy,
|
|
|
x.CreateUserName,
|
|
|
x.BookingReference,
|
|
|
x.BookingId,
|
|
|
x.RequestAcknowledgementId,
|
|
|
x.Status,
|
|
|
//x.TenantId,
|
|
|
x.IsRecvBC,
|
|
|
x.LstRecvBCDate,
|
|
|
x.IsRecvBKCancel,
|
|
|
x.LstRecvBKCancelDate
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
|
if (model.ctns != null && model.ctns.Count > 0)
|
|
|
{
|
|
|
var ctnEntityList = tenantDb.Queryable<SpaceBookingOrderCtn>()
|
|
|
.Where(a => a.RecordId == entity.Id && a.Deleted == false).ToList();
|
|
|
|
|
|
model.ctns.ForEach(ctn =>
|
|
|
{
|
|
|
if (ctn.id.HasValue && ctn.id.Value > 0)
|
|
|
{
|
|
|
if (ctnEntityList.Any(x => x.Id == ctn.id.Value))
|
|
|
{
|
|
|
ctnEntityList.Remove(ctnEntityList.FirstOrDefault(x => x.Id == ctn.id.Value));
|
|
|
}
|
|
|
|
|
|
//更新
|
|
|
var ctnEntity = new SpaceBookingOrderCtn
|
|
|
{
|
|
|
CtnCode = ctn.ctnCode,
|
|
|
CtnName = ctn.ctnName,
|
|
|
CtnNum = ctn.ctnNum,
|
|
|
CtnSufferWeight = ctn.ctnSufferWeight.HasValue?(int)ctn.ctnSufferWeight.Value:0
|
|
|
};
|
|
|
|
|
|
ctnEntity.Id = ctn.id.Value;
|
|
|
ctnEntity.RecordId = entity.Id;
|
|
|
ctnEntity.UpdateTime = nowDate;
|
|
|
ctnEntity.UpdateBy = long.Parse(user.UserId);
|
|
|
ctnEntity.UpdateUserName = user.UserName;
|
|
|
|
|
|
tenantDb.Updateable<SpaceBookingOrderCtn>(ctnEntity).IgnoreColumns(x => new
|
|
|
{
|
|
|
x.CreateBy,
|
|
|
x.CreateUserName,
|
|
|
x.CreateTime,
|
|
|
//x.TenantId,
|
|
|
x.StuffingMeasurementType,
|
|
|
x.StuffingMeasurementUnit,
|
|
|
x.CtnSufferWeight
|
|
|
}).ExecuteCommand();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var ctnEntity = new SpaceBookingOrderCtn
|
|
|
{
|
|
|
CtnCode = ctn.ctnCode,
|
|
|
CtnName = ctn.ctnName,
|
|
|
CtnNum = ctn.ctnNum.Value,
|
|
|
CtnSufferWeight = (int)ctn.ctnSufferWeight.Value,
|
|
|
};
|
|
|
|
|
|
ctnEntity.RecordId = entity.Id;
|
|
|
ctnEntity.CreateTime = nowDate;
|
|
|
ctnEntity.UpdateTime = nowDate;
|
|
|
ctnEntity.CreateBy = long.Parse(user.UserId);
|
|
|
ctnEntity.CreateUserName = user.UserName;
|
|
|
ctnEntity.StuffingMeasurementType = "WEIGHT";
|
|
|
ctnEntity.StuffingMeasurementUnit = "KGS";
|
|
|
|
|
|
tenantDb.Insertable<SpaceBookingOrderCtn>(ctnEntity).ExecuteCommand();
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (ctnEntityList.Count > 0)
|
|
|
{
|
|
|
ctnEntityList.ForEach(async ctn =>
|
|
|
{
|
|
|
ctn.Deleted = true;
|
|
|
ctn.DeleteTime = nowDate;
|
|
|
ctn.DeleteBy = long.Parse(user.UserId);
|
|
|
ctn.UpdateUserName = user.UserName;
|
|
|
|
|
|
await tenantDb.Updateable<SpaceBookingOrderCtn>(ctn).UpdateColumns(x => new
|
|
|
{
|
|
|
x.Deleted,
|
|
|
x.DeleteTime,
|
|
|
x.DeleteBy,
|
|
|
x.UpdateUserName
|
|
|
}).ExecuteCommandAsync();
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (shipScheduleRecord == null)
|
|
|
{
|
|
|
if (model.PId > 0 && selectedShipSchedule != null)
|
|
|
{
|
|
|
shipScheduleRecord = new SpaceBookingOrderShipSchedule
|
|
|
{
|
|
|
Id = SnowFlakeSingle.Instance.NextId(),
|
|
|
RecordId = model.id.Value,
|
|
|
ShipRatePid = selectedShipSchedule.PId,
|
|
|
ShipRateMD5 = selectedShipSchedule.MD5,
|
|
|
ShipJson = Newtonsoft.Json.JsonConvert.SerializeObject(selectedShipSchedule),
|
|
|
CreateTime = nowDate,
|
|
|
UpdateTime = nowDate,
|
|
|
CreateBy = long.Parse(user.UserId),
|
|
|
UpdateUserName = user.UserName
|
|
|
};
|
|
|
|
|
|
await tenantDb.Insertable<SpaceBookingOrderShipSchedule>(shipScheduleRecord).ExecuteCommandAsync();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return DataResult<long>.Success(model.id.Value);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
#region 赋值
|
|
|
SpaceBookingOrder entity = new SpaceBookingOrder {
|
|
|
CarrierCode = model.carrierCode,
|
|
|
vesselCarrierCode = model.vesselCarrierCode,
|
|
|
CarrierId = model.carrierId,
|
|
|
PriceReference = model.priceReference,
|
|
|
ProductCode = model.productCode,
|
|
|
Sender = model.sender,
|
|
|
BookedByCompanyName = model.bookedByCompanyName,
|
|
|
BookedByCompanyPartyCode = model.bookedByMaerskPartyCode,
|
|
|
BookedByCompanyContact = model.bookedByCompanyContactName,
|
|
|
BookedByCompanyContactEmail = model.bookedByCompanyContactEmail,
|
|
|
IsBookingPartOwnPrice = model.isBookingPartOwnPrice,
|
|
|
PriceOwnerCompanyName = model.priceOwnerCompanyName,
|
|
|
PriceOwnerCompanyPartyCode = model.priceOwnerMaerskPartyCode,
|
|
|
PriceOwnerCompanyContact = model.priceOwnerContactName,
|
|
|
PriceOwnerCompanyContactEmail = model.priceOwnerContactEmail,
|
|
|
EarliestDepartureDate = model.earliestDepartureDate,
|
|
|
ExportServiceMode = model.exportServiceMode,
|
|
|
ImportServiceMode = model.importServiceMode,
|
|
|
PlaceReceiptCity = model.placeOfReceiptCityName,
|
|
|
PlaceReceiptUnlocCode = model.placeOfReceiptUnLocCode,
|
|
|
PlaceDeliveryCity = model.placeOfDeliveryCityName,
|
|
|
PlaceDeliveryUnlocCode = model.placeOfDeliveryUnLocCode,
|
|
|
ETD = model.originDepartureDateTimeLocal,
|
|
|
ETA = model.destinationArrivalDateTimeLocal,
|
|
|
Vessel = model.vesselName,
|
|
|
VesselCode = model.carrierVesselCode,
|
|
|
Voyno = model.exportVoyageNumber,
|
|
|
TransportMode = model.transportMode,
|
|
|
TotalCargoWeight = model.totalCargoWeight,
|
|
|
NoOfProbes = model.noOfProbes,
|
|
|
TempSet = model.temperature.HasValue? model.temperature.Value.ToString():"",
|
|
|
Vent = model.ventilation,
|
|
|
Humidity = model.humidity,
|
|
|
CommodityCodeType = model.commodityCodeType,
|
|
|
GoodsCode = model.commodityCode,
|
|
|
GoodsName = model.commodityName,
|
|
|
CargoType = model.cargoType,
|
|
|
PlaceReceiptCountryCode = model.placeOfReceiptCountryCode,
|
|
|
PlaceDeliveryCountryCode = model.placeOfDeliveryCountryCode,
|
|
|
EstSailingDays = model.EstSailingDays,
|
|
|
PriceReferenceId = model.priceReferenceId,
|
|
|
PriceReferenceName = model.priceReferenceName,
|
|
|
PriceOwnerReferenceId = !string.IsNullOrWhiteSpace(model.priceOwnerReferenceId)?long.Parse(model.priceOwnerReferenceId):null,
|
|
|
PriceOwnerReference = model.priceOwnerReference,
|
|
|
PriceOwnerReferenceName = model.priceOwnerReferenceName,
|
|
|
IsReefer = model.isReefer,
|
|
|
IsShipperOwner = model.isShipperOwned,
|
|
|
IsImportReturned = model.isImportReturned,
|
|
|
CarrierProductId = model.carrierProductId,
|
|
|
IsSendNoSchedule = model.isSendNoSchedule,
|
|
|
PlaceReceiptCountryName = model.placeOfReceiptCountryName,
|
|
|
PlaceReceiptRegionName = model.placeOfReceiptRegionName,
|
|
|
PlaceDeliveryRegionName = model.placeOfDeliveryRegionName,
|
|
|
PlaceDeliveryCountryName = model.userPlaceOfDeliveryCountryName,
|
|
|
ShipRatePId = model.PId,
|
|
|
ShipRateMD5 = model.MD5,
|
|
|
PlaceReceiptGeoId = model.carrierCollectionOriginGeoID,
|
|
|
PlaceDeliveryGeoId = model.carrierDeliveryDestinationGeoID,
|
|
|
};
|
|
|
#endregion
|
|
|
|
|
|
entity.CreateTime = nowDate;
|
|
|
entity.UpdateTime = nowDate;
|
|
|
entity.CreateBy = long.Parse(user.UserId);
|
|
|
entity.CreateUserName = user.UserName;
|
|
|
|
|
|
entity.Status = "TEMP";
|
|
|
entity.StatusName = "暂存";
|
|
|
entity.CtnStat = ctnStat;
|
|
|
entity.BookingChannelType = "CON_API";
|
|
|
entity.BookingChannelTypeName = "合约订舱";
|
|
|
|
|
|
await tenantDb.Insertable<SpaceBookingOrder>(entity).ExecuteReturnEntityAsync();
|
|
|
|
|
|
if (model.ctns != null && model.ctns.Count > 0)
|
|
|
{
|
|
|
model.ctns.ForEach(ctn =>
|
|
|
{
|
|
|
var ctnEntity = new SpaceBookingOrderCtn
|
|
|
{
|
|
|
CtnCode = ctn.ctnCode,
|
|
|
CtnName = ctn.ctnName,
|
|
|
CtnNum = ctn.ctnNum.Value,
|
|
|
CtnSufferWeight = (int)ctn.ctnSufferWeight.Value,
|
|
|
};
|
|
|
|
|
|
ctnEntity.RecordId = entity.Id;
|
|
|
ctnEntity.CreateTime = nowDate;
|
|
|
ctnEntity.UpdateTime = nowDate;
|
|
|
ctnEntity.CreateBy = long.Parse(user.UserId);
|
|
|
ctnEntity.CreateUserName = user.UserName;
|
|
|
ctnEntity.StuffingMeasurementType = "WEIGHT";
|
|
|
ctnEntity.StuffingMeasurementUnit = "KGS";
|
|
|
|
|
|
tenantDb.Insertable<SpaceBookingOrderCtn>(ctnEntity).ExecuteCommand();
|
|
|
});
|
|
|
}
|
|
|
|
|
|
if (shipScheduleRecord == null)
|
|
|
{
|
|
|
if (model.PId > 0 && selectedShipSchedule != null)
|
|
|
{
|
|
|
shipScheduleRecord = new SpaceBookingOrderShipSchedule
|
|
|
{
|
|
|
Id = SnowFlakeSingle.Instance.NextId(),
|
|
|
RecordId = entity.Id,
|
|
|
ShipRatePid = selectedShipSchedule.PId,
|
|
|
ShipRateMD5 = selectedShipSchedule.MD5,
|
|
|
ShipJson = Newtonsoft.Json.JsonConvert.SerializeObject(selectedShipSchedule),
|
|
|
CreateTime = nowDate,
|
|
|
UpdateTime = nowDate,
|
|
|
CreateBy = long.Parse(user.UserId),
|
|
|
CreateUserName = user.UserName
|
|
|
};
|
|
|
|
|
|
await tenantDb.Insertable<SpaceBookingOrderShipSchedule>(shipScheduleRecord).ExecuteCommandAsync();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//只有船期发生变化时才重新写入新的船期记录
|
|
|
if (model.PId != shipScheduleRecord.ShipRatePid.Value)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"MSK CON id={model.id} 换了船期 原记录:{selectedShipSchedule.PId} 新记录:{model.PId} 作废原船期,插入新船期");
|
|
|
|
|
|
shipScheduleRecord.Deleted = true;
|
|
|
shipScheduleRecord.DeleteTime = nowDate;
|
|
|
shipScheduleRecord.DeleteBy = long.Parse(user.UserId);
|
|
|
shipScheduleRecord.UpdateUserName = user.UserName;
|
|
|
|
|
|
await tenantDb.Updateable<SpaceBookingOrderShipSchedule>(shipScheduleRecord).UpdateColumns(x => new
|
|
|
{
|
|
|
x.Deleted,
|
|
|
x.DeleteTime,
|
|
|
x.DeleteBy,
|
|
|
x.UpdateTime
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
|
shipScheduleRecord = new SpaceBookingOrderShipSchedule
|
|
|
{
|
|
|
Id = SnowFlakeSingle.Instance.NextId(),
|
|
|
RecordId = model.id.Value,
|
|
|
ShipRatePid = selectedShipSchedule.PId,
|
|
|
ShipRateMD5 = selectedShipSchedule.MD5,
|
|
|
ShipJson = Newtonsoft.Json.JsonConvert.SerializeObject(selectedShipSchedule),
|
|
|
CreateTime = nowDate,
|
|
|
UpdateTime = nowDate,
|
|
|
CreateBy = long.Parse(user.UserId),
|
|
|
CreateUserName = user.UserName
|
|
|
};
|
|
|
|
|
|
await tenantDb.Insertable<SpaceBookingOrderShipSchedule>(shipScheduleRecord).ExecuteCommandAsync();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"MSK CON id={model.id} 船期没变化 model.PId={model.PId} shipScheduleRecord.SHIP_RATE_PID={shipScheduleRecord.ShipRatePid.Value}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return DataResult<long>.Success(entity.Id);
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 删除
|
|
|
/// <summary>
|
|
|
/// 删除
|
|
|
/// </summary>
|
|
|
/// <param name="id">请求订舱ID</param>
|
|
|
/// <returns></returns>
|
|
|
public async Task<DataResult<string>> Delete(long id)
|
|
|
{
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
var info = tenantDb.Queryable<SpaceBookingOrder>().First(a => a.Id == id);
|
|
|
|
|
|
//删除失败,业务信息不存在或已作废
|
|
|
if (info == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIDeleteFailNoExists)));
|
|
|
|
|
|
info.Deleted = true;
|
|
|
info.DeleteTime = DateTime.Now;
|
|
|
info.DeleteBy = long.Parse(user.UserId);
|
|
|
info.DeleteUserName = user.UserName;
|
|
|
|
|
|
await tenantDb.Updateable<SpaceBookingOrder>(info).UpdateColumns(x => new
|
|
|
{
|
|
|
x.Deleted,
|
|
|
x.DeleteTime,
|
|
|
x.DeleteBy
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
|
return DataResult<string>.Success("成功");
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 批量发送
|
|
|
/// <summary>
|
|
|
/// 批量发送
|
|
|
/// </summary>
|
|
|
/// <param name="ids">马士基API订舱ID组</param>
|
|
|
/// <returns>返回执行结果消息</returns>
|
|
|
public async Task<DataResult<string>> BatchSend(long[] ids)
|
|
|
{
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
var list = await tenantDb.Queryable<SpaceBookingOrder>()
|
|
|
.Where(a => ids.Contains(a.Id)).ToListAsync();
|
|
|
|
|
|
if (list.Count != ids.Length)
|
|
|
throw new Exception("订舱数据获取失败,请确认选中的记录是否存在");
|
|
|
|
|
|
List<string> msgList = new List<string>();
|
|
|
int totalNum = list.Count;
|
|
|
int succNum = 0;
|
|
|
int failNum = 0;
|
|
|
|
|
|
if (list.Count > 1)
|
|
|
{
|
|
|
list.ForEach(entity =>
|
|
|
{
|
|
|
MSKBookingResultDto result = null;
|
|
|
try
|
|
|
{
|
|
|
var model = GetInfo(entity.Id).GetAwaiter().GetResult().Data;
|
|
|
result = InnerSendMSKBooking(model, entity.Id, false).GetAwaiter().GetResult()?.Data;
|
|
|
|
|
|
succNum++;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
msgList.Add(ex.Message);
|
|
|
|
|
|
failNum++;
|
|
|
}
|
|
|
|
|
|
Thread.Sleep(1000);
|
|
|
});
|
|
|
|
|
|
msgList.Add($"共计{totalNum} 条 成功{succNum}条 失败:{failNum}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
MSKBookingResultDto result = null;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var entity = list.FirstOrDefault();
|
|
|
|
|
|
var model = GetInfo(entity.Id).GetAwaiter().GetResult()?.Data;
|
|
|
result = InnerSendMSKBooking(model, entity.Id, false).GetAwaiter().GetResult()?.Data;
|
|
|
|
|
|
if (result.succ)
|
|
|
return DataResult<string>.Success("成功");
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
msgList.Add(ex.Message);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return DataResult<string>.Success(string.Join("#", msgList.ToArray()));
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 批量复制
|
|
|
/// <summary>
|
|
|
/// 批量复制
|
|
|
/// </summary>
|
|
|
/// <param name="model">马士基API批量复制指定数据</param>
|
|
|
/// <returns>返回执行结果消息</returns>
|
|
|
public async Task<DataResult<string>> BatchCopy(MSKAPIBookingCopyDto model)
|
|
|
{
|
|
|
//复制数量不能小于1
|
|
|
if (model.copyNum < 1)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICopyLowNum)));
|
|
|
|
|
|
//复制数量不能大于1000
|
|
|
if (model.copyNum > 1000)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICopyLimitNum)));
|
|
|
|
|
|
//请求的操作类型不能为空
|
|
|
if (string.IsNullOrWhiteSpace(model.opType))
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOpTypeNull)));
|
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
var entity = await tenantDb.Queryable<SpaceBookingOrder>().FirstAsync(a => a.Id == model.originalId);
|
|
|
|
|
|
//预订舱数据不存在或已作废
|
|
|
if (entity == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingRecordDeletedOrNoExists)));
|
|
|
|
|
|
var ctnList = tenantDb.Queryable<SpaceBookingOrderCtn>()
|
|
|
.Where(a => a.RecordId == model.originalId && a.Deleted == false).ToList();
|
|
|
|
|
|
var shipScheduleRecord = await tenantDb.Queryable<SpaceBookingOrderShipSchedule>()
|
|
|
.FirstAsync(a => a.RecordId == model.originalId && a.ShipRatePid != null &&
|
|
|
a.ShipRatePid.Value == entity.ShipRatePId && a.Deleted == false);
|
|
|
|
|
|
var numArg = "".PadLeft(model.copyNum, '0').Select((a, idx) => idx + 1).ToList();
|
|
|
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, "获取到批量复制功能");
|
|
|
|
|
|
//如果是指定的编辑信息需要先把编辑数据同步到实体类,再进行复制
|
|
|
if (model.opType == "copy_edit")
|
|
|
{
|
|
|
string ctnStat = string.Empty;
|
|
|
|
|
|
if (model.bookingDto.ctns != null && model.bookingDto.ctns.Count > 0)
|
|
|
{
|
|
|
ctnStat = string.Join(",", model.bookingDto.ctns.GroupBy(a => a.ctnName)
|
|
|
.Select(a => $"{a.Key}*{a.ToList().Sum(b => b.ctnNum.HasValue ? b.ctnNum.Value : 0)}").ToArray());
|
|
|
|
|
|
ctnList = new List<SpaceBookingOrderCtn>();
|
|
|
|
|
|
model.bookingDto.ctns.ForEach(ctn =>
|
|
|
{
|
|
|
var ctnEntity = new SpaceBookingOrderCtn
|
|
|
{
|
|
|
CtnCode = ctn.ctnCode,
|
|
|
CtnName = ctn.ctnName,
|
|
|
CtnNum = ctn.ctnNum.HasValue? ctn.ctnNum.Value:0,
|
|
|
CtnSufferWeight = (int)ctn.ctnSufferWeight.Value,
|
|
|
};
|
|
|
|
|
|
ctnEntity.CreateTime = nowDate;
|
|
|
ctnEntity.UpdateTime = nowDate;
|
|
|
ctnEntity.CreateBy = long.Parse(user.UserId);
|
|
|
ctnEntity.CreateUserName = user.UserName;
|
|
|
ctnEntity.StuffingMeasurementType = "WEIGHT";
|
|
|
ctnEntity.StuffingMeasurementUnit = "KGS";
|
|
|
|
|
|
ctnList.Add(ctnEntity);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
entity = model.bookingDto.Adapt<SpaceBookingOrder>();
|
|
|
|
|
|
entity.CreateTime = nowDate;
|
|
|
entity.UpdateTime = nowDate;
|
|
|
entity.CreateBy = long.Parse(user.UserId);
|
|
|
entity.CreateUserName = user.UserName;
|
|
|
entity.Status = "TEMP";
|
|
|
entity.StatusName = "暂存";
|
|
|
entity.CtnStat = ctnStat;
|
|
|
entity.BookingChannelType = "CON_API";
|
|
|
entity.BookingChannelTypeName = "合约订舱";
|
|
|
}
|
|
|
|
|
|
int totalNum = 0;
|
|
|
|
|
|
foreach (var a in numArg)
|
|
|
{
|
|
|
var copyEntity = entity.Adapt<SpaceBookingOrder>();
|
|
|
|
|
|
copyEntity.Id = 0;
|
|
|
copyEntity.CreateTime = nowDate;
|
|
|
copyEntity.CreateBy = long.Parse(user.UserId);
|
|
|
copyEntity.CreateUserName = user.UserName;
|
|
|
copyEntity.UpdateTime = nowDate;
|
|
|
copyEntity.Status = "TEMP";
|
|
|
copyEntity.StatusName = "暂存";
|
|
|
copyEntity.IsRecvBC = false;
|
|
|
copyEntity.LstRecvBCDate = null;
|
|
|
copyEntity.IsRecvBKCancel = false;
|
|
|
copyEntity.LstRecvBKCancelDate = null;
|
|
|
copyEntity.RequestAcknowledgementId = null;
|
|
|
copyEntity.BookingReference = null;
|
|
|
copyEntity.Notes = $"COPY NO.{a} BY={model.originalId}";
|
|
|
|
|
|
await tenantDb.Insertable<SpaceBookingOrder>(copyEntity).ExecuteReturnEntityAsync();
|
|
|
|
|
|
totalNum++;
|
|
|
|
|
|
if (ctnList.Count > 0)
|
|
|
{
|
|
|
ctnList.ForEach(async ctn =>
|
|
|
{
|
|
|
var ctnEntity = ctn.Adapt<SpaceBookingOrderCtn>();
|
|
|
|
|
|
ctnEntity.Id = 0;
|
|
|
ctnEntity.RecordId = copyEntity.Id;
|
|
|
ctnEntity.CreateTime = nowDate;
|
|
|
ctnEntity.UpdateTime = nowDate;
|
|
|
ctnEntity.CreateBy = long.Parse(user.UserId);
|
|
|
ctnEntity.CreateUserName = user.UserName;
|
|
|
|
|
|
await tenantDb.Insertable<SpaceBookingOrderCtn>(ctnEntity).ExecuteReturnEntityAsync();
|
|
|
});
|
|
|
}
|
|
|
|
|
|
if (shipScheduleRecord != null)
|
|
|
{
|
|
|
var currShipScheduleRecord = shipScheduleRecord.Adapt<SpaceBookingOrderShipSchedule>();
|
|
|
|
|
|
currShipScheduleRecord.Id = 0;
|
|
|
currShipScheduleRecord.RecordId = copyEntity.Id;
|
|
|
currShipScheduleRecord.CreateTime = nowDate;
|
|
|
currShipScheduleRecord.UpdateTime = nowDate;
|
|
|
currShipScheduleRecord.CreateBy = long.Parse(user.UserId);
|
|
|
currShipScheduleRecord.CreateUserName = user.UserName;
|
|
|
|
|
|
await tenantDb.Insertable<SpaceBookingOrderShipSchedule>(currShipScheduleRecord).ExecuteCommandAsync();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return DataResult<string>.Success(JsonConvert.SerializeObject(new { Total = totalNum }));
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 同步BC状态(BC,Cancellation)
|
|
|
/// <summary>
|
|
|
/// 同步BC状态(BC,Cancellation)
|
|
|
/// </summary>
|
|
|
/// <param name="mblno">提单号</param>
|
|
|
/// <param name="tenantId">租户ID</param>
|
|
|
/// <param name="opTypeName">操作类型 BC-同步BC状态 Cancellation-同步取消状态</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
public async Task<DataResult<MSKBookingResultDto>> SyncBCInfo(string mblno, long tenantId, string opTypeName = "BookingConfirmation")
|
|
|
{
|
|
|
MSKBookingResultDto result = new MSKBookingResultDto();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
var model = await tenantDb.Queryable<SpaceBookingOrder>()
|
|
|
.Where(a => a.BookingReference == mblno && a.Deleted == false)
|
|
|
.FirstAsync();
|
|
|
|
|
|
//预订舱数据不存在或已作废
|
|
|
if (model == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIOrderDeletedOrNoExists)));
|
|
|
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
|
|
|
if (opTypeName == "BookingConfirmation")
|
|
|
{
|
|
|
model.IsRecvBC = true;
|
|
|
model.LstRecvBCDate = nowDate;
|
|
|
model.UpdateTime = nowDate;
|
|
|
model.UpdateBy = long.Parse(user.UserId);
|
|
|
model.UpdateUserName = user.UserName;
|
|
|
|
|
|
await tenantDb.Updateable<SpaceBookingOrder>(model).UpdateColumns(x => new
|
|
|
{
|
|
|
x.IsRecvBC,
|
|
|
x.LstRecvBCDate,
|
|
|
x.UpdateTime,
|
|
|
x.UpdateBy,
|
|
|
x.UpdateUserName
|
|
|
}).ExecuteCommandAsync();
|
|
|
}
|
|
|
else if (opTypeName == "Cancellation")
|
|
|
{
|
|
|
model.IsRecvBKCancel = true;
|
|
|
model.LstRecvBKCancelDate = nowDate;
|
|
|
model.UpdateTime = nowDate;
|
|
|
model.UpdateBy = long.Parse(user.UserId);
|
|
|
model.UpdateUserName = user.UserName;
|
|
|
|
|
|
await tenantDb.Updateable<SpaceBookingOrder>(model).UpdateColumns(x => new
|
|
|
{
|
|
|
x.IsRecvBKCancel,
|
|
|
x.LstRecvBKCancelDate,
|
|
|
x.UpdateTime,
|
|
|
x.UpdateBy,
|
|
|
x.UpdateUserName
|
|
|
}).ExecuteCommandAsync();
|
|
|
}
|
|
|
|
|
|
result.succ = true;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
result.succ = false;
|
|
|
result.msg = $"同步BC状态异常,原因:{ex.Message}";
|
|
|
}
|
|
|
|
|
|
return DataResult<MSKBookingResultDto>.Success(result);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 同步BC状态(BC,Cancellation)作为任务台执行模块
|
|
|
/// </summary>
|
|
|
/// <param name="dataContext">数据上下文</param>
|
|
|
public async Task<DataResult<MSKBookingResultDto>> SyncBCInfoTask(TaskFlowDataContext dataContext)
|
|
|
{
|
|
|
var messageInfo = dataContext.Get<TaskManageOrderMessageInfo>(TaskFlowDataNameConst.TaskManageOrderMessageInfo);
|
|
|
if (messageInfo == null)
|
|
|
{
|
|
|
throw new ArgumentNullException($"缺少参数:{TaskFlowDataNameConst.TaskManageOrderMessageInfo}");
|
|
|
}
|
|
|
if (string.IsNullOrEmpty(messageInfo.Main?.BCInfo?.MBLNo))
|
|
|
{
|
|
|
throw new ArgumentNullException($"提单号为空");
|
|
|
}
|
|
|
|
|
|
var tenantId = long.Parse(user.TenantId);
|
|
|
//var tenantId = dataContext.Get<long>(TaskFlowDataNameConst.TenantId);
|
|
|
//if (tenantId == 0)
|
|
|
//{
|
|
|
// throw new ArgumentNullException($"缺少参数:TenantId");
|
|
|
//}
|
|
|
|
|
|
string type = messageInfo.Main.TaskType switch
|
|
|
{
|
|
|
TaskBaseTypeEnum.BC => "BookingConfirmation",
|
|
|
TaskBaseTypeEnum.CANCELLATION => "Cancellation",
|
|
|
_ => throw new NotImplementedException()
|
|
|
};
|
|
|
|
|
|
var result = await this.SyncBCInfo(messageInfo.Main.BCInfo.MBLNo, tenantId, type);
|
|
|
Logger.Log(NLog.LogLevel.Info, $"入库完BC,自动推送状态到API订舱列表 mblno={messageInfo.Main.BCInfo.MBLNo} synRlt={JsonConvert.SerializeObject(result)}");
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 批量复制前调取校验预警
|
|
|
/// <summary>
|
|
|
/// 批量复制前调取校验预警
|
|
|
/// </summary>
|
|
|
/// <param name="model">马士基API批量复制指定数据</param>
|
|
|
/// <returns>返回提示信息</returns>
|
|
|
public async Task<DataResult<string>> CheckWarningBatchCopy(MSKAPIBookingCopyDto model)
|
|
|
{
|
|
|
/*
|
|
|
主要校验内容
|
|
|
1、如果待复制的单子里还有“托运人自己的集装箱”或“进口退货集装箱或者其他三角集运”需要做提醒是否继续复制。
|
|
|
2、如果是opType=copy_edit-复制使用提交的编辑信息,需要判断原始货物标志变化是否继续。
|
|
|
3、如果是冷冻处理的提示是否继续。
|
|
|
*/
|
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
var entity = await tenantDb.Queryable<SpaceBookingOrder>().FirstAsync(a => a.Id == model.originalId);
|
|
|
|
|
|
if (entity != null)
|
|
|
{
|
|
|
List<string> msgList = new List<string>();
|
|
|
|
|
|
if (entity.IsShipperOwner || (model.bookingDto != null && model.bookingDto.isShipperOwned))
|
|
|
{
|
|
|
//含有指定托运人自己的集装箱
|
|
|
msgList.Add(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIIncludeShipperOwner)));
|
|
|
}
|
|
|
|
|
|
if (entity.IsImportReturned || (model.bookingDto != null && model.bookingDto.isImportReturned))
|
|
|
{
|
|
|
//含有指定进口退货集装箱或者其他三角集运
|
|
|
msgList.Add(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIIncludeImportReturned)));
|
|
|
}
|
|
|
|
|
|
if (entity.IsReefer || (model.bookingDto != null && model.bookingDto.isReefer))
|
|
|
{
|
|
|
//含有是冷冻处理
|
|
|
msgList.Add(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIIncludeReefer)));
|
|
|
}
|
|
|
|
|
|
if (model.bookingDto != null && model.bookingDto.cargoType != entity.CargoType)
|
|
|
{
|
|
|
//货物标志与被复制货物标志不一致
|
|
|
msgList.Add(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPICargoTypeWithCopyDiff)));
|
|
|
}
|
|
|
|
|
|
if (msgList.Count > 0)
|
|
|
throw new Exception(string.Join(",", msgList.ToArray()));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return DataResult<string>.Success(string.Empty);
|
|
|
}
|
|
|
|
|
|
return DataResult<string>.Success("校验成功");
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 批量发送API前调取校验预警
|
|
|
/// <summary>
|
|
|
/// 批量发送API前调取校验预警
|
|
|
/// </summary>
|
|
|
/// <param name="ids">马士基API订舱ID组</param>
|
|
|
/// <returns>返回提示信息</returns>
|
|
|
public async Task<DataResult<string>> CheckWarningBatchSend(long[] ids)
|
|
|
{
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
var list = await tenantDb.Queryable<SpaceBookingOrder>().Where(a => ids.Contains(a.Id)).ToListAsync();
|
|
|
|
|
|
if (list.Count > 0)
|
|
|
{
|
|
|
List<string> msgList = new List<string>();
|
|
|
|
|
|
if (list.Any(a => a.IsShipperOwner))
|
|
|
{
|
|
|
//含有指定托运人自己的集装箱
|
|
|
msgList.Add(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIIncludeShipperOwner)));
|
|
|
}
|
|
|
|
|
|
if (list.Any(a => a.IsImportReturned))
|
|
|
{
|
|
|
//含有指定进口退货集装箱或者其他三角集运
|
|
|
msgList.Add(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIIncludeImportReturned)));
|
|
|
}
|
|
|
|
|
|
if (list.Any(a => a.IsReefer))
|
|
|
{
|
|
|
//含有是冷冻处理
|
|
|
msgList.Add(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIIncludeReefer)));
|
|
|
}
|
|
|
|
|
|
if (msgList.Count > 0)
|
|
|
throw new Exception(string.Join(",", msgList.ToArray()));
|
|
|
}
|
|
|
|
|
|
return DataResult<string>.Success("校验成功");
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 获取初始化页面默认值
|
|
|
/// <summary>
|
|
|
/// 获取初始化页面默认值
|
|
|
/// </summary>
|
|
|
/// <returns>返回详情</returns>
|
|
|
public async Task<DataResult<MSKSPOTBookingInitDto>> GetInitInfo()
|
|
|
{
|
|
|
MSKSPOTBookingInitDto dto = null;
|
|
|
|
|
|
var webAccountConfig = codeThirdPartyService.GetCodeThirdPartyInfoWithCompany("MSKApi").GetAwaiter().GetResult()?.Data;
|
|
|
|
|
|
//未配置公司或个人的第三方账户维护-(MSK API合约),请联系管理员
|
|
|
if (webAccountConfig == null)
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIMSKConThirdPartySettingNull)));
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(webAccountConfig.RegistPartyCode)
|
|
|
|| string.IsNullOrWhiteSpace(webAccountConfig.RegistPartyName) || string.IsNullOrWhiteSpace(webAccountConfig.RegistContractName)
|
|
|
|| string.IsNullOrWhiteSpace(webAccountConfig.RegistContractEmail))
|
|
|
{
|
|
|
//第三方账户(MSK API合约)维护配置缺少(备案代码、备案全称、联系人、邮箱必填),请联系管理员
|
|
|
throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPIMSKConThirdPartySettingShortage)));
|
|
|
}
|
|
|
|
|
|
dto = new MSKSPOTBookingInitDto
|
|
|
{
|
|
|
bookedByMaerskPartyCode = webAccountConfig.RegistPartyCode,
|
|
|
bookedByCompanyName = webAccountConfig.RegistPartyName,
|
|
|
priceOwnerMaerskPartyCode = webAccountConfig.RegistPartyCode,
|
|
|
priceOwnerCompanyName = webAccountConfig.RegistPartyName,
|
|
|
bookedByCompanyContactName = webAccountConfig.RegistContractName,
|
|
|
bookedByCompanyContactEmail = webAccountConfig.RegistContractEmail,
|
|
|
priceOwnerContactName = webAccountConfig.RegistContractName,
|
|
|
priceOwnerContactEmail = webAccountConfig.RegistContractEmail,
|
|
|
};
|
|
|
|
|
|
return DataResult<MSKSPOTBookingInitDto>.Success(dto);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 马士基API订舱台账
|
|
|
/// <summary>
|
|
|
/// 马士基API订舱台账
|
|
|
/// </summary>
|
|
|
/// <param name="QuerySearch">查询条件</param>
|
|
|
/// <returns>返回台账列表</returns>
|
|
|
public async Task<DataResult<List<SpaceBookingPageDto>>> GetPageAsync(PageRequest QuerySearch)
|
|
|
{
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
//序列化查询条件
|
|
|
var whereList = db.ConfigQuery.Context.Utilities.JsonToConditionalModels(QuerySearch.QueryCondition);
|
|
|
|
|
|
var data = tenantDb.Queryable<SpaceBookingOrder>()
|
|
|
.Where(whereList)
|
|
|
.Select<SpaceBookingPageDto>().ToQueryPage(QuerySearch.PageCondition);
|
|
|
return data;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 获取预订舱途径选择
|
|
|
/// <summary>
|
|
|
/// 获取预订舱途径选择
|
|
|
/// </summary>
|
|
|
/// <returns>返回回执</returns>
|
|
|
public async Task<DataResult<List<string>>> GetBookingChannelSelectShow()
|
|
|
{
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
var rlt = await configService.GetConfig(CONST_MSK_API_CHANNEL_SHOW, long.Parse(user.TenantId), false);
|
|
|
|
|
|
if (rlt.Succeeded)
|
|
|
{
|
|
|
var list = rlt.Data.Value.Split(new char[] { ',' }).ToList();
|
|
|
|
|
|
return DataResult<List<string>>.Success(list);
|
|
|
}
|
|
|
|
|
|
return DataResult<List<string>>.FailedData(new List<string>());
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 批量设定定时订舱时间
|
|
|
/// <summary>
|
|
|
/// 批量设定定时订舱时间
|
|
|
/// </summary>
|
|
|
/// <param name="model">请求详情</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
public async Task<DataResult<string>> BatchSetupTimerBooking(MSKAPITimerBookingDto model)
|
|
|
{
|
|
|
/*
|
|
|
1、校验当前预订舱是否存在。
|
|
|
2、更新定时时间和设置。
|
|
|
3、判断当前定时是否已有记录,没有新增加定时。
|
|
|
4、
|
|
|
*/
|
|
|
string result = string.Empty;
|
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
var list = await tenantDb.Queryable<SpaceBookingOrder>()
|
|
|
.Where(a => model.ids.Contains(a.Id)).ToListAsync();
|
|
|
|
|
|
if (list.Count != model.ids.Length)
|
|
|
throw new Exception("订舱数据获取失败,请确认选中的记录是否存在");
|
|
|
|
|
|
StringBuilder msgBuilder = new StringBuilder();
|
|
|
|
|
|
foreach (var item in list)
|
|
|
{
|
|
|
var bookingOrder = GetInfo(item.Id).GetAwaiter().GetResult().Data;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
if (item.Status == "SUCC")
|
|
|
{
|
|
|
throw new Exception($"当前状态是已发送成功,不能重复发送");
|
|
|
}
|
|
|
|
|
|
ValidateMSKAPIData(bookingOrder);
|
|
|
|
|
|
var runInfo = tenantDb.Queryable<SpaceBookingOrderBookingJobRun>().Filter(null, true)
|
|
|
.First(a => a.RecordId == item.Id && a.Deleted == false);
|
|
|
|
|
|
if (runInfo != null)
|
|
|
{
|
|
|
throw new Exception($"当前记录已开始定时发送不能修改");
|
|
|
}
|
|
|
|
|
|
item.IsJob = true;
|
|
|
|
|
|
DateTime jobTime = DateTime.MinValue;
|
|
|
|
|
|
if (DateTime.TryParse(model.StartTime, out jobTime))
|
|
|
{
|
|
|
item.JobTime = jobTime;
|
|
|
}
|
|
|
|
|
|
item.TimerPlanId = model.TimerSchemeType;
|
|
|
item.TimerPlanName = string.Format(((MSKAPITimerSchemeTypeEnum)System.Enum.Parse(typeof(MSKAPITimerSchemeTypeEnum), model.TimerSchemeType)).GetDescription(), model.StartTime);
|
|
|
item.UpdateTime = DateTime.Now;
|
|
|
item.UpdateBy = long.Parse(user.UserId);
|
|
|
item.UpdateUserName = user.UserName;
|
|
|
|
|
|
tenantDb.Updateable<SpaceBookingOrder>(item).UpdateColumns(x => new
|
|
|
{
|
|
|
x.IsJob,
|
|
|
x.JobTime,
|
|
|
x.TimerPlanId,
|
|
|
x.TimerPlanName,
|
|
|
x.UpdateTime,
|
|
|
x.UpdateBy,
|
|
|
x.UpdateUserName
|
|
|
}).ExecuteCommand();
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
msgBuilder.Append(ex.Message);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var msg = msgBuilder.ToString();
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(msg))
|
|
|
throw new Exception(msg);
|
|
|
|
|
|
return DataResult<string>.Success(msg);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 获取定时订舱方案列表
|
|
|
/// <summary>
|
|
|
/// 获取定时订舱方案列表
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public async Task<DataResult<List<MSKAPITimerSchemeDto>>> GetTimerSchemeList()
|
|
|
{
|
|
|
List<MSKAPITimerSchemeDto> list = new List<MSKAPITimerSchemeDto>();
|
|
|
|
|
|
list.Add(new MSKAPITimerSchemeDto
|
|
|
{
|
|
|
code = MSKAPITimerSchemeTypeEnum.SpecificTimeDoOnce.ToString(),
|
|
|
name = MSKAPITimerSchemeTypeEnum.SpecificTimeDoOnce.GetDescription()
|
|
|
});
|
|
|
|
|
|
|
|
|
return DataResult<List<MSKAPITimerSchemeDto>>.Success(list);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 生成订舱订舱报告邮件并自动转发
|
|
|
/// <summary>
|
|
|
/// 生成订舱订舱报告邮件并自动转发
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public async Task<DataResult<string>> GenerateTimerReportEmail()
|
|
|
{
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
DateTime nowDate = DateTime.Now;
|
|
|
|
|
|
DateTime startDate = new DateTime(nowDate.Year, nowDate.Month, nowDate.Day);
|
|
|
|
|
|
var runList = tenantDb.Queryable<SpaceBookingOrderBookingJobRun>().Filter(null, true)
|
|
|
.Where(a => a.SendTime >= startDate && a.Deleted == false && a.IsSendReport == false).ToList();
|
|
|
|
|
|
if (runList.Count > 0)
|
|
|
{
|
|
|
var idList = runList.Select(a => a.RecordId).ToList();
|
|
|
|
|
|
var orderList = tenantDb.Queryable<SpaceBookingOrder>().Filter(null, true)
|
|
|
.Where(a => a.Deleted == false && idList.Contains(a.Id)).ToList();
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"获取相关预订舱记录,{string.Join(",", idList.ToArray())}");
|
|
|
|
|
|
orderList.GroupBy(a => a.CreateBy).ToList().ForEach(b =>
|
|
|
{
|
|
|
var nextJobTime = DateTime.MinValue;
|
|
|
|
|
|
var waitList = tenantDb.Queryable<SpaceBookingOrder>().Filter(null, true)
|
|
|
.Where(a => a.Deleted == false && a.JobTime != null && a.JobTime.Value >= nowDate && a.CreateBy == b.Key && a.Status == "TEMP").OrderBy(a => a.JobTime.Value).ToList();
|
|
|
|
|
|
if (waitList.Count > 0)
|
|
|
nextJobTime = waitList.FirstOrDefault().JobTime.Value;
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"获取完待订舱的记录");
|
|
|
|
|
|
var opUser = tenantDb.Queryable<SysUser>().Filter(null, true).First(a => a.Id == b.Key);
|
|
|
|
|
|
//提取当前公共邮箱的配置
|
|
|
CodeUserEmailRes publicMailAccount = _userEmailService.GetEmailSettings("PublicSend").GetAwaiter().GetResult().Data;
|
|
|
|
|
|
if (publicMailAccount == null)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"提取公共邮箱配置失败,请在用户邮箱账号管理增加配置显示名为PublicSend或者配置个人邮箱");
|
|
|
}
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"取完邮箱配置");
|
|
|
|
|
|
string emailHtml = string.Empty;
|
|
|
|
|
|
var currList = b.OrderBy(t => t.SendTime.Value).ToList();
|
|
|
|
|
|
//string templatePath = App.Configuration["EmailTemplateFilePath"];
|
|
|
|
|
|
//var opt = App.GetOptions<BookingAttachOptions>();
|
|
|
//var dirAbs = opt.basePath;
|
|
|
//if (string.IsNullOrEmpty(dirAbs))
|
|
|
//{
|
|
|
// dirAbs = App.WebHostEnvironment.WebRootPath;
|
|
|
//}
|
|
|
string dirAbs = string.Empty;
|
|
|
//string templatePath = string.Empty;
|
|
|
|
|
|
string templatePath = $"{dirAbs}\\MSKAPITimerReportTemplate.html";
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"取完模板");
|
|
|
|
|
|
string baseHtml = File.ReadAllText(templatePath);
|
|
|
|
|
|
baseHtml = baseHtml.Replace("#ReportTime#", nowDate.ToString("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
|
baseHtml = baseHtml.Replace("#total#", currList.Count.ToString());
|
|
|
baseHtml = baseHtml.Replace("#succ#", currList.Count(x => x.Status == "SUCC").ToString());
|
|
|
baseHtml = baseHtml.Replace("#failure#", currList.Count(x => x.Status == "FAILURE").ToString());
|
|
|
|
|
|
if (waitList.Count > 0)
|
|
|
{
|
|
|
baseHtml = baseHtml.Replace("#wait#", currList.Count().ToString());
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
baseHtml = baseHtml.Replace("#wait#", "0");
|
|
|
}
|
|
|
|
|
|
if (nextJobTime != DateTime.MinValue)
|
|
|
{
|
|
|
baseHtml = baseHtml.Replace("#NextTime#", nextJobTime.ToString("yyyy-MM-dd HH:mm"));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
baseHtml = baseHtml.Replace("#NextTime#", "");
|
|
|
}
|
|
|
|
|
|
HtmlDocument html = new HtmlDocument();
|
|
|
html.LoadHtml(baseHtml);
|
|
|
|
|
|
var tableNode = html.DocumentNode.SelectSingleNode(".//table[@id='show-table']");
|
|
|
|
|
|
if (tableNode != null)
|
|
|
{
|
|
|
for (int i = 0; i < currList.Count; i++)
|
|
|
{
|
|
|
StringBuilder tableBuilder = new StringBuilder();
|
|
|
|
|
|
tableBuilder.Append($"<tr><td>{i + 1}</td><td>{(currList[i].SendTime.HasValue ? currList[i].SendTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : "")}</td>");
|
|
|
tableBuilder.Append($"<td>{currList[i].StatusName}</td><td>{currList[i].BookingReference}</td><td>{currList[i].PlaceReceiptCity}</td><td>{currList[i].PlaceDeliveryCity}</td>");
|
|
|
tableBuilder.Append($"<td>{currList[i].CtnStat}</td><td>{(currList[i].ETD.HasValue ? currList[i].ETD.Value.ToString("yyyy-MM-dd HH:mm") : "")}</td>");
|
|
|
tableBuilder.Append($"<td>{(currList[i].TotalCargoWeight.HasValue ? currList[i].TotalCargoWeight.Value.ToString() : "")}</td><td>{currList[i].PriceReference}</td>");
|
|
|
tableBuilder.Append($"<td>{(currList[i].IsRecvBC ? "1" : "")}</td><td>{(currList[i].IsRecvBKCancel ? "1" : "")}</td><td>{(currList[i].JobTime.HasValue ? currList[i].JobTime.Value.ToString("yyyy-MM-dd HH:mm") : "")}</td></tr>");
|
|
|
|
|
|
tableNode.ChildNodes.Add(HtmlNode.CreateNode(tableBuilder.ToString()));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
emailHtml = html.DocumentNode.OuterHtml;
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"填充完邮件正文");
|
|
|
|
|
|
EmailApiUserDefinedDto emailApiUserDefinedDto = new EmailApiUserDefinedDto
|
|
|
{
|
|
|
SendTo = opUser.Email,
|
|
|
CCTo = "",
|
|
|
Title = $"马士基API定时订舱统计报告 {nowDate.ToString("yyyy-MM-dd HH:mm:ss")}",
|
|
|
Body = emailHtml,
|
|
|
Account = publicMailAccount.MailAccount?.Trim(),
|
|
|
Password = publicMailAccount.Password?.Trim(),
|
|
|
Server = publicMailAccount.SmtpServer?.Trim(),
|
|
|
Port = publicMailAccount.SmtpPort.HasValue ? publicMailAccount.SmtpPort.Value : 465,
|
|
|
UseSSL = publicMailAccount.SmtpSSL.HasValue ? publicMailAccount.SmtpSSL.Value : true,
|
|
|
Attaches = new List<AttachesInfo>()
|
|
|
};
|
|
|
List<EmailApiUserDefinedDto> emailList = new List<EmailApiUserDefinedDto>();
|
|
|
|
|
|
var emailUrl = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "email_api_url" && x.TenantId == 1288018625843826688).First().Value;
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"获取完邮件API地址");
|
|
|
|
|
|
if (emailUrl == null)
|
|
|
Logger.Log(NLog.LogLevel.Info, "字典未配置 url_set->email_api_url 请联系管理员");
|
|
|
|
|
|
emailList.Add(emailApiUserDefinedDto);
|
|
|
|
|
|
//string strJoin = System.IO.File.ReadAllText(filePath);
|
|
|
|
|
|
DateTime bDate = DateTime.Now;
|
|
|
|
|
|
string res = string.Empty;
|
|
|
|
|
|
try
|
|
|
{
|
|
|
var jsonBody = JsonConvert.SerializeObject(emailList);
|
|
|
|
|
|
res = RequestHelper.Post(jsonBody, emailUrl);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"发送邮件异常:{ex.Message}");
|
|
|
}
|
|
|
|
|
|
DateTime eDate = DateTime.Now;
|
|
|
TimeSpan ts = eDate.Subtract(bDate);
|
|
|
var timeDiff = ts.TotalMilliseconds;
|
|
|
|
|
|
Logger.Log(NLog.LogLevel.Info, $"发送邮件返回:{JsonConvert.SerializeObject(res)}");
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(res))
|
|
|
{
|
|
|
var respObj = JsonConvert.DeserializeAnonymousType(res, new
|
|
|
{
|
|
|
Success = false,
|
|
|
Message = string.Empty,
|
|
|
Code = -9999,
|
|
|
});
|
|
|
|
|
|
if (respObj.Success)
|
|
|
{
|
|
|
var updateList = currList.Join(runList, l => l.Id, r => r.RecordId, (l, r) =>
|
|
|
{
|
|
|
return r;
|
|
|
}).ToList();
|
|
|
|
|
|
foreach (var update in updateList)
|
|
|
{
|
|
|
update.IsSendReport = true;
|
|
|
update.ReportTime = DateTime.Now;
|
|
|
|
|
|
tenantDb.Updateable<SpaceBookingOrderBookingJobRun>(update).UpdateColumns(x => new
|
|
|
{
|
|
|
x.IsSendReport,
|
|
|
x.ReportTime
|
|
|
}).ExecuteCommand();
|
|
|
};
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Logger.Log(NLog.LogLevel.Info, $"自动订舱报告失败,没有可执行的记录");
|
|
|
}
|
|
|
|
|
|
return DataResult<string>.SuccessMsg("");
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 批量取消定时订舱时间
|
|
|
/// <summary>
|
|
|
/// 批量取消定时订舱时间
|
|
|
/// </summary>
|
|
|
/// <param name="ids">马士基API订舱ID组</param>
|
|
|
/// <returns>返回回执</returns>
|
|
|
public async Task<DataResult<string>> BatchCancelTimerBooking(long[] ids)
|
|
|
{
|
|
|
string result = string.Empty;
|
|
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
|
|
var list = await tenantDb.Queryable<SpaceBookingOrder>()
|
|
|
.Where(a => ids.Contains(a.Id)).ToListAsync();
|
|
|
|
|
|
if (list.Count != ids.Length)
|
|
|
throw new Exception("订舱数据获取失败,请确认选中的记录是否存在");
|
|
|
|
|
|
StringBuilder msgBuilder = new StringBuilder();
|
|
|
|
|
|
foreach (var item in list)
|
|
|
{
|
|
|
var bookingOrder = GetInfo(item.Id).GetAwaiter().GetResult();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
if (item.Status == "SUCC")
|
|
|
{
|
|
|
throw new Exception($"当前状态是已发送成功,不能取消");
|
|
|
}
|
|
|
|
|
|
var runInfo = tenantDb.Queryable<SpaceBookingOrderBookingJobRun>().Filter(null, true)
|
|
|
.First(a => a.RecordId == item.Id && a.Deleted == false);
|
|
|
|
|
|
if (runInfo != null)
|
|
|
{
|
|
|
throw new Exception($"当前记录已开始定时发送不能修改");
|
|
|
}
|
|
|
|
|
|
item.IsJob = false;
|
|
|
item.JobTime = null;
|
|
|
|
|
|
item.TimerPlanId = null;
|
|
|
item.TimerPlanName = null;
|
|
|
|
|
|
item.UpdateTime = DateTime.Now;
|
|
|
item.UpdateBy = long.Parse(user.UserId);
|
|
|
item.UpdateUserName = user.UserName;
|
|
|
|
|
|
tenantDb.Updateable<SpaceBookingOrder>(item).UpdateColumns(x => new
|
|
|
{
|
|
|
x.IsJob,
|
|
|
x.JobTime,
|
|
|
x.TimerPlanId,
|
|
|
x.TimerPlanName,
|
|
|
x.UpdateTime,
|
|
|
x.UpdateBy,
|
|
|
x.UpdateUserName
|
|
|
}).ExecuteCommand();
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
msgBuilder.Append(ex.Message);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var msg = msgBuilder.ToString();
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(msg))
|
|
|
throw new Exception(msg);
|
|
|
|
|
|
return DataResult<string>.Success(msg);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 发送马士基订舱请求
|
|
|
/// <summary>
|
|
|
/// 发送马士基订舱请求
|
|
|
/// </summary>
|
|
|
/// <param name="id">请求订舱ID</param>
|
|
|
/// <returns>返回检索结果</returns>
|
|
|
public async Task<DataResult<MSKBookingResultDto>> SendMSKBookingById(long id)
|
|
|
{
|
|
|
var model = GetInfo(id).GetAwaiter().GetResult().Data;
|
|
|
|
|
|
if (model != null)
|
|
|
{
|
|
|
if (model.Status == "SUCC")
|
|
|
{
|
|
|
return DataResult<MSKBookingResultDto>.FailedData(new MSKBookingResultDto
|
|
|
{
|
|
|
succ = false,
|
|
|
msg = "订舱数据已发送成功,不能重复发送"
|
|
|
});
|
|
|
}
|
|
|
|
|
|
return await InnerSendMSKBooking(model, id, false);
|
|
|
}
|
|
|
return DataResult<MSKBookingResultDto>.FailedData(new MSKBookingResultDto
|
|
|
{
|
|
|
succ = false,
|
|
|
msg = "预订舱信息不存在"
|
|
|
});
|
|
|
}
|
|
|
#endregion
|
|
|
}
|
|
|
}
|