AFR对接

master
zhangxiaofeng 11 months ago
parent 84326c754a
commit a2f65a89d2

@ -23,6 +23,6 @@
/// <summary>
/// AFR申报代码名称为“AFR申报”
/// </summary>
public const int AFR_REPORT = 999;
public const int AFR_REPORT = 27;
}
}

@ -23,7 +23,7 @@ namespace djy.IService.Afr
Task<AFRMaster> Get(string gid);
Task<AFRMaster> SaveInfo(AFRMaster input);
Task Delete(string ids);
Task<string> Send(string ids, string hids, int sendType);
Task<(bool isSuccess, string message)> Send(string ids, string hids, int sendType);
Task SaveReceipt(AFRReceiptDto input);
Task<List<AFRMasterHistory>> GetHistory(string mid, string hid);
}

@ -14,7 +14,7 @@ namespace djy.Model.AFR
/// <summary>
/// 最后修改时间
/// </summary>
[Column(CanInsert = false)]
//[Column(CanInsert = false)]
public DateTime? LastUpdate { get; set; }
/// <summary>

@ -23,6 +23,17 @@ namespace djy.Model.Afr
/// </summary>
public bool IsDel { get; set; }
/// <summary>
/// 最后更新的用户ID
/// </summary>
public string LastUpdateUserID { get; set; }
/// <summary>
/// 最后更新的用户名称
/// </summary>
public string LastUpdateUserName { get; set; }
///// <summary>
///// 货代提单号唯一编号 同货代提单号,原始修改删除重发报文,该值要一致
///// </summary>
@ -42,6 +53,11 @@ namespace djy.Model.Afr
/// </summary>
public bool StateIsSend { get; set; }
/// <summary>
/// 状态:是否已经删除发送
/// </summary>
public bool StateIsDelete { get; set; }
/// <summary>
/// 状态:海关是否接收
/// </summary>

@ -21,6 +21,15 @@ namespace djy.Model.Afr
/// 用户名称
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 最后更新的用户ID
/// </summary>
public string LastUpdateUserID { get; set; }
/// <summary>
/// 最后更新的用户名称
/// </summary>
public string LastUpdateUserName { get; set; }
/// <summary>
/// 公司ID
@ -145,7 +154,7 @@ namespace djy.Model.Afr
/// <summary>
/// 操作历史
/// </summary>
[Navigate(nameof(AFRMasterHistory.MID))]
[Navigate(nameof(AFRMasterHistory.PID))]
public AFRMasterHistory History { get; set; }
#endregion

@ -22,7 +22,7 @@ namespace djy.Model.Afr
/// <summary>
/// Master表主键
/// </summary>
public string MID { get; set; }
public string PID { get; set; }
/// <summary>
/// House表主键
/// </summary>

@ -6,7 +6,7 @@
public string content { get; set; }
public string houseBillNo { get; set; }
/// <summary>
/// 值有Accept、Warning、Reject、Matched、Hold、Cancel
/// 值有Accept海关接收、Warning警告、Reject海关拒绝、Matched已匹配、Hold海关监控、Cancel海关删除
/// </summary>
public string status { get; set; }
}

