177 lines
10 KiB
C#
177 lines
10 KiB
C#
|
|
using Dapper;
|
||
|
|
using GestionIntegral.Api.Models.Distribucion;
|
||
|
|
using Microsoft.Extensions.Logging;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Data;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Threading.Tasks;
|
||
|
|
|
||
|
|
namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||
|
|
{
|
||
|
|
public class PrecioRepository : IPrecioRepository
|
||
|
|
{
|
||
|
|
private readonly DbConnectionFactory _connectionFactory;
|
||
|
|
private readonly ILogger<PrecioRepository> _logger;
|
||
|
|
|
||
|
|
public PrecioRepository(DbConnectionFactory connectionFactory, ILogger<PrecioRepository> logger)
|
||
|
|
{
|
||
|
|
_connectionFactory = connectionFactory;
|
||
|
|
_logger = logger;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<IEnumerable<Precio>> GetByPublicacionIdAsync(int idPublicacion)
|
||
|
|
{
|
||
|
|
const string sql = "SELECT * FROM dbo.dist_Precios WHERE Id_Publicacion = @IdPublicacion ORDER BY VigenciaD DESC";
|
||
|
|
using var connection = _connectionFactory.CreateConnection();
|
||
|
|
return await connection.QueryAsync<Precio>(sql, new { IdPublicacion = idPublicacion });
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<Precio?> GetByIdAsync(int idPrecio)
|
||
|
|
{
|
||
|
|
const string sql = "SELECT * FROM dbo.dist_Precios WHERE Id_Precio = @IdPrecio";
|
||
|
|
using var connection = _connectionFactory.CreateConnection();
|
||
|
|
return await connection.QuerySingleOrDefaultAsync<Precio>(sql, new { IdPrecio = idPrecio });
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<Precio?> GetActiveByPublicacionAndDateAsync(int idPublicacion, DateTime fecha, IDbTransaction? transaction = null)
|
||
|
|
{
|
||
|
|
// Obtiene el precio vigente para una publicación en una fecha específica
|
||
|
|
const string sql = @"
|
||
|
|
SELECT TOP 1 * FROM dbo.dist_Precios
|
||
|
|
WHERE Id_Publicacion = @IdPublicacion
|
||
|
|
AND VigenciaD <= @Fecha
|
||
|
|
AND (VigenciaH IS NULL OR VigenciaH >= @Fecha)
|
||
|
|
ORDER BY VigenciaD DESC;"; // Por si hay solapamientos incorrectos, tomar el más reciente
|
||
|
|
|
||
|
|
var cn = transaction?.Connection ?? _connectionFactory.CreateConnection();
|
||
|
|
return await cn.QuerySingleOrDefaultAsync<Precio>(sql, new { IdPublicacion = idPublicacion, Fecha = fecha }, transaction);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<Precio?> GetPreviousActivePriceAsync(int idPublicacion, DateTime vigenciaDNuevo, IDbTransaction transaction)
|
||
|
|
{
|
||
|
|
// Busca el último precio activo antes de la vigenciaD del nuevo precio, que no tenga VigenciaH o cuya VigenciaH sea mayor o igual a la nueva VigenciaD - 1 día
|
||
|
|
// y que no sea el mismo periodo que se está por crear/actualizar (si tuviera un ID).
|
||
|
|
const string sql = @"
|
||
|
|
SELECT TOP 1 *
|
||
|
|
FROM dbo.dist_Precios
|
||
|
|
WHERE Id_Publicacion = @IdPublicacion
|
||
|
|
AND VigenciaD < @VigenciaDNuevo
|
||
|
|
AND VigenciaH IS NULL
|
||
|
|
ORDER BY VigenciaD DESC;";
|
||
|
|
return await transaction.Connection!.QuerySingleOrDefaultAsync<Precio>(sql, new { IdPublicacion = idPublicacion, VigenciaDNuevo = vigenciaDNuevo }, transaction);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public async Task<Precio?> CreateAsync(Precio nuevoPrecio, int idUsuario, IDbTransaction transaction)
|
||
|
|
{
|
||
|
|
const string sqlInsert = @"
|
||
|
|
INSERT INTO dbo.dist_Precios (Id_Publicacion, VigenciaD, VigenciaH, Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo)
|
||
|
|
OUTPUT INSERTED.*
|
||
|
|
VALUES (@IdPublicacion, @VigenciaD, @VigenciaH, @Lunes, @Martes, @Miercoles, @Jueves, @Viernes, @Sabado, @Domingo);";
|
||
|
|
const string sqlInsertHistorico = @"
|
||
|
|
INSERT INTO dbo.dist_Precios_H
|
||
|
|
(Id_Precio, Id_Publicacion, VigenciaD, VigenciaH, Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo, Id_Usuario, FechaMod, TipoMod)
|
||
|
|
VALUES (@IdPrecio, @IdPublicacion, @VigenciaD, @VigenciaH, @Lunes, @Martes, @Miercoles, @Jueves, @Viernes, @Sabado, @Domingo, @Id_Usuario, @FechaMod, @TipoMod);";
|
||
|
|
|
||
|
|
var inserted = await transaction.Connection!.QuerySingleAsync<Precio>(sqlInsert, nuevoPrecio, transaction);
|
||
|
|
if (inserted == null) throw new DataException("Error al crear precio.");
|
||
|
|
|
||
|
|
await transaction.Connection!.ExecuteAsync(sqlInsertHistorico, new
|
||
|
|
{
|
||
|
|
inserted.IdPrecio, inserted.IdPublicacion, inserted.VigenciaD, inserted.VigenciaH,
|
||
|
|
inserted.Lunes, inserted.Martes, inserted.Miercoles, inserted.Jueves, inserted.Viernes, inserted.Sabado, inserted.Domingo,
|
||
|
|
Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Creado"
|
||
|
|
}, transaction);
|
||
|
|
return inserted;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<bool> UpdateAsync(Precio precioAActualizar, int idUsuario, IDbTransaction transaction)
|
||
|
|
{
|
||
|
|
var actual = await transaction.Connection!.QuerySingleOrDefaultAsync<Precio>(
|
||
|
|
"SELECT * FROM dbo.dist_Precios WHERE Id_Precio = @IdPrecio",
|
||
|
|
new { precioAActualizar.IdPrecio }, transaction);
|
||
|
|
if (actual == null) throw new KeyNotFoundException("Precio no encontrado.");
|
||
|
|
|
||
|
|
const string sqlUpdate = @"
|
||
|
|
UPDATE dbo.dist_Precios SET
|
||
|
|
VigenciaH = @VigenciaH, Lunes = @Lunes, Martes = @Martes, Miercoles = @Miercoles,
|
||
|
|
Jueves = @Jueves, Viernes = @Viernes, Sabado = @Sabado, Domingo = @Domingo
|
||
|
|
-- No se permite cambiar IdPublicacion ni VigenciaD de un registro de precio existente
|
||
|
|
WHERE Id_Precio = @IdPrecio;";
|
||
|
|
const string sqlInsertHistorico = @"
|
||
|
|
INSERT INTO dbo.dist_Precios_H
|
||
|
|
(Id_Precio, Id_Publicacion, VigenciaD, VigenciaH, Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo, Id_Usuario, FechaMod, TipoMod)
|
||
|
|
VALUES (@IdPrecio, @IdPublicacion, @VigenciaD, @VigenciaH, @Lunes, @Martes, @Miercoles, @Jueves, @Viernes, @Sabado, @Domingo, @Id_Usuario, @FechaMod, @TipoMod);";
|
||
|
|
|
||
|
|
await transaction.Connection!.ExecuteAsync(sqlInsertHistorico, new
|
||
|
|
{
|
||
|
|
actual.IdPrecio, actual.IdPublicacion, actual.VigenciaD, // VigenciaD actual para el historial
|
||
|
|
VigenciaH = actual.VigenciaH, // VigenciaH actual para el historial
|
||
|
|
Lunes = actual.Lunes, Martes = actual.Martes, Miercoles = actual.Miercoles, Jueves = actual.Jueves,
|
||
|
|
Viernes = actual.Viernes, Sabado = actual.Sabado, Domingo = actual.Domingo, // Precios actuales para el historial
|
||
|
|
Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Actualizado" // O "Cerrado" si solo se actualiza VigenciaH
|
||
|
|
}, transaction);
|
||
|
|
|
||
|
|
var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlUpdate, precioAActualizar, transaction);
|
||
|
|
return rowsAffected == 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<bool> DeleteAsync(int idPrecio, int idUsuario, IDbTransaction transaction)
|
||
|
|
{
|
||
|
|
var actual = await transaction.Connection!.QuerySingleOrDefaultAsync<Precio>(
|
||
|
|
"SELECT * FROM dbo.dist_Precios WHERE Id_Precio = @IdPrecio", new { IdPrecio = idPrecio }, transaction);
|
||
|
|
if (actual == null) throw new KeyNotFoundException("Precio no encontrado para eliminar.");
|
||
|
|
|
||
|
|
const string sqlDelete = "DELETE FROM dbo.dist_Precios WHERE Id_Precio = @IdPrecio";
|
||
|
|
const string sqlInsertHistorico = @"
|
||
|
|
INSERT INTO dbo.dist_Precios_H
|
||
|
|
(Id_Precio, Id_Publicacion, VigenciaD, VigenciaH, Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo, Id_Usuario, FechaMod, TipoMod)
|
||
|
|
VALUES (@IdPrecio, @IdPublicacion, @VigenciaD, @VigenciaH, @Lunes, @Martes, @Miercoles, @Jueves, @Viernes, @Sabado, @Domingo, @Id_Usuario, @FechaMod, @TipoMod);";
|
||
|
|
|
||
|
|
await transaction.Connection!.ExecuteAsync(sqlInsertHistorico, new
|
||
|
|
{
|
||
|
|
actual.IdPrecio, actual.IdPublicacion, actual.VigenciaD, actual.VigenciaH,
|
||
|
|
actual.Lunes, actual.Martes, actual.Miercoles, actual.Jueves, actual.Viernes, actual.Sabado, actual.Domingo,
|
||
|
|
Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Eliminado"
|
||
|
|
}, transaction);
|
||
|
|
|
||
|
|
var rowsAffected = await transaction.Connection!.ExecuteAsync(sqlDelete, new { IdPrecio = idPrecio }, transaction);
|
||
|
|
return rowsAffected == 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<bool> DeleteByPublicacionIdAsync(int idPublicacion, int idUsuarioAuditoria, IDbTransaction transaction) // MODIFICADO: Recibe idUsuarioAuditoria
|
||
|
|
{
|
||
|
|
const string selectPrecios = "SELECT * FROM dbo.dist_Precios WHERE Id_Publicacion = @IdPublicacion";
|
||
|
|
var preciosAEliminar = await transaction.Connection!.QueryAsync<Precio>(selectPrecios, new { IdPublicacion = idPublicacion }, transaction);
|
||
|
|
|
||
|
|
const string sqlInsertHistorico = @"
|
||
|
|
INSERT INTO dbo.dist_Precios_H
|
||
|
|
(Id_Precio, Id_Publicacion, VigenciaD, VigenciaH, Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo, Id_Usuario, FechaMod, TipoMod)
|
||
|
|
VALUES (@IdPrecio, @IdPublicacion, @VigenciaD, @VigenciaH, @Lunes, @Martes, @Miercoles, @Jueves, @Viernes, @Sabado, @Domingo, @Id_Usuario, @FechaMod, @TipoMod);";
|
||
|
|
|
||
|
|
foreach (var precio in preciosAEliminar)
|
||
|
|
{
|
||
|
|
await transaction.Connection!.ExecuteAsync(sqlInsertHistorico, new
|
||
|
|
{
|
||
|
|
precio.IdPrecio, precio.IdPublicacion, precio.VigenciaD, precio.VigenciaH,
|
||
|
|
precio.Lunes, precio.Martes, precio.Miercoles, precio.Jueves, precio.Viernes, precio.Sabado, precio.Domingo,
|
||
|
|
Id_Usuario = idUsuarioAuditoria, // MODIFICADO: Usar el idUsuarioAuditoria pasado
|
||
|
|
FechaMod = DateTime.Now, TipoMod = "Eliminado (Cascada)"
|
||
|
|
}, transaction);
|
||
|
|
}
|
||
|
|
|
||
|
|
const string sql = "DELETE FROM dbo.dist_Precios WHERE Id_Publicacion = @IdPublicacion";
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var rowsAffected = await transaction.Connection!.ExecuteAsync(sql, new { IdPublicacion = idPublicacion }, transaction: transaction);
|
||
|
|
// No necesitamos devolver rowsAffected >= 0 si la lógica del servicio ya valida si debe haber registros
|
||
|
|
return true; // Indica que la operación de borrado (incluyendo 0 filas) se intentó
|
||
|
|
}
|
||
|
|
catch (System.Exception ex)
|
||
|
|
{
|
||
|
|
_logger.LogError(ex, "Error al eliminar precios por IdPublicacion: {IdPublicacion}", idPublicacion);
|
||
|
|
throw;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|