Fix Selectores de Fechas Reporte Existencia de Papel.
Se agrega Total a Liquidar para la E/S de Canillitas.
This commit is contained in:
@@ -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")]
|
||||
|
||||
@@ -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":{}}
|
||||
{"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":{}}
|
||||
@@ -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":{}}
|
||||
{"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":{}}
|
||||
@@ -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<EntradaSalidaCanillaDto[]>([]);
|
||||
const [loading, setLoading] = useState(true); // Para carga principal de movimientos
|
||||
const [error, setError] = useState<string | null>(null); // Error general o de carga
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null); // Para errores de modal/API
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | null>(null);
|
||||
|
||||
const [filtroFecha, setFiltroFecha] = useState<string>(new Date().toISOString().split('T')[0]);
|
||||
const [filtroIdPublicacion, setFiltroIdPublicacion] = useState<number | string>('');
|
||||
@@ -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 <Box sx={{ p: 2 }}><Alert severity="error">{error || "Acceso denegado."}</Alert></Box>;
|
||||
}
|
||||
|
||||
|
||||
const numSelectedToLiquidate = selectedIdsParaLiquidar.size;
|
||||
const numNotLiquidatedOnPage = displayData.filter(m => !m.liquidado).length;
|
||||
|
||||
@@ -354,11 +352,12 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
|
||||
<Paper sx={{ p: 2, mb: 2 }}>
|
||||
<Typography variant="h6" gutterBottom>Filtros <FilterListIcon fontSize="small" /></Typography>
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 2, alignItems: 'center', mb: 2 }}>
|
||||
{/* ... (Filtros sin cambios) ... */}
|
||||
<TextField label="Fecha" type="date" size="small" value={filtroFecha}
|
||||
onChange={(e) => 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" : ""}
|
||||
/>
|
||||
<ToggleButtonGroup
|
||||
@@ -398,14 +397,13 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
{/* --- CAMBIO: DESHABILITAR BOTÓN SI FILTROS OBLIGATORIOS NO ESTÁN --- */}
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap:2 }}>
|
||||
{puedeCrear && (
|
||||
<Button
|
||||
variant="contained"
|
||||
startIcon={<AddIcon />}
|
||||
onClick={() => handleOpenModal()}
|
||||
disabled={!filtroFecha || !filtroIdCanillitaSeleccionado} // <<-- AÑADIDO
|
||||
disabled={!filtroFecha || !filtroIdCanillitaSeleccionado}
|
||||
>
|
||||
Registrar Movimiento
|
||||
</Button>
|
||||
@@ -422,19 +420,25 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
|
||||
{filtroFecha && !filtroIdCanillitaSeleccionado && <Alert severity="info" sx={{my:1}}>Por favor, seleccione un {filtroTipoDestinatario === 'canillitas' ? 'canillita' : 'accionista'}.</Alert>}
|
||||
|
||||
{loading && <Box sx={{ display: 'flex', justifyContent: 'center', my: 2 }}><CircularProgress /></Box>}
|
||||
{/* Mostrar error general si no hay error de API específico y no está cargando filtros */}
|
||||
{error && !loading && !apiErrorMessage && !loadingFiltersDropdown && <Alert severity="error" sx={{ my: 2 }}>{error}</Alert>}
|
||||
{error && !loading && !apiErrorMessage && <Alert severity="error" sx={{ my: 2 }}>{error}</Alert>}
|
||||
{apiErrorMessage && <Alert severity="error" sx={{ my: 2 }}>{apiErrorMessage}</Alert>}
|
||||
{loadingTicketPdf &&
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', my: 2 }}>
|
||||
<CircularProgress size={20} sx={{ mr: 1 }} />
|
||||
<Typography variant="body2">Cargando ticket...</Typography>
|
||||
</Box>
|
||||
}
|
||||
{loadingTicketPdf && ( <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', my: 2 }}> <CircularProgress size={20} sx={{ mr: 1 }} /> <Typography variant="body2">Cargando ticket...</Typography> </Box> )}
|
||||
|
||||
|
||||
{!loading && movimientos.length > 0 && (
|
||||
<Paper sx={{ p: 1.5, mb: 2, mt:1, backgroundColor: 'grey.100' }}>
|
||||
<Box sx={{display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
|
||||
<Typography variant="subtitle1" sx={{mr:2}}>
|
||||
Total a Liquidar:
|
||||
</Typography>
|
||||
<Typography variant="h6" sx={{fontWeight: 'bold', color: 'error.main'}}>
|
||||
{totalARendirVisible.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Paper>
|
||||
)}
|
||||
|
||||
{!loading && !error && puedeVer && filtroFecha && filtroIdCanillitaSeleccionado && (
|
||||
// ... (Tabla y Paginación sin cambios)
|
||||
<TableContainer component={Paper}>
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
@@ -530,17 +534,19 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
|
||||
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleMenuClose}>
|
||||
{puedeModificar && selectedRow && !selectedRow.liquidado && (
|
||||
<MenuItem onClick={() => { handleOpenModal(selectedRow); handleMenuClose(); }}><EditIcon fontSize="small" sx={{ mr: 1 }} /> Modificar</MenuItem>)}
|
||||
{/* --- CAMBIO: MOSTRAR REIMPRIMIR TICKET SIEMPRE SI ESTÁ LIQUIDADO --- */}
|
||||
{selectedRow && selectedRow.liquidado && puedeLiquidar && ( // Usar puedeLiquidar para consistencia
|
||||
|
||||
{selectedRow && selectedRow.liquidado && puedeLiquidar && (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
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))
|
||||
) && (
|
||||
<MenuItem onClick={() => { if (selectedRow) handleDelete(selectedRow.idParte); }}>
|
||||
<DeleteIcon fontSize="small" sx={{ mr: 1 }} /> Eliminar
|
||||
<MenuItem onClick={() => {if (selectedRow) handleDelete(selectedRow.idParte);}}>
|
||||
<DeleteIcon fontSize="small" sx={{ mr: 1 }} />
|
||||
Eliminar
|
||||
</MenuItem>
|
||||
)}
|
||||
</Menu>
|
||||
@@ -561,14 +568,13 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
|
||||
<EntradaSalidaCanillaFormModal
|
||||
open={modalOpen}
|
||||
onClose={handleCloseModal}
|
||||
onSubmit={handleModalEditSubmit} // Este onSubmit es solo para edición
|
||||
onSubmit={handleModalEditSubmit}
|
||||
initialData={editingMovimiento}
|
||||
prefillData={prefillModalData}
|
||||
errorMessage={apiErrorMessage}
|
||||
clearErrorMessage={() => setApiErrorMessage(null)}
|
||||
/>
|
||||
|
||||
{/* ... (Dialog de Liquidación sin cambios) ... */}
|
||||
<Dialog open={openLiquidarDialog} onClose={handleCloseLiquidarDialog}>
|
||||
<DialogTitle>Confirmar Liquidación</DialogTitle>
|
||||
<DialogContent>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// src/pages/Reportes/ReporteExistenciaPapelPage.tsx
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import {
|
||||
Box,
|
||||
|
||||
@@ -12,10 +12,10 @@ interface SeleccionaReporteExistenciaPapelProps {
|
||||
fechaHasta: string;
|
||||
idPlanta?: number | null;
|
||||
consolidado: boolean;
|
||||
}) => Promise<void>; // 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<void>;
|
||||
onCancel?: () => void; // onCancel sigue acá por si lo necesito en otros selectores
|
||||
isLoading?: boolean;
|
||||
apiErrorMessage?: string | null;
|
||||
}
|
||||
|
||||
const SeleccionaReporteExistenciaPapel: React.FC<SeleccionaReporteExistenciaPapelProps> = ({
|
||||
@@ -24,7 +24,12 @@ const SeleccionaReporteExistenciaPapel: React.FC<SeleccionaReporteExistenciaPape
|
||||
apiErrorMessage
|
||||
}) => {
|
||||
const [fechaDesde, setFechaDesde] = useState<string>(new Date().toISOString().split('T')[0]);
|
||||
const [fechaHasta, setFechaHasta] = useState<string>(new Date().toISOString().split('T')[0]);
|
||||
const [fechaHasta, setFechaHasta] = useState<string>(() => {
|
||||
// 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<number | string>('');
|
||||
const [consolidado, setConsolidado] = useState<boolean>(false);
|
||||
|
||||
@@ -49,18 +54,39 @@ const SeleccionaReporteExistenciaPapel: React.FC<SeleccionaReporteExistenciaPape
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// 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<SeleccionaReporteExistenciaPape
|
||||
label="Fecha Desde"
|
||||
type="date"
|
||||
value={fechaDesde}
|
||||
onChange={(e) => { 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<SeleccionaReporteExistenciaPape
|
||||
helperText={localErrors.fechaHasta}
|
||||
disabled={isLoading}
|
||||
InputLabelProps={{ shrink: true }}
|
||||
inputProps={{
|
||||
min: getMinFechaHasta()
|
||||
}}
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
@@ -126,7 +155,7 @@ const SeleccionaReporteExistenciaPapel: React.FC<SeleccionaReporteExistenciaPape
|
||||
<Select
|
||||
labelId="planta-select-label"
|
||||
label="Planta"
|
||||
value={consolidado ? '' : idPlanta} // Limpiar selección si es consolidado
|
||||
value={consolidado ? '' : idPlanta}
|
||||
onChange={(e) => { setIdPlanta(e.target.value as number); setLocalErrors(p => ({ ...p, idPlanta: null })); }}
|
||||
>
|
||||
<MenuItem value="" disabled><em>{consolidado ? 'N/A (Consolidado)' : 'Seleccione una planta'}</em></MenuItem>
|
||||
|
||||
Reference in New Issue
Block a user