Implementación AnomalIA - Fix de dropdowns y permisos.
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 5m17s
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 5m17s
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using GestionIntegral.Api.Dtos.Anomalia;
|
||||
using GestionIntegral.Api.Services.Anomalia;
|
||||
|
||||
namespace GestionIntegral.Api.Controllers.Anomalia
|
||||
{
|
||||
[Route("api/alertas")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class AlertasController : ControllerBase
|
||||
{
|
||||
private readonly IAlertaService _alertaService;
|
||||
|
||||
public AlertasController(IAlertaService alertaService)
|
||||
{
|
||||
_alertaService = alertaService;
|
||||
}
|
||||
|
||||
// GET: api/alertas
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(IEnumerable<AlertaGenericaDto>), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetAlertasNoLeidas()
|
||||
{
|
||||
var alertas = await _alertaService.ObtenerAlertasNoLeidasAsync();
|
||||
return Ok(alertas);
|
||||
}
|
||||
|
||||
// POST: api/alertas/{idAlerta}/marcar-leida
|
||||
[HttpPost("{idAlerta:int}/marcar-leida")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> MarcarComoLeida(int idAlerta)
|
||||
{
|
||||
var (exito, error) = await _alertaService.MarcarComoLeidaAsync(idAlerta);
|
||||
if (!exito)
|
||||
{
|
||||
return NotFound(new { message = error });
|
||||
}
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
// POST: api/alertas/marcar-grupo-leido
|
||||
[HttpPost("marcar-grupo-leido")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> MarcarGrupoLeido([FromBody] MarcarGrupoLeidoRequestDto request)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
var (exito, error) = await _alertaService.MarcarGrupoComoLeidoAsync(request.TipoAlerta, request.IdEntidad);
|
||||
if (!exito)
|
||||
{
|
||||
return BadRequest(new { message = error });
|
||||
}
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
|
||||
// DTO para el cuerpo del request de marcar grupo
|
||||
public class MarcarGrupoLeidoRequestDto
|
||||
{
|
||||
[System.ComponentModel.DataAnnotations.Required]
|
||||
public string TipoAlerta { get; set; } = string.Empty;
|
||||
|
||||
[System.ComponentModel.DataAnnotations.Required]
|
||||
public int IdEntidad { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -50,10 +50,19 @@ namespace GestionIntegral.Api.Controllers.Distribucion
|
||||
public async Task<IActionResult> GetAllCanillas([FromQuery] string? nomApe, [FromQuery] int? legajo, [FromQuery] bool? esAccionista, [FromQuery] bool? soloActivos = true)
|
||||
{
|
||||
if (!TienePermiso(PermisoVer)) return Forbid();
|
||||
var canillitas = await _canillaService.ObtenerTodosAsync(nomApe, legajo, soloActivos, esAccionista); // <<-- Pasa el parámetro
|
||||
var canillitas = await _canillaService.ObtenerTodosAsync(nomApe, legajo, soloActivos, esAccionista);
|
||||
return Ok(canillitas);
|
||||
}
|
||||
|
||||
[HttpGet("dropdown")]
|
||||
[ProducesResponseType(typeof(IEnumerable<CanillaDropdownDto>), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetAllDropdownCanillas([FromQuery] bool? esAccionista, [FromQuery] bool? soloActivos = true)
|
||||
{
|
||||
var canillitas = await _canillaService.ObtenerTodosDropdownAsync(esAccionista, soloActivos);
|
||||
return Ok(canillitas);
|
||||
}
|
||||
|
||||
|
||||
// GET: api/canillas/{id}
|
||||
[HttpGet("{id:int}", Name = "GetCanillaById")]
|
||||
[ProducesResponseType(typeof(CanillaDto), StatusCodes.Status200OK)]
|
||||
|
||||
@@ -64,6 +64,23 @@ namespace GestionIntegral.Api.Controllers.Distribucion
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("dropdown")]
|
||||
[ProducesResponseType(typeof(IEnumerable<OtroDestinoDropdownDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<IActionResult> GetAllOtrosDestinosDropdown()
|
||||
{
|
||||
try
|
||||
{
|
||||
var destinos = await _otroDestinoService.ObtenerTodosDropdownAsync();
|
||||
return Ok(destinos);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener Otros Destinos para dropdown.");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al obtener la lista de destinos.");
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/otrosdestinos/{id}
|
||||
[HttpGet("{id:int}", Name = "GetOtroDestinoById")]
|
||||
[ProducesResponseType(typeof(OtroDestinoDto), StatusCodes.Status200OK)]
|
||||
|
||||
@@ -67,6 +67,23 @@ namespace GestionIntegral.Api.Controllers.Impresion
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/estadosbobina/dropdown
|
||||
[HttpGet("dropdown")]
|
||||
[ProducesResponseType(typeof(IEnumerable<EstadoBobinaDto>), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetAllDropdownEstadosBobina()
|
||||
{
|
||||
try
|
||||
{
|
||||
var estados = await _estadoBobinaService.ObtenerTodosDropdownAsync();
|
||||
return Ok(estados);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener todos los Estados de Bobina.");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al obtener los estados de bobina.");
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/estadosbobina/{id}
|
||||
[HttpGet("{id:int}", Name = "GetEstadoBobinaById")]
|
||||
[ProducesResponseType(typeof(EstadoBobinaDto), StatusCodes.Status200OK)]
|
||||
|
||||
@@ -62,6 +62,25 @@ namespace GestionIntegral.Api.Controllers.Impresion
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/tiposbobina/dropdown
|
||||
[HttpGet("dropdown")]
|
||||
[ProducesResponseType(typeof(IEnumerable<TipoBobinaDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<IActionResult> GetAllTiposBobina()
|
||||
{
|
||||
try
|
||||
{
|
||||
var tiposBobina = await _tipoBobinaService.ObtenerTodosDropdownAsync();
|
||||
return Ok(tiposBobina);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener todos los Tipos de Bobina.");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al obtener los tipos de bobina.");
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/tiposbobina/{id}
|
||||
// Permiso: IB006 (Ver Tipos Bobinas)
|
||||
[HttpGet("{id:int}", Name = "GetTipoBobinaById")]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Dapper;
|
||||
using GestionIntegral.Api.Dtos.Distribucion;
|
||||
using GestionIntegral.Api.Models.Distribucion;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System; // Para Exception
|
||||
@@ -25,7 +26,7 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
string? nomApeFilter,
|
||||
int? legajoFilter,
|
||||
bool? esAccionista,
|
||||
bool? soloActivos) // <<-- Parámetro aquí
|
||||
bool? soloActivos)
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
var sqlBuilder = new System.Text.StringBuilder(@"
|
||||
@@ -73,6 +74,37 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<CanillaDropdownDto>> GetAllDropdownAsync(bool? esAccionista, bool? soloActivos)
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
var sqlBuilder = new System.Text.StringBuilder(@"
|
||||
SELECT c.Id_Canilla AS IdCanilla, c.Legajo, c.NomApe
|
||||
FROM dbo.dist_dtCanillas c
|
||||
WHERE 1=1 ");
|
||||
|
||||
var parameters = new DynamicParameters();
|
||||
|
||||
if (soloActivos.HasValue)
|
||||
{
|
||||
sqlBuilder.Append(" AND c.Baja = @BajaStatus ");
|
||||
parameters.Add("BajaStatus", !soloActivos.Value); // Si soloActivos es true, Baja debe ser false
|
||||
}
|
||||
|
||||
if (esAccionista.HasValue)
|
||||
{
|
||||
sqlBuilder.Append(" AND c.Accionista = @EsAccionista ");
|
||||
parameters.Add("EsAccionista", esAccionista.Value); // true para accionistas, false para no accionistas (canillitas)
|
||||
}
|
||||
|
||||
sqlBuilder.Append(" ORDER BY c.NomApe;");
|
||||
|
||||
var result = await connection.QueryAsync<CanillaDropdownDto>(
|
||||
sqlBuilder.ToString(),
|
||||
parameters
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<(Canilla? Canilla, string? NombreZona, string? NombreEmpresa)> GetByIdAsync(int id)
|
||||
{
|
||||
const string sql = @"
|
||||
|
||||
@@ -2,12 +2,14 @@ using GestionIntegral.Api.Models.Distribucion;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Data;
|
||||
using GestionIntegral.Api.Dtos.Distribucion;
|
||||
|
||||
namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
{
|
||||
public interface ICanillaRepository
|
||||
{
|
||||
Task<IEnumerable<(Canilla Canilla, string? NombreZona, string? NombreEmpresa)>> GetAllAsync(string? nomApeFilter, int? legajoFilter, bool? soloActivos, bool? esAccionista);
|
||||
Task<IEnumerable<CanillaDropdownDto>> GetAllDropdownAsync(bool? esAccionista, bool? soloActivos);
|
||||
Task<(Canilla? Canilla, string? NombreZona, string? NombreEmpresa)> GetByIdAsync(int id);
|
||||
Task<Canilla?> GetByIdSimpleAsync(int id); // Para obtener solo la entidad Canilla
|
||||
Task<Canilla?> CreateAsync(Canilla nuevoCanilla, int idUsuario, IDbTransaction transaction);
|
||||
|
||||
@@ -2,12 +2,14 @@ using GestionIntegral.Api.Models.Distribucion;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Data;
|
||||
using GestionIntegral.Api.Dtos.Distribucion;
|
||||
|
||||
namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
{
|
||||
public interface IOtroDestinoRepository
|
||||
{
|
||||
Task<IEnumerable<OtroDestino>> GetAllAsync(string? nombreFilter);
|
||||
Task<IEnumerable<OtroDestinoDropdownDto>> GetAllDropdownAsync();
|
||||
Task<OtroDestino?> GetByIdAsync(int id);
|
||||
Task<OtroDestino?> CreateAsync(OtroDestino nuevoDestino, int idUsuario, IDbTransaction transaction);
|
||||
Task<bool> UpdateAsync(OtroDestino destinoAActualizar, int idUsuario, IDbTransaction transaction);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Dapper;
|
||||
using GestionIntegral.Api.Dtos.Distribucion;
|
||||
using GestionIntegral.Api.Models.Distribucion;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.Generic;
|
||||
@@ -44,6 +45,21 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<OtroDestinoDropdownDto>> GetAllDropdownAsync()
|
||||
{
|
||||
const string sql = "SELECT Id_Destino AS IdDestino, Nombre FROM dbo.dist_dtOtrosDestinos ORDER BY Nombre;";
|
||||
try
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QueryAsync<OtroDestinoDropdownDto>(sql);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener Otros Destinos para dropdown.");
|
||||
return Enumerable.Empty<OtroDestinoDropdownDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<OtroDestino?> GetByIdAsync(int id)
|
||||
{
|
||||
const string sql = "SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Dapper;
|
||||
using GestionIntegral.Api.Data.Repositories.Impresion;
|
||||
using GestionIntegral.Api.Dtos.Impresion;
|
||||
using GestionIntegral.Api.Models.Impresion;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.Generic;
|
||||
@@ -45,6 +46,25 @@ namespace GestionIntegral.Api.Data.Repositories.Impresion
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<EstadoBobinaDropdownDto>> GetAllDropdownAsync()
|
||||
{
|
||||
var sqlBuilder = new StringBuilder("SELECT Id_EstadoBobina AS IdEstadoBobina, Denominacion FROM dbo.bob_dtEstadosBobinas WHERE 1=1");
|
||||
var parameters = new DynamicParameters();
|
||||
|
||||
sqlBuilder.Append(" ORDER BY Denominacion;");
|
||||
|
||||
try
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QueryAsync<EstadoBobinaDropdownDto>(sqlBuilder.ToString(), parameters);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener todos los Estados de Bobina.");
|
||||
return Enumerable.Empty<EstadoBobinaDropdownDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<EstadoBobina?> GetByIdAsync(int id)
|
||||
{
|
||||
const string sql = "SELECT Id_EstadoBobina AS IdEstadoBobina, Denominacion, Obs FROM dbo.bob_dtEstadosBobinas WHERE Id_EstadoBobina = @Id";
|
||||
|
||||
@@ -2,12 +2,14 @@ using GestionIntegral.Api.Models.Impresion;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Data;
|
||||
using GestionIntegral.Api.Dtos.Impresion;
|
||||
|
||||
namespace GestionIntegral.Api.Data.Repositories.Impresion
|
||||
{
|
||||
public interface IEstadoBobinaRepository
|
||||
{
|
||||
Task<IEnumerable<EstadoBobina>> GetAllAsync(string? denominacionFilter);
|
||||
Task<IEnumerable<EstadoBobinaDropdownDto>> GetAllDropdownAsync();
|
||||
Task<EstadoBobina?> GetByIdAsync(int id);
|
||||
Task<EstadoBobina?> CreateAsync(EstadoBobina nuevoEstadoBobina, int idUsuario, IDbTransaction transaction);
|
||||
Task<bool> UpdateAsync(EstadoBobina estadoBobinaAActualizar, int idUsuario, IDbTransaction transaction);
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace GestionIntegral.Api.Data.Repositories.Impresion
|
||||
public interface ITipoBobinaRepository
|
||||
{
|
||||
Task<IEnumerable<TipoBobina>> GetAllAsync(string? denominacionFilter);
|
||||
Task<IEnumerable<TipoBobina>> GetAllDropdownAsync();
|
||||
Task<TipoBobina?> GetByIdAsync(int id);
|
||||
Task<TipoBobina?> CreateAsync(TipoBobina nuevoTipoBobina, int idUsuario, IDbTransaction transaction);
|
||||
Task<bool> UpdateAsync(TipoBobina tipoBobinaAActualizar, int idUsuario, IDbTransaction transaction);
|
||||
|
||||
@@ -44,6 +44,24 @@ namespace GestionIntegral.Api.Data.Repositories.Impresion
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TipoBobina>> GetAllDropdownAsync()
|
||||
{
|
||||
var sqlBuilder = new StringBuilder("SELECT Id_TipoBobina AS IdTipoBobina, Denominacion FROM dbo.bob_dtBobinas WHERE 1=1");
|
||||
|
||||
sqlBuilder.Append(" ORDER BY Denominacion;");
|
||||
|
||||
try
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QueryAsync<TipoBobina>(sqlBuilder.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener todos los Tipos de Bobina.");
|
||||
return Enumerable.Empty<TipoBobina>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<TipoBobina?> GetByIdAsync(int id)
|
||||
{
|
||||
const string sql = "SELECT Id_TipoBobina AS IdTipoBobina, Denominacion FROM dbo.bob_dtBobinas WHERE Id_TipoBobina = @Id";
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace GestionIntegral.Api.Dtos.Anomalia
|
||||
{
|
||||
public class AlertaGenericaDto
|
||||
{
|
||||
public int IdAlerta { get; set; }
|
||||
public DateTime FechaDeteccion { get; set; }
|
||||
public string TipoAlerta { get; set; } = string.Empty;
|
||||
public string Entidad { get; set; } = string.Empty;
|
||||
public int IdEntidad { get; set; }
|
||||
public string Mensaje { get; set; } = string.Empty;
|
||||
public DateTime FechaAnomalia { get; set; }
|
||||
public bool Leida { get; set; }
|
||||
|
||||
// Propiedades que pueden ser nulas porque no aplican a todos los tipos de alerta
|
||||
public int? CantidadEnviada { get; set; }
|
||||
public int? CantidadDevuelta { get; set; }
|
||||
public decimal? PorcentajeDevolucion { get; set; }
|
||||
|
||||
// Podríamos añadir más propiedades opcionales en el futuro
|
||||
// public string? NombreEntidad { get; set; } // Por ejemplo, el nombre del canillita
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
{
|
||||
public class CanillaDropdownDto
|
||||
{
|
||||
public int IdCanilla { get; set; }
|
||||
public int? Legajo { get; set; }
|
||||
public string NomApe { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
{
|
||||
public class OtroDestinoDropdownDto
|
||||
{
|
||||
public int IdDestino { get; set; }
|
||||
public string Nombre { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
{
|
||||
public int IdPublicacion { get; set; }
|
||||
public string Nombre { get; set; } = string.Empty;
|
||||
public bool Habilitada { get; set; } // Simplificamos a bool, el backend manejará el default si es null
|
||||
public string NombreEmpresa { get; set; } = string.Empty;
|
||||
public bool Habilitada { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace GestionIntegral.Api.Dtos.Impresion
|
||||
{
|
||||
public class EstadoBobinaDropdownDto
|
||||
{
|
||||
public int IdEstadoBobina { get; set; }
|
||||
public string Denominacion { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ using GestionIntegral.Api.Data.Repositories.Reportes;
|
||||
using GestionIntegral.Api.Services.Reportes;
|
||||
using GestionIntegral.Api.Services.Pdf;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using GestionIntegral.Api.Services.Anomalia;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -96,6 +97,8 @@ builder.Services.AddScoped<IReportesRepository, ReportesRepository>();
|
||||
builder.Services.AddScoped<IReportesService, ReportesService>();
|
||||
// QuestPDF
|
||||
builder.Services.AddScoped<IQuestPdfGenerator, QuestPdfGenerator>();
|
||||
// Servicio de Alertas
|
||||
builder.Services.AddScoped<IAlertaService, AlertaService>();
|
||||
|
||||
// --- SERVICIO DE HEALTH CHECKS ---
|
||||
// Añadimos una comprobación específica para SQL Server.
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
using GestionIntegral.Api.Data;
|
||||
using GestionIntegral.Api.Dtos.Anomalia;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace GestionIntegral.Api.Services.Anomalia
|
||||
{
|
||||
public class AlertaService : IAlertaService
|
||||
{
|
||||
private readonly DbConnectionFactory _dbConnectionFactory;
|
||||
private readonly ILogger<AlertaService> _logger;
|
||||
|
||||
public AlertaService(DbConnectionFactory dbConnectionFactory, ILogger<AlertaService> logger)
|
||||
{
|
||||
_dbConnectionFactory = dbConnectionFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<AlertaGenericaDto>> ObtenerAlertasNoLeidasAsync()
|
||||
{
|
||||
// Apunta a la nueva tabla genérica 'Sistema_Alertas'
|
||||
var query = "SELECT * FROM Sistema_Alertas WHERE Leida = 0 ORDER BY FechaDeteccion DESC";
|
||||
try
|
||||
{
|
||||
using (var connection = _dbConnectionFactory.CreateConnection())
|
||||
{
|
||||
var alertas = await connection.QueryAsync<AlertaGenericaDto>(query);
|
||||
return alertas ?? Enumerable.Empty<AlertaGenericaDto>();
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener las alertas no leídas desde Sistema_Alertas.");
|
||||
return Enumerable.Empty<AlertaGenericaDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<(bool Exito, string? Error)> MarcarComoLeidaAsync(int idAlerta)
|
||||
{
|
||||
var query = "UPDATE Sistema_Alertas SET Leida = 1 WHERE IdAlerta = @IdAlerta";
|
||||
try
|
||||
{
|
||||
using (var connection = _dbConnectionFactory.CreateConnection())
|
||||
{
|
||||
var result = await connection.ExecuteAsync(query, new { IdAlerta = idAlerta });
|
||||
if (result > 0)
|
||||
{
|
||||
return (true, null);
|
||||
}
|
||||
return (false, "La alerta no fue encontrada o ya estaba marcada.");
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al marcar la alerta {IdAlerta} como leída.", idAlerta);
|
||||
return (false, "Error interno del servidor.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<(bool Exito, string? Error)> MarcarGrupoComoLeidoAsync(string tipoAlerta, int idEntidad)
|
||||
{
|
||||
var query = "UPDATE Sistema_Alertas SET Leida = 1 WHERE TipoAlerta = @TipoAlerta AND IdEntidad = @IdEntidad AND Leida = 0";
|
||||
try
|
||||
{
|
||||
using (var connection = _dbConnectionFactory.CreateConnection())
|
||||
{
|
||||
var result = await connection.ExecuteAsync(query, new { TipoAlerta = tipoAlerta, IdEntidad = idEntidad });
|
||||
// No es un error si no se actualizan filas (puede que no hubiera ninguna para ese grupo)
|
||||
_logger.LogInformation("Marcadas como leídas {Count} alertas para Tipo: {Tipo}, EntidadID: {IdEntidad}", result, tipoAlerta, idEntidad);
|
||||
return (true, null);
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al marcar grupo de alertas como leídas. Tipo: {Tipo}, EntidadID: {IdEntidad}", tipoAlerta, idEntidad);
|
||||
return (false, "Error interno del servidor.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using GestionIntegral.Api.Dtos.Anomalia;
|
||||
|
||||
namespace GestionIntegral.Api.Services.Anomalia
|
||||
{
|
||||
public interface IAlertaService
|
||||
{
|
||||
/// <summary>
|
||||
/// Obtiene todas las alertas que no han sido marcadas como leídas.
|
||||
/// </summary>
|
||||
/// <returns>Una colección de DTOs de alertas genéricas.</returns>
|
||||
Task<IEnumerable<AlertaGenericaDto>> ObtenerAlertasNoLeidasAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Marca una alerta específica como leída.
|
||||
/// </summary>
|
||||
/// <param name="idAlerta">El ID de la alerta a marcar.</param>
|
||||
/// <returns>Una tupla indicando si la operación fue exitosa y un mensaje de error si falló.</returns>
|
||||
Task<(bool Exito, string? Error)> MarcarComoLeidaAsync(int idAlerta);
|
||||
|
||||
/// <summary>
|
||||
/// Marca como leídas todas las alertas de un mismo tipo y para una misma entidad.
|
||||
/// (Ej: todas las alertas de "DevolucionAnomala" para el Canillita ID 45).
|
||||
/// </summary>
|
||||
/// <param name="tipoAlerta">El tipo de alerta a marcar (ej. "DevolucionAnomala").</param>
|
||||
/// <param name="idEntidad">El ID de la entidad afectada (ej. el IdCanilla).</param>
|
||||
/// <returns>Una tupla indicando si la operación fue exitosa y un mensaje de error si falló.</returns>
|
||||
Task<(bool Exito, string? Error)> MarcarGrupoComoLeidoAsync(string tipoAlerta, int idEntidad);
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,6 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// CORREGIDO: MapToDto ahora acepta una tupla con tipos anulables
|
||||
private CanillaDto? MapToDto((Canilla? Canilla, string? NombreZona, string? NombreEmpresa) data)
|
||||
{
|
||||
if (data.Canilla == null) return null;
|
||||
@@ -62,10 +61,14 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
return data.Select(MapToDto).Where(dto => dto != null).Select(dto => dto!);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<CanillaDropdownDto>> ObtenerTodosDropdownAsync(bool? esAccionista, bool? soloActivos)
|
||||
{
|
||||
return await _canillaRepository.GetAllDropdownAsync(esAccionista, soloActivos) ?? Enumerable.Empty<CanillaDropdownDto>();
|
||||
}
|
||||
|
||||
public async Task<CanillaDto?> ObtenerPorIdAsync(int id)
|
||||
{
|
||||
var data = await _canillaRepository.GetByIdAsync(id);
|
||||
// MapToDto ahora devuelve CanillaDto? así que esto es correcto
|
||||
return MapToDto(data);
|
||||
}
|
||||
|
||||
@@ -89,7 +92,6 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
}
|
||||
}
|
||||
|
||||
// CORREGIDO: Usar directamente el valor booleano
|
||||
if (createDto.Accionista == true && createDto.Empresa != 0)
|
||||
{
|
||||
return (null, "Un canillita accionista no debe tener una empresa asignada (Empresa debe ser 0).");
|
||||
@@ -287,6 +289,6 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
FechaMod = h.Historial.FechaMod,
|
||||
TipoMod = h.Historial.TipoMod
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
public interface ICanillaService
|
||||
{
|
||||
Task<IEnumerable<CanillaDto>> ObtenerTodosAsync(string? nomApeFilter, int? legajoFilter, bool? esAccionista, bool? soloActivos);
|
||||
Task<IEnumerable<CanillaDropdownDto>> ObtenerTodosDropdownAsync(bool? esAccionista, bool? soloActivos);
|
||||
Task<CanillaDto?> ObtenerPorIdAsync(int id);
|
||||
Task<(CanillaDto? Canilla, string? Error)> CrearAsync(CreateCanillaDto createDto, int idUsuario);
|
||||
Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdateCanillaDto updateDto, int idUsuario);
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
public interface IOtroDestinoService
|
||||
{
|
||||
Task<IEnumerable<OtroDestinoDto>> ObtenerTodosAsync(string? nombreFilter);
|
||||
Task<IEnumerable<OtroDestinoDropdownDto>> ObtenerTodosDropdownAsync();
|
||||
Task<OtroDestinoDto?> ObtenerPorIdAsync(int id);
|
||||
Task<(OtroDestinoDto? Destino, string? Error)> CrearAsync(CreateOtroDestinoDto createDto, int idUsuario);
|
||||
Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdateOtroDestinoDto updateDto, int idUsuario);
|
||||
|
||||
@@ -37,6 +37,11 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
return destinos.Select(MapToDto);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<OtroDestinoDropdownDto>> ObtenerTodosDropdownAsync()
|
||||
{
|
||||
return await _otroDestinoRepository.GetAllDropdownAsync();
|
||||
}
|
||||
|
||||
public async Task<OtroDestinoDto?> ObtenerPorIdAsync(int id)
|
||||
{
|
||||
var destino = await _otroDestinoRepository.GetByIdAsync(id);
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
{
|
||||
IdPublicacion = d.Publicacion!.IdPublicacion, // Usar ! si estás seguro que no es null después del Where
|
||||
Nombre = d.Publicacion!.Nombre,
|
||||
NombreEmpresa = d.NombreEmpresa ?? "Empresa Desconocida",
|
||||
Habilitada = d.Publicacion!.Habilitada ?? true // Si necesitas filtrar por esto
|
||||
})
|
||||
.OrderBy(p => p.Nombre)
|
||||
|
||||
@@ -37,6 +37,12 @@ namespace GestionIntegral.Api.Services.Impresion
|
||||
return estadosBobina.Select(MapToDto);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<EstadoBobinaDropdownDto>> ObtenerTodosDropdownAsync()
|
||||
{
|
||||
var estadosBobina = await _estadoBobinaRepository.GetAllDropdownAsync();
|
||||
return estadosBobina;
|
||||
}
|
||||
|
||||
public async Task<EstadoBobinaDto?> ObtenerPorIdAsync(int id)
|
||||
{
|
||||
var estadoBobina = await _estadoBobinaRepository.GetByIdAsync(id);
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace GestionIntegral.Api.Services.Impresion
|
||||
public interface IEstadoBobinaService
|
||||
{
|
||||
Task<IEnumerable<EstadoBobinaDto>> ObtenerTodosAsync(string? denominacionFilter);
|
||||
Task<IEnumerable<EstadoBobinaDropdownDto>> ObtenerTodosDropdownAsync();
|
||||
Task<EstadoBobinaDto?> ObtenerPorIdAsync(int id);
|
||||
Task<(EstadoBobinaDto? EstadoBobina, string? Error)> CrearAsync(CreateEstadoBobinaDto createDto, int idUsuario);
|
||||
Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdateEstadoBobinaDto updateDto, int idUsuario);
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace GestionIntegral.Api.Services.Impresion
|
||||
public interface ITipoBobinaService
|
||||
{
|
||||
Task<IEnumerable<TipoBobinaDto>> ObtenerTodosAsync(string? denominacionFilter);
|
||||
Task<IEnumerable<TipoBobinaDto>> ObtenerTodosDropdownAsync();
|
||||
Task<TipoBobinaDto?> ObtenerPorIdAsync(int id);
|
||||
Task<(TipoBobinaDto? TipoBobina, string? Error)> CrearAsync(CreateTipoBobinaDto createDto, int idUsuario);
|
||||
Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdateTipoBobinaDto updateDto, int idUsuario);
|
||||
|
||||
@@ -36,6 +36,12 @@ namespace GestionIntegral.Api.Services.Impresion
|
||||
return tiposBobina.Select(MapToDto);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TipoBobinaDto>> ObtenerTodosDropdownAsync()
|
||||
{
|
||||
var tiposBobina = await _tipoBobinaRepository.GetAllDropdownAsync();
|
||||
return tiposBobina.Select(MapToDto);
|
||||
}
|
||||
|
||||
public async Task<TipoBobinaDto?> ObtenerPorIdAsync(int id)
|
||||
{
|
||||
var tipoBobina = await _tipoBobinaRepository.GetByIdAsync(id);
|
||||
|
||||
Reference in New Issue
Block a user