From a01ed93aab201fad608203ee11d0b7a2d5f7b198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=A2=93=E5=BD=AD?= Date: Sat, 9 May 2026 17:06:53 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B5=9B=E4=BA=8B=E6=8A=A5=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Event/UnifiedRegistrationService.cs | 152 ++++++++++++++++-- YD_Event.Application/YD_Event.Application.xml | 5 + 2 files changed, 141 insertions(+), 16 deletions(-) diff --git a/YD_Event.Application/Event/UnifiedRegistrationService.cs b/YD_Event.Application/Event/UnifiedRegistrationService.cs index 2d41fe1..27251b9 100644 --- a/YD_Event.Application/Event/UnifiedRegistrationService.cs +++ b/YD_Event.Application/Event/UnifiedRegistrationService.cs @@ -215,7 +215,7 @@ public class UnifiedRegistrationService : ITransient TeamName = input.RegistrationMode == 2 ? input.TeamName : null, ContactName = input.ContactName, ContactPhone = input.ContactPhone, - PaymentStatus = 0, + PaymentStatus = 5, // 5=待支付确认,不占用正式名额 RegistrationTime = DateTime.Now, CreatedUserId = input.CreatedUserId, CreatedTime = DateTime.Now, @@ -225,6 +225,7 @@ public class UnifiedRegistrationService : ITransient }; await _registrationRepository.InsertAsync(registration); + _logger.LogInformation("创建预报名记录(待支付确认),报名ID: {RegistrationId}", registration.Id); return registration; } @@ -1103,29 +1104,29 @@ public class UnifiedRegistrationService : ITransient /// private async Task HandleOfflinePaymentAsync(EventRegistration registration, UnifiedPaymentInput input) { - // 如果是银行转账,先不设置支付状态,等用户确认转账后再处理 + // 如果是银行转账,保持状态为5(待支付确认),等用户确认转账后再处理 if (input.PaymentMethodType == PaymentMethodType.BankTransfer) { registration.PaymentProofUrl = input.PaymentProofUrl; - // 保持支付状态为未支付,等用户确认转账后再更新 - registration.PaymentStatus = 4; // 临时状态:待确认转账 + // 保持支付状态为5(待支付确认),不占用正式名额 + registration.PaymentStatus = 5; registration.UpdatedTime = DateTime.Now; registration.UpdatedUserId = input.OperatorUserId; await _registrationRepository.UpdateAsync(registration); - _logger.LogInformation("银行转账方式,等待用户确认,报名ID:{RegistrationId},凭证URL:{ProofUrl}", + _logger.LogInformation("银行转账方式,等待用户确认转账,报名ID:{RegistrationId},凭证URL:{ProofUrl}", registration.Id, input.PaymentProofUrl); return new UnifiedPaymentOutput { RegistrationId = registration.Id, OrderNo = registration.OrderNo, - PaymentStatus = 4, // 待确认转账 + PaymentStatus = 5, // 待支付确认 IsFree = false }; } - // 其他线下支付方式,保持原有逻辑 + // 其他线下支付方式,立即升级为正式报名(状态0) registration.PaymentProofUrl = input.PaymentProofUrl; registration.PaymentStatus = 0; // 待审核 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.PaymentStatus = 0; // 待审核 + registration.PaymentStatus = 0; // 待审核 - 正式报名记录 registration.UpdatedTime = DateTime.Now; registration.UpdatedUserId = operatorUserId; await _registrationRepository.UpdateAsync(registration); - _logger.LogInformation("银行转账确认成功,报名ID:{RegistrationId},状态已更新为待审核", input.RegistrationId); + _logger.LogInformation("银行转账确认成功,报名ID:{RegistrationId},正式创建报名记录,状态已更新为待审核", input.RegistrationId); return new ConfirmBankTransferOutput { @@ -1196,6 +1246,23 @@ public class UnifiedRegistrationService : ITransient }; } + /// + /// 删除报名记录(用于删除预报名记录) + /// + 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); + } + /// /// 检查报名限制 /// @@ -1219,7 +1286,7 @@ public class UnifiedRegistrationService : ITransient // 线上支付类型的报名记录,仅统计PaymentStatus == 1(已支付)的记录 // 线下支付类型的报名记录: // - 银行转账方式:仅统计PaymentStatus == 1(已支付)和PaymentStatus == 0(待审核)的记录, - // 不统计PaymentStatus == 4(待确认转账)的记录 + // 不统计PaymentStatus == 4(待确认转账)和PaymentStatus == 5(待支付确认)的记录 // - 其他线下方式:统计PaymentStatus == 1(已支付)和PaymentStatus == 0(待审核)的记录 var eventRegistrationsQuery = _registrationRepository.AsQueryable().Where(x => x.EventId == input.EventId && !x.DeleteMark && @@ -1230,12 +1297,12 @@ public class UnifiedRegistrationService : ITransient (x.PaymentMethod == 1 && ( // 已支付的都统计 x.PaymentStatus == 1 || - // 待审核的,且不是银行转账方式中待确认转账状态的 - (x.PaymentStatus == 0 && !(x.PaymentMethodType == PaymentMethodType.BankTransfer && x.PaymentStatus == 4)) + // 待审核的都统计 + x.PaymentStatus == 0 )) ) && - // 排除银行转账方式中待确认转账状态的记录 - !(x.PaymentMethodType == PaymentMethodType.BankTransfer && x.PaymentStatus == 4) + // 排除待支付确认的记录(状态5)、待确认转账的记录(状态4)、支付成功但名额已满的记录(状态6) + x.PaymentStatus != 4 && x.PaymentStatus != 5 && x.PaymentStatus != 6 ); // 如果指定了要排除的报名ID,则排除该记录 @@ -2137,9 +2204,62 @@ public class UnifiedRegistrationService : ITransient 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}", reg.OrderNo, evt.Id, evt.MerchantId); + // 正式创建报名记录,更新状态为已支付 reg.PaymentStatus = 1; reg.PaymentTime = successTime; reg.RegistrationRemark = transactionId; @@ -2147,7 +2267,7 @@ public class UnifiedRegistrationService : ITransient reg.UpdatedUserId = operatorUserId; await _registrationRepository.UpdateAsync(reg); - _logger.LogInformation($"订单 {reg.OrderNo} 支付成功,微信交易号:{transactionId}"); + _logger.LogInformation($"订单 {reg.OrderNo} 支付成功,正式创建报名记录,微信交易号:{transactionId}"); var payment = new EventRegistrationPayment { diff --git a/YD_Event.Application/YD_Event.Application.xml b/YD_Event.Application/YD_Event.Application.xml index 2d037f4..dcfbebc 100644 --- a/YD_Event.Application/YD_Event.Application.xml +++ b/YD_Event.Application/YD_Event.Application.xml @@ -8900,6 +8900,11 @@ 确认银行转账 + + + 删除报名记录(用于删除预报名记录) + + 检查报名限制