Files
pos-system/services/ads-manager-service-net/src/AdsManagerService.API/Application/Queries/AudienceQueryHandlers.cs
Ho Ngoc Hai 59b2cecaf2 feat(P1): add 57 validators + 10 missing handlers across 13 services
Wave 2 — 3 parallel agents fixing P1 issues:

Validators (57 new FluentValidation validators):
- ads-manager: 10 validators for all commands
- ads-billing: 3 validators for all commands
- ads-tracking: 2 validators for missing commands
- ads-analytics: 1 validator for CreateReport
- social: 8 validators for all commands
- mining: 16 validators for all commands
- mission: 4 validators for all commands
- promotion: 13 validators for all commands

Missing handlers (10 implemented):
- promotion: ExchangeVoucher, PurchaseVoucher, SearchVouchers,
  GetCampaignStatistics, GetCampaignVouchers
- mission: GetUserMissionProgress
- mkt-facebook: GetConversations, GetCustomers
- ads-manager: ListAudiences, GetAudienceById

All validators use bilingual messages (EN/VI) and are auto-registered
via MediatR ValidatorBehavior pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 20:24:06 +07:00

116 lines
4.1 KiB
C#

using AdsManagerService.API.Controllers;
using AdsManagerService.Domain.AggregatesModel.AudienceAggregate;
using AdsManagerService.Infrastructure;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace AdsManagerService.API.Application.Queries;
/// <summary>
/// EN: Handler for ListAudiencesQuery - returns audiences for an advertiser.
/// VI: Handler cho ListAudiencesQuery - trả về audiences cho nhà quảng cáo.
/// </summary>
public class ListAudiencesQueryHandler : IRequestHandler<ListAudiencesQuery, List<AudienceDto>>
{
private readonly AdsManagerServiceContext _context;
public ListAudiencesQueryHandler(AdsManagerServiceContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task<List<AudienceDto>> Handle(ListAudiencesQuery request, CancellationToken cancellationToken)
{
// EN: Get custom audiences for the advertiser / VI: Lấy custom audiences cho nhà quảng cáo
var customAudiences = await _context.CustomAudiences
.AsNoTracking()
.Where(a => a.AdvertiserId == request.AdvertiserId)
.OrderByDescending(a => a.CreatedAt)
.Select(a => new AudienceDto
{
Id = a.Id,
Name = a.Name,
Type = "custom",
Size = a.Size,
CreatedAt = a.CreatedAt
})
.ToListAsync(cancellationToken);
// EN: Get lookalike audiences for the advertiser / VI: Lấy lookalike audiences cho nhà quảng cáo
var lookalikeAudiences = await _context.LookalikeAudiences
.AsNoTracking()
.Where(a => a.AdvertiserId == request.AdvertiserId)
.OrderByDescending(a => a.CreatedAt)
.Select(a => new AudienceDto
{
Id = a.Id,
Name = a.Name,
Type = "lookalike",
Size = a.Size,
CreatedAt = a.CreatedAt
})
.ToListAsync(cancellationToken);
// EN: Merge and sort by creation date / VI: Gộp và sắp xếp theo ngày tạo
var allAudiences = customAudiences
.Concat(lookalikeAudiences)
.OrderByDescending(a => a.CreatedAt)
.ToList();
return allAudiences;
}
}
/// <summary>
/// EN: Handler for GetAudienceByIdQuery - returns a single audience by ID.
/// VI: Handler cho GetAudienceByIdQuery - trả về một audience theo ID.
/// </summary>
public class GetAudienceByIdQueryHandler : IRequestHandler<GetAudienceByIdQuery, AudienceDto?>
{
private readonly AdsManagerServiceContext _context;
public GetAudienceByIdQueryHandler(AdsManagerServiceContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task<AudienceDto?> Handle(GetAudienceByIdQuery request, CancellationToken cancellationToken)
{
// EN: Try custom audience first / VI: Thử custom audience trước
var customAudience = await _context.CustomAudiences
.AsNoTracking()
.FirstOrDefaultAsync(a => a.Id == request.AudienceId, cancellationToken);
if (customAudience != null)
{
return new AudienceDto
{
Id = customAudience.Id,
Name = customAudience.Name,
Type = "custom",
Size = customAudience.Size,
CreatedAt = customAudience.CreatedAt
};
}
// EN: Try lookalike audience / VI: Thử lookalike audience
var lookalikeAudience = await _context.LookalikeAudiences
.AsNoTracking()
.FirstOrDefaultAsync(a => a.Id == request.AudienceId, cancellationToken);
if (lookalikeAudience != null)
{
return new AudienceDto
{
Id = lookalikeAudience.Id,
Name = lookalikeAudience.Name,
Type = "lookalike",
Size = lookalikeAudience.Size,
CreatedAt = lookalikeAudience.CreatedAt
};
}
return null;
}
}