using DS.Module.Core; using DS.Module.Core.Extensions; using DS.Module.Core.Helpers; using DS.WMS.Core.Code.Entity; using DS.WMS.Core.Info.Entity; using DS.WMS.Core.Map.Entity; using DS.WMS.Core.Op.Dtos; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Sys.Entity; using Mapster; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace DS.WMS.Core.Op.Method { /// /// 海运出口VGM接口 /// public partial class SeaExportService { #region VGM及VMG链接 /// /// 获取VGM、VGM SI链接 /// /// 业务Id /// public async Task> VgmLink(string id) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); var bookingId = long.Parse(id); var order = tenantDb.Queryable().First(x => x.Id == bookingId); if (order == null) { return await Task.FromResult(DataResult.Failed("海运出口信息不存在!", MultiLanguageConst.SeaExportNotExist)); } var orderUrl = tenantDb.Queryable().First(x => x.BusinessId == bookingId); if (orderUrl == null) { orderUrl = new BookingOrderUrl() { BusinessId = bookingId }; await tenantDb.Insertable(orderUrl).ExecuteCommandAsync(); } if (!string.IsNullOrEmpty(orderUrl.UrlVgm)) { return await Task.FromResult(DataResult.Success(new string[] { orderUrl.UrlVgm, orderUrl.UrlVgmSi })); } //校验船公司 if (string.IsNullOrEmpty(order.Carrier)) { return await Task.FromResult(DataResult.Failed("船公司未正确填写!")); } var ctns = tenantDb.Queryable().Where(x => x.BSNO == id).ToList(); //判断船公司是否支持 var allowCarrier = db.Queryable().Where(x => x.TypeId == 1790194688729419776).Select(x => x.Value).ToList(); if (!allowCarrier.Contains(order.Carrier)) return await Task.FromResult(DataResult.Failed("不支持的船公司")); //船公司网站账号 var webacc = tenantDb.Queryable().Where(x => x.CustomerId == order.CarrierId && x.AccountType == "VgmSet").First(); ; if (webacc == null) return await Task.FromResult(DataResult.Failed("船公司网站账号未配置")); //场站转换 var yardset = tenantDb.Queryable().Where(x => x.Status == StatusEnum.Enable && x.Module == "BookingVgm" && x.LinkId == order.YardId).First(); if (yardset == null) { return await Task.FromResult(DataResult.Failed(String.Format("场站EDI配置未找到:{0}", $"{order.Yard}(VGM)"))); } //校验箱子数据录入 if (ctns.Where(c => string.IsNullOrEmpty(c.CtnAll) || !c.CtnNum.HasValue).Count() > 0) { return await Task.FromResult(DataResult.Failed("所有箱型箱量必须录入完整!")); } //箱型映射 var ctnMapping = tenantDb.Queryable().Where(x => x.Module == "BookingVgm").ToList(); //if (ctnMapping.Count == 0) //{ // throw Oops.Bah(BookingErrorCode.BOOK122); //} var expCode = ctns.Select(x => x.CtnCode).Distinct().Except(ctnMapping.Select(y => y.Code)).ToList(); if (expCode.Count > 0) { return await Task.FromResult(DataResult.Failed(String.Format("箱型EDI配置未找到:{0}", $"{string.Join(',', expCode)}(VGM)"))); } //接收反馈地址 var dicUrlVgmResp = db.Queryable().Filter(null, true).Where(x => x.Code == "vgm_si_post_reponse" && x.TenantId == 1288018625843826688).First(); var dicUrlSiResp = db.Queryable().Filter(null, true).Where(x => x.Code == "si_post_response" && x.TenantId == 1288018625843826688).First(); var userInfo = await db.Queryable().Filter(null, true).FirstAsync(x => x.Id == long.Parse(user.UserId)); var tenant = db.Queryable().Filter(null, true).First(x => x.Id == long.Parse(user.TenantId)); //调用vgm链接服务 var postUrl = db.Queryable().Filter(null, true).Where(x => x.Code == "vgm_link_service" && x.TenantId == 1288018625843826688).First().Value; var postObj = new { SystemCode = "djy_hechuan", billOrderId = order.Id.ToString(), sendOrderCode = order.MBLNO, customerName = $"{tenant.Name}+{userInfo.UserName}", //公司名称+用户姓名 customerId = order.CustomerId.ToString(), agentName = string.IsNullOrEmpty(order.Forwarder) ? tenant.Name : order.Forwarder, carrierCode = order.Carrier, userName = webacc.AppKey, userPassword = webacc.AppSecret, depotCode = yardset.MapCode, depotName = yardset.MapName, linkName = userInfo.UserName, linkMobile = userInfo.Phone, linkEmail = userInfo.Email, userId = userInfo.DjyUserId, signatory = userInfo.NickName, returnUrl = dicUrlVgmResp?.Value, shipName = order.Vessel, voyNo = order.Voyno, etdstr = order.ETD.HasValue ? order.ETD.Value.ToString("yyyy-MM-dd") : string.Empty, potrSend = order.LoadPort, potrGoal = order.DischargePort, boxinfoStr = order.CntrTotal.Replace("'", ""), vgmEndTimeStr = order.CloseVgmDate.HasValue ? order.CloseVgmDate.Value.ToString("yyyy-MM-dd") : string.Empty, returnOkUrl = "", SiReturnUrl = dicUrlSiResp?.Value, DataInfoJson = new { order.Shipper, order.Consignee, order.NotifyParty, order.Marks, order.Description, order.MBLFrt, order.Service, order.IssueType, order.Transport, order.TransportCode, order.Destination, order.DestinationId, order.KindPkgs, order.ThirdPayAt, order.LoadPort, order.LoadPortId, order.DischargePort, order.DischargePortId } }; string strPostObj = postObj.ToJsonString(); _logger.Info($"调用VGM链接接口 {postUrl} 传递数据:{strPostObj}"); var result = RequestHelper.Post(strPostObj, postUrl); _logger.Info($"调用VGM链接接口返回:{result}"); var jobjResp = JObject.Parse(result); int respCode = jobjResp.GetIntValue("code"); if (respCode != 200) { return await Task.FromResult(DataResult.Failed(jobjResp.GetStringValue("message"))); } //保存url var memoData = jobjResp.GetJObjectValue("memoData"); orderUrl.UrlVgm = memoData.GetStringValue("vgmUrl"); orderUrl.UrlVgmSi = memoData.GetStringValue("vgmAndSiUrl"); await tenantDb.Updateable(orderUrl).ExecuteCommandAsync(); //货运动态 var bookingStatus = new BookingStatusLog() { BusinessId = bookingId, Status = $"生成VGM链接", Group = "ship", OpTime = DateTime.Now, MBLNO = order.MBLNO }; await tenantDb.Insertable(bookingStatus).ExecuteCommandAsync(); return await Task.FromResult(DataResult.Success(new string[] { orderUrl.UrlVgm, orderUrl.UrlVgmSi })); } /// /// 发送VGM /// /// 业务Id /// public async Task> VgmSend(string id) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); var bookingId = long.Parse(id); var order = tenantDb.Queryable().First(x => x.Id == bookingId); var ctns = tenantDb.Queryable().Where(x => x.BSNO == id).ToList(); //船公司 if (order.CarrierId == 0 || order.CarrierId.ToString().IsNull()) return await Task.FromResult(DataResult.Failed("船公司未正确填写!")); //提单号不能为空 if (string.IsNullOrEmpty(order.MBLNO)) return await Task.FromResult(DataResult.Failed("主提单号不能为空!")); var config = db.Queryable().Where(x => x.Code == "VgmDirectSendCarrierCode").First(); if (config == null) return await Task.FromResult(DataResult.Failed("请配置租户的VGM直发船司参数!")); var arrCarr = config.Value.Split(",", StringSplitOptions.RemoveEmptyEntries); if (!arrCarr.Contains(order.Carrier)) //使用大简云发送vgm { //ETD不能为空 if (!order.ETD.HasValue) return await Task.FromResult(DataResult.Failed("ETD不能为空!")); //重量不能为空 if (!order.KGS.HasValue) return await Task.FromResult(DataResult.Failed("重量不能为空!")); var urlConfig = db.Queryable().Filter(null, true).Where(x => x.Code == "DjyVgmApiMyshppingUrl" && x.TenantId == 1288018625843826688).First().Value; var userKey = db.Queryable().Filter(null, true).Where(x => x.Code == "DjyVgmApiMyshppingUserKey" && x.TenantId == 1288018625843826688).First().Value; var userPwd = db.Queryable().Filter(null, true).Where(x => x.Code == "DjyVgmApiMyshppingUserPwd" && x.TenantId == 1288018625843826688).First().Value; if (userKey.IsNull() || userPwd.IsNull()) return await Task.FromResult(DataResult.Failed("请在网站账号中维护VGM接口的用户id和秘钥!")); var objMdata = new { MBLNO = order.MBLNO, CARRIER = order.Carrier, ChuanMing = order.Vessel, HangCi = order.VoucherNo, ETD = order.ETD.Value.ToString("yyyy-MM-dd HH:mm:ss"), ZongZhongLiang = order.KGS.ToString(), BeiZhu = "", ORDERNO = order.CustomerNo, VGMCLOSETIME = order.CloseVgmDate.HasValue ? order.CloseVgmDate.Value.ToString("yyyy-MM-dd HH:mm:ss") : "" }; var listCtn = new List(); foreach (var ctn in ctns) { if (string.IsNullOrEmpty(ctn.CtnAll) || string.IsNullOrEmpty(ctn.CntrNo) || string.IsNullOrEmpty(ctn.SealNo) || !ctn.WeightKGS.HasValue || string.IsNullOrEmpty(ctn.WeightDate)) { return await Task.FromResult(DataResult.Failed("所有箱子的箱型、箱号、封号、称重重量和称重时间都不能为空!")); } listCtn.Add(new { ChengZhongZhongLiang = ctn.WeightKGS.Value.ToString(), ChengZhongShiJian = ctn.WeightDate, CTNALL = ctn.CtnAll.Replace("'", ""), CNTRNO = ctn.CntrNo, SEALNO = ctn.SealNo }); } var dictParam = new Dictionary { { "ac", "vgm" }, { "uid", userKey }, { "skey", userPwd }, { "optype", "9"}, { "mdata", JsonConvert.SerializeObject(objMdata)}, { "ctndata", JsonConvert.SerializeObject(listCtn)} }; _logger.Info($"调用vgm发送接口:{urlConfig},参数:{JsonConvert.SerializeObject(dictParam)}"); var result = RequestHelper.Post(JsonConvert.SerializeObject(dictParam), urlConfig); _logger.Info($"调用vgm发送接口:{urlConfig},返回:{result}"); var jobjRtn = JObject.Parse(result); if (jobjRtn.GetBooleanValue("Success")) { //货运动态 var bookingStatus = new BookingStatusLog() { BusinessId = bookingId, Status = $"发送VGM", Group = "ship", MBLNO = order.MBLNO }; await tenantDb.Insertable(bookingStatus).ExecuteCommandAsync(); } else { return await Task.FromResult(DataResult.Failed(jobjRtn.GetStringValue("Message"))); } } else //直接调用vgm接口直发 { //判断船公司是否支持 var allowCarrier = db.Queryable().Where(x => x.TypeId == 1790194688729419776).Select(x => x.Value).ToList(); if (!allowCarrier.Contains(order.Carrier)) return await Task.FromResult(DataResult.Failed("不支持的船公司")); ////船公司网站账号 //var carrWebAccMap = _cache.GetAllDictData().Result.FirstOrDefault(x => x.TypeCode == "carrier_web_account_mapping" && x.Code == order.Carrier); //if (carrWebAccMap == null) // return await Task.FromResult(DataResult.Failed("不支持的船公司或账号映射未配置")); var webacc = tenantDb.Queryable().Where(x => x.CustomerId == order.CarrierId && x.AccountType == "VgmSet").First(); ; if (webacc == null) return await Task.FromResult(DataResult.Failed("船公司网站账号未配置")); #region 箱信息校验,2022-7-1修改:【累加】的必须有重量、皮重和称重重量;【总重】的只需要称重重量不为空 if (ctns.Where(c => c.WeightType == "累加" && ( string.IsNullOrEmpty(c.CntrNo) || !c.WeightKGS.HasValue || c.WeightKGS == 0 || !c.TareWeight.HasValue || c.TareWeight == 0 || !c.KGS.HasValue || c.KGS == 0) ).Count() > 0) { return await Task.FromResult(DataResult.Failed("称重方式为累加时,箱号、重量、箱皮重以及称重重量都不能为空")); } if (ctns.Where(c => c.WeightType == "总重" && ( string.IsNullOrEmpty(c.CntrNo) || !c.WeightKGS.HasValue || c.WeightKGS == 0) ).Count() > 0) { return await Task.FromResult(DataResult.Failed("称重方式为总重时,箱号和称重重量都不能为空")); } #endregion if (string.IsNullOrEmpty(order.Yard) || string.IsNullOrEmpty(order.YardId.ToString())) return await Task.FromResult(DataResult.Failed("场站未正确选择!")); // 场站映射 string mappingYard, mappingYardId; var yardMapList = tenantDb.Queryable().Where(x => x.Status == StatusEnum.Enable && x.Module == "BookingVgm" && x.LinkId == order.YardId && (x.CarrierId == 0 || x.CarrierId == order.CarrierId))?.ToList(); if (yardMapList?.Any() == true) { var yardset = yardMapList.FirstOrDefault(x => x.CarrierId == order.CarrierId) ?? yardMapList.FirstOrDefault(x => x.CarrierId == 0 || x.CarrierId.ToString() == ""); mappingYard = yardset.MapName; mappingYardId = yardset.MapCode; } else { var yard = tenantDb.Queryable().First(x => x.Id == order.YardId); mappingYard = yard.ShortName; mappingYardId = yard.CodeName; } // 船司映射 var carrMap = tenantDb.Queryable().Where(x => x.Status == StatusEnum.Enable && x.Module == "BookingVgm" && x.LinkId == order.CarrierId).First(); string mappingCarrierCode = carrMap != null ? carrMap.MapCode : order.Carrier; var userInfo = await db.Queryable().Filter(null, true).FirstAsync(x => x.Id == long.Parse(user.UserId)); var tenant = db.Queryable().Filter(null, true).First(x => x.Id == long.Parse(user.TenantId)); int idx = 1; //调用接口 var postUrl = db.Queryable().Filter(null, true).Where(x => x.Code == "vgm_service_single" && x.TenantId == 1288018625843826688).First().Value; //var dicUrl = _cache.GetAllDictData().Result.First(x => x.TypeCode == "url_set" && x.Code == "vgm_service_single"); var sendObj = new { SystemCode = "djy_hechuan", billOrderId = order.Id.ToString(), sendOrderCode = order.MBLNO, customerName = $"{tenant.Name}+{userInfo.UserName}", //公司名称+用户姓名 customerId = order.CustomerId.ToString(), agentName = string.IsNullOrEmpty(order.Forwarder) ? tenant.Name : order.Forwarder, carrierCode = mappingCarrierCode, userName = webacc.AppKey, userPassword = webacc.AppSecret, depotCode = mappingYardId, depotName = mappingYard, linkName = userInfo.UserName, linkMobile = userInfo.Phone, linkEmail = userInfo.Email, userId = userInfo.DjyUserId, signatory = userInfo.NickName, //2023年8月28日,董怡含:把用户昵称当做vgm上传人 returnUrl = "", shipName = order.Vessel, voyNo = order.Voyno, etdstr = order.ETD.HasValue ? order.ETD.Value.ToString("yyyy-MM-dd") : string.Empty, potrSend = order.LoadPort, potrGoal = order.DischargePort, boxinfoStr = order.CntrTotal.Replace("'", ""), vgmEndTimeStr = order.CloseVgmDate.HasValue ? order.CloseVgmDate.Value.ToString("yyyy-MM-dd") : string.Empty, BoxInfo = ctns.Select(c => new { index = idx++, boxType = c.CtnAll.Replace("'", ""), boxcount = c.CtnNum.HasValue ? c.CtnNum.Value : 0, code = c.CntrNo, sealCode = c.SealNo, weigth = c.KGS, weigthTare = c.TareWeight, weigthTotal = c.WeightKGS, weigthType = c.WeightType == "累加" ? "SM2" : "SM1" }).ToList(), returnOkUrl = "" }; string strPostObj = sendObj.ToJsonString(); _logger.Info($"调用VGM直发接口 {postUrl} 传递数据:{strPostObj}"); var result = RequestHelper.Post(strPostObj, postUrl); _logger.Info($"调用VGM直发接口返回:{result}"); var jobjResp = JObject.Parse(result); int respCode = jobjResp.GetIntValue("code"); if (respCode != 200) { return await Task.FromResult(DataResult.Failed(jobjResp.GetStringValue("message"))); } //货运动态 var bookingStatus = new BookingStatusLog() { BusinessId = bookingId, Status = $"直发VGM", Group = "ship", OpTime = DateTime.Now, MBLNO = order.MBLNO }; await tenantDb.Insertable(bookingStatus).ExecuteCommandAsync(); } ////设置货物状态:已发VGM,并回传东胜 await seaComService.SetGoodsStatus("YFVGM", bookingId); //await SendBookingOrder(new long[] { bookingId }); return await Task.FromResult(DataResult.Success("Vgm发送成功!")); } /// /// 批量获取vgm /// /// 业务id 逗号拼接 /// public async Task>> GetVmgDataList(string ids) { var arr = ids.Split(','); if (arr.Length == 0) { return await Task.FromResult(DataResult>.Failed("请传入正确数据!")); } var tenantDb = saasService.GetBizDbScopeById(user.TenantId); var main = await tenantDb.Queryable().Where(x => x.ParentId == 0).ToListAsync(); List batchVGMs = new List(); foreach (var item in arr) { BatchVGM batchVGM = new BatchVGM(); batchVGM.Id = Convert.ToInt64(item); batchVGM.MBLNO = main.Where(x => x.Id == batchVGM.Id).Select(x => x.MBLNO).FirstOrDefault(); batchVGM.ctnlist = await tenantDb.Queryable().Where(x => x.BSNO == item).Select(x => new BatchVGMList { Id = x.Id, CtnCode = x.CtnCode, CtnAll = x.CtnAll, CntrNo = x.CntrNo, KGS = x.KGS, TareWeight = x.TareWeight, WeightType = x.WeightType, WeightKGS = x.WeightKGS }).ToListAsync(); batchVGMs.Add(batchVGM); } return await Task.FromResult(DataResult>.Success(batchVGMs)); } /// /// 批量保存vgm /// /// /// public async Task> SaveBatchVgm(List dto) { var tenantDb = saasService.GetBizDbScopeById(user.TenantId); if (dto == null) { return await Task.FromResult(DataResult.Failed("未提交数据!")); } foreach (var item in dto) { var dic = item.GetPropertiesArray(); var info = tenantDb.Queryable().Where(x => x.Id == item.Id).First(); info = item.Adapt(info); tenantDb.Updateable(info).UpdateColumns(dic).ExecuteCommand(); } return await Task.FromResult(DataResult.Success("更新成功!", MultiLanguageConst.DataUpdateSuccess)); } #endregion } }