using Furion; using Furion.Logging; using Furion.RemoteRequest.Extensions; using Myshipping.Application.Entity; using Myshipping.Core; using Myshipping.Core.Entity; using Myshipping.Core.Service; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Myshipping.Application.EDI { /// /// 中远API订舱 /// public static class ZhongYuanSoApiHelper { public async static Task> DoPost(long custOrderId) { var repCustOrder = App.GetService>(); var repOrder = App.GetService>(); var repCtn = App.GetService>(); var repCustomer = App.GetService>(); var repContact = App.GetService>(); var repTemplate = App.GetService>(); var cache = App.GetService(); var cacheService = App.GetService(); //var order = await repOrder.AsQueryable().Filter(null, true).FirstAsync(o => o.Id == bookingId); //if (order == null) //{ // return new KeyValuePair(false, "订舱信息未找到"); //} var custOrder = await repCustOrder.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == custOrderId); if (custOrder == null) { return new KeyValuePair(false, "客户订舱信息未找到"); } var sysConfigList = await cache.GetAllSysConfig(); var sCfgSpiderUrl = sysConfigList.FirstOrDefault(x => x.Code == "ZhongYuanApiSpiderUrl" && x.GroupCode == "DJY_CONST"); if (sCfgSpiderUrl == null) { return new KeyValuePair(false, "中远订舱API的爬虫URL地址未配置,请联系管理员"); } var sCfgUserKey = sysConfigList.FirstOrDefault(x => x.Code == "ZhongYuanApiSpiderKey" && x.GroupCode == "DJY_CONST"); var sCfgUserSecret = sysConfigList.FirstOrDefault(x => x.Code == "ZhongYuanApiSpiderSecret" && x.GroupCode == "DJY_CONST"); if (sCfgUserKey == null || sCfgUserSecret == null) { return new KeyValuePair(false, "中远订舱API的KEY和密钥未配置,请联系管理员"); } BookingSoTemplate template = null; DjyCustomerContact custContact = null; var postModel = new ZhongYuanSoApiModel(); JObject extObj = null; if (!string.IsNullOrEmpty(custOrder.ExtendData)) { extObj = JObject.Parse(custOrder.ExtendData); postModel.webAccount = extObj.GetStringValue("Account"); postModel.webPassword = extObj.GetStringValue("Password"); } else { return new KeyValuePair(false, "未找到订舱账号信息"); } //查找模板: //1.根据客户订舱信息中的BookingUserId和BookingTenantId,去客户信息中根据CustSysId查找客户(公司)及联系人(员工)信息 //2.根据找到的客户及联系人信息,查找中远订舱模板 if (custOrder.BookingUserId > 0 && custOrder.BookingTenantId > 0) { custContact = await repCustomer.AsQueryable() .InnerJoin((cust, contact) => cust.Id == contact.CustomerId) .Where((cust, contact) => cust.CustSysId == custOrder.BookingTenantId && contact.CustSysId == custOrder.BookingUserId) .Select((cust, contact) => contact) .SingleAsync(); if (custContact == null) { return new KeyValuePair(false, "未找到客户及联系人信息"); } //根据:用户+船司+船司账号+约号,找到启用的模板 template = await repTemplate.AsQueryable().FirstAsync(x => x.CarrierId == custOrder.CARRIERID && x.UserId == custContact.Id && x.ContractNO == custOrder.CONTRACTNO && x.BookingAccount == postModel.webAccount && x.IsEnable); if (template == null) { return new KeyValuePair(false, "未找到订舱模板"); } } else { return new KeyValuePair(false, "未找到客户端公司和用户ID"); } var mappingCtn = await cache.GetAllMappingCtn(); var mappingFrt = await cache.GetAllMappingFrt(); var mappingPortLoad = await cache.GetAllMappingPortLoad(); var mappingPort = await cache.GetAllMappingPort(); postModel.userKey = sCfgUserKey.Value; postModel.userSecret = sCfgUserSecret.Value; postModel.uploadType = template.Category; //DRAFT, TEMPLATE, BOOKING分别对应:草稿, 模板, 订舱 postModel.saveName = template.TemplateName; var mapPortLoad = mappingPortLoad.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "COSCO" && x.Code == custOrder.PORTLOADCODE); var mapPort = mappingPort.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "COSCO" && x.Code == custOrder.PORTDISCHARGECODE); if (mapPortLoad == null) { return new KeyValuePair(false, $"未找到起运港映射信息:{custOrder.PORTLOADCODE}"); } if (mapPort == null) { return new KeyValuePair(false, $"未找到目的港映射信息:{custOrder.PORTDISCHARGECODE}"); } //运输条款 var mappingService = await cacheService.GetAllMappingService(); var mappService = mappingService.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "COSCO" && x.Code == custOrder.SERVICE); if (mappService == null) { return new KeyValuePair(false, $"未找到运输条款映射信息:{custOrder.SERVICE}"); } if (!Regex.IsMatch(mappService.MapCode, "^[A-Za-z]+-[A-Za-z]+$")) { return new KeyValuePair(false, $"映射配置不正确:{mappService.MapCode}"); } var mapServArr = mappService.MapCode.Split('-'); postModel.routes = new ZhongYuanSoApiRoute() { originCity = mapPortLoad.MapCode, destinationCity = mapPort.MapCode, vesselName = custOrder.VESSEL, voyageNumber = custOrder.VOYNO, serviceCode = custOrder.LANECODE, sailSchedulePriority = template.Priority.Split(',').ToList(), outboundHaulage = mapServArr[0], inboundHaulage = mapServArr[1], }; #region 收发通及货代 //发货人 ZhongYuanSoApiPhone shipperPhone = null; if (string.IsNullOrEmpty(template.ShipperName)) { shipperPhone = new ZhongYuanSoApiPhone() { countryCode = custOrder.ShipperPhoneCountryCode, areaCode = custOrder.ShipperPhoneCode, number = custOrder.ShipperPhone }; } else { shipperPhone = new ZhongYuanSoApiPhone() { countryCode = template.ShipperPhoneCountryCode, areaCode = template.ShipperPhoneCode, number = template.ShipperPhone }; } shipperPhone.countryCode = shipperPhone.countryCode == null ? "" : shipperPhone.countryCode; shipperPhone.areaCode = shipperPhone.areaCode == null ? "" : shipperPhone.areaCode; shipperPhone.number = shipperPhone.number == null ? "" : shipperPhone.number; postModel.shipperInfo = new ZhongYuanSoApiSFT() { firstName = string.IsNullOrEmpty(template.ShipperName) ? custOrder.ShipperFirstName : template.ShipperFirstName, lastName = string.IsNullOrEmpty(template.ShipperLastName) ? custOrder.ShipperLastName : template.ShipperLastName, country = string.IsNullOrEmpty(template.ShipperCountry) ? custOrder.ShipperCountry : template.ShipperCountry, state = string.IsNullOrEmpty(template.ShipperProvince) ? custOrder.ShipperProvince : template.ShipperProvince, city = string.IsNullOrEmpty(template.ShipperCity) ? custOrder.ShipperCity : template.ShipperCity, partyName = string.IsNullOrEmpty(template.ShipperName) ? custOrder.ShipperName : template.ShipperName, addressDes = string.IsNullOrEmpty(template.ShipperAddress) ? custOrder.ShipperAddress : template.ShipperAddress, phone = shipperPhone, postalCode = string.IsNullOrEmpty(template.ShipperPostCode) ? custOrder.ShipperPostCode : template.ShipperPostCode }; //收货人 ZhongYuanSoApiPhone consigneePhone = null; if (string.IsNullOrEmpty(template.ConsigneeName)) { consigneePhone = new ZhongYuanSoApiPhone() { countryCode = custOrder.ConsigneePhoneCountryCode, areaCode = custOrder.ConsigneePhoneCode, number = custOrder.ConsigneePhone }; } else { consigneePhone = new ZhongYuanSoApiPhone() { countryCode = template.ConsigneePhoneCountryCode, areaCode = template.ConsigneePhoneCode, number = template.ConsigneePhone }; } consigneePhone.countryCode = consigneePhone.countryCode == null ? "" : consigneePhone.countryCode; consigneePhone.areaCode = consigneePhone.areaCode == null ? "" : consigneePhone.areaCode; consigneePhone.number = consigneePhone.number == null ? "" : consigneePhone.number; postModel.consigneeInfo = new ZhongYuanSoApiSFT() { firstName = string.IsNullOrEmpty(template.ConsigneeFirstName) ? custOrder.ConsigneeFirstName : template.ConsigneeFirstName, lastName = string.IsNullOrEmpty(template.ConsigneeLastName) ? custOrder.ConsigneeLastName : template.ConsigneeLastName, country = string.IsNullOrEmpty(template.ConsigneeCountry) ? custOrder.ConsigneeCountry : template.ConsigneeCountry, state = string.IsNullOrEmpty(template.ConsigneeProvince) ? custOrder.ConsigneeProvince : template.ConsigneeProvince, city = string.IsNullOrEmpty(template.ConsigneeCity) ? custOrder.ConsigneeCity : template.ConsigneeCity, partyName = string.IsNullOrEmpty(template.ConsigneeName) ? custOrder.ConsigneeName : template.ConsigneeName, addressDes = string.IsNullOrEmpty(template.ConsigneeAddress) ? custOrder.ConsigneeAddress : template.ConsigneeAddress, phone = consigneePhone, postalCode = string.IsNullOrEmpty(template.ConsigneePostCode) ? custOrder.ConsigneePostCode : template.ConsigneePostCode }; //通知人 ZhongYuanSoApiPhone notifyPhone = null; if (string.IsNullOrEmpty(template.NotifypartName)) { notifyPhone = new ZhongYuanSoApiPhone() { countryCode = custOrder.NotifypartPhoneCountryCode, areaCode = custOrder.NotifypartPhoneCode, number = custOrder.NotifypartPhone }; } else { notifyPhone = new ZhongYuanSoApiPhone() { countryCode = template.NotifypartPhoneCountryCode, areaCode = template.NotifypartPhoneCode, number = template.NotifypartPhone }; } notifyPhone.countryCode = notifyPhone.countryCode == null ? "" : notifyPhone.countryCode; notifyPhone.areaCode = notifyPhone.areaCode == null ? "" : notifyPhone.areaCode; notifyPhone.number = notifyPhone.number == null ? "" : notifyPhone.number; postModel.notifyInfo = new ZhongYuanSoApiSFT() { firstName = string.IsNullOrEmpty(template.NotifypartFirstName) ? custOrder.NotifypartFirstName : template.NotifypartFirstName, lastName = string.IsNullOrEmpty(template.NotifypartLastName) ? custOrder.NotifypartLastName : template.NotifypartLastName, country = string.IsNullOrEmpty(template.NotifypartCountry) ? custOrder.NotifypartCountry : template.NotifypartCountry, state = string.IsNullOrEmpty(template.NotifypartProvince) ? custOrder.NotifypartProvince : template.NotifypartProvince, city = string.IsNullOrEmpty(template.NotifypartCity) ? custOrder.NotifypartCity : template.NotifypartCity, partyName = string.IsNullOrEmpty(template.NotifypartName) ? custOrder.NotifypartName : template.NotifypartName, addressDes = string.IsNullOrEmpty(template.NotifypartAddress) ? custOrder.NotifypartAddress : template.NotifypartAddress, phone = notifyPhone, postalCode = string.IsNullOrEmpty(template.NotifypartPostCode) ? custOrder.NotifypartPostCode : template.NotifypartPostCode }; //货代 ZhongYuanSoApiPhone forwarderPhone = null; if (string.IsNullOrEmpty(template.BookingName)) { forwarderPhone = new ZhongYuanSoApiPhone() { countryCode = custOrder.BookingPhoneCountryCode, areaCode = custOrder.BookingPhoneCode, number = custOrder.BookingPhone }; } else { forwarderPhone = new ZhongYuanSoApiPhone() { countryCode = template.BookingPhoneCountryCode, areaCode = template.BookingPhoneCode, number = template.BookingPhone }; } forwarderPhone.countryCode = forwarderPhone.countryCode == null ? "" : forwarderPhone.countryCode; forwarderPhone.areaCode = forwarderPhone.areaCode == null ? "" : forwarderPhone.areaCode; forwarderPhone.number = forwarderPhone.number == null ? "" : forwarderPhone.number; postModel.forwarderInfo = new ZhongYuanSoApiSFT() { firstName = string.IsNullOrEmpty(template.BookingFirstName) ? custOrder.BookingFirstName : template.BookingFirstName, lastName = string.IsNullOrEmpty(template.BookingLastName) ? custOrder.BookingLastName : template.BookingLastName, country = string.IsNullOrEmpty(template.BookingCountry) ? custOrder.BookingCountry : template.BookingCountry, state = string.IsNullOrEmpty(template.BookingProvince) ? custOrder.BookingProvince : template.BookingProvince, city = string.IsNullOrEmpty(template.BookingCity) ? custOrder.BookingCity : template.BookingCity, partyName = string.IsNullOrEmpty(template.BookingName) ? custOrder.BookingName : template.BookingName, addressDes = string.IsNullOrEmpty(template.BookingAddress) ? custOrder.BookingAddress : template.BookingAddress, phone = forwarderPhone, postalCode = string.IsNullOrEmpty(template.BookingPostCode) ? custOrder.BookingPostCode : template.BookingPostCode }; #endregion postModel.cargoInfo = new ZhongYuanSoApiCargoInfo() { cargoName = CargoIdZhongyuan(custOrder.CARGOID), cargoDes = custOrder.DESCRIPTION, hsCode = custOrder.HSCODE, }; var ctns = await repCtn.AsQueryable().Where(x => x.BILLID == custOrder.Id).ToListAsync(); postModel.boxInfos = new List(); foreach (var ctn in ctns) { if (!ctn.CTNNUM.HasValue || !ctn.KGS.HasValue) { return new KeyValuePair(false, $"所有箱的箱量和毛重都不能为空"); } var mapCtn = mappingCtn.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "COSCO" && x.Code == ctn.CTNCODE); if (mapCtn == null) { return new KeyValuePair(false, $"未找箱型映射信息:{ctn.CTNCODE}"); } var apiBox = new ZhongYuanSoApiBoxInfo() { boxType = mapCtn.MapCode, boxNum = ctn.CTNNUM.Value, weight = ctn.KGS.Value.ToString(), weightUnit = "KGS" }; postModel.boxInfos.Add(apiBox); } var mapFrt = mappingFrt.FirstOrDefault(x => x.Module == "DjyCustBooking" && x.CarrierCode == "COSCO" && x.Code == custOrder.FRTCODE); if (mapFrt == null) { return new KeyValuePair(false, $"未找到付款方式映射信息:{custOrder.FRTCODE}"); } postModel.rateInfos = new ZhongYuanSoApiRateInfo() { paymentMethod = mapFrt.MapCode }; //大简云客户订舱接收BC邮箱 var djyBookMail = sysConfigList.FirstOrDefault(x => x.Code == "DjyCustomerBookReceiveBcMail"); var bcMail = custContact.Email; if (extObj != null) //优先使用东胜上传的邮箱 { var opMail = extObj.GetStringValue("OpMail"); if (!string.IsNullOrEmpty(opMail)) { bcMail = opMail; } } if (djyBookMail != null) { bcMail += ";" + djyBookMail.Value; } postModel.special = new ZhongYuanSoApiSpecial() { emailAddresses = bcMail, remarksForEntireBooking = custOrder.SOREMARK }; Log.Information($"发送API数据给爬虫({sCfgSpiderUrl.Value}):{postModel.ToJsonString()}"); var rtn = await sCfgSpiderUrl.Value.SetBody(postModel) .PostAsStringAsync(); Log.Information($"爬虫返回:{rtn}"); var jobjRtn = JObject.Parse(rtn); if (jobjRtn.GetIntValue("code") == 200) { return new KeyValuePair(true, "发送成功"); } else { return new KeyValuePair(false, jobjRtn.GetStringValue("msg")); } } /// /// 获取中远货物类型 /// /// /// private static string CargoIdZhongyuan(string cargoId) { if (cargoId is "S") { return "General"; } else if (cargoId is "R") { return "Reefer"; } else if (cargoId is "D") { return "Dangerous"; } return null; } } /// /// 中远API订舱传输对象 /// public class ZhongYuanSoApiModel { /// /// 用户key /// public string userKey { get; set; } /// /// 用户secret /// public string userSecret { get; set; } /// /// 网站账户 /// public string webAccount { get; set; } /// /// 网站密码 /// public string webPassword { get; set; } /// /// 上传类型 /// public string uploadType { get; set; } /// /// 在选择草稿及模板时, 保存时填写的名称 /// public string saveName { get; set; } /// /// 在选择草稿及模板时的描述 /// public string saveDes { get; set; } /// /// 路线信息 /// public ZhongYuanSoApiRoute routes { get; set; } /// /// 发货人信息 /// public ZhongYuanSoApiSFT shipperInfo { get; set; } /// /// 收货人信息 /// public ZhongYuanSoApiSFT consigneeInfo { get; set; } /// /// 通知人信息 /// public ZhongYuanSoApiSFT notifyInfo { get; set; } /// /// 货代信息 /// public ZhongYuanSoApiSFT forwarderInfo { get; set; } /// /// 货物信息 /// public ZhongYuanSoApiCargoInfo cargoInfo { get; set; } /// /// 箱信息 /// public List boxInfos { get; set; } /// /// 费率相关信息 /// public ZhongYuanSoApiRateInfo rateInfos { get; set; } /// /// 特殊要求及备注 /// public ZhongYuanSoApiSpecial special { get; set; } } /// /// 路线信息 /// public class ZhongYuanSoApiRoute { /// /// 出发城市 /// public string originCity { get; set; } /// /// 目的城市 /// public string destinationCity { get; set; } /// /// 船名 /// public string vesselName { get; set; } /// /// 航次 /// public string voyageNumber { get; set; } /// /// 航线代码 /// public string serviceCode { get; set; } /// /// 船期选择优先级 /// public List sailSchedulePriority { get; set; } /// /// 出发地运输条款 /// public string outboundHaulage { get; set; } /// /// 目的地运输条款 /// public string inboundHaulage { get; set; } } /// /// 收发通信息 /// public class ZhongYuanSoApiSFT { /// /// 名字 /// public string partyName { get; set; } /// /// 国家 /// public string country { get; set; } /// /// 省 /// public string state { get; set; } /// /// 城市名 /// public string city { get; set; } /// /// 区 /// public string county { get; set; } /// /// 详细地址 /// public string addressDes { get; set; } /// /// 邮编 /// public string postalCode { get; set; } /// /// 姓 /// public string firstName { get; set; } /// /// 名 /// public string lastName { get; set; } /// /// 电话 /// public ZhongYuanSoApiPhone phone { get; set; } } /// /// 收发通电话 /// public class ZhongYuanSoApiPhone { /// /// 国家代码 /// public string countryCode { get; set; } /// /// 区号 /// public string areaCode { get; set; } /// /// 电话号码 /// public string number { get; set; } } /// /// 货物信息 /// public class ZhongYuanSoApiCargoInfo { /// /// 货物类型 /// public string cargoName { get; set; } /// /// 货物描述 /// public string cargoDes { get; set; } /// /// HS代码 /// public string hsCode { get; set; } } /// /// 箱信息 /// public class ZhongYuanSoApiBoxInfo { /// /// 箱量 /// public int boxNum { get; set; } /// /// 箱型 /// public string boxType { get; set; } /// /// 毛重 /// public string weight { get; set; } /// /// 重量单位 /// public string weightUnit { get; set; } } public class ZhongYuanSoApiRateInfo { /// /// 付款方式 /// public string paymentMethod { get; set; } } /// /// 特殊要求及备注 /// public class ZhongYuanSoApiSpecial { /// /// 备注信息 /// public string remarksForEntireBooking { get; set; } /// /// 邮箱地址 /// public string emailAddresses { get; set; } } }