diff --git a/YD_Event.Application/Coupon/CouponService.cs b/YD_Event.Application/Coupon/CouponService.cs index 09d2bb1..386e5e7 100644 --- a/YD_Event.Application/Coupon/CouponService.cs +++ b/YD_Event.Application/Coupon/CouponService.cs @@ -10,15 +10,21 @@ public class CouponService : BaseService, ITransi { private readonly ISqlSugarRepository _repository; private readonly ISqlSugarRepository _eventRepository; + private readonly ISqlSugarRepository _redemptionCodeRepository; + private readonly ISqlSugarRepository _userCouponRepository; private readonly IIdGenerator _idGenerator; public CouponService( ISqlSugarRepository repository, ISqlSugarRepository eventRepository, + ISqlSugarRepository redemptionCodeRepository, + ISqlSugarRepository userCouponRepository, IIdGenerator idGenerator) : base(repository) { _repository = repository; _eventRepository = eventRepository; + _redemptionCodeRepository = redemptionCodeRepository; + _userCouponRepository = userCouponRepository; _idGenerator = idGenerator; } @@ -77,7 +83,6 @@ public class CouponService : BaseService, 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, 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, ITransi } /// - /// 生成兑换码 + /// 生成单个兑换码(兼容旧接口) /// [DisplayName("生成兑换码")] [UnitOfWork] + [Obsolete("请使用 GenerateRedemptionCodes 方法")] public async Task 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; - } + /// + /// 批量生成兑换码 + /// + [DisplayName("批量生成兑换码")] + [UnitOfWork] + public async Task> 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(); + 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(); + } + + /// + /// 兑换码分页查询 + /// + [DisplayName("兑换码分页查询")] + public async Task> 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 + { + 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() + }; + } + + /// + /// 使用兑换码 + /// + [DisplayName("使用兑换码")] + [UnitOfWork] + public async Task 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; + } + + /// + /// 生成随机兑换码 + /// + 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()); } /// diff --git a/YD_Event.Application/Coupon/Dtos/CouponDtos.cs b/YD_Event.Application/Coupon/Dtos/CouponDtos.cs index 7cdb43e..b6fcf02 100644 --- a/YD_Event.Application/Coupon/Dtos/CouponDtos.cs +++ b/YD_Event.Application/Coupon/Dtos/CouponDtos.cs @@ -109,11 +109,6 @@ public class CouponPageOutput /// public List EventIds { get; set; } - /// - /// 兑换码 - /// - public string RedemptionCode { get; set; } - /// /// 总数量 /// @@ -161,3 +156,101 @@ public class EventSelectOutput /// public string Name { get; set; } } + +/// +/// 生成兑换码输入 +/// +public class GenerateRedemptionCodesInput +{ + /// + /// 优惠券ID + /// + [Required(ErrorMessage = "优惠券ID不能为空")] + public long CouponId { get; set; } + + /// + /// 生成数量 + /// + [Required(ErrorMessage = "生成数量不能为空")] + [Range(1, 1000, ErrorMessage = "生成数量必须在1-1000之间")] + public int Count { get; set; } +} + +/// +/// 兑换码输出 +/// +public class RedemptionCodeOutput +{ + /// + /// ID + /// + public long Id { get; set; } + + /// + /// 优惠券ID + /// + public long CouponId { get; set; } + + /// + /// 兑换码 + /// + public string Code { get; set; } + + /// + /// 使用状态(0-未使用 1-已使用) + /// + public int Status { get; set; } + + /// + /// 使用时间 + /// + public DateTime? UsedTime { get; set; } + + /// + /// 关联的用户优惠券ID + /// + public long? UserCouponId { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedTime { get; set; } +} + +/// +/// 使用兑换码输入 +/// +public class UseRedemptionCodeInput +{ + /// + /// 兑换码 + /// + [Required(ErrorMessage = "兑换码不能为空")] + public string Code { get; set; } + + /// + /// 用户ID + /// + public long? UserId { get; set; } +} + +/// +/// 兑换码查询输入 +/// +public class RedemptionCodeQueryInput : Pagination +{ + /// + /// 优惠券ID + /// + public long? CouponId { get; set; } + + /// + /// 使用状态(0-未使用 1-已使用) + /// + public int? Status { get; set; } + + /// + /// 兑换码(模糊查询) + /// + public string? Code { get; set; } +} diff --git a/YD_Event.Application/Event/UserEventRecordService.cs b/YD_Event.Application/Event/UserEventRecordService.cs index 7c51692..092558d 100644 --- a/YD_Event.Application/Event/UserEventRecordService.cs +++ b/YD_Event.Application/Event/UserEventRecordService.cs @@ -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; diff --git a/YD_Event.Application/Event/UserEventRegistrationService.cs b/YD_Event.Application/Event/UserEventRegistrationService.cs index 59f94cb..5ea47ff 100644 --- a/YD_Event.Application/Event/UserEventRegistrationService.cs +++ b/YD_Event.Application/Event/UserEventRegistrationService.cs @@ -62,6 +62,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient private readonly ProjectService _projectService; private readonly ISqlSugarRepository _couponRepository; private readonly ISqlSugarRepository _userCouponRepository; + private readonly ISqlSugarRepository _redemptionCodeRepository; private readonly ISqlSugarRepository _paymentRepository; private readonly ILogger _logger; private readonly OrderNoGeneratorService _orderNoGeneratorService; @@ -95,6 +96,7 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient ProjectService projectService, ISqlSugarRepository couponRepository, ISqlSugarRepository userCouponRepository, + ISqlSugarRepository redemptionCodeRepository, ISqlSugarRepository paymentRepository, ILogger 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); diff --git a/YD_Event.Application/Merchant/Dtos/AddMerchantInput.cs b/YD_Event.Application/Merchant/Dtos/AddMerchantInput.cs index cc453b9..2681a4a 100644 --- a/YD_Event.Application/Merchant/Dtos/AddMerchantInput.cs +++ b/YD_Event.Application/Merchant/Dtos/AddMerchantInput.cs @@ -41,6 +41,8 @@ public class AddMerchantInput /// /// 联系电话 /// + [Required(ErrorMessage = "联系电话不能为空")] + [RegularExpression(@"^1[3-9]\d{9}$", ErrorMessage = "请输入正确的手机号格式")] public string? ContactPhone { get; set; } /// diff --git a/YD_Event.Application/Points/PointsRuleService.cs b/YD_Event.Application/Points/PointsRuleService.cs index 94eb34f..b2ad9e0 100644 --- a/YD_Event.Application/Points/PointsRuleService.cs +++ b/YD_Event.Application/Points/PointsRuleService.cs @@ -50,6 +50,8 @@ public class PointsRuleService : BaseService, ITransient [UnitOfWork] public async Task Add(AddPointsRuleInput input) { + ValidateRankDetails(input.Details); + var entity = input.Adapt(); entity.Id = _idGenerator.NextId(); @@ -78,6 +80,8 @@ public class PointsRuleService : BaseService, 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, ITransient } } + /// + /// 验证名次积分详情是否有重叠 + /// + private void ValidateRankDetails(List? 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} 存在重叠,请调整!"); + } + } + } + } + /// /// 删除积分规则 /// diff --git a/YD_Event.Application/YD_Event.Application.xml b/YD_Event.Application/YD_Event.Application.xml index 2e6152e..27239de 100644 --- a/YD_Event.Application/YD_Event.Application.xml +++ b/YD_Event.Application/YD_Event.Application.xml @@ -3631,7 +3631,27 @@ - 生成兑换码 + 生成单个兑换码(兼容旧接口) + + + + + 批量生成兑换码 + + + + + 兑换码分页查询 + + + + + 使用兑换码 + + + + + 生成随机兑换码 @@ -3734,11 +3754,6 @@ 适用赛事ID集合 (编辑回显用) - - - 兑换码 - - 总数量 @@ -3784,6 +3799,96 @@ 赛事名称 + + + 生成兑换码输入 + + + + + 优惠券ID + + + + + 生成数量 + + + + + 兑换码输出 + + + + + ID + + + + + 优惠券ID + + + + + 兑换码 + + + + + 使用状态(0-未使用 1-已使用) + + + + + 使用时间 + + + + + 关联的用户优惠券ID + + + + + 创建时间 + + + + + 使用兑换码输入 + + + + + 兑换码 + + + + + 用户ID + + + + + 兑换码查询输入 + + + + + 优惠券ID + + + + + 使用状态(0-未使用 1-已使用) + + + + + 兑换码(模糊查询) + + 编排项目列表输出 @@ -6724,11 +6829,7 @@ 教练/领队列表 - - - 导入成绩 - - + 发放证书 @@ -9113,6 +9214,11 @@ 更新积分规则 + + + 验证名次积分详情是否有重叠 + + 删除积分规则 diff --git a/YD_Event.Core/Entities/Coupon.cs b/YD_Event.Core/Entities/Coupon.cs index 0cde2c9..adf9f32 100644 --- a/YD_Event.Core/Entities/Coupon.cs +++ b/YD_Event.Core/Entities/Coupon.cs @@ -47,12 +47,6 @@ public class Coupon : Entity, ISoftDelete, ICreatedUserId, ICreatedTime, I [SugarColumn(ColumnDescription = "可用赛事ID集合", Length = 500, IsNullable = true)] public string EventIds { get; set; } - /// - /// 兑换码 - /// - [SugarColumn(ColumnDescription = "兑换码", Length = 32, IsNullable = true)] - public string RedemptionCode { get; set; } - /// /// 总数量(库存) /// diff --git a/YD_Event.Core/Entities/CouponRedemptionCode.cs b/YD_Event.Core/Entities/CouponRedemptionCode.cs new file mode 100644 index 0000000..d7bcf5b --- /dev/null +++ b/YD_Event.Core/Entities/CouponRedemptionCode.cs @@ -0,0 +1,63 @@ +namespace YD_Event.Core.Entities; + +/// +/// 优惠券兑换码记录表 +/// +[SugarTable("CouponRedemptionCode")] +public class CouponRedemptionCode : Entity, ISoftDelete, ICreatedUserId, ICreatedTime, IUpdatedUserId, IUpdatedTime +{ + /// + /// 优惠券ID + /// + [SugarColumn(ColumnDescription = "优惠券ID")] + public long CouponId { get; set; } + + /// + /// 兑换码 + /// + [SugarColumn(ColumnDescription = "兑换码", Length = 32)] + public string Code { get; set; } + + /// + /// 使用状态(0-未使用 1-已使用) + /// + [SugarColumn(ColumnDescription = "使用状态", DefaultValue = "0")] + public int Status { get; set; } + + /// + /// 使用时间 + /// + [SugarColumn(ColumnDescription = "使用时间", IsNullable = true)] + public DateTime? UsedTime { get; set; } + + /// + /// 关联的用户优惠券ID + /// + [SugarColumn(ColumnDescription = "关联的用户优惠券ID", IsNullable = true)] + public long? UserCouponId { get; set; } + + /// + /// 删除标志 + /// + public bool DeleteMark { get; set; } + + /// + /// 创建人Id + /// + public long CreatedUserId { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedTime { get; set; } + + /// + /// 更新人Id + /// + public long? UpdatedUserId { get; set; } + + /// + /// 更新时间 + /// + public DateTime? UpdatedTime { get; set; } +} diff --git a/YD_Event.Core/Entities/UserCoupon.cs b/YD_Event.Core/Entities/UserCoupon.cs index 857e326..176bbf7 100644 --- a/YD_Event.Core/Entities/UserCoupon.cs +++ b/YD_Event.Core/Entities/UserCoupon.cs @@ -44,6 +44,18 @@ public class UserCoupon : Entity, ISoftDelete, ICreatedUserId, ICreatedTim [SugarColumn(ColumnDescription = "关联订单ID", IsNullable = true)] public long? OrderId { get; set; } + /// + /// 兑换码ID + /// + [SugarColumn(ColumnDescription = "兑换码ID", IsNullable = true)] + public long? RedemptionCodeId { get; set; } + + /// + /// 兑换码 + /// + [SugarColumn(ColumnDescription = "兑换码", Length = 32, IsNullable = true)] + public string? RedemptionCode { get; set; } + /// /// 删除标志 /// diff --git a/YD_Event.Core/InitData/sysmenu.txt b/YD_Event.Core/InitData/sysmenu.txt index e832237..6942a16 100644 --- a/YD_Event.Core/InitData/sysmenu.txt +++ b/YD_Event.Core/InitData/sysmenu.txt @@ -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": "赛事管理", diff --git a/YD_Event.Core/SqlSugar/SqlSugarCache.cs b/YD_Event.Core/SqlSugar/SqlSugarCache.cs index 72c8e54..6757786 100644 --- a/YD_Event.Core/SqlSugar/SqlSugarCache.cs +++ b/YD_Event.Core/SqlSugar/SqlSugarCache.cs @@ -1,13 +1,17 @@ -using EasyCaching.Core; +using EasyCaching.Core; namespace SqlSugar; /// /// SqlSugar ORM框架所需缓存配置 +/// 解决对象池已释放的问题:每次获取缓存实例时都从服务容器获取 /// public class SqlSugarCache : ICacheService { - private static readonly IEasyCachingProvider Cache = App.GetRequiredService(); + /// + /// 获取当前的缓存提供程序实例 + /// + private static IEasyCachingProvider Cache => App.GetRequiredService(); public void Add(string key, V value) { diff --git a/YD_Event.Core/YD_Event.Core.xml b/YD_Event.Core/YD_Event.Core.xml index 7620ff2..a89b5db 100644 --- a/YD_Event.Core/YD_Event.Core.xml +++ b/YD_Event.Core/YD_Event.Core.xml @@ -353,6 +353,37 @@ 执行导出 + + + 订单号生成器服务 + 提供分布式唯一订单号生成,确保高并发下的唯一性 + + + + + 生成唯一订单号 + 格式:yyyyMMddHHmmss + 4位序列号 + 保证高并发下的唯一性 + + 唯一订单号 + + + + 生成退款订单号 + 格式:REF + yyyyMMddHHmmss + 4位序列号 + + 退款订单号 + + + + 内部生成订单号(带线程安全的序列号) + + + + + 获取时间戳(用于比较) + + 赛事定价计算服务 @@ -938,11 +969,6 @@ 可用赛事ID集合(逗号分隔) - - - 兑换码 - - 总数量(库存) @@ -993,6 +1019,61 @@ 更新时间 + + + 优惠券兑换码记录表 + + + + + 优惠券ID + + + + + 兑换码 + + + + + 使用状态(0-未使用 1-已使用) + + + + + 使用时间 + + + + + 关联的用户优惠券ID + + + + + 删除标志 + + + + + 创建人Id + + + + + 创建时间 + + + + + 更新人Id + + + + + 更新时间 + + 赛事证书表 @@ -4051,6 +4132,16 @@ 关联订单ID + + + 兑换码ID + + + + + 兑换码 + + 删除标志 @@ -5895,6 +5986,12 @@ SqlSugar ORM框架所需缓存配置 + 解决对象池已释放的问题:每次获取缓存实例时都从服务容器获取 + + + + + 获取当前的缓存提供程序实例