+ <>
+
+
@@ -949,7 +1221,7 @@ function AutoCorregirResultModal({ modal, onClose, onConsultar, consultando, onE
-
+ >
);
}
@@ -959,6 +1231,7 @@ function Auditor() {
const [loading, setLoading] = useState(false);
const [loadingTable, setLoadingTable] = useState(false);
const isFirstLoad = useRef(true);
+ const rowDropdownRef = useRef(null);
const [error, setError] = useState('');
const [pedimentos, setPedimentos] = useState([]);
const [showInstructions, setShowInstructions] = useState(false);
@@ -991,6 +1264,20 @@ function Auditor() {
const [analizandoIndividual, setAnalizandoIndividual] = useState(null); // pedimento_id en curso, o null
const [xmlData, setXmlData] = useState(null);
+ // Estados para auditorías de integridad (globales y por pedimento)
+ const [auditandoIntegridadPartidas, setAuditandoIntegridadPartidas] = useState(false);
+ const [auditandoIntegridadEdocuments, setAuditandoIntegridadEdocuments] = useState(false);
+ const [auditandoIntegridadCoves, setAuditandoIntegridadCoves] = useState(false);
+ const [auditandoIntegridadRemesa, setAuditandoIntegridadRemesa] = useState(false);
+ const [procesandoIntegridadPartida, setProcesandoIntegridadPartida] = useState(null);
+ const [procesandoIntegridadEdocument, setProcesandoIntegridadEdocument] = useState(null);
+ const [procesandoIntegridadCoves, setProcesandoIntegridadCoves] = useState(null);
+ const [procesandoIntegridadRemesa, setProcesandoIntegridadRemesa] = useState(null);
+
+ // Estados para correcciones de integridad
+ const [corrigiendoIntegridadGlobal, setCorrigiendoIntegridadGlobal] = useState(false);
+ const [corrigiendoIntegridadPedimento, setCorrigiendoIntegridadPedimento] = useState(null);
+
// Estados para modal de preview
const [previewOpen, setPreviewOpen] = useState(false);
const [previewUrl, setPreviewUrl] = useState('');
@@ -1010,6 +1297,16 @@ function Auditor() {
const [detalleModalXml, setDetalleModalXml] = useState(null);
+ // Estados para paneles deslizantes y dropdowns
+ const [auditResultClosing, setAuditResultClosing] = useState(false);
+ const [globalAuditClosing, setGlobalAuditClosing] = useState(false);
+ const [autoCorregirClosing, setAutoCorregirClosing] = useState(false);
+ const [openGlobalDropdown, setOpenGlobalDropdown] = useState(null);
+ const [openRowDropdown, setOpenRowDropdown] = useState(null);
+ const [rowDropdownPos, setRowDropdownPos] = useState(null);
+ const [auditPanelDetalles, setAuditPanelDetalles] = useState(null);
+ const [cargandoDetallesPeticion, setCargandoDetallesPeticion] = useState(false);
+
// Agrega este estado cerca de los otros estados
const [activeVista, setActiveVista] = useState(null); // 'pc', 'rm', 'pt', 'ac', 'cove', 'ac_cove', 'edoc'
@@ -1068,6 +1365,8 @@ function Auditor() {
label: task.label,
organizacion_id: task.organizacion_id,
task_id: task.task_id,
+ procesamiento: task.procesamiento ?? null,
+ tipo_integridad: task.tipo_integridad ?? null,
};
if (task.resultado) {
@@ -1177,7 +1476,7 @@ function Auditor() {
throw new Error(await extractApiError(response));
}
const data = await response.json();
- addTask({ task_id: data.task_id, label: 'Acuses', organizacion_id: organizacionId });
+ addTask({ task_id: data.task_id, label: 'Acuses', organizacion_id: organizacionId, procesamiento: 'acuses' });
setGlobalAuditModal({ label: 'Acuses', procesamiento: 'acuses', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
} catch (error) {
showMessage(error.message || 'Error al iniciar la auditoría de acuses', 'error');
@@ -1202,7 +1501,7 @@ function Auditor() {
throw new Error(await extractApiError(response));
}
const data = await response.json();
- addTask({ task_id: data.task_id, label: 'EDocuments', organizacion_id: organizacionId });
+ addTask({ task_id: data.task_id, label: 'EDocuments', organizacion_id: organizacionId, procesamiento: 'edocs' });
setGlobalAuditModal({ label: 'EDocuments', procesamiento: 'edocs', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
} catch (error) {
showMessage(error.message || 'Error al iniciar la auditoría de EDocuments', 'error');
@@ -1227,7 +1526,7 @@ function Auditor() {
throw new Error(await extractApiError(response));
}
const data = await response.json();
- addTask({ task_id: data.task_id, label: 'Acuses de COVE', organizacion_id: organizacionId });
+ addTask({ task_id: data.task_id, label: 'Acuses de COVE', organizacion_id: organizacionId, procesamiento: 'acuse_coves' });
setGlobalAuditModal({ label: 'Acuses de COVE', procesamiento: 'acuse_coves', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
} catch (error) {
showMessage(error.message || 'Error al iniciar la auditoría de acuses cove', 'error');
@@ -1301,7 +1600,7 @@ function Auditor() {
}
const data = await response.json();
- addTask({ task_id: data.task_id, label: 'Remesas', organizacion_id: organizacionId });
+ addTask({ task_id: data.task_id, label: 'Remesas', organizacion_id: organizacionId, procesamiento: 'remesas' });
setGlobalAuditModal({ label: 'Remesas', procesamiento: 'remesas', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
} catch (error) {
@@ -1354,7 +1653,7 @@ function Auditor() {
}
const data = await response.json();
- addTask({ task_id: data.task_id, label: 'Partidas', organizacion_id: organizacionId });
+ addTask({ task_id: data.task_id, label: 'Partidas', organizacion_id: organizacionId, procesamiento: 'partidas' });
setGlobalAuditModal({ label: 'Partidas', procesamiento: 'partidas', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
} catch (error) {
@@ -1571,6 +1870,295 @@ const handleAuditarEDocumentPedimento = async (pedimentoId) => {
}
};
+ const handleAuditarIntegridadPartidas = async () => {
+ if (auditandoIntegridadPartidas) return;
+ try {
+ setAuditandoIntegridadPartidas(true);
+ const organizacionId = pedimentos[0]?.organizacion;
+ if (!organizacionId) throw new Error('No hay organización disponible');
+ const response = await postWithAuth(`${API_URL}/customs/auditor/auditar-integridad-partidas/`, { organizacion_id: organizacionId });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const data = await response.json();
+ addTask({ task_id: data.task_id, label: 'Integridad de Partidas', organizacion_id: organizacionId, tipo_integridad: 'partidas' });
+ setGlobalAuditModal({ label: 'Integridad de Partidas', tipo_integridad: 'partidas', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
+ } catch (error) {
+ showMessage(error.message || 'Error al auditar integridad de partidas', 'error');
+ } finally {
+ setAuditandoIntegridadPartidas(false);
+ }
+ };
+
+ const handleAuditarIntegridadEdocuments = async () => {
+ if (auditandoIntegridadEdocuments) return;
+ try {
+ setAuditandoIntegridadEdocuments(true);
+ const organizacionId = pedimentos[0]?.organizacion;
+ if (!organizacionId) throw new Error('No hay organización disponible');
+ const response = await postWithAuth(`${API_URL}/customs/auditor/auditar-integridad-edocuments/`, { organizacion_id: organizacionId });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const data = await response.json();
+ addTask({ task_id: data.task_id, label: 'Integridad de EDocuments', organizacion_id: organizacionId, tipo_integridad: 'edocuments' });
+ setGlobalAuditModal({ label: 'Integridad de EDocuments', tipo_integridad: 'edocuments', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
+ } catch (error) {
+ showMessage(error.message || 'Error al auditar integridad de edocuments', 'error');
+ } finally {
+ setAuditandoIntegridadEdocuments(false);
+ }
+ };
+
+ const handleAuditarIntegridadCoves = async () => {
+ if (auditandoIntegridadCoves) return;
+ try {
+ setAuditandoIntegridadCoves(true);
+ const organizacionId = pedimentos[0]?.organizacion;
+ if (!organizacionId) throw new Error('No hay organización disponible');
+ const response = await postWithAuth(`${API_URL}/customs/auditor/auditar-integridad-coves/`, { organizacion_id: organizacionId });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const data = await response.json();
+ addTask({ task_id: data.task_id, label: 'Integridad COVEs (PC XML)', organizacion_id: organizacionId, tipo_integridad: 'coves' });
+ setGlobalAuditModal({ label: 'Integridad COVEs (PC XML)', tipo_integridad: 'coves', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
+ } catch (error) {
+ showMessage(error.message || 'Error al auditar integridad de COVEs', 'error');
+ } finally {
+ setAuditandoIntegridadCoves(false);
+ }
+ };
+
+ const handleAuditarIntegridadRemesa = async () => {
+ if (auditandoIntegridadRemesa) return;
+ try {
+ setAuditandoIntegridadRemesa(true);
+ const organizacionId = pedimentos[0]?.organizacion;
+ if (!organizacionId) throw new Error('No hay organización disponible');
+ const response = await postWithAuth(`${API_URL}/customs/auditor/auditar-integridad-remesa/`, { organizacion_id: organizacionId });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const data = await response.json();
+ addTask({ task_id: data.task_id, label: 'Integridad Remesas', organizacion_id: organizacionId, tipo_integridad: 'remesa' });
+ setGlobalAuditModal({ label: 'Integridad Remesas', tipo_integridad: 'remesa', organizacion_id: organizacionId, task_id: data.task_id, resultado: null });
+ } catch (error) {
+ showMessage(error.message || 'Error al auditar integridad de remesas', 'error');
+ } finally {
+ setAuditandoIntegridadRemesa(false);
+ }
+ };
+
+ const handleAuditarIntegridadPartidasPedimento = async (pedimentoId) => {
+ if (procesandoIntegridadPartida) return;
+ const pedimento = pedimentos.find(p => p.id === pedimentoId);
+ try {
+ setProcesandoIntegridadPartida(pedimentoId);
+ const response = await postWithAuth(`${API_URL}/customs/auditor/auditar-integridad-partidas/pedimento/`, { pedimento_id: pedimentoId });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const raw = await response.json();
+ const completado = raw.estado === 'completado';
+ const data = {
+ estado: raw.estado,
+ auditoria_completa: completado,
+ mensaje: completado
+ ? `Partidas completas: ${raw.en_db} de ${raw.esperadas}`
+ : raw.estado === 'sin_datos_xml'
+ ? raw.mensaje
+ : `Faltan ${raw.faltantes} partida(s): DB tiene ${raw.en_db} de ${raw.esperadas}`,
+ resumen: (!completado && raw.estado !== 'sin_datos_xml') ? {
+ 'Esperadas (XML)': raw.esperadas,
+ 'En DB': raw.en_db,
+ 'Faltantes': raw.faltantes,
+ } : null,
+ };
+ setAuditResultModal({ tipo: 'int_pt', pedimento_id: pedimentoId, pedimento_app: pedimento?.pedimento_app, data });
+ } catch (error) {
+ showMessage(error.message || 'Error al auditar integridad de partidas', 'error');
+ } finally {
+ setProcesandoIntegridadPartida(null);
+ }
+ };
+
+ const handleAuditarIntegridadEdocumentsPedimento = async (pedimentoId) => {
+ if (procesandoIntegridadEdocument) return;
+ const pedimento = pedimentos.find(p => p.id === pedimentoId);
+ try {
+ setProcesandoIntegridadEdocument(pedimentoId);
+ const response = await postWithAuth(`${API_URL}/customs/auditor/auditar-integridad-edocuments/pedimento/`, { pedimento_id: pedimentoId });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const raw = await response.json();
+ const completado = raw.estado === 'completado';
+ const data = {
+ estado: raw.estado,
+ auditoria_completa: completado,
+ mensaje: completado
+ ? `EDocuments completos: ${raw.en_db} de ${raw.esperados_xml}`
+ : raw.estado === 'sin_xml'
+ ? 'No hay pedimento completo descargado para comparar'
+ : `Faltan ${raw.faltantes_en_db?.length ?? 0} edocument(s) en DB`,
+ resumen: (!completado && raw.estado !== 'sin_xml') ? {
+ 'Esperados (XML)': raw.esperados_xml,
+ 'En DB': raw.en_db,
+ 'Faltantes': raw.faltantes_en_db?.length ?? 0,
+ } : null,
+ pendientes: raw.faltantes_en_db ?? [],
+ };
+ setAuditResultModal({ tipo: 'int_edoc', pedimento_id: pedimentoId, pedimento_app: pedimento?.pedimento_app, data });
+ } catch (error) {
+ showMessage(error.message || 'Error al auditar integridad de edocuments', 'error');
+ } finally {
+ setProcesandoIntegridadEdocument(null);
+ }
+ };
+
+ const handleAuditarIntegridadCovesPedimento = async (pedimentoId) => {
+ if (procesandoIntegridadCoves) return;
+ const pedimento = pedimentos.find(p => p.id === pedimentoId);
+ try {
+ setProcesandoIntegridadCoves(pedimentoId);
+ const response = await postWithAuth(`${API_URL}/customs/auditor/auditar-integridad-coves/pedimento/`, { pedimento_id: pedimentoId });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const raw = await response.json();
+ const completado = raw.estado === 'completado';
+ const data = {
+ estado: raw.estado,
+ auditoria_completa: completado,
+ mensaje: completado
+ ? `COVEs íntegros: ${raw.coves_db} de ${raw.coves_xml} en XML`
+ : raw.estado === 'sin_xml'
+ ? 'No hay pedimento completo descargado para comparar'
+ : `Faltan ${raw.faltantes?.length ?? 0} COVE(s) en DB`,
+ resumen: completado
+ ? { 'COVEs en XML': raw.coves_xml, 'COVEs en DB': raw.coves_db }
+ : (!completado && raw.estado !== 'sin_xml') ? { 'COVEs en XML': raw.coves_xml, 'COVEs en DB': raw.coves_db } : null,
+ faltantes: raw.faltantes ?? [],
+ coves_xml: raw.coves_xml,
+ coves_db: raw.coves_db,
+ };
+ setAuditResultModal({ tipo: 'int_cove', pedimento_id: pedimentoId, pedimento_app: pedimento?.pedimento_app, data });
+ } catch (error) {
+ showMessage(error.message || 'Error al auditar integridad de COVEs', 'error');
+ } finally {
+ setProcesandoIntegridadCoves(null);
+ }
+ };
+
+ const handleAuditarIntegridadRemesaPedimento = async (pedimentoId) => {
+ if (procesandoIntegridadRemesa) return;
+ const pedimento = pedimentos.find(p => p.id === pedimentoId);
+ try {
+ setProcesandoIntegridadRemesa(pedimentoId);
+ const response = await postWithAuth(`${API_URL}/customs/auditor/auditar-integridad-remesa/pedimento/`, { pedimento_id: pedimentoId });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const raw = await response.json();
+ const completado = raw.estado === 'completado';
+ const sinRemesas = raw.estado === 'sin_remesas';
+ const data = {
+ estado: raw.estado,
+ auditoria_completa: completado || sinRemesas,
+ mensaje: completado
+ ? `Remesa íntegra: ${raw.coves_db} COVEs de remesa en DB`
+ : sinRemesas
+ ? raw.mensaje
+ : raw.estado === 'sin_xml'
+ ? raw.mensaje ?? 'No hay XML de remesa descargado'
+ : `Faltan ${raw.faltantes?.length ?? 0} COVE(s) de remesa en DB`,
+ resumen: completado
+ ? { 'COVEs en remesa': raw.total_en_remesa, 'COVEs en DB': raw.coves_db }
+ : (!completado && !sinRemesas && raw.estado !== 'sin_xml') ? { 'COVEs en remesa': raw.total_en_remesa, 'COVEs en DB': raw.coves_db } : null,
+ faltantes: raw.faltantes ?? [],
+ total_en_remesa: raw.total_en_remesa,
+ coves_db: raw.coves_db,
+ };
+ setAuditResultModal({ tipo: 'int_rm', pedimento_id: pedimentoId, pedimento_app: pedimento?.pedimento_app, data });
+ } catch (error) {
+ showMessage(error.message || 'Error al auditar integridad de remesa', 'error');
+ } finally {
+ setProcesandoIntegridadRemesa(null);
+ }
+ };
+
+ // Handler para corregir integridad de un pedimento específico
+ const handleCorregirIntegridadPedimento = async (tipo) => {
+ if (!auditResultModal || corrigiendoIntegridadPedimento) return;
+ const { pedimento_id } = auditResultModal;
+
+ const urlMap = {
+ int_pt: 'corregir-integridad-partidas',
+ int_edoc: 'corregir-integridad-edocuments',
+ int_cove: 'corregir-integridad-coves',
+ int_rm: 'corregir-integridad-remesa',
+ };
+ const path = urlMap[tipo];
+ if (!path) return;
+
+ try {
+ setCorrigiendoIntegridadPedimento(pedimento_id);
+ const response = await postWithAuth(`${API_URL}/customs/auditor/${path}/pedimento/`, { pedimento_id });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const raw = await response.json();
+
+ // Mostrar resultado de la corrección en el modal
+ const creados = raw.creadas ?? raw.edocuments_creados?.length ?? raw.coves_creados?.length ?? 0;
+ const mensaje = raw.estado === 'sin_xml'
+ ? 'No se encontró el XML del pedimento completo'
+ : raw.estado === 'sin_datos'
+ ? raw.razon ?? 'Sin datos suficientes'
+ : creados > 0
+ ? `Se crearon ${creados} registro(s) y se inició el procesamiento VUCEM`
+ : 'Registros ya existentes — procesamiento VUCEM iniciado';
+
+ setAuditResultModal(prev => prev ? {
+ ...prev,
+ data: {
+ ...prev.data,
+ auditoria_completa: raw.estado !== 'sin_xml' && raw.estado !== 'sin_datos',
+ estado: raw.estado === 'corregido' ? 'completado' : raw.estado,
+ mensaje,
+ resumen: raw.creadas != null ? { 'Esperadas': raw.esperadas, 'Creadas': raw.creadas } :
+ Array.isArray(raw.edocuments_creados) ? { 'EDocuments creados': raw.edocuments_creados.length } :
+ Array.isArray(raw.coves_creados) ? { 'COVEs creados': raw.coves_creados.length } : null,
+ },
+ } : null);
+ showMessage(mensaje, 'success');
+ } catch (error) {
+ showMessage(error.message || 'Error al corregir integridad', 'error');
+ } finally {
+ setCorrigiendoIntegridadPedimento(null);
+ }
+ };
+
+ // Handler para corregir integridad a nivel organización (org-level Celery)
+ const handleCorregirIntegridadGlobal = async () => {
+ if (!globalAuditModal?.tipo_integridad || corrigiendoIntegridadGlobal) return;
+ const { tipo_integridad, organizacion_id } = globalAuditModal;
+
+ const urlMap = {
+ partidas: 'corregir-integridad-partidas',
+ edocuments: 'corregir-integridad-edocuments',
+ coves: 'corregir-integridad-coves',
+ remesa: 'corregir-integridad-remesa',
+ };
+ const path = urlMap[tipo_integridad];
+ if (!path) return;
+
+ const labelMap = {
+ partidas: 'Corrección de Partidas',
+ edocuments: 'Corrección de EDocuments',
+ coves: 'Corrección de COVEs',
+ remesa: 'Corrección de Remesas',
+ };
+
+ try {
+ setCorrigiendoIntegridadGlobal(true);
+ const response = await postWithAuth(`${API_URL}/customs/auditor/${path}/`, { organizacion_id });
+ if (!response.ok) throw new Error(await extractApiError(response));
+ const data = await response.json();
+ const label = labelMap[tipo_integridad];
+ addTask({ task_id: data.task_id, label, organizacion_id });
+ setGlobalAuditModal({ label, organizacion_id, task_id: data.task_id, resultado: null });
+ showMessage(`${label} iniciada`, 'success');
+ } catch (error) {
+ showMessage(error.message || 'Error al iniciar la corrección', 'error');
+ } finally {
+ setCorrigiendoIntegridadGlobal(false);
+ }
+ };
+
const handleAnalizarPedimentoIndividual = async (pedimentoId) => {
if (analizandoIndividual) return;
try {
@@ -1719,6 +2307,52 @@ const handleAuditarEDocumentPedimento = async (pedimentoId) => {
}, 280);
};
+ const closeAuditResultPanel = () => {
+ setAuditResultClosing(true);
+ setAuditPanelDetalles(null);
+ setTimeout(() => { setAuditResultModal(null); setAuditResultClosing(false); }, 280);
+ };
+ const closeGlobalAuditPanel = () => {
+ setGlobalAuditClosing(true);
+ setTimeout(() => { setGlobalAuditModal(null); setGlobalAuditClosing(false); }, 280);
+ };
+ useEffect(() => {
+ if (!openRowDropdown) return;
+ const close = (e) => {
+ if (rowDropdownRef.current && rowDropdownRef.current.contains(e.target)) return;
+ setOpenRowDropdown(null);
+ setRowDropdownPos(null);
+ };
+ window.addEventListener('scroll', close, true);
+ return () => window.removeEventListener('scroll', close, true);
+ }, [openRowDropdown]);
+
+ const closeAutoCorregirPanel = () => {
+ setAutoCorregirClosing(true);
+ setTimeout(() => { setAutoCorregirModal(null); setAutoCorregirClosing(false); }, 280);
+ };
+
+ const handleCargarDetallesPeticion = async () => {
+ if (!auditResultModal || cargandoDetallesPeticion) return;
+ setCargandoDetallesPeticion(true);
+ try {
+ const response = await postWithAuth(`${API_URL}/customs/auditor/peticion-respuesta/pedimento-vu/`, {
+ pedimento_id: auditResultModal.pedimento_id,
+ vista: auditResultModal.tipo,
+ });
+ if (!response.ok) {
+ showMessage(`No se encontraron documentos: ${await extractApiError(response)}`, 'warning');
+ return;
+ }
+ const data = await response.json();
+ setAuditPanelDetalles(data);
+ } catch (error) {
+ showMessage(error.message || 'Error al cargar documentos VUCEM', 'error');
+ } finally {
+ setCargandoDetallesPeticion(false);
+ }
+ };
+
const handleCorregirOpen = (pedimento) => {
setCorregirForm({
numero_operacion: pedimento.numero_operacion || '',
@@ -2380,211 +3014,147 @@ function formatXml(xml) {
) : (
+ {/* Overlay para cerrar dropdowns al hacer click fuera */}
+ {(openGlobalDropdown || openRowDropdown) && (
+
{ setOpenGlobalDropdown(null); setOpenRowDropdown(null); setRowDropdownPos(null); }} />
+ )}
-
-
-
- Servicios de Auditoría
-
-
-
{/* Tabla de pedimentos */}
-
-
-
+
+
+
- |
+ |
Pedimento
|
-
- PC
- Pedimento Completo
+ |
+ Auditorías VUCEM
+ PC - RM - PT - AC - COVE - AC_COVE - EDoc
|
-
- RM
- Remesas
+ |
+ Integridad
+ Partidas - EDocuments - COVEs - Remesas
|
-
- PT
- Partidas
- |
-
- AC
- Acuse
- |
-
- COVE
- Cove
- |
-
- AC_COVE
- Acuse de Cove
- |
-
- EDoc
- EDocument
- |
-
- Corregir
+ |
+ Acciones
|
-
+
{loadingTable ? (
- |
+ |
|
- ) : pedimentos.map((pedimento) => (
-
- |
- {pedimento.pedimento_app}
- |
- {/* PC - Pedimento Completo */}
-
-
- handleAuditarPedimento(pedimento.id)}
- // onClick={handlePeticionPedimentoVU(pedimento.id)}
- // disabled = {peticionPedimentoVU}
- title='Auditar Pedimento Completo'
- className="inline-flex items-center justify-center w-8 h-8 transition-all duration-200 bg-white border border-gray-200 rounded-full shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 hover:scale-110">
-
-
-
- |
- {/* RM - Remesas */}
-
-
+ ) : pedimentos.map((pedimento) => {
+ const auditVucemOpen = openRowDropdown?.pedimentoId === pedimento.id && openRowDropdown?.type === 'vucem';
+ const integridadOpen = openRowDropdown?.pedimentoId === pedimento.id && openRowDropdown?.type === 'integridad';
+ return (
+
+ |
+
+ {pedimento.pedimento_app}
+
+ |
+ {/* Auditorías VUCEM */}
+
handleAuditarRemesaPedimento(pedimento.id)}
- title='Auditar Remesa'
- disabled={procesandoRemesa === pedimento.id}
- className={`inline-flex items-center justify-center w-8 h-8 rounded-full bg-white border border-gray-200
- ${procesandoRemesa === pedimento.id
- ? 'opacity-50 cursor-not-allowed'
- : 'shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-all duration-200 hover:scale-110'
- }
- `}
+ onClick={(e) => {
+ if (auditVucemOpen) {
+ setOpenRowDropdown(null);
+ setRowDropdownPos(null);
+ } else {
+ const rect = e.currentTarget.getBoundingClientRect();
+ const estimatedH = 330;
+ const spaceBelow = window.innerHeight - rect.bottom - 8;
+ const top = spaceBelow >= estimatedH ? rect.bottom + 4 : Math.max(8, rect.top - estimatedH);
+ setRowDropdownPos({ top, left: Math.min(rect.left, window.innerWidth - 296) });
+ setOpenRowDropdown({ pedimentoId: pedimento.id, type: 'vucem' });
+ }
+ }}
+ className="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-lg text-blue-700 bg-blue-50 border border-blue-200 hover:bg-blue-100 transition-colors"
>
- {procesandoRemesa === pedimento.id ? (
-
- {/* nuevo botón “view” */}
- handleModalPeticionRespuesta(pedimento,"rm")}
- title='Ver Petición y Respuesta de Remesas'
- >
-
-
-
-
-
-
- |
- {/* PT - Partidas */}
-
-
+
+ |
+ {/* Integridad */}
+
handleAuditarPartidasPedimento(pedimento.id)}
- title='Auditar Partidas'
- disabled={procesandoPartida === pedimento.id}
- className={`inline-flex items-center justify-center w-8 h-8 rounded-full bg-white border border-gray-200
- ${procesandoPartida === pedimento.id
- ? 'opacity-50 cursor-not-allowed'
- : 'shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-all duration-200 hover:scale-110'
- }
- `}
- >
- {procesandoPartida === pedimento.id ? (
-
-
-
-
- ) : (
-
-
-
- )}
-
- {/* nuevo botón “view” */}
- handleModalPeticionRespuesta(pedimento,"pt")}
- title='Ver Petición y Respuesta de Partidas'
+ onClick={(e) => {
+ if (integridadOpen) {
+ setOpenRowDropdown(null);
+ setRowDropdownPos(null);
+ } else {
+ const rect = e.currentTarget.getBoundingClientRect();
+ const estimatedH = 270;
+ const spaceBelow = window.innerHeight - rect.bottom - 8;
+ const top = spaceBelow >= estimatedH ? rect.bottom + 4 : Math.max(8, rect.top - estimatedH);
+ setRowDropdownPos({ top, left: Math.min(rect.left, window.innerWidth - 296) });
+ setOpenRowDropdown({ pedimentoId: pedimento.id, type: 'integridad' });
+ }
+ }}
+ className="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-lg text-blue-700 bg-blue-50 border border-blue-200 hover:bg-blue-100 transition-colors"
>
-
-
-
-
-
-
- |
- {/* AC - Acuse */}
-
-
- handleAuditarAcusePedimento(pedimento.id)}
- title='Auditar Acuse'
- disabled={procesandoAcuse === pedimento.id}
- className={`inline-flex items-center justify-center w-8 h-8 rounded-full bg-white border border-gray-200 ${procesandoAcuse === pedimento.id
- ? 'opacity-50 cursor-not-allowed'
- : 'shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-all duration-200 hover:scale-110'
- }`}
- >
- {procesandoAcuse === pedimento.id ? (
-
-
-
+
+
- ) : (
-
-
+ Integridad
+
+
- )}
- {/* nuevo botón “view” */}
- handleModalPeticionRespuesta(pedimento,"ac")}
- title='Ver Petición y Respuesta de Acuse'
- >
-
-
-
-
-
-
- |
- {/* COVE */}
-
-
- handleAuditarCovePedimento(pedimento.id)}
- title='Auditar Cove'
- disabled={procesandoCove === pedimento.id}
- className={`inline-flex items-center justify-center w-8 h-8 rounded-full bg-white border border-gray-200 ${procesandoCove === pedimento.id
- ? 'opacity-50 cursor-not-allowed'
- : 'shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-all duration-200 hover:scale-110'
- }`}
- >
- {procesandoCove === pedimento.id ? (
-
-
-
-
- ) : (
-
-
-
- )}
-
- {/* nuevo botón “view” */}
- handleModalPeticionRespuesta(pedimento,"cove")}
- title='Ver Petición y Respuesta de Cove'
- >
-
-
-
-
-
-
- |
- {/* AC_COVE */}
-
-
- handleAuditarAcusesCovePedimento(pedimento.id)}
- title='Auditar Acuse COVE'>
-
-
-
-
- {/* nuevo botón “view” */}
- handleModalPeticionRespuesta(pedimento,"ac_cove")}
- title='Ver Petición y Respuesta de Acuse COVE'
- >
-
-
-
-
-
-
- |
- {/* EDoc */}
-
-
- handleAuditarEDocumentPedimento(pedimento.id)}
- title='Auditar EDocument'>
-
-
-
-
- {/* nuevo botón “view” */}
- handleModalPeticionRespuesta(pedimento,"edoc")}
- title='Ver Petición y Respuesta de EDocument'
- >
-
-
-
-
-
-
- |
- {/* Auditar incompleto individual */}
-
- handleAnalizarPedimentoIndividual(pedimento.id)}
- disabled={analizandoIndividual !== null}
- title="Analizar pedimento incompleto"
- className="inline-flex items-center justify-center w-8 h-8 transition-all duration-200 bg-white border border-indigo-300 rounded-full shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-400 hover:scale-110 disabled:opacity-50 disabled:cursor-not-allowed"
- >
- {analizandoIndividual === pedimento.id ? (
-
-
-
-
- ) : (
-
-
-
- )}
-
- |
-
- ))}
+ |
+ {/* Acciones */}
+
+
+ handleAnalizarPedimentoIndividual(pedimento.id)}
+ disabled={analizandoIndividual !== null}
+ title="Analizar pedimento incompleto y preparar auto-corrección"
+ className="inline-flex items-center gap-1.5 px-3 py-2 text-xs font-medium rounded-lg text-blue-700 bg-blue-50 border border-blue-200 hover:bg-blue-100 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
+ >
+ {analizandoIndividual === pedimento.id ? (
+
+
+
+
+ ) : (
+
+
+
+ )}
+ Analizar
+
+ handleCorregirOpen(pedimento)}
+ title="Corregir datos del pedimento (número de operación, aduana, patente, etc.)"
+ className="inline-flex items-center gap-1.5 px-3 py-2 text-xs font-medium rounded-lg text-gray-600 bg-gray-50 border border-gray-200 hover:bg-gray-100 transition-colors"
+ >
+
+
+
+ Corregir
+
+
+ |
+
+ );
+ })}
@@ -3044,33 +3464,44 @@ function formatXml(xml) {
)}
- {/* Modal de auditoría global */}
- {globalAuditModal && (
- setGlobalAuditModal(null)}
+ closing={globalAuditClosing}
+ onClose={closeGlobalAuditPanel}
onConsultar={handleConsultarTask}
consultando={consultandoTask}
onIniciarProceso={handleIniciarProcesoGlobal}
iniciandoProceso={iniciandoProcesoGlobal}
+ onCorregirIntegridad={handleCorregirIntegridadGlobal}
+ corrigiendoIntegridad={corrigiendoIntegridadGlobal}
/>
)}
- {/* Modal de resultado de auditoría individual */}
- {auditResultModal && (
- setAuditResultModal(null)}
+ onClose={closeAuditResultPanel}
onIniciarProcesamiento={handleIniciarProcesamiento}
+ corrigiendoIntegridad={corrigiendoIntegridadPedimento === auditResultModal?.pedimento_id}
+ onCorregirIntegridad={() => handleCorregirIntegridadPedimento(auditResultModal?.tipo)}
+ detalles={auditPanelDetalles}
+ cargandoDetalles={cargandoDetallesPeticion}
+ onCargarDetalles={handleCargarDetallesPeticion}
+ onPreviewDoc={previewDocument}
/>
)}
- {/* Modal auto-corrección de pedamentos incompletos */}
- {autoCorregirModal && (
- setAutoCorregirModal(null)}
+ closing={autoCorregirClosing}
+ onClose={closeAutoCorregirPanel}
onConsultar={handleConsultarAutoCorregir}
consultando={consultandoAutoCorregir}
onEjecutar={handleEjecutarAutoCorregir}
@@ -3745,6 +4176,96 @@ function formatXml(xml) {
>
)}
+ {/* Dropdowns de fila fijos (escapan el overflow-x-auto de la tabla) */}
+ {openRowDropdown && rowDropdownPos && (() => {
+ const ped = pedimentos.find(p => p.id === openRowDropdown.pedimentoId);
+ if (!ped) return null;
+ const isVucem = openRowDropdown.type === 'vucem';
+
+ const vucemItems = [
+ { key: 'pc', label: 'Pedimento Completo', desc: 'Verifica el XML del pedimento completo descargado de VUCEM y actualiza los campos en DB.', loading: procesandoPedimento === ped.id, runHandler: () => { handleAuditarPedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'rm', label: 'Remesas', desc: 'Audita los COVEs registrados en el documento de remesa XML.', loading: procesandoRemesa === ped.id, runHandler: () => { handleAuditarRemesaPedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'pt', label: 'Partidas', desc: 'Crea o verifica las partidas arancelarias del pedimento a partir del XML.', loading: procesandoPartida === ped.id, runHandler: () => { handleAuditarPartidasPedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'ac', label: 'Acuse de EDocs', desc: 'Verifica el acuse de eDocs del pedimento en VUCEM.', loading: procesandoAcuse === ped.id, runHandler: () => { handleAuditarAcusePedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'cove', label: 'COVE', desc: 'Audita los documentos COVE asociados al pedimento en VUCEM.', loading: procesandoCove === ped.id, runHandler: () => { handleAuditarCovePedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'ac_cove', label: 'Acuse de COVE', desc: 'Verifica el acuse de confirmación de COVE emitido por VUCEM.', loading: procesandoAcuseCove === ped.id, runHandler: () => { handleAuditarAcusesCovePedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'edoc', label: 'EDocument', desc: 'Audita los documentos electrónicos (EDoc) del pedimento en VUCEM.', loading: procesandoEdocumento === ped.id, runHandler: () => { handleAuditarEDocumentPedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ ];
+
+ const integridadItems = [
+ { key: 'int_pt', label: 'Partidas', desc: 'Compara partidas esperadas en XML del PC contra las registradas en DB.', loading: procesandoIntegridadPartida === ped.id, handler: () => { handleAuditarIntegridadPartidasPedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'int_edoc', label: 'EDocuments', desc: 'Verifica que todos los EDocuments del PC XML existan en la base de datos.', loading: procesandoIntegridadEdocument === ped.id, handler: () => { handleAuditarIntegridadEdocumentsPedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'int_cove', label: 'COVEs (PC XML)', desc: 'Compara COVEs referenciados en el pedimento completo XML contra los registrados en DB.', loading: procesandoIntegridadCoves === ped.id, handler: () => { handleAuditarIntegridadCovesPedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ { key: 'int_rm', label: 'Remesas', desc: 'Verifica que los COVEs listados en el XML de remesa estén en la base de datos.', loading: procesandoIntegridadRemesa === ped.id, handler: () => { handleAuditarIntegridadRemesaPedimento(ped.id); setOpenRowDropdown(null); setRowDropdownPos(null); } },
+ ];
+
+ return (
+
+
+
+ {isVucem ? `Auditorías VUCEM — ${ped.pedimento_app}` : `Integridad — ${ped.pedimento_app}`}
+
+
+
+ {isVucem ? (
+ vucemItems.map(item => (
+
+
+ {item.loading ? (
+
+
+
+
+ ) : (
+
+
+
+ )}
+
+
{item.label}
+
{item.desc}
+
+
+
+ ))
+ ) : (
+ integridadItems.map(item => (
+
+ {item.loading ? (
+
+
+
+
+ ) : (
+
+
+
+ )}
+
+
{item.label}
+
{item.desc}
+
+
+ ))
+ )}
+
+
+ );
+ })()}
+
{/* Animaciones CSS */}