From d8c23dcf0916a25afd0f82207f0a0350d9966ebb Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 26 Nov 2025 08:59:23 -0700 Subject: [PATCH 1/4] Remove .env from Git tracking --- .env | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index ac7ad1b..0000000 --- a/.env +++ /dev/null @@ -1,5 +0,0 @@ -VITE_DEBUG_MODE=true - -VITE_EFC_API_URL=http://192.168.1.79:8000/api/v1 -VITE_EFC_MICROSERVICE_URL=http://192.168.1.79:8001/api/v1 -VITE_EFC_MICROSERVICE_URL_2=http://192.168.1.79:8001/api/v2 From 70f0b38e9348cbd80014d2b47594f22ad0e18275 Mon Sep 17 00:00:00 2001 From: Luis Date: Fri, 5 Dec 2025 08:22:45 -0700 Subject: [PATCH 2/4] =?UTF-8?q?fix/Se=20modifica=20vista=20principal=20de?= =?UTF-8?q?=20detalle=20de=20pedimento=20y=20se=20ajusta=20la=20visualizac?= =?UTF-8?q?ion=20de=20los=20documentos=20respectivos=20a=20cada=20pesta?= =?UTF-8?q?=C3=B1a.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/pedimentoCompleto.ts | 68 ++ src/pages/PedimentoDetail.jsx | 1740 +++++++++++++++++++++++++-------- 2 files changed, 1424 insertions(+), 384 deletions(-) create mode 100644 src/api/pedimentoCompleto.ts diff --git a/src/api/pedimentoCompleto.ts b/src/api/pedimentoCompleto.ts new file mode 100644 index 0000000..f3f08fe --- /dev/null +++ b/src/api/pedimentoCompleto.ts @@ -0,0 +1,68 @@ +// src\api\pedimentoCompleto.ts +import { fetchWithAuth } from '../fetchWithAuth'; + +export interface PedimentoCompleto { + id: string; + organizacion: string; + pedimento: string; + pedimento_numero: string; + archivo: string; + document_type: number; + size: number; + extension: string; + fuente: number; + created_at: string; + updated_at: string; +} + +export interface PedimentoCompletoResponse { + count: number; + next: string | null; + previous: string | null; + results: PedimentoCompleto[]; +} + +export interface DocumentFilters { + document_type?: string; + archivo__icontains?: string; + extension?: string; + created_at__date?: string; + ordering?: string; +} + +const API_URL = (import.meta as any).env.VITE_EFC_API_URL; + +export async function fetchPedimentoCompleto( + pedimentoId: string, + page: number = 1, + pageSize: number = 10, + filters: DocumentFilters = {} +): Promise { + try { + // Construir URL con filtros + const params = new URLSearchParams({ + page: page.toString(), + page_size: pageSize.toString(), + pedimento: pedimentoId + }); + + // Agregar filtros si existen + Object.entries(filters).forEach(([key, value]) => { + if (value !== undefined && value !== '') { + params.append(key, value.toString()); + } + }); + + // const res = await fetchWithAuth(`${API_URL}/record/documents/?${params.toString()}`); + const res = await fetchWithAuth(`${API_URL}/record/pedimento-documents/?${params.toString()}`); + + if (!res.ok) { + throw new Error('No autorizado o error en la petición'); + } + + return res.json(); + } catch (error) { + console.error('Error in fetchPedimentoCompleto:', error); + throw error; + } +} diff --git a/src/pages/PedimentoDetail.jsx b/src/pages/PedimentoDetail.jsx index 4c24fe8..1beaaa3 100644 --- a/src/pages/PedimentoDetail.jsx +++ b/src/pages/PedimentoDetail.jsx @@ -16,6 +16,7 @@ import xml from 'highlight.js/lib/languages/xml'; import 'highlight.js/styles/github.css'; hljs.registerLanguage('xml', xml); import { fetchPedimentoDocuments } from '../api/pedimentoDocuments'; +import { fetchPedimentoCompleto} from '../api/pedimentoCompleto'; import { fetchWithAuth, postWithAuth, putWithAuth, postFormDataWithAuth } from '../fetchWithAuth'; import { fetchTasks } from '../api/procesos.ts'; import { fetchPedimentoCoves, downloadCove, downloadAcuseCove } from '../api/coves'; @@ -107,7 +108,8 @@ function formatXml(xml) { export default function PedimentoDetail() { // Estados principales - const [activeTab, setActiveTab] = useState('documentos'); + // const [activeTab, setActiveTab] = useState('documentos'); + const [activeTab, setActiveTab] = useState('pedimento'); const [pedimento, setPedimento] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); @@ -139,7 +141,8 @@ export default function PedimentoDetail() { const [dashboardSummary, setDashboardSummary] = useState(null); const [showFilters, setShowFilters] = useState(false); - + const [showFiltersPedimento, setShowFiltersPedimento] = useState(false); + // Filtros simplificados de documentos (nuevo diseño) const [filters, setFilters] = useState({ name: '', @@ -151,6 +154,18 @@ export default function PedimentoDetail() { fuente: '', pedimento_numero: '' }); + + // Filtros simplificados de pedimento (nuevo diseño) + const [pedimentoFilters, setPedimentoFilters] = useState({ + name: '', + document_type: '', + extension: '', + date: '', + created_at__gte: '', + created_at__lte: '', + fuente: '', + pedimento_numero: '' + }); // Estados para filtros (legacy - para compatibilidad) const [documentTypeFilter, setDocumentTypeFilter] = useState(''); @@ -192,6 +207,105 @@ export default function PedimentoDetail() { created_at__lte: '' }); + // Estados para Pedimento T2025-10-152 + const [peddocuments, setPedDocuments] = useState([]); + const [peddocsCount, setPedDocsCount] = useState(0); + const [pedimentoNext, setPedimentoNext] = useState(null); + const [pedimentoPrev, setPedimentoPrev] = useState(null); + const [pedimentoLoading, setPedimentoLoading] = useState(false); + const [pedimentoError, setPedimentoError] = useState(''); + const [pedimentoPage, setPedimentoPage] = useState(1); + const [pedimentoPageSize, setPedimentoPageSize] = useState(10); + const [downloadingAllPedimento, setDownloadingAllPedimento] = useState(false); + // Agrega estos estados para selección de documentos de pedimento + const [selectedPedimentoDocuments, setSelectedPedimentoDocuments] = useState([]); + const [isSelectAllPedimentoDocs, setIsSelectAllPedimentoDocs] = useState(false); + + // Efecto para actualizar isSelectAllPedimentoDocs cuando cambia la selección + useEffect(() => { + if (peddocuments.length > 0) { + const allSelected = peddocuments.every(doc => selectedPedimentoDocuments.includes(doc.id)); + setIsSelectAllPedimentoDocs(allSelected && selectedPedimentoDocuments.length > 0); + } + }, [selectedPedimentoDocuments, peddocuments]); + + // Efecto para limpiar selección cuando cambia de página + useEffect(() => { + setSelectedPedimentoDocuments([]); + setIsSelectAllPedimentoDocs(false); + }, [pedimentoPage]); + + // Funciones para manejo de selección múltiple de documentos de pedimento + const handleSelectPedimentoDocument = (documentId) => { + const isSelected = selectedPedimentoDocuments.includes(documentId); + if (isSelected) { + setSelectedPedimentoDocuments(prev => prev.filter(id => id !== documentId)); + } else { + setSelectedPedimentoDocuments(prev => [...prev, documentId]); + } + }; + + const handleSelectAllPedimentoDocuments = () => { + if (isSelectAllPedimentoDocs) { + setSelectedPedimentoDocuments([]); + setIsSelectAllPedimentoDocs(false); + } else { + const allDocumentIds = peddocuments.map(doc => doc.id); + setSelectedPedimentoDocuments(allDocumentIds); + setIsSelectAllPedimentoDocs(true); + } + }; + + // Función para eliminar documentos seleccionados de pedimento +const handleDeleteSelectedPedimentoDocuments = async () => { + if (selectedPedimentoDocuments.length === 0) { + showMessage('No hay documentos seleccionados para eliminar', 'warning'); + return; + } + + try { + showMessage(`Eliminando ${selectedPedimentoDocuments.length} documento(s)...`, 'info'); + + const response = await fetchWithAuth(`${API_URL}/record/documents/bulk-delete/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + ids: selectedPedimentoDocuments + }) + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => null); + throw new Error(errorData?.detail || errorData?.message || `Error ${response.status}: ${response.statusText}`); + } + + const result = await response.json(); + + showMessage( + `${result.deleted_count || selectedPedimentoDocuments.length} documento(s) eliminado(s) exitosamente`, + 'success' + ); + + setSelectedPedimentoDocuments([]); + setIsSelectAllPedimentoDocs(false); + + // Forzar recarga de documentos + const currentPage = pedimentoPage; + setPedimentoPage(0); + setTimeout(() => setPedimentoPage(currentPage), 100); + } catch (error) { + console.error('Error durante la eliminación masiva:', error); + showMessage(`Error durante la eliminación: ${error.message}`, 'error'); + } +}; + + // Resetear página cuando cambien los filtros de pedimento + useEffect(() => { + setPedimentoPage(1); + }, [pedimentoFilters]); + // Estados para Partidas const [partidas, setPartidas] = useState([]); const [partidasCount, setPartidasCount] = useState(0); @@ -219,6 +333,38 @@ export default function PedimentoDetail() { const [processingEdoc, setProcessingEdoc] = useState(null); const [processingAcuseEdoc, setProcessingAcuseEdoc] = useState(null); + // Agregar estado para el modal de documentos + const [showDocumentsModal, setShowDocumentsModal] = useState(false); + const [selectedVUDocuments, setSelectedVUDocuments] = useState([]); + const [selectedVUNumber, setSelectedVUNumber] = useState(''); + + // Función para manejar la visualización de documentos COVE + const handleShowCoveDocuments = (cove) => { + if (cove.documentos && cove.documentos.length > 0) { + setSelectedVUDocuments(cove.documentos); + setSelectedVUNumber(cove.numero_cove); + setShowDocumentsModal(true); + } + }; + + // Función para manejar la visualización de documentos COVE + const handleShowPartidaDocuments = (partida) => { + if (partida.documentos && partida.documentos.length > 0) { + setSelectedVUDocuments(partida.documentos); + setSelectedVUNumber(partida.numero_partida); + setShowDocumentsModal(true); + } + }; + + // Función para manejar la visualización de Edocuments + const handleShowEDocuments = (edocument) => { + if (edocument.documentos && edocument.documentos.length > 0) { + setSelectedVUDocuments(edocument.documentos); + setSelectedVUNumber(edocument.numero_edocument); + setShowDocumentsModal(true); + } + }; + // Función para obtener el resumen del dashboard const fetchDashboardSummary = async () => { try { @@ -476,6 +622,70 @@ export default function PedimentoDetail() { setDownloading(false); }; + // Vista previa de documento + const handlePreviewVU = async (doc) => { + setPreviewLoading(true); + setPreviewError(''); + setPreviewUrl(''); + setPreviewType(''); + setPreviewXml(''); + setPreviewDoc(doc); + setImageZoom(1); + setPreviewContent(''); + setPreviewOpen(true); + try { + const res = await fetchWithAuth(`${API_URL}/record/documents/descargar/${doc.id}/`); + + if (!res.ok) { + setPreviewError('Error al obtener el archivo'); + setPreviewLoading(false); + return; + } + + // Detectar tipo de archivo + let type = ''; + if (doc.extension) { + if (doc.extension.toLowerCase() === 'pdf') type = 'pdf'; + else if (["jpg","jpeg","png","gif","bmp","webp"].includes(doc.extension.toLowerCase())) type = 'img'; + else if (doc.extension.toLowerCase() === 'xml') type = 'xml'; + else if (["txt","log","csv"].includes(doc.extension.toLowerCase())) type = 'txt'; + else type = 'other'; + } + setPreviewType(type); + + if (type === 'xml') { + const text = await res.text(); + const prettyText = formatXml(text); + setPreviewXml(prettyText); + // Formatear y resaltar XML + try { + const highlighted = hljs.highlight(prettyText, { language: 'xml' }).value; + setPreviewXmlHtml(highlighted); + } catch (e) { + setPreviewXmlHtml(prettyText); + } + setPreviewLoading(false); + } else if (type === 'txt') { + const text = await res.text(); + setPreviewContent(text); + setPreviewLoading(false); + } else { + const blob = await res.blob(); + const url = window.URL.createObjectURL(blob); + setPreviewUrl(url); + setPreviewLoading(false); + } + } catch (err) { + console.error('Error in preview:', err); + if (err.message === 'SESSION_EXPIRED') { + setPreviewError('Tu sesión ha expirado, por favor inicia sesión de nuevo.'); + } else { + setPreviewError('Error al obtener el archivo'); + } + setPreviewLoading(false); + } + }; + // Vista previa de documento const handlePreview = async (doc) => { setPreviewLoading(true); @@ -568,6 +778,47 @@ export default function PedimentoDetail() { } }; + // Funciones para el nuevo diseño de documentos + const downloadAllPedimento = async () => { + setDownloadingAllPedimento(true); + try { + const allDocIds = peddocuments.map(doc => doc.id); + await handleBulkDownload(allDocIds); + } catch (error) { + console.error('Error downloading all documents:', error); + showMessage('Error al descargar todos los documentos', 'error'); + } finally { + setDownloadingAllPedimento(false); + } + }; + + const previewDocumentVU = async (doc) => { + // Cerrar el modal primero + setShowDocumentsModal(false); + setSelectedVUDocuments([]); + setSelectedVUNumber(''); + + await handlePreviewVU(doc); + }; + + const downloadAllVU = async () => { + setDownloadingAll(true); + try { + const allDocIds = selectedVUDocuments.map(doc => doc.id); + await handleBulkDownload(allDocIds); + } catch (error) { + console.error('Error downloading all documents:', error); + showMessage('Error al descargar todos los documentos', 'error'); + } finally { + setDownloadingAll(false); + } + }; + + const downloadDocumentVU = async (doc) => { + const fileName = doc.archivo ? doc.archivo.split('/').pop() : `documento_${doc.id}`; + await downloadFile(doc.id, fileName, showMessage); + }; + const previewDocument = async (doc) => { await handlePreview(doc); }; @@ -786,6 +1037,9 @@ export default function PedimentoDetail() { if (filters.fuente) apiFilters.fuente = filters.fuente; if (filters.pedimento_numero) apiFilters.pedimento_numero__icontains = filters.pedimento_numero; + // Filtro para identificar modulo de pedimento + apiFilters.modulo = 'expedientes-detalle-pedimentos'; + // Mantener compatibilidad con filtros legacy si están en uso if (documentTypeFilter) apiFilters.document_type = documentTypeFilter; if (fileNameFilter) apiFilters.archivo__icontains = fileNameFilter; @@ -832,6 +1086,60 @@ export default function PedimentoDetail() { console.log('Documents data:', { documents, docsCount, page, pageSize, docsLoading, docsError }); }, [documents, docsCount, page, pageSize, docsLoading, docsError]); + // Fetch Pedimento T2025-10-152 documents + useEffect(() => { + if (!id || activeTab !== 'pedimento') return; + + setPedimentoLoading(true); + setPedimentoError(''); + + // Construir parámetros de filtros para pedimento completo + const apiFilters = {}; + if (pedimentoFilters.document_type) apiFilters.document_type = pedimentoFilters.document_type; + if (pedimentoFilters.name) apiFilters.archivo__icontains = pedimentoFilters.name; + if (pedimentoFilters.extension) apiFilters.extension = pedimentoFilters.extension; + if (pedimentoFilters.date) apiFilters.created_at__date = pedimentoFilters.date; + if (pedimentoFilters.created_at__gte) apiFilters.created_at__gte = pedimentoFilters.created_at__gte; + if (pedimentoFilters.created_at__lte) apiFilters.created_at__lte = pedimentoFilters.created_at__lte; + if (pedimentoFilters.fuente) apiFilters.fuente = pedimentoFilters.fuente; + if (pedimentoFilters.pedimento_numero) apiFilters.pedimento_numero__icontains = pedimentoFilters.pedimento_numero; + + // Mantener compatibilidad con filtros legacy si están en uso + if (documentTypeFilter) apiFilters.document_type = documentTypeFilter; + if (fileNameFilter) apiFilters.archivo__icontains = fileNameFilter; + if (extensionFilter) apiFilters.extension = extensionFilter; + if (dateFilter) apiFilters.created_at__date = dateFilter; + + if (orderBy) { + const orderField = orderBy === 'archivo' ? 'archivo' : + orderBy === 'document_type' ? 'document_type' : + orderBy === 'created_at' ? 'created_at' : + orderBy === 'size' ? 'size' : orderBy; + apiFilters.ordering = orderDir === 'desc' ? `-${orderField}` : orderField; + } + + fetchPedimentoCompleto(id, pedimentoPage, pedimentoPageSize,apiFilters) + .then((data) => { + setPedDocuments(data.results); + setPedDocsCount(data.count); + setPedimentoNext(data.next); + setPedimentoPrev(data.previous); + setPedimentoLoading(false); + }) + .catch(err => { + console.error('Error fetching Pedimento Completo:', err); + if (err.message === 'SESSION_EXPIRED') { + showMessage('Tu sesión ha expirado, por favor inicia sesión de nuevo.', 'error'); + } else { + setPedimentoError(err.message); + } + setPedimentoLoading(false); + }); + + },[id, activeTab, pedimentoPage, pedimentoPageSize, showMessage, pedimentoFilters, documentTypeFilter, fileNameFilter, extensionFilter, dateFilter, orderBy, orderDir]); + + + // Fetch COVEs cuando sea necesario useEffect(() => { if (!id || activeTab !== 'coves') return; @@ -2005,25 +2313,25 @@ export default function PedimentoDetail() { // Estados de carga if (loading) return ( -
+
-
-

