feat(infra): MedioRepository + SeccionRepository + integration tests — ADM-001 B5
This commit is contained in:
188
src/api/SIGCM2.Infrastructure/Persistence/MedioRepository.cs
Normal file
188
src/api/SIGCM2.Infrastructure/Persistence/MedioRepository.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using System.Text;
|
||||
using Dapper;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.Common;
|
||||
using SIGCM2.Domain.Entities;
|
||||
|
||||
namespace SIGCM2.Infrastructure.Persistence;
|
||||
|
||||
public sealed class MedioRepository : IMedioRepository
|
||||
{
|
||||
private readonly SqlConnectionFactory _connectionFactory;
|
||||
|
||||
public MedioRepository(SqlConnectionFactory connectionFactory)
|
||||
{
|
||||
_connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
public async Task<int> AddAsync(Medio m, CancellationToken ct = default)
|
||||
{
|
||||
// DF handles: Activo (1), FechaCreacion (SYSUTCDATETIME()).
|
||||
const string sql = """
|
||||
INSERT INTO dbo.Medio (Codigo, Nombre, Tipo, PlataformaEmpresaId)
|
||||
OUTPUT INSERTED.Id
|
||||
VALUES (@Codigo, @Nombre, @Tipo, @PlataformaEmpresaId)
|
||||
""";
|
||||
|
||||
await using var connection = _connectionFactory.CreateConnection();
|
||||
await connection.OpenAsync(ct);
|
||||
|
||||
return await connection.ExecuteScalarAsync<int>(sql, new
|
||||
{
|
||||
m.Codigo,
|
||||
m.Nombre,
|
||||
Tipo = (int)m.Tipo,
|
||||
m.PlataformaEmpresaId,
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<Medio?> GetByIdAsync(int id, CancellationToken ct = default)
|
||||
{
|
||||
const string sql = """
|
||||
SELECT Id, Codigo, Nombre, Tipo, PlataformaEmpresaId, Activo, FechaCreacion, FechaModificacion
|
||||
FROM dbo.Medio
|
||||
WHERE Id = @Id
|
||||
""";
|
||||
|
||||
await using var connection = _connectionFactory.CreateConnection();
|
||||
await connection.OpenAsync(ct);
|
||||
|
||||
var row = await connection.QuerySingleOrDefaultAsync<MedioRow>(sql, new { Id = id });
|
||||
return row is null ? null : MapRow(row);
|
||||
}
|
||||
|
||||
public async Task<bool> ExistsByCodigoAsync(string codigo, CancellationToken ct = default)
|
||||
{
|
||||
const string sql = """
|
||||
SELECT COUNT(1) FROM dbo.Medio WHERE Codigo = @Codigo
|
||||
""";
|
||||
|
||||
await using var connection = _connectionFactory.CreateConnection();
|
||||
await connection.OpenAsync(ct);
|
||||
|
||||
var count = await connection.ExecuteScalarAsync<int>(sql, new { Codigo = codigo });
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
public async Task UpdateAsync(Medio m, CancellationToken ct = default)
|
||||
{
|
||||
const string sql = """
|
||||
UPDATE dbo.Medio
|
||||
SET Nombre = @Nombre,
|
||||
Tipo = @Tipo,
|
||||
PlataformaEmpresaId = @PlataformaEmpresaId,
|
||||
Activo = @Activo,
|
||||
FechaModificacion = @FechaModificacion
|
||||
WHERE Id = @Id
|
||||
""";
|
||||
|
||||
await using var connection = _connectionFactory.CreateConnection();
|
||||
await connection.OpenAsync(ct);
|
||||
|
||||
await connection.ExecuteAsync(sql, new
|
||||
{
|
||||
m.Nombre,
|
||||
Tipo = (int)m.Tipo,
|
||||
m.PlataformaEmpresaId,
|
||||
m.Activo,
|
||||
FechaModificacion = m.FechaModificacion ?? DateTime.UtcNow,
|
||||
m.Id,
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<PagedResult<Medio>> GetPagedAsync(MediosQuery q, CancellationToken ct = default)
|
||||
{
|
||||
var page = Math.Max(1, q.Page);
|
||||
var pageSize = Math.Clamp(q.PageSize, 1, 100);
|
||||
var offset = (page - 1) * pageSize;
|
||||
|
||||
var where = new StringBuilder("WHERE 1=1");
|
||||
var parameters = new DynamicParameters();
|
||||
parameters.Add("PageSize", pageSize);
|
||||
parameters.Add("Offset", offset);
|
||||
|
||||
if (q.Activo.HasValue)
|
||||
{
|
||||
where.Append(" AND Activo = @Activo");
|
||||
parameters.Add("Activo", q.Activo.Value ? 1 : 0);
|
||||
}
|
||||
|
||||
if (q.Tipo.HasValue)
|
||||
{
|
||||
where.Append(" AND Tipo = @Tipo");
|
||||
parameters.Add("Tipo", (int)q.Tipo.Value);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(q.Search))
|
||||
{
|
||||
where.Append(" AND (Codigo LIKE @Search OR Nombre LIKE @Search)");
|
||||
parameters.Add("Search", $"%{q.Search}%");
|
||||
}
|
||||
|
||||
var sql = $"""
|
||||
SELECT
|
||||
Id, Codigo, Nombre, Tipo, PlataformaEmpresaId, Activo, FechaCreacion, FechaModificacion,
|
||||
COUNT(*) OVER() AS TotalCount
|
||||
FROM dbo.Medio
|
||||
{where}
|
||||
ORDER BY Codigo
|
||||
OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY
|
||||
""";
|
||||
|
||||
await using var connection = _connectionFactory.CreateConnection();
|
||||
await connection.OpenAsync(ct);
|
||||
|
||||
var rows = await connection.QueryAsync<MedioPagedRow>(sql, parameters);
|
||||
var list = rows.ToList();
|
||||
|
||||
var total = list.Count > 0 ? list[0].TotalCount : 0;
|
||||
var items = list.Select(r => MapRow(r)).ToList();
|
||||
|
||||
return new PagedResult<Medio>(items, page, pageSize, total);
|
||||
}
|
||||
|
||||
// ── mapping ───────────────────────────────────────────────────────────────
|
||||
|
||||
private static Medio MapRow(MedioRow r)
|
||||
=> new(
|
||||
id: r.Id,
|
||||
codigo: r.Codigo,
|
||||
nombre: r.Nombre,
|
||||
tipo: (TipoMedio)r.Tipo,
|
||||
plataformaEmpresaId: r.PlataformaEmpresaId,
|
||||
activo: r.Activo,
|
||||
fechaCreacion: r.FechaCreacion,
|
||||
fechaModificacion: r.FechaModificacion);
|
||||
|
||||
private static Medio MapRow(MedioPagedRow r)
|
||||
=> new(
|
||||
id: r.Id,
|
||||
codigo: r.Codigo,
|
||||
nombre: r.Nombre,
|
||||
tipo: (TipoMedio)r.Tipo,
|
||||
plataformaEmpresaId: r.PlataformaEmpresaId,
|
||||
activo: r.Activo,
|
||||
fechaCreacion: r.FechaCreacion,
|
||||
fechaModificacion: r.FechaModificacion);
|
||||
|
||||
private sealed record MedioRow(
|
||||
int Id,
|
||||
string Codigo,
|
||||
string Nombre,
|
||||
byte Tipo,
|
||||
int? PlataformaEmpresaId,
|
||||
bool Activo,
|
||||
DateTime FechaCreacion,
|
||||
DateTime? FechaModificacion);
|
||||
|
||||
private sealed record MedioPagedRow(
|
||||
int Id,
|
||||
string Codigo,
|
||||
string Nombre,
|
||||
byte Tipo,
|
||||
int? PlataformaEmpresaId,
|
||||
bool Activo,
|
||||
DateTime FechaCreacion,
|
||||
DateTime? FechaModificacion,
|
||||
int TotalCount);
|
||||
}
|
||||
Reference in New Issue
Block a user