Comenzando la implementación final de permisos y depuración. Se sigue...

This commit is contained in:
2025-06-03 18:42:56 -03:00
parent 062cc05fd0
commit 8fb94f8cef
46 changed files with 711 additions and 493 deletions

View File

@@ -38,6 +38,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion
return null; return null;
} }
// GET: api/publicaciones
[HttpGet] [HttpGet]
[ProducesResponseType(typeof(IEnumerable<PublicacionDto>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(IEnumerable<PublicacionDto>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status403Forbidden)]
@@ -48,6 +49,26 @@ namespace GestionIntegral.Api.Controllers.Distribucion
return Ok(publicaciones); return Ok(publicaciones);
} }
// GET: api/publicaciones/dropdown
[HttpGet("dropdown")]
[ProducesResponseType(typeof(IEnumerable<PublicacionDropdownDto>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
// No se verifica permiso DP001, solo requiere autenticación general ([Authorize] del controlador)
public async Task<IActionResult> 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")] [HttpGet("{id:int}", Name = "GetPublicacionById")]
[ProducesResponseType(typeof(PublicacionDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(PublicacionDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status403Forbidden)]
@@ -60,6 +81,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion
return Ok(publicacion); return Ok(publicacion);
} }
// POST: api/publicaciones
[HttpPost] [HttpPost]
[ProducesResponseType(typeof(PublicacionDto), StatusCodes.Status201Created)] [ProducesResponseType(typeof(PublicacionDto), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
@@ -77,6 +99,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion
return CreatedAtRoute("GetPublicacionById", new { id = dto.IdPublicacion }, dto); return CreatedAtRoute("GetPublicacionById", new { id = dto.IdPublicacion }, dto);
} }
// PUT: api/publicaciones/{id}
[HttpPut("{id:int}")] [HttpPut("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
@@ -98,6 +121,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion
return NoContent(); return NoContent();
} }
// DELETE: api/publicaciones/{id}
[HttpDelete("{id:int}")] [HttpDelete("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
@@ -118,7 +142,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion
return NoContent(); 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")] [HttpGet("{idPublicacion:int}/dias-semana")]
[ProducesResponseType(typeof(IEnumerable<PublicacionDiaSemanaDto>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(IEnumerable<PublicacionDiaSemanaDto>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status403Forbidden)]

View File

@@ -71,6 +71,25 @@ namespace GestionIntegral.Api.Controllers.Impresion
} }
} }
// GET: api/plantas/dropdown
[HttpGet("dropdown")]
[ProducesResponseType(typeof(IEnumerable<PlantaDropdownDto>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
// NO chequeo TienePermiso("IP001")(requiere autenticación)
public async Task<IActionResult> 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} // GET: api/plantas/{id}
// Permiso: IP001 (Ver Plantas) // Permiso: IP001 (Ver Plantas)
[HttpGet("{id:int}", Name = "GetPlantaById")] [HttpGet("{id:int}", Name = "GetPlantaById")]

View File

@@ -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
}
}

View File

@@ -0,0 +1,8 @@
namespace GestionIntegral.Api.Dtos.Impresion
{
public class PlantaDropdownDto
{
public int IdPlanta { get; set; }
public required string Nombre { get; set; }
}
}

View File

@@ -14,5 +14,6 @@ namespace GestionIntegral.Api.Services.Distribucion
Task<IEnumerable<PublicacionDiaSemanaDto>> ObtenerConfiguracionDiasAsync(int idPublicacion); Task<IEnumerable<PublicacionDiaSemanaDto>> ObtenerConfiguracionDiasAsync(int idPublicacion);
Task<IEnumerable<PublicacionDto>> ObtenerPublicacionesPorDiaSemanaAsync(byte diaSemana); // Devolvemos el DTO completo Task<IEnumerable<PublicacionDto>> ObtenerPublicacionesPorDiaSemanaAsync(byte diaSemana); // Devolvemos el DTO completo
Task<(bool Exito, string? Error)> ActualizarConfiguracionDiasAsync(int idPublicacion, UpdatePublicacionDiasSemanaRequestDto requestDto, int idUsuario); Task<(bool Exito, string? Error)> ActualizarConfiguracionDiasAsync(int idPublicacion, UpdatePublicacionDiasSemanaRequestDto requestDto, int idUsuario);
Task<IEnumerable<PublicacionDropdownDto>> ObtenerParaDropdownAsync(bool soloHabilitadas = true);
} }
} }

View File

@@ -75,6 +75,22 @@ namespace GestionIntegral.Api.Services.Distribucion
return MapToDto(data); return MapToDto(data);
} }
public async Task<IEnumerable<PublicacionDropdownDto>> 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) public async Task<(PublicacionDto? Publicacion, string? Error)> CrearAsync(CreatePublicacionDto createDto, int idUsuario)
{ {
if (await _empresaRepository.GetByIdAsync(createDto.IdEmpresa) == null) if (await _empresaRepository.GetByIdAsync(createDto.IdEmpresa) == null)

View File

@@ -11,5 +11,6 @@ namespace GestionIntegral.Api.Services.Impresion
Task<(PlantaDto? Planta, string? Error)> CrearAsync(CreatePlantaDto createDto, int idUsuario); 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)> ActualizarAsync(int id, UpdatePlantaDto updateDto, int idUsuario);
Task<(bool Exito, string? Error)> EliminarAsync(int id, int idUsuario); Task<(bool Exito, string? Error)> EliminarAsync(int id, int idUsuario);
Task<IEnumerable<PlantaDropdownDto>> ObtenerParaDropdownAsync();
} }
} }

View File

@@ -181,5 +181,14 @@ namespace GestionIntegral.Api.Services.Impresion
return (false, $"Error interno al eliminar la planta: {ex.Message}"); return (false, $"Error interno al eliminar la planta: {ex.Message}");
} }
} }
public async Task<IEnumerable<PlantaDropdownDto>> 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();
}
} }
} }

View File

@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("GestionIntegral.Api")] [assembly: System.Reflection.AssemblyCompanyAttribute("GestionIntegral.Api")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [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.AssemblyProductAttribute("GestionIntegral.Api")]
[assembly: System.Reflection.AssemblyTitleAttribute("GestionIntegral.Api")] [assembly: System.Reflection.AssemblyTitleAttribute("GestionIntegral.Api")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@@ -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":{}} {"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":{}}

View File

@@ -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":{}} {"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":{}}

View File

@@ -0,0 +1,4 @@
export interface PublicacionDropdownDto {
idPublicacion: number;
nombre: string;
}

View File

@@ -0,0 +1,4 @@
export interface PlantaDropdownDto {
idPlanta: number;
nombre: string;
}

View File

@@ -51,7 +51,7 @@ const GestionarNotasCDPage: React.FC = () => {
const [editingNota, setEditingNota] = useState<NotaCreditoDebitoDto | null>(null); const [editingNota, setEditingNota] = useState<NotaCreditoDebitoDto | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedRow, setSelectedRow] = useState<NotaCreditoDebitoDto | null>(null); const [selectedRow, setSelectedRow] = useState<NotaCreditoDebitoDto | null>(null);
@@ -236,7 +236,7 @@ const GestionarNotasCDPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[10, 25, 50]} component="div" count={notas.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={notas.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -45,7 +45,7 @@ const GestionarPagosDistribuidorPage: React.FC = () => {
const [editingPago, setEditingPago] = useState<PagoDistribuidorDto | null>(null); const [editingPago, setEditingPago] = useState<PagoDistribuidorDto | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedRow, setSelectedRow] = useState<PagoDistribuidorDto | null>(null); const [selectedRow, setSelectedRow] = useState<PagoDistribuidorDto | null>(null);
@@ -205,7 +205,7 @@ const GestionarPagosDistribuidorPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[10, 25, 50]} component="div" count={pagos.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={pagos.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -126,7 +126,7 @@ const GestionarTiposPagoPage: React.FC = () => {
}; };
const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => { const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
setRowsPerPage(parseInt(event.target.value, 10)); setRowsPerPage(parseInt(event.target.value, 25));
setPage(0); setPage(0);
}; };
@@ -200,7 +200,7 @@ const GestionarTiposPagoPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} rowsPerPageOptions={[25, 50, 100]}
component="div" component="div"
count={tiposPago.length} count={tiposPago.length}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}

