Implementación AnomalIA - Fix de dropdowns y permisos.
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 5m17s

This commit is contained in:
2025-06-30 15:26:14 -03:00
parent 95aa09d62a
commit c96d259892
59 changed files with 1430 additions and 337 deletions

View File

@@ -16,13 +16,14 @@ import empresaService from '../../services/Distribucion/empresaService';
import type { ControlDevolucionesDto } from '../../models/dtos/Distribucion/ControlDevolucionesDto';
import type { CreateControlDevolucionesDto } from '../../models/dtos/Distribucion/CreateControlDevolucionesDto';
import type { UpdateControlDevolucionesDto } from '../../models/dtos/Distribucion/UpdateControlDevolucionesDto';
import type { EmpresaDto } from '../../models/dtos/Distribucion/EmpresaDto';
import type { EmpresaDropdownDto } from '../../models/dtos/Distribucion/EmpresaDropdownDto';
import ControlDevolucionesFormModal from '../../components/Modals/Distribucion/ControlDevolucionesFormModal';
import { usePermissions } from '../../hooks/usePermissions';
import axios from 'axios';
const GestionarControlDevolucionesPage: React.FC = () => {
// ... (estados sin cambios) ...
const [controles, setControles] = useState<ControlDevolucionesDto[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
@@ -32,8 +33,8 @@ const GestionarControlDevolucionesPage: React.FC = () => {
const [filtroFechaHasta, setFiltroFechaHasta] = useState<string>(new Date().toISOString().split('T')[0]);
const [filtroIdEmpresa, setFiltroIdEmpresa] = useState<number | string>('');
const [empresas, setEmpresas] = useState<EmpresaDto[]>([]);
const [loadingFiltersDropdown, setLoadingFiltersDropdown] = useState(false);
const [empresas, setEmpresas] = useState<EmpresaDropdownDto[]>([]);
const [loadingFiltersDropdown, setLoadingFiltersDropdown] = useState(true); // << CAMBIO: Iniciar en true
const [modalOpen, setModalOpen] = useState(false);
const [editingControl, setEditingControl] = useState<ControlDevolucionesDto | null>(null);
@@ -47,42 +48,58 @@ const GestionarControlDevolucionesPage: React.FC = () => {
const puedeVer = isSuperAdmin || tienePermiso("CD001");
const puedeCrear = isSuperAdmin || tienePermiso("CD002");
const puedeModificar = isSuperAdmin || tienePermiso("CD003");
const puedeEliminar = isSuperAdmin || tienePermiso("CD003");
// << CAMBIO: Permiso de eliminar debe ser diferente
const puedeEliminar = isSuperAdmin || tienePermiso("CD004"); // Asumiendo que CD004 es para eliminar
// CORREGIDO: Función para formatear la fecha
// ... (formatDate sin cambios) ...
const formatDate = (dateString?: string | null): string => {
if (!dateString) return '-';
// Asumimos que dateString viene del backend como "YYYY-MM-DD" o "YYYY-MM-DDTHH:mm:ss..."
const datePart = dateString.split('T')[0]; // Tomar solo la parte YYYY-MM-DD
const datePart = dateString.split('T')[0];
const parts = datePart.split('-');
if (parts.length === 3) {
// parts[0] = YYYY, parts[1] = MM, parts[2] = DD
return `${parts[2]}/${parts[1]}/${parts[0]}`; // Formato DD/MM/YYYY
return `${parts[2]}/${parts[1]}/${parts[0]}`;
}
return datePart; // Fallback si el formato no es el esperado
return datePart;
};
const fetchFiltersDropdownData = useCallback(async () => {
// << CAMBIO: Guardián de permisos para la carga de filtros
if (!puedeVer) {
setError("No tiene permiso para ver esta sección.");
setLoading(false); // Detiene el spinner principal
setLoadingFiltersDropdown(false); // Detiene el spinner de filtros
return;
}
setLoadingFiltersDropdown(true);
try {
const empresasData = await empresaService.getAllEmpresas();
const empresasData = await empresaService.getEmpresasDropdown();
setEmpresas(empresasData);
} catch (err) {
console.error("Error cargando empresas para filtro:", err);
// El error principal se manejará en cargarControles si también falla
setError("Error al cargar opciones de filtro.");
} finally {
setLoadingFiltersDropdown(false);
}
}, []);
}, [puedeVer]); // << CAMBIO: Añadir `puedeVer` como dependencia
useEffect(() => { fetchFiltersDropdownData(); }, [fetchFiltersDropdownData]);
useEffect(() => {
fetchFiltersDropdownData();
}, [fetchFiltersDropdownData]);
const cargarControles = useCallback(async () => {
// El guardián aquí ya estaba y es correcto.
if (!puedeVer) {
setError("No tiene permiso para ver esta sección."); setLoading(false); return;
// Si ya se estableció el error en el fetch de filtros, no lo sobrescribimos.
if (!error) setError("No tiene permiso para ver esta sección.");
setLoading(false);
return;
}
setLoading(true); setError(null); setApiErrorMessage(null);
setLoading(true);
setError(null);
setApiErrorMessage(null);
try {
const params = {
fechaDesde: filtroFechaDesde || null,
@@ -92,19 +109,27 @@ const GestionarControlDevolucionesPage: React.FC = () => {
const data = await controlDevolucionesService.getAllControlesDevoluciones(params);
setControles(data);
} catch (err) {
console.error(err); setError('Error al cargar los controles de devoluciones.');
} finally { setLoading(false); }
}, [puedeVer, filtroFechaDesde, filtroFechaHasta, filtroIdEmpresa]);
console.error(err);
setError('Error al cargar los controles de devoluciones.');
} finally {
setLoading(false);
}
}, [puedeVer, filtroFechaDesde, filtroFechaHasta, filtroIdEmpresa, error]); // << CAMBIO: Añadido `error` a dependencias
useEffect(() => { cargarControles(); }, [cargarControles]);
useEffect(() => {
// Solo cargar controles si los filtros se han cargado (o intentado cargar)
if (!loadingFiltersDropdown) {
cargarControles();
}
}, [cargarControles, loadingFiltersDropdown]); // << CAMBIO: Depende de la carga de filtros
// ... (resto de los handlers sin cambios) ...
const handleOpenModal = (item?: ControlDevolucionesDto) => {
setEditingControl(item || null); setApiErrorMessage(null); setModalOpen(true);
};
const handleCloseModal = () => {
setModalOpen(false); setEditingControl(null);
};
const handleSubmitModal = async (data: CreateControlDevolucionesDto | UpdateControlDevolucionesDto, idControl?: number) => {
setApiErrorMessage(null);
try {
@@ -119,7 +144,6 @@ const GestionarControlDevolucionesPage: React.FC = () => {
setApiErrorMessage(message); throw err;
}
};
const handleDelete = async (idControl: number) => {
if (window.confirm(`¿Seguro de eliminar este control de devoluciones (ID: ${idControl})?`)) {
setApiErrorMessage(null);
@@ -133,26 +157,35 @@ const GestionarControlDevolucionesPage: React.FC = () => {
}
handleMenuClose();
};
const handleMenuOpen = (event: React.MouseEvent<HTMLElement>, item: ControlDevolucionesDto) => {
setAnchorEl(event.currentTarget); setSelectedRow(item);
};
const handleMenuClose = () => {
setAnchorEl(null); setSelectedRow(null);
};
const handleChangePage = (_event: unknown, newPage: number) => setPage(newPage);
const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
setRowsPerPage(parseInt(event.target.value, 25)); setPage(0);
setRowsPerPage(parseInt(event.target.value, 10)); setPage(0);
};
// displayData ahora usará la 'controles' directamente, el formato se aplica en el renderizado
const displayData = controles.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
if (!loading && !puedeVer && !loadingFiltersDropdown) return <Box sx={{ p: 2 }}><Alert severity="error">{error || "Acceso denegado."}</Alert></Box>;
// Si no tiene permiso, muestra solo la alerta y nada más.
if (!puedeVer) {
return (
<Box sx={{ p: 2 }}>
<Alert severity="error">
{error || "No tiene permiso para acceder a esta sección."}
</Alert>
</Box>
);
}
return (
<Box sx={{ p: 1 }}>
<Typography variant="h5" gutterBottom>Control de Devoluciones a Empresa</Typography>
{/* El resto del JSX se renderizará solo si 'puedeVer' es true */}
<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 }}>
@@ -169,12 +202,12 @@ const GestionarControlDevolucionesPage: React.FC = () => {
{puedeCrear && (<Button variant="contained" startIcon={<AddIcon />} onClick={() => handleOpenModal()}>Registrar Control</Button>)}
</Paper>
{loading && <Box sx={{ display: 'flex', justifyContent: 'center', my: 2 }}><CircularProgress /></Box>}
{(loading || loadingFiltersDropdown) && <Box sx={{ display: 'flex', justifyContent: 'center', my: 2 }}><CircularProgress /></Box>}
{error && !loading && <Alert severity="error" sx={{ my: 2 }}>{error}</Alert>}
{apiErrorMessage && <Alert severity="error" sx={{ my: 2 }}>{apiErrorMessage}</Alert>}
{!loading && !error && puedeVer && (
<TableContainer component={Paper} sx={{ maxHeight: 'calc(100vh - 240px)' }}> {/* Ajusta maxHeight según sea necesario */}
{!loading && !loadingFiltersDropdown && !error && (
<TableContainer component={Paper} sx={{ maxHeight: 'calc(100vh - 300px)' }}> {/* Ajusta maxHeight */}
<Table stickyHeader size="small">
<TableHead><TableRow>
<TableCell>Fecha</TableCell><TableCell>Empresa</TableCell>
@@ -186,7 +219,7 @@ const GestionarControlDevolucionesPage: React.FC = () => {
</TableRow></TableHead>
<TableBody>
{displayData.length === 0 ? (
<TableRow><TableCell colSpan={puedeModificar || puedeEliminar ? 7 : 6} align="center">No se encontraron controles.</TableCell></TableRow>
<TableRow><TableCell colSpan={puedeModificar || puedeEliminar ? 7 : 6} align="center">No se encontraron controles con los filtros aplicados.</TableCell></TableRow>
) : (
displayData.map((c) => (
<TableRow key={c.idControl} hover>
@@ -217,7 +250,10 @@ const GestionarControlDevolucionesPage: React.FC = () => {
{puedeModificar && selectedRow && (
<MenuItem onClick={() => { handleOpenModal(selectedRow); handleMenuClose(); }}><EditIcon fontSize="small" sx={{ mr: 1 }} /> Modificar</MenuItem>)}
{puedeEliminar && selectedRow && (
<MenuItem onClick={() => handleDelete(selectedRow.idControl)}><DeleteIcon fontSize="small" sx={{ mr: 1 }} /> Eliminar</MenuItem>)}
<MenuItem onClick={() => { if (selectedRow) handleDelete(selectedRow.idControl) }}>
<DeleteIcon fontSize="small" sx={{ mr: 1 }} /> Eliminar
</MenuItem>
)}
</Menu>
<ControlDevolucionesFormModal

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react'; // << Añadido useMemo
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import {
Box, Typography, TextField, Button, Paper, IconButton, Menu, MenuItem, Chip,
Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TablePagination,
@@ -21,7 +21,7 @@ import canillaService from '../../services/Distribucion/canillaService';
import type { EntradaSalidaCanillaDto } from '../../models/dtos/Distribucion/EntradaSalidaCanillaDto';
import type { UpdateEntradaSalidaCanillaDto } from '../../models/dtos/Distribucion/UpdateEntradaSalidaCanillaDto';
import type { PublicacionDropdownDto } from '../../models/dtos/Distribucion/PublicacionDropdownDto';
import type { CanillaDto } from '../../models/dtos/Distribucion/CanillaDto';
import type { CanillaDropdownDto } from '../../models/dtos/Distribucion/CanillaDropdownDto';
import type { LiquidarMovimientosCanillaRequestDto } from '../../models/dtos/Distribucion/LiquidarMovimientosCanillaDto';
import EntradaSalidaCanillaFormModal from '../../components/Modals/Distribucion/EntradaSalidaCanillaFormModal';
@@ -44,8 +44,8 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
const [loadingTicketPdf, setLoadingTicketPdf] = useState(false);
const [publicaciones, setPublicaciones] = useState<PublicacionDropdownDto[]>([]);
const [destinatariosDropdown, setDestinatariosDropdown] = useState<CanillaDto[]>([]);
const [loadingFiltersDropdown, setLoadingFiltersDropdown] = useState(false);
const [destinatariosDropdown, setDestinatariosDropdown] = useState<CanillaDropdownDto[]>([]);
const [loadingFiltersDropdown, setLoadingFiltersDropdown] = useState(false)
const [modalOpen, setModalOpen] = useState(false);
const [editingMovimiento, setEditingMovimiento] = useState<EntradaSalidaCanillaDto | null>(null);
@@ -81,29 +81,40 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
};
useEffect(() => {
const fetchPublicaciones = async () => {
const fetchDropdownData = async () => {
if (!puedeVer) {
setError("No tiene permiso para ver esta sección.");
setLoading(false); // Detiene el spinner principal
setLoadingFiltersDropdown(false); // Detiene el spinner de los filtros
return;
}
setLoadingFiltersDropdown(true);
setError(null);
try {
const pubsData = await publicacionService.getPublicacionesForDropdown(true);
setPublicaciones(pubsData);
// La carga de destinatarios se hará en el otro useEffect
} catch (err) {
console.error("Error cargando publicaciones para filtro:",err);
console.error("Error cargando publicaciones para filtro:", err);
setError("Error al cargar publicaciones.");
} finally {
// No setLoadingFiltersDropdown(false) acá, esperar a la otra carga
// La carga finaliza cuando se cargan los destinatarios también.
}
};
fetchPublicaciones();
}, []);
fetchDropdownData();
}, [puedeVer]); // << CAMBIO: Añadir `puedeVer` como dependencia
const fetchDestinatariosParaDropdown = useCallback(async () => {
if (!puedeVer) { return; }
setLoadingFiltersDropdown(true);
setFiltroIdCanillitaSeleccionado('');
setDestinatariosDropdown([]);
setError(null);
try {
const esAccionistaFilter = filtroTipoDestinatario === 'accionistas';
const data = await canillaService.getAllCanillas(undefined, undefined, true, esAccionistaFilter);
const data = await canillaService.getAllDropdownCanillas(true, esAccionistaFilter);
setDestinatariosDropdown(data);
} catch (err) {
console.error("Error cargando destinatarios para filtro:", err);
@@ -111,21 +122,23 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
} finally {
setLoadingFiltersDropdown(false);
}
}, [filtroTipoDestinatario]);
}, [filtroTipoDestinatario, puedeVer]);
useEffect(() => {
fetchDestinatariosParaDropdown();
}, [fetchDestinatariosParaDropdown]);
const cargarMovimientos = useCallback(async () => {
if (!puedeVer) { setError("No tiene permiso para ver esta sección."); setLoading(false); return; }
if (!puedeVer) {
setError("No tiene permiso para ver esta sección.");
setLoading(false);
return;
}
if (!filtroFecha || !filtroIdCanillitaSeleccionado) {
if (loading) setLoading(false);
setMovimientos([]);
return;
}
setLoading(true); setError(null); setApiErrorMessage(null);
try {
const params = {
@@ -148,6 +161,7 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
}
}, [puedeVer, filtroFecha, filtroIdPublicacion, filtroIdCanillitaSeleccionado]);
useEffect(() => {
if (filtroFecha && filtroIdCanillitaSeleccionado) {
cargarMovimientos();
@@ -156,8 +170,7 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
if (loading) setLoading(false);
}
}, [cargarMovimientos, filtroFecha, filtroIdCanillitaSeleccionado]);
const handleOpenModal = (item?: EntradaSalidaCanillaDto) => {
if (!puedeCrear && !item) {
setApiErrorMessage("No tiene permiso para registrar nuevos movimientos.");
@@ -195,7 +208,6 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
}
handleMenuClose();
};
const handleMenuOpen = (event: React.MouseEvent<HTMLElement>, item: EntradaSalidaCanillaDto) => {
event.currentTarget.setAttribute('data-rowid', item.idParte.toString());
setAnchorEl(event.currentTarget);
@@ -258,17 +270,15 @@ 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(); // Recargar la lista para reflejar el estado liquidado
await cargarMovimientos();
// 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,
movimientoParaTicket.fecha, // Usar la fecha del movimiento
movimientoParaTicket.fecha,
false
);
} else if (movimientoParaTicket && movimientoParaTicket.canillaEsAccionista) {
@@ -328,7 +338,6 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
} finally { setLoadingTicketPdf(false); }
}, []);
const handleChangePage = (_event: unknown, newPage: number) => setPage(newPage);
const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
setRowsPerPage(parseInt(event.target.value, 10)); setPage(0);
@@ -339,8 +348,14 @@ const GestionarEntradasSalidasCanillaPage: React.FC = () => {
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>;
if (!puedeVer) {
return (
<Box sx={{ p: 2 }}>
<Alert severity="error">
{error || "No tiene permiso para acceder a esta sección."}
</Alert>
</Box>
);
}
const numSelectedToLiquidate = selectedIdsParaLiquidar.size;
@@ -352,7 +367,6 @@ 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 }}

View File

@@ -17,8 +17,8 @@ import distribuidorService from '../../services/Distribucion/distribuidorService
import type { EntradaSalidaDistDto } from '../../models/dtos/Distribucion/EntradaSalidaDistDto';
import type { CreateEntradaSalidaDistDto } from '../../models/dtos/Distribucion/CreateEntradaSalidaDistDto';
import type { UpdateEntradaSalidaDistDto } from '../../models/dtos/Distribucion/UpdateEntradaSalidaDistDto';
import type { PublicacionDto } from '../../models/dtos/Distribucion/PublicacionDto';
import type { DistribuidorDto } from '../../models/dtos/Distribucion/DistribuidorDto';
import type { PublicacionDropdownDto } from '../../models/dtos/Distribucion/PublicacionDropdownDto';
import type { DistribuidorDropdownDto } from '../../models/dtos/Distribucion/DistribuidorDropdownDto';
import EntradaSalidaDistFormModal from '../../components/Modals/Distribucion/EntradaSalidaDistFormModal';
import { usePermissions } from '../../hooks/usePermissions';
@@ -36,8 +36,8 @@ const GestionarEntradasSalidasDistPage: React.FC = () => {
const [filtroIdDistribuidor, setFiltroIdDistribuidor] = useState<number | string>('');
const [filtroTipoMov, setFiltroTipoMov] = useState<'Salida' | 'Entrada' | ''>('');
const [publicaciones, setPublicaciones] = useState<PublicacionDto[]>([]);
const [distribuidores, setDistribuidores] = useState<DistribuidorDto[]>([]);
const [publicaciones, setPublicaciones] = useState<PublicacionDropdownDto[]>([]);
const [distribuidores, setDistribuidores] = useState<DistribuidorDropdownDto[]>([]);
const [loadingFiltersDropdown, setLoadingFiltersDropdown] = useState(false);
const [modalOpen, setModalOpen] = useState(false);
@@ -69,8 +69,8 @@ const GestionarEntradasSalidasDistPage: React.FC = () => {
setLoadingFiltersDropdown(true);
try {
const [pubsData, distData] = await Promise.all([
publicacionService.getAllPublicaciones(undefined, undefined, true),
distribuidorService.getAllDistribuidores()
publicacionService.getPublicacionesForDropdown(true),
distribuidorService.getAllDistribuidoresDropdown()
]);
setPublicaciones(pubsData);
setDistribuidores(distData);

View File

@@ -16,8 +16,8 @@ import otroDestinoService from '../../services/Distribucion/otroDestinoService';
import type { SalidaOtroDestinoDto } from '../../models/dtos/Distribucion/SalidaOtroDestinoDto';
import type { CreateSalidaOtroDestinoDto } from '../../models/dtos/Distribucion/CreateSalidaOtroDestinoDto';
import type { UpdateSalidaOtroDestinoDto } from '../../models/dtos/Distribucion/UpdateSalidaOtroDestinoDto';
import type { PublicacionDto } from '../../models/dtos/Distribucion/PublicacionDto';
import type { OtroDestinoDto } from '../../models/dtos/Distribucion/OtroDestinoDto';
import type { PublicacionDropdownDto } from '../../models/dtos/Distribucion/PublicacionDropdownDto';
import type { OtroDestinoDropdownDto } from '../../models/dtos/Distribucion/OtroDestinoDropdownDto';
import SalidaOtroDestinoFormModal from '../../components/Modals/Distribucion/SalidaOtroDestinoFormModal';
import { usePermissions } from '../../hooks/usePermissions';
@@ -34,8 +34,8 @@ const GestionarSalidasOtrosDestinosPage: React.FC = () => {
const [filtroIdPublicacion, setFiltroIdPublicacion] = useState<number | string>('');
const [filtroIdDestino, setFiltroIdDestino] = useState<number | string>('');
const [publicaciones, setPublicaciones] = useState<PublicacionDto[]>([]);
const [otrosDestinos, setOtrosDestinos] = useState<OtroDestinoDto[]>([]);
const [publicaciones, setPublicaciones] = useState<PublicacionDropdownDto[]>([]);
const [otrosDestinos, setOtrosDestinos] = useState<OtroDestinoDropdownDto[]>([]);
const [loadingFiltersDropdown, setLoadingFiltersDropdown] = useState(false);
const [modalOpen, setModalOpen] = useState(false);
@@ -68,8 +68,8 @@ const GestionarSalidasOtrosDestinosPage: React.FC = () => {
setLoadingFiltersDropdown(true);
try {
const [pubsData, destinosData] = await Promise.all([
publicacionService.getAllPublicaciones(undefined, undefined, true),
otroDestinoService.getAllOtrosDestinos()
publicacionService.getPublicacionesForDropdown(true),
otroDestinoService.getAllDropdownOtrosDestinos()
]);
setPublicaciones(pubsData);
setOtrosDestinos(destinosData);