项目,积分bug

This commit is contained in:
马梓彭 2026-04-12 13:14:20 +08:00
parent fcfb534f46
commit b73ad0a94e
13 changed files with 673 additions and 79 deletions

View File

@ -10,15 +10,21 @@ public class CouponService : BaseService<YD_Event.Core.Entities.Coupon>, ITransi
{
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Coupon> _repository;
private readonly ISqlSugarRepository<EventInfo> _eventRepository;
private readonly ISqlSugarRepository<CouponRedemptionCode> _redemptionCodeRepository;
private readonly ISqlSugarRepository<UserCoupon> _userCouponRepository;
private readonly IIdGenerator _idGenerator;
public CouponService(
ISqlSugarRepository<YD_Event.Core.Entities.Coupon> repository,
ISqlSugarRepository<EventInfo> eventRepository,
ISqlSugarRepository<CouponRedemptionCode> redemptionCodeRepository,
ISqlSugarRepository<UserCoupon> userCouponRepository,
IIdGenerator idGenerator) : base(repository)
{
_repository = repository;
_eventRepository = eventRepository;
_redemptionCodeRepository = redemptionCodeRepository;
_userCouponRepository = userCouponRepository;
_idGenerator = idGenerator;
}
@ -77,7 +83,6 @@ public class CouponService : BaseService<YD_Event.Core.Entities.Coupon>, ITransi
Value = item.Value,
StartTime = item.StartTime,
EndTime = item.EndTime,
RedemptionCode = item.RedemptionCode,
TotalQuantity = item.TotalQuantity,
ClaimedQuantity = item.ClaimedQuantity,
UsedQuantity = item.UsedQuantity,
@ -123,16 +128,10 @@ public class CouponService : BaseService<YD_Event.Core.Entities.Coupon>, ITransi
{
var entity = await _repository.GetByIdAsync(input.Id);
if (entity == null) throw Oops.Bah("优惠券不存在");
// 保存当前的兑换码,防止被意外清空
var currentRedemptionCode = entity.RedemptionCode;
// 使用Mapster进行属性映射,但保留兑换码
// 使用Mapster进行属性映射
input.Adapt(entity);
// 恢复兑换码
entity.RedemptionCode = currentRedemptionCode;
// 处理赛事ID集合
if (input.EventIds != null && input.EventIds.Any())
{
@ -157,57 +156,206 @@ public class CouponService : BaseService<YD_Event.Core.Entities.Coupon>, ITransi
}
/// <summary>
/// 生成兑换码
/// 生成单个兑换码(兼容旧接口)
/// </summary>
[DisplayName("生成兑换码")]
[UnitOfWork]
[Obsolete("请使用 GenerateRedemptionCodes 方法")]
public async Task<string> GenerateCode(long id)
{
// 使用事务和乐观锁来确保并发安全
var entity = await _repository.AsQueryable()
.Where(x => x.Id == id)
.FirstAsync();
if (entity == null) throw Oops.Bah("优惠券不存在");
var result = await GenerateRedemptionCodes(new GenerateRedemptionCodesInput { CouponId = id, Count = 1 });
return result.FirstOrDefault()?.Code ?? string.Empty;
}
// 如果已经有码,直接返回
if (!string.IsNullOrWhiteSpace(entity.RedemptionCode))
{
return entity.RedemptionCode;
}
/// <summary>
/// 批量生成兑换码
/// </summary>
[DisplayName("批量生成兑换码")]
[UnitOfWork]
public async Task<List<RedemptionCodeOutput>> GenerateRedemptionCodes(GenerateRedemptionCodesInput input)
{
// 验证优惠券是否存在
var coupon = await _repository.GetByIdAsync(input.CouponId);
if (coupon == null) throw Oops.Bah("优惠券不存在");
// 生成新的兑换码,并确保唯一性
string newCode;
int retryCount = 0;
const int maxRetry = 5;
do
var generatedCodes = new List<CouponRedemptionCode>();
const int maxRetryPerCode = 5;
for (int i = 0; i < input.Count; i++)
{
// 生成8位大写字母数字组合的兑换码
newCode = Guid.NewGuid().ToString("N").Substring(0, 8).ToUpper();
retryCount++;
// 检查是否已存在
var exists = await _repository.AsQueryable()
.Where(x => x.RedemptionCode == newCode)
.AnyAsync();
if (!exists)
string newCode;
int retryCount = 0;
bool codeIsUnique = false;
do
{
break;
// 生成12位大写字母数字组合的兑换码
newCode = GenerateRandomCode(12);
retryCount++;
// 检查是否已存在
var exists = await _redemptionCodeRepository.AsQueryable()
.Where(x => x.Code == newCode)
.AnyAsync();
if (!exists)
{
codeIsUnique = true;
}
} while (!codeIsUnique && retryCount < maxRetryPerCode);
if (!codeIsUnique)
{
throw Oops.Bah($"生成第 {i + 1} 个兑换码时失败,请重试");
}
} while (retryCount < maxRetry);
if (retryCount >= maxRetry)
{
throw Oops.Bah("生成兑换码失败,请重试");
var redemptionCode = new CouponRedemptionCode
{
Id = _idGenerator.NextId(),
CouponId = input.CouponId,
Code = newCode,
Status = 0,
DeleteMark = false
};
generatedCodes.Add(redemptionCode);
}
// 更新兑换码
entity.RedemptionCode = newCode;
await _repository.UpdateAsync(entity);
// 批量插入
await _redemptionCodeRepository.InsertRangeAsync(generatedCodes);
return entity.RedemptionCode;
// 返回结果
return generatedCodes.Select(x => new RedemptionCodeOutput
{
Id = x.Id,
CouponId = x.CouponId,
Code = x.Code,
Status = x.Status,
CreatedTime = x.CreatedTime
}).ToList();
}
/// <summary>
/// 兑换码分页查询
/// </summary>
[DisplayName("兑换码分页查询")]
public async Task<PageResult<RedemptionCodeOutput>> GetRedemptionCodePage(RedemptionCodeQueryInput input)
{
var query = _redemptionCodeRepository.AsQueryable()
.WhereIF(input.CouponId.HasValue, x => x.CouponId == input.CouponId.Value)
.WhereIF(input.Status.HasValue, x => x.Status == input.Status.Value)
.WhereIF(!string.IsNullOrWhiteSpace(input.Code), x => x.Code.Contains(input.Code))
.OrderByDescending(x => x.CreatedTime);
var pagedList = await query.ToPagedListAsync(input);
return new PageResult<RedemptionCodeOutput>
{
PageNo = pagedList.PageNo,
PageSize = pagedList.PageSize,
Total = pagedList.Total,
Rows = pagedList.Rows.Select(x => new RedemptionCodeOutput
{
Id = x.Id,
CouponId = x.CouponId,
Code = x.Code,
Status = x.Status,
UsedTime = x.UsedTime,
UserCouponId = x.UserCouponId,
CreatedTime = x.CreatedTime
}).ToList()
};
}
/// <summary>
/// 使用兑换码
/// </summary>
[DisplayName("使用兑换码")]
[UnitOfWork]
public async Task<long> UseRedemptionCode(UseRedemptionCodeInput input)
{
// 查找兑换码
var redemptionCode = await _redemptionCodeRepository.AsQueryable()
.Where(x => x.Code == input.Code)
.FirstAsync();
if (redemptionCode == null)
{
throw Oops.Bah("兑换码不存在");
}
// 检查是否已使用
if (redemptionCode.Status == 1)
{
throw Oops.Bah("该兑换码已被使用");
}
// 检查优惠券是否有效
var coupon = await _repository.GetByIdAsync(redemptionCode.CouponId);
if (coupon == null)
{
throw Oops.Bah("关联优惠券不存在");
}
if (coupon.Status != AvailabilityStatus.Enable)
{
throw Oops.Bah("优惠券已停用");
}
// 检查优惠券有效期
var now = DateTime.Now;
if (coupon.StartTime.HasValue && now < coupon.StartTime.Value)
{
throw Oops.Bah("优惠券尚未到使用时间");
}
if (coupon.EndTime.HasValue && now > coupon.EndTime.Value)
{
throw Oops.Bah("优惠券已过期");
}
// 检查库存
if (coupon.TotalQuantity > 0 && coupon.ClaimedQuantity >= coupon.TotalQuantity)
{
throw Oops.Bah("优惠券已领完");
}
// 创建用户优惠券记录
var userCoupon = new UserCoupon
{
Id = _idGenerator.NextId(),
UserId = input.UserId ?? 0,
CouponId = coupon.Id,
ClaimTime = now,
Status = 0,
RedemptionCodeId = redemptionCode.Id,
RedemptionCode = redemptionCode.Code,
DeleteMark = false
};
await _userCouponRepository.InsertAsync(userCoupon);
// 更新兑换码状态
redemptionCode.Status = 1;
redemptionCode.UsedTime = now;
redemptionCode.UserCouponId = userCoupon.Id;
await _redemptionCodeRepository.UpdateAsync(redemptionCode);
// 更新优惠券领取数量
coupon.ClaimedQuantity++;
await _repository.UpdateAsync(coupon);
return userCoupon.Id;
}
/// <summary>
/// 生成随机兑换码
/// </summary>
private string GenerateRandomCode(int length)
{
const string chars = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";
var random = new Random();
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
/// <summary>

View File

@ -109,11 +109,6 @@ public class CouponPageOutput
/// </summary>
public List<long> EventIds { get; set; }
/// <summary>
/// 兑换码
/// </summary>
public string RedemptionCode { get; set; }
/// <summary>
/// 总数量
/// </summary>
@ -161,3 +156,101 @@ public class EventSelectOutput
/// </summary>
public string Name { get; set; }
}
/// <summary>
/// 生成兑换码输入
/// </summary>
public class GenerateRedemptionCodesInput
{
/// <summary>
/// 优惠券ID
/// </summary>
[Required(ErrorMessage = "优惠券ID不能为空")]
public long CouponId { get; set; }
/// <summary>
/// 生成数量
/// </summary>
[Required(ErrorMessage = "生成数量不能为空")]
[Range(1, 1000, ErrorMessage = "生成数量必须在1-1000之间")]
public int Count { get; set; }
}
/// <summary>
/// 兑换码输出
/// </summary>
public class RedemptionCodeOutput
{
/// <summary>
/// ID
/// </summary>
public long Id { get; set; }
/// <summary>
/// 优惠券ID
/// </summary>
public long CouponId { get; set; }
/// <summary>
/// 兑换码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 使用状态(0-未使用 1-已使用)
/// </summary>
public int Status { get; set; }
/// <summary>
/// 使用时间
/// </summary>
public DateTime? UsedTime { get; set; }
/// <summary>
/// 关联的用户优惠券ID
/// </summary>
public long? UserCouponId { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedTime { get; set; }
}
/// <summary>
/// 使用兑换码输入
/// </summary>
public class UseRedemptionCodeInput
{
/// <summary>
/// 兑换码
/// </summary>
[Required(ErrorMessage = "兑换码不能为空")]
public string Code { get; set; }
/// <summary>
/// 用户ID
/// </summary>
public long? UserId { get; set; }
}
/// <summary>
/// 兑换码查询输入
/// </summary>
public class RedemptionCodeQueryInput : Pagination
{
/// <summary>
/// 优惠券ID
/// </summary>
public long? CouponId { get; set; }
/// <summary>
/// 使用状态(0-未使用 1-已使用)
/// </summary>
public int? Status { get; set; }
/// <summary>
/// 兑换码(模糊查询)
/// </summary>
public string? Code { get; set; }
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YD_Event.Application.Event.Dtos;
using YD_Event.Application.Common;
using YD_Event.Core.Entities;
using YD_Event.Core.Enum;
using Easy.Core;

View File

@ -62,6 +62,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
private readonly ProjectService _projectService;
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Coupon> _couponRepository;
private readonly ISqlSugarRepository<YD_Event.Core.Entities.UserCoupon> _userCouponRepository;
private readonly ISqlSugarRepository<YD_Event.Core.Entities.CouponRedemptionCode> _redemptionCodeRepository;
private readonly ISqlSugarRepository<EventRegistrationPayment> _paymentRepository;
private readonly ILogger<UserEventRegistrationService> _logger;
private readonly OrderNoGeneratorService _orderNoGeneratorService;
@ -95,6 +96,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
ProjectService projectService,
ISqlSugarRepository<YD_Event.Core.Entities.Coupon> couponRepository,
ISqlSugarRepository<YD_Event.Core.Entities.UserCoupon> userCouponRepository,
ISqlSugarRepository<YD_Event.Core.Entities.CouponRedemptionCode> redemptionCodeRepository,
ISqlSugarRepository<EventRegistrationPayment> paymentRepository,
ILogger<UserEventRegistrationService> logger,
OrderNoGeneratorService orderNoGeneratorService)
@ -127,6 +129,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
_projectService = projectService;
_couponRepository = couponRepository;
_userCouponRepository = userCouponRepository;
_redemptionCodeRepository = redemptionCodeRepository;
_paymentRepository = paymentRepository;
_logger = logger;
_orderNoGeneratorService = orderNoGeneratorService;
@ -1171,9 +1174,21 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
InvalidReason = ""
};
// 查找优惠券(通过兑换码)
// 查找兑换码
var redemptionCode = await _redemptionCodeRepository.GetFirstAsync(rc =>
rc.Code == input.CouponCode &&
rc.Status == 0 && // 0-未使用
!rc.DeleteMark);
if (redemptionCode == null)
{
result.InvalidReason = "兑换码不存在或已使用";
return result;
}
// 查找优惠券
var coupon = await _couponRepository.GetFirstAsync(c =>
c.RedemptionCode == input.CouponCode &&
c.Id == redemptionCode.CouponId &&
c.Status == AvailabilityStatus.Enable &&
!c.DeleteMark);
@ -1234,12 +1249,20 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
CouponId = coupon.Id,
ClaimTime = DateTime.Now,
Status = 0, // 未使用
RedemptionCodeId = redemptionCode.Id,
RedemptionCode = redemptionCode.Code,
CreatedUserId = userId,
CreatedTime = DateTime.Now,
DeleteMark = false
};
await _userCouponRepository.InsertAsync(userCoupon);
// 更新兑换码状态和关联
redemptionCode.Status = 1; // 已使用
redemptionCode.UsedTime = DateTime.Now;
redemptionCode.UserCouponId = userCoupon.Id;
await _redemptionCodeRepository.UpdateAsync(redemptionCode);
// 更新优惠券已领取数量
coupon.ClaimedQuantity += 1;
await _couponRepository.UpdateAsync(coupon);

View File

@ -41,6 +41,8 @@ public class AddMerchantInput
/// <summary>
/// 联系电话
/// </summary>
[Required(ErrorMessage = "联系电话不能为空")]
[RegularExpression(@"^1[3-9]\d{9}$", ErrorMessage = "请输入正确的手机号格式")]
public string? ContactPhone { get; set; }
/// <summary>

View File

@ -50,6 +50,8 @@ public class PointsRuleService : BaseService<PointsRule>, ITransient
[UnitOfWork]
public async Task Add(AddPointsRuleInput input)
{
ValidateRankDetails(input.Details);
var entity = input.Adapt<PointsRule>();
entity.Id = _idGenerator.NextId();
@ -78,6 +80,8 @@ public class PointsRuleService : BaseService<PointsRule>, ITransient
var entity = await _repository.GetByIdAsync(input.Id);
if (entity == null) throw Oops.Bah("规则不存在");
ValidateRankDetails(input.Details);
input.Adapt(entity);
await _repository.UpdateAsync(entity);
@ -96,6 +100,32 @@ public class PointsRuleService : BaseService<PointsRule>, ITransient
}
}
/// <summary>
/// 验证名次积分详情是否有重叠
/// </summary>
private void ValidateRankDetails(List<PointsRuleDetailInput>? details)
{
if (details == null || details.Count <= 1)
return;
for (int i = 0; i < details.Count; i++)
{
var item1 = details[i];
for (int j = i + 1; j < details.Count; j++)
{
var item2 = details[j];
// 检查是否重叠:两个区间 [s1, e1] 和 [s2, e2] 不重叠的条件是 e1 < s2 或 e2 < s1
bool isOverlap = !(item1.EndRank < item2.StartRank || item2.EndRank < item1.StartRank);
if (isOverlap)
{
throw Oops.Bah($"名次范围 {item1.StartRank}-{item1.EndRank} 与 {item2.StartRank}-{item2.EndRank} 存在重叠,请调整!");
}
}
}
}
/// <summary>
/// 删除积分规则
/// </summary>

