赛事编排
This commit is contained in:
parent
f7aedcce91
commit
565ca9cc36
@ -117,12 +117,6 @@ public class AuthService : IDynamicApiController
|
||||
throw Oops.Bah("验证码错误或已过期");
|
||||
}
|
||||
|
||||
var existAccount = await _sysUseRepository.IsAnyAsync(x => x.Account == dto.Account);
|
||||
if (existAccount)
|
||||
{
|
||||
throw Oops.Bah("该账号已被注册");
|
||||
}
|
||||
|
||||
var existPhone = await _sysUseRepository.IsAnyAsync(x => x.Mobile == dto.Phone);
|
||||
if (existPhone)
|
||||
{
|
||||
@ -132,8 +126,8 @@ public class AuthService : IDynamicApiController
|
||||
var user = new SysUser
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
Account = dto.Account,
|
||||
Name = dto.Account,
|
||||
Account = dto.Phone,
|
||||
Name = dto.Phone,
|
||||
Mobile = dto.Phone,
|
||||
Gender = Gender.Unknown,
|
||||
OrgId = 0,
|
||||
|
||||
@ -15,14 +15,6 @@ public class RegisterInput
|
||||
[RegularExpression(@"^1[3456789]\d{9}$", ErrorMessage = "手机号格式不正确")]
|
||||
public string Phone { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 账号
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "账号不能为空")]
|
||||
[MinLength(3, ErrorMessage = "账号至少3个字符")]
|
||||
[MaxLength(32, ErrorMessage = "账号最多32个字符")]
|
||||
public string Account { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
|
||||
@ -433,6 +433,20 @@ public class CertificateTemplateService : BaseService<CertificateTemplate>, ITra
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取证书模板列表(用于选择)
|
||||
/// </summary>
|
||||
[DisplayName("获取证书模板列表")]
|
||||
public async Task<List<CertificateTemplateSimpleOutput>> GetTemplateList()
|
||||
{
|
||||
var templates = await _templateRepository.AsQueryable()
|
||||
.Where(x => x.Status == Core.Enum.AvailabilityStatus.Enable && !x.DeleteMark)
|
||||
.OrderByDescending(x => x.CreatedTime)
|
||||
.ToListAsync();
|
||||
|
||||
return templates.Adapt<List<CertificateTemplateSimpleOutput>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前用户ID
|
||||
/// </summary>
|
||||
|
||||
@ -354,4 +354,9 @@ public class CertificateTemplateSimpleOutput
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 显示名称
|
||||
/// </summary>
|
||||
public string DisplayName => $"模板 {Id} (v{Version}) - {TemplateType}";
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ using Furion.DatabaseAccessor;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Security.Claims;
|
||||
using Furion.FriendlyException;
|
||||
using EasyCaching.Core;
|
||||
using ProjectEntity = YD_Event.Core.Entities.Project;
|
||||
|
||||
namespace YD_Event.Application.Client;
|
||||
@ -29,6 +30,7 @@ public class MyController : IDynamicApiController
|
||||
private readonly ISqlSugarRepository<EventInfo> _eventRepository;
|
||||
private readonly ISqlSugarRepository<MerchantCertification> _merchantCertificationRepository;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IEasyCachingProvider _cachingProvider;
|
||||
|
||||
public MyController(
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.AppUser> appUserRepository,
|
||||
@ -41,7 +43,8 @@ public class MyController : IDynamicApiController
|
||||
ISqlSugarRepository<EventRegistrationItem> registrationItemRepository,
|
||||
ISqlSugarRepository<EventInfo> eventRepository,
|
||||
ISqlSugarRepository<MerchantCertification> merchantCertificationRepository,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IEasyCachingProvider cachingProvider)
|
||||
{
|
||||
_appUserRepository = appUserRepository;
|
||||
_teamRepository = teamRepository;
|
||||
@ -54,6 +57,7 @@ public class MyController : IDynamicApiController
|
||||
_eventRepository = eventRepository;
|
||||
_merchantCertificationRepository = merchantCertificationRepository;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_cachingProvider = cachingProvider;
|
||||
}
|
||||
|
||||
private long GetCurrentUserId()
|
||||
@ -178,6 +182,31 @@ public class MyController : IDynamicApiController
|
||||
|
||||
if (string.IsNullOrEmpty(input.SmsCode)) throw Oops.Bah("手机号验证码不能为空");
|
||||
|
||||
// 1. 验证短信验证码格式(6位数字)
|
||||
if (input.SmsCode.Length != 6 || !input.SmsCode.All(char.IsDigit))
|
||||
{
|
||||
throw Oops.Bah("验证码格式错误");
|
||||
}
|
||||
|
||||
// 2. 从缓存中获取验证码,验证是否为系统最新生成且在有效期内
|
||||
var codeCacheKey = $"sms:code:{input.Mobile}";
|
||||
var cachedCode = await _cachingProvider.GetAsync<string>(codeCacheKey);
|
||||
|
||||
// 3. 验证验证码是否在有效期内
|
||||
if (!cachedCode.HasValue)
|
||||
{
|
||||
throw Oops.Bah("验证码已过期");
|
||||
}
|
||||
|
||||
// 4. 验证验证码是否一致
|
||||
if (cachedCode.Value != input.SmsCode)
|
||||
{
|
||||
throw Oops.Bah("验证码不正确");
|
||||
}
|
||||
|
||||
// 验证成功后,移除验证码缓存
|
||||
await _cachingProvider.RemoveAsync(codeCacheKey);
|
||||
|
||||
user.Name = input.Name;
|
||||
user.Mobile = input.Mobile;
|
||||
|
||||
|
||||
@ -41,7 +41,12 @@ public class ArrangementProjectListOutput
|
||||
public int SortIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总时长(分钟)
|
||||
/// 总时长(秒)
|
||||
/// </summary>
|
||||
public int TotalDurationSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总时长(分钟,向上取整)
|
||||
/// </summary>
|
||||
public int TotalDurationMinutes { get; set; }
|
||||
}
|
||||
|
||||
@ -155,7 +155,8 @@ public class EventArrangementService : BaseService<YD_Event.Core.Entities.Projec
|
||||
totalDurationSeconds = rounds * proj.DurationSeconds;
|
||||
}
|
||||
|
||||
// 向上取整到最近的分钟数
|
||||
// 设置总时长秒数和分钟数
|
||||
dto.TotalDurationSeconds = totalDurationSeconds;
|
||||
dto.TotalDurationMinutes = (int)Math.Ceiling((double)totalDurationSeconds / 60);
|
||||
|
||||
result.Add(dto);
|
||||
|
||||
@ -15,6 +15,8 @@ public class EventRegistrationService : BaseService<EventRegistration>, ITransie
|
||||
private readonly ISqlSugarRepository<EventRegistrationPerson> _personRepository;
|
||||
private readonly ISqlSugarRepository<EventRegistrationPayment> _paymentRepository;
|
||||
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Order> _orderRepository;
|
||||
private readonly ISqlSugarRepository<TeamMember> _teamMemberRepository;
|
||||
private readonly ISqlSugarRepository<YD_Event.Core.Entities.AppUser> _appUserRepository;
|
||||
private readonly AuthManager _authManager;
|
||||
|
||||
public EventRegistrationService(
|
||||
@ -23,6 +25,8 @@ public class EventRegistrationService : BaseService<EventRegistration>, ITransie
|
||||
ISqlSugarRepository<EventRegistrationPerson> personRepository,
|
||||
ISqlSugarRepository<EventRegistrationPayment> paymentRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Order> orderRepository,
|
||||
ISqlSugarRepository<TeamMember> teamMemberRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.AppUser> appUserRepository,
|
||||
AuthManager authManager) : base(repository)
|
||||
{
|
||||
_repository = repository;
|
||||
@ -30,6 +34,8 @@ public class EventRegistrationService : BaseService<EventRegistration>, ITransie
|
||||
_personRepository = personRepository;
|
||||
_paymentRepository = paymentRepository;
|
||||
_orderRepository = orderRepository;
|
||||
_teamMemberRepository = teamMemberRepository;
|
||||
_appUserRepository = appUserRepository;
|
||||
_authManager = authManager;
|
||||
}
|
||||
|
||||
@ -82,6 +88,75 @@ public class EventRegistrationService : BaseService<EventRegistration>, ITransie
|
||||
.Where(x => regIds.Contains(x.RegistrationId))
|
||||
.ToListAsync();
|
||||
|
||||
// 获取所有报名人员的 UserId
|
||||
var allAthleteUserIds = persons
|
||||
.Where(p => p.PersonType == YD_Event.Core.Enum.PersonType.Athlete && p.UserId > 0)
|
||||
.Select(p => p.UserId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
// 步骤1:通过运动员的 UserId 找到对应的 TeamId
|
||||
var teamIds = new List<long>();
|
||||
if (allAthleteUserIds.Any())
|
||||
{
|
||||
teamIds = await _teamMemberRepository.AsQueryable()
|
||||
.Where(tm => allAthleteUserIds.Contains(tm.UserId) && !tm.DeleteMark)
|
||||
.Select(tm => tm.TeamId)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
// 步骤2:通过 TeamId 获取同团队的教练/领队的 UserId,并获取用户详情
|
||||
Dictionary<long, List<YD_Event.Core.Entities.AppUser>> teamLeadersDict = new();
|
||||
Dictionary<long, List<YD_Event.Core.Entities.AppUser>> teamCoachesDict = new();
|
||||
|
||||
if (teamIds.Any())
|
||||
{
|
||||
var teamMembers = await _teamMemberRepository.AsQueryable()
|
||||
.Where(tm => teamIds.Contains(tm.TeamId) && !tm.DeleteMark)
|
||||
.ToListAsync();
|
||||
|
||||
var coachLeaderUserIds = teamMembers
|
||||
.Where(tm => tm.PersonType == YD_Event.Core.Enum.PersonType.Leader ||
|
||||
tm.PersonType == YD_Event.Core.Enum.PersonType.Coach)
|
||||
.Select(tm => tm.UserId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
if (coachLeaderUserIds.Any())
|
||||
{
|
||||
var coachLeaderUsers = await _appUserRepository.AsQueryable()
|
||||
.Where(u => coachLeaderUserIds.Contains(u.Id) && !u.DeleteMark)
|
||||
.ToListAsync();
|
||||
|
||||
var userDict = coachLeaderUsers.ToDictionary(u => u.Id);
|
||||
|
||||
// 按团队分组
|
||||
foreach (var teamId in teamIds)
|
||||
{
|
||||
var teamLeaders = teamMembers
|
||||
.Where(tm => tm.TeamId == teamId && tm.PersonType == YD_Event.Core.Enum.PersonType.Leader)
|
||||
.Select(tm => userDict.TryGetValue(tm.UserId, out var user) ? user : null)
|
||||
.Where(u => u != null)
|
||||
.Cast<YD_Event.Core.Entities.AppUser>()
|
||||
.ToList();
|
||||
|
||||
var teamCoaches = teamMembers
|
||||
.Where(tm => tm.TeamId == teamId && tm.PersonType == YD_Event.Core.Enum.PersonType.Coach)
|
||||
.Select(tm => userDict.TryGetValue(tm.UserId, out var user) ? user : null)
|
||||
.Where(u => u != null)
|
||||
.Cast<YD_Event.Core.Entities.AppUser>()
|
||||
.ToList();
|
||||
|
||||
if (teamLeaders.Any())
|
||||
teamLeadersDict[teamId] = teamLeaders;
|
||||
|
||||
if (teamCoaches.Any())
|
||||
teamCoachesDict[teamId] = teamCoaches;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var dto in result.Rows)
|
||||
{
|
||||
var myItems = items.Where(x => x.RegistrationId == dto.Id).ToList();
|
||||
@ -120,17 +195,81 @@ public class EventRegistrationService : BaseService<EventRegistration>, ITransie
|
||||
dto.Items.Add(detail);
|
||||
}
|
||||
|
||||
// 设置领队信息和教练信息
|
||||
// 设置领队信息和教练信息 - 从团队中获取
|
||||
var regPersons = persons.Where(p => p.RegistrationId == dto.Id).ToList();
|
||||
var leaders = regPersons.Where(p => p.PersonType == YD_Event.Core.Enum.PersonType.Leader).ToList();
|
||||
var coaches = regPersons.Where(p => p.PersonType == YD_Event.Core.Enum.PersonType.Coach).ToList();
|
||||
|
||||
dto.TeamLeaderInfo = leaders.Any()
|
||||
? string.Join(";", leaders.Select(l => $"{l.Name}({l.Phone})"))
|
||||
var regAthleteUserIds = regPersons
|
||||
.Where(p => p.PersonType == YD_Event.Core.Enum.PersonType.Athlete && p.UserId > 0)
|
||||
.Select(p => p.UserId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
// 获取这些运动员所属的团队
|
||||
var regTeamIds = new List<long>();
|
||||
if (regAthleteUserIds.Any())
|
||||
{
|
||||
regTeamIds = await _teamMemberRepository.AsQueryable()
|
||||
.Where(tm => regAthleteUserIds.Contains(tm.UserId) && !tm.DeleteMark)
|
||||
.Select(tm => tm.TeamId)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
// 收集所有相关团队的领队和教练
|
||||
var allLeaders = new List<YD_Event.Core.Entities.AppUser>();
|
||||
var allCoaches = new List<YD_Event.Core.Entities.AppUser>();
|
||||
|
||||
foreach (var teamId in regTeamIds)
|
||||
{
|
||||
if (teamLeadersDict.TryGetValue(teamId, out var leaders))
|
||||
allLeaders.AddRange(leaders);
|
||||
if (teamCoachesDict.TryGetValue(teamId, out var coaches))
|
||||
allCoaches.AddRange(coaches);
|
||||
}
|
||||
|
||||
// 去重
|
||||
allLeaders = allLeaders.GroupBy(l => l.Id).Select(g => g.First()).ToList();
|
||||
allCoaches = allCoaches.GroupBy(c => c.Id).Select(g => g.First()).ToList();
|
||||
|
||||
// 如果从团队中没有找到,再回退到从报名人员中查找
|
||||
if (!allLeaders.Any())
|
||||
{
|
||||
var regLeaders = regPersons.Where(p => p.PersonType == YD_Event.Core.Enum.PersonType.Leader).ToList();
|
||||
allLeaders = regLeaders.Select(l => new YD_Event.Core.Entities.AppUser
|
||||
{
|
||||
Name = l.Name,
|
||||
Mobile = l.Phone,
|
||||
Gender = l.Gender
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
if (!allCoaches.Any())
|
||||
{
|
||||
var regCoaches = regPersons.Where(p => p.PersonType == YD_Event.Core.Enum.PersonType.Coach).ToList();
|
||||
allCoaches = regCoaches.Select(c => new YD_Event.Core.Entities.AppUser
|
||||
{
|
||||
Name = c.Name,
|
||||
Mobile = c.Phone,
|
||||
Gender = c.Gender
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
// 辅助函数:获取性别文本
|
||||
Func<YD_Event.Core.Enum.Gender, string> getGenderText = (gender) =>
|
||||
{
|
||||
return gender switch
|
||||
{
|
||||
YD_Event.Core.Enum.Gender.Male => "男",
|
||||
YD_Event.Core.Enum.Gender.Female => "女",
|
||||
_ => "未知"
|
||||
};
|
||||
};
|
||||
|
||||
dto.TeamLeaderInfo = allLeaders.Any()
|
||||
? string.Join(",", allLeaders.Select(l => $"{l.Name}({l.Mobile})/{getGenderText(l.Gender)}"))
|
||||
: null;
|
||||
|
||||
dto.CoachInfo = coaches.Any()
|
||||
? string.Join(";", coaches.Select(c => $"{c.Name}({c.Phone})"))
|
||||
dto.CoachInfo = allCoaches.Any()
|
||||
? string.Join(",", allCoaches.Select(c => $"{c.Name}({c.Mobile})/{getGenderText(c.Gender)}"))
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +54,8 @@ public class PaymentExpirationBackgroundService : BackgroundService
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var registrationRepository = scope.ServiceProvider.GetRequiredService<ISqlSugarRepository<EventRegistration>>();
|
||||
var orderRepository = scope.ServiceProvider.GetRequiredService<ISqlSugarRepository<YD_Event.Core.Entities.Order>>();
|
||||
var userCouponRepository = scope.ServiceProvider.GetRequiredService<ISqlSugarRepository<YD_Event.Core.Entities.UserCoupon>>();
|
||||
var couponRepository = scope.ServiceProvider.GetRequiredService<ISqlSugarRepository<YD_Event.Core.Entities.Coupon>>();
|
||||
|
||||
var now = DateTime.Now;
|
||||
var expirationTime = now.AddMinutes(-30);
|
||||
@ -80,6 +82,18 @@ public class PaymentExpirationBackgroundService : BackgroundService
|
||||
|
||||
if (orderNos.Any())
|
||||
{
|
||||
// 获取这些订单并释放优惠券
|
||||
var orders = await orderRepository.AsQueryable()
|
||||
.Where(x => orderNos.Contains(x.OrderNo) && x.CouponId.HasValue)
|
||||
.ToListAsync(stoppingToken);
|
||||
|
||||
foreach (var order in orders)
|
||||
{
|
||||
await ReleaseCouponAsync(order.CouponId.Value, order.CreatedUserId, order.Id,
|
||||
userCouponRepository, couponRepository, stoppingToken);
|
||||
}
|
||||
|
||||
// 更新订单状态
|
||||
await orderRepository.UpdateAsync(x => new YD_Event.Core.Entities.Order
|
||||
{
|
||||
OrderStatus = OrderStatus.Cancelled,
|
||||
@ -96,6 +110,46 @@ public class PaymentExpirationBackgroundService : BackgroundService
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放优惠券,恢复为未使用状态
|
||||
/// </summary>
|
||||
private async Task ReleaseCouponAsync(long couponId, long userId, long orderId,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.UserCoupon> userCouponRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Coupon> couponRepository,
|
||||
CancellationToken stoppingToken)
|
||||
{
|
||||
var userCoupon = await userCouponRepository.GetFirstAsync(uc =>
|
||||
uc.CouponId == couponId &&
|
||||
uc.UserId == userId &&
|
||||
uc.OrderId == orderId &&
|
||||
!uc.DeleteMark, stoppingToken);
|
||||
|
||||
if (userCoupon != null && userCoupon.Status == 1)
|
||||
{
|
||||
userCoupon.Status = 0;
|
||||
userCoupon.UseTime = null;
|
||||
userCoupon.OrderId = null;
|
||||
await userCouponRepository.UpdateAsync(userCoupon, stoppingToken);
|
||||
|
||||
// 减少优惠券的已使用数量
|
||||
var coupon = await couponRepository.GetByIdAsync(couponId, stoppingToken);
|
||||
if (coupon != null && coupon.UsedQuantity > 0)
|
||||
{
|
||||
coupon.UsedQuantity--;
|
||||
await couponRepository.UpdateAsync(coupon, stoppingToken);
|
||||
}
|
||||
|
||||
_logger.LogInformation($"优惠券已释放,用户优惠券ID={userCoupon.Id},订单ID={orderId}");
|
||||
}
|
||||
else if (userCoupon != null && userCoupon.Status == 0)
|
||||
{
|
||||
// 如果优惠券还没有被标记为已使用,只需要清空OrderId
|
||||
userCoupon.OrderId = null;
|
||||
await userCouponRepository.UpdateAsync(userCoupon, stoppingToken);
|
||||
_logger.LogInformation($"优惠券OrderId已清空,用户优惠券ID={userCoupon.Id},订单ID={orderId}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理微信未支付订单:定期检查并更新订单状态
|
||||
/// </summary>
|
||||
@ -182,12 +236,16 @@ public class PaymentExpirationBackgroundService : BackgroundService
|
||||
}
|
||||
else if (queryResult.TradeState == "CLOSED" || queryResult.TradeState == "REVOKED")
|
||||
{
|
||||
var userCouponRepository = scope.ServiceProvider.GetRequiredService<ISqlSugarRepository<YD_Event.Core.Entities.UserCoupon>>();
|
||||
var couponRepository = scope.ServiceProvider.GetRequiredService<ISqlSugarRepository<YD_Event.Core.Entities.Coupon>>();
|
||||
await ProcessWeChatPaymentClosedAsync(
|
||||
registration,
|
||||
order,
|
||||
now,
|
||||
registrationRepository,
|
||||
orderRepository,
|
||||
userCouponRepository,
|
||||
couponRepository,
|
||||
stoppingToken);
|
||||
}
|
||||
}
|
||||
@ -277,6 +335,8 @@ public class PaymentExpirationBackgroundService : BackgroundService
|
||||
DateTime now,
|
||||
ISqlSugarRepository<EventRegistration> registrationRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Order> orderRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.UserCoupon> userCouponRepository,
|
||||
ISqlSugarRepository<YD_Event.Core.Entities.Coupon> couponRepository,
|
||||
CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation("订单 {OrderNo} 支付已关闭,更新订单状态为已取消", registration.OrderNo);
|
||||
@ -288,6 +348,13 @@ public class PaymentExpirationBackgroundService : BackgroundService
|
||||
order.OrderStatus = OrderStatus.Cancelled;
|
||||
order.UpdatedTime = now;
|
||||
await orderRepository.UpdateAsync(order);
|
||||
|
||||
// 释放优惠券
|
||||
if (order.CouponId.HasValue)
|
||||
{
|
||||
await ReleaseCouponAsync(order.CouponId.Value, order.CreatedUserId, order.Id,
|
||||
userCouponRepository, couponRepository, stoppingToken);
|
||||
}
|
||||
|
||||
_logger.LogInformation("订单 {OrderNo} 状态更新为已取消成功", registration.OrderNo);
|
||||
}
|
||||
|
||||
@ -1728,6 +1728,34 @@ public class UnifiedRegistrationService : ITransient
|
||||
order.UpdatedTime = DateTime.Now;
|
||||
await _orderRepository.UpdateAsync(order);
|
||||
_logger.LogInformation($"Order 记录 {order.OrderNo} 状态已更新为已支付");
|
||||
|
||||
// 支付成功后,标记优惠券为已使用
|
||||
if (order.CouponId.HasValue)
|
||||
{
|
||||
var userCoupon = await _userCouponRepository.GetFirstAsync(uc =>
|
||||
uc.CouponId == order.CouponId.Value &&
|
||||
uc.UserId == order.CreatedUserId &&
|
||||
uc.Status == 0 &&
|
||||
!uc.DeleteMark);
|
||||
|
||||
if (userCoupon != null)
|
||||
{
|
||||
userCoupon.Status = 1;
|
||||
userCoupon.UseTime = successTime ?? DateTime.Now;
|
||||
userCoupon.OrderId = order.Id;
|
||||
await _userCouponRepository.UpdateAsync(userCoupon);
|
||||
|
||||
// 更新优惠券的已使用数量
|
||||
var coupon = await _couponRepository.GetByIdAsync(order.CouponId.Value);
|
||||
if (coupon != null)
|
||||
{
|
||||
coupon.UsedQuantity++;
|
||||
await _couponRepository.UpdateAsync(coupon);
|
||||
}
|
||||
|
||||
_logger.LogInformation($"优惠券已标记为已使用,用户优惠券ID={userCoupon.Id},订单ID={order.Id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -508,11 +508,6 @@
|
||||
手机号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Auth.Dtos.RegisterInput.Account">
|
||||
<summary>
|
||||
账号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Auth.Dtos.RegisterInput.Password">
|
||||
<summary>
|
||||
密码
|
||||
@ -1007,6 +1002,11 @@
|
||||
生成显示名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Certificate.CertificateTemplateService.GetTemplateList">
|
||||
<summary>
|
||||
获取证书模板列表(用于选择)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Certificate.CertificateTemplateService.GetCurrentUserUserId">
|
||||
<summary>
|
||||
获取当前用户ID
|
||||
@ -1452,6 +1452,11 @@
|
||||
创建时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Certificate.Dtos.CertificateTemplateSimpleOutput.DisplayName">
|
||||
<summary>
|
||||
显示名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Certificate.Dtos.DeleteCertificateInput">
|
||||
<summary>
|
||||
删除证书输入参数
|
||||
@ -4052,9 +4057,14 @@
|
||||
排序索引
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.ArrangementProjectListOutput.TotalDurationSeconds">
|
||||
<summary>
|
||||
总时长(秒)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.ArrangementProjectListOutput.TotalDurationMinutes">
|
||||
<summary>
|
||||
总时长(分钟)
|
||||
总时长(分钟,向上取整)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Event.Dtos.ArrangementGroupDto">
|
||||
@ -5752,6 +5762,11 @@
|
||||
性别
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.CoachLeaderListOutput.BirthDate">
|
||||
<summary>
|
||||
出生日期
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Event.Dtos.CoachLeaderListOutput.IdCardNumber">
|
||||
<summary>
|
||||
身份证号
|
||||
@ -7687,6 +7702,11 @@
|
||||
支付超时处理后台服务
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Event.PaymentExpirationBackgroundService.ReleaseCouponAsync(System.Int64,System.Int64,System.Int64,SqlSugar.ISqlSugarRepository{YD_Event.Core.Entities.UserCoupon},SqlSugar.ISqlSugarRepository{YD_Event.Core.Entities.Coupon},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
释放优惠券,恢复为未使用状态
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Event.PaymentExpirationBackgroundService.ProcessUnpaidWeChatOrdersAsync(System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
处理微信未支付订单:定期检查并更新订单状态
|
||||
@ -7697,7 +7717,7 @@
|
||||
处理微信支付成功的订单
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Event.PaymentExpirationBackgroundService.ProcessWeChatPaymentClosedAsync(YD_Event.Core.Entities.EventRegistration,YD_Event.Core.Entities.Order,System.DateTime,SqlSugar.ISqlSugarRepository{YD_Event.Core.Entities.EventRegistration},SqlSugar.ISqlSugarRepository{YD_Event.Core.Entities.Order},System.Threading.CancellationToken)">
|
||||
<member name="M:YD_Event.Application.Event.PaymentExpirationBackgroundService.ProcessWeChatPaymentClosedAsync(YD_Event.Core.Entities.EventRegistration,YD_Event.Core.Entities.Order,System.DateTime,SqlSugar.ISqlSugarRepository{YD_Event.Core.Entities.EventRegistration},SqlSugar.ISqlSugarRepository{YD_Event.Core.Entities.Order},SqlSugar.ISqlSugarRepository{YD_Event.Core.Entities.UserCoupon},SqlSugar.ISqlSugarRepository{YD_Event.Core.Entities.Coupon},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
处理微信支付关闭的订单
|
||||
</summary>
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
"DbType": "SqlServer", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access、OpenGauss、QuestDB、HG、ClickHouse、GBase、Odbc、Custom
|
||||
"ConnectionString": "Data Source=rm-uf64b8oxdt19pfyxfao.sqlserver.rds.aliyuncs.com;Database=EventServerDB_QA;User ID=qa;Password=Admin@123;Connect Timeout=500;Encrypt=True;TrustServerCertificate=True;",
|
||||
"IsAutoCloseConnection": true,
|
||||
"EnableInitDb": true // 启用数据库以及数据表初始化(首次运行项目时开启可以自动创建数据库和初始化项目运行的基础数据)
|
||||
"EnableInitDb": false // 启用数据库以及数据表初始化(首次运行项目时开启可以自动创建数据库和初始化项目运行的基础数据)
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user