Cargando detalle del pedimento...

+
+

Cargando detalle del pedimento...

); if (error) return ( -
+
-
+
-

Error al cargar

+

Error al cargar

{error}

- + ← Volver a expedientes
@@ -2031,23 +2339,23 @@ export default function PedimentoDetail() { ); return ( -
-
+
+
{/* Header */} -
Volver a la lista -

+

Detalle de Pedimento

@@ -2055,7 +2363,7 @@ export default function PedimentoDetail() {

{docsCount > 0 && (
- + 📄 {docsCount} documentos
@@ -2065,7 +2373,7 @@ export default function PedimentoDetail() { {/* Información del Pedimento */} {pedimento && ( -
@@ -2078,9 +2386,9 @@ export default function PedimentoDetail() {
-
-
-
+
+
+
@@ -2089,8 +2397,8 @@ export default function PedimentoDetail() {
{pedimento.pedimento_app}
-
-
+
+
@@ -2099,8 +2407,8 @@ export default function PedimentoDetail() {
{pedimento.contribuyente}
-
-
+
+
@@ -2114,12 +2422,89 @@ export default function PedimentoDetail() { )} {/* Sistema de pestañas */} -
{/* Navegación de pestañas */}
-
- - - - - - - - + {/* Pestaña Auditor */} @@ -2409,11 +2739,11 @@ export default function PedimentoDetail() { {/* Área de acciones para documentos seleccionados */} {selectedDocuments.length > 0 && ( -
+
-
+
@@ -2430,7 +2760,7 @@ export default function PedimentoDetail() { setSelectedDocuments([]); setIsSelectAllDocs(false); }} - className="text-gray-400 hover:text-gray-600 transition-colors" + className="text-gray-400 transition-colors hover:text-gray-600" title="Limpiar selección" > @@ -2443,7 +2773,7 @@ export default function PedimentoDetail() {