View File

@ -3631,7 +3631,27 @@
</member>
<member name="M:YD_Event.Application.Coupon.CouponService.GenerateCode(System.Int64)">
<summary>
生成兑换码
生成单个兑换码(兼容旧接口)
</summary>
</member>
<member name="M:YD_Event.Application.Coupon.CouponService.GenerateRedemptionCodes(YD_Event.Application.Coupon.Dtos.GenerateRedemptionCodesInput)">
<summary>
批量生成兑换码
</summary>
</member>
<member name="M:YD_Event.Application.Coupon.CouponService.GetRedemptionCodePage(YD_Event.Application.Coupon.Dtos.RedemptionCodeQueryInput)">
<summary>
兑换码分页查询
</summary>
</member>
<member name="M:YD_Event.Application.Coupon.CouponService.UseRedemptionCode(YD_Event.Application.Coupon.Dtos.UseRedemptionCodeInput)">
<summary>
使用兑换码
</summary>
</member>
<member name="M:YD_Event.Application.Coupon.CouponService.GenerateRandomCode(System.Int32)">
<summary>
生成随机兑换码
</summary>
</member>
<member name="M:YD_Event.Application.Coupon.CouponService.GetEventList">
@ -3734,11 +3754,6 @@
适用赛事ID集合 (编辑回显用)
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.CouponPageOutput.RedemptionCode">
<summary>
兑换码
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.CouponPageOutput.TotalQuantity">
<summary>
总数量
@ -3784,6 +3799,96 @@
赛事名称
</summary>
</member>
<member name="T:YD_Event.Application.Coupon.Dtos.GenerateRedemptionCodesInput">
<summary>
生成兑换码输入
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.GenerateRedemptionCodesInput.CouponId">
<summary>
优惠券ID
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.GenerateRedemptionCodesInput.Count">
<summary>
生成数量
</summary>
</member>
<member name="T:YD_Event.Application.Coupon.Dtos.RedemptionCodeOutput">
<summary>
兑换码输出
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeOutput.Id">
<summary>
ID
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeOutput.CouponId">
<summary>
优惠券ID
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeOutput.Code">
<summary>
兑换码
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeOutput.Status">
<summary>
使用状态(0-未使用 1-已使用)
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeOutput.UsedTime">
<summary>
使用时间
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeOutput.UserCouponId">
<summary>
关联的用户优惠券ID
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeOutput.CreatedTime">
<summary>
创建时间
</summary>
</member>
<member name="T:YD_Event.Application.Coupon.Dtos.UseRedemptionCodeInput">
<summary>
使用兑换码输入
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.UseRedemptionCodeInput.Code">
<summary>
兑换码
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.UseRedemptionCodeInput.UserId">
<summary>
用户ID
</summary>
</member>
<member name="T:YD_Event.Application.Coupon.Dtos.RedemptionCodeQueryInput">
<summary>
兑换码查询输入
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeQueryInput.CouponId">
<summary>
优惠券ID
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeQueryInput.Status">
<summary>
使用状态(0-未使用 1-已使用)
</summary>
</member>
<member name="P:YD_Event.Application.Coupon.Dtos.RedemptionCodeQueryInput.Code">
<summary>
兑换码(模糊查询)
</summary>
</member>
<member name="T:YD_Event.Application.Event.Dtos.ArrangementProjectListOutput">
<summary>
编排项目列表输出
@ -6724,11 +6829,7 @@
教练/领队列表
</summary>
</member>
<member name="M:YD_Event.Application.Event.EventScoreService.ImportScore(System.Int64,Microsoft.AspNetCore.Http.IFormFile)">
<summary>
导入成绩
</summary>
</member>
<!-- Badly formed XML comment ignored for member "M:YD_Event.Application.Event.EventScoreService.ImportScore(System.Int64,Microsoft.AspNetCore.Http.IFormFile)" -->
<member name="M:YD_Event.Application.Event.EventScoreService.IssueCertificate(YD_Event.Application.Event.Dtos.IssueCertificateInput)">
<summary>
发放证书
@ -9113,6 +9214,11 @@
更新积分规则
</summary>
</member>
<member name="M:YD_Event.Application.Points.PointsRuleService.ValidateRankDetails(System.Collections.Generic.List{YD_Event.Application.Points.Dtos.PointsRuleDetailInput})">
<summary>
验证名次积分详情是否有重叠
</summary>
</member>
<member name="M:YD_Event.Application.Points.PointsRuleService.Delete(System.Collections.Generic.List{System.Int64})">
<summary>
删除积分规则

