You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2454 lines
114 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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 NLog.Fluent;
using Fasterflect;
using AutoMapper;
using System.Reflection;
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 Logger Logger = LogManager.GetCurrentClassLogger();
private readonly IMappingCtnService mappingCtnService;
private readonly IRedisService redisService;
private readonly IConfigService configService;
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>();
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.carrierId))
//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>>();
//var ctnCodeMappingList = _cache.GetAllMappingCtn().GetAwaiter().GetResult().ToList();
//if (ctnCodeMappingList.Count > 0)
//ctnCodeMappingList = ctnCodeMappingList.Where(x => x.CarrierCode == "MSK" && x.Module == "BOOK_MSK_API").ToList();
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 Oops.Bah($"查询船期错误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 Oops.Bah($"查询船期错误pid={model.PId} 预计离港日期departureDate 格式解析错误");
}
//ETA
if (detail.arrivalDateTime.HasValue)
{
currDto.destinationArrivalDateTimeLocal = detail.arrivalDateTime.Value.ToString("yyyy-MM-ddTHH:mm:ss");
}
else
{
//throw Oops.Bah($"查询船期错误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 Oops.Oh($"未配置相应的箱型对应{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.LogInformation($"开始请求MSK API订舱JSON={jsonBody}");
//var rlt = await sendUrl.SetBody(jsonBody).PostAsStringAsync();
var rlt = RequestHelper.Post(jsonBody, sendUrl);
//_logger.LogInformation($"开始请求MSK API订舱返回结果 JSON={JSON.Serialize(rlt)}");
if (!string.IsNullOrWhiteSpace(rlt))
{
try
{
resultInfo = JsonConvert.DeserializeObject<MSKAPIBookingResultDto>(rlt);
}
catch (Exception ex)
{
//_logger.LogInformation($"请求MSK API订舱异常原因{ex.Message}");
//throw Oops.Bah($"请求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 Oops.Bah(resultInfo.msg);
}
result.succ = true;
}
catch (Exception ex)
{
//_logger.LogError($"MSK API订舱异常req={JSON.Serialize(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 Oops.Bah($"当前订舱合同号是非订舱方合约持约方不能和订舱方ID信息一样请根据实际情况填写");
}
//当前订舱合同号是非订舱方合约,持约方公司名称不能和订舱方公司名称信息一样,请根据实际情况填写
if (model.bookedByCompanyName.Equals(model.priceOwnerCompanyName))
{
//throw Oops.Bah($"当前订舱合同号是非订舱方合约,持约方公司名称不能和订舱方公司名称信息一样,请根据实际情况填写");
}
}
else
{
//当前订舱合同号是订舱方合约持约方ID必需和订舱方ID信息一致请根据实际情况填写
if (!model.bookedByMaerskPartyCode.Equals(model.priceOwnerMaerskPartyCode))
{
//throw Oops.Bah($"当前订舱合同号是订舱方合约持约方ID必需和订舱方ID信息一致请根据实际情况填写");
}
//当前订舱合同号是订舱方合约,持约方名称必需和订舱方名称信息一致,请根据实际情况填写
if (!model.bookedByCompanyName.Equals(model.priceOwnerCompanyName))
{
//throw Oops.Bah($"当前订舱合同号是订舱方合约,持约方名称必需和订舱方名称信息一致,请根据实际情况填写");
}
}
}
#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,
};
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">是否发送APItrue-发送需要校验状态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 Oops.Oh("船期数据校验失败,请重新查询船期信息");
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 Oops.Oh("订舱数据获取失败,请确认选中的记录是否存在");
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 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();
});
}
}
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.UpdatedUserName = UserManager.Name;
await tenantDb.Updateable<SpaceBookingOrder>(model).UpdateColumns(x => new
{
x.IsRecvBC,
x.LstRecvBCDate,
x.UpdateTime,
x.UpdateBy,
//x.UpdatedUserName
}).ExecuteCommandAsync();
}
else if (opTypeName == "Cancellation")
{
model.IsRecvBKCancel = true;
model.LstRecvBKCancelDate = nowDate;
model.UpdateTime = nowDate;
model.UpdateBy = long.Parse(user.UserId);
//model.UpdatedUserName = UserManager.Name;
await tenantDb.Updateable<SpaceBookingOrder>(model).UpdateColumns(x => new
{
x.IsRecvBKCancel,
x.LstRecvBKCancelDate,
x.UpdateTime,
x.UpdateBy,
//x.UpdatedUserName
}).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
}
}