View File

@@ -51,7 +51,7 @@ const GestionarCanillitasPage: React.FC = () => {
} }
setLoading(true); setError(null); setApiErrorMessage(null); setLoading(true); setError(null); setApiErrorMessage(null);
try { try {
const legajoNum = filtroLegajo ? parseInt(filtroLegajo, 10) : undefined; const legajoNum = filtroLegajo ? parseInt(filtroLegajo, 25) : undefined;
if (filtroLegajo && isNaN(legajoNum!)) { if (filtroLegajo && isNaN(legajoNum!)) {
setApiErrorMessage("Legajo debe ser un número."); setApiErrorMessage("Legajo debe ser un número.");
setCanillitas([]); // Limpiar resultados si el filtro es inválido setCanillitas([]); // Limpiar resultados si el filtro es inválido
@@ -194,7 +194,7 @@ const GestionarCanillitasPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} component="div" count={canillitas.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={canillitas.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -39,7 +39,7 @@ const GestionarControlDevolucionesPage: React.FC = () => {
const [editingControl, setEditingControl] = useState<ControlDevolucionesDto | null>(null); const [editingControl, setEditingControl] = useState<ControlDevolucionesDto | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedRow, setSelectedRow] = useState<ControlDevolucionesDto | null>(null); const [selectedRow, setSelectedRow] = useState<ControlDevolucionesDto | null>(null);
@@ -206,7 +206,7 @@ const GestionarControlDevolucionesPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[10, 25, 50]} component="div" count={controles.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={controles.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -30,7 +30,7 @@ const GestionarDistribuidoresPage: React.FC = () => {
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedDistribuidorRow, setSelectedDistribuidorRow] = useState<DistribuidorDto | null>(null); const [selectedDistribuidorRow, setSelectedDistribuidorRow] = useState<DistribuidorDto | null>(null);
@@ -171,7 +171,7 @@ const GestionarDistribuidoresPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} component="div" count={distribuidores.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={distribuidores.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -30,7 +30,7 @@ const GestionarEmpresasPage: React.FC = () => {
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); // Para errores del modal (Create/Update/Delete) const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); // Para errores del modal (Create/Update/Delete)
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5); const [rowsPerPage, setRowsPerPage] = useState(25);
// Para el menú contextual de acciones por fila // Para el menú contextual de acciones por fila
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
@@ -227,7 +227,7 @@ const GestionarEmpresasPage: React.FC = () => {
</Table> </Table>
{/* Paginación */} {/* Paginación */}
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} rowsPerPageOptions={[25, 50, 100]}
component="div" component="div"
count={empresas.length} count={empresas.length}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}

View File

@@ -49,7 +49,7 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
const [editingMovimiento, setEditingMovimiento] = useState<EntradaSalidaCanillaDto | null>(null); const [editingMovimiento, setEditingMovimiento] = useState<EntradaSalidaCanillaDto | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedRow, setSelectedRow] = useState<EntradaSalidaCanillaDto | null>(null); const [selectedRow, setSelectedRow] = useState<EntradaSalidaCanillaDto | null>(null);
const [selectedIdsParaLiquidar, setSelectedIdsParaLiquidar] = useState<Set<number>>(new Set()); const [selectedIdsParaLiquidar, setSelectedIdsParaLiquidar] = useState<Set<number>>(new Set());
@@ -452,7 +452,7 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[10, 25, 50, 100]} component="div" count={movimientos.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={movimientos.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -44,7 +44,7 @@ const GestionarEntradasSalidasDistPage: React.FC = () => {
const [editingMovimiento, setEditingMovimiento] = useState<EntradaSalidaDistDto | null>(null); const [editingMovimiento, setEditingMovimiento] = useState<EntradaSalidaDistDto | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedRow, setSelectedRow] = useState<EntradaSalidaDistDto | null>(null); const [selectedRow, setSelectedRow] = useState<EntradaSalidaDistDto | null>(null);
@@ -220,7 +220,7 @@ const GestionarEntradasSalidasDistPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[10, 25, 50]} component="div" count={movimientos.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={movimientos.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -29,7 +29,7 @@ const GestionarOtrosDestinosPage: React.FC = () => {
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedDestinoRow, setSelectedDestinoRow] = useState<OtroDestinoDto | null>(null); const [selectedDestinoRow, setSelectedDestinoRow] = useState<OtroDestinoDto | null>(null);
@@ -193,7 +193,7 @@ const GestionarOtrosDestinosPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} rowsPerPageOptions={[25, 50, 100]}
component="div" component="div"
count={otrosDestinos.length} count={otrosDestinos.length}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}

View File

@@ -47,7 +47,7 @@ const GestionarPublicacionesPage: React.FC = () => {
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedPublicacionRow, setSelectedPublicacionRow] = useState<PublicacionDto | null>(null); const [selectedPublicacionRow, setSelectedPublicacionRow] = useState<PublicacionDto | null>(null);
@@ -284,7 +284,7 @@ const GestionarPublicacionesPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} component="div" count={publicaciones.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={publicaciones.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -42,7 +42,7 @@ const GestionarSalidasOtrosDestinosPage: React.FC = () => {
const [editingSalida, setEditingSalida] = useState<SalidaOtroDestinoDto | null>(null); const [editingSalida, setEditingSalida] = useState<SalidaOtroDestinoDto | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedRow, setSelectedRow] = useState<SalidaOtroDestinoDto | null>(null); const [selectedRow, setSelectedRow] = useState<SalidaOtroDestinoDto | null>(null);
@@ -224,7 +224,7 @@ const GestionarSalidasOtrosDestinosPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} component="div" count={salidas.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={salidas.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -30,7 +30,7 @@ const GestionarZonasPage: React.FC = () => {
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedZonaRow, setSelectedZonaRow] = useState<ZonaDto | null>(null); const [selectedZonaRow, setSelectedZonaRow] = useState<ZonaDto | null>(null);
@@ -201,7 +201,7 @@ const GestionarZonasPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} rowsPerPageOptions={[25, 50, 100]}
component="div" component="div"
count={zonas.length} count={zonas.length}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}

View File

@@ -29,7 +29,7 @@ const GestionarEstadosBobinaPage: React.FC = () => {
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedEstadoRow, setSelectedEstadoRow] = useState<EstadoBobinaDto | null>(null); const [selectedEstadoRow, setSelectedEstadoRow] = useState<EstadoBobinaDto | null>(null);
@@ -209,7 +209,7 @@ const GestionarEstadosBobinaPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} rowsPerPageOptions={[25, 50, 100]}
component="div" component="div"
count={estadosBobina.length} count={estadosBobina.length}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}

View File

@@ -30,7 +30,7 @@ const GestionarPlantasPage: React.FC = () => {
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedPlantaRow, setSelectedPlantaRow] = useState<PlantaDto | null>(null); const [selectedPlantaRow, setSelectedPlantaRow] = useState<PlantaDto | null>(null);
@@ -220,7 +220,7 @@ const GestionarPlantasPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} rowsPerPageOptions={[25, 50, 100]}
component="div" component="div"
count={plantas.length} count={plantas.length}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}

