修复bug
This commit is contained in:
parent
daf573b94d
commit
4bd2585680
@ -225,6 +225,11 @@ public class CancelPreviewOutput
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal RefundableAmount { get; set; }
|
public decimal RefundableAmount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 历史已退款金额
|
||||||
|
/// </summary>
|
||||||
|
public decimal RefundedAmount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前选择的退款金额(动态计算)
|
/// 当前选择的退款金额(动态计算)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -319,29 +319,59 @@ namespace YD_Event.Application.Event;
|
|||||||
// 计算项目总时长(在查询前计算,避免在SQL中使用C#方法)
|
// 计算项目总时长(在查询前计算,避免在SQL中使用C#方法)
|
||||||
int projTotalDuration = proj.GetTotalDurationInSeconds();
|
int projTotalDuration = proj.GetTotalDurationInSeconds();
|
||||||
|
|
||||||
// 获取参赛人员,并关联用户和单位认证信息
|
// 第一步:先查询主要数据和相关的 MerchantCertificationId
|
||||||
var persons = await _personRepository.AsQueryable()
|
var basicPersons = await _personRepository.AsQueryable()
|
||||||
.InnerJoin<EventRegistration>((p, r) => p.RegistrationId == r.Id)
|
.InnerJoin<EventRegistration>((p, r) => p.RegistrationId == r.Id)
|
||||||
.LeftJoin<MerchantCertification>((p, r, m) => r.MerchantCertificationId == m.Id)
|
.Where((p, r) => p.ProjectId == eventProj.Id
|
||||||
.Where((p, r, m) => p.ProjectId == eventProj.Id
|
|
||||||
&& r.PaymentStatus != 4
|
&& r.PaymentStatus != 4
|
||||||
&& !p.DeleteMark
|
&& !p.DeleteMark
|
||||||
&& p.PersonType == PersonType.Athlete)
|
&& p.PersonType == PersonType.Athlete)
|
||||||
.OrderBy(p => p.GroupName)
|
.OrderBy(p => p.GroupName)
|
||||||
.OrderBy(p => p.Id)
|
.OrderBy(p => p.Id)
|
||||||
.Select((p, r, m) => new {
|
.Select((p, r) => new {
|
||||||
Id = p.Id, // 添加 Id 属性
|
Id = p.Id,
|
||||||
RegistrationItemId = p.RegistrationItemId,
|
RegistrationItemId = p.RegistrationItemId,
|
||||||
p.UserId,
|
p.UserId,
|
||||||
p.Name,
|
p.Name,
|
||||||
p.GroupName,
|
p.GroupName,
|
||||||
r.TeamName,
|
r.TeamName,
|
||||||
MerchantName = m.MerchantName ?? "",
|
r.MerchantCertificationId,
|
||||||
m.AuditStatus,
|
|
||||||
Duration = projTotalDuration
|
Duration = projTotalDuration
|
||||||
})
|
})
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
|
// 第二步:收集所有需要查询的 MerchantCertificationId
|
||||||
|
var merchantCertIds = basicPersons
|
||||||
|
.Where(x => x.MerchantCertificationId.HasValue)
|
||||||
|
.Select(x => x.MerchantCertificationId.Value)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// 第三步:批量查询 MerchantCertification
|
||||||
|
Dictionary<long, MerchantCertification> merchantDict = new Dictionary<long, MerchantCertification>();
|
||||||
|
if (merchantCertIds.Any())
|
||||||
|
{
|
||||||
|
var merchants = await _merchantCertificationRepository.GetListAsync(x => merchantCertIds.Contains(x.Id));
|
||||||
|
merchantDict = merchants.ToDictionary(x => x.Id, x => x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第四步:在内存中合并数据
|
||||||
|
var persons = basicPersons.Select(bp => new {
|
||||||
|
bp.Id,
|
||||||
|
bp.RegistrationItemId,
|
||||||
|
bp.UserId,
|
||||||
|
bp.Name,
|
||||||
|
bp.GroupName,
|
||||||
|
bp.TeamName,
|
||||||
|
MerchantName = bp.MerchantCertificationId.HasValue && merchantDict.ContainsKey(bp.MerchantCertificationId.Value)
|
||||||
|
? merchantDict[bp.MerchantCertificationId.Value].MerchantName
|
||||||
|
: null,
|
||||||
|
AuditStatus = bp.MerchantCertificationId.HasValue && merchantDict.ContainsKey(bp.MerchantCertificationId.Value)
|
||||||
|
? merchantDict[bp.MerchantCertificationId.Value].AuditStatus
|
||||||
|
: (AuditStatus?)null,
|
||||||
|
bp.Duration
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
if (!persons.Any()) continue;
|
if (!persons.Any()) continue;
|
||||||
|
|
||||||
// 计算项目总时长
|
// 计算项目总时长
|
||||||
@ -471,7 +501,14 @@ namespace YD_Event.Application.Event;
|
|||||||
var teamNameProp = personData.GetType().GetProperty("TeamName");
|
var teamNameProp = personData.GetType().GetProperty("TeamName");
|
||||||
|
|
||||||
string? merchantName = merchantNameProp?.GetValue(personData) as string;
|
string? merchantName = merchantNameProp?.GetValue(personData) as string;
|
||||||
AuditStatus? auditStatus = auditStatusProp?.GetValue(personData) as AuditStatus?;
|
var auditStatusValue = auditStatusProp?.GetValue(personData);
|
||||||
|
AuditStatus? auditStatus = null;
|
||||||
|
|
||||||
|
if (auditStatusValue != null && auditStatusValue is AuditStatus status)
|
||||||
|
{
|
||||||
|
auditStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
string? teamName = teamNameProp?.GetValue(personData) as string;
|
string? teamName = teamNameProp?.GetValue(personData) as string;
|
||||||
|
|
||||||
// 优先使用认证通过的单位名称
|
// 优先使用认证通过的单位名称
|
||||||
|
|||||||
@ -2468,10 +2468,21 @@ public class UnifiedRegistrationService : ITransient
|
|||||||
var items = await _db.Queryable<EventRegistrationItem>().Where(x => x.RegistrationId == registrationId).ToListAsync();
|
var items = await _db.Queryable<EventRegistrationItem>().Where(x => x.RegistrationId == registrationId).ToListAsync();
|
||||||
var persons = await _registrationPersonRepository.GetListAsync(x => x.RegistrationId == registrationId);
|
var persons = await _registrationPersonRepository.GetListAsync(x => x.RegistrationId == registrationId);
|
||||||
|
|
||||||
var refundableAmount = await CalculateRefundAmountAsync(registration.TotalAmount, eventInfo.MatchStartTime);
|
// 查询历史已退款金额
|
||||||
|
var historyRefunds = await _refundRecordRepository.GetListAsync(x => x.RegistrationId == registrationId && x.RefundStatus == 1);
|
||||||
|
var refundedAmount = historyRefunds.Sum(x => x.RefundAmount);
|
||||||
|
|
||||||
|
// 计算剩余未退款的原始金额
|
||||||
|
var remainingOriginalAmount = registration.TotalAmount - refundedAmount;
|
||||||
|
|
||||||
|
// 基于剩余金额计算可退款金额
|
||||||
|
var refundableAmount = await CalculateRefundAmountAsync(remainingOriginalAmount, eventInfo.MatchStartTime);
|
||||||
|
|
||||||
|
// 确保可退款金额不小于0
|
||||||
|
refundableAmount = Math.Max(0, refundableAmount);
|
||||||
|
|
||||||
_logger.LogInformation("统一取消报名预览:报名ID={RegistrationId}, 赛事名称={EventName}, 实际支付={ActualAmount}, 可退款={RefundAmount}, 支付方式={PaymentMethod}",
|
_logger.LogInformation("统一取消报名预览:报名ID={RegistrationId}, 赛事名称={EventName}, 实际支付={ActualAmount}, 已退款={RefundedAmount}, 剩余可退款={RefundAmount}, 支付方式={PaymentMethod}",
|
||||||
registrationId, eventInfo?.EventName, registration.TotalAmount, refundableAmount, registration.PaymentMethod);
|
registrationId, eventInfo?.EventName, registration.TotalAmount, refundedAmount, refundableAmount, registration.PaymentMethod);
|
||||||
|
|
||||||
// 获取组别信息(年龄和性别限制)
|
// 获取组别信息(年龄和性别限制)
|
||||||
var groupIds = items.Where(x => x.EventProjectGroupId.HasValue).Select(x => x.EventProjectGroupId.Value).Distinct().ToList();
|
var groupIds = items.Where(x => x.EventProjectGroupId.HasValue).Select(x => x.EventProjectGroupId.Value).Distinct().ToList();
|
||||||
@ -2501,6 +2512,7 @@ public class UnifiedRegistrationService : ITransient
|
|||||||
ChargeMode = (int)eventInfo.ChargeMode,
|
ChargeMode = (int)eventInfo.ChargeMode,
|
||||||
ActualPaidAmount = registration.TotalAmount,
|
ActualPaidAmount = registration.TotalAmount,
|
||||||
RefundableAmount = refundableAmount,
|
RefundableAmount = refundableAmount,
|
||||||
|
RefundedAmount = refundedAmount,
|
||||||
CurrentRefundAmount = refundableAmount,
|
CurrentRefundAmount = refundableAmount,
|
||||||
PaymentMethod = registration.PaymentMethod,
|
PaymentMethod = registration.PaymentMethod,
|
||||||
PaymentStatus = registration.PaymentStatus,
|
PaymentStatus = registration.PaymentStatus,
|
||||||
@ -2669,15 +2681,28 @@ public class UnifiedRegistrationService : ITransient
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询历史已退款金额
|
||||||
|
var historyRefunds = await _refundRecordRepository.GetListAsync(x => x.RegistrationId == registration.Id && x.RefundStatus == 1);
|
||||||
|
var refundedAmount = historyRefunds.Sum(x => x.RefundAmount);
|
||||||
|
|
||||||
|
// 计算剩余的原始未退款金额
|
||||||
|
var remainingOriginalAmount = registration.TotalAmount - refundedAmount;
|
||||||
|
|
||||||
|
// 如果没有剩余可退,直接返回0
|
||||||
|
if (remainingOriginalAmount <= 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// 全部取消
|
// 全部取消
|
||||||
if (input.CancelType == 0)
|
if (input.CancelType == 0)
|
||||||
{
|
{
|
||||||
return await CalculateRefundAmountAsync(registration.TotalAmount, eventInfo.MatchStartTime);
|
return await CalculateRefundAmountAsync(remainingOriginalAmount, eventInfo.MatchStartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 部分取消
|
// 部分取消
|
||||||
var baseRefundAmount = await CalculateRefundAmountAsync(registration.TotalAmount, eventInfo.MatchStartTime);
|
var baseRefundAmount = await CalculateRefundAmountAsync(remainingOriginalAmount, eventInfo.MatchStartTime);
|
||||||
var refundRatio = registration.TotalAmount > 0 ? baseRefundAmount / registration.TotalAmount : 1;
|
var refundRatio = remainingOriginalAmount > 0 ? baseRefundAmount / remainingOriginalAmount : 1;
|
||||||
|
|
||||||
var cancelMemberIds = input.PersonIds ?? new List<long>();
|
var cancelMemberIds = input.PersonIds ?? new List<long>();
|
||||||
var cancelTeams = input.CancelTeams ?? new List<string>();
|
var cancelTeams = input.CancelTeams ?? new List<string>();
|
||||||
@ -2712,7 +2737,9 @@ public class UnifiedRegistrationService : ITransient
|
|||||||
return baseRefundAmount;
|
return baseRefundAmount;
|
||||||
}
|
}
|
||||||
// 否则,按人数比例退款
|
// 否则,按人数比例退款
|
||||||
return baseRefundAmount * (decimal)cancelTeamMemberCount / persons.Count;
|
var fixedPriceCalculated = baseRefundAmount * (decimal)cancelTeamMemberCount / persons.Count;
|
||||||
|
// 确保不超过剩余可退款金额
|
||||||
|
return Math.Min(fixedPriceCalculated, baseRefundAmount);
|
||||||
|
|
||||||
case ChargeMode.UnitPriceEvent:
|
case ChargeMode.UnitPriceEvent:
|
||||||
// 单价(赛事):按取消人数计算
|
// 单价(赛事):按取消人数计算
|
||||||
@ -2732,8 +2759,10 @@ public class UnifiedRegistrationService : ITransient
|
|||||||
}
|
}
|
||||||
|
|
||||||
var cancelCount = allCancelMemberIds.Count;
|
var cancelCount = allCancelMemberIds.Count;
|
||||||
var unitPrice = persons.Count > 0 ? registration.TotalAmount / persons.Count : 0;
|
var unitPrice = persons.Count > 0 ? remainingOriginalAmount / persons.Count : 0;
|
||||||
return unitPrice * cancelCount * refundRatio;
|
var calculatedAmount = unitPrice * cancelCount * refundRatio;
|
||||||
|
// 确保不超过剩余可退款金额
|
||||||
|
return Math.Min(calculatedAmount, baseRefundAmount);
|
||||||
|
|
||||||
case ChargeMode.UnitPriceProject:
|
case ChargeMode.UnitPriceProject:
|
||||||
// 单价(项目):按每个项目的人数计算
|
// 单价(项目):按每个项目的人数计算
|
||||||
@ -2766,7 +2795,9 @@ public class UnifiedRegistrationService : ITransient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalCancelAmount * refundRatio;
|
var projectCalculatedAmount = totalCancelAmount * refundRatio;
|
||||||
|
// 确保不超过剩余可退款金额
|
||||||
|
return Math.Min(projectCalculatedAmount, baseRefundAmount);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -5034,6 +5034,11 @@
|
|||||||
可退款金额(全部取消时)
|
可退款金额(全部取消时)
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="P:YD_Event.Application.Event.Dtos.CancelPreviewOutput.RefundedAmount">
|
||||||
|
<summary>
|
||||||
|
历史已退款金额
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="P:YD_Event.Application.Event.Dtos.CancelPreviewOutput.CurrentRefundAmount">
|
<member name="P:YD_Event.Application.Event.Dtos.CancelPreviewOutput.CurrentRefundAmount">
|
||||||
<summary>
|
<summary>
|
||||||
当前选择的退款金额(动态计算)
|
当前选择的退款金额(动态计算)
|
||||||
|
|||||||
@ -53,7 +53,7 @@
|
|||||||
"SleepMs": 300,
|
"SleepMs": 300,
|
||||||
"dbconfig": {
|
"dbconfig": {
|
||||||
"ConnectionStrings": [
|
"ConnectionStrings": [
|
||||||
"8.153.108.90,Password=yd708090,SyncTimeout=15000,ConnectTimeout=15000,ResponseTimeout=15000,defaultDatabase=7,poolsize=100,ssl=false,writeBuffer=10240,idleTimeout=30000,connectRetry=3,asyncPipeline=false",
|
"8.153.108.90,Password=yd708090,SyncTimeout=15000,ConnectTimeout=15000,ResponseTimeout=15000,defaultDatabase=7,poolsize=100,ssl=false,writeBuffer=10240,idleTimeout=30000,connectRetry=3,asyncPipeline=false"
|
||||||
//"8.153.108.90,Password=yd708090,SyncTimeout=15000,ConnectTimeout=15000,ResponseTimeout=15000,defaultDatabase=8,poolsize=100,ssl=false,writeBuffer=10240,idleTimeout=30000,connectRetry=3,asyncPipeline=false"
|
//"8.153.108.90,Password=yd708090,SyncTimeout=15000,ConnectTimeout=15000,ResponseTimeout=15000,defaultDatabase=8,poolsize=100,ssl=false,writeBuffer=10240,idleTimeout=30000,connectRetry=3,asyncPipeline=false"
|
||||||
],
|
],
|
||||||
//"Sentinels": [
|
//"Sentinels": [
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user