From 48ada643125d01af7b9618768144e94fb32c6817 Mon Sep 17 00:00:00 2001 From: jianghaiqing Date: Wed, 10 Jul 2024 16:18:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Constants/MultiLanguageConst.cs | 33 + .../Code/Dtos/CodeThirdPartyRes.cs | 26 + .../DS.WMS.Core/Code/Entity/CodeThirdParty.cs | 30 + .../Code/Interface/ICodeThirdPartyService.cs | 9 +- .../Code/Method/CodeThirdPartyService.cs | 32 + .../MSKAPISearchPoint2PointScheduleDto.cs | 149 ++ ...SKAPISearchPoint2PointScheduleResultDto.cs | 390 +++ .../SpaceBooking/SpaceBookingMSKAPIService.cs | 2236 +++++++++++++++++ ds-wms-service/DS.WMS.OpApi/appsettings.json | 5 + 9 files changed, 2908 insertions(+), 2 deletions(-) create mode 100644 ds-wms-service/DS.WMS.Core/Op/Dtos/SpaceBooking/MSKAPISearchPoint2PointScheduleDto.cs create mode 100644 ds-wms-service/DS.WMS.Core/Op/Dtos/SpaceBooking/MSKAPISearchPoint2PointScheduleResultDto.cs create mode 100644 ds-wms-service/DS.WMS.Core/Op/Method/SpaceBooking/SpaceBookingMSKAPIService.cs diff --git a/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs b/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs index a4f4db56..e5d9cc77 100644 --- a/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs +++ b/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs @@ -624,4 +624,37 @@ public static class MultiLanguageConst [Description("非原币申请必须指定原始币别")] public const string OriginalCurrencyCanNotNull = "OriginalCurrency_CanNot_Null"; #endregion + + #region 预订舱API + [Description("始发地不能为空")] + public const string SpaceBookingAPIOriginCityNameNull = "SpaceBK_API_OrigCityName_Null"; + + [Description("目的地不能为空")] + public const string SpaceBookingAPIDestCityNameNull = "SpaceBK_API_DestCityName_Null"; + + [Description("服务船公司不能为空")] + public const string SpaceBookingAPIVesselCarrierCodeNull = "SpaceBK_API_VesselCarrierCode_Null"; + + [Description("船公司代码不能为空")] + public const string SpaceBookingAPICarrierIdNull = "SpaceBK_API_CarrierId_Null"; + + [Description("预计离港日期不能为空")] + public const string SpaceBookingAPIETDNull = "SpaceBK_API_ETD_Null"; + + [Description("预计离港日期格式错误")] + public const string SpaceBookingAPIETDFormatError = "SpaceBK_API_ETD_Format_Error"; + + [Description("当前船公司{0} 未配置相应的请求接口")] + public const string SpaceBookingAPICarrierSearchShipNOConfig = "SpaceBK_API_Carrier_SearchShip_NoConfig"; + + [Description("未配置查询船期请求接口地址,请联系管理员")] + public const string SpaceBookingAPISearchShipNOConfig = "SpaceBK_API_SearchShip_NoConfig"; + + [Description("未配置第三方账户个人账户(MSKApi)")] + public const string SpaceBookingAPIThirdPartyNull = "SpaceBK_API_ThirdParty_Null"; + + [Description("请求MSK API查询船期异常,原因:{0}")] + public const string SpaceBookingAPISearchShipException = "SpaceBK_API_SearchShip_Exception"; + + #endregion } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Code/Dtos/CodeThirdPartyRes.cs b/ds-wms-service/DS.WMS.Core/Code/Dtos/CodeThirdPartyRes.cs index 6a376ae6..cdf14419 100644 --- a/ds-wms-service/DS.WMS.Core/Code/Dtos/CodeThirdPartyRes.cs +++ b/ds-wms-service/DS.WMS.Core/Code/Dtos/CodeThirdPartyRes.cs @@ -1,4 +1,5 @@ using DS.Module.Core; +using SqlSugar; namespace DS.WMS.Core.Code.Dtos; @@ -51,4 +52,29 @@ public class CodeThirdPartyRes /// 创建时间 /// public DateTime CreateTime { get; set; } + + /// + /// 是否为公司账号 true-是 false-否 + /// + public bool IsCompany { get; set; } + + /// + /// 备案代码 + /// + public string RegistPartyCode { get; set; } + + /// + /// 备案全称 + /// + public string RegistPartyName { get; set; } + + /// + /// 联系人 + /// + public string RegistContractName { get; set; } + + /// + /// 联系邮箱 + /// + public string RegistContractEmail { get; set; } } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Code/Entity/CodeThirdParty.cs b/ds-wms-service/DS.WMS.Core/Code/Entity/CodeThirdParty.cs index 08fbf8e3..ad646a43 100644 --- a/ds-wms-service/DS.WMS.Core/Code/Entity/CodeThirdParty.cs +++ b/ds-wms-service/DS.WMS.Core/Code/Entity/CodeThirdParty.cs @@ -50,4 +50,34 @@ public class CodeThirdParty : BaseModel /// [SugarColumn(ColumnDescription = "状态", DefaultValue = "0")] public StatusEnum? Status { get; set; } = StatusEnum.Enable; + + /// + /// 是否为公司账号 + /// + [SugarColumn(ColumnDescription = "是否为公司账号", DefaultValue = "0")] + public bool IsCompany { get; set; } = false; + + /// + /// 备案代码 + /// + [SugarColumn(ColumnDescription = "备案代码", IsNullable = true, Length = 50)] + public string RegistPartyCode { get; set; } + + /// + /// 备案全称 + /// + [SugarColumn(ColumnDescription = "备案全称", IsNullable = true, Length = 200)] + public string RegistPartyName { get; set; } + + /// + /// 联系人 + /// + [SugarColumn(ColumnDescription = "联系人", IsNullable = true, Length = 255)] + public string RegistContractName { get; set; } + + /// + /// 联系邮箱 + /// + [SugarColumn(ColumnDescription = "联系邮箱", IsNullable = true, Length = 150)] + public string RegistContractEmail { get; set; } } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Code/Interface/ICodeThirdPartyService.cs b/ds-wms-service/DS.WMS.Core/Code/Interface/ICodeThirdPartyService.cs index 98914003..bf2a44bf 100644 --- a/ds-wms-service/DS.WMS.Core/Code/Interface/ICodeThirdPartyService.cs +++ b/ds-wms-service/DS.WMS.Core/Code/Interface/ICodeThirdPartyService.cs @@ -27,6 +27,11 @@ public interface ICodeThirdPartyService /// /// DataResult GetCodeThirdPartyInfo(string id); - - + + /// + /// 获取第三方详情(优先取个人配置,如果没有默认取公司配置) + /// + /// 账号类型 + /// 返回第三方账户详情 + Task> GetCodeThirdPartyInfoWithCompany(string AccountType); } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Code/Method/CodeThirdPartyService.cs b/ds-wms-service/DS.WMS.Core/Code/Method/CodeThirdPartyService.cs index 50ed66dd..6f4826a0 100644 --- a/ds-wms-service/DS.WMS.Core/Code/Method/CodeThirdPartyService.cs +++ b/ds-wms-service/DS.WMS.Core/Code/Method/CodeThirdPartyService.cs @@ -78,5 +78,37 @@ namespace DS.WMS.Core.Code.Method .First(); return DataResult.Success(data, MultiLanguageConst.DataQuerySuccess); } + + #region 获取第三方详情(优先取个人配置,如果没有默认取公司配置) + /// + /// 获取第三方详情(优先取个人配置,如果没有默认取公司配置) + /// + /// 账号类型 + /// 返回第三方账户详情 + public async Task> GetCodeThirdPartyInfoWithCompany(string AccountType) + { + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + var data = await tenantDb.Queryable() + .Where(a => a.AccountType == AccountType && a.IsCompany == false && a.CreateBy == long.Parse(user.UserId)) + .Select() + .FirstAsync(); + + if (data == null) + { + data = await tenantDb.Queryable() + .Where(a => a.AccountType == AccountType && a.IsCompany == true) + .Select() + .FirstAsync(); + } + + if (data == null) + return DataResult.FailedData(data, MultiLanguageConst.DataQuerySuccess); + + + return DataResult.Success(data, MultiLanguageConst.DataQuerySuccess); + } + #endregion + } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/SpaceBooking/MSKAPISearchPoint2PointScheduleDto.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/SpaceBooking/MSKAPISearchPoint2PointScheduleDto.cs new file mode 100644 index 00000000..39ac8095 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/SpaceBooking/MSKAPISearchPoint2PointScheduleDto.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS.WMS.Core.Op.Dtos +{ + /// + /// 马士基点对点查询船期请求 + /// + public class MSKAPISearchPoint2PointScheduleDto + { + /// + /// 用户key(取用户配置) + /// + public string userKey { get; set; } + + /// + /// 用户secret + /// + public string userSecret { get; set; } + + /// + /// app的key + /// + public string mskAppKey { get; set; } + + /// + /// 运行环境 TEST-测试环境;PRODUCTION-生产环境 + /// + public string operatingEnvironment { get; set; } + + /// + /// 起始地的GEO ID + /// + public string carrierCollectionOriginGeoID { get; set; } + + /// + /// 目的地的GEO ID + /// + public string carrierDeliveryDestinationGeoID { get; set; } + + /// + /// 起始地国家代码(英文) + /// + public string collectionOriginCountryCode { get; set; } + + /// + /// 起始地城市名 + /// + public string collectionOriginCityName { get; set; } + + /// + /// 起始地五字码 + /// + public string collectionOriginUNLocationCode { get; set; } + + /// + /// 起始地区代码 + /// + public string collectionOriginUNRegionCode { get; set; } + + /// + /// 目的地国家代码 二字码 + /// + public string deliveryDestinationCountryCode { get; set; } + + /// + /// 目的地城市名称 + /// + public string deliveryDestinationCityName { get; set; } + + /// + /// 目的都五字码 + /// + public string deliveryDestinationUNLocationCode { get; set; } + + /// + /// 目的地区代码 + /// + public string deliveryDestinationUNRegionCode { get; set; } + + /// + /// 承运人代码(MAEU, SEAU, SEJJ, MCPU, MAEI) + /// + public string vesselOperatorCarrierCode { get; set; } + + /// + /// 货物类型代码(DRY, REEFER) + /// + public string cargoType { get; set; } + + /// + /// 箱型代码 + /// + public string ISOEquipmentCode { get; set; } + + /// + /// 箱重量 + /// + public string stuffingWeight { get; set; } + + /// + /// 重量单位(KGS, LBS) + /// + public string weightMeasurementUnit { get; set; } + + /// + /// 箱体积 + /// + public Nullable stuffingVolume { get; set; } + + /// + /// 体积单位(MTQ, FTQ) + /// + public string volumeMeasurementUnit { get; set; } + + /// + /// 出口服务代码(CY, SD, CFS) + /// + public string exportServiceMode { get; set; } + + /// + /// 进口服务代码(CY, SD, CFS) + /// + public string importServiceMode { get; set; } + + /// + /// 开始时间 + /// + public string startDate { get; set; } + + /// + /// 开始时间类型(D, A) + /// + public string startDateType { get; set; } + + /// + /// 请求产品信息的时间段(P1W, P2W, P3W, P4W, P5W, P6W, P7W, P8W) + /// + public string dateRange { get; set; } + + /// + /// 船舶标志代号 + /// + public string vesselFlagCode { get; set; } + } +} diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/SpaceBooking/MSKAPISearchPoint2PointScheduleResultDto.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/SpaceBooking/MSKAPISearchPoint2PointScheduleResultDto.cs new file mode 100644 index 00000000..9c27c3b6 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/SpaceBooking/MSKAPISearchPoint2PointScheduleResultDto.cs @@ -0,0 +1,390 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS.WMS.Core.Op.Dtos +{ + /// + /// 马士基点对点查询船期回执 + /// + public class MSKAPISearchPoint2PointScheduleResultDto + { + /// + /// 回执代码 + /// + public int code { get; set; } + + /// + /// 回执消息 + /// + public string msg { get; set; } + + /// + /// 回执代码 + /// + public List data { get; set; } + } + public class MSKAPISearchPoint2PointScheduleResultDataDto + { + /// + /// 产品id + /// + public string carrierProductId { get; set; } + + /// + /// 产品序号 + /// + public string carrierProductSequenceId { get; set; } + + /// + /// 产品的生效日期,格式为YYYY-MM-DD + /// + public string productValidFromDate { get; set; } + + /// + /// 产品的截止日期,格式为YYYY-MM-DD + /// + public string productValidToDate { get; set; } + + /// + /// 产品从原产地到目的地的链接数 + /// + public string numberOfProductLinks { get; set; } + + /// + /// 产品从原产地到目的地的链接数 + /// + public List transportSchedules { get; set; } + + } + + /// + /// 路线的详细信息 + /// + public class MSKAPISearchTransportSchedules + { + /// + /// 出发时间, ISO格式 + /// + public Nullable departureDateTime { get; set; } + + /// + /// 到达时间, ISO格式 + /// + public Nullable arrivalDateTime { get; set; } + + /// + /// 路线相关数据 + /// + public MSKAPISearchFacilities facilities { get; set; } + + /// + /// 头程船信息 + /// + public MSKDepartureVessel firstDepartureVessel { get; set; } + + /// + /// 通过的时间,以分钟为单位 + /// + public string transitTime { get; set; } + + /// + /// The details for the individual schedule + /// + public List transportLegs { get; set; } + + /// + /// 承运人代码(MAEU, SEAU, SEJJ, MCPU, MAEI) + /// + public string vesselOperatorCarrierCode { get; set; } + + //以下的字段是自己添加的不是船期返回的信息 + /// + /// 产品id + /// + public string carrierProductId { get; set; } + + /// + /// 产品序号 + /// + public string carrierProductSequenceId { get; set; } + + /// + /// 产品的生效日期,格式为YYYY-MM-DD + /// + public string productValidFromDate { get; set; } + + /// + /// 产品的截止日期,格式为YYYY-MM-DD + /// + public string productValidToDate { get; set; } + + /// + /// 产品从原产地到目的地的链接数 + /// + public string numberOfProductLinks { get; set; } + + /// + /// 船期MD5 + /// + public string MD5 { get; set; } + + /// + /// 主键ID + /// + public long PId { get; set; } + + /// + /// 起运地rkst代码 + /// + public string originRkstCode { get; set; } + + /// + /// 起运地geoID + /// + public string originGeoId { get; set; } + + /// + /// 起运地五子码 + /// + public string originUnLocCode { get; set; } + + /// + /// 起运地城市名 + /// + public string originCityName { get; set; } + + /// + /// 起运地区名 + /// + public string originRegionName { get; set; } + + /// + /// 起运地国家名 + /// + public string originCountryName { get; set; } + + /// + /// 目的地rkst代码 + /// + public string destinationRkstCode { get; set; } + + /// + /// 目的地geoID + /// + public string destinationGeoId { get; set; } + + /// + /// 目的地五子码 + /// + public string destinationUnLocCode { get; set; } + + /// + /// 目的地城市名 + /// + public string destinationCityName { get; set; } + + /// + /// 目的地区名 + /// + public string destinationRegionName { get; set; } + + /// + /// 目的地国家名 + /// + public string destinationCountryName { get; set; } + } + + /// + /// 路线相关数据 + /// + public class MSKAPISearchFacilities + { + /// + /// 出发地港口信息 + /// + public MSKAPISearchFacilitiesCityInfo collectionOrigin { get; set; } + + /// + /// 目的地港口信息 + /// + public MSKAPISearchFacilitiesCityInfo deliveryDestination { get; set; } + + + } + + /// + /// 城市信息 + /// + public class MSKAPISearchFacilitiesCityInfo + { + /// + /// 城市名 + /// + public string cityName { get; set; } + + /// + /// 地点的GEO ID + /// + public string carrierSiteGeoID { get; set; } + + /// + /// 地点的名称 + /// + public string locationName { get; set; } + + /// + /// 国家代码 + /// + public string countryCode { get; set; } + + /// + /// 位置类型 + /// + public string locationType { get; set; } + + /// + /// 五字码 + /// + public string UNLocationCode { get; set; } + + /// + /// 区代码 + /// + public string UNRegionCode { get; set; } + } + + /// + /// 头程船信息 + /// + public class MSKDepartureVessel + { + /// + /// IMO + /// + public string vesselIMONumber { get; set; } + + /// + /// 船名代码 + /// + public string carrierVesselCode { get; set; } + + /// + /// 船名 + /// + public string vesselName { get; set; } + } + + + public class MSKTransportLegInfo + { + /// + /// 出发时间, ISO格式 + /// + public Nullable departureDateTime { get; set; } + + /// + /// 到达时间, ISO格式 + /// + public Nullable arrivalDateTime { get; set; } + + /// + /// 路线相关数据 + /// + public MSKTransportLegInfoFacilities facilities { get; set; } + + /// + /// 航运信息 + /// + public MSKAPISearchTransportInfo transport { get; set; } + } + + /// + /// + /// + public class MSKTransportLegInfoFacilities + { + /// + /// 出发地港口信息 + /// + public MSKAPISearchFacilitiesCityInfo startLocation { get; set; } + + /// + /// 目的地港口信息 + /// + public MSKAPISearchFacilitiesCityInfo endLocation { get; set; } + } + + public class MSKAPISearchTransportInfo + { + /// + /// 运输方式 + /// + public string transportMode { get; set; } + + /// + /// 船信息 + /// + public MSKAPISearchVesselInfo vessel { get; set; } + + /// + /// 贸易航线名称 + /// + public string carrierTradeLaneName { get; set; } + + /// + /// 航次代码 + /// + public string carrierDepartureVoyageNumber { get; set; } + + /// + /// Indicator that defines the link as a port call offered as an inducement + /// + public string inducementLinkFlag { get; set; } + + /// + /// + /// + public string carrierServiceCode { get; set; } + + /// + /// 服务代码 + /// + public string carrierServiceName { get; set; } + + /// + /// 航行方向 + /// + public string linkDirection { get; set; } + + /// + /// RKST system Carrier Code as defined by A.P. Moller-Maersk A/S for the scheduled carrier + /// + public string carrierCode { get; set; } + + /// + /// Describes the type of route link + /// + public string routingType { get; set; } + } + + public class MSKAPISearchVesselInfo + { + /// + /// IMO号 + /// + public string vesselIMONumber { get; set; } + + /// + /// 内部船舶代码 + /// + public string carrierVesselCode { get; set; } + + /// + /// 船名 + /// + public string vesselName { get; set; } + } +} diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/SpaceBooking/SpaceBookingMSKAPIService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/SpaceBooking/SpaceBookingMSKAPIService.cs new file mode 100644 index 00000000..76b3e9ce --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Method/SpaceBooking/SpaceBookingMSKAPIService.cs @@ -0,0 +1,2236 @@ +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; + +namespace DS.WMS.Core.Op.Method +{ + public class SpaceBookingMSKAPIService: SpaceBookingMSKAPIService + { + 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(); + + const string CONST_MSK_API_Poing2P_SECD_URL = "MSKApiSailingSchedulePoint2Point"; + const long CONST_ADMIN_TENANTID = 1288018625843826688; + + public SpaceBookingMSKAPIService(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + db = _serviceProvider.GetRequiredService(); + user = _serviceProvider.GetRequiredService(); + saasService = _serviceProvider.GetRequiredService(); + codeThirdPartyService = _serviceProvider.GetRequiredService(); + + mskAPIUserKey = AppSetting.app(new string[] { "MSKAPIService", "SaveServiceProjectUrl" }); + mskAPIUserSecret = AppSetting.app(new string[] { "MSKAPIService", "CancelServiceProjectUrl" }); + mskAPIEnvironment = AppSetting.app(new string[] { "MSKAPIService", "GetServiceProjectListUrl" }); + } + + #region 检索海运船期详情 + /// + /// 检索海运船期详情 + /// + /// 请求船期详情 + /// 返回船期结果 + public async Task>> SearchShipSailingSchedule(QueryShipSailingScheduleDto model) + { + List list = new List(); + + /* + MSKApiSailingSchedulePoint2Point + */ + try + { + if (string.IsNullOrWhiteSpace(model.collectionOriginCityName)) + return DataResult>.Failed("始发地不能为空", MultiLanguageConst.SpaceBookingAPIOriginCityNameNull); + + if (string.IsNullOrWhiteSpace(model.deliveryDestinationCityName)) + return DataResult>.Failed("目的地不能为空", MultiLanguageConst.SpaceBookingAPIDestCityNameNull); + + if (string.IsNullOrWhiteSpace(model.vesselOperatorCarrierCode)) + return DataResult>.Failed("服务船公司不能为空", MultiLanguageConst.SpaceBookingAPIVesselCarrierCodeNull); + + if (string.IsNullOrWhiteSpace(model.carrierId)) + return DataResult>.Failed("船公司代码不能为空", MultiLanguageConst.SpaceBookingAPICarrierIdNull); + + if (string.IsNullOrWhiteSpace(model.startDate)) + return DataResult>.Failed("预计离港日期不能为空", MultiLanguageConst.SpaceBookingAPIETDNull); + + DateTime etd = DateTime.MinValue; + + if (!DateTime.TryParse(model.startDate, out etd)) + return DataResult>.Failed("预计离港日期格式错误", MultiLanguageConst.SpaceBookingAPIETDFormatError); + + string queryUrl = string.Empty; + + if (model.carrierId.Equals("MSK", StringComparison.OrdinalIgnoreCase)) + { + //调用小票服务 + queryUrl = db.Queryable().Filter(null, true).Where(x => x.Code == CONST_MSK_API_Poing2P_SECD_URL && x.TenantId == CONST_ADMIN_TENANTID).First()?.Value; + } + else + { + return DataResult> + .Failed(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.SpaceBookingAPISearchShipNOConfig)),model.carrierId)); + } + + if (string.IsNullOrWhiteSpace(queryUrl)) + return DataResult>.Failed("未配置查询船期请求接口地址,请联系管理员", MultiLanguageConst.SpaceBookingAPISearchShipNOConfig); + + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + var webAccountConfig = codeThirdPartyService.GetCodeThirdPartyInfoWithCompany("MSKApi").GetAwaiter().GetResult()?.Data; + + if (webAccountConfig == null) + return DataResult>.Failed("未配置第三方账户个人账户(MSKApi)", 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)); + + 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(rlt); + } + catch (Exception ex) + { + //_logger.LogInformation($"请求MSK API查询船期异常,原因:{ex.Message}"); + return DataResult>.Failed("请求MSK API查询船期异常,原因:", MultiLanguageConst.SpaceBookingAPISearchShipException); + } + } + + 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.LogError($"检索海运船期详情异常,req={JsonConvert.SerializeObject(model)} 原因:{ex.Message}"); + + //throw Oops.Bah($"检索海运船期详情失败,{ex.Message}"); + + return DataResult>.Failed("请求MSK API查询船期异常,原因:", MultiLanguageConst.SpaceBookingAPISearchShipException); + } + + return DataResult>.Success(list); + } + #endregion + + #region 组织返回船期数据 + /// + /// 组织返回船期数据 + /// + /// 查询的船期详情 + /// 返回显示的船期数据 + 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() + }; + + //ETD + if (model.departureDateTime.HasValue) + { + showDto.ETD = model.departureDateTime.Value; + } + else + { + throw Oops.Bah($"查询船期错误,预计离港日期查询为空"); + } + + //ETA + if (model.arrivalDateTime.HasValue) + { + showDto.ETA = model.arrivalDateTime.Value; + } + else + { + throw Oops.Bah($"查询船期错误,预计到港日期查询为空"); + } + + //计算预计天数 + 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(); + + 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 Oops.Bah($"查询船期错误,预计离港日期查询为空"); + } + + //ETA + if (b.arrivalDateTime.HasValue) + { + leg.ETA = b.arrivalDateTime.Value; + } + else + { + throw Oops.Bah($"查询船期错误,预计到港日期查询为空"); + } + + 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 缓存船期数据 + /// + /// 缓存船期数据 + /// + /// 船期查询结果明细 + /// 船期类型 MSKSPOT-马士基即期 + /// 返回主键ID + private async Task CacheShipSailingSchedule(MSKAPISearchTransportSchedules model, string busiType = "MSKCON") + { + /* + 1、按照船期明细缓存,并把ID作为缓存的KEY + 2、对数据进行JSON串行化的文本提取MD5 + 3、写入缓存,并返回ID + */ + var newModel = model.Adapt(); + + //newModel.priceID = null; + + var json = Newtonsoft.Json.JsonConvert.SerializeObject(newModel); + model.PId = YitIdHelper.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 (!_cache.Exists($"{shareKey}_{busiType}")) + { + await _cache.SetTimeoutAsync($"{shareKey}_{busiType}", Newtonsoft.Json.JsonConvert.SerializeObject(model), expireTimeSpan); + } + } + #endregion + + private MSKAPISearchTransportSchedules GetCacheShipSailingSchedule(long pid, string busiType = "MSKCON") + { + if (_cache.Exists($"{pid}_{busiType}")) + { + return _cache.Get($"{pid}_{busiType}"); + } + + return null; + } + + #region 发送马士基订舱请求 + /// + /// 发送马士基订舱请求 + /// + /// 请求订舱详情 + /// + [HttpPost("/BookingMSKAPI/SendMSKBooking")] + public async Task SendMSKBooking(MSKBookingDto model) + { + MSKBookingResultDto result = await InnerSendMSKBooking(model, 0); + return result; + } + #endregion + + #region 发送马士基订舱请求(内部方法) + /// + /// 发送马士基订舱请求(内部方法) + /// + /// 请求订舱详情 + /// 当前马士基订舱主键 + /// 是否默认保存 + /// + private async Task InnerSendMSKBooking(MSKBookingDto model, long currId, bool isDefaultSave = true) + { + MSKBookingResultDto result = new MSKBookingResultDto(); + + /* + MSKApiBooking + */ + try + { + if (string.IsNullOrWhiteSpace(model.carrierCode)) + throw Oops.Oh($"服务船公司不能为空"); + + if (string.IsNullOrWhiteSpace(model.carrierId)) + throw Oops.Oh("船公司代码不能为空"); + + string sendUrl = string.Empty; + + if (model.carrierId.Equals("MSK", StringComparison.OrdinalIgnoreCase)) + { + sendUrl = _cache.GetAllDictData().GetAwaiter().GetResult() + .FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == CONST_MSK_API_BOOKING_URL)?.Value; + } + else + { + throw Oops.Oh($"当前船公司 {model.carrierId} 未配置相应的请求接口"); + } + + if (string.IsNullOrWhiteSpace(sendUrl)) + throw Oops.Oh("未配置发送订舱请求接口地址,请联系管理员"); + + var webAccountConfig = _webAccountConfig + .GetAccountConfig("MSKApi", UserManager.UserId).GetAwaiter().GetResult(); + + if (webAccountConfig == null) + throw Oops.Oh("未配置个人账户,请先配置个人账户 类型-MSKApi"); + + //这里是校验必填项 + ValidateMSKAPIData(model); + + BookingDeliveryRecordShipSchedule shipScheduleRecord = null; + + MSKAPISearchTransportSchedules selectedShipSchedule = null; + + if (model.PId == 0) + throw Oops.Oh("船期信息不能为空,请重新检索船期"); + + if (model.PId > 0) + { + if (model.id.HasValue && model.id.Value > 0) + { + var recordId = model.id.Value; + + shipScheduleRecord = await _bookingDeliveryRecordShipScheduleRep.AsQueryable() + .FirstAsync(a => a.RECORD_ID == recordId && a.SHIP_RATE_PID != null && + a.SHIP_RATE_PID.Value == model.PId && a.IsDeleted == false); + } + + if (shipScheduleRecord == null) + { + selectedShipSchedule = GetCacheShipSailingSchedule(model.PId); + } + else + { + selectedShipSchedule = JSON.Deserialize(shipScheduleRecord.SHIP_JSON); + } + + if (selectedShipSchedule == null) + throw Oops.Oh("船期数据校验失败,请重新查询船期信息"); + } + + DateTime nowDate = DateTime.Now; + + var recordInfo = model.Adapt(); + var recordCtnList = model.ctns.Adapt>(); + + 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 = App.Configuration["MSKAPIDjyUserKey"], + userSecret = App.Configuration["MSKAPIDjyUserSecret"], + operatingEnvironment = App.Configuration["MSKAPIOPEnvironment"], + mskAppKey = webAccountConfig.Account, + mskAppSecret = webAccountConfig.Password, + 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.carrierCode, + 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(), + }, + } + }; + + //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 格式解析错误"); + } + + 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(); + + if (model.ctns != null && model.ctns.Count > 0) + { + model.ctns.ForEach(ctn => + { + 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() + }; + + 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(); + } + 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(); + + _logger.LogInformation($"开始请求MSK API订舱,返回结果 JSON={JSON.Serialize(rlt)}"); + + if (!string.IsNullOrWhiteSpace(rlt)) + { + try + { + resultInfo = JSON.Deserialize(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 = JSON.Deserialize(JSON.Serialize(resultInfo.data)); + } + + var entity = _bookingDeliveryRecordRep + .FirstOrDefault(a => a.Id == id); + + if (resultInfo != null && resultInfo.code == 200 + && resultData != null) + { + entity.REQUEST_ACKNOWLEDGEMENT_ID = resultData.requestAcknowledgementId; + entity.BOOKING_REFERENCE = resultData.bookingReference; + entity.STATUS = "SUCC"; + entity.STATUS_NAME = "发送成功"; + + await _bookingDeliveryRecordRep.AsUpdateable(entity).UpdateColumns(x => new + { + x.REQUEST_ACKNOWLEDGEMENT_ID, + x.BOOKING_REFERENCE, + x.STATUS, + x.STATUS_NAME + }).ExecuteCommandAsync(); + } + else + { + entity.STATUS = "FAILURE"; + entity.STATUS_NAME = "发送失败"; + entity.NOTES = resultInfo.msg.Length > 500 ? resultInfo.msg.Substring(0, 500) : resultInfo.msg; + + await _bookingDeliveryRecordRep.AsUpdateable(entity).UpdateColumns(x => new + { + x.STATUS, + x.STATUS_NAME, + 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 result; + } + #endregion + + #region 校验马士基API订舱必填项 + /// + /// 校验马士基API订舱必填项 + /// + /// + 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、预计离港日期必填 + */ + if (string.IsNullOrWhiteSpace(model.priceReference)) + throw Oops.Bah($"订舱合同惟一ID必填"); + + if (!Regex.IsMatch(model.priceReference, "[a-zA-Z0-9_/,-]{1,50}")) + throw Oops.Bah($"订舱合同惟一ID格式错误 [a-zA-Z0-9_/,-]{{1,50}}"); + + if (string.IsNullOrWhiteSpace(model.sender)) + throw Oops.Bah($"请求类别必填"); + + if (string.IsNullOrWhiteSpace(model.carrierCode)) + throw Oops.Bah($"服务船公司必填"); + + if (string.IsNullOrWhiteSpace(model.bookedByCompanyName)) + throw Oops.Bah($"订舱公司名称必填"); + + if (string.IsNullOrWhiteSpace(model.bookedByMaerskPartyCode)) + throw Oops.Bah($"订舱方ID必填"); + + if (string.IsNullOrWhiteSpace(model.bookedByCompanyContactName)) + throw Oops.Bah($"订舱方公司联系人必填"); + + if (string.IsNullOrWhiteSpace(model.bookedByCompanyContactEmail)) + throw Oops.Bah($"订舱方公司邮箱必填"); + + if (string.IsNullOrWhiteSpace(model.priceOwnerContactName)) + throw Oops.Bah($"持约方公司名称必填"); + + if (string.IsNullOrWhiteSpace(model.priceOwnerMaerskPartyCode)) + throw Oops.Bah($"持约方ID必填"); + + if (string.IsNullOrWhiteSpace(model.priceOwnerContactName)) + throw Oops.Bah($"持约方公司联系人必填"); + + if (string.IsNullOrWhiteSpace(model.priceOwnerContactEmail)) + throw Oops.Bah($"持约方公司邮箱必填"); + + if (string.IsNullOrWhiteSpace(model.placeOfReceiptCityName)) + throw Oops.Bah($"始发地城市名称必填"); + + if (string.IsNullOrWhiteSpace(model.placeOfReceiptUnLocCode)) + throw Oops.Bah($"始发地UN CODE必填"); + + if (string.IsNullOrWhiteSpace(model.placeOfReceiptCountryCode)) + throw Oops.Bah($"始发地国家代码必填"); + + if (string.IsNullOrWhiteSpace(model.exportServiceMode)) + throw Oops.Bah($"始发地服务模式必填"); + + if (string.IsNullOrWhiteSpace(model.placeOfDeliveryCityName)) + throw Oops.Bah($"目的地城市名称必填"); + + if (string.IsNullOrWhiteSpace(model.placeOfDeliveryUnLocCode)) + throw Oops.Bah($"目的地UN CODE必填"); + + if (string.IsNullOrWhiteSpace(model.placeOfDeliveryCountryCode)) + throw Oops.Bah($"目的地国家代码必填"); + + if (string.IsNullOrWhiteSpace(model.importServiceMode)) + throw Oops.Bah($"目的地服务模式必填"); + + if (string.IsNullOrWhiteSpace(model.vesselName)) + throw Oops.Bah($"船名必填,请确认正确选择了船期"); + + if (string.IsNullOrWhiteSpace(model.exportVoyageNumber)) + throw Oops.Bah($"航次号必填,请确认正确选择了船期"); + + if (!model.originDepartureDateTimeLocal.HasValue) + throw Oops.Bah($"ETD必填,请确认正确选择了船期"); + + if (!model.destinationArrivalDateTimeLocal.HasValue) + throw Oops.Bah($"ETA必填,请确认正确选择了船期"); + + if (string.IsNullOrWhiteSpace(model.commodityCode)) + throw Oops.Bah($"商品代码必填,请确认正确选择了商品"); + + if (string.IsNullOrWhiteSpace(model.commodityName)) + throw Oops.Bah($"商品名称必填,请确认正确选择了商品"); + + if (!model.totalCargoWeight.HasValue || model.totalCargoWeight.Value < 1) + throw Oops.Bah($"总重必填"); + + if (string.IsNullOrWhiteSpace(model.cargoType)) + throw Oops.Bah($"货物标志必填"); + + if (!model.earliestDepartureDate.HasValue) + throw Oops.Bah($"预计离港日期必填"); + + if (string.IsNullOrWhiteSpace(model.userPlaceOfReceiptUnLocCode)) + throw Oops.Bah($"始发地必填"); + + if (string.IsNullOrWhiteSpace(model.userPlaceOfDeliveryUnLocCode)) + throw Oops.Bah($"目的地必填"); + + //if (!model.isSendNoSchedule && string.IsNullOrWhiteSpace(model.carrierProductId)) + // throw Oops.Bah($"船期信息不能为空,请查询船期信息"); + + if (model.isReefer) + { + if (!model.temperature.HasValue) + throw Oops.Bah($"选择了冷冻处理,温度必填"); + } + + if (model.ctns.Count == 0) + throw Oops.Bah($"箱型箱量信息必填"); + + if (model.ctns.Any(a => string.IsNullOrWhiteSpace(a.ctnCode))) + throw Oops.Bah($"箱型不能为空"); + + if (model.ctns.Any(a => !a.ctnNum.HasValue || a.ctnNum.Value < 1)) + throw Oops.Bah($"箱量不能为空,并且不能小于1"); + + if (model.ctns.Any(a => !a.ctnSufferWeight.HasValue || a.ctnSufferWeight.Value < 1)) + throw Oops.Bah($"箱内重量不能为空,并且不能小于1"); + + + if (model.totalCargoWeight.Value != model.ctns.Sum(b => b.ctnNum.Value * b.ctnSufferWeight.Value)) + { + throw Oops.Bah($"箱内重量合计不等于总重,请修改"); + } + + if (!model.isBookingPartOwnPrice) + { + if (model.bookedByMaerskPartyCode.Equals(model.priceOwnerMaerskPartyCode)) + { + throw Oops.Bah($"当前订舱合同号是非订舱方合约,持约方不能和订舱方ID信息一样,请根据实际情况填写"); + } + + if (model.bookedByCompanyName.Equals(model.priceOwnerCompanyName)) + { + throw Oops.Bah($"当前订舱合同号是非订舱方合约,持约方公司名称不能和订舱方公司名称信息一样,请根据实际情况填写"); + } + } + else + { + if (!model.bookedByMaerskPartyCode.Equals(model.priceOwnerMaerskPartyCode)) + { + throw Oops.Bah($"当前订舱合同号是订舱方合约,持约方ID必需和订舱方ID信息一致,请根据实际情况填写"); + } + + if (!model.bookedByCompanyName.Equals(model.priceOwnerCompanyName)) + { + throw Oops.Bah($"当前订舱合同号是订舱方合约,持约方名称必需和订舱方名称信息一致,请根据实际情况填写"); + } + } + } + #endregion + + #region 检索商品名称 + /// + /// 检索商品名称 + /// + /// 请求详情 + /// 返回检索结果 + [HttpPost("/BookingMSKAPI/SearchCommodities")] + public async Task> SearchCommodities(QueryCommoditiesDto model) + { + List list = new List(); + + /* + MSKApiCommodity + */ + try + { + if (string.IsNullOrWhiteSpace(model.commodityName)) + throw Oops.Oh("商品名称不能为空"); + + if (string.IsNullOrWhiteSpace(model.carrierId)) + throw Oops.Oh("船公司代码不能为空"); + + if (model.commodityName.Length < 3) + throw Oops.Oh("商品名称至少输入3个以上字符"); + + string queryUrl = string.Empty; + + if (model.carrierId.Equals("MSK", StringComparison.OrdinalIgnoreCase)) + { + queryUrl = _cache.GetAllDictData().GetAwaiter().GetResult() + .FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == CONST_MSK_API_COMMODITY_URL)?.Value; + } + else + { + throw Oops.Oh($"当前船公司 {model.carrierId} 未配置相应的请求接口"); + } + + if (string.IsNullOrWhiteSpace(queryUrl)) + throw Oops.Oh("未配置商品请求接口地址,请联系管理员"); + + var webAccountConfig = _webAccountConfig + .GetAccountConfig("MSKApi", UserManager.UserId).GetAwaiter().GetResult(); + + if (webAccountConfig == null) + throw Oops.Oh("未配置个人账户,请先配置个人账户 类型-MSKApi"); + + MSKAPISearchCommodityDto queryInfo = new MSKAPISearchCommodityDto + { + userKey = App.Configuration["MSKAPIDjyUserKey"], + userSecret = App.Configuration["MSKAPIDjyUserSecret"], + operatingEnvironment = App.Configuration["MSKAPIOPEnvironment"], + commodityName = model.commodityName, + mskAppKey = webAccountConfig.Account + }; + + MSKAPISearchCommodityResultDto resultInfo = null; + + var rlt = await queryUrl.SetBody(queryInfo) + .PostAsStringAsync(); + + if (!string.IsNullOrWhiteSpace(rlt)) + { + try + { + resultInfo = JSON.Deserialize(rlt); + } + catch (Exception ex) + { + _logger.LogInformation($"请求MSK API检索商品异常,原因:{ex.Message}"); + + throw Oops.Bah($"请求MSK API检索商品异常,原因:{ex.Message}"); + } + } + + if (resultInfo != null && resultInfo.code == 200 + && resultInfo.data != null && resultInfo.data.Count > 0) + { + list = resultInfo.data.Adapt>(); + } + } + catch (Exception ex) + { + _logger.LogError($"检索商品名称异常,req={JSON.Serialize(model)} 原因:{ex.Message}"); + + throw Oops.Bah($"检索商品名称失败,{ex.Message}"); + } + + return list; + } + #endregion + + #region 检索始发地、目的港口信息 + /// + /// 检索始发地、目的港口信息 + /// + /// 请求详情 + /// 返回检索结果 + [HttpPost("/BookingMSKAPI/SearchLocations")] + public async Task> SearchLocations(QueryLocationsDto model) + { + List list = new List(); + + /* + MSKApiCommodity + */ + try + { + if (string.IsNullOrWhiteSpace(model.cityName)) + throw Oops.Oh("港口或城市名称不能为空"); + + if (string.IsNullOrWhiteSpace(model.carrierCode)) + throw Oops.Oh("服务船公司不能为空"); + + if (string.IsNullOrWhiteSpace(model.carrierId)) + throw Oops.Oh("船公司代码不能为空"); + + if (model.cityName.Length < 3) + throw Oops.Oh("港口或城市名称至少输入3个以上字符"); + + + string queryUrl = string.Empty; + + if (model.carrierId.Equals("MSK", StringComparison.OrdinalIgnoreCase)) + { + queryUrl = _cache.GetAllDictData().GetAwaiter().GetResult() + .FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == CONST_MSK_API_LOCATION_URL)?.Value; + } + else + { + throw Oops.Oh($"当前船公司 {model.carrierId} 未配置相应的请求接口"); + } + + if (string.IsNullOrWhiteSpace(queryUrl)) + throw Oops.Oh("未配置商品请求接口地址,请联系管理员"); + + var webAccountConfig = _webAccountConfig + .GetAccountConfig("MSKApi", UserManager.UserId).GetAwaiter().GetResult(); + + if (webAccountConfig == null) + throw Oops.Oh("未配检索始发地、目的港口,请先配置个人账户 类型-MSKApi"); + + MSKAPISearchLocationDto queryInfo = new MSKAPISearchLocationDto + { + userKey = App.Configuration["MSKAPIDjyUserKey"], + userSecret = App.Configuration["MSKAPIDjyUserSecret"], + operatingEnvironment = App.Configuration["MSKAPIOPEnvironment"], + name = model.cityName, + mskAppKey = webAccountConfig.Account, + carrierCode = model.carrierCode + }; + + MSKAPISearchLocationResultDto resultInfo = null; + + var rlt = await queryUrl.SetBody(queryInfo) + .PostAsStringAsync(); + + if (!string.IsNullOrWhiteSpace(rlt)) + { + try + { + resultInfo = JSON.Deserialize(rlt); + } + catch (Exception ex) + { + _logger.LogInformation($"请求MSK API检索始发地、目的港口异常,原因:{ex.Message}"); + + throw Oops.Bah($"请求MSK API检索始发地、目的港口异常,原因:{ex.Message}"); + } + } + + if (resultInfo != null && resultInfo.code == 200 + && resultInfo.data != null && resultInfo.data.Count > 0) + { + list = resultInfo.data.Adapt>(); + } + } + catch (Exception ex) + { + _logger.LogError($"检索始发地、目的港口异常,req={JSON.Serialize(model)} 原因:{ex.Message}"); + + throw Oops.Bah($"检索始发地、目的港口失败,{ex.Message}"); + } + + return list; + } + #endregion + + #region 马士基API订舱台账 + /// + /// 马士基API订舱台账 + /// + /// 查询条件 + /// 返回台账列表 + [HttpPost("/BookingMSKAPI/GetPage")] + public async Task> GetPageAsync([FromBody] QueryBookingDeliveryRecordDto QuerySearch) + { + + //制单日期 + DateTime createBegin = DateTime.MinValue; + DateTime createEnd = DateTime.MinValue; + //更新日期 + DateTime updateBegin = DateTime.MinValue; + DateTime updateEnd = DateTime.MinValue; + //预计离港日期 + DateTime edepartureBegin = DateTime.MinValue; + DateTime edepartureEnd = DateTime.MinValue; + //ETD日期 + DateTime etdBegin = DateTime.MinValue; + DateTime etdEnd = DateTime.MinValue; + //ETA时间 + DateTime etaBegin = DateTime.MinValue; + DateTime etaEnd = DateTime.MinValue; + + //定时 + DateTime jobBegin = DateTime.MinValue; + DateTime jobEnd = DateTime.MinValue; + + #region 查询条件 + + //制单日期 + if (!string.IsNullOrWhiteSpace(QuerySearch.CreateBegin)) + { + if (!DateTime.TryParse(QuerySearch.CreateBegin, out createBegin)) + throw Oops.Oh($"创建起始日期格式错误,{QuerySearch.CreateBegin}"); + } + + if (!string.IsNullOrWhiteSpace(QuerySearch.CreateEnd)) + { + if (!DateTime.TryParse(QuerySearch.CreateEnd, out createEnd)) + throw Oops.Oh($"创建结束日期格式错误,{QuerySearch.CreateEnd}"); + + createEnd = createEnd.AddDays(1); + } + //更新日期 + if (!string.IsNullOrWhiteSpace(QuerySearch.UpdateBegin)) + { + if (!DateTime.TryParse(QuerySearch.UpdateBegin, out updateBegin)) + throw Oops.Oh($"更新起始日期开始格式错误,{QuerySearch.UpdateBegin}"); + } + + if (!string.IsNullOrWhiteSpace(QuerySearch.UpdateEnd)) + { + if (!DateTime.TryParse(QuerySearch.UpdateEnd, out updateEnd)) + throw Oops.Oh($"更新结束日期格式错误,{QuerySearch.UpdateEnd}"); + + updateEnd = updateEnd.AddDays(1); + } + //预计离港日期 + if (!string.IsNullOrWhiteSpace(QuerySearch.EDepartureBegin)) + { + if (!DateTime.TryParse(QuerySearch.EDepartureBegin, out edepartureBegin)) + throw Oops.Oh($"预计离港日期起始格式错误,{QuerySearch.EDepartureBegin}"); + } + + if (!string.IsNullOrWhiteSpace(QuerySearch.EDepartureEnd)) + { + if (!DateTime.TryParse(QuerySearch.EDepartureEnd, out edepartureEnd)) + throw Oops.Oh($"预计离港日期结束格式错误,{QuerySearch.EDepartureEnd}"); + + edepartureEnd = edepartureEnd.AddDays(1); + } + + //ETD + if (!string.IsNullOrWhiteSpace(QuerySearch.ETDBegin)) + { + if (!DateTime.TryParse(QuerySearch.ETDBegin, out etdBegin)) + throw Oops.Oh($"ETD起始日期格式错误,{QuerySearch.ETDBegin}"); + } + + if (!string.IsNullOrWhiteSpace(QuerySearch.ETDEnd)) + { + if (!DateTime.TryParse(QuerySearch.ETDEnd, out etdEnd)) + throw Oops.Oh($"ETD结束日期格式错误,{QuerySearch.ETDEnd}"); + + etdEnd = etdEnd.AddDays(1); + } + //ETA + if (!string.IsNullOrWhiteSpace(QuerySearch.ETDBegin)) + { + if (!DateTime.TryParse(QuerySearch.ETDBegin, out etaBegin)) + throw Oops.Oh($"ETA起始日期格式错误,{QuerySearch.ETDBegin}"); + } + + if (!string.IsNullOrWhiteSpace(QuerySearch.ETAEnd)) + { + if (!DateTime.TryParse(QuerySearch.ETAEnd, out etaEnd)) + throw Oops.Oh($"ETA结束日期格式错误,{QuerySearch.ETAEnd}"); + + etaEnd = etaEnd.AddDays(1); + } + + //定时 + if (!string.IsNullOrWhiteSpace(QuerySearch.JOBBegin)) + { + if (!DateTime.TryParse(QuerySearch.JOBBegin, out jobBegin)) + throw Oops.Oh($"返场起始日期格式错误,{QuerySearch.JOBBegin}"); + } + + if (!string.IsNullOrWhiteSpace(QuerySearch.JOBEnd)) + { + if (!DateTime.TryParse(QuerySearch.JOBEnd, out jobEnd)) + throw Oops.Oh($"返场结束日期格式错误,{QuerySearch.JOBEnd}"); + + jobEnd = jobEnd.AddDays(1); + } + #endregion + + string entityOrderCol = "CreatedTime"; + + //这里因为返回给前端的台账数据是DTO,所以这里排序时候需要转换成Entity对应的字段 + if (!string.IsNullOrWhiteSpace(QuerySearch.SortField)) + entityOrderCol = MapsterExtHelper.GetAdaptProperty(QuerySearch.SortField); + + //菜单375504048771141=我的任务台账 + List userlist = await _sysDataUserMenuService.GetDataScopeList(MenuConst.MenuMSKApi); + + bool isAdmin = false; + + if (userlist == null) + { + isAdmin = true; + userlist = new List(); + } + else if (userlist != null && userlist.Count > 0) + { + userlist.Add(UserManager.UserId); + userlist = userlist.Distinct().ToList(); + } + + _logger.LogInformation("任务台账权限范围 {list}", userlist); + + var entities = await _bookingDeliveryRecordRep.AsQueryable() + .Where(t => isAdmin || userlist.Contains(t.CreatedUserId.Value)) + .WhereIF(createBegin != DateTime.MinValue, t => t.CreatedTime.HasValue && t.CreatedTime.Value >= createBegin) + .WhereIF(createEnd != DateTime.MinValue, t => t.CreatedTime.HasValue && t.CreatedTime.Value < createEnd) + .WhereIF(updateBegin != DateTime.MinValue, t => t.UpdatedTime.HasValue && t.UpdatedTime.Value >= updateBegin) + .WhereIF(updateEnd != DateTime.MinValue, t => t.UpdatedTime.HasValue && t.UpdatedTime.Value < updateEnd) + .WhereIF(edepartureBegin != DateTime.MinValue, t => t.EARLIEST_DEPARTURE_DATE.HasValue && t.EARLIEST_DEPARTURE_DATE.Value >= edepartureBegin) + .WhereIF(edepartureEnd != DateTime.MinValue, t => t.EARLIEST_DEPARTURE_DATE.HasValue && t.EARLIEST_DEPARTURE_DATE.Value < edepartureEnd) + .WhereIF(etdBegin != DateTime.MinValue, t => t.ETD.HasValue && t.ETD.Value >= etdBegin) + .WhereIF(etdEnd != DateTime.MinValue, t => t.ETD.HasValue && t.ETA.Value < etdEnd) + .WhereIF(etaBegin != DateTime.MinValue, t => t.ETA.HasValue && t.ETA.Value >= etaBegin) + .WhereIF(etaEnd != DateTime.MinValue, t => t.ETA.HasValue && t.ETA.Value < etaEnd) + .WhereIF(jobBegin != DateTime.MinValue, t => t.JOB_TIME.HasValue && t.JOB_TIME.Value >= jobBegin) + .WhereIF(jobEnd != DateTime.MinValue, t => t.JOB_TIME.HasValue && t.JOB_TIME.Value < jobEnd) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TotalAmountStart), t => t.SHIP_RATE_TOTAL_AMOUNT != null && t.SHIP_RATE_TOTAL_AMOUNT.Value >= decimal.Parse(QuerySearch.TotalAmountStart)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TotalAmountEnd), t => t.SHIP_RATE_TOTAL_AMOUNT != null && t.SHIP_RATE_TOTAL_AMOUNT.Value <= decimal.Parse(QuerySearch.TotalAmountEnd)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.BookingChannelType), t => t.BOOKING_CHANNEL_TYPE == QuerySearch.BookingChannelType) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.TotalCurrency), t => t.SHIP_RATE_TOTAL_CURRENCY == QuerySearch.TotalCurrency) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.Carrier), t => t.CARRIERID.Equals(QuerySearch.Carrier)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.PriceReference), t => t.PRICE_REFERENCE.Contains(QuerySearch.PriceReference)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.BookedByCompanyName), t => t.BOOKEDBY_COMPANY_NAME.Contains(QuerySearch.BookedByCompanyName)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.BookedByCompanyPartyCode), t => t.BOOKEDBY_COMPANY_PARTYCODE.Contains(QuerySearch.BookedByCompanyPartyCode)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.PriceOwnerCompanyName), t => t.PRICE_OWNER_COMPANY_NAME.Contains(QuerySearch.PriceOwnerCompanyName)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.PriceOwnerCompanyPartyCode), t => t.PRICE_OWNER_COMPANY_PARTYCODE.Contains(QuerySearch.PriceOwnerCompanyPartyCode)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.PlaceReceiptCity), t => t.PLACERECEIPT_CITY.Contains(QuerySearch.PlaceReceiptCity) || t.PLACERECEIPT_UNLOC_CODE.Contains(QuerySearch.PlaceReceiptCity)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.PlaceDeliveryCity), t => t.PLACEDELIVERY_CITY.Contains(QuerySearch.PlaceDeliveryCity) || t.PLACEDELIVERY_UNLOC_CODE.Contains(QuerySearch.PlaceDeliveryCity)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.BookingReference), t => t.BOOKING_REFERENCE.Contains(QuerySearch.BookingReference)) + .WhereIF(!string.IsNullOrWhiteSpace(QuerySearch.BookingCreator), t => t.CreatedUserName.Contains(QuerySearch.BookingCreator) || t.UpdatedUserName.Contains(QuerySearch.BookingCreator)) + .OrderBy(entityOrderCol + (QuerySearch.descSort ? " desc " : " asc ")) + .ToPagedListAsync(QuerySearch.PageNo, QuerySearch.PageSize); + + + return entities.Adapt>(); + } + #endregion + + #region 获取马士基API订舱详情 + /// + /// 获取马士基API订舱详情 + /// + /// 马士基API订舱ID + /// 返回详情 + [HttpGet("/BookingMSKAPI/GetInfo")] + public async Task GetInfo(long id) + { + MSKBookingDto model = null; + + var entity = await _bookingDeliveryRecordRep.AsQueryable() + .FirstAsync(a => a.Id == id); + + if (entity == null) + throw Oops.Oh($"获取马士基API订舱详情失败,不存在或已作废"); + + model = entity.Adapt(); + + var ctnList = _bookingDeliveryRecordCtnRep.AsQueryable() + .Where(a => a.RECORD_ID == id && a.IsDeleted == false).ToList(); + + if (ctnList.Count > 0) + { + model.ctns = ctnList.Select(a => new MSKBookingCtnInfo + { + id = a.Id, + ctnCode = a.CTN_CODE, + carrierCtnCode = a.CARRIER_CTN_CODE, + ctnNum = a.CTN_NUM, + ctnName = a.CTN_NAME, + ctnSufferWeight = a.CTN_SUFFER_WEIGHT, + stuffingMeasurementType = a.STUFFING_MEASUREMENT_TYPE, + stuffingMeasurementUnit = a.STUFFING_MEASUREMENT_UNIT + }).ToList(); + } + + MSKAPISearchTransportSchedules selectedShipSchedule = null; + + if (model.PId > 0) + { + var shipScheduleRecord = await _bookingDeliveryRecordShipScheduleRep.AsQueryable() + .FirstAsync(a => a.SHIP_RATE_PID != null && a.SHIP_RATE_PID.Value == model.PId); + + if (shipScheduleRecord != null) + { + selectedShipSchedule = JSON.Deserialize(shipScheduleRecord.SHIP_JSON); + + if (selectedShipSchedule != null) + { + model.selectedShipScheduleShow = GetShipScheduleShow(selectedShipSchedule); + } + + } + } + + return model; + } + #endregion + + #region 保存 + /// + /// 保存 + /// + /// 请求订舱详情 + /// 返回ID + [HttpPost("/BookingMSKAPI/Save")] + public async Task Save([FromBody] MSKBookingDto model) + { + return await InnerSave(model); + } + #endregion + + #region 保存内部方法 + /// + /// 保存内部方法 + /// + /// API订舱详情 + /// 是否发送API,true-发送需要校验状态;false-不校验状态 + /// + private async Task InnerSave(MSKBookingDto model, bool isSendApi = false) + { + DateTime nowDate = DateTime.Now; + + string ctnStat = string.Empty; + + _logger.LogInformation($"获取请求马士基API订舱报文,JSON={JSON.Serialize(model)}"); + + BookingDeliveryRecordShipSchedule shipScheduleRecord = null; + + MSKAPISearchTransportSchedules selectedShipSchedule = null; + + if (model.PId > 0) + { + if (model.id.HasValue && model.id.Value > 0) + { + var recordId = model.id.Value; + + shipScheduleRecord = await _bookingDeliveryRecordShipScheduleRep.AsQueryable() + .FirstAsync(a => a.RECORD_ID == recordId && a.SHIP_RATE_PID != null && + a.SHIP_RATE_PID.Value == model.PId && a.IsDeleted == false); + } + + if (shipScheduleRecord == null) + { + selectedShipSchedule = GetCacheShipSailingSchedule(model.PId); + } + else + { + selectedShipSchedule = JSON.Deserialize(shipScheduleRecord.SHIP_JSON); + } + + 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 = _bookingDeliveryRecordRep.AsQueryable() + .First(a => a.Id == model.id); + + if (oldInfo == null) + throw Oops.Oh("订舱数据不存在或已作废"); + + if (oldInfo.STATUS == "SUCC") + { + if (isSendApi) + throw Oops.Oh("订舱数据已发送成功,不能重复发送"); + + throw Oops.Oh("订舱数据已发送成功,不能修改"); + } + + + BookingDeliveryRecord entity = model.Adapt(); + + entity.Id = model.id.Value; + entity.UpdatedTime = nowDate; + entity.UpdatedUserId = UserManager.UserId; + entity.UpdatedUserName = UserManager.Name; + entity.CTN_STAT = ctnStat; + entity.BOOKING_CHANNEL_TYPE = "CON_API"; + entity.BOOKING_CHANNEL_TYPE_NAME = "合约订舱"; + + await _bookingDeliveryRecordRep.AsUpdateable(entity).IgnoreColumns(x => new + { + x.CreatedTime, + x.CreatedUserId, + x.CreatedUserName, + x.BOOKING_REFERENCE, + x.BookingId, + x.REQUEST_ACKNOWLEDGEMENT_ID, + x.STATUS, + x.TenantId, + x.IS_RECV_BC, + x.LST_RECV_BC_DATE, + x.IS_RECV_BK_CANCEL, + x.LST_RECV_BK_CANCEL_DATE + }).ExecuteCommandAsync(); + + if (model.ctns != null && model.ctns.Count > 0) + { + var ctnEntityList = _bookingDeliveryRecordCtnRep.AsQueryable() + .Where(a => a.RECORD_ID == entity.Id && a.IsDeleted == 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 = ctn.Adapt(); + + ctnEntity.Id = ctn.id.Value; + ctnEntity.RECORD_ID = entity.Id; + ctnEntity.UpdatedTime = nowDate; + ctnEntity.UpdatedUserId = UserManager.UserId; + ctnEntity.UpdatedUserName = UserManager.Name; + + _bookingDeliveryRecordCtnRep.AsUpdateable(ctnEntity).IgnoreColumns(x => new { + x.CreatedUserId, + x.CreatedUserName, + x.CreatedTime, + x.TenantId, + x.STUFFING_MEASUREMENT_TYPE, + x.STUFFING_MEASUREMENT_UNIT, + x.CTN_SUFFER_WEIGHT + }).ExecuteCommand(); + } + else + { + var ctnEntity = new BookingDeliveryRecordCtn + { + CTN_CODE = ctn.ctnCode, + CTN_NAME = ctn.ctnName, + CTN_NUM = ctn.ctnNum.Value, + CTN_SUFFER_WEIGHT = (int)ctn.ctnSufferWeight.Value, + }; + + ctnEntity.RECORD_ID = entity.Id; + ctnEntity.CreatedTime = nowDate; + ctnEntity.UpdatedTime = nowDate; + ctnEntity.CreatedUserId = UserManager.UserId; + ctnEntity.CreatedUserName = UserManager.Name; + ctnEntity.STUFFING_MEASUREMENT_TYPE = "WEIGHT"; + ctnEntity.STUFFING_MEASUREMENT_UNIT = "KGS"; + + _bookingDeliveryRecordCtnRep.Insert(ctnEntity); + } + + }); + + if (ctnEntityList.Count > 0) + { + ctnEntityList.ForEach(async ctn => { + ctn.IsDeleted = true; + ctn.UpdatedTime = nowDate; + ctn.UpdatedUserId = UserManager.UserId; + ctn.UpdatedUserName = UserManager.Name; + + await _bookingDeliveryRecordCtnRep.AsUpdateable(ctn).UpdateColumns(x => new { + x.IsDeleted, + x.UpdatedTime, + x.UpdatedUserId, + x.UpdatedUserName + }).ExecuteCommandAsync(); + }); + } + } + + if (shipScheduleRecord == null) + { + if (model.PId > 0 && selectedShipSchedule != null) + { + shipScheduleRecord = new BookingDeliveryRecordShipSchedule + { + Id = YitIdHelper.NextId(), + RECORD_ID = model.id.Value, + SHIP_RATE_PID = selectedShipSchedule.PId, + SHIP_RATE_MD5 = selectedShipSchedule.MD5, + SHIP_JSON = Newtonsoft.Json.JsonConvert.SerializeObject(selectedShipSchedule), + CreatedTime = nowDate, + UpdatedTime = nowDate, + CreatedUserId = UserManager.UserId, + CreatedUserName = UserManager.Name + }; + + await _bookingDeliveryRecordShipScheduleRep.InsertAsync(shipScheduleRecord); + } + } + + return model.id.Value; + } + else + { + BookingDeliveryRecord entity = model.Adapt(); + + entity.CreatedTime = nowDate; + entity.UpdatedTime = nowDate; + entity.CreatedUserId = UserManager.UserId; + entity.CreatedUserName = UserManager.Name; + entity.STATUS = "TEMP"; + entity.STATUS_NAME = "暂存"; + entity.CTN_STAT = ctnStat; + entity.BOOKING_CHANNEL_TYPE = "CON_API"; + entity.BOOKING_CHANNEL_TYPE_NAME = "合约订舱"; + + await _bookingDeliveryRecordRep.InsertAsync(entity); + + if (model.ctns != null && model.ctns.Count > 0) + { + model.ctns.ForEach(ctn => + { + var ctnEntity = new BookingDeliveryRecordCtn + { + CTN_CODE = ctn.ctnCode, + CTN_NAME = ctn.ctnName, + CTN_NUM = ctn.ctnNum.Value, + CTN_SUFFER_WEIGHT = (int)ctn.ctnSufferWeight.Value, + }; + + ctnEntity.RECORD_ID = entity.Id; + ctnEntity.CreatedTime = nowDate; + ctnEntity.UpdatedTime = nowDate; + ctnEntity.CreatedUserId = UserManager.UserId; + ctnEntity.CreatedUserName = UserManager.Name; + ctnEntity.STUFFING_MEASUREMENT_TYPE = "WEIGHT"; + ctnEntity.STUFFING_MEASUREMENT_UNIT = "KGS"; + + _bookingDeliveryRecordCtnRep.Insert(ctnEntity); + }); + } + + if (shipScheduleRecord == null) + { + if (model.PId > 0 && selectedShipSchedule != null) + { + shipScheduleRecord = new BookingDeliveryRecordShipSchedule + { + Id = YitIdHelper.NextId(), + RECORD_ID = entity.Id, + SHIP_RATE_PID = selectedShipSchedule.PId, + SHIP_RATE_MD5 = selectedShipSchedule.MD5, + SHIP_JSON = Newtonsoft.Json.JsonConvert.SerializeObject(selectedShipSchedule), + CreatedTime = nowDate, + UpdatedTime = nowDate, + CreatedUserId = UserManager.UserId, + CreatedUserName = UserManager.Name + }; + + await _bookingDeliveryRecordShipScheduleRep.InsertAsync(shipScheduleRecord); + } + } + else + { + //只有船期发生变化时才重新写入新的船期记录 + if (model.PId != shipScheduleRecord.SHIP_RATE_PID.Value) + { + _logger.LogInformation($"MSK CON id={model.id} 换了船期 原记录:{selectedShipSchedule.PId} 新记录:{model.PId} 作废原船期,插入新船期"); + + shipScheduleRecord.IsDeleted = true; + shipScheduleRecord.UpdatedTime = nowDate; + shipScheduleRecord.UpdatedUserId = UserManager.UserId; + shipScheduleRecord.UpdatedUserName = UserManager.Name; + + await _bookingDeliveryRecordShipScheduleRep.AsUpdateable(shipScheduleRecord).UpdateColumns(x => new { + x.IsDeleted, + x.UpdatedUserId, + x.UpdatedUserName, + x.UpdatedTime + }).ExecuteCommandAsync(); + + shipScheduleRecord = new BookingDeliveryRecordShipSchedule + { + Id = YitIdHelper.NextId(), + RECORD_ID = model.id.Value, + SHIP_RATE_PID = selectedShipSchedule.PId, + SHIP_RATE_MD5 = selectedShipSchedule.MD5, + SHIP_JSON = Newtonsoft.Json.JsonConvert.SerializeObject(selectedShipSchedule), + CreatedTime = nowDate, + UpdatedTime = nowDate, + CreatedUserId = UserManager.UserId, + CreatedUserName = UserManager.Name + }; + + await _bookingDeliveryRecordShipScheduleRep.InsertAsync(shipScheduleRecord); + } + else + { + _logger.LogInformation($"MSK CON id={model.id} 船期没变化 model.PId={model.PId} shipScheduleRecord.SHIP_RATE_PID={shipScheduleRecord.SHIP_RATE_PID.Value}"); + } + } + + return entity.Id; + } + } + #endregion + + #region 删除 + /// + /// 删除 + /// + /// 请求订舱ID + /// + [HttpGet("/BookingMSKAPI/Delete")] + public async Task Delete(long id) + { + var info = _bookingDeliveryRecordRep.AsQueryable().First(a => a.Id == id); + + if (info == null) + throw Oops.Bah($"删除失败,业务信息不存在或已作废"); + + info.IsDeleted = true; + info.UpdatedTime = DateTime.Now; + info.UpdatedUserId = UserManager.UserId; + info.UpdatedUserName = UserManager.Name; + + await _bookingDeliveryRecordRep.AsUpdateable(info).UpdateColumns(x => new { + x.IsDeleted, + x.UpdatedTime, + x.UpdatedUserId, + x.UpdatedUserName + }).ExecuteCommandAsync(); + } + #endregion + + #region 批量发送 + /// + /// 批量发送 + /// + /// 马士基API订舱ID组 + /// 返回执行结果消息 + [HttpPost("/BookingMSKAPI/BatchSend")] + public async Task BatchSend([FromBody] long[] ids) + { + var list = await _bookingDeliveryRecordRep.AsQueryable() + .Where(a => ids.Contains(a.Id)).ToListAsync(); + + if (list.Count != ids.Length) + throw Oops.Oh("订舱数据获取失败,请确认选中的记录是否存在"); + + List msgList = new List(); + 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(); + result = InnerSendMSKBooking(model, entity.Id, false).GetAwaiter().GetResult(); + + 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(); + result = InnerSendMSKBooking(model, entity.Id, false).GetAwaiter().GetResult(); + + if (result.succ) + return string.Empty; + } + catch (Exception ex) + { + msgList.Add(ex.Message); + } + } + + return string.Join("#", msgList.ToArray()); + } + #endregion + + #region 批量复制 + /// + /// 批量复制 + /// + /// 马士基API批量复制指定数据 + /// 返回执行结果消息 + [HttpPost("/BookingMSKAPI/BatchCopy")] + public async Task BatchCopy(MSKAPIBookingCopyDto model) + { + if (model.copyNum < 1) + throw Oops.Oh($"复制数量不能小于1"); + + if (model.copyNum > 1000) + throw Oops.Oh($"复制数量不能大于1000"); + + if (string.IsNullOrWhiteSpace(model.opType)) + throw Oops.Oh($"请求的操作类型不能为空"); + + var entity = await _bookingDeliveryRecordRep.AsQueryable() + .FirstAsync(a => a.Id == model.originalId); + + if (entity == null) + throw Oops.Oh($"获取马士基API订舱详情失败,不存在或已作废"); + + var ctnList = _bookingDeliveryRecordCtnRep.AsQueryable() + .Where(a => a.RECORD_ID == model.originalId && a.IsDeleted == false).ToList(); + + var numArg = "".PadLeft(model.copyNum, '0').Select((a, idx) => idx + 1).ToList(); + + DateTime nowDate = DateTime.Now; + + _logger.LogInformation("获取到批量复制功能"); + + //如果是指定的编辑信息需要先把编辑数据同步到实体类,再进行复制 + 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(); + + model.bookingDto.ctns.ForEach(ctn => + { + var ctnEntity = new BookingDeliveryRecordCtn + { + CTN_CODE = ctn.ctnCode, + CTN_NAME = ctn.ctnName, + CTN_NUM = ctn.ctnNum.Value, + CTN_SUFFER_WEIGHT = (int)ctn.ctnSufferWeight.Value, + }; + + ctnEntity.CreatedTime = nowDate; + ctnEntity.UpdatedTime = nowDate; + ctnEntity.CreatedUserId = UserManager.UserId; + ctnEntity.CreatedUserName = UserManager.Name; + ctnEntity.STUFFING_MEASUREMENT_TYPE = "WEIGHT"; + ctnEntity.STUFFING_MEASUREMENT_UNIT = "KGS"; + + ctnList.Add(ctnEntity); + }); + } + + entity = model.bookingDto.Adapt(); + + entity.CreatedTime = nowDate; + entity.UpdatedTime = nowDate; + entity.CreatedUserId = UserManager.UserId; + entity.CreatedUserName = UserManager.Name; + entity.STATUS = "TEMP"; + entity.STATUS_NAME = "暂存"; + entity.CTN_STAT = ctnStat; + entity.BOOKING_CHANNEL_TYPE = "CON_API"; + entity.BOOKING_CHANNEL_TYPE_NAME = "合约订舱"; + } + + int totalNum = 0; + + foreach (var a in numArg) + { + var copyEntity = entity.Adapt(); + + copyEntity.Id = 0; + copyEntity.CreatedTime = nowDate; + copyEntity.CreatedUserId = UserManager.UserId; + copyEntity.CreatedUserName = UserManager.Name; + copyEntity.UpdatedTime = nowDate; + copyEntity.STATUS = "TEMP"; + copyEntity.STATUS_NAME = "暂存"; + copyEntity.IS_RECV_BC = false; + copyEntity.LST_RECV_BC_DATE = null; + copyEntity.IS_RECV_BK_CANCEL = false; + copyEntity.LST_RECV_BK_CANCEL_DATE = null; + copyEntity.REQUEST_ACKNOWLEDGEMENT_ID = null; + copyEntity.BOOKING_REFERENCE = null; + copyEntity.NOTES = $"COPY NO.{a} BY={model.originalId}"; + + await _bookingDeliveryRecordRep.InsertAsync(copyEntity); + + totalNum++; + + if (ctnList.Count > 0) + { + ctnList.ForEach(async ctn => + { + var ctnEntity = ctn.Adapt(); + + ctnEntity.Id = 0; + ctnEntity.RECORD_ID = copyEntity.Id; + ctnEntity.CreatedTime = nowDate; + ctnEntity.UpdatedTime = nowDate; + ctnEntity.CreatedUserId = UserManager.UserId; + ctnEntity.CreatedUserName = UserManager.Name; + + await _bookingDeliveryRecordCtnRep.InsertAsync(ctnEntity); + }); + } + } + + return JSON.Serialize(new { Total = totalNum }); + } + #endregion + + #region 同步BC状态(BC,Cancellation) + /// + /// 同步BC状态(BC,Cancellation) + /// + /// 提单号 + /// 租户ID + /// 操作类型 BC-同步BC状态 Cancellation-同步取消状态 + /// 返回回执 + [HttpGet("/BookingMSKAPI/SyncBCInfo")] + public async Task SyncBCInfo(string mblno, long tenantId, string opTypeName = "BookingConfirmation") + { + MSKBookingResultDto result = new MSKBookingResultDto(); + + try + { + var model = await _bookingDeliveryRecordRep.AsQueryable().Filter(null, true) + .FirstAsync(a => a.BOOKING_REFERENCE == mblno && a.IsDeleted == false && a.TenantId == tenantId); + + + if (model == null) + throw Oops.Oh("订舱数据不存在或已作废"); + + + if (opTypeName == "BookingConfirmation") + { + model.IS_RECV_BC = true; + model.LST_RECV_BC_DATE = DateTime.Now; + model.UpdatedTime = model.LST_RECV_BC_DATE; + model.UpdatedUserId = UserManager.UserId; + model.UpdatedUserName = UserManager.Name; + + await _bookingDeliveryRecordRep.AsUpdateable(model).UpdateColumns(x => new { + x.IS_RECV_BC, + x.LST_RECV_BC_DATE, + x.UpdatedTime, + x.UpdatedUserId, + x.UpdatedUserName + }).ExecuteCommandAsync(); + } + else if (opTypeName == "Cancellation") + { + model.IS_RECV_BK_CANCEL = true; + model.LST_RECV_BK_CANCEL_DATE = DateTime.Now; + model.UpdatedTime = model.LST_RECV_BC_DATE; + model.UpdatedUserId = UserManager.UserId; + model.UpdatedUserName = UserManager.Name; + + await _bookingDeliveryRecordRep.AsUpdateable(model).UpdateColumns(x => new { + x.IS_RECV_BK_CANCEL, + x.LST_RECV_BK_CANCEL_DATE, + x.UpdatedTime, + x.UpdatedUserId, + x.UpdatedUserName + }).ExecuteCommandAsync(); + } + + result.succ = true; + } + catch (Exception ex) + { + result.succ = false; + result.msg = $"同步BC状态异常,原因:{ex.Message}"; + } + + return result; + } + #endregion + + #region 批量复制前调取校验预警 + /// + /// 批量复制前调取校验预警 + /// + /// 马士基API批量复制指定数据 + /// 返回提示信息 + [HttpPost("/BookingMSKAPI/CheckWarningBatchCopy")] + public async Task CheckWarningBatchCopy(MSKAPIBookingCopyDto model) + { + /* + 主要校验内容 + 1、如果待复制的单子里还有“托运人自己的集装箱”或“进口退货集装箱或者其他三角集运”需要做提醒是否继续复制。 + 2、如果是opType=copy_edit-复制使用提交的编辑信息,需要判断原始货物标志变化是否继续。 + 3、如果是冷冻处理的提示是否继续。 + */ + var entity = await _bookingDeliveryRecordRep.AsQueryable() + .FirstAsync(a => a.Id == model.originalId); + + if (entity != null) + { + List msgList = new List(); + + if (entity.IS_SHIPPER_OWNED || (model.bookingDto != null && model.bookingDto.isShipperOwned)) + { + msgList.Add("含有指定托运人自己的集装箱"); + } + + if (entity.IS_IMPORT_RETURNED || (model.bookingDto != null && model.bookingDto.isImportReturned)) + { + msgList.Add("含有指定进口退货集装箱或者其他三角集运"); + } + + if (entity.IS_REEFER || (model.bookingDto != null && model.bookingDto.isReefer)) + { + msgList.Add("含有是冷冻处理"); + } + + if (model.bookingDto != null && model.bookingDto.cargoType != entity.CARGO_TYPE) + { + msgList.Add("货物标志与被复制货物标志不一致"); + } + + if (msgList.Count > 0) + throw Oops.Oh(string.Join(",", msgList.ToArray())); + } + else + { + return string.Empty; + } + + return "校验成功"; + } + #endregion + + #region 批量发送API前调取校验预警 + /// + /// 批量发送API前调取校验预警 + /// + /// 马士基API订舱ID组 + /// 返回提示信息 + [HttpPost("/BookingMSKAPI/CheckWarningBatchSend")] + public async Task CheckWarningBatchSend([FromBody] long[] ids) + { + var list = await _bookingDeliveryRecordRep.AsQueryable().Where(a => ids.Contains(a.Id)).ToListAsync(); + + if (list.Count > 0) + { + List msgList = new List(); + + if (list.Any(a => a.IS_SHIPPER_OWNED)) + { + msgList.Add("含有指定托运人自己的集装箱"); + } + + if (list.Any(a => a.IS_IMPORT_RETURNED)) + { + msgList.Add("含有指定进口退货集装箱或者其他三角集运"); + } + + if (list.Any(a => a.IS_REEFER)) + { + msgList.Add("含有是冷冻处理"); + } + + if (msgList.Count > 0) + throw Oops.Oh(string.Join("#", msgList.ToArray())); + } + + return "校验成功"; + } + #endregion + + #region 获取初始化页面默认值 + /// + /// 获取初始化页面默认值 + /// + /// 返回详情 + [HttpGet("/BookingMSKAPI/GetInitInfo")] + public async Task GetInitInfo() + { + MSKSPOTBookingInitDto dto = null; + + var webAccountConfig = await _webAccountConfig.GetAccountConfigByTenantId("MSKApi", UserManager.UserId, UserManager.TENANT_ID); + + if (webAccountConfig == null) + throw Oops.Oh("未配置公司账户维护-MSK即期,请联系管理员"); + + if (string.IsNullOrWhiteSpace(webAccountConfig.RegistPartyCode) + || string.IsNullOrWhiteSpace(webAccountConfig.RegistPartyName) || string.IsNullOrWhiteSpace(webAccountConfig.RegistContractName) + || string.IsNullOrWhiteSpace(webAccountConfig.RegistContractEmail)) + { + throw Oops.Oh("账户维护-MSK即期,未配置完整注册信息(备案代码、备案全称、联系人、邮箱必填),请联系管理员"); + } + + 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 dto; + } + #endregion + } +} diff --git a/ds-wms-service/DS.WMS.OpApi/appsettings.json b/ds-wms-service/DS.WMS.OpApi/appsettings.json index a1076f79..2d30182b 100644 --- a/ds-wms-service/DS.WMS.OpApi/appsettings.json +++ b/ds-wms-service/DS.WMS.OpApi/appsettings.json @@ -85,5 +85,10 @@ "Port": "7115", "SenderKey": "SEFBZkh5V3R1TGxtdlBIcTF4QmNMWURCS08vb2EvTzVxS0F0eDFKdlgyS3lKVUx6K3JRRE94Q2kvcWZMRytZeWxyVkhLdk9hRGpzVStPamhIUXd5NU9FMjhFTktwUlZ2eThJZGlQd3p5dUk9", "SendUrl": "/api/RulesEngineManage/ExcuteWorkFlow" + }, + "MSKAPIService": { + "UserKey": "wu", + "UserSecret": "123456", + "Environment": "TEST" } }