@ -3,6 +3,7 @@ using Common;
using Common.Const;
using Common.DJYModel;
using Common.Extensions;
using Common.Helpers;
using Common.Tools;
using Common.Utilities;
using djy.IService.Afr;
@ -21,6 +22,7 @@ using Newtonsoft.Json.Linq;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Ocsp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
@ -211,35 +213,22 @@ namespace djy.Service.AFR
public async Task<PageModel<AFRMaster>> Load(AFRMasterInputDto input)
{
ISelect<AFRMaster> select = null;
bool isSend = false;
// 查询草稿箱列表,草稿箱列表采用一主单内含有多个分单的显示模式
List<AFRMaster> result = null;
if (input.Type == 1)
{
select = DbAMS.Select<AFRMaster>();
isSend = false;
}
// 查询已发送列表,已发送列表采用按分单的显示方式,所以采用内连接的方式
else if (input.Type == 2)
{
select = DbAMS.Select<AFRMaster>()
.InnerJoin<AFRHouse>((m, h) => m.GID == h.PID);
isSend = true;
}
ISelect<AFRMaster> select = DbAMS.Select<AFRMaster>();
select.Where((m) => m.IsDel == false && m.StateIsSend == isSend)
select.Where((m) => m.IsDel == false && m.StateIsSend == false)
//下面两个是Controller中传来的条件
.WhereIf(!string.IsNullOrEmpty(input.CompanyId), m => m.CompID == input.CompanyId)
.WhereIf(!string.IsNullOrEmpty(input.UserId), m => m.UserID == input.UserId)
.WhereIf(!string.IsNullOrEmpty(input.CompanyId), (m) => m.CompID == input.CompanyId)
.WhereIf(!string.IsNullOrEmpty(input.UserId), (m) => m.UserID == input.UserId)
// 下面是前端传来的条件
.WhereIf(!string.IsNullOrEmpty(input.MBLNO), m => m.MBLNO.Contains(input.MBLNO))
.WhereIf(!string.IsNullOrEmpty(input.UserName), m => m.UserName.Contains(input.UserName))
.WhereIf(!string.IsNullOrEmpty(input.DischargeHarbour), m => m.DischargeHarbour.Contains(input.DischargeHarbour))
.WhereIf(!string.IsNullOrEmpty(input.ShipCompanyName), m => m.ShipCompanyName.Contains(input.ShipCompanyName))
.WhereIf(input.CreateTimeStart != null, m => m.CreateTime >= input.CreateTimeStart)
.WhereIf(input.CreateTimeEnd != null, m => m.CreateTime <= input.CreateTimeEnd);
.WhereIf(!string.IsNullOrEmpty(input.MBLNO), (m) => m.MBLNO.Contains(input.MBLNO))
.WhereIf(!string.IsNullOrEmpty(input.UserName), (m) => m.UserName.Contains(input.UserName))
.WhereIf(!string.IsNullOrEmpty(input.DischargeHarbour), (m) => m.DischargeHarbour.Contains(input.DischargeHarbour))
.WhereIf(!string.IsNullOrEmpty(input.ShipCompanyName), (m) => m.ShipCompanyName.Contains(input.ShipCompanyName))
.WhereIf(input.CreateTimeStart != null, (m) => m.CreateTime >= input.CreateTimeStart)
.WhereIf(input.CreateTimeEnd != null, (m) => m.CreateTime <= input.CreateTimeEnd);
// 分单上的查询条件在这里实现方式查出分单中的PID作为主单的筛选条件
if (!string.IsNullOrEmpty(input.HouseBillNo))
@ -247,31 +236,87 @@ namespace djy.Service.AFR
var pids = await DbAMS.Select<AFRHouse>()
.Where(h => h.HouseBillNo.Contains(input.HouseBillNo))
.ToListAsync(h => h.PID);
select.Where(m => pids.Contains(m.GID));
select.Where((m) => pids.Contains(m.GID));
}
List<AFRMaster> result = await select.IncludeMany(m => m.HouseList, then => then.Where(h => h.IsDel == false))
result = await select.IncludeMany(m => m.HouseList, then => then.Where(h => h.IsDel == false))
.Page(input)
.OrderByDescending(m => m.CreateTime)
.ToListAsync();
}
else if (input.Type == 2)
{
var select = DbAMS.Select<AFRMaster, AFRHouse>()
.InnerJoin<AFRHouse>((m, h) => m.GID == h.PID);
select.Where((m, h) => m.IsDel == false && m.StateIsSend == true)
//下面两个是Controller中传来的条件
.WhereIf(!string.IsNullOrEmpty(input.CompanyId), (m, h) => m.CompID == input.CompanyId)
.WhereIf(!string.IsNullOrEmpty(input.UserId), (m, h) => m.UserID == input.UserId)
// 下面是前端传来的条件
.WhereIf(!string.IsNullOrEmpty(input.MBLNO), (m, h) => m.MBLNO.Contains(input.MBLNO))
.WhereIf(!string.IsNullOrEmpty(input.UserName), (m, h) => m.UserName.Contains(input.UserName))
.WhereIf(!string.IsNullOrEmpty(input.DischargeHarbour), (m, h) => m.DischargeHarbour.Contains(input.DischargeHarbour))
.WhereIf(!string.IsNullOrEmpty(input.ShipCompanyName), (m, h) => m.ShipCompanyName.Contains(input.ShipCompanyName))
.WhereIf(input.CreateTimeStart != null, (m, h) => m.CreateTime >= input.CreateTimeStart)
.WhereIf(input.CreateTimeEnd != null, (m, h) => m.CreateTime <= input.CreateTimeEnd)
.WhereIf(!string.IsNullOrEmpty(input.HouseBillNo), (m, h) => h.HouseBillNo.Contains(input.HouseBillNo));
var dtoList = await select.Page(input)
.OrderByDescending((m, h) => m.CreateTime)
.ToListAsync((m, h) => new { AFRMaster = m, AFRHouse = h });
result = new List<AFRMaster>();
dtoList.ForEach(d =>
{
d.AFRMaster.HouseList = new List<AFRHouse>() { d.AFRHouse };
result.Add(d.AFRMaster);
});
}
// 查询操作历史(只查询最新的一条人为操作历史)
if (result.Count > 0)
{
// FreeSql版本较低无法使用嵌套查询所以采用拼sql的方式
if (input.Type == 1)
{
var pids = result.Select(m => m.GID);
var pidStr = string.Join("','", pids);
var histories = await DbAMS.Select<AFRMasterHistory>()
List<AFRMasterHistory> histories = await DbAMS.Select<AFRMasterHistory>()
.WithSql(@$"SELECT * FROM (
SELECT *,row_number() over ( PARTITION BY Pid ORDER BY {nameof(AFRMasterHistory.CreateTime)} DESC ) AS row_num FROM AFR_MasterHistory WHERE {nameof(AFRMasterHistory.Type)} = 0 AND pid IN ('{pidStr}')) t WHERE row_num =1")
SELECT *,row_number() over ( PARTITION BY PID ORDER BY CreateTime DESC ) AS row_num FROM AFR_MasterHistory WHERE Type = 0 and PID IN ('{pidStr}')) t WHERE row_num =1")
.ToListAsync();
histories.ForEach(item =>
result.ForEach(master =>
{
master.History = histories.FirstOrDefault(h => h.PID == master.GID);
});
}
else if (input.Type == 2)
{
var pids = result.SelectMany(m => m.HouseList).Select(h => h.GID);
if (pids.Any())
{
var pidStr = string.Join("','", pids);
List<AFRMasterHistory> histories = await DbAMS.Select<AFRMasterHistory>()
.WithSql(@$"SELECT * FROM (
SELECT *,row_number() over ( PARTITION BY HID ORDER BY CreateTime DESC ) AS row_num FROM AFR_MasterHistory WHERE Type = 0 and HID IN ('{pidStr}')) t WHERE row_num =1")
.ToListAsync();
result.ForEach(master =>
{
if (master.HouseList?.Any() ?? false)
{
var master = result.FirstOrDefault(m => m.GID == item.MID);
if (master == null) return;
master.History = item;
master.History = histories.FirstOrDefault(h => h.HID == master.HouseList[0].GID);
}
});
}
}
}
return new PageModel<AFRMaster>(input.PageNumber,
input.Count,
@ -303,6 +348,9 @@ namespace djy.Service.AFR
oldMaster = await Get(input.GID);
type = oldMaster == null ? 0 : 1;
}
input.LastUpdate = nowTime;
input.LastUpdateUserID = User.GID;
input.LastUpdateUserName = User.ShowName;
// 新增
if (type == 0)
{
@ -319,7 +367,10 @@ namespace djy.Service.AFR
{
house.GID = Guid.NewGuid().ToString();
house.PID = input.GID;
house.LastUpdateUserID = User.GID;
house.LastUpdateUserName = User.ShowName;
house.CreateTime = nowTime;
house.LastUpdate = nowTime;
house.MBLNO = input.MBLNO;
// 将null换为空对象避免后续处理null值麻烦
@ -329,6 +380,7 @@ namespace djy.Service.AFR
cntr.GID = Guid.NewGuid().ToString();
cntr.PID = house.GID;
cntr.CreateTime = nowTime;
cntr.LastUpdate = nowTime;
cntr.HouseBillNo = house.HouseBillNo;
});
});
@ -339,7 +391,7 @@ namespace djy.Service.AFR
await DbAMS.Insert(input.HouseList).WithTransaction(tran).ExecuteAffrowsAsync();
await DbAMS.Insert(input.HouseList.SelectMany(h => h.CntrList)).WithTransaction(tran).ExecuteAffrowsAsync();
await BuildAFRMasterHistoryAsync(input.GID, input.HouseList.Select(h => h.GID), "新增", 0, "创建了单据", tran);
await SaveHistoryAsync(input.GID, input.HouseList, "新增", 0, "创建了单据", tran);
tran.Commit();
}
@ -350,7 +402,6 @@ namespace djy.Service.AFR
// 1. 将null换为空对象避免后续处理null值麻烦
// 2. 如果主键为null说明是新加的数据这时候需要手动给GID、PID、CreateTime赋值
// 3. 如果主键不为null说明是修改的数据这时候需要手动给LastUpdate赋值
input.LastUpdate = nowTime;
if (input.HouseList == null)
{
input.HouseList = new List<AFRHouse>();
@ -359,6 +410,9 @@ namespace djy.Service.AFR
{
input.HouseList.ForEach(house =>
{
house.LastUpdate = nowTime;
house.LastUpdateUserID = User.GID;
house.LastUpdateUserName = User.ShowName;
if (string.IsNullOrEmpty(house.GID))
{
house.GID = Guid.NewGuid().ToString();
@ -366,10 +420,6 @@ namespace djy.Service.AFR
house.CreateTime = nowTime;
house.MBLNO = input.MBLNO;
}
else
{
house.LastUpdate = nowTime;
}
if (house.CntrList == null)
{
@ -379,6 +429,7 @@ namespace djy.Service.AFR
{
house.CntrList.ForEach(cntr =>
{
cntr.LastUpdate = nowTime;
if (string.IsNullOrEmpty(cntr.GID))
{
cntr.GID = Guid.NewGuid().ToString();
@ -386,10 +437,6 @@ namespace djy.Service.AFR
cntr.CreateTime = nowTime;
cntr.HouseBillNo = house.HouseBillNo;
}
else
{
cntr.LastUpdate = nowTime;
}
});
}
});
@ -453,7 +500,7 @@ namespace djy.Service.AFR
{
await DbAMS.Insert(waitInsertHouseList).WithTransaction(tran).ExecuteAffrowsAsync();
await BuildAFRMasterHistoryAsync(input.GID, waitInsertHouseGids, "新增", 0, "新增了单据", tran);
await SaveHistoryAsync(input.GID, waitInsertHouseList, "新增", 0, "新增了单据", tran);
}
if (waitDeleteHouseGids.Any())
{
@ -464,17 +511,17 @@ namespace djy.Service.AFR
.Where(h => waitDeleteHouseGids.Contains(h.GID))
.ExecuteAffrowsAsync();
await BuildAFRMasterHistoryAsync(input.GID, waitDeleteHouseGids, "删除", 0, "删除了单据", tran);
await SaveHistoryAsync(input.GID, waitDeleteHouseGids.Select(gid => new AFRHouse() { GID = gid }), "删除", 0, "删除了单据", tran);
}
if (waitUpdateHouseGids.Any())
{
await DbAMS.Update<AFRHouse>()
.SetSource(waitUpdateHouseList)
.IgnoreColumns(h => new { h.StateIsMatched, h.StateIsAccept, h.StateIsSend, h.NewNotice })
.IgnoreColumns(h => new { h.StateIsMatched, h.StateIsAccept, h.StateIsSend, h.StateIsDelete, h.NewNotice })
.WithTransaction(tran)
.ExecuteAffrowsAsync();
await BuildAFRMasterHistoryAsync(input.GID, waitUpdateHouseGids, "修改", 0, "修改了单据", tran);
await SaveHistoryAsync(input.GID, waitUpdateHouseList, "修改", 0, "修改了单据", tran);
}
// 箱子执行
@ -504,33 +551,7 @@ namespace djy.Service.AFR
return await Get(input.GID);
}
private async Task BuildAFRMasterHistoryAsync(string mid, IEnumerable<string> hids, string state, int type, string remark, DbTransaction tran = null)
{
List<AFRMasterHistory> list = new(hids.Count());
foreach (string hid in hids)
{
var history = new AFRMasterHistory()
{
GID = Guid.NewGuid().ToString(),
CreateTime = DateTime.Now,
Operator = User.ShowName,
MID = mid,
HID = hid,
State = state,
Type = Convert.ToByte(type)
};
history.Remark = $"{history.Operator}于{(DateTime)history.CreateTime:yyyy-MM-dd HH:mm:ss}{remark}";
list.Add(history);
}
if (tran == null)
{
await DbAMS.Insert(list).ExecuteAffrowsAsync();
}
else
{
await DbAMS.Insert(list).WithTransaction(tran).ExecuteAffrowsAsync();
}
}
public async Task Delete(string ids)
{
@ -563,9 +584,18 @@ namespace djy.Service.AFR
}
}
public async Task<string> Send(string ids, string hids, int sendType)
/// <summary>
/// 发送
/// </summary>
/// <param name="ids"></param>
/// <param name="hids"></param>
/// <param name="sendType">1原始发送 2重发 3修改 4删除</param>
public async Task<(bool, string)> Send(string ids, string hids, int sendType)
{
//return "发送成功";
//return (true,"发送成功");
// 是否全部成功
bool isFullSuccess = true;
#region 查询电子口岸的请求参数
var paramSets = await DbBus.Get(DbList.djydb).Select<ParamSet>().Where(x => x.PARAMNAME == "AFRURL" || x.PARAMNAME == "AFRAccount" || x.PARAMNAME == "AFRKey").ToListAsync(p => new
{
@ -622,30 +652,17 @@ namespace djy.Service.AFR
var housePids = houseAll.Select(h => h.PID);
masterAll = await DbAMS.Select<AFRMaster>().Where(m => m.IsDel == false && housePids.Contains(m.GID)).ToListAsync();
}
//else if (sendType is 4)
//{
// if (string.IsNullOrEmpty(hids))
// {
// throw new ArgumentNullException(nameof(hids));
// }
// var hidArr = hids.Split(',');
// houseAll = await DbAMS.Select<AFRHouse>().Where(h => h.IsDel == false && hidArr.Contains(h.GID)).ToListAsync();
// if (houseAll.Count != hidArr.Length)
// {
// throw new Exception("所选记录有些已被删除,请刷新页面后重试");
// }
//}
#endregion
StringBuilder messageBuilder = new();
#region 构建请求参数
// 原始发送
// 原始发送 重发 修改
if (sendType is 1 or 2 or 3)
{
foreach (AFRMaster masterItem in masterAll)
{
// 待处理的分单
List<AFRHouse> houseList = null;
try
@ -654,29 +671,39 @@ namespace djy.Service.AFR
// 判断是否有分单数据
houseList = houseAll.Where(h => h.PID == masterItem.GID).ToList() ?? throw new Exception("分单为空");
// 验证接口要求
// 验证数据是否符合接口要求
if (masterItem.FilingType == "Tranship" && (string.IsNullOrWhiteSpace(masterItem.LastForeignHarbourCode) || string.IsNullOrWhiteSpace(masterItem.LastForeignHarbour)))
{
throw new Exception("当【申报运输类型】为【Tranship】时【交货地全称】与【交货地五字码】为必填项");
}
// 如果操作类型为“重发”,则待发送的记录必须都为“已删除”,因为宁波接口要求记录状态是“删除成功”的,才可以重发
if (sendType is 2)
{
if (houseList.Any(h => h.StateIsDelete == false))
{
string tip = string.Join("、", houseList.Where(h => h.StateIsDelete == false).Select(h => h.HouseBillNo).ToList());
throw new Exception($"所选分单中存在未“删除发送”的记录,分单号:【{tip}】,请重新选择(只有“删除发送”成功的,才能进行“重发”操作)");
}
}
// 如果操作类型为“修改”,则待发送记录不能有“已删除”的
if (sendType is 3)
{
if (houseList.Any(h => h.StateIsDelete))
{
string tip = string.Join("、", houseList.Where(h => h.StateIsDelete).Select(h => h.HouseBillNo).ToList());
throw new Exception($"所选分单中存在已经“删除发送”的记录,分单号:【{tip}】,请重新选择(已“删除发送”的记录需要先进行“重发”,才能进行 “修改发送”或“删除发送” 操作)");
}
}
// 记录状态是回执成功的,才可以修改(暂不校验)
// 验证账户余额是否充足
var fin = new FinanceService();
var getfinrs = fin.CheckBalance(new CustFee
{
CARRIER = masterItem.ShipCompanyCode,
//ETD = null,
//VOYNO = masterItem.Voyno,
//VESSEL = masterItem.Vessel,
//HBLNO = item.HBLNo,
//SENDUSERID = user.GID,
LURURENID = User.GID,
//CtnrCount = ,
//CtnrInfo = string.Empty,
BSTYPE = BusinessType.AFR_REPORT,
SENDTYPE = sendType switch { 1 or 2 => 0, 3 => 1, _ => throw new NotImplementedException() },
//BSNO = oid.ToString(),
//MBLNO = master.MBLNO.ToString(),
}, houseList.Count);
if (!getfinrs.Status)
@ -781,14 +808,14 @@ namespace djy.Service.AFR
}
// 开始请求电子口岸的接口
var masterBillInfoStr = JsonConvert.SerializeObject(requestDto);
var masterBillInfoStr = JsonHelper.Instance.Serialize(requestDto);
var businessParam = new Dictionary<string, string>()
{
{ "masterBillInfo", masterBillInfoStr }
};
var param = BuildRequestParam(sendType, afrAccount, afrKey, businessParam);
var request = JsonConvert.SerializeObject(param);
var request = JsonHelper.Instance.Serialize(param);
var logGuid = Guid.NewGuid().ToString();
logger.LogInformation($"请求宁波电子口岸API{logGuid},入参:{request}");
@ -826,7 +853,7 @@ namespace djy.Service.AFR
HBLNO = dealHouseItem.HouseBillNo,
SENDUSERID = User.GID,
LURURENID = User.GID,
CtnrCount = dealHouseItem.CntrList?.Count ?? 0,
CtnrCount = 1,
CtnrInfo = string.Empty,
BSTYPE = BusinessType.AFR_REPORT,
SENDTYPE = sendType switch { 1 or 2 => 0, 3 => 1, _ => -1 },
@ -844,18 +871,31 @@ namespace djy.Service.AFR
logger.LogError($"执行扣费时发生未知异常,{logGuid},异常信息:{ex.Message}");
}
// 保存状态
}
// 记录历史
#endregion
var pidList = houseList.Select(h => h.PID);
var state = sendType switch { 1 => "新增发送成功", 2 => "重发成功", 3 => "修改发送成功", _ => "" };
await BuildAFRMasterHistoryAsync(masterItem.GID, houseList.Select(h => h.GID), state, 0, "发送了单据");
#endregion
// 保存状态
var hidList = houseList.Select(h => h.GID);
await DbAMS.Update<AFRHouse>()
.Set(h => h.StateIsSend == true)
.Set(h => h.NewNotice == state)
.SetIf(sendType == 2, h => h.StateIsDelete == false) //如果操作为重发,则把"删除发送"状态重置为“未删除发送”,这样后续才能重新 修改、删除
.Where(h => hidList.Contains(h.GID))
.ExecuteAffrowsAsync();
await DbAMS.Update<AFRMaster>()
.Set(h => h.StateIsSend == true) // 把主单的状态改为“已发送”,这样主单才会在“已发送”页面显示
.Where(h => pidList.Contains(h.GID))
.ExecuteAffrowsAsync();
// 记录历史
await SaveHistoryAsync(masterItem.GID, houseList, state, 0, "发送了单据");
}
else
{
throw new Exception($"电子口岸接口返回失败结果(code:{code2},msg:{msg})");
throw new Exception($"电子口岸接口返回失败结果(code:{code2},msg:{msg2})");
}
}
else
@ -865,11 +905,17 @@ namespace djy.Service.AFR
}
catch (Exception ex)
{
// 记录历史
var state = sendType switch { 1 => "新增发送失败", 2 => "重发失败", 3 => "修改发送失败", _ => "" };
await BuildAFRMasterHistoryAsync(masterItem.GID, houseList.Select(h => h.GID), state, 0, $"发送单据失败,失败原因:{ex.Message}");
await SaveHistoryAsync(masterItem.GID, houseList, state, 0, $"发送单据失败,失败原因:{ex.Message}");
// 保存状态
var hidList = houseList.Select(h => h.GID);
await DbAMS.Update<AFRHouse>()
.Set(h => h.NewNotice == state)
.Where(h => hidList.Contains(h.GID))
.ExecuteAffrowsAsync();
// 构建响应
string tip;
@ -883,6 +929,8 @@ namespace djy.Service.AFR
}
messageBuilder.Append(tip);
isFullSuccess = false;
// 继续处理下一单
continue;
}
@ -894,6 +942,13 @@ namespace djy.Service.AFR
try
{
#region 发送前的各项校验
// 待发送记录不能有“已删除”的
if (houseAll.Any(h => h.StateIsDelete))
{
string tip = string.Join("、", houseAll.Where(h => h.StateIsDelete).Select(h => h.HouseBillNo).ToList());
throw new Exception($"所选分单中存在已经“删除发送”的记录,分单号:【{tip}】,请重新选择(已“删除发送”的记录需要先进行“重发”,才能进行 “修改发送”或“删除发送” 操作)");
}
// 验证账户余额是否充足
var fin = new FinanceService();
var getfinrs = fin.CheckBalance(new CustFee
@ -917,7 +972,7 @@ namespace djy.Service.AFR
};
var param = BuildRequestParam(sendType, afrAccount, afrKey, businessParam);
var request = JsonConvert.SerializeObject(param);
var request = JsonHelper.Instance.Serialize(param);
var logGuid = Guid.NewGuid().ToString();
logger.LogInformation($"请求宁波电子口岸API{logGuid},入参:{request}");
@ -976,17 +1031,23 @@ namespace djy.Service.AFR
continue;
}
// 记录历史
await BuildAFRMasterHistoryAsync(expendMasterItem.GID, new string[] { expendHouseItem.GID }, "删除发送成功", 0, "删除发送了单据");
// 保存状态
await SaveHistoryAsync(expendMasterItem.GID, new AFRHouse[] { expendHouseItem }, "删除发送成功", 0, "删除发送了单据");
}
// 保存状态
var hidList = houseAll.Select(h => h.GID);
await DbAMS.Update<AFRHouse>()
.Set(h => h.NewNotice == "删除发送成功")
.Set(h => h.StateIsDelete == true)
.Set(h => h.StateIsAccept == false) //@铁幕 何工,如果有一票我这收到了回执推送,然后我 删除 并 重发 了这票,那后续我还会再收到完整的回执推送吗? ————会的
.Set(h => h.StateIsMatched == false) //@铁幕 何工,如果有一票我这收到了回执推送,然后我 删除 并 重发 了这票,那后续我还会再收到完整的回执推送吗? ————会的
.Where(h => hidList.Contains(h.GID))
.ExecuteAffrowsAsync();
#endregion
}
else
{
throw new Exception($"电子口岸接口返回失败结果(code:{code2},msg:{msg})");
throw new Exception($"电子口岸接口返回失败结果(code:{code2},msg:{msg2})");
}
}
else
@ -1003,44 +1064,86 @@ namespace djy.Service.AFR
// 记录历史
houseAll.ForEach(async h =>
{
await BuildAFRMasterHistoryAsync(h.PID, new string[] { h.GID }, "删除发送失败", 0, $"删除发送单据失败,原因:{ex.Message}");
await SaveHistoryAsync(h.PID, new AFRHouse[] { h }, "删除发送失败", 0, $"删除发送单据失败,原因:{ex.Message}");
});
// 保存状态
var hidList = houseAll.Select(h => h.GID);
await DbAMS.Update<AFRHouse>()
.Set(h => h.NewNotice == "删除发送失败")
.Where(h => hidList.Contains(h.GID))
.ExecuteAffrowsAsync();
isFullSuccess = false;
}
}
#endregion
return (isFullSuccess, messageBuilder.ToString());
}
public async Task SaveReceipt(AFRReceiptDto input)
{
if (string.IsNullOrEmpty(input.businessId))
{
logger.LogError("接收到回执中businessId为空");
return;
}
var house = await DbAMS.Select<AFRHouse>()
.Where(h => h.HouseBillNo == input.businessId && h.IsDel == false)
.FirstAsync();
if (house == null)
{
logger.LogError("接收到回执后根据businessId未查到AFRHouse");
return;
}
var update = DbAMS.Update<AFRHouse>()
.Set(h => h.NewNotice == input.content);
// Accept、Warning、Reject、Matched、Hold、Cancel
string statusDesc = string.Empty;
switch (input.status)
{
case "Accept":
update.Set(h => h.StateIsAccept == true);
statusDesc = "海关接收";
break;
case "Matched":
update.Set(h => h.StateIsMatched == true);
statusDesc = "已匹配";
break;
case "Warning": statusDesc = "警告"; break;
case "Reject": statusDesc = "海关拒绝"; break;
case "Hold": statusDesc = "海关监控"; break;
case "Cancel": statusDesc = "海关删除"; break;
default: break;
}
// 更新AFRHouse的状态
await update.Where(h => h.GID == house.GID)
.ExecuteAffrowsAsync();
// 记录历史
await SaveHistoryAsync(house.PID, new AFRHouse[] { house }, statusDesc, 1, input.content);
return messageBuilder.ToString();
//var method = sendType switch
//{
// 1 => "eportyun.manifest.afr.sendBill",
// 2 => "eportyun.manifest.afr.resendBill",
// 3 => "eportyun.manifest.afr.modifyBill",
// 4 => "eportyun.manifest.afr.deleteBill",
// _ => throw new Exception()
//};
//// 原始重发 || 修改发送
//else if (sendType == 2 || sendType == 3)
//{
// foreach (string id in idArr)
// {
// var param = new
// {
// method = sendType switch
// {
// 2 => "eportyun.manifest.afr.sendBill",
// 3 => "eportyun.manifest.afr.modifyBill",
// _ => throw new Exception()
// },
// masterBillInfo = "",
// };
// }
//}
return;
}
public async Task<List<AFRMasterHistory>> GetHistory(string id, string hid)
{
var data = await DbAMS.Select<AFRMasterHistory>()
.WhereIf(!string.IsNullOrEmpty(id), h => h.PID == id)
.WhereIf(!string.IsNullOrEmpty(hid), h => h.HID == hid)
.OrderByDescending(h => h.CreateTime)
.ToListAsync();
return data;
}
private SortedDictionary<string, string> BuildRequestParam(int sendType, string afrAccount, string afrKey, Dictionary<string, string> businessParam)
{
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
@ -1078,18 +1181,49 @@ namespace djy.Service.AFR
param.Add("sign", builder.ToString().ToMd5().ToUpper());
return param;
}
public Task SaveReceipt(AFRReceiptDto input)
/// <summary>
/// 保存操作历史或回执接收历史
/// </summary>
/// <param name="mid">主单主键</param>
/// <param name="hids">分单主键列表</param>
/// <param name="state">状态</param>
/// <param name="type">0人工操作历史1回执接收历史</param>
/// <param name="remark"></param>
/// <param name="tran"></param>
/// <returns></returns>
private async Task SaveHistoryAsync(string mid, IEnumerable<AFRHouse> houseList, string state, int type, string remark, DbTransaction tran = null)
{
List<AFRMasterHistory> list = new(houseList.Count());
foreach (AFRHouse item in houseList)
{
throw new NotImplementedException();
var history = new AFRMasterHistory()
{
GID = Guid.NewGuid().ToString(),
CreateTime = DateTime.Now,
Operator = type == 0 ? User.ShowName : "系统管理员",
PID = mid,
HID = item.GID,
State = state,
Type = Convert.ToByte(type)
};
if (type == 0)
{
history.Remark = $"{history.Operator} 于 {(DateTime)history.CreateTime:yyyy-MM-dd HH:mm:ss} {remark}";
}
public async Task<List<AFRMasterHistory>> GetHistory(string mid, string hid)
else if (type == 1)
{
var data = await DbAMS.Select<AFRMasterHistory>()
.WhereIf(!string.IsNullOrEmpty(mid), h => h.MID == mid)
.WhereIf(!string.IsNullOrEmpty(hid), h => h.HID == hid)
.ToListAsync();
return data;
history.Remark = $"您的单据 {item.HouseBillNo} 于 {(DateTime)history.CreateTime:yyyy-MM-dd HH:mm:ss} 接收到回执:{remark}";
}
list.Add(history);
}
if (tran == null)
{
await DbAMS.Insert(list).ExecuteAffrowsAsync();
}
else
{
await DbAMS.Insert(list).WithTransaction(tran).ExecuteAffrowsAsync();
}
}
}
}

