Se modifico datastage

This commit is contained in:
2025-08-20 16:49:08 -06:00
parent b0b7114386
commit 6eea8c8ac1

View File

@@ -60,10 +60,8 @@ function RegistrosCargadosModal({ open, onClose, registros }) {
} }
// Procesar datastage (adaptado para mostrar registros cargados) // Procesar datastage (adaptado para mostrar registros cargados)
// Recibe setEnProcesoId como argumento para manejar el estado desde el componente async function procesarDatastage(item, setDatastages, setSuccess, setError, setRegistrosCargados, setShowRegistrosModal) {
async function procesarDatastage(item, setDatastages, setSuccess, setError, setRegistrosCargados, setShowRegistrosModal, setEnProcesoId) {
try { try {
setEnProcesoId(item.id);
const url = `${import.meta.env.VITE_EFC_API_URL}/datastage/datastages/${item.id}/procesar/`; const url = `${import.meta.env.VITE_EFC_API_URL}/datastage/datastages/${item.id}/procesar/`;
const body = { const body = {
organizacion: item.organizacion, organizacion: item.organizacion,
@@ -75,23 +73,26 @@ async function procesarDatastage(item, setDatastages, setSuccess, setError, setR
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body) body: JSON.stringify(body)
}); });
const data = await res.json();
if (res.status === 200) { if (res.status === 200) {
// PATCH para marcar como procesado en backend // PATCH para marcar como procesado en backend
await patchProcesadoTrue(item); await patchProcesadoTrue(item);
setDatastages(prev => prev.map(d => d.id === item.id ? { ...d, procesado: true } : d)); setDatastages(prev => prev.map(d => d.id === item.id ? { ...d, procesado: true } : d));
setSuccess('Procesado correctamente'); // Mostrar el mensaje con task_id y detail si existen
const data = await res.json(); if (data && data.task_id && data.detail) {
setSuccess(`Procesamiento iniciado.\nTask ID: ${data.task_id}\n${data.detail}`);
} else {
setSuccess('Procesado correctamente');
}
if (data && data.registros_cargados) { if (data && data.registros_cargados) {
setRegistrosCargados(data.registros_cargados); setRegistrosCargados(data.registros_cargados);
setShowRegistrosModal(true); setShowRegistrosModal(true);
} }
} else { } else {
setError('No se pudo procesar el datastage'); setError(data && data.detail ? data.detail : 'No se pudo procesar el datastage');
} }
} catch (e) { } catch (e) {
setError('No se pudo procesar el datastage'); setError('No se pudo procesar el datastage');
} finally {
setEnProcesoId(null);
} }
} }
// Descarga autenticada de archivos datastage // Descarga autenticada de archivos datastage
@@ -132,8 +133,6 @@ export default function Datastage() {
// Animación header // Animación header
const [showAnimation, setShowAnimation] = useState(false); const [showAnimation, setShowAnimation] = useState(false);
const [hasAnimated, setHasAnimated] = useState(false); const [hasAnimated, setHasAnimated] = useState(false);
// Estado para mostrar mensaje "En proceso" por cada datastage
const [enProcesoId, setEnProcesoId] = useState(null);
useLayoutEffect(() => { setShowAnimation(true); }, []); useLayoutEffect(() => { setShowAnimation(true); }, []);
useEffect(() => { if (showAnimation && !hasAnimated) setTimeout(() => setHasAnimated(true), 800); }, [showAnimation, hasAnimated]); useEffect(() => { if (showAnimation && !hasAnimated) setTimeout(() => setHasAnimated(true), 800); }, [showAnimation, hasAnimated]);
@@ -186,6 +185,46 @@ export default function Datastage() {
setLoading(false); setLoading(false);
}; };
// Editar
const handleEdit = async (e) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
const fd = new FormData();
fd.append('contribuyente', form.contribuyente);
if (form.archivo) fd.append('archivo', form.archivo);
await patchFormDataWithAuth(`${import.meta.env.VITE_EFC_API_URL}/datastage/datastages/${editingId}/`, fd);
setForm({ archivo: null, contribuyente: '' });
setEditingId(null);
setShowEditModal(false);
setSuccess('Datastage actualizado exitosamente');
setShowSuccessModal(true);
load();
} catch (e) {
setError(e.message);
}
setLoading(false);
};
// Eliminar
const handleDelete = async () => {
if (!deleteId) return;
setLoading(true);
setError(null);
try {
await deleteDatastage(deleteId);
if (selected && selected.id === deleteId) setSelected(null);
setShowDeleteModal(false);
setSuccess('Datastage eliminado exitosamente');
setShowSuccessModal(true);
load();
} catch (e) {
setError(e.message);
}
setLoading(false);
};
// Abrir modal de edición // Abrir modal de edición
const openEditModal = (item) => { const openEditModal = (item) => {
setForm({ archivo: null, contribuyente: item.contribuyente }); setForm({ archivo: null, contribuyente: item.contribuyente });
@@ -369,18 +408,14 @@ export default function Datastage() {
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /></svg> <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /></svg>
</button> </button>
<button <button
onClick={() => procesarDatastage(item, setDatastages, setSuccess, setError, setRegistrosCargados, setShowRegistrosModal, setEnProcesoId)} onClick={() => procesarDatastage(item, setDatastages, setSuccess, setError, setRegistrosCargados, setShowRegistrosModal)}
className={`inline-flex items-center justify-center w-24 h-9 rounded-lg border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-1 text-sm font-semibold ${item.procesado ? 'bg-gray-100 border-gray-200 cursor-not-allowed opacity-50' : enProcesoId === item.id ? 'bg-yellow-50 border-yellow-200 text-yellow-700 cursor-wait' : 'bg-green-50 border-green-200 hover:bg-green-100 hover:border-green-300 focus:ring-green-500 cursor-pointer'}`} className={`inline-flex items-center justify-center w-9 h-9 rounded-lg border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-1 ${item.procesado ? 'bg-gray-100 border-gray-200 cursor-not-allowed opacity-50' : 'bg-green-50 border-green-200 hover:bg-green-100 hover:border-green-300 focus:ring-green-500 cursor-pointer'}`}
title={item.procesado ? 'Ya procesado' : enProcesoId === item.id ? 'En proceso' : 'Procesar'} title={item.procesado ? 'Ya procesado' : 'Procesar'}
disabled={item.procesado || enProcesoId === item.id} disabled={item.procesado}
> >
{item.procesado ? ( <svg className="w-5 h-5 text-green-600" fill="currentColor" viewBox="0 0 24 24">
<span className="flex items-center gap-1"><svg className="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>Procesado</span> <path d="M8 5v14l11-7z"/>
) : enProcesoId === item.id ? ( </svg>
<span className="flex items-center gap-1"><svg className="w-5 h-5 animate-spin text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle><path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"></path></svg>En proceso...</span>
) : (
<span className="flex items-center gap-1"><svg className="w-5 h-5 text-green-600" fill="currentColor" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>Procesar</span>
)}
</button> </button>
</td> </td>
</tr> </tr>
@@ -450,18 +485,14 @@ export default function Datastage() {
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /></svg> <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /></svg>
</button> </button>
<button <button
onClick={() => procesarDatastage(item, setDatastages, setSuccess, setError, setRegistrosCargados, setShowRegistrosModal, setEnProcesoId)} onClick={() => procesarDatastage(item, setDatastages, setSuccess, setError, setRegistrosCargados, setShowRegistrosModal)}
className={`inline-flex items-center justify-center w-24 h-9 rounded-lg border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-1 text-sm font-semibold ${item.procesado ? 'bg-gray-100 border-gray-200 cursor-not-allowed opacity-50' : enProcesoId === item.id ? 'bg-yellow-50 border-yellow-200 text-yellow-700 cursor-wait' : 'bg-green-50 border-green-200 hover:bg-green-100 hover:border-green-300 focus:ring-green-500 cursor-pointer'}`} className={`inline-flex items-center justify-center w-9 h-9 rounded-lg border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-1 ${item.procesado ? 'bg-gray-100 border-gray-200 cursor-not-allowed opacity-50' : 'bg-green-50 border-green-200 hover:bg-green-100 hover:border-green-300 focus:ring-green-500 cursor-pointer'}`}
title={item.procesado ? 'Ya procesado' : enProcesoId === item.id ? 'En proceso' : 'Procesar'} title={item.procesado ? 'Ya procesado' : 'Procesar'}
disabled={item.procesado || enProcesoId === item.id} disabled={item.procesado}
> >
{item.procesado ? ( <svg className="w-5 h-5 text-green-600" fill="currentColor" viewBox="0 0 24 24">
<span className="flex items-center gap-1"><svg className="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>Procesado</span> <path d="M8 5v14l11-7z"/>
) : enProcesoId === item.id ? ( </svg>
<span className="flex items-center gap-1"><svg className="w-5 h-5 animate-spin text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle><path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"></path></svg>En proceso...</span>
) : (
<span className="flex items-center gap-1"><svg className="w-5 h-5 text-green-600" fill="currentColor" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>Procesar</span>
)}
</button> </button>
</div> </div>
</div> </div>