赛事报名

This commit is contained in:
马梓彭 2026-05-09 17:06:53 +08:00
parent 4259236415
commit a01ed93aab
2 changed files with 141 additions and 16 deletions

View File

@ -215,7 +215,7 @@ public class UnifiedRegistrationService : ITransient
TeamName = input.RegistrationMode == 2 ? input.TeamName : null, TeamName = input.RegistrationMode == 2 ? input.TeamName : null,
ContactName = input.ContactName, ContactName = input.ContactName,
ContactPhone = input.ContactPhone, ContactPhone = input.ContactPhone,
PaymentStatus = 0, PaymentStatus = 5, // 5=待支付确认,不占用正式名额
RegistrationTime = DateTime.Now, RegistrationTime = DateTime.Now,
CreatedUserId = input.CreatedUserId, CreatedUserId = input.CreatedUserId,
CreatedTime = DateTime.Now, CreatedTime = DateTime.Now,
@ -225,6 +225,7 @@ public class UnifiedRegistrationService : ITransient
}; };
await _registrationRepository.InsertAsync(registration); await _registrationRepository.InsertAsync(registration);
_logger.LogInformation("创建预报名记录(待支付确认),报名ID: {RegistrationId}", registration.Id);
return registration; return registration;
} }
@ -1103,29 +1104,29 @@ public class UnifiedRegistrationService : ITransient
/// </summary> /// </summary>
private async Task<UnifiedPaymentOutput> HandleOfflinePaymentAsync(EventRegistration registration, UnifiedPaymentInput input) private async Task<UnifiedPaymentOutput> HandleOfflinePaymentAsync(EventRegistration registration, UnifiedPaymentInput input)
{ {
// 如果是银行转账,先不设置支付状态,等用户确认转账后再处理 // 如果是银行转账,保持状态为5(待支付确认),等用户确认转账后再处理
if (input.PaymentMethodType == PaymentMethodType.BankTransfer) if (input.PaymentMethodType == PaymentMethodType.BankTransfer)
{ {
registration.PaymentProofUrl = input.PaymentProofUrl; registration.PaymentProofUrl = input.PaymentProofUrl;
// 保持支付状态为未支付,等用户确认转账后再更新 // 保持支付状态为5(待支付确认),不占用正式名额
registration.PaymentStatus = 4; // 临时状态:待确认转账 registration.PaymentStatus = 5;
registration.UpdatedTime = DateTime.Now; registration.UpdatedTime = DateTime.Now;
registration.UpdatedUserId = input.OperatorUserId; registration.UpdatedUserId = input.OperatorUserId;
await _registrationRepository.UpdateAsync(registration); await _registrationRepository.UpdateAsync(registration);
_logger.LogInformation("银行转账方式,等待用户确认,报名ID:{RegistrationId},凭证URL:{ProofUrl}", _logger.LogInformation("银行转账方式,等待用户确认转账,报名ID:{RegistrationId},凭证URL:{ProofUrl}",
registration.Id, input.PaymentProofUrl); registration.Id, input.PaymentProofUrl);
return new UnifiedPaymentOutput return new UnifiedPaymentOutput
{ {
RegistrationId = registration.Id, RegistrationId = registration.Id,
OrderNo = registration.OrderNo, OrderNo = registration.OrderNo,
PaymentStatus = 4, // 待确认转账 PaymentStatus = 5, // 待支付确认
IsFree = false IsFree = false
}; };
} }
// 其他线下支付方式,保持原有逻辑 // 其他线下支付方式,立即升级为正式报名(状态0)
registration.PaymentProofUrl = input.PaymentProofUrl; registration.PaymentProofUrl = input.PaymentProofUrl;
registration.PaymentStatus = 0; // 待审核 registration.PaymentStatus = 0; // 待审核
registration.UpdatedTime = DateTime.Now; registration.UpdatedTime = DateTime.Now;
@ -1178,14 +1179,63 @@ public class UnifiedRegistrationService : ITransient
}; };
} }
// 更新报名记录状态为待审核 // 重新验证报名限制,防止在等待转账期间名额已满
var unifiedInput = new UnifiedRegistrationInput
{
EventId = registration.EventId,
RegistrationMode = registration.RegistrationMode,
CreatedUserId = registration.CreatedUserId
};
// 获取报名明细来重建完整的输入
var items = await _registrationItemRepository.GetListAsync(x => x.RegistrationId == registration.Id);
var persons = await _registrationPersonRepository.GetListAsync(x => x.RegistrationId == registration.Id);
unifiedInput.Items = items.Select(item =>
{
var itemPersons = persons.Where(p => p.RegistrationItemId == item.Id).ToList();
return new UnifiedRegistrationItemInput
{
ProjectId = item.ProjectId,
GroupId = item.EventProjectGroupId,
Persons = itemPersons.Select(p => new UnifiedPersonInput
{
UserId = p.UserId,
Name = p.Name,
Gender = p.Gender,
IdCardNumber = p.IdCard,
BirthDate = p.BirthDate,
Mobile = p.Phone
}).ToList()
};
}).ToList();
var limitCheck = await CheckRegistrationLimitAsync(unifiedInput, registration.Id);
if (limitCheck.HasLimit)
{
_logger.LogWarning("银行转账确认时发现报名限制,报名ID:{RegistrationId},原因:{Reason}",
input.RegistrationId, limitCheck.LimitDetails.FirstOrDefault()?.LimitMessage);
// 删除预报名记录,释放名额
await DeleteRegistrationAsync(registration);
return new ConfirmBankTransferOutput
{
RegistrationId = input.RegistrationId,
PaymentStatus = -2,
Success = false,
Message = limitCheck.LimitDetails.FirstOrDefault()?.LimitMessage ?? "报名名额已满,请重新报名"
};
}
// 更新报名记录状态为待审核 - 正式创建报名记录
registration.PaymentProofUrl = input.PaymentProofUrl ?? registration.PaymentProofUrl; registration.PaymentProofUrl = input.PaymentProofUrl ?? registration.PaymentProofUrl;
registration.PaymentStatus = 0; // 待审核 registration.PaymentStatus = 0; // 待审核 - 正式报名记录
registration.UpdatedTime = DateTime.Now; registration.UpdatedTime = DateTime.Now;
registration.UpdatedUserId = operatorUserId; registration.UpdatedUserId = operatorUserId;
await _registrationRepository.UpdateAsync(registration); await _registrationRepository.UpdateAsync(registration);
_logger.LogInformation("银行转账确认成功,报名ID:{RegistrationId},状态已更新为待审核", input.RegistrationId); _logger.LogInformation("银行转账确认成功,报名ID:{RegistrationId},正式创建报名记录,状态已更新为待审核", input.RegistrationId);
return new ConfirmBankTransferOutput return new ConfirmBankTransferOutput
{ {
@ -1196,6 +1246,23 @@ public class UnifiedRegistrationService : ITransient
}; };
} }
/// <summary>
/// 删除报名记录(用于删除预报名记录)
/// </summary>
private async Task DeleteRegistrationAsync(EventRegistration registration)
{
// 删除报名明细
await _registrationItemRepository.DeleteAsync(x => x.RegistrationId == registration.Id);
// 删除报名人员
await _registrationPersonRepository.DeleteAsync(x => x.RegistrationId == registration.Id);
// 删除报名记录
await _registrationRepository.DeleteAsync(registration);
_logger.LogInformation("已删除预报名记录,报名ID:{RegistrationId}", registration.Id);
}
/// <summary> /// <summary>
/// 检查报名限制 /// 检查报名限制
/// </summary> /// </summary>
@ -1219,7 +1286,7 @@ public class UnifiedRegistrationService : ITransient
// 线上支付类型的报名记录,仅统计PaymentStatus == 1(已支付)的记录 // 线上支付类型的报名记录,仅统计PaymentStatus == 1(已支付)的记录
// 线下支付类型的报名记录: // 线下支付类型的报名记录:
// - 银行转账方式:仅统计PaymentStatus == 1(已支付)和PaymentStatus == 0(待审核)的记录, // - 银行转账方式:仅统计PaymentStatus == 1(已支付)和PaymentStatus == 0(待审核)的记录,
// 不统计PaymentStatus == 4(待确认转账)的记录 // 不统计PaymentStatus == 4(待确认转账)和PaymentStatus == 5(待支付确认)的记录
// - 其他线下方式:统计PaymentStatus == 1(已支付)和PaymentStatus == 0(待审核)的记录 // - 其他线下方式:统计PaymentStatus == 1(已支付)和PaymentStatus == 0(待审核)的记录
var eventRegistrationsQuery = _registrationRepository.AsQueryable().Where(x => var eventRegistrationsQuery = _registrationRepository.AsQueryable().Where(x =>
x.EventId == input.EventId && !x.DeleteMark && x.EventId == input.EventId && !x.DeleteMark &&
@ -1230,12 +1297,12 @@ public class UnifiedRegistrationService : ITransient
(x.PaymentMethod == 1 && ( (x.PaymentMethod == 1 && (
// 已支付的都统计 // 已支付的都统计
x.PaymentStatus == 1 || x.PaymentStatus == 1 ||
// 待审核的,且不是银行转账方式中待确认转账状态的 // 待审核的都统计
(x.PaymentStatus == 0 && !(x.PaymentMethodType == PaymentMethodType.BankTransfer && x.PaymentStatus == 4)) x.PaymentStatus == 0
)) ))
) && ) &&
// 排除银行转账方式中待确认转账状态的记录 // 排除待支付确认的记录(状态5)、待确认转账的记录(状态4)、支付成功但名额已满的记录(状态6)
!(x.PaymentMethodType == PaymentMethodType.BankTransfer && x.PaymentStatus == 4) x.PaymentStatus != 4 && x.PaymentStatus != 5 && x.PaymentStatus != 6
); );
// 如果指定了要排除的报名ID,则排除该记录 // 如果指定了要排除的报名ID,则排除该记录
@ -2137,9 +2204,62 @@ public class UnifiedRegistrationService : ITransient
return; return;
} }
// 如果当前状态是待支付确认,需要先重新验证报名限制
if (reg.PaymentStatus == 5)
{
// 重新验证报名限制,防止在支付期间名额已满
var unifiedInput = new UnifiedRegistrationInput
{
EventId = reg.EventId,
RegistrationMode = reg.RegistrationMode,
CreatedUserId = reg.CreatedUserId
};
// 获取报名明细来重建完整的输入
var items = await _registrationItemRepository.GetListAsync(x => x.RegistrationId == reg.Id);
var persons = await _registrationPersonRepository.GetListAsync(x => x.RegistrationId == reg.Id);
unifiedInput.Items = items.Select(item =>
{
var itemPersons = persons.Where(p => p.RegistrationItemId == item.Id).ToList();
return new UnifiedRegistrationItemInput
{
ProjectId = item.ProjectId,
GroupId = item.EventProjectGroupId,
Persons = itemPersons.Select(p => new UnifiedPersonInput
{
UserId = p.UserId,
Name = p.Name,
Gender = p.Gender,
IdCardNumber = p.IdCard,
BirthDate = p.BirthDate,
Mobile = p.Phone
}).ToList()
};
}).ToList();
var limitCheck = await CheckRegistrationLimitAsync(unifiedInput, reg.Id);
if (limitCheck.HasLimit)
{
_logger.LogWarning("微信支付成功时发现报名限制,报名ID:{RegistrationId},原因:{Reason}",
reg.Id, limitCheck.LimitDetails.FirstOrDefault()?.LimitMessage);
// 虽然支付成功了,但名额已满,这里我们需要记录日志,后续人工处理
// 不删除报名记录,保留支付信息,方便后续退款处理
reg.PaymentStatus = 6; // 支付成功但名额已满的状态
reg.RegistrationRemark = $"支付成功但名额已满: {limitCheck.LimitDetails.FirstOrDefault()?.LimitMessage}";
reg.UpdatedTime = DateTime.Now;
reg.UpdatedUserId = operatorUserId;
await _registrationRepository.UpdateAsync(reg);
return;
}
}
_logger.LogInformation("订单支付成功,订单号={OrderNo},赛事ID={EventId},商户ID={MerchantId}", _logger.LogInformation("订单支付成功,订单号={OrderNo},赛事ID={EventId},商户ID={MerchantId}",
reg.OrderNo, evt.Id, evt.MerchantId); reg.OrderNo, evt.Id, evt.MerchantId);
// 正式创建报名记录,更新状态为已支付
reg.PaymentStatus = 1; reg.PaymentStatus = 1;
reg.PaymentTime = successTime; reg.PaymentTime = successTime;
reg.RegistrationRemark = transactionId; reg.RegistrationRemark = transactionId;
@ -2147,7 +2267,7 @@ public class UnifiedRegistrationService : ITransient
reg.UpdatedUserId = operatorUserId; reg.UpdatedUserId = operatorUserId;
await _registrationRepository.UpdateAsync(reg); await _registrationRepository.UpdateAsync(reg);
_logger.LogInformation($"订单 {reg.OrderNo} 支付成功,微信交易号:{transactionId}"); _logger.LogInformation($"订单 {reg.OrderNo} 支付成功,正式创建报名记录,微信交易号:{transactionId}");
var payment = new EventRegistrationPayment var payment = new EventRegistrationPayment
{ {

View File

@ -8900,6 +8900,11 @@
确认银行转账 确认银行转账
</summary> </summary>
</member> </member>
<member name="M:YD_Event.Application.Event.UnifiedRegistrationService.DeleteRegistrationAsync(YD_Event.Core.Entities.EventRegistration)">
<summary>
删除报名记录(用于删除预报名记录)
</summary>
</member>
<member name="M:YD_Event.Application.Event.UnifiedRegistrationService.CheckRegistrationLimitAsync(YD_Event.Application.Event.Dtos.UnifiedRegistrationInput,System.Nullable{System.Int64})"> <member name="M:YD_Event.Application.Event.UnifiedRegistrationService.CheckRegistrationLimitAsync(YD_Event.Application.Event.Dtos.UnifiedRegistrationInput,System.Nullable{System.Int64})">
<summary> <summary>
检查报名限制 检查报名限制