View File

@@ -59,7 +59,7 @@ const GestionarStockBobinasPage: React.FC = () => {
const [selectedBobina, setSelectedBobina] = useState<StockBobinaDto | null>(null); const [selectedBobina, setSelectedBobina] = useState<StockBobinaDto | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const { tienePermiso, isSuperAdmin } = usePermissions(); const { tienePermiso, isSuperAdmin } = usePermissions();
@@ -258,7 +258,7 @@ const GestionarStockBobinasPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25, 50]} component="div" count={stock.length} rowsPerPageOptions={[25, 50, 100]} component="div" count={stock.length}
rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:" onRowsPerPageChange={handleChangeRowsPerPage} labelRowsPerPage="Filas por página:"
/> />

View File

@@ -29,7 +29,7 @@ const GestionarTiposBobinaPage: React.FC = () => {
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null);
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5); const [rowsPerPage, setRowsPerPage] = useState(25);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [selectedTipoBobinaRow, setSelectedTipoBobinaRow] = useState<TipoBobinaDto | null>(null); const [selectedTipoBobinaRow, setSelectedTipoBobinaRow] = useState<TipoBobinaDto | null>(null);
@@ -208,7 +208,7 @@ const GestionarTiposBobinaPage: React.FC = () => {
</TableBody> </TableBody>
</Table> </Table>
<TablePagination <TablePagination
rowsPerPageOptions={[5, 10, 25]} rowsPerPageOptions={[25, 50, 100]}
component="div" component="div"
count={tiposBobina.length} count={tiposBobina.length}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}

View File

@@ -4,11 +4,11 @@ import { Outlet, useNavigate, useLocation } from 'react-router-dom';
// Define las sub-pestañas del módulo Impresión // Define las sub-pestañas del módulo Impresión
const impresionSubModules = [ const impresionSubModules = [
{ label: 'Stock Bobinas', path: 'stock-bobinas' },
{ label: 'Tiradas', path: 'tiradas' },
{ label: 'Plantas', path: 'plantas' }, { label: 'Plantas', path: 'plantas' },
{ label: 'Tipos Bobina', path: 'tipos-bobina' }, { label: 'Tipos Bobina', path: 'tipos-bobina' },
{ label: 'Estados Bobina', path: 'estados-bobina' }, { label: 'Estados Bobina', path: 'estados-bobina' },
{ label: 'Stock Bobinas', path: 'stock-bobinas' },
{ label: 'Tiradas', path: 'tiradas' },
]; ];
const ImpresionIndexPage: React.FC = () => { const ImpresionIndexPage: React.FC = () => {
@@ -17,23 +17,37 @@ const ImpresionIndexPage: React.FC = () => {
const [selectedSubTab, setSelectedSubTab] = useState<number | false>(false); const [selectedSubTab, setSelectedSubTab] = useState<number | false>(false);
useEffect(() => { useEffect(() => {
const currentBasePath = '/impresion'; // Ruta base de este módulo const currentBasePath = '/impresion';
const subPath = location.pathname.startsWith(currentBasePath + '/') const defaultSubPath = 'stock-bobinas'; // Define tu sub-ruta por defecto aquí
? location.pathname.substring(currentBasePath.length + 1)
: (location.pathname === currentBasePath ? impresionSubModules[0]?.path : undefined);
const activeTabIndex = impresionSubModules.findIndex( const pathParts = location.pathname.split('/');
(subModule) => subModule.path === subPath 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
); );
}
if (activeTabIndex !== -1) { if (activeTabIndex !== -1) {
setSelectedSubTab(activeTabIndex); setSelectedSubTab(activeTabIndex);
} else { } else {
if (location.pathname === currentBasePath && impresionSubModules.length > 0) { // Si estamos en la ruta base /impresion o una subruta no reconocida
navigate(impresionSubModules[0].path, { replace: true }); 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); setSelectedSubTab(0);
} else { } else {
setSelectedSubTab(false); setSelectedSubTab(false); // No hay sub-módulos
}
} else {
setSelectedSubTab(false); // No es una ruta del módulo contable
} }
} }
}, [location.pathname, navigate]); }, [location.pathname, navigate]);

View File

