diff --git a/web/Djy.Common/Common.xml b/web/Djy.Common/Common.xml index fcf219e..ff427b7 100644 --- a/web/Djy.Common/Common.xml +++ b/web/Djy.Common/Common.xml @@ -116,6 +116,11 @@ ISF-bond使用费代码;名称为“ISF-bond使用费” + + + AFR申报代码;名称为“AFR申报” + + 流程状态 diff --git a/web/Djy.Common/Const/BusinessType.cs b/web/Djy.Common/Const/BusinessType.cs index cad7095..679632f 100644 --- a/web/Djy.Common/Const/BusinessType.cs +++ b/web/Djy.Common/Const/BusinessType.cs @@ -19,5 +19,10 @@ /// ISF-bond使用费代码;名称为“ISF-bond使用费” /// public const int ISF_BOUND = 26; + + /// + /// AFR申报代码;名称为“AFR申报” + /// + public const int AFR_REPORT = 999; } } diff --git a/web/djy.IService/Afr/IAfrService.cs b/web/djy.IService/Afr/IAfrService.cs index f8cda5f..8ae8d3e 100644 --- a/web/djy.IService/Afr/IAfrService.cs +++ b/web/djy.IService/Afr/IAfrService.cs @@ -25,6 +25,6 @@ namespace djy.IService.Afr Task Delete(string ids); Task Send(string ids, string hids, int sendType); Task SaveReceipt(AFRReceiptDto input); - Task> GetHistory(string id); + Task> GetHistory(string mid, string hid); } } diff --git a/web/djy.Model/AFR/AFRHouse.cs b/web/djy.Model/AFR/AFRHouse.cs index 7d1cbac..598045c 100644 --- a/web/djy.Model/AFR/AFRHouse.cs +++ b/web/djy.Model/AFR/AFRHouse.cs @@ -53,9 +53,9 @@ namespace djy.Model.Afr public bool StateIsMatched { get; set; } /// - /// 最新状态内容 + /// 最新通知 /// - public string StateContent { get; set; } + public string NewNotice { get; set; } /// /// 通知人地址 diff --git a/web/djy.Model/AFR/AFRMaster.cs b/web/djy.Model/AFR/AFRMaster.cs index 14f900c..caafc5c 100644 --- a/web/djy.Model/AFR/AFRMaster.cs +++ b/web/djy.Model/AFR/AFRMaster.cs @@ -145,7 +145,7 @@ namespace djy.Model.Afr /// /// 操作历史 /// - [Navigate(nameof(AFRMasterHistory.PID))] + [Navigate(nameof(AFRMasterHistory.MID))] public AFRMasterHistory History { get; set; } #endregion diff --git a/web/djy.Model/AFR/AFRMasterHistory.cs b/web/djy.Model/AFR/AFRMasterHistory.cs index 0da25c4..5481bac 100644 --- a/web/djy.Model/AFR/AFRMasterHistory.cs +++ b/web/djy.Model/AFR/AFRMasterHistory.cs @@ -20,9 +20,13 @@ namespace djy.Model.Afr public string Operator { get; set; } /// - /// + /// Master表主键 + /// + public string MID { get; set; } + /// + /// House表主键 /// - public string PID { get; set; } + public string HID { get; set; } /// /// diff --git a/web/djy.Service/Afr/AfrService.cs b/web/djy.Service/Afr/AfrService.cs index da2300e..7846875 100644 --- a/web/djy.Service/Afr/AfrService.cs +++ b/web/djy.Service/Afr/AfrService.cs @@ -1,4 +1,6 @@ -using Common; +using AutoMapper; +using Common; +using Common.Const; using Common.DJYModel; using Common.Extensions; using Common.Tools; @@ -17,14 +19,17 @@ using NETCore.Encrypt.Internal; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NPOI.SS.Formula.Functions; +using Org.BouncyCastle.Ocsp; using System; using System.Collections.Generic; using System.Data.Common; using System.Linq; +using System.Security.Cryptography; using System.Security.Policy; using System.Security.Principal; using System.Text; using System.Threading.Tasks; +using static NPOI.HSSF.Util.HSSFColor; namespace djy.Service.AFR { @@ -262,7 +267,7 @@ namespace djy.Service.AFR .ToListAsync(); histories.ForEach(item => { - var master = result.FirstOrDefault(m => m.GID == item.PID); + var master = result.FirstOrDefault(m => m.GID == item.MID); if (master == null) return; master.History = item; }); @@ -334,8 +339,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(); - AFRMasterHistory history = BuildAFRMasterHistory(input.GID, "新增", 0, "创建了单据"); - await DbAMS.Insert(history).WithTransaction(tran).ExecuteAffrowsAsync(); + await BuildAFRMasterHistoryAsync(input.GID, input.HouseList.Select(h => h.GID), "新增", 0, "创建了单据", tran); tran.Commit(); } @@ -448,6 +452,8 @@ namespace djy.Service.AFR if (waitInsertHouseGids.Any()) { await DbAMS.Insert(waitInsertHouseList).WithTransaction(tran).ExecuteAffrowsAsync(); + + await BuildAFRMasterHistoryAsync(input.GID, waitInsertHouseGids, "新增", 0, "新增了单据", tran); } if (waitDeleteHouseGids.Any()) { @@ -457,14 +463,18 @@ namespace djy.Service.AFR .WithTransaction(tran) .Where(h => waitDeleteHouseGids.Contains(h.GID)) .ExecuteAffrowsAsync(); + + await BuildAFRMasterHistoryAsync(input.GID, waitDeleteHouseGids, "删除", 0, "删除了单据", tran); } if (waitUpdateHouseGids.Any()) { await DbAMS.Update() .SetSource(waitUpdateHouseList) - .IgnoreColumns(h => new { h.StateIsMatched, h.StateIsAccept }) + .IgnoreColumns(h => new { h.StateIsMatched, h.StateIsAccept, h.StateIsSend, h.NewNotice }) .WithTransaction(tran) .ExecuteAffrowsAsync(); + + await BuildAFRMasterHistoryAsync(input.GID, waitUpdateHouseGids, "修改", 0, "修改了单据", tran); } // 箱子执行 @@ -488,28 +498,38 @@ namespace djy.Service.AFR } #endregion - AFRMasterHistory history = BuildAFRMasterHistory(input.GID, "修改", 0, "修改了单据"); - await DbAMS.Insert(history).WithTransaction(tran).ExecuteAffrowsAsync(); - tran.Commit(); } return await Get(input.GID); } - private AFRMasterHistory BuildAFRMasterHistory(string pid, string state, int type, string remark) + private async Task BuildAFRMasterHistoryAsync(string mid, IEnumerable hids, string state, int type, string remark, DbTransaction tran = null) { - var history = new AFRMasterHistory() - { - GID = Guid.NewGuid().ToString(), - CreateTime = DateTime.Now, - Operator = User.ShowName, - PID = pid, - State = state, - Type = Convert.ToByte(type) - }; - history.Remark = $"{history.Operator}于{(DateTime)history.CreateTime:yyyy-MM-dd HH:mm:ss}{remark}"; - return history; + List 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) @@ -545,7 +565,7 @@ namespace djy.Service.AFR public async Task Send(string ids, string hids, int sendType) { - + //return "发送成功"; #region 查询电子口岸的请求参数 var paramSets = await DbBus.Get(DbList.djydb).Select().Where(x => x.PARAMNAME == "AFRURL" || x.PARAMNAME == "AFRAccount" || x.PARAMNAME == "AFRKey").ToListAsync(p => new { @@ -582,7 +602,7 @@ namespace djy.Service.AFR var houseGids = houseAll.Select(h => h.GID); cntrAll = await DbAMS.Select().Where(c => houseGids.Contains(c.PID)).ToListAsync(); } - else if (sendType is 2 or 3) + else if (sendType is 2 or 3 or 4) { if (string.IsNullOrEmpty(hids)) { @@ -602,20 +622,20 @@ namespace djy.Service.AFR var housePids = houseAll.Select(h => h.PID); masterAll = await DbAMS.Select().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(','); + //else if (sendType is 4) + //{ + // if (string.IsNullOrEmpty(hids)) + // { + // throw new ArgumentNullException(nameof(hids)); + // } + // var hidArr = hids.Split(','); - houseAll = await DbAMS.Select().Where(h => h.IsDel == false && hidArr.Contains(h.GID)).ToListAsync(); - if (houseAll.Count != hidArr.Length) - { - throw new Exception("所选记录有些已被删除,请刷新页面后重试"); - } - } + // houseAll = await DbAMS.Select().Where(h => h.IsDel == false && hidArr.Contains(h.GID)).ToListAsync(); + // if (houseAll.Count != hidArr.Length) + // { + // throw new Exception("所选记录有些已被删除,请刷新页面后重试"); + // } + //} #endregion StringBuilder messageBuilder = new(); @@ -630,13 +650,39 @@ namespace djy.Service.AFR try { - #region 发送前的参数验证 + #region 发送前的各项校验 + // 判断是否有分单数据 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】时,【交货地全称】与【交货地五字码】为必填项"); } + + // 验证账户余额是否充足 + 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) + { + throw new Exception(getfinrs.Message); + } #endregion AFRRequestDto requestDto = new AFRRequestDto() @@ -765,6 +811,47 @@ namespace djy.Service.AFR { string tip = $"发送成功!船东提单号:【{masterItem.MBLNO}】货代提单号:【{string.Join("、", houseList.Select(h => h.HouseBillNo))}】{Environment.NewLine}"; messageBuilder.Append(tip); + + #region 扣费、保存状态 + foreach (AFRHouse dealHouseItem in houseList) + { + try + { + var expendResult = fin.Expend(new CustFee + { + CARRIER = masterItem.ShipCompanyCode, + ETD = null, + VOYNO = masterItem.Voyno, + VESSEL = masterItem.Vessel, + HBLNO = dealHouseItem.HouseBillNo, + SENDUSERID = User.GID, + LURURENID = User.GID, + CtnrCount = dealHouseItem.CntrList?.Count ?? 0, + CtnrInfo = string.Empty, + BSTYPE = BusinessType.AFR_REPORT, + SENDTYPE = sendType switch { 1 or 2 => 0, 3 => 1, _ => -1 }, + BSNO = masterItem.GID, + MBLNO = masterItem.MBLNO, + }, 1); + + if (!expendResult.Status) + { + logger.LogError($"执行扣费失败,{logGuid},异常信息:{expendResult.Message}"); + } + } + catch (Exception ex) + { + logger.LogError($"执行扣费时发生未知异常,{logGuid},异常信息:{ex.Message}"); + } + + // 保存状态 + } + + // 记录历史 + var state = sendType switch { 1 => "新增发送成功", 2 => "重发成功", 3 => "修改发送成功", _ => "" }; + await BuildAFRMasterHistoryAsync(masterItem.GID, houseList.Select(h => h.GID), state, 0, "发送了单据"); + + #endregion } else { @@ -778,6 +865,13 @@ 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}"); + + // 保存状态 + + // 构建响应 string tip; if (houseList == null) { @@ -788,6 +882,8 @@ namespace djy.Service.AFR tip = $"发送失败!船东提单号:【{masterItem.MBLNO}】货代提单号:【{string.Join("、", houseList.Select(h => h.HouseBillNo))}】,原因:{ex.Message}{Environment.NewLine}"; } messageBuilder.Append(tip); + + // 继续处理下一单 continue; } } @@ -797,6 +893,22 @@ namespace djy.Service.AFR { try { + #region 发送前的各项校验 + // 验证账户余额是否充足 + var fin = new FinanceService(); + var getfinrs = fin.CheckBalance(new CustFee + { + LURURENID = User.GID, + BSTYPE = BusinessType.AFR_REPORT, + SENDTYPE = 5, + }, houseAll.Count); + + if (!getfinrs.Status) + { + throw new Exception(getfinrs.Message); + } + #endregion + string hbnos = string.Join(',', houseAll.Select(h => h.HouseBillNo)); var businessParam = new Dictionary() { @@ -813,45 +925,88 @@ namespace djy.Service.AFR logger.LogInformation($"请求宁波电子口岸API,{logGuid},响应:{response}"); - //JObject rlt = JObject.Parse(response); - //var code = rlt.GetValue("code")?.ToString(); - //var msg = rlt.GetValue("msg")?.ToString(); - //if (code == "T") - //{ - // var data = rlt["data"] as JObject; - - // var code2 = data.GetValue("code")?.ToString(); - // var msg2 = data.GetValue("msg")?.ToString(); - // var data2 = data.GetValue("data")?.ToString(); - - // if (code2 == "1") - // { - // string tip = $"发送成功!船东提单号:【{masterItem.MBLNO}】货代提单号:【{string.Join("、", houseList.Select(h => h.HouseBillNo))}】{Environment.NewLine}"; - // messageBuilder.Append(tip); - // } - // else - // { - // throw new Exception($"电子口岸接口返回失败结果(code:{code2},msg:{msg})"); - // } - //} - //else - //{ - // throw new Exception($"电子口岸接口调用失败(msg:{msg})"); - //} + JObject rlt = JObject.Parse(response); + var code = rlt.GetValue("code")?.ToString(); + var msg = rlt.GetValue("msg")?.ToString(); + if (code == "T") + { + var data = rlt["data"] as JObject; + + var code2 = data.GetValue("code")?.ToString(); + var msg2 = data.GetValue("msg")?.ToString(); + var data2 = data.GetValue("data")?.ToString(); + + if (code2 == "1") + { + string tip = $"发送成功!货代提单号:【{string.Join("、", houseAll.Select(h => h.HouseBillNo))}】{Environment.NewLine}"; + messageBuilder.Append(tip); + + #region 扣费、记录历史、保存状态 + foreach (AFRHouse expendHouseItem in houseAll) + { + AFRMaster expendMasterItem = masterAll.First(m => m.GID == expendHouseItem.PID); + // 扣费 + try + { + var expendResult = fin.Expend(new CustFee + { + CARRIER = expendMasterItem.ShipCompanyCode, + ETD = null, + VOYNO = expendMasterItem.Voyno, + VESSEL = expendMasterItem.Vessel, + HBLNO = expendHouseItem.HouseBillNo, + SENDUSERID = User.GID, + LURURENID = User.GID, + CtnrCount = cntrAll.Count(c => c.PID == expendHouseItem.GID), + CtnrInfo = string.Empty, + BSTYPE = BusinessType.AFR_REPORT, + SENDTYPE = 5, + BSNO = expendMasterItem.GID, + MBLNO = expendMasterItem.MBLNO, + }, 1); + + if (!expendResult.Status) + { + logger.LogError($"执行扣费失败,{logGuid},异常信息:{expendResult.Message}"); + } + } + catch (Exception ex) + { + logger.LogError($"执行扣费时发生未知异常,{logGuid},异常信息:{ex.Message}"); + continue; + } + // 记录历史 + await BuildAFRMasterHistoryAsync(expendMasterItem.GID, new string[] { expendHouseItem.GID }, "删除发送成功", 0, "删除发送了单据"); + + // 保存状态 + } + + + #endregion + } + else + { + throw new Exception($"电子口岸接口返回失败结果(code:{code2},msg:{msg})"); + } + } + else + { + throw new Exception($"电子口岸接口调用失败(msg:{msg})"); + } } catch (Exception ex) { - //string tip; - //if (houseList == null) - //{ - // tip = $"发送失败!船东提单号:【{masterItem.MBLNO}】,原因:{ex.Message}{Environment.NewLine}"; - //} - //else - //{ - // tip = $"发送失败!船东提单号:【{masterItem.MBLNO}】货代提单号:【{string.Join("、", houseList.Select(h => h.HouseBillNo))}】,原因:{ex.Message}{Environment.NewLine}"; - //} - //messageBuilder.Append(tip); - //continue; + // 构建响应 + string tip = $"发送失败!货代提单号:【{string.Join("、", houseAll.Select(h => h.HouseBillNo))}】,原因:{ex.Message}"; + messageBuilder.Append(tip); + + // 记录历史 + houseAll.ForEach(async h => + { + await BuildAFRMasterHistoryAsync(h.PID, new string[] { h.GID }, "删除发送失败", 0, $"删除发送单据失败,原因:{ex.Message}"); + }); + + // 保存状态 } } #endregion @@ -928,10 +1083,11 @@ namespace djy.Service.AFR throw new NotImplementedException(); } - public async Task> GetHistory(string id) + public async Task> GetHistory(string mid, string hid) { var data = await DbAMS.Select() - .Where(h => h.PID == id) + .WhereIf(!string.IsNullOrEmpty(mid), h => h.MID == mid) + .WhereIf(!string.IsNullOrEmpty(hid), h => h.HID == hid) .ToListAsync(); return data; } diff --git a/web/djy.Service/DjyService/FinanceService.cs b/web/djy.Service/DjyService/FinanceService.cs index fa2219d..25f4a4a 100644 --- a/web/djy.Service/DjyService/FinanceService.cs +++ b/web/djy.Service/DjyService/FinanceService.cs @@ -20,7 +20,7 @@ namespace djy.Service.DjyService /// /// /// - /// 1验证是否可以扣款 2扣除操作 + /// 1扣除操作 其他验证是否可以扣款 /// bond是否自有;值是:1或者2;1表示“自有BOND”,2表示“使用CargoEDI的BOND”;当值为2时,需要额外扣除ISF-Bond使用费 /// public ReturnResult Expend(CustFee Dto, int exptype, BondOwnTypeEnum? bondOwnType = null) @@ -216,5 +216,72 @@ namespace djy.Service.DjyService return rs; } + + + /// + /// 验证余额是否充足 + /// 验证的计费次数 + /// + public ReturnResult CheckBalance(CustFee Dto, int times) + { + _LogsAdd("Expend 验证余额是否充足", "open", Dto); + + var rs = new ReturnResult(); + try + { + if (Dto == null) + { + rs.Not("错误的null请求"); + return rs; + } + + if (Dto.BSTYPE == null || Dto.SENDTYPE == null) + { + rs.Not("请求的业务类型和发送类型不能为空!"); + return rs; + } + + if (Dto.LURURENID.IsNotNull()) + { + var luser = DbBus.Get(DbList.djydb).Select().Where(w => w.GID == Dto.LURURENID).ToOne(); + if (luser != null) + { + Dto.LURUREN = luser.SHOWNAME; + Dto.LURURENID = luser.GID; + Dto.COMNAME = luser.COMNAME; + Dto.COMID = luser.CompId; + } + } + + decimal price_total = 0; // 总金额 + + // 获取 计费规则 + CustPrice cp1 = DbBus.Get(DbList.djydb).Select().Where(w => w.BSTYPE == Dto.BSTYPE && w.SENDTYPE == Dto.SENDTYPE && w.COMID == Dto.COMID).ToOne(); + if (cp1 == null) + { + rs.Not("没有找到此业务的计费规则!"); + return rs; + } + price_total = ((decimal)cp1.PRICE) * times; + + var PayInfo = new { Total = price_total, Price = price_total, Count = Dto.CtnrCount }; + + if (DbBus.Get(DbList.djydb).Select().Where(a => a.Balance >= price_total && a.COMNAME == Dto.COMNAME).Count() > 0) + { + rs.Data = new { PayInfo }; + rs.OK("钱包金额充足"); + } + else + { + rs.Data = new { PayInfo }; + rs.Not("钱包金额不足"); + } + } + catch (Exception ex) + { + rs.Not(ex.Message); + } + return rs; + } } } diff --git a/web/djy_AfrApi/Controllers/AfrController.cs b/web/djy_AfrApi/Controllers/AfrController.cs index 2c57639..7f5fd61 100644 --- a/web/djy_AfrApi/Controllers/AfrController.cs +++ b/web/djy_AfrApi/Controllers/AfrController.cs @@ -126,12 +126,13 @@ namespace djy_AfrApi.Controllers /// /// 获取历史记录 /// - /// 主键 + /// 主单主键 + /// 分单主键 /// 历史记录列表 [HttpGet("GetHistory")] - public async Task>> GetHistory(string id) + public async Task>> GetHistory([Required] string mid, string hid) { - var data = await _afrService.GetHistory(id); + var data = await _afrService.GetHistory(mid, hid); return SuccessResp(data); } diff --git a/web/djy_AfrApi/Properties/PublishProfiles/FolderProfile-Windows.pubxml.user b/web/djy_AfrApi/Properties/PublishProfiles/FolderProfile-Windows.pubxml.user index 312dda1..fa9222e 100644 --- a/web/djy_AfrApi/Properties/PublishProfiles/FolderProfile-Windows.pubxml.user +++ b/web/djy_AfrApi/Properties/PublishProfiles/FolderProfile-Windows.pubxml.user @@ -6,7 +6,7 @@ <_PublishTargetUrl>D:\DJY\Code\djyweb_ams\web\djy_AfrApi\bin\Release\net5.0\publish-windows\ - True|2024-01-03T08:04:13.6208067Z;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; + 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; \ No newline at end of file