diff --git a/Backend/GestionIntegral.Api/Controllers/Distribucion/PublicacionesController.cs b/Backend/GestionIntegral.Api/Controllers/Distribucion/PublicacionesController.cs index a44e593..ba6de5b 100644 --- a/Backend/GestionIntegral.Api/Controllers/Distribucion/PublicacionesController.cs +++ b/Backend/GestionIntegral.Api/Controllers/Distribucion/PublicacionesController.cs @@ -38,6 +38,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion return null; } + // GET: api/publicaciones [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] @@ -48,6 +49,26 @@ namespace GestionIntegral.Api.Controllers.Distribucion return Ok(publicaciones); } + // GET: api/publicaciones/dropdown + [HttpGet("dropdown")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + // No se verifica permiso DP001, solo requiere autenticación general ([Authorize] del controlador) + public async Task GetPublicacionesForDropdown([FromQuery] bool soloHabilitadas = true) + { + try + { + var publicaciones = await _publicacionService.ObtenerParaDropdownAsync(soloHabilitadas); + return Ok(publicaciones); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error al obtener publicaciones para dropdown."); + return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al obtener publicaciones para selección."); + } + } + + // GET: api/publicaciones/{id} [HttpGet("{id:int}", Name = "GetPublicacionById")] [ProducesResponseType(typeof(PublicacionDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] @@ -60,6 +81,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion return Ok(publicacion); } + // POST: api/publicaciones [HttpPost] [ProducesResponseType(typeof(PublicacionDto), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] @@ -77,6 +99,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion return CreatedAtRoute("GetPublicacionById", new { id = dto.IdPublicacion }, dto); } + // PUT: api/publicaciones/{id} [HttpPut("{id:int}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] @@ -98,6 +121,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion return NoContent(); } + // DELETE: api/publicaciones/{id} [HttpDelete("{id:int}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] @@ -118,7 +142,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion return NoContent(); } - // Endpoint para obtener las configuraciones de días para una publicación + // Endpoint para obtener la configuración de días de publicación para una publicación específica [HttpGet("{idPublicacion:int}/dias-semana")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] diff --git a/Backend/GestionIntegral.Api/Controllers/Impresion/PlantasController.cs b/Backend/GestionIntegral.Api/Controllers/Impresion/PlantasController.cs index b2941d4..5294e8e 100644 --- a/Backend/GestionIntegral.Api/Controllers/Impresion/PlantasController.cs +++ b/Backend/GestionIntegral.Api/Controllers/Impresion/PlantasController.cs @@ -71,6 +71,25 @@ namespace GestionIntegral.Api.Controllers.Impresion } } + // GET: api/plantas/dropdown + [HttpGet("dropdown")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + // NO chequeo TienePermiso("IP001")(requiere autenticación) + public async Task GetPlantasForDropdown() + { + try + { + var plantas = await _plantaService.ObtenerParaDropdownAsync(); + return Ok(plantas); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error al obtener plantas para dropdown."); + return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al obtener plantas para selección."); + } + } + // GET: api/plantas/{id} // Permiso: IP001 (Ver Plantas) [HttpGet("{id:int}", Name = "GetPlantaById")] diff --git a/Backend/GestionIntegral.Api/Models/Dtos/Distribucion/PublicacioDropdownDto.cs b/Backend/GestionIntegral.Api/Models/Dtos/Distribucion/PublicacioDropdownDto.cs new file mode 100644 index 0000000..258209f --- /dev/null +++ b/Backend/GestionIntegral.Api/Models/Dtos/Distribucion/PublicacioDropdownDto.cs @@ -0,0 +1,9 @@ +namespace GestionIntegral.Api.Dtos.Distribucion +{ + public class PublicacionDropdownDto + { + 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 + } +} \ No newline at end of file diff --git a/Backend/GestionIntegral.Api/Models/Dtos/Impresion/PlantaDropdownDto.cs b/Backend/GestionIntegral.Api/Models/Dtos/Impresion/PlantaDropdownDto.cs new file mode 100644 index 0000000..d759ee0 --- /dev/null +++ b/Backend/GestionIntegral.Api/Models/Dtos/Impresion/PlantaDropdownDto.cs @@ -0,0 +1,8 @@ +namespace GestionIntegral.Api.Dtos.Impresion +{ + public class PlantaDropdownDto + { + public int IdPlanta { get; set; } + public required string Nombre { get; set; } + } +} \ No newline at end of file diff --git a/Backend/GestionIntegral.Api/Services/Distribucion/IPublicacionService.cs b/Backend/GestionIntegral.Api/Services/Distribucion/IPublicacionService.cs index 30971d7..4fee753 100644 --- a/Backend/GestionIntegral.Api/Services/Distribucion/IPublicacionService.cs +++ b/Backend/GestionIntegral.Api/Services/Distribucion/IPublicacionService.cs @@ -14,5 +14,6 @@ namespace GestionIntegral.Api.Services.Distribucion Task> ObtenerConfiguracionDiasAsync(int idPublicacion); Task> ObtenerPublicacionesPorDiaSemanaAsync(byte diaSemana); // Devolvemos el DTO completo Task<(bool Exito, string? Error)> ActualizarConfiguracionDiasAsync(int idPublicacion, UpdatePublicacionDiasSemanaRequestDto requestDto, int idUsuario); + Task> ObtenerParaDropdownAsync(bool soloHabilitadas = true); } } \ No newline at end of file diff --git a/Backend/GestionIntegral.Api/Services/Distribucion/PublicacionService.cs b/Backend/GestionIntegral.Api/Services/Distribucion/PublicacionService.cs index 8789e29..6f088cd 100644 --- a/Backend/GestionIntegral.Api/Services/Distribucion/PublicacionService.cs +++ b/Backend/GestionIntegral.Api/Services/Distribucion/PublicacionService.cs @@ -75,6 +75,22 @@ namespace GestionIntegral.Api.Services.Distribucion return MapToDto(data); } + public async Task> ObtenerParaDropdownAsync(bool soloHabilitadas = true) + { + var data = await _publicacionRepository.GetAllAsync(null, null, soloHabilitadas ? (bool?)true : null); + + return data + .Where(p => p.Publicacion != null) // Asegurar que la publicación no sea null + .Select(d => new PublicacionDropdownDto + { + IdPublicacion = d.Publicacion!.IdPublicacion, // Usar ! si estás seguro que no es null después del Where + Nombre = d.Publicacion!.Nombre, + Habilitada = d.Publicacion!.Habilitada ?? true // Si necesitas filtrar por esto + }) + .OrderBy(p => p.Nombre) + .ToList(); // O ToListAsync si el método del repo es async y devuelve IQueryable + } + public async Task<(PublicacionDto? Publicacion, string? Error)> CrearAsync(CreatePublicacionDto createDto, int idUsuario) { if (await _empresaRepository.GetByIdAsync(createDto.IdEmpresa) == null) diff --git a/Backend/GestionIntegral.Api/Services/Impresion/IPlantaService.cs b/Backend/GestionIntegral.Api/Services/Impresion/IPlantaService.cs index 6528513..fe2d4e6 100644 --- a/Backend/GestionIntegral.Api/Services/Impresion/IPlantaService.cs +++ b/Backend/GestionIntegral.Api/Services/Impresion/IPlantaService.cs @@ -11,5 +11,6 @@ namespace GestionIntegral.Api.Services.Impresion Task<(PlantaDto? Planta, string? Error)> CrearAsync(CreatePlantaDto createDto, int idUsuario); Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdatePlantaDto updateDto, int idUsuario); Task<(bool Exito, string? Error)> EliminarAsync(int id, int idUsuario); + Task> ObtenerParaDropdownAsync(); } } \ No newline at end of file diff --git a/Backend/GestionIntegral.Api/Services/Impresion/PlantaService.cs b/Backend/GestionIntegral.Api/Services/Impresion/PlantaService.cs index 294cc68..e9359e8 100644 --- a/Backend/GestionIntegral.Api/Services/Impresion/PlantaService.cs +++ b/Backend/GestionIntegral.Api/Services/Impresion/PlantaService.cs @@ -114,8 +114,8 @@ namespace GestionIntegral.Api.Services.Impresion }; using var connection = _connectionFactory.CreateConnection(); - if (connection is System.Data.Common.DbConnection dbConnection) { await dbConnection.OpenAsync(); } else { connection.Open(); } - using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); + if (connection is System.Data.Common.DbConnection dbConnection) { await dbConnection.OpenAsync(); } else { connection.Open(); } + using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); try { @@ -133,14 +133,14 @@ namespace GestionIntegral.Api.Services.Impresion } catch (KeyNotFoundException knfex) // Captura específica si el repo la lanza { - try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en ActualizarAsync Planta."); } - _logger.LogWarning(knfex, "Intento de actualizar Planta ID: {Id} no encontrada.", id); - return (false, "Planta no encontrada."); + try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en ActualizarAsync Planta."); } + _logger.LogWarning(knfex, "Intento de actualizar Planta ID: {Id} no encontrada.", id); + return (false, "Planta no encontrada."); } catch (Exception ex) { try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en ActualizarAsync Planta."); } - _logger.LogError(ex, "Error en transacción ActualizarAsync para Planta ID: {Id}", id); + _logger.LogError(ex, "Error en transacción ActualizarAsync para Planta ID: {Id}", id); return (false, $"Error interno al actualizar la planta: {ex.Message}"); } } @@ -153,33 +153,42 @@ namespace GestionIntegral.Api.Services.Impresion } using var connection = _connectionFactory.CreateConnection(); - if (connection is System.Data.Common.DbConnection dbConnection) { await dbConnection.OpenAsync(); } else { connection.Open(); } + if (connection is System.Data.Common.DbConnection dbConnection) { await dbConnection.OpenAsync(); } else { connection.Open(); } using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); try { var eliminado = await _plantaRepository.DeleteAsync(id, idUsuario, transaction); - if (!eliminado) - { + if (!eliminado) + { throw new DataException("La operación de eliminación no afectó ninguna fila."); - } + } transaction.Commit(); // <--- CORREGIDO: Commit síncrono _logger.LogInformation("Planta ID {IdPlanta} eliminada exitosamente por Usuario ID {IdUsuario}.", id, idUsuario); return (true, null); } - catch (KeyNotFoundException knfex) // Captura específica si el repo la lanza + catch (KeyNotFoundException knfex) // Captura específica si el repo la lanza { - try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en EliminarAsync Planta."); } - _logger.LogWarning(knfex, "Intento de eliminar Planta ID: {Id} no encontrada.", id); - return (false, "Planta no encontrada."); + try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en EliminarAsync Planta."); } + _logger.LogWarning(knfex, "Intento de eliminar Planta ID: {Id} no encontrada.", id); + return (false, "Planta no encontrada."); } catch (Exception ex) { - try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en EliminarAsync Planta."); } - _logger.LogError(ex, "Error en transacción EliminarAsync para Planta ID: {Id}", id); + try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error adicional durante el rollback en EliminarAsync Planta."); } + _logger.LogError(ex, "Error en transacción EliminarAsync para Planta ID: {Id}", id); return (false, $"Error interno al eliminar la planta: {ex.Message}"); } } + + public async Task> ObtenerParaDropdownAsync() + { + var plantas = await _plantaRepository.GetAllAsync(null, null); + return plantas + .OrderBy(p => p.Nombre) + .Select(p => new PlantaDropdownDto { IdPlanta = p.IdPlanta, Nombre = p.Nombre }) + .ToList(); + } } } \ No newline at end of file diff --git a/Backend/GestionIntegral.Api/obj/Debug/net9.0/GestionIntegral.Api.AssemblyInfo.cs b/Backend/GestionIntegral.Api/obj/Debug/net9.0/GestionIntegral.Api.AssemblyInfo.cs index 66bdd9c..b742cf0 100644 --- a/Backend/GestionIntegral.Api/obj/Debug/net9.0/GestionIntegral.Api.AssemblyInfo.cs +++ b/Backend/GestionIntegral.Api/obj/Debug/net9.0/GestionIntegral.Api.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("GestionIntegral.Api")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99532b03f191d55f42e738a90b97f9f1e0dc1a9c")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+062cc05fd00a484e43f8b4ff022e53ac49670a78")] [assembly: System.Reflection.AssemblyProductAttribute("GestionIntegral.Api")] [assembly: System.Reflection.AssemblyTitleAttribute("GestionIntegral.Api")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Backend/GestionIntegral.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json b/Backend/GestionIntegral.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json index 495d1b5..5beb38e 100644 --- a/Backend/GestionIntegral.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json +++ b/Backend/GestionIntegral.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"C9goqBDGh4B0L1HpPwpJHjfbRNoIuzqnU7zFMHk1LhM=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["V/5slELlkFDzZ8iiVKV8Jt0Ia8AL5AZxPCWo9apx5lQ=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","k3qzLxTWHeeJhAuWKMdta6j24bmJ9BMRMjuFEEVCRu0=","x/sHyso3gy4zVCu3ljpnTYCqu8IGZNRok1JoXiabIP8=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","hUWSz0FL2Jxxt3J4cPvysP9naCA2/Cxeo8sJx8s2hvs="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"C9goqBDGh4B0L1HpPwpJHjfbRNoIuzqnU7zFMHk1LhM=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["V/5slELlkFDzZ8iiVKV8Jt0Ia8AL5AZxPCWo9apx5lQ=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","k3qzLxTWHeeJhAuWKMdta6j24bmJ9BMRMjuFEEVCRu0=","x/sHyso3gy4zVCu3ljpnTYCqu8IGZNRok1JoXiabIP8=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","1I2C2FVhJyFRbvyuGXnropbTYN\u002BqpCoTcHfxWbfWF10="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Backend/GestionIntegral.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json b/Backend/GestionIntegral.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json index 72f6aca..e25e282 100644 --- a/Backend/GestionIntegral.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json +++ b/Backend/GestionIntegral.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"w3MBbMV9Msh0YEq9AW/8s16bzXJ93T9lMVXKPm/r6es=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["V/5slELlkFDzZ8iiVKV8Jt0Ia8AL5AZxPCWo9apx5lQ=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","k3qzLxTWHeeJhAuWKMdta6j24bmJ9BMRMjuFEEVCRu0=","x/sHyso3gy4zVCu3ljpnTYCqu8IGZNRok1JoXiabIP8=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","hUWSz0FL2Jxxt3J4cPvysP9naCA2/Cxeo8sJx8s2hvs="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"w3MBbMV9Msh0YEq9AW/8s16bzXJ93T9lMVXKPm/r6es=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["V/5slELlkFDzZ8iiVKV8Jt0Ia8AL5AZxPCWo9apx5lQ=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","k3qzLxTWHeeJhAuWKMdta6j24bmJ9BMRMjuFEEVCRu0=","x/sHyso3gy4zVCu3ljpnTYCqu8IGZNRok1JoXiabIP8=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","1I2C2FVhJyFRbvyuGXnropbTYN\u002BqpCoTcHfxWbfWF10="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Frontend/src/models/dtos/Distribucion/PublicacionDropdownDto.ts b/Frontend/src/models/dtos/Distribucion/PublicacionDropdownDto.ts new file mode 100644 index 0000000..ed2cf79 --- /dev/null +++ b/Frontend/src/models/dtos/Distribucion/PublicacionDropdownDto.ts @@ -0,0 +1,4 @@ +export interface PublicacionDropdownDto { + idPublicacion: number; + nombre: string; +} \ No newline at end of file diff --git a/Frontend/src/models/dtos/Impresion/PlantaDropdownDto.ts b/Frontend/src/models/dtos/Impresion/PlantaDropdownDto.ts new file mode 100644 index 0000000..0228d39 --- /dev/null +++ b/Frontend/src/models/dtos/Impresion/PlantaDropdownDto.ts @@ -0,0 +1,4 @@ +export interface PlantaDropdownDto { + idPlanta: number; + nombre: string; +} \ No newline at end of file diff --git a/Frontend/src/pages/Contables/GestionarNotasCDPage.tsx b/Frontend/src/pages/Contables/GestionarNotasCDPage.tsx index 43b0696..87ba974 100644 --- a/Frontend/src/pages/Contables/GestionarNotasCDPage.tsx +++ b/Frontend/src/pages/Contables/GestionarNotasCDPage.tsx @@ -51,7 +51,7 @@ const GestionarNotasCDPage: React.FC = () => { const [editingNota, setEditingNota] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedRow, setSelectedRow] = useState(null); @@ -236,7 +236,7 @@ const GestionarNotasCDPage: React.FC = () => { diff --git a/Frontend/src/pages/Contables/GestionarPagosDistribuidorPage.tsx b/Frontend/src/pages/Contables/GestionarPagosDistribuidorPage.tsx index baa4531..66b5a09 100644 --- a/Frontend/src/pages/Contables/GestionarPagosDistribuidorPage.tsx +++ b/Frontend/src/pages/Contables/GestionarPagosDistribuidorPage.tsx @@ -45,7 +45,7 @@ const GestionarPagosDistribuidorPage: React.FC = () => { const [editingPago, setEditingPago] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedRow, setSelectedRow] = useState(null); @@ -205,7 +205,7 @@ const GestionarPagosDistribuidorPage: React.FC = () => { diff --git a/Frontend/src/pages/Contables/GestionarTiposPagoPage.tsx b/Frontend/src/pages/Contables/GestionarTiposPagoPage.tsx index 903c8bb..34bbff1 100644 --- a/Frontend/src/pages/Contables/GestionarTiposPagoPage.tsx +++ b/Frontend/src/pages/Contables/GestionarTiposPagoPage.tsx @@ -126,7 +126,7 @@ const GestionarTiposPagoPage: React.FC = () => { }; const handleChangeRowsPerPage = (event: React.ChangeEvent) => { - setRowsPerPage(parseInt(event.target.value, 10)); + setRowsPerPage(parseInt(event.target.value, 25)); setPage(0); }; @@ -200,7 +200,7 @@ const GestionarTiposPagoPage: React.FC = () => { { } setLoading(true); setError(null); setApiErrorMessage(null); try { - const legajoNum = filtroLegajo ? parseInt(filtroLegajo, 10) : undefined; + const legajoNum = filtroLegajo ? parseInt(filtroLegajo, 25) : undefined; if (filtroLegajo && isNaN(legajoNum!)) { setApiErrorMessage("Legajo debe ser un número."); setCanillitas([]); // Limpiar resultados si el filtro es inválido @@ -194,7 +194,7 @@ const GestionarCanillitasPage: React.FC = () => { diff --git a/Frontend/src/pages/Distribucion/GestionarControlDevolucionesPage.tsx b/Frontend/src/pages/Distribucion/GestionarControlDevolucionesPage.tsx index d40d1fd..4be5e07 100644 --- a/Frontend/src/pages/Distribucion/GestionarControlDevolucionesPage.tsx +++ b/Frontend/src/pages/Distribucion/GestionarControlDevolucionesPage.tsx @@ -39,7 +39,7 @@ const GestionarControlDevolucionesPage: React.FC = () => { const [editingControl, setEditingControl] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedRow, setSelectedRow] = useState(null); @@ -206,7 +206,7 @@ const GestionarControlDevolucionesPage: React.FC = () => { diff --git a/Frontend/src/pages/Distribucion/GestionarDistribuidoresPage.tsx b/Frontend/src/pages/Distribucion/GestionarDistribuidoresPage.tsx index 5e442ec..461dbe7 100644 --- a/Frontend/src/pages/Distribucion/GestionarDistribuidoresPage.tsx +++ b/Frontend/src/pages/Distribucion/GestionarDistribuidoresPage.tsx @@ -30,7 +30,7 @@ const GestionarDistribuidoresPage: React.FC = () => { const [apiErrorMessage, setApiErrorMessage] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedDistribuidorRow, setSelectedDistribuidorRow] = useState(null); @@ -171,7 +171,7 @@ const GestionarDistribuidoresPage: React.FC = () => { diff --git a/Frontend/src/pages/Distribucion/GestionarEmpresasPage.tsx b/Frontend/src/pages/Distribucion/GestionarEmpresasPage.tsx index 6e6df0d..9c60045 100644 --- a/Frontend/src/pages/Distribucion/GestionarEmpresasPage.tsx +++ b/Frontend/src/pages/Distribucion/GestionarEmpresasPage.tsx @@ -30,7 +30,7 @@ const GestionarEmpresasPage: React.FC = () => { const [apiErrorMessage, setApiErrorMessage] = useState(null); // Para errores del modal (Create/Update/Delete) const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [rowsPerPage, setRowsPerPage] = useState(25); // Para el menú contextual de acciones por fila const [anchorEl, setAnchorEl] = useState(null); @@ -227,7 +227,7 @@ const GestionarEmpresasPage: React.FC = () => { {/* Paginación */} { const [editingMovimiento, setEditingMovimiento] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedRow, setSelectedRow] = useState(null); const [selectedIdsParaLiquidar, setSelectedIdsParaLiquidar] = useState>(new Set()); @@ -452,7 +452,7 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { diff --git a/Frontend/src/pages/Distribucion/GestionarEntradasSalidasDistPage.tsx b/Frontend/src/pages/Distribucion/GestionarEntradasSalidasDistPage.tsx index 7ff493c..f309247 100644 --- a/Frontend/src/pages/Distribucion/GestionarEntradasSalidasDistPage.tsx +++ b/Frontend/src/pages/Distribucion/GestionarEntradasSalidasDistPage.tsx @@ -44,7 +44,7 @@ const GestionarEntradasSalidasDistPage: React.FC = () => { const [editingMovimiento, setEditingMovimiento] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedRow, setSelectedRow] = useState(null); @@ -220,7 +220,7 @@ const GestionarEntradasSalidasDistPage: React.FC = () => { diff --git a/Frontend/src/pages/Distribucion/GestionarOtrosDestinosPage.tsx b/Frontend/src/pages/Distribucion/GestionarOtrosDestinosPage.tsx index cdc4a6a..1bffcc1 100644 --- a/Frontend/src/pages/Distribucion/GestionarOtrosDestinosPage.tsx +++ b/Frontend/src/pages/Distribucion/GestionarOtrosDestinosPage.tsx @@ -29,7 +29,7 @@ const GestionarOtrosDestinosPage: React.FC = () => { const [apiErrorMessage, setApiErrorMessage] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedDestinoRow, setSelectedDestinoRow] = useState(null); @@ -193,7 +193,7 @@ const GestionarOtrosDestinosPage: React.FC = () => { { const [apiErrorMessage, setApiErrorMessage] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedPublicacionRow, setSelectedPublicacionRow] = useState(null); @@ -284,7 +284,7 @@ const GestionarPublicacionesPage: React.FC = () => { diff --git a/Frontend/src/pages/Distribucion/GestionarSalidasOtrosDestinosPage.tsx b/Frontend/src/pages/Distribucion/GestionarSalidasOtrosDestinosPage.tsx index 658e2b0..24ea500 100644 --- a/Frontend/src/pages/Distribucion/GestionarSalidasOtrosDestinosPage.tsx +++ b/Frontend/src/pages/Distribucion/GestionarSalidasOtrosDestinosPage.tsx @@ -42,7 +42,7 @@ const GestionarSalidasOtrosDestinosPage: React.FC = () => { const [editingSalida, setEditingSalida] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedRow, setSelectedRow] = useState(null); @@ -224,7 +224,7 @@ const GestionarSalidasOtrosDestinosPage: React.FC = () => { diff --git a/Frontend/src/pages/Distribucion/GestionarZonasPage.tsx b/Frontend/src/pages/Distribucion/GestionarZonasPage.tsx index 2d18c49..62f4654 100644 --- a/Frontend/src/pages/Distribucion/GestionarZonasPage.tsx +++ b/Frontend/src/pages/Distribucion/GestionarZonasPage.tsx @@ -30,7 +30,7 @@ const GestionarZonasPage: React.FC = () => { const [apiErrorMessage, setApiErrorMessage] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedZonaRow, setSelectedZonaRow] = useState(null); @@ -201,7 +201,7 @@ const GestionarZonasPage: React.FC = () => { { const [apiErrorMessage, setApiErrorMessage] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedEstadoRow, setSelectedEstadoRow] = useState(null); @@ -209,7 +209,7 @@ const GestionarEstadosBobinaPage: React.FC = () => { { const [apiErrorMessage, setApiErrorMessage] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedPlantaRow, setSelectedPlantaRow] = useState(null); @@ -220,7 +220,7 @@ const GestionarPlantasPage: React.FC = () => { { const [selectedBobina, setSelectedBobina] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(10); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const { tienePermiso, isSuperAdmin } = usePermissions(); @@ -258,7 +258,7 @@ const GestionarStockBobinasPage: React.FC = () => { diff --git a/Frontend/src/pages/Impresion/GestionarTiposBobinaPage.tsx b/Frontend/src/pages/Impresion/GestionarTiposBobinaPage.tsx index ba1eb19..284dc85 100644 --- a/Frontend/src/pages/Impresion/GestionarTiposBobinaPage.tsx +++ b/Frontend/src/pages/Impresion/GestionarTiposBobinaPage.tsx @@ -29,7 +29,7 @@ const GestionarTiposBobinaPage: React.FC = () => { const [apiErrorMessage, setApiErrorMessage] = useState(null); const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const [rowsPerPage, setRowsPerPage] = useState(25); const [anchorEl, setAnchorEl] = useState(null); const [selectedTipoBobinaRow, setSelectedTipoBobinaRow] = useState(null); @@ -208,7 +208,7 @@ const GestionarTiposBobinaPage: React.FC = () => { { @@ -17,26 +17,40 @@ const ImpresionIndexPage: React.FC = () => { const [selectedSubTab, setSelectedSubTab] = useState(false); useEffect(() => { - const currentBasePath = '/impresion'; // Ruta base de este módulo - const subPath = location.pathname.startsWith(currentBasePath + '/') - ? location.pathname.substring(currentBasePath.length + 1) - : (location.pathname === currentBasePath ? impresionSubModules[0]?.path : undefined); - - const activeTabIndex = impresionSubModules.findIndex( - (subModule) => subModule.path === subPath - ); - - if (activeTabIndex !== -1) { - setSelectedSubTab(activeTabIndex); - } else { - if (location.pathname === currentBasePath && impresionSubModules.length > 0) { - navigate(impresionSubModules[0].path, { replace: true }); - setSelectedSubTab(0); - } else { - setSelectedSubTab(false); + const currentBasePath = '/impresion'; + const defaultSubPath = 'stock-bobinas'; // Define tu sub-ruta por defecto aquí + + const pathParts = location.pathname.split('/'); + const currentSubPathSegment = pathParts[2]; // /impresion -> pathParts[1] es 'impresion', pathParts[2] sería la sub-ruta + + let activeTabIndex = -1; + + if (currentSubPathSegment) { + activeTabIndex = impresionSubModules.findIndex( + (subModule) => subModule.path === currentSubPathSegment + ); } - } - }, [location.pathname, navigate]); + + if (activeTabIndex !== -1) { + setSelectedSubTab(activeTabIndex); + } else { + // Si estamos en la ruta base /impresion o una subruta no reconocida + if (location.pathname === currentBasePath || (location.pathname.startsWith(currentBasePath) && activeTabIndex === -1) ) { + const defaultTabIndex = impresionSubModules.findIndex(sm => sm.path === defaultSubPath); + if (defaultTabIndex !== -1) { + navigate(`${currentBasePath}/${defaultSubPath}`, { replace: true }); + setSelectedSubTab(defaultTabIndex); + } else if (impresionSubModules.length > 0) { // Fallback al primero si el default no existe + navigate(`${currentBasePath}/${impresionSubModules[0].path}`, { replace: true }); + setSelectedSubTab(0); + } else { + setSelectedSubTab(false); // No hay sub-módulos + } + } else { + setSelectedSubTab(false); // No es una ruta del módulo contable + } + } + }, [location.pathname, navigate]); const handleSubTabChange = (_event: React.SyntheticEvent, newValue: number) => { setSelectedSubTab(newValue); diff --git a/Frontend/src/pages/Reportes/ReporteComparativaConsumoBobinasPage.tsx b/Frontend/src/pages/Reportes/ReporteComparativaConsumoBobinasPage.tsx index 8eca575..9897226 100644 --- a/Frontend/src/pages/Reportes/ReporteComparativaConsumoBobinasPage.tsx +++ b/Frontend/src/pages/Reportes/ReporteComparativaConsumoBobinasPage.tsx @@ -3,17 +3,18 @@ import { Box, Typography, Paper, CircularProgress, Alert, Button } from '@mui/material'; import { DataGrid, type GridColDef, GridFooterContainer, GridFooter } from '@mui/x-data-grid'; -import type {Theme} from '@mui/material/styles'; +import type { Theme } from '@mui/material/styles'; import { esES } from '@mui/x-data-grid/locales'; import reportesService from '../../services/Reportes/reportesService'; import type { ComparativaConsumoBobinasDto } from '../../models/dtos/Reportes/ComparativaConsumoBobinasDto'; import SeleccionaReporteComparativaConsumoBobinas from './SeleccionaReporteComparativaConsumoBobinas'; +import { usePermissions } from '../../hooks/usePermissions'; import * as XLSX from 'xlsx'; import axios from 'axios'; // Interfaz extendida para DataGrid interface ComparativaConsumoBobinasDataGridDto extends ComparativaConsumoBobinasDto { - id: string; + id: string; } const ReporteComparativaConsumoBobinasPage: React.FC = () => { @@ -28,9 +29,11 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => { fechaInicioMesB: string; fechaFinMesB: string; idPlanta?: number | null; consolidado: boolean; nombrePlanta?: string; - mesA?: string; - mesB?: string; + mesA?: string; + mesB?: string; } | null>(null); + const { tienePermiso, isSuperAdmin } = usePermissions(); + const puedeVerReporte = isSuperAdmin || tienePermiso("RR007"); const numberLocaleFormatter = (value: number | null | undefined) => value != null ? Number(value).toLocaleString('es-AR') : ''; @@ -40,6 +43,11 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => { fechaInicioMesB: string; fechaFinMesB: string; idPlanta?: number | null; consolidado: boolean; }) => { + if (!puedeVerReporte) { + setError("No tiene permiso para generar este reporte."); + setLoading(false); + return; + } setLoading(true); setError(null); setApiErrorParams(null); @@ -47,23 +55,23 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => { let plantaNombre = "Consolidado"; if (!params.consolidado && params.idPlanta) { - const plantaService = (await import('../../services/Impresion/plantaService')).default; - const plantaData = await plantaService.getPlantaById(params.idPlanta); - plantaNombre = plantaData?.nombre ?? "N/A"; + const plantaService = (await import('../../services/Impresion/plantaService')).default; + const plantaData = await plantaService.getPlantaById(params.idPlanta); + plantaNombre = plantaData?.nombre ?? "N/A"; } // Formatear nombres de meses para el PDF const formatMonthYear = (dateString: string) => { - const date = new Date(dateString + 'T00:00:00'); // Asegurar que se parsea como local - return date.toLocaleDateString('es-AR', { month: 'long', year: 'numeric', timeZone: 'UTC' }); + const date = new Date(dateString + 'T00:00:00'); // Asegurar que se parsea como local + return date.toLocaleDateString('es-AR', { month: 'long', year: 'numeric', timeZone: 'UTC' }); }; setCurrentParams({ - ...params, - nombrePlanta: plantaNombre, - mesA: formatMonthYear(params.fechaInicioMesA), - mesB: formatMonthYear(params.fechaInicioMesB) + ...params, + nombrePlanta: plantaNombre, + mesA: formatMonthYear(params.fechaInicioMesA), + mesB: formatMonthYear(params.fechaInicioMesB) }); - + try { const data = await reportesService.getComparativaConsumoBobinas(params); const dataWithIds = data.map((item, index) => ({ ...item, id: `${item.tipoBobina}-${index}` })); @@ -106,23 +114,23 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => { })); const totales = dataToExport.reduce((acc, row) => { - acc.cantA += Number(row["Cant. Mes A"]); acc.cantB += Number(row["Cant. Mes B"]); - acc.difCant += Number(row["Dif. Cant."]); acc.kgA += Number(row["Kg Mes A"]); - acc.kgB += Number(row["Kg Mes B"]); acc.difKg += Number(row["Dif. Kg"]); - return acc; - }, { cantA:0, cantB:0, difCant:0, kgA:0, kgB:0, difKg:0 }); + acc.cantA += Number(row["Cant. Mes A"]); acc.cantB += Number(row["Cant. Mes B"]); + acc.difCant += Number(row["Dif. Cant."]); acc.kgA += Number(row["Kg Mes A"]); + acc.kgB += Number(row["Kg Mes B"]); acc.difKg += Number(row["Dif. Kg"]); + return acc; + }, { cantA: 0, cantB: 0, difCant: 0, kgA: 0, kgB: 0, difKg: 0 }); dataToExport.push({ - "Tipo Bobina": "TOTALES", "Cant. Mes A": totales.cantA, "Cant. Mes B": totales.cantB, - "Dif. Cant.": totales.difCant, "Kg Mes A": totales.kgA, "Kg Mes B": totales.kgB, - "Dif. Kg": totales.difKg, + "Tipo Bobina": "TOTALES", "Cant. Mes A": totales.cantA, "Cant. Mes B": totales.cantB, + "Dif. Cant.": totales.difCant, "Kg Mes A": totales.kgA, "Kg Mes B": totales.kgB, + "Dif. Kg": totales.difKg, }); const ws = XLSX.utils.json_to_sheet(dataToExport); const headers = Object.keys(dataToExport[0] || {}); - ws['!cols'] = headers.map(h => { - const maxLen = Math.max(...dataToExport.map(row => (row as any)[h]?.toString().length ?? 0), h.length); - return { wch: maxLen + 2 }; + ws['!cols'] = headers.map(h => { + const maxLen = Math.max(...dataToExport.map(row => (row as any)[h]?.toString().length ?? 0), h.length); + return { wch: maxLen + 2 }; }); ws['!freeze'] = { xSplit: 0, ySplit: 1 }; const wb = XLSX.utils.book_new(); @@ -192,88 +200,91 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => { if (!totalesGenerales) return null; const getCellStyle = (field: (typeof columns)[number]['field'] | 'label', isLabel: boolean = false) => { - const colConfig = columns.find(c => c.field === field); - // Ajustar anchos para los totales para que sean más compactos - let targetWidth: number | string = 'auto'; - let targetMinWidth: number | string = 'auto'; + const colConfig = columns.find(c => c.field === field); + // Ajustar anchos para los totales para que sean más compactos + let targetWidth: number | string = 'auto'; + let targetMinWidth: number | string = 'auto'; - if (isLabel) { - targetWidth = colConfig?.width ? Math.max(80, colConfig.width * 0.5) : 100; // Más corto para "TOTALES:" - targetMinWidth = 80; - } else if (colConfig) { - targetWidth = colConfig.width ? Math.max(70, colConfig.width * 0.75) : 90; // 75% del ancho de columna, mínimo 70 - targetMinWidth = 70; - } - - const style: React.CSSProperties = { - minWidth: targetMinWidth, - width: targetWidth, - textAlign: isLabel ? 'left' : (colConfig?.align || 'right') as 'left' | 'right' | 'center', - paddingRight: isLabel ? 1 : (field === 'diferenciaKilosUtilizados' ? 0 : 1), // pr en theme units - fontWeight: 'bold', - whiteSpace: 'nowrap', - }; + if (isLabel) { + targetWidth = colConfig?.width ? Math.max(80, colConfig.width * 0.5) : 100; // Más corto para "TOTALES:" + targetMinWidth = 80; + } else if (colConfig) { + targetWidth = colConfig.width ? Math.max(70, colConfig.width * 0.75) : 90; // 75% del ancho de columna, mínimo 70 + targetMinWidth = 70; + } - // Aplicar el separador si es la columna 'kilosUtilizadosMesA' - if (field === 'kilosUtilizadosMesA') { - style.borderLeft = `2px solid grey`; // O theme.palette.divider - style.paddingLeft = '8px'; // Espacio después del separador - } - return style; + const style: React.CSSProperties = { + minWidth: targetMinWidth, + width: targetWidth, + textAlign: isLabel ? 'left' : (colConfig?.align || 'right') as 'left' | 'right' | 'center', + paddingRight: isLabel ? 1 : (field === 'diferenciaKilosUtilizados' ? 0 : 1), // pr en theme units + fontWeight: 'bold', + whiteSpace: 'nowrap', + }; + + // Aplicar el separador si es la columna 'kilosUtilizadosMesA' + if (field === 'kilosUtilizadosMesA') { + style.borderLeft = `2px solid grey`; // O theme.palette.divider + style.paddingLeft = '8px'; // Espacio después del separador + } + return style; }; return ( - `1px solid ${theme.palette.divider}`, - minHeight: '52px', + `1px solid ${theme.palette.divider}`, + minHeight: '52px', + }}> + - - - + + - - TOTALES: - {numberLocaleFormatter(totalesGenerales.bobinasUtilizadasMesA)} - {numberLocaleFormatter(totalesGenerales.bobinasUtilizadasMesB)} - {numberLocaleFormatter(totalesGenerales.diferenciaBobinasUtilizadas)} - {numberLocaleFormatter(totalesGenerales.kilosUtilizadosMesA)} - {numberLocaleFormatter(totalesGenerales.kilosUtilizadosMesB)} - {numberLocaleFormatter(totalesGenerales.diferenciaKilosUtilizados)} - - + + TOTALES: + {numberLocaleFormatter(totalesGenerales.bobinasUtilizadasMesA)} + {numberLocaleFormatter(totalesGenerales.bobinasUtilizadasMesB)} + {numberLocaleFormatter(totalesGenerales.diferenciaBobinasUtilizadas)} + {numberLocaleFormatter(totalesGenerales.kilosUtilizadosMesA)} + {numberLocaleFormatter(totalesGenerales.kilosUtilizadosMesB)} + {numberLocaleFormatter(totalesGenerales.diferenciaKilosUtilizados)} + + ); }; if (showParamSelector) { + if (!loading && !puedeVerReporte) { + return No tiene permiso para acceder a este reporte.; + } return ( @@ -293,7 +304,7 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => { Reporte: Comparativa Consumo de Bobinas - + + ); + } + return ( diff --git a/Frontend/src/pages/Reportes/ReporteTiradasPublicacionesSeccionesPage.tsx b/Frontend/src/pages/Reportes/ReporteTiradasPublicacionesSeccionesPage.tsx index 699840d..03f68b1 100644 --- a/Frontend/src/pages/Reportes/ReporteTiradasPublicacionesSeccionesPage.tsx +++ b/Frontend/src/pages/Reportes/ReporteTiradasPublicacionesSeccionesPage.tsx @@ -7,12 +7,13 @@ import { esES } from '@mui/x-data-grid/locales'; import reportesService from '../../services/Reportes/reportesService'; import type { TiradasPublicacionesSeccionesDto } from '../../models/dtos/Reportes/TiradasPublicacionesSeccionesDto'; import SeleccionaReporteTiradasPublicacionesSecciones from './SeleccionaReporteTiradasPublicacionesSecciones'; +import { usePermissions } from '../../hooks/usePermissions'; import * as XLSX from 'xlsx'; import axios from 'axios'; // Interfaz extendida para DataGrid interface TiradasPublicacionesSeccionesDataGridDto extends TiradasPublicacionesSeccionesDto { - id: string; + id: string; } const ReporteTiradasPublicacionesSeccionesPage: React.FC = () => { @@ -32,17 +33,24 @@ const ReporteTiradasPublicacionesSeccionesPage: React.FC = () => { nombrePlanta?: string; mesAnioParaNombreArchivo?: string; } | null>(null); + const { tienePermiso, isSuperAdmin } = usePermissions(); + const puedeVerReporte = isSuperAdmin || tienePermiso("RR008"); const numberLocaleFormatter = (value: number | null | undefined, fractionDigits: number = 0) => value != null ? Number(value).toLocaleString('es-AR', { minimumFractionDigits: fractionDigits, maximumFractionDigits: fractionDigits }) : ''; const handleGenerarReporte = useCallback(async (params: { -idPublicacion: number; -fechaDesde: string; -fechaHasta: string; -idPlanta?: number | null; -consolidado: boolean; -}) => { + idPublicacion: number; + fechaDesde: string; + fechaHasta: string; + idPlanta?: number | null; + consolidado: boolean; + }) => { + if (!puedeVerReporte) { + setError("No tiene permiso para generar este reporte."); + setLoading(false); + return; + } setLoading(true); setError(null); setApiErrorParams(null); @@ -52,9 +60,9 @@ consolidado: boolean; const pubData = await pubService.getPublicacionById(params.idPublicacion); let plantaNombre = "Consolidado"; if (!params.consolidado && params.idPlanta) { - const plantaService = (await import('../../services/Impresion/plantaService')).default; - const plantaData = await plantaService.getPlantaById(params.idPlanta); - plantaNombre = plantaData?.nombre ?? "N/A"; + const plantaService = (await import('../../services/Impresion/plantaService')).default; + const plantaData = await plantaService.getPlantaById(params.idPlanta); + plantaNombre = plantaData?.nombre ?? "N/A"; } // Formatear mes y año para el título/nombre de archivo // const fechaDesdeObj = new Date(params.fechaDesde + 'T00:00:00'); // Asegurar que es local @@ -65,8 +73,8 @@ consolidado: boolean; const mesAnioNombre = `${dateParts[1]}/${dateParts[0]}`; - setCurrentParams({...params, nombrePublicacion: pubData?.nombre, nombrePlanta: plantaNombre, mesAnioParaNombreArchivo: mesAnioNombre}); - + setCurrentParams({ ...params, nombrePublicacion: pubData?.nombre, nombrePlanta: plantaNombre, mesAnioParaNombreArchivo: mesAnioNombre }); + try { const data = await reportesService.getTiradasPublicacionesSecciones(params); const dataWithIds = data.map((item, index) => ({ ...item, id: `${item.nombreSeccion}-${index}` })); @@ -109,20 +117,20 @@ consolidado: boolean; // Totales para Excel const totales = { - "Nombre Sección": "Totales", - "Páginas Impresas": reportData.reduce((sum, item) => sum + item.totalPaginasImpresas, 0), - "Total Ediciones": reportData.reduce((sum, item) => sum + item.cantidadTiradas, 0), - "Pág. Por Edición (Promedio)": reportData.reduce((sum, item) => sum + item.totalPaginasEjemplares, 0), // Suma de promedios para el total, como en el PDF - "Total Ejemplares": reportData.reduce((sum, item) => sum + item.totalEjemplares, 0), - "Pág. Ejemplar (Promedio)": reportData.reduce((sum, item) => sum + item.promedioPaginasPorEjemplar, 0), // Suma de promedios para el total + "Nombre Sección": "Totales", + "Páginas Impresas": reportData.reduce((sum, item) => sum + item.totalPaginasImpresas, 0), + "Total Ediciones": reportData.reduce((sum, item) => sum + item.cantidadTiradas, 0), + "Pág. Por Edición (Promedio)": reportData.reduce((sum, item) => sum + item.totalPaginasEjemplares, 0), // Suma de promedios para el total, como en el PDF + "Total Ejemplares": reportData.reduce((sum, item) => sum + item.totalEjemplares, 0), + "Pág. Ejemplar (Promedio)": reportData.reduce((sum, item) => sum + item.promedioPaginasPorEjemplar, 0), // Suma de promedios para el total }; dataToExport.push(totales); const ws = XLSX.utils.json_to_sheet(dataToExport); const headers = Object.keys(dataToExport[0] || {}); - ws['!cols'] = headers.map(h => { - const maxLen = Math.max(...dataToExport.map(row => (row as any)[h]?.toString().length ?? 0), h.length); - return { wch: maxLen + 2 }; + ws['!cols'] = headers.map(h => { + const maxLen = Math.max(...dataToExport.map(row => (row as any)[h]?.toString().length ?? 0), h.length); + return { wch: maxLen + 2 }; }); ws['!freeze'] = { xSplit: 0, ySplit: 1 }; @@ -192,57 +200,61 @@ consolidado: boolean; if (!totalesGenerales) return null; const getCellStyle = (field: (typeof columns)[number]['field'] | 'label', isLabel: boolean = false) => { - const colConfig = columns.find(c => c.field === field); - let targetWidth: number | string = 'auto'; - let targetMinWidth: number | string = 'auto'; + const colConfig = columns.find(c => c.field === field); + let targetWidth: number | string = 'auto'; + let targetMinWidth: number | string = 'auto'; - if (isLabel) { - targetWidth = colConfig?.width ? Math.max(100, colConfig.width * 0.6) : 150; - targetMinWidth = 100; - } else if (colConfig) { - targetWidth = colConfig.width ? Math.max(80, colConfig.width * 0.8) : 100; - targetMinWidth = 80; - } - - return { - minWidth: targetMinWidth, - width: targetWidth, - textAlign: isLabel ? 'left' : (colConfig?.align || 'right') as 'left' | 'right' | 'center', - pr: isLabel ? 1 : (field === 'promedioPaginasPorEjemplar' ? 0 : 1), - fontWeight: 'bold', - whiteSpace: 'nowrap', - }; + if (isLabel) { + targetWidth = colConfig?.width ? Math.max(100, colConfig.width * 0.6) : 150; + targetMinWidth = 100; + } else if (colConfig) { + targetWidth = colConfig.width ? Math.max(80, colConfig.width * 0.8) : 100; + targetMinWidth = 80; + } + + return { + minWidth: targetMinWidth, + width: targetWidth, + textAlign: isLabel ? 'left' : (colConfig?.align || 'right') as 'left' | 'right' | 'center', + pr: isLabel ? 1 : (field === 'promedioPaginasPorEjemplar' ? 0 : 1), + fontWeight: 'bold', + whiteSpace: 'nowrap', + }; }; return ( - `1px solid ${theme.palette.divider}`, minHeight: '52px', + `1px solid ${theme.palette.divider}`, minHeight: '52px', + }}> + + + + - - - - - Totales {/* Cambiado de TOTALES: a Totales */} - {numberLocaleFormatter(totalesGenerales.totalPaginasImpresas)} - {numberLocaleFormatter(totalesGenerales.cantidadTiradas)} - {numberLocaleFormatter(totalesGenerales.totalPaginasEjemplares)} - {numberLocaleFormatter(totalesGenerales.totalEjemplares)} - {numberLocaleFormatter(totalesGenerales.promedioPaginasPorEjemplar)} - - + Totales {/* Cambiado de TOTALES: a Totales */} + {numberLocaleFormatter(totalesGenerales.totalPaginasImpresas)} + {numberLocaleFormatter(totalesGenerales.cantidadTiradas)} + {numberLocaleFormatter(totalesGenerales.totalPaginasEjemplares)} + {numberLocaleFormatter(totalesGenerales.totalEjemplares)} + {numberLocaleFormatter(totalesGenerales.promedioPaginasPorEjemplar)} + + ); }; if (showParamSelector) { + if (!loading && !puedeVerReporte) { + return No tiene permiso para acceder a este reporte.; + } return ( @@ -274,12 +286,12 @@ consolidado: boolean; - Publicación: {currentParams?.nombrePublicacion} | - Planta: {currentParams?.nombrePlanta} | + Publicación: {currentParams?.nombrePublicacion} | + Planta: {currentParams?.nombrePlanta} | Mes Consultado: {currentParams?.mesAnioParaNombreArchivo} - {loading && } + {loading && } {error && !loading && {error}} {!loading && !error && reportData.length > 0 && ( @@ -293,15 +305,15 @@ consolidado: boolean; sx={{ height: 'calc(100vh - 320px)' }} // Ajustar altura según sea necesario initialState={{ pagination: { - paginationModel: { pageSize: 100, page: 0 }, + paginationModel: { pageSize: 100, page: 0 }, }, }} - pageSizeOptions={[25, 50 , 100]} + pageSizeOptions={[25, 50, 100]} disableRowSelectionOnClick /> )} - {!loading && !error && reportData.length === 0 && currentParams && (No se encontraron datos para los criterios seleccionados.)} + {!loading && !error && reportData.length === 0 && currentParams && (No se encontraron datos para los criterios seleccionados.)} ); }; diff --git a/Frontend/src/pages/Reportes/SeleccionaReporteComparativaConsumoBobinas.tsx b/Frontend/src/pages/Reportes/SeleccionaReporteComparativaConsumoBobinas.tsx index 025755b..5d7602c 100644 --- a/Frontend/src/pages/Reportes/SeleccionaReporteComparativaConsumoBobinas.tsx +++ b/Frontend/src/pages/Reportes/SeleccionaReporteComparativaConsumoBobinas.tsx @@ -3,7 +3,7 @@ import { Box, Typography, TextField, Button, CircularProgress, Alert, FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox } from '@mui/material'; -import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; +import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto'; import plantaService from '../../services/Impresion/plantaService'; interface SeleccionaReporteComparativaConsumoBobinasProps { @@ -35,7 +35,7 @@ const SeleccionaReporteComparativaConsumoBobinas: React.FC(''); const [consolidado, setConsolidado] = useState(false); - const [plantas, setPlantas] = useState([]); + const [plantas, setPlantas] = useState([]); const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); @@ -43,7 +43,7 @@ const SeleccionaReporteComparativaConsumoBobinas: React.FC { setLoadingDropdowns(true); try { - const plantasData = await plantaService.getAllPlantas(); + const plantasData = await plantaService.getPlantasForDropdown(); setPlantas(plantasData); } catch (error) { console.error("Error al cargar plantas:", error); diff --git a/Frontend/src/pages/Reportes/SeleccionaReporteConsumoBobinasSeccion.tsx b/Frontend/src/pages/Reportes/SeleccionaReporteConsumoBobinasSeccion.tsx index 66681e3..76a1867 100644 --- a/Frontend/src/pages/Reportes/SeleccionaReporteConsumoBobinasSeccion.tsx +++ b/Frontend/src/pages/Reportes/SeleccionaReporteConsumoBobinasSeccion.tsx @@ -3,7 +3,7 @@ import { Box, Typography, TextField, Button, CircularProgress, Alert, FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox } from '@mui/material'; -import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; +import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto'; import plantaService from '../../services/Impresion/plantaService'; interface SeleccionaReporteConsumoBobinasSeccionProps { @@ -29,7 +29,7 @@ const SeleccionaReporteConsumoBobinasSeccion: React.FC(''); const [consolidado, setConsolidado] = useState(false); - const [plantas, setPlantas] = useState([]); + const [plantas, setPlantas] = useState([]); const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); @@ -37,7 +37,7 @@ const SeleccionaReporteConsumoBobinasSeccion: React.FC { setLoadingDropdowns(true); try { - const plantasData = await plantaService.getAllPlantas(); + const plantasData = await plantaService.getPlantasForDropdown(); setPlantas(plantasData); } catch (error) { console.error("Error al cargar plantas:", error); diff --git a/Frontend/src/pages/Reportes/SeleccionaReporteExistenciaPapel.tsx b/Frontend/src/pages/Reportes/SeleccionaReporteExistenciaPapel.tsx index f475a48..61ad8a5 100644 --- a/Frontend/src/pages/Reportes/SeleccionaReporteExistenciaPapel.tsx +++ b/Frontend/src/pages/Reportes/SeleccionaReporteExistenciaPapel.tsx @@ -3,7 +3,7 @@ import { Box, Typography, TextField, Button, CircularProgress, Alert, FormControl, InputLabel, Select, MenuItem, Checkbox, FormControlLabel } from '@mui/material'; -import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; +import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto'; import plantaService from '../../services/Impresion/plantaService'; interface SeleccionaReporteExistenciaPapelProps { @@ -28,7 +28,7 @@ const SeleccionaReporteExistenciaPapel: React.FC(''); const [consolidado, setConsolidado] = useState(false); - const [plantas, setPlantas] = useState([]); + const [plantas, setPlantas] = useState([]); const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); @@ -36,10 +36,10 @@ const SeleccionaReporteExistenciaPapel: React.FC { setLoadingDropdowns(true); try { - const plantasData = await plantaService.getAllPlantas(); + const plantasData = await plantaService.getPlantasForDropdown(); setPlantas(plantasData); } catch (error) { - console.error("Error al cargar plantas:", error); + console.error("Error al cargar plantas para dropdown:", error); setLocalErrors(prev => ({ ...prev, dropdowns: 'Error al cargar plantas.' })); } finally { setLoadingDropdowns(false); diff --git a/Frontend/src/pages/Reportes/SeleccionaReporteMovimientoBobinas.tsx b/Frontend/src/pages/Reportes/SeleccionaReporteMovimientoBobinas.tsx index f298390..a4b5873 100644 --- a/Frontend/src/pages/Reportes/SeleccionaReporteMovimientoBobinas.tsx +++ b/Frontend/src/pages/Reportes/SeleccionaReporteMovimientoBobinas.tsx @@ -3,8 +3,8 @@ import { Box, Typography, TextField, Button, CircularProgress, Alert, FormControl, InputLabel, Select, MenuItem } from '@mui/material'; -import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; // Asumo que ya tienes este DTO -import plantaService from '../../services/Impresion/plantaService'; // Asumo que ya tienes este servicio +import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto'; +import plantaService from '../../services/Impresion/plantaService'; interface SeleccionaReporteMovimientoBobinasProps { onGenerarReporte: (params: { @@ -26,7 +26,7 @@ const SeleccionaReporteMovimientoBobinas: React.FC(new Date().toISOString().split('T')[0]); const [idPlanta, setIdPlanta] = useState(''); // Puede ser string inicialmente por el MenuItem vacío - const [plantas, setPlantas] = useState([]); + const [plantas, setPlantas] = useState([]); const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); @@ -34,7 +34,7 @@ const SeleccionaReporteMovimientoBobinas: React.FC { setLoadingDropdowns(true); try { - const plantasData = await plantaService.getAllPlantas(); // Asumiendo que esto devuelve todas + const plantasData = await plantaService.getPlantasForDropdown(); setPlantas(plantasData); } catch (error) { console.error("Error al cargar plantas:", error); diff --git a/Frontend/src/pages/Reportes/SeleccionaReporteMovimientoBobinasEstado.tsx b/Frontend/src/pages/Reportes/SeleccionaReporteMovimientoBobinasEstado.tsx index 99d62ed..520afba 100644 --- a/Frontend/src/pages/Reportes/SeleccionaReporteMovimientoBobinasEstado.tsx +++ b/Frontend/src/pages/Reportes/SeleccionaReporteMovimientoBobinasEstado.tsx @@ -3,7 +3,7 @@ import { Box, Typography, TextField, Button, CircularProgress, Alert, FormControl, InputLabel, Select, MenuItem } from '@mui/material'; -import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; +import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto'; import plantaService from '../../services/Impresion/plantaService'; interface SeleccionaReporteMovimientoBobinasEstadoProps { @@ -26,7 +26,7 @@ const SeleccionaReporteMovimientoBobinasEstado: React.FC(new Date().toISOString().split('T')[0]); const [idPlanta, setIdPlanta] = useState(''); - const [plantas, setPlantas] = useState([]); + const [plantas, setPlantas] = useState([]); const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); @@ -34,7 +34,7 @@ const SeleccionaReporteMovimientoBobinasEstado: React.FC { setLoadingDropdowns(true); try { - const plantasData = await plantaService.getAllPlantas(); + const plantasData = await plantaService.getPlantasForDropdown(); setPlantas(plantasData); } catch (error) { console.error("Error al cargar plantas:", error); @@ -65,7 +65,7 @@ const SeleccionaReporteMovimientoBobinasEstado: React.FC(''); const [consolidado, setConsolidado] = useState(false); - const [publicaciones, setPublicaciones] = useState([]); - const [plantas, setPlantas] = useState([]); + const [publicaciones, setPublicaciones] = useState([]); + const [plantas, setPlantas] = useState([]); const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); @@ -41,8 +41,8 @@ const SeleccionaReporteTiradasPublicacionesSecciones: React.FC p)); setPlantas(plantaData); diff --git a/Frontend/src/services/Distribucion/publicacionService.ts b/Frontend/src/services/Distribucion/publicacionService.ts index f343ce1..a40dc05 100644 --- a/Frontend/src/services/Distribucion/publicacionService.ts +++ b/Frontend/src/services/Distribucion/publicacionService.ts @@ -4,6 +4,7 @@ import type { CreatePublicacionDto } from '../../models/dtos/Distribucion/Create import type { UpdatePublicacionDto } from '../../models/dtos/Distribucion/UpdatePublicacionDto'; import type { PublicacionDiaSemanaDto } from '../../models/dtos/Distribucion/PublicacionDiaSemanaDto'; import type { UpdatePublicacionDiasSemanaRequestDto } from '../../models/dtos/Distribucion/UpdatePublicacionDiasSemanaRequestDto'; +import type { PublicacionDropdownDto } from '../../models/dtos/Distribucion/PublicacionDropdownDto'; const getAllPublicaciones = async ( nombreFilter?: string, @@ -51,6 +52,11 @@ const getPublicacionesPorDiaSemana = async (diaSemana: number): Promise => { // << NUEVA FUNCIÓN + const response = await apiClient.get('/publicaciones/dropdown', { params: { soloHabilitadas } }); + return response.data; +}; + const publicacionService = { getAllPublicaciones, getPublicacionById, @@ -59,7 +65,8 @@ const publicacionService = { deletePublicacion, getConfiguracionDiasPublicacion, updateConfiguracionDiasPublicacion, - getPublicacionesPorDiaSemana + getPublicacionesPorDiaSemana, + getPublicacionesForDropdown, }; export default publicacionService; \ No newline at end of file diff --git a/Frontend/src/services/Impresion/plantaService.ts b/Frontend/src/services/Impresion/plantaService.ts index d17a818..82f2b71 100644 --- a/Frontend/src/services/Impresion/plantaService.ts +++ b/Frontend/src/services/Impresion/plantaService.ts @@ -2,6 +2,7 @@ import apiClient from '../apiClient'; import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; import type { CreatePlantaDto } from '../../models/dtos/Impresion/CreatePlantaDto'; import type { UpdatePlantaDto } from '../../models/dtos/Impresion/UpdatePlantaDto'; +import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto'; const getAllPlantas = async (nombreFilter?: string, detalleFilter?: string): Promise => { const params: Record = {}; @@ -35,12 +36,18 @@ const deletePlanta = async (id: number): Promise => { await apiClient.delete(`/plantas/${id}`); }; +const getPlantasForDropdown = async (): Promise => { // << NUEVA FUNCIÓN + const response = await apiClient.get('/plantas/dropdown'); + return response.data; +}; + const plantaService = { getAllPlantas, getPlantaById, createPlanta, updatePlanta, deletePlanta, + getPlantasForDropdown, }; export default plantaService; \ No newline at end of file