View File

@ -47,12 +47,6 @@ public class Coupon : Entity<long>, ISoftDelete, ICreatedUserId, ICreatedTime, I
[SugarColumn(ColumnDescription = "可用赛事ID集合", Length = 500, IsNullable = true)]
public string EventIds { get; set; }
/// <summary>
/// 兑换码
/// </summary>
[SugarColumn(ColumnDescription = "兑换码", Length = 32, IsNullable = true)]
public string RedemptionCode { get; set; }
/// <summary>
/// 总数量(库存)
/// </summary>

View File

@ -0,0 +1,63 @@
namespace YD_Event.Core.Entities;
/// <summary>
/// 优惠券兑换码记录表
/// </summary>
[SugarTable("CouponRedemptionCode")]
public class CouponRedemptionCode : Entity<long>, ISoftDelete, ICreatedUserId, ICreatedTime, IUpdatedUserId, IUpdatedTime
{
/// <summary>
/// 优惠券ID
/// </summary>
[SugarColumn(ColumnDescription = "优惠券ID")]
public long CouponId { get; set; }
/// <summary>
/// 兑换码
/// </summary>
[SugarColumn(ColumnDescription = "兑换码", Length = 32)]
public string Code { get; set; }
/// <summary>
/// 使用状态(0-未使用 1-已使用)
/// </summary>
[SugarColumn(ColumnDescription = "使用状态", DefaultValue = "0")]
public int Status { get; set; }
/// <summary>
/// 使用时间
/// </summary>
[SugarColumn(ColumnDescription = "使用时间", IsNullable = true)]
public DateTime? UsedTime { get; set; }
/// <summary>
/// 关联的用户优惠券ID
/// </summary>
[SugarColumn(ColumnDescription = "关联的用户优惠券ID", IsNullable = true)]
public long? UserCouponId { get; set; }
/// <summary>
/// 删除标志
/// </summary>
public bool DeleteMark { get; set; }
/// <summary>
/// 创建人Id
/// </summary>
public long CreatedUserId { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedTime { get; set; }
/// <summary>
/// 更新人Id
/// </summary>
public long? UpdatedUserId { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime? UpdatedTime { get; set; }
}

View File

@ -44,6 +44,18 @@ public class UserCoupon : Entity<long>, ISoftDelete, ICreatedUserId, ICreatedTim
[SugarColumn(ColumnDescription = "关联订单ID", IsNullable = true)]
public long? OrderId { get; set; }
/// <summary>
/// 兑换码ID
/// </summary>
[SugarColumn(ColumnDescription = "兑换码ID", IsNullable = true)]
public long? RedemptionCodeId { get; set; }
/// <summary>
/// 兑换码
/// </summary>
[SugarColumn(ColumnDescription = "兑换码", Length = 32, IsNullable = true)]
public string? RedemptionCode { get; set; }
/// <summary>
/// 删除标志
/// </summary>

View File

@ -279,9 +279,9 @@
"Id": 1012,
"Name": "查看详情",
"Type": 2,
"Code": "project:view",
"Code": "project:detail",
"ParentId": 1008,
"RouteName": "btn_project_view",
"RouteName": "btn_project_detail",
"Path": "",
"Component": "",
"Redirect": "",
@ -1639,6 +1639,27 @@
"CreatedUserId": 1000,
"CreatedTime": "2023-06-01T00:00:00"
},
{
"Id": 1068,
"Name": "查看详情",
"Type": 2,
"Code": "integral:config:detail",
"ParentId": 1064,
"RouteName": "btn_integral_config_detail",
"Path": "",
"Component": "",
"Icon": "",
"IsIframe": "0",
"IsVisible": "0",
"IsKeepAlive": "1",
"IsFixed": "0",
"Status": 0,
"Sort": 4,
"Remark": "",
"DeleteMark": false,
"CreatedUserId": 1000,
"CreatedTime": "2023-06-01T00:00:00"
},
{
"Id": 2000,
"Name": "赛事管理",

View File

@ -1,13 +1,17 @@
using EasyCaching.Core;
using EasyCaching.Core;
namespace SqlSugar;
/// <summary>
/// SqlSugar ORM框架所需缓存配置
/// 解决对象池已释放的问题:每次获取缓存实例时都从服务容器获取
/// </summary>
public class SqlSugarCache : ICacheService
{
private static readonly IEasyCachingProvider Cache = App.GetRequiredService<IEasyCachingProvider>();
/// <summary>
/// 获取当前的缓存提供程序实例
/// </summary>
private static IEasyCachingProvider Cache => App.GetRequiredService<IEasyCachingProvider>();
public void Add<V>(string key, V value)
{

View File

@ -353,6 +353,37 @@
执行导出
</summary>
</member>
<member name="T:YD_Event.Core.Domain.OrderNoGeneratorService">
<summary>
订单号生成器服务
提供分布式唯一订单号生成,确保高并发下的唯一性
</summary>
</member>
<member name="M:YD_Event.Core.Domain.OrderNoGeneratorService.GenerateOrderNoAsync">
<summary>
生成唯一订单号
格式:yyyyMMddHHmmss + 4位序列号
保证高并发下的唯一性
</summary>
<returns>唯一订单号</returns>
</member>
<member name="M:YD_Event.Core.Domain.OrderNoGeneratorService.GenerateRefundOrderNoAsync">
<summary>
生成退款订单号
格式:REF + yyyyMMddHHmmss + 4位序列号
</summary>
<returns>退款订单号</returns>
</member>
<member name="M:YD_Event.Core.Domain.OrderNoGeneratorService.GenerateOrderNoInternal">
<summary>
内部生成订单号(带线程安全的序列号)
</summary>
</member>
<member name="M:YD_Event.Core.Domain.OrderNoGeneratorService.GetTimestamp(System.DateTime)">
<summary>
获取时间戳(用于比较)
</summary>
</member>
<member name="T:YD_Event.Core.Domain.Pricing.EventPricingService">
<summary>
赛事定价计算服务
@ -938,11 +969,6 @@
可用赛事ID集合(逗号分隔)
</summary>
</member>
<member name="P:YD_Event.Core.Entities.Coupon.RedemptionCode">
<summary>
兑换码
</summary>
</member>
<member name="P:YD_Event.Core.Entities.Coupon.TotalQuantity">
<summary>
总数量(库存)
@ -993,6 +1019,61 @@
更新时间
</summary>
</member>
<member name="T:YD_Event.Core.Entities.CouponRedemptionCode">
<summary>
优惠券兑换码记录表
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.CouponId">
<summary>
优惠券ID
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.Code">
<summary>
兑换码
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.Status">
<summary>
使用状态(0-未使用 1-已使用)
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.UsedTime">
<summary>
使用时间
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.UserCouponId">
<summary>
关联的用户优惠券ID
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.DeleteMark">
<summary>
删除标志
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.CreatedUserId">
<summary>
创建人Id
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.CreatedTime">
<summary>
创建时间
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.UpdatedUserId">
<summary>
更新人Id
</summary>
</member>
<member name="P:YD_Event.Core.Entities.CouponRedemptionCode.UpdatedTime">
<summary>
更新时间
</summary>
</member>
<member name="T:YD_Event.Core.Entities.EventCertificate">
<summary>
赛事证书表
@ -4051,6 +4132,16 @@
关联订单ID
</summary>
</member>
<member name="P:YD_Event.Core.Entities.UserCoupon.RedemptionCodeId">
<summary>
兑换码ID
</summary>
</member>
<member name="P:YD_Event.Core.Entities.UserCoupon.RedemptionCode">
<summary>
兑换码
</summary>
</member>
<member name="P:YD_Event.Core.Entities.UserCoupon.DeleteMark">
<summary>
删除标志
@ -5895,6 +5986,12 @@
<member name="T:SqlSugar.SqlSugarCache">
<summary>
SqlSugar ORM框架所需缓存配置
解决对象池已释放的问题:每次获取缓存实例时都从服务容器获取
</summary>
</member>
<member name="P:SqlSugar.SqlSugarCache.Cache">
<summary>
获取当前的缓存提供程序实例
</summary>
</member>
<member name="M:SqlSugar.SqlSugarExtensions.AddSqlSugar(Microsoft.Extensions.DependencyInjection.IServiceCollection,YD_Event.Core.Options.ConnectionConfigExt,System.Action{SqlSugar.ISqlSugarClient})">