You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
BookingHeChuan/Myshipping.Application/Service/BookingOrder/BookingMSKAPIService.cs

1219 lines
54 KiB
C#

This file contains ambiguous Unicode characters!

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

using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.RemoteRequest.Extensions;
using Furion;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Myshipping.Application.Entity;
using Myshipping.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Furion.DynamicApiController;
using Furion.DependencyInjection;
using Myshipping.Core.Service;
using Microsoft.Extensions.Logging;
using Myshipping.Application.Helper;
using System.Text.RegularExpressions;
using System.Globalization;
namespace Myshipping.Application.Service.BookingOrder
{
/// <summary>
/// 马士基API订舱
/// </summary>
[ApiDescriptionSettings("Application", Name = "BookingMSKAPI", Order = 10)]
public class BookingMSKAPIService: IBookingMSKAPIService, IDynamicApiController, ITransient
{
private readonly SqlSugarRepository<BookingDeliveryRecord> _bookingDeliveryRecordRep;
private readonly SqlSugarRepository<BookingDeliveryRecordCtn> _bookingDeliveryRecordCtnRep;
private readonly ISysCacheService _cache;
private readonly IDjyWebsiteAccountConfigService _webAccountConfig;
private readonly ILogger<BookingMSKAPIService> _logger;
const string CONST_MSK_API_COMMODITY_URL = "MSKApiCommodity";
const string CONST_MSK_API_BOOKING_URL = "MSKApiBooking";
const string CONST_MSK_API_Poing2P_SECD_URL = "MSKApiSailingSchedulePoint2Point";
const string CONST_MSK_API_LOCATION_URL = "MSKApilocation";
public BookingMSKAPIService(ILogger<BookingMSKAPIService> logger, ISysCacheService cache,
IDjyWebsiteAccountConfigService webAccountConfig, SqlSugarRepository<BookingDeliveryRecord> bookingDeliveryRecordRep,
SqlSugarRepository<BookingDeliveryRecordCtn> bookingDeliveryRecordCtnRep)
{
_logger = logger;
_cache = cache;
_webAccountConfig = webAccountConfig;
_bookingDeliveryRecordRep = bookingDeliveryRecordRep;
_bookingDeliveryRecordCtnRep = bookingDeliveryRecordCtnRep;
}
#region 检索海运船期详情
/// <summary>
/// 检索海运船期详情
/// </summary>
/// <param name="model">请求船期详情</param>
/// <returns>返回船期结果</returns>
[HttpPost("/BookingMSKAPI/SearchShipSailingSchedule")]
public async Task<List<SearchShipSailingScheduleResultDto>> SearchShipSailingSchedule(QueryShipSailingScheduleDto model)
{
List<SearchShipSailingScheduleResultDto> list = new List<SearchShipSailingScheduleResultDto>();
/*
MSKApiSailingSchedulePoint2Point
*/
try
{
if (string.IsNullOrWhiteSpace(model.collectionOriginCityName))
throw Oops.Oh($"始发地不能为空");
if (string.IsNullOrWhiteSpace(model.deliveryDestinationCityName))
throw Oops.Oh($"目的地不能为空");
if (string.IsNullOrWhiteSpace(model.vesselOperatorCarrierCode))
throw Oops.Oh($"服务船公司不能为空");
if (string.IsNullOrWhiteSpace(model.carrierId))
throw Oops.Oh("船公司代码不能为空");
if (string.IsNullOrWhiteSpace(model.startDate))
throw Oops.Oh($"预计离港日期不能为空");
DateTime etd = DateTime.MinValue;
if (!DateTime.TryParse(model.startDate, out etd))
throw Oops.Oh($"预计离港日期格式错误");
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_Poing2P_SECD_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");
MSKAPISearchPoint2PointScheduleDto queryInfo = new MSKAPISearchPoint2PointScheduleDto
{
userKey = App.Configuration["MSKAPIDjyUserKey"],
userSecret = App.Configuration["MSKAPIDjyUserSecret"],
operatingEnvironment = App.Configuration["MSKAPIOPEnvironment"],
mskAppKey = webAccountConfig.Account,
collectionOriginCityName = model.collectionOriginCityName,
collectionOriginCountryCode = model.collectionOriginCountryCode,
deliveryDestinationCityName = model.deliveryDestinationCityName,
deliveryDestinationCountryCode = model.deliveryDestinationCountryCode,
cargoType = model.cargoType,
exportServiceMode = model.exportServiceMode,
importServiceMode = model.importServiceMode,
vesselOperatorCarrierCode = model.vesselOperatorCarrierCode,
startDate = etd.ToString("yyyy-MM-dd"),
startDateType = "D",
};
MSKAPISearchPoint2PointScheduleResultDto resultInfo = null;
var rlt = await queryUrl.SetBody(queryInfo)
.PostAsStringAsync();
if (!string.IsNullOrWhiteSpace(rlt))
{
try
{
resultInfo = JSON.Deserialize<MSKAPISearchPoint2PointScheduleResultDto>(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)
{
resultInfo.data.ForEach(a =>
{
a.transportSchedules.ForEach(b =>
{
SearchShipSailingScheduleResultDto info = new SearchShipSailingScheduleResultDto
{
carrierProductId = a.carrierProductId,
carrierProductSequenceId = a.carrierProductSequenceId,
ETD = b.departureDateTime,
ATD = b.arrivalDateTime,
vesselOperatorCarrierCode = b.vesselOperatorCarrierCode
};
if (b.departureDateTime.HasValue && b.arrivalDateTime.HasValue)
{
TimeSpan ts = b.arrivalDateTime.Value.Subtract(b.departureDateTime.Value);
var timeDiff = ts.TotalHours;
info.days = (int)Math.Ceiling(timeDiff / 24.0);
}
if (b.facilities != null)
{
info.orignCityName = b.facilities.collectionOrigin?.cityName;
info.orignCarrierSiteGeoID = b.facilities.collectionOrigin?.carrierSiteGeoID;
info.orignLocationName = b.facilities.collectionOrigin?.locationName;
info.orignCountryCode = b.facilities.collectionOrigin?.countryCode;
info.orignLocationType = b.facilities.collectionOrigin?.locationType;
info.orignUNLocationCode = b.facilities.collectionOrigin?.UNLocationCode;
info.orignUNRegionCode = b.facilities.collectionOrigin?.UNRegionCode;
info.deliveryCityName = b.facilities.deliveryDestination?.cityName;
info.deliveryCarrierSiteGeoID = b.facilities.deliveryDestination?.carrierSiteGeoID;
info.deliveryLocationName = b.facilities.deliveryDestination?.locationName;
info.deliveryCountryCode = b.facilities.deliveryDestination?.countryCode;
info.deliveryLocationType = b.facilities.deliveryDestination?.locationType;
info.deliveryUNLocationCode = b.facilities.deliveryDestination?.UNLocationCode;
info.deliveryUNRegionCode = b.facilities.deliveryDestination?.UNRegionCode;
}
info.vesselIMONumber = b.firstDepartureVessel?.vesselIMONumber;
info.carrierVesselCode = b.firstDepartureVessel?.carrierVesselCode;
info.vesselName = b.firstDepartureVessel?.vesselName;
if (b.transportLegs != null && b.transportLegs.Count > 0)
{
var firstTransportLegs = b.transportLegs.FirstOrDefault();
if (firstTransportLegs.transport != null)
{
info.transportMode = firstTransportLegs.transport.transportMode;
info.carrierDepartureVoyageNumber = firstTransportLegs.transport.carrierDepartureVoyageNumber;
}
}
list.Add(info);
});
});
}
}
catch (Exception ex)
{
_logger.LogError($"检索海运船期详情异常req={JSON.Serialize(model)} 原因:{ex.Message}");
throw Oops.Bah($"检索海运船期详情失败,{ex.Message}");
}
return list;
}
#endregion
#region 发送马士基订舱请求
/// <summary>
/// 发送马士基订舱请求
/// </summary>
/// <param name="model">请求订舱详情</param>
/// <returns></returns>
[HttpPost("/BookingMSKAPI/SendMSKBooking")]
public async Task<MSKBookingResultDto> SendMSKBooking(MSKBookingDto model)
{
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);
DateTime nowDate = DateTime.Now;
var recordInfo = model.Adapt<BookingDeliveryRecord>();
var recordCtnList = model.ctns.Adapt<List<BookingDeliveryRecordCtn>>();
var ctnCodeMappingList = _cache.GetAllMappingCtn().GetAwaiter().GetResult().ToList();
if (ctnCodeMappingList.Count > 0)
ctnCodeMappingList = ctnCodeMappingList.Where(x => x.CarrierCode == "MSK" && x.Module == "BOOK_OR_CLOSING").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.placeOfReceiptUnLocCode,
cityName = model.placeOfReceiptCityName,
},
placeOfDelivery = new MSKAPIBookingRouteDetailsBase
{
UNLocationCode = model.placeOfDeliveryUnLocCode,
cityName = model.placeOfDeliveryCityName,
},
selectedRoute = new MSKAPIBookingRoute
{
bookingSchedules = new List<MSKAPIBookingSchedules> {
new MSKAPIBookingSchedules
{
originDepartureDateTimeLocal = model.originDepartureDateTimeLocal.Value.ToString("yyyy-MM-ddTHH:mm:ss"),
destinationArrivalDateTimeLocal = model.destinationArrivalDateTimeLocal.Value.ToString("yyyy-MM-ddTHH:mm:ss"),
transportMode = new MSKAPIBookingTransportMode
{
vessel = new MSKAPIBookingTransportModeVessel
{
name = model.vesselName,
maerskVesselCode = model.carrierVesselCode,
},
exportVoyageNumber = model.exportVoyageNumber,
},
startLocation = new MSKAPIBookingRouteDetailsBase
{
cityName = model.placeOfReceiptCityName,
UNLocationCode = model.placeOfReceiptUnLocCode
},
endLocation = new MSKAPIBookingRouteDetailsBase
{
cityName = model.placeOfDeliveryCityName,
UNLocationCode = model.placeOfDeliveryUnLocCode
},
transportModeCode = model.transportMode
}
}
},
}
};
bookingDto.bookingBody.cargo = new MSKAPIBookingCargo
{
commodityCode = model.commodityCode,
commodityCodeType = "MaerskCode",
cargoType = model.cargoType,
totalCargoWeight = model.totalCargoWeight
};
//是否冷冻处理
if (model.isReefer)
{
bookingDto.bookingBody.cargo.reeferSettings = new MSKAPIBookingCargoReeferSettings();
bookingDto.bookingBody.cargo.reeferSettings.temperatureDetails = model.temperature;
bookingDto.bookingBody.cargo.reeferSettings.temperatureMeasureUnit = "C";
bookingDto.bookingBody.cargo.reeferSettings.noOfProbes = model.noOfProbes;
//每小时需要的通风量,单位为立方米(0-285)
bookingDto.bookingBody.cargo.reeferSettings.ventilation = model.ventilation;
bookingDto.bookingBody.cargo.reeferSettings.humidity = model.humidity;
}
bookingDto.bookingBody.equipmentAndHaulage = new List<MSKAPIBookingEquipmentAndHaulage>();
if (model.ctns != null && model.ctns.Count > 0)
{
model.ctns.ForEach(ctn =>
{
var ctnMapping = ctnCodeMappingList.FirstOrDefault(t => t.Code.Equals(ctn.ctnCode));
if(ctnMapping == null)
throw Oops.Oh("未配置发送订舱请求接口地址,请联系管理员");
MSKAPIBookingEquipmentAndHaulage haulage = new MSKAPIBookingEquipmentAndHaulage
{
equipmentDetails = new MSKAPIBookingEquipmentAndHaulageItem(),
stuffingDetails = new List<MSKAPIBookingStuffingdetails>()
};
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);
});
}
var id = await InnerSave(model, isSendApi: true);
MSKAPIBookingResultDto resultInfo = null;
_logger.LogInformation($"开始请求MSK API订舱JSON={JSON.Serialize(bookingDto)}");
var jsonBody = Newtonsoft.Json.JsonConvert.SerializeObject(bookingDto);
var rlt = await sendUrl.SetBody(jsonBody)
.PostAsStringAsync();
_logger.LogInformation($"开始请求MSK API订舱返回结果 JSON={JSON.Serialize(rlt)}");
if (!string.IsNullOrWhiteSpace(rlt))
{
try
{
resultInfo = JSON.Deserialize<MSKAPIBookingResultDto>(rlt);
}
catch (Exception ex)
{
_logger.LogInformation($"请求MSK API订舱异常原因{ex.Message}");
throw Oops.Bah($"请求MSK API订舱异常原因{ex.Message}");
}
}
MSKAPIBookingResultDataDto resultData = null;
if(resultInfo.code == 200)
{
resultData = JSON.Deserialize<MSKAPIBookingResultDataDto>(JSON.Serialize(resultInfo.data));
}
var entity = _bookingDeliveryRecordRep
.FirstOrDefault(a => a.Id == recordInfo.Id);
if (resultInfo != null && resultInfo.code == 200
&& resultData != null)
{
entity.REQUEST_ACKNOWLEDGEMENT_ID = resultData.requestAcknowledgementId;
entity.BOOKING_REFERENCE = resultData.bookingReference;
entity.STATUS = "SUCC";
await _bookingDeliveryRecordRep.AsUpdateable(entity).UpdateColumns(x => new
{
x.REQUEST_ACKNOWLEDGEMENT_ID,
x.BOOKING_REFERENCE,
x.STATUS
}).ExecuteCommandAsync();
}
else
{
entity.STATUS = "FAILURE";
entity.NOTES = resultInfo.msg.Length > 500 ? resultInfo.msg.Substring(0, 500) : resultInfo.msg;
await _bookingDeliveryRecordRep.AsUpdateable(entity).UpdateColumns(x => new
{
x.STATUS,
x.NOTES
}).ExecuteCommandAsync();
throw Oops.Bah(resultInfo.msg);
}
}
catch (Exception ex)
{
_logger.LogError($"MSK API订舱异常req={JSON.Serialize(model)} 原因:{ex.Message}");
throw Oops.Bah($"MSK API订舱失败{ex.Message}");
}
return result;
}
#endregion
#region 校验马士基API订舱必填项
/// <summary>
/// 校验马士基API订舱必填项
/// </summary>
/// <param name="model"></param>
private void ValidateMSKAPIData(MSKBookingDto model)
{
/*
马士基API订舱内容校验
1、合约号必填
2、请求类别必填
3、服务船公司必填
4、订舱公司名称、代码、联系人、邮箱必填
5、持约方公司名称、代码、联系、邮箱必填
6、始发地城市名称、UNLOC、国家代码、服务模式
7、目的地城市名称、UNLOC、国家代码、服务模式
8、船名、航次、ETD、ETA
9、商品名称、代码必填
10、总重必填
11、货物标志必填
12、如果选择了冷冻处理至少要填个温度
13、箱型、箱量、重量必填
14、总重=箱量*单箱重量
15、预计离港日期必填
*/
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 (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($"箱内重量合计不等于总重,请修改");
}
}
#endregion
#region 检索商品名称
/// <summary>
/// 检索商品名称
/// </summary>
/// <param name="model">请求详情</param>
/// <returns>返回检索结果</returns>
[HttpPost("/BookingMSKAPI/SearchCommodities")]
public async Task<List<SearchCommodityResultDto>> SearchCommodities(QueryCommoditiesDto model)
{
List<SearchCommodityResultDto> list = new List<SearchCommodityResultDto>();
/*
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<MSKAPISearchCommodityResultDto>(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<List<SearchCommodityResultDto>>();
}
}
catch (Exception ex)
{
_logger.LogError($"检索商品名称异常req={JSON.Serialize(model)} 原因:{ex.Message}");
throw Oops.Bah($"检索商品名称失败,{ex.Message}");
}
return list;
}
#endregion
#region 检索始发地、目的港口信息
/// <summary>
/// 检索始发地、目的港口信息
/// </summary>
/// <param name="model">请求详情</param>
/// <returns>返回检索结果</returns>
[HttpPost("/BookingMSKAPI/SearchLocations")]
public async Task<List<QueryLocationsResultDto>> SearchLocations(QueryLocationsDto model)
{
List<QueryLocationsResultDto> list = new List<QueryLocationsResultDto>();
/*
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<MSKAPISearchLocationResultDto>(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<List<QueryLocationsResultDto>>();
}
}
catch (Exception ex)
{
_logger.LogError($"检索始发地、目的港口异常req={JSON.Serialize(model)} 原因:{ex.Message}");
throw Oops.Bah($"检索始发地、目的港口失败,{ex.Message}");
}
return list;
}
#endregion
#region 马士基API订舱台账
/// <summary>
/// 马士基API订舱台账
/// </summary>
/// <param name="QuerySearch">查询条件</param>
/// <returns>返回台账列表</returns>
[HttpPost("/BookingMSKAPI/GetPage")]
public async Task<SqlSugarPagedList<BookingDeliveryRecordPageDto>> 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<BookingDeliveryRecordDto, BookingDeliveryRecord>(QuerySearch.SortField);
var entities = await _bookingDeliveryRecordRep.AsQueryable()
.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.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))
.OrderBy(entityOrderCol + (QuerySearch.descSort ? " desc " : " asc "))
.ToPagedListAsync(QuerySearch.PageNo, QuerySearch.PageSize);
return entities.Adapt<SqlSugarPagedList<BookingDeliveryRecordPageDto>>();
}
#endregion
#region 获取马士基API订舱详情
/// <summary>
/// 获取马士基API订舱详情
/// </summary>
/// <param name="id">马士基API订舱ID</param>
/// <returns>返回详情</returns>
[HttpGet("/BookingMSKAPI/GetInfo")]
public async Task<MSKBookingDto> 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<MSKBookingDto>();
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,
ctnSufferWeight = a.CTN_SUFFER_WEIGHT,
stuffingMeasurementType = a.STUFFING_MEASUREMENT_TYPE,
stuffingMeasurementUnit = a.STUFFING_MEASUREMENT_UNIT
}).ToList();
}
return model;
}
#endregion
#region 保存
/// <summary>
/// 保存
/// </summary>
/// <param name="model">请求订舱详情</param>
/// <returns>返回ID</returns>
[HttpPost("/BookingMSKAPI/Save")]
public async Task<long> Save([FromBody] MSKBookingDto model)
{
return await InnerSave(model);
}
#endregion
/// <summary>
/// 保存内部方法
/// </summary>
/// <param name="model">API订舱详情</param>
/// <param name="isSendApi">是否发送APItrue-发送需要校验状态false-不校验状态</param>
/// <returns></returns>
private async Task<long> InnerSave(MSKBookingDto model,bool isSendApi = false)
{
DateTime nowDate = DateTime.Now;
string ctnStat = string.Empty;
_logger.LogInformation($"获取请求马士基API订舱报文JSON={JSON.Serialize(model)}");
if (model.ctns != null && model.ctns.Count > 0)
{
ctnStat = string.Join(",", model.ctns.GroupBy(a => a.ctnCode)
.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<BookingDeliveryRecord>();
entity.Id = model.id.Value;
entity.UpdatedTime = nowDate;
entity.UpdatedUserId = UserManager.UserId;
entity.UpdatedUserName = UserManager.Name;
entity.CTN_STAT = ctnStat;
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,
}).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<BookingDeliveryRecordCtn>();
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
}).ExecuteCommand();
}
else
{
var ctnEntity = ctn.Adapt<BookingDeliveryRecordCtn>();
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();
});
}
}
return model.id.Value;
}
else
{
BookingDeliveryRecord entity = model.Adapt<BookingDeliveryRecord>();
entity.CreatedTime = nowDate;
entity.UpdatedTime = nowDate;
entity.CreatedUserId = UserManager.UserId;
entity.CreatedUserName = UserManager.Name;
entity.STATUS = "TEMP";
entity.CTN_STAT = ctnStat;
await _bookingDeliveryRecordRep.InsertAsync(entity);
if (model.ctns != null && model.ctns.Count > 0)
{
model.ctns.ForEach(ctn =>
{
var ctnEntity = ctn.Adapt<BookingDeliveryRecordCtn>();
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);
});
}
return entity.Id;
}
}
#region 删除
/// <summary>
/// 删除
/// </summary>
/// <param name="id">请求订舱ID</param>
/// <returns></returns>
[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
}
}