@@ -8,6 +8,7 @@ import { esES } from '@mui/x-data-grid/locales';
import reportesService from '../../services/Reportes/reportesService'; import reportesService from '../../services/Reportes/reportesService';
import type { ComparativaConsumoBobinasDto } from '../../models/dtos/Reportes/ComparativaConsumoBobinasDto'; import type { ComparativaConsumoBobinasDto } from '../../models/dtos/Reportes/ComparativaConsumoBobinasDto';
import SeleccionaReporteComparativaConsumoBobinas from './SeleccionaReporteComparativaConsumoBobinas'; import SeleccionaReporteComparativaConsumoBobinas from './SeleccionaReporteComparativaConsumoBobinas';
import { usePermissions } from '../../hooks/usePermissions';
import * as XLSX from 'xlsx'; import * as XLSX from 'xlsx';
import axios from 'axios'; import axios from 'axios';
@@ -31,6 +32,8 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => {
mesA?: string; mesA?: string;
mesB?: string; mesB?: string;
} | null>(null); } | null>(null);
const { tienePermiso, isSuperAdmin } = usePermissions();
const puedeVerReporte = isSuperAdmin || tienePermiso("RR007");
const numberLocaleFormatter = (value: number | null | undefined) => const numberLocaleFormatter = (value: number | null | undefined) =>
value != null ? Number(value).toLocaleString('es-AR') : ''; value != null ? Number(value).toLocaleString('es-AR') : '';
@@ -40,6 +43,11 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => {
fechaInicioMesB: string; fechaFinMesB: string; fechaInicioMesB: string; fechaFinMesB: string;
idPlanta?: number | null; consolidado: boolean; idPlanta?: number | null; consolidado: boolean;
}) => { }) => {
if (!puedeVerReporte) {
setError("No tiene permiso para generar este reporte.");
setLoading(false);
return;
}
setLoading(true); setLoading(true);
setError(null); setError(null);
setApiErrorParams(null); setApiErrorParams(null);
@@ -274,6 +282,9 @@ const ReporteComparativaConsumoBobinasPage: React.FC = () => {
if (showParamSelector) { if (showParamSelector) {
if (!loading && !puedeVerReporte) {
return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
}
return ( return (
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}> <Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
<Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}> <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>

View File

@@ -12,6 +12,7 @@ import { esES } from '@mui/x-data-grid/locales';
import reportesService from '../../services/Reportes/reportesService'; import reportesService from '../../services/Reportes/reportesService';
import type { ConsumoBobinasPublicacionDto } from '../../models/dtos/Reportes/ConsumoBobinasPublicacionDto'; import type { ConsumoBobinasPublicacionDto } from '../../models/dtos/Reportes/ConsumoBobinasPublicacionDto';
import SeleccionaReporteConsumoBobinasPublicacion from './SeleccionaReporteConsumoBobinasPublicacion'; import SeleccionaReporteConsumoBobinasPublicacion from './SeleccionaReporteConsumoBobinasPublicacion';
import { usePermissions } from '../../hooks/usePermissions';
import * as XLSX from 'xlsx'; import * as XLSX from 'xlsx';
import axios from 'axios'; import axios from 'axios';
@@ -27,11 +28,18 @@ const ReporteConsumoBobinasPublicacionPage: React.FC = () => {
fechaHasta: string; fechaHasta: string;
nombrePublicacion?: string; // Mantenido para nombre de archivo, no afecta al título DataGrid nombrePublicacion?: string; // Mantenido para nombre de archivo, no afecta al título DataGrid
} | null>(null); } | null>(null);
const { tienePermiso, isSuperAdmin } = usePermissions();
const puedeVerReporte = isSuperAdmin || tienePermiso("RR007");
const handleGenerarReporte = useCallback(async (params: { const handleGenerarReporte = useCallback(async (params: {
fechaDesde: string; fechaDesde: string;
fechaHasta: string; fechaHasta: string;
}) => { }) => {
if (!puedeVerReporte) {
setError("No tiene permiso para generar este reporte.");
setLoading(false);
return;
}
setLoading(true); setLoading(true);
setError(null); setError(null);
setApiErrorParams(null); setApiErrorParams(null);
@@ -227,6 +235,9 @@ const CustomFooter = () => {
}; };
if (showParamSelector) { if (showParamSelector) {
if (!loading && !puedeVerReporte) {
return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
}
return ( return (
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}> <Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
<Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}> <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>

View File

@@ -6,6 +6,7 @@ import {
import reportesService from '../../services/Reportes/reportesService'; import reportesService from '../../services/Reportes/reportesService';
import type { ConsumoBobinasSeccionDto } from '../../models/dtos/Reportes/ConsumoBobinasSeccionDto'; import type { ConsumoBobinasSeccionDto } from '../../models/dtos/Reportes/ConsumoBobinasSeccionDto';
import SeleccionaReporteConsumoBobinasSeccion from './SeleccionaReporteConsumoBobinasSeccion'; import SeleccionaReporteConsumoBobinasSeccion from './SeleccionaReporteConsumoBobinasSeccion';
import { usePermissions } from '../../hooks/usePermissions';
import * as XLSX from 'xlsx'; import * as XLSX from 'xlsx';
import axios from 'axios'; import axios from 'axios';
@@ -40,6 +41,8 @@ const ReporteConsumoBobinasSeccionPage: React.FC = () => {
consolidado: boolean; consolidado: boolean;
nombrePlanta?: string; // Para el PDF nombrePlanta?: string; // Para el PDF
} | null>(null); } | null>(null);
const { tienePermiso, isSuperAdmin } = usePermissions();
const puedeVerReporte = isSuperAdmin || tienePermiso("RR007");
const handleGenerarReporte = useCallback(async (params: { const handleGenerarReporte = useCallback(async (params: {
fechaDesde: string; fechaDesde: string;
@@ -47,6 +50,11 @@ const ReporteConsumoBobinasSeccionPage: React.FC = () => {
idPlanta?: number | null; idPlanta?: number | null;
consolidado: boolean; consolidado: boolean;
}) => { }) => {
if (!puedeVerReporte) {
setError("No tiene permiso para generar este reporte.");
setLoading(false);
return;
}
setLoading(true); setLoading(true);
setError(null); setError(null);
setApiErrorParams(null); setApiErrorParams(null);
@@ -161,6 +169,9 @@ const ReporteConsumoBobinasSeccionPage: React.FC = () => {
const totalGeneralKilos = reportData.reduce((sum, item) => sum + item.totalKilos, 0); const totalGeneralKilos = reportData.reduce((sum, item) => sum + item.totalKilos, 0);
if (showParamSelector) { if (showParamSelector) {
if (!loading && !puedeVerReporte) {
return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
}
return ( return (
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}> <Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
<Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}> <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>

View File

@@ -17,6 +17,7 @@ import {
import reportesService from '../../services/Reportes/reportesService'; import reportesService from '../../services/Reportes/reportesService';
import type { ExistenciaPapelDto } from '../../models/dtos/Reportes/ExistenciaPapelDto'; import type { ExistenciaPapelDto } from '../../models/dtos/Reportes/ExistenciaPapelDto';
import SeleccionaReporteExistenciaPapel from './SeleccionaReporteExistenciaPapel'; import SeleccionaReporteExistenciaPapel from './SeleccionaReporteExistenciaPapel';
import { usePermissions } from '../../hooks/usePermissions';
import * as XLSX from 'xlsx'; import * as XLSX from 'xlsx';
import axios from 'axios'; import axios from 'axios';
@@ -27,6 +28,8 @@ const ReporteExistenciaPapelPage: React.FC = () => {
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [apiErrorParams, setApiErrorParams] = useState<string | null>(null); const [apiErrorParams, setApiErrorParams] = useState<string | null>(null);
const [showParamSelector, setShowParamSelector] = useState(true); const [showParamSelector, setShowParamSelector] = useState(true);
const { tienePermiso, isSuperAdmin } = usePermissions();
const puedeVerReporte = isSuperAdmin || tienePermiso("RR005");
const [currentParams, setCurrentParams] = useState<{ const [currentParams, setCurrentParams] = useState<{
fechaDesde: string; fechaDesde: string;
fechaHasta: string; fechaHasta: string;
@@ -40,6 +43,11 @@ const ReporteExistenciaPapelPage: React.FC = () => {
idPlanta?: number | null; idPlanta?: number | null;
consolidado: boolean; consolidado: boolean;
}) => { }) => {
if (!puedeVerReporte) {
setError("No tiene permiso para generar este reporte.");
setLoading(false); // Asegurarse que loading no quede en true
return;
}
setLoading(true); setLoading(true);
setError(null); setError(null);
setApiErrorParams(null); setApiErrorParams(null);
@@ -175,6 +183,9 @@ const ReporteExistenciaPapelPage: React.FC = () => {
}, [currentParams]); }, [currentParams]);
if (showParamSelector) { if (showParamSelector) {
if (!loading && !puedeVerReporte) {
return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
}
return ( return (
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}> <Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
<Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}> <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>

View File

@@ -5,20 +5,19 @@ import {
import { DataGrid, type GridColDef, GridFooterContainer, GridFooter } from '@mui/x-data-grid'; import { DataGrid, type GridColDef, GridFooterContainer, GridFooter } from '@mui/x-data-grid';
import { esES } from '@mui/x-data-grid/locales'; import { esES } from '@mui/x-data-grid/locales';
import reportesService from '../../services/Reportes/reportesService'; import reportesService from '../../services/Reportes/reportesService';
// Corregir importaciones de DTOs
import type { MovimientoBobinasPorEstadoResponseDto } from '../../models/dtos/Reportes/MovimientoBobinasPorEstadoResponseDto'; import type { MovimientoBobinasPorEstadoResponseDto } from '../../models/dtos/Reportes/MovimientoBobinasPorEstadoResponseDto';
import type { MovimientoBobinaEstadoDetalleDto } from '../../models/dtos/Reportes/MovimientoBobinaEstadoDetalleDto'; import type { MovimientoBobinaEstadoDetalleDto } from '../../models/dtos/Reportes/MovimientoBobinaEstadoDetalleDto';
import type { MovimientoBobinaEstadoTotalDto } from '../../models/dtos/Reportes/MovimientoBobinaEstadoTotalDto'; import type { MovimientoBobinaEstadoTotalDto } from '../../models/dtos/Reportes/MovimientoBobinaEstadoTotalDto';
import { usePermissions } from '../../hooks/usePermissions';
import SeleccionaReporteMovimientoBobinasEstado from './SeleccionaReporteMovimientoBobinasEstado'; import SeleccionaReporteMovimientoBobinasEstado from './SeleccionaReporteMovimientoBobinasEstado';
import * as XLSX from 'xlsx'; import * as XLSX from 'xlsx';
import axios from 'axios'; import axios from 'axios';
// Interfaces extendidas para DataGrid con 'id' // Interfaces extendidas para DataGrid con 'id'
interface DetalleMovimientoDataGrid extends MovimientoBobinaEstadoDetalleDto { // Usar el DTO correcto interface DetalleMovimientoDataGrid extends MovimientoBobinaEstadoDetalleDto {
id: string; id: string;
} }
interface TotalPorEstadoDataGrid extends MovimientoBobinaEstadoTotalDto { // Usar el DTO correcto interface TotalPorEstadoDataGrid extends MovimientoBobinaEstadoTotalDto {
id: string; id: string;
} }
@@ -35,6 +34,8 @@ const ReporteMovimientoBobinasEstadoPage: React.FC = () => {
idPlanta: number; idPlanta: number;
nombrePlanta?: string; nombrePlanta?: string;
} | null>(null); } | null>(null);
const { tienePermiso, isSuperAdmin } = usePermissions();
const puedeVerReporte = isSuperAdmin || tienePermiso("RR006");
const numberLocaleFormatter = (value: number | null | undefined) => const numberLocaleFormatter = (value: number | null | undefined) =>
value != null ? Number(value).toLocaleString('es-AR') : ''; value != null ? Number(value).toLocaleString('es-AR') : '';
@@ -48,6 +49,11 @@ const ReporteMovimientoBobinasEstadoPage: React.FC = () => {
fechaHasta: string; fechaHasta: string;
idPlanta: number; idPlanta: number;
}) => { }) => {
if (!puedeVerReporte) {
setError("No tiene permiso para generar este reporte.");
setLoading(false);
return;
}
setLoading(true); setLoading(true);
setError(null); setError(null);
setApiErrorParams(null); setApiErrorParams(null);
@@ -205,6 +211,9 @@ const ReporteMovimientoBobinasEstadoPage: React.FC = () => {
if (showParamSelector) { if (showParamSelector) {
if (!loading && !puedeVerReporte) { // Si no tiene permiso Y no está cargando, muestra error
return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
}
return ( return (
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}> <Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
<Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}> <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>

View File

@@ -6,6 +6,7 @@ import { DataGrid, type GridColDef, GridFooterContainer, GridFooter } from '@mui
import { esES } from '@mui/x-data-grid/locales'; // Para localización import { esES } from '@mui/x-data-grid/locales'; // Para localización
import reportesService from '../../services/Reportes/reportesService'; import reportesService from '../../services/Reportes/reportesService';
import type { MovimientoBobinasDto } from '../../models/dtos/Reportes/MovimientoBobinasDto'; import type { MovimientoBobinasDto } from '../../models/dtos/Reportes/MovimientoBobinasDto';
import { usePermissions } from '../../hooks/usePermissions';
import SeleccionaReporteMovimientoBobinas from './SeleccionaReporteMovimientoBobinas'; import SeleccionaReporteMovimientoBobinas from './SeleccionaReporteMovimientoBobinas';
import * as XLSX from 'xlsx'; import * as XLSX from 'xlsx';
import axios from 'axios'; import axios from 'axios';
@@ -16,11 +17,11 @@ interface MovimientoBobinasDataGridDto extends MovimientoBobinasDto {
} }
const ReporteMovimientoBobinasPage: React.FC = () => { const ReporteMovimientoBobinasPage: React.FC = () => {
const [reportData, setReportData] = useState<MovimientoBobinasDataGridDto[]>([]); // Usar el tipo extendido const [reportData, setReportData] = useState<MovimientoBobinasDataGridDto[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false); // Loading para generar reporte
const [loadingPdf, setLoadingPdf] = useState(false); const [loadingPdf, setLoadingPdf] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null); // Error al generar reporte
const [apiErrorParams, setApiErrorParams] = useState<string | null>(null); const [apiErrorParams, setApiErrorParams] = useState<string | null>(null); // Error específico del selector
const [showParamSelector, setShowParamSelector] = useState(true); const [showParamSelector, setShowParamSelector] = useState(true);
const [currentParams, setCurrentParams] = useState<{ const [currentParams, setCurrentParams] = useState<{
fechaDesde: string; fechaDesde: string;
@@ -29,6 +30,9 @@ const ReporteMovimientoBobinasPage: React.FC = () => {
nombrePlanta?: string; nombrePlanta?: string;
} | null>(null); } | null>(null);
const { tienePermiso, isSuperAdmin } = usePermissions(); // << OBTENER PERMISOS
const puedeVerReporte = isSuperAdmin || tienePermiso("RR006"); // << PERMISO ESPECÍFICO
const numberLocaleFormatter = (value: number | null | undefined) => const numberLocaleFormatter = (value: number | null | undefined) =>
value != null ? Number(value).toLocaleString('es-AR') : ''; value != null ? Number(value).toLocaleString('es-AR') : '';
@@ -37,20 +41,29 @@ const ReporteMovimientoBobinasPage: React.FC = () => {
fechaHasta: string; fechaHasta: string;
idPlanta: number; idPlanta: number;
}) => { }) => {
if (!puedeVerReporte) { // << CHEQUEO DE PERMISO
setError("No tiene permiso para generar este reporte.");
setLoading(false);
return;
}
setLoading(true); setLoading(true);
setError(null); setError(null);
setApiErrorParams(null); setApiErrorParams(null);
// Opcional: Obtener nombre de la planta
// const plantaService = (await import('../../services/Maestros/plantaService')).default; let plantaNombre = `Planta ${params.idPlanta}`; // Default
// const plantaData = await plantaService.getPlantaById(params.idPlanta); try {
// setCurrentParams({...params, nombrePlanta: plantaData?.nombre}); const plantaService = (await import('../../services/Impresion/plantaService')).default;
setCurrentParams(params); const plantaData = await plantaService.getPlantaById(params.idPlanta);
if (plantaData) plantaNombre = plantaData.nombre;
} catch (e) { console.warn("No se pudo obtener nombre de planta para el reporte", e)}
setCurrentParams({...params, nombrePlanta: plantaNombre});
try { try {
const data = await reportesService.getMovimientoBobinas(params); const data = await reportesService.getMovimientoBobinas(params);
// Añadir 'id' único a cada fila para DataGrid
const dataWithIds = data.map((item, index) => ({ const dataWithIds = data.map((item, index) => ({
...item, ...item,
id: `${item.tipoBobina}-${index}` // Asumiendo que tipoBobina es único por reporte o combinar con index id: `${item.tipoBobina}-${index}`
})); }));
setReportData(dataWithIds); setReportData(dataWithIds);
if (dataWithIds.length === 0) { if (dataWithIds.length === 0) {
@@ -61,12 +74,12 @@ const ReporteMovimientoBobinasPage: React.FC = () => {
const message = axios.isAxiosError(err) && err.response?.data?.message const message = axios.isAxiosError(err) && err.response?.data?.message
? err.response.data.message ? err.response.data.message
: 'Ocurrió un error al generar el reporte.'; : 'Ocurrió un error al generar el reporte.';
setApiErrorParams(message); setApiErrorParams(message); // Error para el selector
setReportData([]); setReportData([]);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, []); }, [puedeVerReporte]); // << AÑADIR puedeVerReporte
const handleVolverAParametros = useCallback(() => { const handleVolverAParametros = useCallback(() => {
setShowParamSelector(true); setShowParamSelector(true);
@@ -291,7 +304,12 @@ const ReporteMovimientoBobinasPage: React.FC = () => {
); );
}; };
// --- Lógica de Renderizado Principal ---
// Primero, el chequeo de permiso para el selector
if (showParamSelector) { if (showParamSelector) {
if (!loading && !puedeVerReporte) { // Si está cargando, no mostrar nada aún
return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
}
return ( return (
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}> <Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
<Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}> <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>
@@ -299,13 +317,25 @@ const ReporteMovimientoBobinasPage: React.FC = () => {
onGenerarReporte={handleGenerarReporte} onGenerarReporte={handleGenerarReporte}
onCancel={handleVolverAParametros} onCancel={handleVolverAParametros}
isLoading={loading} isLoading={loading}
apiErrorMessage={apiErrorParams} apiErrorMessage={apiErrorParams} // Pasar el error del selector
/> />
</Paper> </Paper>
</Box> </Box>
); );
} }
// Si ya pasó el selector y no tiene permiso (ej. cambio de roles mientras ve la pantalla)
if (!loading && !puedeVerReporte && !showParamSelector) {
return (
<Box sx={{ p: 2 }}>
<Alert severity="error" sx={{ m: 2 }}>No tiene permiso para ver este reporte.</Alert>
<Button onClick={handleVolverAParametros} variant="outlined" color="secondary" size="small">
Volver
</Button>
</Box>
);
}
return ( return (
<Box sx={{ p: 2 }}> <Box sx={{ p: 2 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2, flexWrap: 'wrap', gap: 1 }}> <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2, flexWrap: 'wrap', gap: 1 }}>

View File

@@ -7,6 +7,7 @@ import { esES } from '@mui/x-data-grid/locales';
import reportesService from '../../services/Reportes/reportesService'; import reportesService from '../../services/Reportes/reportesService';
import type { TiradasPublicacionesSeccionesDto } from '../../models/dtos/Reportes/TiradasPublicacionesSeccionesDto'; import type { TiradasPublicacionesSeccionesDto } from '../../models/dtos/Reportes/TiradasPublicacionesSeccionesDto';
import SeleccionaReporteTiradasPublicacionesSecciones from './SeleccionaReporteTiradasPublicacionesSecciones'; import SeleccionaReporteTiradasPublicacionesSecciones from './SeleccionaReporteTiradasPublicacionesSecciones';
import { usePermissions } from '../../hooks/usePermissions';
import * as XLSX from 'xlsx'; import * as XLSX from 'xlsx';
import axios from 'axios'; import axios from 'axios';
@@ -32,6 +33,8 @@ const ReporteTiradasPublicacionesSeccionesPage: React.FC = () => {
nombrePlanta?: string; nombrePlanta?: string;
mesAnioParaNombreArchivo?: string; mesAnioParaNombreArchivo?: string;
} | null>(null); } | null>(null);
const { tienePermiso, isSuperAdmin } = usePermissions();
const puedeVerReporte = isSuperAdmin || tienePermiso("RR008");
const numberLocaleFormatter = (value: number | null | undefined, fractionDigits: number = 0) => const numberLocaleFormatter = (value: number | null | undefined, fractionDigits: number = 0) =>
value != null ? Number(value).toLocaleString('es-AR', { minimumFractionDigits: fractionDigits, maximumFractionDigits: fractionDigits }) : ''; value != null ? Number(value).toLocaleString('es-AR', { minimumFractionDigits: fractionDigits, maximumFractionDigits: fractionDigits }) : '';
@@ -43,6 +46,11 @@ fechaHasta: string;
idPlanta?: number | null; idPlanta?: number | null;
consolidado: boolean; consolidado: boolean;
}) => { }) => {
if (!puedeVerReporte) {
setError("No tiene permiso para generar este reporte.");
setLoading(false);
return;
}
setLoading(true); setLoading(true);
setError(null); setError(null);
setApiErrorParams(null); setApiErrorParams(null);
@@ -221,7 +229,8 @@ consolidado: boolean;
}}> }}>
<Box sx={{ display: 'flex', alignItems: 'center', flexShrink: 0, overflow: 'hidden', px: 1 }}> <Box sx={{ display: 'flex', alignItems: 'center', flexShrink: 0, overflow: 'hidden', px: 1 }}>
<GridFooter <GridFooter
sx={{ borderTop: 'none', width: 'auto', sx={{
borderTop: 'none', width: 'auto',
'& .MuiToolbar-root': { paddingLeft: 0, paddingRight: 0, }, '& .MuiToolbar-root': { paddingLeft: 0, paddingRight: 0, },
'& .MuiDataGrid-selectedRowCount': { display: 'none' }, '& .MuiDataGrid-selectedRowCount': { display: 'none' },
}} }}
@@ -243,6 +252,9 @@ consolidado: boolean;
}; };
if (showParamSelector) { if (showParamSelector) {
if (!loading && !puedeVerReporte) {
return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
}
return ( return (
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}> <Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
<Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}> <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>

View File

@@ -3,7 +3,7 @@ import {
Box, Typography, TextField, Button, CircularProgress, Alert, Box, Typography, TextField, Button, CircularProgress, Alert,
FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox
} from '@mui/material'; } 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'; import plantaService from '../../services/Impresion/plantaService';
interface SeleccionaReporteComparativaConsumoBobinasProps { interface SeleccionaReporteComparativaConsumoBobinasProps {
@@ -35,7 +35,7 @@ const SeleccionaReporteComparativaConsumoBobinas: React.FC<SeleccionaReporteComp
const [idPlanta, setIdPlanta] = useState<number | string>(''); const [idPlanta, setIdPlanta] = useState<number | string>('');
const [consolidado, setConsolidado] = useState<boolean>(false); const [consolidado, setConsolidado] = useState<boolean>(false);
const [plantas, setPlantas] = useState<PlantaDto[]>([]); const [plantas, setPlantas] = useState<PlantaDropdownDto[]>([]);
const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [loadingDropdowns, setLoadingDropdowns] = useState(false);
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
@@ -43,7 +43,7 @@ const SeleccionaReporteComparativaConsumoBobinas: React.FC<SeleccionaReporteComp
const fetchPlantas = async () => { const fetchPlantas = async () => {
setLoadingDropdowns(true); setLoadingDropdowns(true);
try { try {
const plantasData = await plantaService.getAllPlantas(); const plantasData = await plantaService.getPlantasForDropdown();
setPlantas(plantasData); setPlantas(plantasData);
} catch (error) { } catch (error) {
console.error("Error al cargar plantas:", error); console.error("Error al cargar plantas:", error);

View File

@@ -3,7 +3,7 @@ import {
Box, Typography, TextField, Button, CircularProgress, Alert, Box, Typography, TextField, Button, CircularProgress, Alert,
FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox
} from '@mui/material'; } 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'; import plantaService from '../../services/Impresion/plantaService';
interface SeleccionaReporteConsumoBobinasSeccionProps { interface SeleccionaReporteConsumoBobinasSeccionProps {
@@ -29,7 +29,7 @@ const SeleccionaReporteConsumoBobinasSeccion: React.FC<SeleccionaReporteConsumoB
const [idPlanta, setIdPlanta] = useState<number | string>(''); const [idPlanta, setIdPlanta] = useState<number | string>('');
const [consolidado, setConsolidado] = useState<boolean>(false); const [consolidado, setConsolidado] = useState<boolean>(false);
const [plantas, setPlantas] = useState<PlantaDto[]>([]); const [plantas, setPlantas] = useState<PlantaDropdownDto[]>([]);
const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [loadingDropdowns, setLoadingDropdowns] = useState(false);
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
@@ -37,7 +37,7 @@ const SeleccionaReporteConsumoBobinasSeccion: React.FC<SeleccionaReporteConsumoB
const fetchPlantas = async () => { const fetchPlantas = async () => {
setLoadingDropdowns(true); setLoadingDropdowns(true);
try { try {
const plantasData = await plantaService.getAllPlantas(); const plantasData = await plantaService.getPlantasForDropdown();
setPlantas(plantasData); setPlantas(plantasData);
} catch (error) { } catch (error) {
console.error("Error al cargar plantas:", error); console.error("Error al cargar plantas:", error);

View File

@@ -3,7 +3,7 @@ import {
Box, Typography, TextField, Button, CircularProgress, Alert, Box, Typography, TextField, Button, CircularProgress, Alert,
FormControl, InputLabel, Select, MenuItem, Checkbox, FormControlLabel FormControl, InputLabel, Select, MenuItem, Checkbox, FormControlLabel
} from '@mui/material'; } 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'; import plantaService from '../../services/Impresion/plantaService';
interface SeleccionaReporteExistenciaPapelProps { interface SeleccionaReporteExistenciaPapelProps {
@@ -28,7 +28,7 @@ const SeleccionaReporteExistenciaPapel: React.FC<SeleccionaReporteExistenciaPape
const [idPlanta, setIdPlanta] = useState<number | string>(''); const [idPlanta, setIdPlanta] = useState<number | string>('');
const [consolidado, setConsolidado] = useState<boolean>(false); const [consolidado, setConsolidado] = useState<boolean>(false);
const [plantas, setPlantas] = useState<PlantaDto[]>([]); const [plantas, setPlantas] = useState<PlantaDropdownDto[]>([]);
const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [loadingDropdowns, setLoadingDropdowns] = useState(false);
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
@@ -36,10 +36,10 @@ const SeleccionaReporteExistenciaPapel: React.FC<SeleccionaReporteExistenciaPape
const fetchPlantas = async () => { const fetchPlantas = async () => {
setLoadingDropdowns(true); setLoadingDropdowns(true);
try { try {
const plantasData = await plantaService.getAllPlantas(); const plantasData = await plantaService.getPlantasForDropdown();
setPlantas(plantasData); setPlantas(plantasData);
} catch (error) { } 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.' })); setLocalErrors(prev => ({ ...prev, dropdowns: 'Error al cargar plantas.' }));
} finally { } finally {
setLoadingDropdowns(false); setLoadingDropdowns(false);

View File

@@ -3,8 +3,8 @@ import {
Box, Typography, TextField, Button, CircularProgress, Alert, Box, Typography, TextField, Button, CircularProgress, Alert,
FormControl, InputLabel, Select, MenuItem FormControl, InputLabel, Select, MenuItem
} from '@mui/material'; } from '@mui/material';
import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; // Asumo que ya tienes este DTO import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto';
import plantaService from '../../services/Impresion/plantaService'; // Asumo que ya tienes este servicio import plantaService from '../../services/Impresion/plantaService';
interface SeleccionaReporteMovimientoBobinasProps { interface SeleccionaReporteMovimientoBobinasProps {
onGenerarReporte: (params: { onGenerarReporte: (params: {
@@ -26,7 +26,7 @@ const SeleccionaReporteMovimientoBobinas: React.FC<SeleccionaReporteMovimientoBo
const [fechaHasta, setFechaHasta] = useState<string>(new Date().toISOString().split('T')[0]); const [fechaHasta, setFechaHasta] = useState<string>(new Date().toISOString().split('T')[0]);
const [idPlanta, setIdPlanta] = useState<number | string>(''); // Puede ser string inicialmente por el MenuItem vacío const [idPlanta, setIdPlanta] = useState<number | string>(''); // Puede ser string inicialmente por el MenuItem vacío
const [plantas, setPlantas] = useState<PlantaDto[]>([]); const [plantas, setPlantas] = useState<PlantaDropdownDto[]>([]);
const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [loadingDropdowns, setLoadingDropdowns] = useState(false);
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
@@ -34,7 +34,7 @@ const SeleccionaReporteMovimientoBobinas: React.FC<SeleccionaReporteMovimientoBo
const fetchPlantas = async () => { const fetchPlantas = async () => {
setLoadingDropdowns(true); setLoadingDropdowns(true);
try { try {
const plantasData = await plantaService.getAllPlantas(); // Asumiendo que esto devuelve todas const plantasData = await plantaService.getPlantasForDropdown();
setPlantas(plantasData); setPlantas(plantasData);
} catch (error) { } catch (error) {
console.error("Error al cargar plantas:", error); console.error("Error al cargar plantas:", error);

View File

@@ -3,7 +3,7 @@ import {
Box, Typography, TextField, Button, CircularProgress, Alert, Box, Typography, TextField, Button, CircularProgress, Alert,
FormControl, InputLabel, Select, MenuItem FormControl, InputLabel, Select, MenuItem
} from '@mui/material'; } 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'; import plantaService from '../../services/Impresion/plantaService';
interface SeleccionaReporteMovimientoBobinasEstadoProps { interface SeleccionaReporteMovimientoBobinasEstadoProps {
@@ -26,7 +26,7 @@ const SeleccionaReporteMovimientoBobinasEstado: React.FC<SeleccionaReporteMovimi
const [fechaHasta, setFechaHasta] = useState<string>(new Date().toISOString().split('T')[0]); const [fechaHasta, setFechaHasta] = useState<string>(new Date().toISOString().split('T')[0]);
const [idPlanta, setIdPlanta] = useState<number | string>(''); const [idPlanta, setIdPlanta] = useState<number | string>('');
const [plantas, setPlantas] = useState<PlantaDto[]>([]); const [plantas, setPlantas] = useState<PlantaDropdownDto[]>([]);
const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [loadingDropdowns, setLoadingDropdowns] = useState(false);
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
@@ -34,7 +34,7 @@ const SeleccionaReporteMovimientoBobinasEstado: React.FC<SeleccionaReporteMovimi
const fetchPlantas = async () => { const fetchPlantas = async () => {
setLoadingDropdowns(true); setLoadingDropdowns(true);
try { try {
const plantasData = await plantaService.getAllPlantas(); const plantasData = await plantaService.getPlantasForDropdown();
setPlantas(plantasData); setPlantas(plantasData);
} catch (error) { } catch (error) {
console.error("Error al cargar plantas:", error); console.error("Error al cargar plantas:", error);
@@ -65,7 +65,7 @@ const SeleccionaReporteMovimientoBobinasEstado: React.FC<SeleccionaReporteMovimi
onGenerarReporte({ onGenerarReporte({
fechaDesde, fechaDesde,
fechaHasta, fechaHasta,
idPlanta: Number(idPlanta) idPlanta: Number(idPlanta) // Asegurarse de que es un número
}); });
}; };

View File

@@ -3,9 +3,9 @@ import {
Box, Typography, TextField, Button, CircularProgress, Alert, Box, Typography, TextField, Button, CircularProgress, Alert,
FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox
} from '@mui/material'; } from '@mui/material';
import type { PublicacionDto } from '../../models/dtos/Distribucion/PublicacionDto'; import type { PublicacionDropdownDto } from '../../models/dtos/Distribucion/PublicacionDropdownDto';
import publicacionService from '../../services/Distribucion/publicacionService'; import publicacionService from '../../services/Distribucion/publicacionService';
import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto';
import plantaService from '../../services/Impresion/plantaService'; import plantaService from '../../services/Impresion/plantaService';
interface SeleccionaReporteTiradasPublicacionesSeccionesProps { interface SeleccionaReporteTiradasPublicacionesSeccionesProps {
@@ -31,8 +31,8 @@ const SeleccionaReporteTiradasPublicacionesSecciones: React.FC<SeleccionaReporte
const [idPlanta, setIdPlanta] = useState<number | string>(''); const [idPlanta, setIdPlanta] = useState<number | string>('');
const [consolidado, setConsolidado] = useState<boolean>(false); const [consolidado, setConsolidado] = useState<boolean>(false);
const [publicaciones, setPublicaciones] = useState<PublicacionDto[]>([]); const [publicaciones, setPublicaciones] = useState<PublicacionDropdownDto[]>([]);
const [plantas, setPlantas] = useState<PlantaDto[]>([]); const [plantas, setPlantas] = useState<PlantaDropdownDto[]>([]);
const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [loadingDropdowns, setLoadingDropdowns] = useState(false);
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
@@ -41,8 +41,8 @@ const SeleccionaReporteTiradasPublicacionesSecciones: React.FC<SeleccionaReporte
setLoadingDropdowns(true); setLoadingDropdowns(true);
try { try {
const [pubData, plantaData] = await Promise.all([ const [pubData, plantaData] = await Promise.all([
publicacionService.getAllPublicaciones(undefined, undefined, true), publicacionService.getPublicacionesForDropdown(true),
plantaService.getAllPlantas() plantaService.getPlantasForDropdown()
]); ]);
setPublicaciones(pubData.map(p => p)); setPublicaciones(pubData.map(p => p));
setPlantas(plantaData); setPlantas(plantaData);

View File

@@ -4,6 +4,7 @@ import type { CreatePublicacionDto } from '../../models/dtos/Distribucion/Create
import type { UpdatePublicacionDto } from '../../models/dtos/Distribucion/UpdatePublicacionDto'; import type { UpdatePublicacionDto } from '../../models/dtos/Distribucion/UpdatePublicacionDto';
import type { PublicacionDiaSemanaDto } from '../../models/dtos/Distribucion/PublicacionDiaSemanaDto'; import type { PublicacionDiaSemanaDto } from '../../models/dtos/Distribucion/PublicacionDiaSemanaDto';
import type { UpdatePublicacionDiasSemanaRequestDto } from '../../models/dtos/Distribucion/UpdatePublicacionDiasSemanaRequestDto'; import type { UpdatePublicacionDiasSemanaRequestDto } from '../../models/dtos/Distribucion/UpdatePublicacionDiasSemanaRequestDto';
import type { PublicacionDropdownDto } from '../../models/dtos/Distribucion/PublicacionDropdownDto';
const getAllPublicaciones = async ( const getAllPublicaciones = async (
nombreFilter?: string, nombreFilter?: string,
@@ -51,6 +52,11 @@ const getPublicacionesPorDiaSemana = async (diaSemana: number): Promise<Publicac
return response.data; return response.data;
}; };
const getPublicacionesForDropdown = async (soloHabilitadas: boolean = true): Promise<PublicacionDropdownDto[]> => { // << NUEVA FUNCIÓN
const response = await apiClient.get<PublicacionDropdownDto[]>('/publicaciones/dropdown', { params: { soloHabilitadas } });
return response.data;
};
const publicacionService = { const publicacionService = {
getAllPublicaciones, getAllPublicaciones,
getPublicacionById, getPublicacionById,
@@ -59,7 +65,8 @@ const publicacionService = {
deletePublicacion, deletePublicacion,
getConfiguracionDiasPublicacion, getConfiguracionDiasPublicacion,
updateConfiguracionDiasPublicacion, updateConfiguracionDiasPublicacion,
getPublicacionesPorDiaSemana getPublicacionesPorDiaSemana,
getPublicacionesForDropdown,
}; };
export default publicacionService; export default publicacionService;

View File

@@ -2,6 +2,7 @@ import apiClient from '../apiClient';
import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto';
import type { CreatePlantaDto } from '../../models/dtos/Impresion/CreatePlantaDto'; import type { CreatePlantaDto } from '../../models/dtos/Impresion/CreatePlantaDto';
import type { UpdatePlantaDto } from '../../models/dtos/Impresion/UpdatePlantaDto'; import type { UpdatePlantaDto } from '../../models/dtos/Impresion/UpdatePlantaDto';
import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto';
const getAllPlantas = async (nombreFilter?: string, detalleFilter?: string): Promise<PlantaDto[]> => { const getAllPlantas = async (nombreFilter?: string, detalleFilter?: string): Promise<PlantaDto[]> => {
const params: Record<string, string> = {}; const params: Record<string, string> = {};
@@ -35,12 +36,18 @@ const deletePlanta = async (id: number): Promise<void> => {
await apiClient.delete(`/plantas/${id}`); await apiClient.delete(`/plantas/${id}`);
}; };
const getPlantasForDropdown = async (): Promise<PlantaDropdownDto[]> => { // << NUEVA FUNCIÓN
const response = await apiClient.get<PlantaDropdownDto[]>('/plantas/dropdown');
return response.data;
};
const plantaService = { const plantaService = {
getAllPlantas, getAllPlantas,
getPlantaById, getPlantaById,
createPlanta, createPlanta,
updatePlanta, updatePlanta,
deletePlanta, deletePlanta,
getPlantasForDropdown,
}; };
export default plantaService; export default plantaService;