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.

1063 lines
53 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 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.Invoice.Dtos;
using DS.WMS.Core.Map.Entity;
using DS.WMS.Core.Op.Dtos;
using DS.WMS.Core.Op.Dtos.VGM;
using DS.WMS.Core.Op.EDI;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Entity;
using Mapster;
using Microsoft.AspNetCore.Identity;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Ocsp;
namespace DS.WMS.Core.Op.Method
{
/// <summary>
/// 海运出口VGM接口
/// </summary>
public partial class SeaExportService
{
#region VGM及VMG链接
/// <summary>
/// 获取VGM、VGM SI链接
/// </summary>
/// <param name="id">业务Id</param>
/// <returns></returns>
public async Task<DataResult<string[]>> VgmLink(string id)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var bookingId = long.Parse(id);
var order = tenantDb.Queryable<SeaExport>().First(x => x.Id == bookingId);
if (order == null)
{
return await Task.FromResult(DataResult<string[]>.Failed("海运出口信息不存在!", MultiLanguageConst.SeaExportNotExist));
}
var orderUrl = tenantDb.Queryable<BookingOrderUrl>().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<string[]>.Success(new string[] { orderUrl.UrlVgm, orderUrl.UrlVgmSi }));
}
//校验船公司
if (string.IsNullOrEmpty(order.Carrier) || order.CarrierId == 0 || order.CarrierId.IsNull())
{
return await Task.FromResult(DataResult<string[]>.Failed("船公司未正确填写!"));
}
var ctns = tenantDb.Queryable<OpCtn>().Where(x => x.BSNO == id).ToList();
//判断船公司是否支持
//db.Queryable<SysDictData>().Where(x => x.TypeId == 1790194688729419776).Select(x => x.Value).ToList();
var allowCarrier = db.Queryable<SysDictData>()
.InnerJoin<SysDictType>((a, b) => a.TypeId == b.Id).Where((a, b) => b.Code == "vgm_carrier_list").Select((a, b) => a.Value).ToList();
var carrCode = seaComService.GetCarrierCode(order.CarrierId, tenantDb);
if (!allowCarrier.Contains(carrCode))
return await Task.FromResult(DataResult<string[]>.Failed("不支持的船公司"));
//船公司网站账号
var carrWebAccMap = db.Queryable<SysDictData>()
.InnerJoin<SysDictType>((a, b) => a.TypeId == b.Id).Where((a, b) => b.Code == "carrier_web_account_mapping" && a.Name == carrCode)
.Select((a, b) => new { Value = a.Value, Name = a.Name }).First();
//x.CustomerId == order.CarrierId &&
var webacc = seaComService.GetCodeThirdParty(carrWebAccMap.Value, user.UserId, tenantDb);
if (webacc == null)
return await Task.FromResult(DataResult<string[]>.Failed("船公司VGM网站账号未配置"));
//场站转换
var yardset = tenantDb.Queryable<MappingYard>().Where(x => x.Status == StatusEnum.Enable && x.Module == "BookingVgm" && x.LinkId == order.YardId).First();
if (yardset == null)
{
return await Task.FromResult(DataResult<string[]>.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<string[]>.Failed("所有箱型箱量必须录入完整!"));
}
//箱型映射
var ctnMapping = tenantDb.Queryable<MappingCtn>().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<string[]>.Failed(String.Format("箱型EDI配置未找到{0}", $"{string.Join(',', expCode)}(VGM)")));
}
////接收反馈地址 TODO 0626注释
//var dicUrlVgmResp = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "vgm_si_post_reponse" && x.TenantId == 1288018625843826688).First();
//var dicUrlSiResp = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "si_post_response" && x.TenantId == 1288018625843826688).First();
var userInfo = await db.Queryable<SysUser>().Filter(null, true).FirstAsync(x => x.Id == long.Parse(user.UserId));
var tenant = db.Queryable<SysTenant>().Filter(null, true).First(x => x.Id == long.Parse(user.TenantId));
var destinationCode = seaComService.GetPortCode(order.DestinationId, tenantDb);
var loadPortCode = seaComService.GetPortCode(order.LoadPortId, tenantDb);
var dischargePortCode = seaComService.GetPortCode(order.DischargePortId, tenantDb);
//调用vgm链接服务
var postUrl = db.Queryable<SysConfig>().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 = carrCode,
userName = webacc.AppKey,
userPassword = webacc.AppSecret,
depotCode = yardset.MapCode,
depotName = yardset.MapName,
linkName = userInfo.UserName,
linkMobile = userInfo.Phone,
linkEmail = userInfo.Email,
//userId = userInfo.DjyUserId,
userId = order.SaleId,
signatory = userInfo.UserName,
//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,
destinationCode,
order.KindPkgs,
order.ThirdPayAt,
order.LoadPort,
//order.LoadPortId,
loadPortCode,
order.DischargePort,
//order.DischargePortId
dischargePortCode
}
};
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<string[]>.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<string[]>.Success(new string[] { orderUrl.UrlVgm, orderUrl.UrlVgmSi }));
}
/// <summary>
/// 发送VGM
/// </summary>
/// <param name="id">业务Id</param>
/// <returns></returns>
public async Task<DataResult<string>> VgmSend(string id)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var bookingId = long.Parse(id);
var order = tenantDb.Queryable<SeaExport>().First(x => x.Id == bookingId);
var ctns = tenantDb.Queryable<OpCtn>().Where(x => x.BSNO == id).ToList();
//船公司
if (order.CarrierId == 0 || order.CarrierId.ToString().IsNull())
return await Task.FromResult(DataResult<string>.Failed("船公司未正确填写!"));
//提单号不能为空
if (string.IsNullOrEmpty(order.MBLNO))
return await Task.FromResult(DataResult<string>.Failed("主提单号不能为空!"));
var vgmApiSendCarrierIdStr = db.Queryable<SysConfig>().Where(x => x.Code == "VgmApiSendCarrierId").First();
//if (config == null)
// return await Task.FromResult(DataResult<string>.Failed("请配置租户的VGM直发船司参数!配置名称:[VgmDirectSendCarrierCode]"));
var arrCarr = vgmApiSendCarrierIdStr.IsNull()
? new string[0] : vgmApiSendCarrierIdStr.Value.Split(",", StringSplitOptions.RemoveEmptyEntries);
var carrCode = seaComService.GetCarrierCode(order.CarrierId, tenantDb);
// VGM发送方式1通过API发送
if (arrCarr.Contains(carrCode))
{
if (!carrCode.Equals("MSK", StringComparison.OrdinalIgnoreCase))
{
return await Task.FromResult(DataResult<string>.Failed($"[{carrCode}]船公司暂不支持通过API发送VGM"));
}
var urlConfig = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "VgmSendMskApiUrl" && x.TenantId == 1288018625843826688).First().Value;
var userKey = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "MSKAPIDjyUserKey" && x.TenantId == 1288018625843826688).First().Value;
var userPwd = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "MSKAPIDjyUserSecret" && x.TenantId == 1288018625843826688).First().Value;
var env = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "MSKAPIOPEnvironment" && x.TenantId == 1288018625843826688).First().Value;
if (userKey.IsNull() || userPwd.IsNull() || env.IsNull())
return await Task.FromResult(DataResult<string>.Failed("通过MSKAPI发送VGM所需的Key或Secret或Environment未配置请联系管理员!"));
if (urlConfig.IsNull())
return await Task.FromResult(DataResult<string>.Failed("通过MSKAPI发送VGM所需的Url未配置请联系管理员配置名称[VgmSendMskApiUrl]"));
var webAccount = seaComService.GetCodeThirdParty("MSKApi", user.UserId, tenantDb);
if (webAccount.IsNull())
return await Task.FromResult(DataResult<string>.Failed("未配置第三方账户类型MSKApi"));
var vgmSendMskCustomerCode = db.Queryable<SysConfig>().Where(x => x.Code == "VgmSendMskCustomerCode").First().Value;
if (webAccount.IsNull())
return await Task.FromResult(DataResult<string>.Failed("通过MSKAPI发送VGM所需的[客户编号],请联系管理员,配置名称:[VgmSendMskCustomerCode]"));
var userInfo = await db.Queryable<SysUser>().Filter(null, true).FirstAsync(x => x.Id == long.Parse(user.UserId));
var param = new
{
userKey,
userPwd,
operatingEnvironment = env,
mskAppKey = webAccount.AppKey,
mskAppSecret = webAccount.AppSecret,
shipmentNumber = order.MBLNO,
brandCode = "MAEU",
customerCode = vgmSendMskCustomerCode,
terminalCode = "",
containerList = new List<object>()
};
foreach (var ctn in ctns)
{
if (string.IsNullOrEmpty(ctn.CntrNo)
|| !ctn.WeightKGS.HasValue
|| ctn.WeightKGS == 0
|| string.IsNullOrWhiteSpace(ctn.WeightType))
{
return await Task.FromResult(DataResult<string>.Failed("所有箱子的箱号、称重重量、称重方式都不能为空!"));
}
var vgmMethod = ctn.WeightType switch
{
"累加" => "CALCULATED",
"总重" => "SCALED",
_ => throw new Exception($"箱号为[{ctn.CntrNo}]的箱子称重方式非[累加]或[总重],请检查")
};
param.containerList.Add(new
{
containerNumber = ctn.CntrNo,
vgmSource = "Shipper",
vgm = ctn.WeightKGS,
vgmUnit = "KGS",
vgmMethod,
authorizedPersonName = userInfo.UserName,
authorizedPersonEmail = userInfo.Email
});
}
_logger.Info("通过MSKAPI发送VGM单号{mblno},入参:{param}", order.MBLNO, param.ToJson());
var result = RequestHelper.Post(JsonConvert.SerializeObject(param), urlConfig);
_logger.Info("通过MSKAPI发送VGM单号{mblno},响应:{resp}", order.MBLNO, result.ToJson());
var resp = JsonConvert.DeserializeObject<MSKAPISendVgmResultDto>(result);
object result1 = null;
if (resp.code == 200)
{
if (resp.data.Any(x => !x.status))
{
result1 = resp.data.Select(x => new
{
CNTRNO = x.containerNumber,
IsSuccess = x.status,
FailReason = x.error_msg
}).ToList();
_logger.Info("通过MSKAPI发送VGM部分成功单号{mblno},详细结果:{data}", order.MBLNO, result1.ToJson());
}
else
{
_logger.Info("通过MSKAPI发送VGM全部成功单号{mblno},详细结果:{data}", order.MBLNO, result1.ToJson());
//货运动态
var bookingStatus = new BookingStatusLog()
{
BusinessId = bookingId,
Status = $"直发VGM(API)",
Group = "ship",
MBLNO = order.MBLNO
};
await tenantDb.Insertable(bookingStatus).ExecuteCommandAsync();
}
}
else
{
_logger.Info("通过MSKAPI发送VGMVGM服务接口返回失败结果单号{mblno}", order.MBLNO);
return await Task.FromResult(DataResult<string>.Failed($"VGM服务接口返回失败结果{resp.msg}"));
}
}
else
{
var config = db.Queryable<SysConfig>().Where(x => x.Code == "VgmDirectSendCarrierId").First();
if (config == null)
{
return await Task.FromResult(DataResult<string>.Failed("请配置租户的VGM直发船司参数!配置名称:[VgmDirectSendCarrierId]"));
}
var allowCarr = config.Value.Split(",", StringSplitOptions.RemoveEmptyEntries);
if (!allowCarr.Contains(carrCode)) //使用大简云发送vgm
{
//ETD不能为空
if (!order.ETD.HasValue)
return await Task.FromResult(DataResult<string>.Failed("ETD不能为空!"));
//重量不能为空
if (!order.KGS.HasValue)
return await Task.FromResult(DataResult<string>.Failed("重量不能为空!"));
var urlConfig = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "DjyVgmApiMyshppingUrl" && x.TenantId == 1288018625843826688).First().Value;
//var userKey = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "DjyVgmApiMyshppingUserKey" && x.TenantId == 1288018625843826688).First().Value;
//var userPwd = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "DjyVgmApiMyshppingUserPwd" && x.TenantId == 1288018625843826688).First().Value;
var webAccount = seaComService.GetCodeThirdParty("DjyVgm", user.UserId, tenantDb);
if (webAccount.IsNull())
return await Task.FromResult(DataResult<string>.Failed("请在网站账号中维护VGM接口的用户id和秘钥!类型DjyVgm"));;
var objMdata = new
{
MBLNO = order.MBLNO,
CARRIER = carrCode,
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<dynamic>();
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<string>.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<string, string> {
{ "ac", "vgm" },
{ "uid", webAccount.AppKey },
{ "skey", webAccount.AppSecret },
{ "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<string>.Failed(jobjRtn.GetStringValue("Message")));
}
}
else //直接调用vgm接口直发
{
//判断船公司是否支持
var allowCarrier = db.Queryable<SysDictData>()
.InnerJoin<SysDictType>((a, b) => a.TypeId == b.Id).Where((a, b) => b.Code == "vgm_carrier_list" && a.Name == carrCode)
.Select((a, b) => a.Value).ToList();
if (!allowCarrier.Contains(carrCode))
return await Task.FromResult(DataResult<string>.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<string>.Failed("不支持的船公司或账号映射未配置"));
var carrWebAccMap = db.Queryable<SysDictData>()
.InnerJoin<SysDictType>((a, b) => a.TypeId == b.Id).Where((a, b) => b.Code == "carrier_web_account_mapping" && a.Name == carrCode)
.Select((a, b) => new { Value = a.Value, Name = a.Name }).First();
if (carrWebAccMap == null)
{
return await Task.FromResult(DataResult<string>.Failed("不支持的船公司或账号映射未配置"));
}
var webacc = seaComService.GetCodeThirdParty(carrWebAccMap.Value, user.UserId, tenantDb, order.CarrierId);
if (webacc == null)
return await Task.FromResult(DataResult<string>.Failed("船公司VGM网站账号未配置"));
//var webacc = tenantDb.Queryable<CodeThirdParty>().Where(x => x.CustomerId == order.CarrierId && x.AccountType == "VgmSet").First(); ;
//if (webacc == null)
// return await Task.FromResult(DataResult<string>.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<string>.Failed("称重方式为累加时,箱号、重量、箱皮重以及称重重量都不能为空"));
}
if (ctns.Where(c => c.WeightType == "总重" &&
(
string.IsNullOrEmpty(c.CntrNo)
|| !c.WeightKGS.HasValue
|| c.WeightKGS == 0)
).Count() > 0)
{
return await Task.FromResult(DataResult<string>.Failed("称重方式为总重时,箱号和称重重量都不能为空"));
}
#endregion
if (string.IsNullOrEmpty(order.Yard) || order.YardId == 0)
return await Task.FromResult(DataResult<string>.Failed("场站未正确选择!"));
// 场站映射
string mappingYard, mappingYardId;
var yardMapList = tenantDb.Queryable<MappingYard>().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<InfoClient>().First(x => x.Id == order.YardId);
mappingYard = yard.ShortName;
mappingYardId = yard.CodeName;
}
// 船司映射
var carrMap = tenantDb.Queryable<MappingCarrier>().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<SysUser>().Filter(null, true).FirstAsync(x => x.Id == long.Parse(user.UserId));
var tenant = db.Queryable<SysTenant>().Filter(null, true).First(x => x.Id == long.Parse(user.TenantId));
int idx = 1;
//调用接口
var postUrl = db.Queryable<SysConfig>().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 customerCode = seaComService.GetClientCode(order.CustomerId,tenantDb);
//var destinationCode = seaComService.GetPortCode(order.DestinationId, tenantDb);
//var loadPortCode = seaComService.GetPortCode(order.LoadPortId, tenantDb);
//var dischargePortCode = seaComService.GetPortCode(order.DischargePortId, tenantDb);
var sendObj = new
{
SystemCode = "djy_hechuan",
billOrderId = order.Id.ToString(),
sendOrderCode = order.MBLNO,
customerName = $"{tenant.Name}+{userInfo.UserName}", //公司名称+用户姓名
customerId = customerCode,
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,
userId = order.SaleId,
signatory = userInfo.UserName, //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<string>.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, tenantDb);
//await SendBookingOrder(new long[] { bookingId });
return await Task.FromResult(DataResult<string>.Success("Vgm发送成功!"));
}
#region 发送VGM
/// <summary>
/// 发送VGM
/// </summary>
/// <param name="model">请求详情</param>
/// <returns>返回回执</returns>
public async Task<DataResult<string>> InnerVgmSend(VgmSendReqDto model)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var sendType = new bool[] { model.isMSKVGMApi, model.isCarrierVGMApi, model.isDjyVGMCarrierApi };
if (sendType.Count(a=>a) > 1)
return await Task.FromResult(DataResult<string>.Failed("请求错误,只能选择一种船司通道"));
if (sendType.Count(a => a) == 0 && !model.isDjyVGMYGTApi)
return await Task.FromResult(DataResult<string>.Failed("请求错误,未正确选择发送请求,请重新选择"));
var order = tenantDb.Queryable<SeaExport>().First(x => x.Id == model.BookingId);
var id = model.BookingId.ToString();
var ctns = tenantDb.Queryable<OpCtn>().Where(x => x.BSNO == id).ToList();
//船公司
if (order.CarrierId == 0 || order.CarrierId.ToString().IsNull())
return await Task.FromResult(DataResult<string>.Failed("船公司未正确填写!"));
//提单号不能为空
if (string.IsNullOrEmpty(order.MBLNO))
return await Task.FromResult(DataResult<string>.Failed("主提单号不能为空!"));
var checkRlt = await InnerGetVgmSendChannel(order);
var checkData = checkRlt.Data;
var carrCode = seaComService.GetCarrierCode(order.CarrierId, tenantDb);
if (checkData.isMSKVGMApi)
{
#region MSK VGM API
if (!carrCode.Equals("MSK", StringComparison.OrdinalIgnoreCase))
{
return await Task.FromResult(DataResult<string>.Failed($"[{carrCode}]船公司暂不支持通过API发送VGM"));
}
var urlConfig = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "VgmSendMskApiUrl" && x.TenantId == 1288018625843826688).First().Value;
var userKey = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "MSKAPIDjyUserKey" && x.TenantId == 1288018625843826688).First().Value;
var userPwd = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "MSKAPIDjyUserSecret" && x.TenantId == 1288018625843826688).First().Value;
var env = db.Queryable<SysConfig>().Filter(null, true).Where(x => x.Code == "MSKAPIOPEnvironment" && x.TenantId == 1288018625843826688).First().Value;
if (userKey.IsNull() || userPwd.IsNull() || env.IsNull())
return await Task.FromResult(DataResult<string>.Failed("通过MSKAPI发送VGM所需的Key或Secret或Environment未配置请联系管理员!"));
if (urlConfig.IsNull())
return await Task.FromResult(DataResult<string>.Failed("通过MSKAPI发送VGM所需的Url未配置请联系管理员配置名称[VgmSendMskApiUrl]"));
var webAccount = seaComService.GetCodeThirdParty("MSKApi", user.UserId, tenantDb);
if (webAccount.IsNull())
return await Task.FromResult(DataResult<string>.Failed("未配置第三方账户类型MSKApi"));
var vgmSendMskCustomerCode = db.Queryable<SysConfig>().Where(x => x.Code == "VgmSendMskCustomerCode").First().Value;
if (webAccount.IsNull())
return await Task.FromResult(DataResult<string>.Failed("通过MSKAPI发送VGM所需的[客户编号],请联系管理员,配置名称:[VgmSendMskCustomerCode]"));
var userInfo = await db.Queryable<SysUser>().Filter(null, true).FirstAsync(x => x.Id == long.Parse(user.UserId));
var param = new
{
userKey,
userPwd,
operatingEnvironment = env,
mskAppKey = webAccount.AppKey,
mskAppSecret = webAccount.AppSecret,
shipmentNumber = order.MBLNO,
brandCode = "MAEU",
customerCode = vgmSendMskCustomerCode,
terminalCode = "",
containerList = new List<object>()
};
foreach (var ctn in ctns)
{
if (string.IsNullOrEmpty(ctn.CntrNo)
|| !ctn.WeightKGS.HasValue
|| ctn.WeightKGS == 0
|| string.IsNullOrWhiteSpace(ctn.WeightType))
{
return await Task.FromResult(DataResult<string>.Failed("所有箱子的箱号、称重重量、称重方式都不能为空!"));
}
var vgmMethod = ctn.WeightType switch
{
"累加" => "CALCULATED",
"总重" => "SCALED",
_ => throw new Exception($"箱号为[{ctn.CntrNo}]的箱子称重方式非[累加]或[总重],请检查")
};
param.containerList.Add(new
{
containerNumber = ctn.CntrNo,
vgmSource = "Shipper",
vgm = ctn.WeightKGS,
vgmUnit = "KGS",
vgmMethod,
authorizedPersonName = userInfo.UserName,
authorizedPersonEmail = userInfo.Email
});
}
_logger.Info("通过MSKAPI发送VGM单号{mblno},入参:{param}", order.MBLNO, param.ToJson());
var result = RequestHelper.Post(JsonConvert.SerializeObject(param), urlConfig);
_logger.Info("通过MSKAPI发送VGM单号{mblno},响应:{resp}", order.MBLNO, result.ToJson());
var resp = JsonConvert.DeserializeObject<MSKAPISendVgmResultDto>(result);
object result1 = null;
if (resp.code == 200)
{
if (resp.data.Any(x => !x.status))
{
result1 = resp.data.Select(x => new
{
CNTRNO = x.containerNumber,
IsSuccess = x.status,
FailReason = x.error_msg
}).ToList();
_logger.Info("通过MSKAPI发送VGM部分成功单号{mblno},详细结果:{data}", order.MBLNO, result1.ToJson());
}
else
{
_logger.Info("通过MSKAPI发送VGM全部成功单号{mblno},详细结果:{data}", order.MBLNO, result1.ToJson());
//货运动态
var bookingStatus = new BookingStatusLog()
{
BusinessId = model.BookingId,
Status = $"直发VGM(API)",
Group = "ship",
MBLNO = order.MBLNO
};
await tenantDb.Insertable(bookingStatus).ExecuteCommandAsync();
}
}
else
{
_logger.Info("通过MSKAPI发送VGMVGM服务接口返回失败结果单号{mblno}", order.MBLNO);
return await Task.FromResult(DataResult<string>.Failed($"VGM服务接口返回失败结果{resp.msg}"));
}
#endregion
}
else if(checkData.isCarrierVGMApi)
{
#region VgmDirectSendCarrierId
//判断船公司是否支持
var allowCarrier = db.Queryable<SysDictData>()
.InnerJoin<SysDictType>((a, b) => a.TypeId == b.Id).Where((a, b) => b.Code == "vgm_carrier_list" && a.Name == carrCode)
.Select((a, b) => a.Value).ToList();
if (!allowCarrier.Contains(carrCode))
return await Task.FromResult(DataResult<string>.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<string>.Failed("不支持的船公司或账号映射未配置"));
var carrWebAccMap = db.Queryable<SysDictData>()
.InnerJoin<SysDictType>((a, b) => a.TypeId == b.Id).Where((a, b) => b.Code == "carrier_web_account_mapping" && a.Name == carrCode)
.Select((a, b) => new { Value = a.Value, Name = a.Name }).First();
if (carrWebAccMap == null)
{
return await Task.FromResult(DataResult<string>.Failed("不支持的船公司或账号映射未配置"));
}
var webacc = seaComService.GetCodeThirdParty(carrWebAccMap.Value, user.UserId, tenantDb, order.CarrierId);
if (webacc == null)
return await Task.FromResult(DataResult<string>.Failed("船公司VGM网站账号未配置"));
//var webacc = tenantDb.Queryable<CodeThirdParty>().Where(x => x.CustomerId == order.CarrierId && x.AccountType == "VgmSet").First(); ;
//if (webacc == null)
// return await Task.FromResult(DataResult<string>.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<string>.Failed("称重方式为累加时,箱号、重量、箱皮重以及称重重量都不能为空"));
}
if (ctns.Where(c => c.WeightType == "总重" &&
(
string.IsNullOrEmpty(c.CntrNo)
|| !c.WeightKGS.HasValue
|| c.WeightKGS == 0)
).Count() > 0)
{
return await Task.FromResult(DataResult<string>.Failed("称重方式为总重时,箱号和称重重量都不能为空"));
}
#endregion
if (string.IsNullOrEmpty(order.Yard) || order.YardId == 0)
return await Task.FromResult(DataResult<string>.Failed("场站未正确选择!"));
// 场站映射
string mappingYard, mappingYardId;
var yardMapList = tenantDb.Queryable<MappingYard>().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<InfoClient>().First(x => x.Id == order.YardId);
mappingYard = yard.ShortName;
mappingYardId = yard.CodeName;
}
// 船司映射
var carrMap = tenantDb.Queryable<MappingCarrier>().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<SysUser>().Filter(null, true).FirstAsync(x => x.Id == long.Parse(user.UserId));
var tenant = db.Queryable<SysTenant>().Filter(null, true).First(x => x.Id == long.Parse(user.TenantId));
int idx = 1;
//调用接口
var postUrl = db.Queryable<SysConfig>().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 customerCode = seaComService.GetClientCode(order.CustomerId, tenantDb);
//var destinationCode = seaComService.GetPortCode(order.DestinationId, tenantDb);
//var loadPortCode = seaComService.GetPortCode(order.LoadPortId, tenantDb);
//var dischargePortCode = seaComService.GetPortCode(order.DischargePortId, tenantDb);
var sendObj = new
{
SystemCode = "djy_hechuan",
billOrderId = order.Id.ToString(),
sendOrderCode = order.MBLNO,
customerName = $"{tenant.Name}+{userInfo.UserName}", //公司名称+用户姓名
customerId = customerCode,
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,
userId = order.SaleId,
signatory = userInfo.UserName, //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<string>.Failed(jobjResp.GetStringValue("message")));
}
//货运动态
var bookingStatus = new BookingStatusLog()
{
BusinessId = model.BookingId,
Status = $"直发VGM",
Group = "ship",
OpTime = DateTime.Now,
MBLNO = order.MBLNO
};
await tenantDb.Insertable(bookingStatus).ExecuteCommandAsync();
#endregion
}
else if(checkData.isDjyVGMCarrierApi)
{
#region isDjyVGMCarrierApi
#endregion
}
////设置货物状态已发VGM并回传东胜
await seaComService.SetGoodsStatus("YFVGM", model.BookingId, tenantDb);
//await SendBookingOrder(new long[] { bookingId });
return await Task.FromResult(DataResult<string>.Success("Vgm发送成功!"));
}
#endregion
#region 获取VGM发送通道选项
/// <summary>
/// 获取VGM发送通道选项
/// </summary>
/// <param name="id">订单主键</param>
/// <returns>返回回执</returns>
public async Task<DataResult<CheckVGMShowDto>> GetVgmSendChannel(string id)
{
CheckVGMShowDto data = new CheckVGMShowDto
{
isDjyVGMYGTApi = true,
};
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var bookingId = long.Parse(id);
var order = tenantDb.Queryable<SeaExport>().First(x => x.Id == bookingId);
return await InnerGetVgmSendChannel(order);
}
#endregion
#region 获取VGM发送通道选项
/// <summary>
/// 获取VGM发送通道选项
/// </summary>
/// <param name="order">订单</param>
/// <returns>返回回执</returns>
public async Task<DataResult<CheckVGMShowDto>> InnerGetVgmSendChannel(SeaExport order)
{
CheckVGMShowDto data = new CheckVGMShowDto
{
isDjyVGMYGTApi = true,
};
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var vgmApiSendCarrierIdStr = db.Queryable<SysConfig>().Where(x => x.Code == "VgmApiSendCarrierId").First();
var arrCarr = vgmApiSendCarrierIdStr.IsNull()
? new string[0] : vgmApiSendCarrierIdStr.Value.Split(",", StringSplitOptions.RemoveEmptyEntries);
var carrCode = seaComService.GetCarrierCode(order.CarrierId, tenantDb);
// VGM发送方式1通过API发送
if (arrCarr.Contains(carrCode) && carrCode.Equals("MSK", StringComparison.OrdinalIgnoreCase))
{
//只提供了MSK VGM API通道
data.isMSKVGMApi = true;
}
else
{
var config = db.Queryable<SysConfig>().Where(x => x.Code == "VgmDirectSendCarrierId").First();
var allowCarr = config.IsNull() ? new string[0] : config.Value.Split(",", StringSplitOptions.RemoveEmptyEntries);
if (allowCarr.Contains(carrCode))
{
data.isCarrierVGMApi = true;
}
else
{
data.isDjyVGMCarrierApi = true;
}
}
return DataResult<CheckVGMShowDto>.Success(data);
}
#endregion
/// <summary>
/// 批量获取vgm
/// </summary>
/// <param name="ids">业务id 逗号拼接</param>
/// <returns></returns>
public async Task<DataResult<List<BatchVGM>>> GetVmgDataList(string ids)
{
var arr = ids.Split(',');
if (arr.Length == 0)
{
return await Task.FromResult(DataResult<List<BatchVGM>>.Failed("请传入正确数据!"));
}
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var main = await tenantDb.Queryable<SeaExport>().Where(x => x.ParentId == 0).ToListAsync();
List<BatchVGM> batchVGMs = new List<BatchVGM>();
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<OpCtn>().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<List<BatchVGM>>.Success(batchVGMs));
}
/// <summary>
/// 批量保存vgm
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<DataResult<string>> SaveBatchVgm(List<BatchVGMList> dto)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
if (dto == null)
{
return await Task.FromResult(DataResult<string>.Failed("未提交数据!"));
}
foreach (var item in dto)
{
var dic = item.GetPropertiesArray();
var info = tenantDb.Queryable<OpCtn>().Where(x => x.Id == item.Id).First();
info = item.Adapt(info);
tenantDb.Updateable(info).UpdateColumns(dic).ExecuteCommand();
}
return await Task.FromResult(DataResult<string>.Success("更新成功!", MultiLanguageConst.DataUpdateSuccess));
}
#endregion
}
}