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