@ -2,7 +2,6 @@
using djy.IService.Djy;
using djy.Model;
using Microsoft.AspNetCore.Http;
using System;
using System.Linq;
namespace djy.Service.DjyService
@ -34,13 +33,13 @@ namespace djy.Service.DjyService
accessor.HttpContext.Items["CurrentUser"] = userTemp.Data;
return userTemp.Data;
}
throw new Exception("登录失效");
return null;
//throw new Exception("未登录");
}
}
public string CompId => CurrentUser.CompId;
public string CompName => CurrentUser.COMNAME;
public string GID => CurrentUser.GID;
public string ShowName => CurrentUser.SHOWNAME;
public string CompId => CurrentUser?.CompId;
public string CompName => CurrentUser?.COMNAME;
public string GID => CurrentUser?.GID;
public string ShowName => CurrentUser?.SHOWNAME;
}
}

@ -105,8 +105,15 @@ namespace djy_AfrApi.Controllers
[HttpGet("Send")]
public async Task<Response> Send(string ids, string hids, [Required] int sendType)
{
string message = await _afrService.Send(ids, hids, sendType);
return SuccessResp(message);
var result = await _afrService.Send(ids, hids, sendType);
if (result.isSuccess)
{
return SuccessResp(result.message);
}
else
{
return FaildResp(result.message);
}
}
/// <summary>
@ -126,13 +133,13 @@ namespace djy_AfrApi.Controllers
/// <summary>
/// 获取历史记录
/// </summary>
/// <param name="mid">主单主键</param>
/// <param name="id">主单主键</param>
/// <param name="hid">分单主键</param>
/// <returns>历史记录列表</returns>
[HttpGet("GetHistory")]
public async Task<Response<List<AFRMasterHistory>>> GetHistory([Required] string mid, string hid)
public async Task<Response<List<AFRMasterHistory>>> GetHistory(string id, string hid)
{
var data = await _afrService.GetHistory(mid, hid);
var data = await _afrService.GetHistory(id, hid);
return SuccessResp(data);
}

