From cec471b4b1743bd712f6210712cbec7ec48fd436 Mon Sep 17 00:00:00 2001 From: eldiadmolinari Date: Fri, 13 Jun 2025 13:23:05 -0300 Subject: [PATCH] Fix Selectores de Fechas Reporte Existencia de Papel. Se agrega Total a Liquidar para la E/S de Canillitas. --- .../GestionIntegral.Api.AssemblyInfo.cs | 2 +- .../Debug/net9.0/rjsmcshtml.dswa.cache.json | 2 +- .../Debug/net9.0/rjsmrazor.dswa.cache.json | 2 +- .../GestionarEntradasSalidasCanillaPage.tsx | 118 +++++++++--------- .../Reportes/ReporteExistenciaPapelPage.tsx | 1 - .../SeleccionaReporteExistenciaPapel.tsx | 53 ++++++-- 6 files changed, 106 insertions(+), 72 deletions(-) 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 e3d5eea..7703c08 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+437b1e88641aca176cc46d68cee7c28d48eb88db")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b04a3b99bf2a45834787bea2220e2af89715eff2")] [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 c399b6a..6e58429 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":["ZZivTt9Zh03vN/jzywHdSIjldJk\u002BW/DgTu7TlHDqhsY=","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=","flM0K9XRNNYylZG0CGbM3aCgbKpYSYF47xY41qCjtsY="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"C9goqBDGh4B0L1HpPwpJHjfbRNoIuzqnU7zFMHk1LhM=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["ZZivTt9Zh03vN/jzywHdSIjldJk\u002BW/DgTu7TlHDqhsY=","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=","xAoI9GEquVEPBtI2g76y50iH7F\u002B5S2DDD/lAn\u002BmYZVM="],"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 de8e31a..96ba9d1 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":["ZZivTt9Zh03vN/jzywHdSIjldJk\u002BW/DgTu7TlHDqhsY=","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=","flM0K9XRNNYylZG0CGbM3aCgbKpYSYF47xY41qCjtsY="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"w3MBbMV9Msh0YEq9AW/8s16bzXJ93T9lMVXKPm/r6es=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["ZZivTt9Zh03vN/jzywHdSIjldJk\u002BW/DgTu7TlHDqhsY=","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=","xAoI9GEquVEPBtI2g76y50iH7F\u002B5S2DDD/lAn\u002BmYZVM="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Frontend/src/pages/Distribucion/GestionarEntradasSalidasCanillaPage.tsx b/Frontend/src/pages/Distribucion/GestionarEntradasSalidasCanillaPage.tsx index a94cf38..d72183f 100644 --- a/Frontend/src/pages/Distribucion/GestionarEntradasSalidasCanillaPage.tsx +++ b/Frontend/src/pages/Distribucion/GestionarEntradasSalidasCanillaPage.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useState, useEffect, useCallback, useMemo } from 'react'; // << Añadido useMemo import { Box, Typography, TextField, Button, Paper, IconButton, Menu, MenuItem, Chip, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TablePagination, @@ -33,9 +33,9 @@ type TipoDestinatarioFiltro = 'canillitas' | 'accionistas'; const GestionarEntradasSalidasCanillaPage: React.FC = () => { const [movimientos, setMovimientos] = useState([]); - const [loading, setLoading] = useState(true); // Para carga principal de movimientos - const [error, setError] = useState(null); // Error general o de carga - const [apiErrorMessage, setApiErrorMessage] = useState(null); // Para errores de modal/API + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [apiErrorMessage, setApiErrorMessage] = useState(null); const [filtroFecha, setFiltroFecha] = useState(new Date().toISOString().split('T')[0]); const [filtroIdPublicacion, setFiltroIdPublicacion] = useState(''); @@ -52,7 +52,7 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { const [prefillModalData, setPrefillModalData] = useState<{ fecha?: string; idCanilla?: number | string; - nombreCanilla?: string; // << AÑADIDO PARA PASAR AL MODAL + nombreCanilla?: string; idPublicacion?: number | string; } | null>(null); @@ -82,34 +82,34 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { useEffect(() => { const fetchPublicaciones = async () => { - setLoadingFiltersDropdown(true); // Mover al inicio de la carga de pubs + setLoadingFiltersDropdown(true); try { const pubsData = await publicacionService.getPublicacionesForDropdown(true); setPublicaciones(pubsData); } catch (err) { console.error("Error cargando publicaciones para filtro:",err); - setError("Error al cargar publicaciones."); // Usar error general + setError("Error al cargar publicaciones."); } finally { - // No poner setLoadingFiltersDropdown(false) aquí, esperar a que ambas cargas terminen + // No setLoadingFiltersDropdown(false) acá, esperar a la otra carga } }; fetchPublicaciones(); }, []); const fetchDestinatariosParaDropdown = useCallback(async () => { - setLoadingFiltersDropdown(true); // Poner al inicio de esta carga también + setLoadingFiltersDropdown(true); setFiltroIdCanillitaSeleccionado(''); setDestinatariosDropdown([]); - setError(null); // Limpiar errores de carga de dropdowns previos + setError(null); try { const esAccionistaFilter = filtroTipoDestinatario === 'accionistas'; const data = await canillaService.getAllCanillas(undefined, undefined, true, esAccionistaFilter); setDestinatariosDropdown(data); } catch (err) { console.error("Error cargando destinatarios para filtro:", err); - setError("Error al cargar canillitas/accionistas."); // Usar error general + setError("Error al cargar canillitas/accionistas."); } finally { - setLoadingFiltersDropdown(false); // Poner al final de AMBAS cargas de dropdown + setLoadingFiltersDropdown(false); } }, [filtroTipoDestinatario]); @@ -153,9 +153,9 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { cargarMovimientos(); } else { setMovimientos([]); - if (loading) setLoading(false); // Asegurar que no se quede en loading si los filtros se limpian + if (loading) setLoading(false); } - }, [cargarMovimientos, filtroFecha, filtroIdCanillitaSeleccionado]); // `cargarMovimientos` ya tiene sus dependencias + }, [cargarMovimientos, filtroFecha, filtroIdCanillitaSeleccionado]); const handleOpenModal = (item?: EntradaSalidaCanillaDto) => { @@ -172,7 +172,6 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { setEditingMovimiento(item); setPrefillModalData(null); } else { - // --- CAMBIO: Obtener nombre del canillita seleccionado para prefill --- const canillitaSeleccionado = destinatariosDropdown.find( c => c.idCanilla === Number(filtroIdCanillitaSeleccionado) ); @@ -180,7 +179,7 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { setPrefillModalData({ fecha: filtroFecha, idCanilla: filtroIdCanillitaSeleccionado, - nombreCanilla: canillitaSeleccionado?.nomApe, // << AÑADIR NOMBRE + nombreCanilla: canillitaSeleccionado?.nomApe, idPublicacion: filtroIdPublicacion }); } @@ -188,7 +187,6 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { setModalOpen(true); }; - // ... handleDelete, handleMenuOpen, handleMenuClose, handleSelectRowForLiquidar, handleSelectAllForLiquidar, handleOpenLiquidarDialog, handleCloseLiquidarDialog sin cambios ... const handleDelete = async (idParte: number) => { if (window.confirm(`¿Seguro de eliminar este movimiento (ID: ${idParte})?`)) { setApiErrorMessage(null); @@ -233,9 +231,8 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { const handleConfirmLiquidar = async () => { - if (selectedIdsParaLiquidar.size === 0) { /* ... */ return; } - if (!fechaLiquidacionDialog) { /* ... */ return; } - // ... (validación de fecha sin cambios) + if (selectedIdsParaLiquidar.size === 0) { return; } + if (!fechaLiquidacionDialog) { return; } const fechaLiquidacionDate = new Date(fechaLiquidacionDialog + 'T00:00:00Z'); let fechaMovimientoMasReciente: Date | null = null; selectedIdsParaLiquidar.forEach(idParte => { @@ -251,7 +248,6 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { setApiErrorMessage(`La fecha de liquidación (${fechaLiquidacionDate.toLocaleDateString('es-AR', {timeZone: 'UTC'})}) no puede ser inferior a la fecha del movimiento más reciente a liquidar (${(fechaMovimientoMasReciente as Date).toLocaleDateString('es-AR', {timeZone: 'UTC'})}).`); return; } - setApiErrorMessage(null); setLoading(true); const liquidarDto: LiquidarMovimientosCanillaRequestDto = { @@ -262,17 +258,18 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { await entradaSalidaCanillaService.liquidarMovimientos(liquidarDto); setOpenLiquidarDialog(false); const primerIdParteLiquidado = Array.from(selectedIdsParaLiquidar)[0]; + // Necesitamos encontrar el movimiento en la lista ANTES de recargar const movimientoParaTicket = movimientos.find(m => m.idParte === primerIdParteLiquidado); - await cargarMovimientos(); + await cargarMovimientos(); // Recargar la lista para reflejar el estado liquidado - // --- CAMBIO: NO IMPRIMIR TICKET SI ES ACCIONISTA --- + // Usar la fecha del movimiento original para el ticket if (movimientoParaTicket && !movimientoParaTicket.canillaEsAccionista) { console.log("Liquidación exitosa, generando ticket para canillita NO accionista:", movimientoParaTicket.idCanilla); await handleImprimirTicketLiquidacion( movimientoParaTicket.idCanilla, - fechaLiquidacionDialog, - false // esAccionista = false + movimientoParaTicket.fecha, // Usar la fecha del movimiento + false ); } else if (movimientoParaTicket && movimientoParaTicket.canillaEsAccionista) { console.log("Liquidación exitosa para accionista. No se genera ticket automáticamente."); @@ -288,7 +285,6 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { }; const handleModalEditSubmit = async (data: UpdateEntradaSalidaCanillaDto, idParte: number) => { - // ... (sin cambios) setApiErrorMessage(null); try { await entradaSalidaCanillaService.updateEntradaSalidaCanilla(idParte, data); @@ -311,7 +307,6 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { const handleImprimirTicketLiquidacion = useCallback(async ( idCanilla: number, fecha: string, esAccionista: boolean ) => { - // ... (sin cambios) setLoadingTicketPdf(true); setApiErrorMessage(null); try { @@ -340,11 +335,14 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { }; const displayData = movimientos.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage); - if (!loading && !puedeVer && !loadingFiltersDropdown && movimientos.length === 0 && !filtroFecha && !filtroIdCanillitaSeleccionado ) { // Modificado para solo mostrar si no hay filtros y no puede ver + const totalARendirVisible = useMemo(() => + displayData.filter(m => !m.liquidado).reduce((sum, item) => sum + item.montoARendir, 0) + , [displayData]); + + if (!loading && !puedeVer && !loadingFiltersDropdown && movimientos.length === 0 && !filtroFecha && !filtroIdCanillitaSeleccionado ) { return {error || "Acceso denegado."}; } - const numSelectedToLiquidate = selectedIdsParaLiquidar.size; const numNotLiquidatedOnPage = displayData.filter(m => !m.liquidado).length; @@ -354,11 +352,12 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { Filtros - setFiltroFecha(e.target.value)} InputLabelProps={{ shrink: true }} sx={{ minWidth: 170 }} required - error={!filtroFecha} // Se marca error si está vacío + error={!filtroFecha} helperText={!filtroFecha ? "Fecha es obligatoria" : ""} /> { - - {/* --- CAMBIO: DESHABILITAR BOTÓN SI FILTROS OBLIGATORIOS NO ESTÁN --- */} + {puedeCrear && ( @@ -417,26 +415,32 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { )} - - {!filtroFecha && Por favor, seleccione una fecha.} + + {!filtroFecha && Por favor, seleccione una fecha.} {filtroFecha && !filtroIdCanillitaSeleccionado && Por favor, seleccione un {filtroTipoDestinatario === 'canillitas' ? 'canillita' : 'accionista'}.} {loading && } - {/* Mostrar error general si no hay error de API específico y no está cargando filtros */} - {error && !loading && !apiErrorMessage && !loadingFiltersDropdown && {error}} + {error && !loading && !apiErrorMessage && {error}} {apiErrorMessage && {apiErrorMessage}} - {loadingTicketPdf && - - - Cargando ticket... - - } + {loadingTicketPdf && ( Cargando ticket... )} + {!loading && movimientos.length > 0 && ( + + + + Total a Liquidar: + + + {totalARendirVisible.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })} + + + + )} + {!loading && !error && puedeVer && filtroFecha && filtroIdCanillitaSeleccionado && ( - // ... (Tabla y Paginación sin cambios) - - + +
{puedeLiquidar && ( @@ -527,20 +531,22 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { )} - + {puedeModificar && selectedRow && !selectedRow.liquidado && ( { handleOpenModal(selectedRow); handleMenuClose(); }}> Modificar)} - {/* --- CAMBIO: MOSTRAR REIMPRIMIR TICKET SIEMPRE SI ESTÁ LIQUIDADO --- */} - {selectedRow && selectedRow.liquidado && puedeLiquidar && ( // Usar puedeLiquidar para consistencia + + {selectedRow && selectedRow.liquidado && puedeLiquidar && ( { if (selectedRow) { + // Usar siempre selectedRow.fecha, que es la fecha original del movimiento handleImprimirTicketLiquidacion( selectedRow.idCanilla, - selectedRow.fechaLiquidado || selectedRow.fecha, - selectedRow.canillaEsAccionista // Pasar si es accionista + selectedRow.fecha, // Usar siempre la fecha del movimiento + selectedRow.canillaEsAccionista ); } + handleMenuClose(); }} disabled={loadingTicketPdf} > @@ -552,8 +558,9 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { {selectedRow && ( ((!selectedRow.liquidado && puedeEliminar) || (selectedRow.liquidado && puedeEliminarLiquidados)) ) && ( - { if (selectedRow) handleDelete(selectedRow.idParte); }}> - Eliminar + {if (selectedRow) handleDelete(selectedRow.idParte);}}> + + Eliminar )} @@ -561,14 +568,13 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => { setApiErrorMessage(null)} /> - {/* ... (Dialog de Liquidación sin cambios) ... */} Confirmar Liquidación diff --git a/Frontend/src/pages/Reportes/ReporteExistenciaPapelPage.tsx b/Frontend/src/pages/Reportes/ReporteExistenciaPapelPage.tsx index 0439364..ecee221 100644 --- a/Frontend/src/pages/Reportes/ReporteExistenciaPapelPage.tsx +++ b/Frontend/src/pages/Reportes/ReporteExistenciaPapelPage.tsx @@ -1,4 +1,3 @@ -// src/pages/Reportes/ReporteExistenciaPapelPage.tsx import React, { useState, useCallback } from 'react'; import { Box, diff --git a/Frontend/src/pages/Reportes/SeleccionaReporteExistenciaPapel.tsx b/Frontend/src/pages/Reportes/SeleccionaReporteExistenciaPapel.tsx index 61ad8a5..bb02db4 100644 --- a/Frontend/src/pages/Reportes/SeleccionaReporteExistenciaPapel.tsx +++ b/Frontend/src/pages/Reportes/SeleccionaReporteExistenciaPapel.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { - Box, Typography, TextField, Button, CircularProgress, Alert, - FormControl, InputLabel, Select, MenuItem, Checkbox, FormControlLabel + Box, Typography, TextField, Button, CircularProgress, Alert, + FormControl, InputLabel, Select, MenuItem, Checkbox, FormControlLabel } from '@mui/material'; import type { PlantaDropdownDto } from '../../models/dtos/Impresion/PlantaDropdownDto'; import plantaService from '../../services/Impresion/plantaService'; @@ -12,10 +12,10 @@ interface SeleccionaReporteExistenciaPapelProps { fechaHasta: string; idPlanta?: number | null; consolidado: boolean; - }) => Promise; // La función que realmente llama al servicio y maneja los datos - onCancel: () => void; // Para cerrar el modal/componente - isLoading?: boolean; // Para mostrar estado de carga desde el padre - apiErrorMessage?: string | null; // Para mostrar errores de API desde el padre + }) => Promise; + onCancel?: () => void; // onCancel sigue acá por si lo necesito en otros selectores + isLoading?: boolean; + apiErrorMessage?: string | null; } const SeleccionaReporteExistenciaPapel: React.FC = ({ @@ -24,7 +24,12 @@ const SeleccionaReporteExistenciaPapel: React.FC { const [fechaDesde, setFechaDesde] = useState(new Date().toISOString().split('T')[0]); - const [fechaHasta, setFechaHasta] = useState(new Date().toISOString().split('T')[0]); + const [fechaHasta, setFechaHasta] = useState(() => { + // Inicializar fechaHasta al día siguiente por defecto + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + return tomorrow.toISOString().split('T')[0]; + }); const [idPlanta, setIdPlanta] = useState(''); const [consolidado, setConsolidado] = useState(false); @@ -49,18 +54,39 @@ const SeleccionaReporteExistenciaPapel: React.FC { - // Si se marca consolidado, limpiar y deshabilitar la selección de planta if (consolidado) { setIdPlanta(''); } }, [consolidado]); + + const handleFechaDesdeChange = (newFechaDesde: string) => { + setFechaDesde(newFechaDesde); + // Limpiar errores + setLocalErrors(p => ({ ...p, fechaDesde: null, fechaHasta: null })); + + // Si la nueva fechaDesde es igual o posterior a la fechaHasta, ajustar fechaHasta + if (newFechaDesde && fechaHasta && new Date(newFechaDesde) >= new Date(fechaHasta)) { + const dDesde = new Date(newFechaDesde + 'T00:00:00'); // Usar T00:00:00 para evitar problemas de zona horaria + dDesde.setDate(dDesde.getDate() + 1); + setFechaHasta(dDesde.toISOString().split('T')[0]); + } + }; + + // Función para obtener la fecha mínima permitida para fechaHasta + const getMinFechaHasta = () => { + if (!fechaDesde) return undefined; + const minDate = new Date(fechaDesde + 'T00:00:00'); + minDate.setDate(minDate.getDate() + 1); // El mínimo es el día SIGUIENTE a fechaDesde + return minDate.toISOString().split('T')[0]; + }; const validate = (): boolean => { const errors: { [key: string]: string | null } = {}; if (!fechaDesde) errors.fechaDesde = 'Fecha Desde es obligatoria.'; if (!fechaHasta) errors.fechaHasta = 'Fecha Hasta es obligatoria.'; - if (fechaDesde && fechaHasta && new Date(fechaDesde) > new Date(fechaHasta)) { - errors.fechaHasta = 'Fecha Hasta no puede ser anterior a Fecha Desde.'; + + if (fechaDesde && fechaHasta && new Date(fechaHasta) <= new Date(fechaDesde)) { + errors.fechaHasta = 'Fecha Hasta debe ser posterior a Fecha Desde.'; } if (!consolidado && !idPlanta) { errors.idPlanta = 'Seleccione una planta si no es consolidado.'; @@ -88,7 +114,7 @@ const SeleccionaReporteExistenciaPapel: React.FC { setFechaDesde(e.target.value); setLocalErrors(p => ({ ...p, fechaDesde: null, fechaHasta: null })); }} + onChange={(e) => handleFechaDesdeChange(e.target.value)} margin="normal" fullWidth required @@ -109,6 +135,9 @@ const SeleccionaReporteExistenciaPapel: React.FC { setIdPlanta(e.target.value as number); setLocalErrors(p => ({ ...p, idPlanta: null })); }} > {consolidado ? 'N/A (Consolidado)' : 'Seleccione una planta'}