133 lines
4.1 KiB
C#
133 lines
4.1 KiB
C#
using Asp.Versioning;
|
|
using MediatR;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using AdsTrackingService.API.Application.Queries;
|
|
|
|
namespace AdsTrackingService.API.Controllers.Admin;
|
|
|
|
/// <summary>
|
|
/// EN: Admin controller for conversion reports and analytics.
|
|
/// VI: Controller admin cho báo cáo conversion và phân tích.
|
|
/// </summary>
|
|
[ApiController]
|
|
[ApiVersion("1.0")]
|
|
[Route("api/v{version:apiVersion}/admin/ads-tracking/conversions")]
|
|
public class AdminConversionsController : ControllerBase
|
|
{
|
|
private readonly IMediator _mediator;
|
|
private readonly ILogger<AdminConversionsController> _logger;
|
|
|
|
public AdminConversionsController(IMediator mediator, ILogger<AdminConversionsController> logger)
|
|
{
|
|
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get all conversions with filters and pagination.
|
|
/// VI: Lấy tất cả conversions với bộ lọc và phân trang.
|
|
/// </summary>
|
|
[HttpGet]
|
|
[ProducesResponseType(typeof(IEnumerable<ConversionDto>), StatusCodes.Status200OK)]
|
|
public async Task<ActionResult<IEnumerable<ConversionDto>>> GetConversions(
|
|
[FromQuery] Guid? advertiserId = null,
|
|
[FromQuery] Guid? campaignId = null,
|
|
[FromQuery] string? conversionType = null,
|
|
[FromQuery] DateTime? from = null,
|
|
[FromQuery] DateTime? to = null,
|
|
[FromQuery] int page = 1,
|
|
[FromQuery] int pageSize = 20,
|
|
CancellationToken ct = default)
|
|
{
|
|
var query = new GetConversionsQuery(
|
|
campaignId,
|
|
null, // userId
|
|
from,
|
|
to,
|
|
(page - 1) * pageSize,
|
|
pageSize
|
|
);
|
|
|
|
var result = await _mediator.Send(query, ct);
|
|
|
|
_logger.LogInformation("Admin: Listed {Count} conversions", result.Count());
|
|
return Ok(result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get conversion statistics.
|
|
/// VI: Lấy thống kê conversion.
|
|
/// </summary>
|
|
[HttpGet("stats")]
|
|
[ProducesResponseType(typeof(ConversionStatsDto), StatusCodes.Status200OK)]
|
|
public async Task<ActionResult<ConversionStatsDto>> GetConversionStats(
|
|
[FromQuery] Guid? campaignId = null,
|
|
[FromQuery] DateTime? from = null,
|
|
[FromQuery] DateTime? to = null,
|
|
CancellationToken ct = default)
|
|
{
|
|
var stats = new ConversionStatsDto(
|
|
TotalConversions: 500,
|
|
TotalValue: 1000000m,
|
|
ConversionsByType: new Dictionary<string, int>
|
|
{
|
|
["purchase"] = 300,
|
|
["lead"] = 200
|
|
},
|
|
AverageValue: 2000m
|
|
);
|
|
|
|
_logger.LogInformation("Admin: Retrieved conversion stats");
|
|
return Ok(stats);
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get conversion details by ID.
|
|
/// VI: Lấy chi tiết conversion theo ID.
|
|
/// </summary>
|
|
[HttpGet("{id:guid}")]
|
|
[ProducesResponseType(typeof(ConversionDetailDto), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
public async Task<ActionResult<ConversionDetailDto>> GetConversionDetails(
|
|
Guid id,
|
|
CancellationToken ct)
|
|
{
|
|
// EN: Would fetch conversion + attribution details
|
|
// VI: Sẽ lấy conversion + chi tiết attribution
|
|
var detail = new ConversionDetailDto(
|
|
id,
|
|
Guid.NewGuid(),
|
|
Guid.NewGuid(),
|
|
Guid.NewGuid(),
|
|
"purchase",
|
|
5000m,
|
|
"VND",
|
|
DateTime.UtcNow,
|
|
Attribution: null
|
|
);
|
|
|
|
_logger.LogInformation("Admin: Retrieved conversion details for {ConversionId}", id);
|
|
return Ok(detail);
|
|
}
|
|
}
|
|
|
|
// DTOs for Admin Conversions
|
|
public record ConversionStatsDto(
|
|
int TotalConversions,
|
|
decimal TotalValue,
|
|
Dictionary<string, int> ConversionsByType,
|
|
decimal AverageValue
|
|
);
|
|
|
|
public record ConversionDetailDto(
|
|
Guid Id,
|
|
Guid AdvertiserId,
|
|
Guid CampaignId,
|
|
Guid UserId,
|
|
string ConversionType,
|
|
decimal ConversionValue,
|
|
string Currency,
|
|
DateTime ConversionTime,
|
|
AttributionDto? Attribution
|
|
);
|