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.

518 lines
24 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.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
{
/// <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))
{
return await Task.FromResult(DataResult<string[]>.Failed("船公司未正确填写!"));
}
var ctns = tenantDb.Queryable<OpCtn>().Where(x => x.BSNO == id).ToList();
//判断船公司是否支持
var allowCarrier = db.Queryable<SysDictData>().Where(x => x.TypeId == 1790194688729419776).Select(x => x.Value).ToList();
if (!allowCarrier.Contains(order.Carrier))
return await Task.FromResult(DataResult<string[]>.Failed("不支持的船公司"));
//船公司网站账号
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("船公司网站账号未配置"));
//场站转换
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)")));
}
//接收反馈地址
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));
//调用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 = 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<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 config = db.Queryable<SysConfig>().Where(x => x.Code == "VgmDirectSendCarrierCode").First();
if (config == null)
return await Task.FromResult(DataResult<string>.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<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;
if (userKey.IsNull() || userPwd.IsNull())
return await Task.FromResult(DataResult<string>.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<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", 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<string>.Failed(jobjRtn.GetStringValue("Message")));
}
}
else //直接调用vgm接口直发
{
//判断船公司是否支持
var allowCarrier = db.Queryable<SysDictData>().Where(x => x.TypeId == 1790194688729419776).Select(x => x.Value).ToList();
if (!allowCarrier.Contains(order.Carrier))
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 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) || string.IsNullOrEmpty(order.YardId.ToString()))
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 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<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);
//await SendBookingOrder(new long[] { bookingId });
return await Task.FromResult(DataResult<string>.Success("Vgm发送成功!"));
}
/// <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
}
}