@ -55,6 +55,15 @@ namespace djy_AfrApi.Controllers
Result = result
};
}
[NonAction]
protected Response FaildResp(string message = "操作失败")
{
return new Response()
{
Code = 500,
Message = message,
};
}
#endregion

@ -36,7 +36,7 @@ namespace djy_AfrApi.Filter
context.Result = res;
//进行错误日志记录
_logger.LogError(WriteLog("GlobalExceptionsFilter中捕获的全局异常", context.Exception));
_logger.LogError(WriteLog($"GlobalExceptionsFilter中捕获的全局异常TraceIdentifier{context.HttpContext?.TraceIdentifier}", context.Exception));
}
/// <summary>

@ -37,7 +37,7 @@ namespace djy_AfrApi.Middlewares
{
if (e == null) return;
logger.LogError(WriteLog("ExceptionHandlerMiddleware中捕获的全局异常", e));
logger.LogError(WriteLog($"ExceptionHandlerMiddleware中捕获的全局异常TraceIdentifier{context.TraceIdentifier}", e));
await WriteExceptionAsync(context, e).ConfigureAwait(false);
}

@ -28,13 +28,6 @@ namespace djy_AfrApi.Milldlewares
var endpoint = context.GetEndpoint();
if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() == null && context.Request.Path.Value.ToLower().Contains("/api/afr"))
{
// 因为ISF/AMS这步验证始终都无效所以这里先不做验证
//if (context.Request.Path.Value.Contains("/Load"))
//{
// var userId = context.User?.Claims?.FirstOrDefault(c => c.Type == "loginid")?.Value;
// var aut = _userService.GetUserAuthority(Guid.Parse(userId), "modAfrList");
//}
var userId = context.User?.Claims?.FirstOrDefault(c => c.Type == "loginid")?.Value;
var user = _userService.GetUserInfo(userId);
if (user.Data == null)

@ -6,7 +6,7 @@
<Project>
<PropertyGroup>
<_PublishTargetUrl>D:\DJY\Code\djyweb_ams\web\djy_AfrApi\bin\Release\net5.0\publish-windows\</_PublishTargetUrl>
<History>True|2024-01-03T13:54:40.3579096Z;True|2024-01-03T21:52:09.6604718+08:00;True|2024-01-03T16:04:13.6208067+08:00;True|2024-01-03T15:07:08.9376581+08:00;True|2024-01-02T10:57:59.7067270+08:00;True|2024-01-02T10:28:44.8223638+08:00;True|2023-12-29T17:26:12.9612280+08:00;</History>
<History>True|2024-01-05T03:59:09.7697688Z;True|2024-01-05T11:33:19.2093394+08:00;True|2024-01-05T11:27:31.2454199+08:00;True|2024-01-05T11:20:20.5464568+08:00;True|2024-01-04T18:36:38.8259124+08:00;True|2024-01-04T15:54:57.9348895+08:00;True|2024-01-04T15:44:34.6535493+08:00;False|2024-01-04T15:44:20.9673752+08:00;True|2024-01-04T11:14:33.4379160+08:00;True|2024-01-03T21:54:40.3579096+08:00;True|2024-01-03T21:52:09.6604718+08:00;True|2024-01-03T16:04:13.6208067+08:00;True|2024-01-03T15:07:08.9376581+08:00;True|2024-01-02T10:57:59.7067270+08:00;True|2024-01-02T10:28:44.8223638+08:00;True|2023-12-29T17:26:12.9612280+08:00;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>

@ -139,12 +139,12 @@ namespace djy_AfrApi
app.UseRouting();
//DefaultFilesOptions defaultFiles = new DefaultFilesOptions();
//defaultFiles.DefaultFileNames.Clear();
//defaultFiles.DefaultFileNames.Add("index.html");
//app.UseDefaultFiles(defaultFiles);
DefaultFilesOptions defaultFiles = new DefaultFilesOptions();
defaultFiles.DefaultFileNames.Clear();
defaultFiles.DefaultFileNames.Add("index.html");
app.UseDefaultFiles(defaultFiles);
//app.UseStaticFiles();
app.UseStaticFiles();
//跨域处理
app.UseCors(builder =>

@ -30,7 +30,7 @@
"Rbmq_Password": "admin",
"Rbmq_Sqlhost": "Data Source =60.209.125.238; Initial Catalog=djy_logs; Persist Security Info=True; User ID =sa; Password=Djy@Sql2022.test;pooling=true",
"DapperDbString": "Data Source =60.209.125.238,32009; Initial Catalog=DevAMS; Persist Security Info=True; User ID =sa; Password=Djy@Sql2022.test;pooling=true;",
"requesterDea": "HWCDDS",
"requesterDea": "SHBR",
"DataConnList": [
{
"SysKey": "AMS",

@ -23,14 +23,14 @@
"ConnName": "sqldb",
"cache_time": 10,
"WebHostUrl": "https://zh-userapi.jingyiji.net",
"Redis": "172.31.85.169:6379,defaultDatabase=待配置,",
"RedisDb": "待配置",
"Redis": "172.31.85.169:6379,defaultDatabase=待配置待配置待配置待配置待配置待配置待配置待配置,",
"RedisDb": "待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置",
"Rbmq_Host": "172.31.85.169:13866",
"Rbmq_UserName": "ams",
"Rbmq_Password": "djy_ams",
"Rbmq_Sqlhost": "Data Source =172.31.85.154; Initial Catalog=djy_logs; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true",
"DapperDbString": "Data Source =172.31.85.161; Initial Catalog=AMS; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true;",
"requesterDea": "HWCDDS",
"requesterDea": "待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置待配置",
"DataConnList": [
{
"SysKey": "AMS",

@ -23,7 +23,7 @@
"ConnName": "sqldb",
"cache_time": 10,
"WebHostUrl": "http://127.0.0.1:30818",
"Redis": "192.168.1.83:6379,password=,defaultDatabase=12",
"Redis": "127.0.0.1:6379,password=,defaultDatabase=12",
"RedisDb": "12",
"Rbmq_Host": "",
"Rbmq_UserName": "admin",

Loading…
Cancel
Save