Project.Fengling.QoderVersion/Backend/src/Fengling.Backend.Web/Application/Queries/MarketingCodes/MarketingCodeQueries.cs
sam d88ec60ef4 feat(marketing): 扩展营销码支持品类信息并完善通知机制
- 在MarketingCode聚合中新增品类ID和品类名称字段,完善产品信息结构
- 迁移生成营销码命令,支持传入品类ID和品类名称参数
- 积分发放失败时发送积分获得失败通知集成事件
- 新增通知发送及积分失败通知的集成事件处理器,使用SSE推送通知
- 在积分相关集成事件处理器中添加发送积分变动通知功能
- 移除Notification聚合,相关数据库表删除
- 新增分页结果类型PagedResult,支持营销码查询分页返回
- 营销码查询支持分页参数,返回分页结果数据
2026-02-13 19:00:06 +08:00

161 lines
5.3 KiB
C#

using Fengling.Backend.Infrastructure;
namespace Fengling.Backend.Web.Application.Queries.MarketingCodes;
/// <summary>
/// 营销码DTO
/// </summary>
public record MarketingCodeDto
{
public Guid Id { get; init; }
public string Code { get; init; } = string.Empty;
public string BatchNo { get; init; } = string.Empty;
public Guid ProductId { get; init; }
public string ProductName { get; init; } = string.Empty;
public Guid? CategoryId { get; init; }
public string? CategoryName { get; init; }
public bool IsUsed { get; init; }
public Guid? UsedByMemberId { get; init; }
public DateTime? UsedAt { get; init; }
public DateTime? ExpiryDate { get; init; }
public DateTime CreatedAt { get; init; }
}
/// <summary>
/// 批次信息DTO
/// </summary>
public record MarketingCodeBatchDto
{
public string BatchNo { get; init; } = string.Empty;
public Guid ProductId { get; init; }
public string ProductName { get; init; } = string.Empty;
public Guid? CategoryId { get; init; }
public string? CategoryName { get; init; }
public int TotalCount { get; init; }
public int UsedCount { get; init; }
public DateTime CreatedAt { get; init; }
public DateTime? ExpiryDate { get; init; }
}
/// <summary>
/// 查询营销码列表
/// </summary>
public record GetMarketingCodesQuery(
string? BatchNo = null,
Guid? ProductId = null,
bool? IsUsed = null,
DateTime? StartDate = null,
DateTime? EndDate = null,
int Page = 1,
int PageSize = 20) : IQuery<PagedResult<MarketingCodeDto>>;
public class GetMarketingCodesQueryHandler(ApplicationDbContext dbContext)
: IQueryHandler<GetMarketingCodesQuery, PagedResult<MarketingCodeDto>>
{
public async Task<PagedResult<MarketingCodeDto>> Handle(GetMarketingCodesQuery request, CancellationToken cancellationToken)
{
var query = dbContext.MarketingCodes.AsQueryable();
// 按批次号筛选
if (!string.IsNullOrWhiteSpace(request.BatchNo))
{
query = query.Where(x => x.BatchNo == request.BatchNo);
}
// 按产品ID筛选
if (request.ProductId.HasValue)
{
query = query.Where(x => x.ProductInfo.ProductId == request.ProductId.Value);
}
// 按使用状态筛选
if (request.IsUsed.HasValue)
{
query = query.Where(x => x.IsUsed == request.IsUsed.Value);
}
// 按创建时间范围筛选
if (request.StartDate.HasValue)
{
query = query.Where(x => x.CreatedAt >= request.StartDate.Value);
}
if (request.EndDate.HasValue)
{
// EndDate包含当天整天
var endOfDay = request.EndDate.Value.Date.AddDays(1);
query = query.Where(x => x.CreatedAt < endOfDay);
}
// 获取总数
var totalCount = await query.CountAsync(cancellationToken);
// 分页查询
var marketingCodes = await query
.OrderByDescending(x => x.CreatedAt)
.Skip((request.Page - 1) * request.PageSize)
.Take(request.PageSize)
.Select(x => new MarketingCodeDto
{
Id = x.Id.Id,
Code = x.Code,
BatchNo = x.BatchNo,
ProductId = x.ProductInfo.ProductId,
ProductName = x.ProductInfo.ProductName,
CategoryId = x.ProductInfo.CategoryId,
CategoryName = x.ProductInfo.CategoryName,
IsUsed = x.IsUsed,
UsedByMemberId = x.UsedByMemberId,
UsedAt = x.UsedAt,
ExpiryDate = x.ExpiryDate,
CreatedAt = x.CreatedAt
})
.ToListAsync(cancellationToken);
return new PagedResult<MarketingCodeDto>(
marketingCodes,
totalCount,
request.Page,
request.PageSize);
}
}
/// <summary>
/// 查询所有批次列表
/// </summary>
public record GetMarketingCodeBatchesQuery : IQuery<List<MarketingCodeBatchDto>>;
public class GetMarketingCodeBatchesQueryHandler(ApplicationDbContext dbContext)
: IQueryHandler<GetMarketingCodeBatchesQuery, List<MarketingCodeBatchDto>>
{
public async Task<List<MarketingCodeBatchDto>> Handle(GetMarketingCodeBatchesQuery request, CancellationToken cancellationToken)
{
var batches = await dbContext.MarketingCodes
.GroupBy(x => new
{
x.BatchNo,
x.ProductInfo.ProductId,
x.ProductInfo.ProductName,
x.ProductInfo.CategoryId,
x.ProductInfo.CategoryName,
x.ExpiryDate
})
.Select(g => new MarketingCodeBatchDto
{
BatchNo = g.Key.BatchNo,
ProductId = g.Key.ProductId,
ProductName = g.Key.ProductName,
CategoryId = g.Key.CategoryId,
CategoryName = g.Key.CategoryName,
TotalCount = g.Count(),
UsedCount = g.Count(x => x.IsUsed),
CreatedAt = g.Min(x => x.CreatedAt),
ExpiryDate = g.Key.ExpiryDate
})
.OrderByDescending(x => x.CreatedAt)
.ToListAsync(cancellationToken);
return batches;
}
}