diff --git a/.gitignore b/.gitignore
index 7ceb59f..6ee797a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,4 @@ dist-ssr
*.sln
*.sw?
.env
+*.bak
\ No newline at end of file
diff --git a/src/pages/Expedientes.jsx b/src/pages/Expedientes.jsx
index 401be41..38626c1 100644
--- a/src/pages/Expedientes.jsx
+++ b/src/pages/Expedientes.jsx
@@ -18,11 +18,13 @@ const API_URL = import.meta.env.VITE_EFC_API_URL;
const downloadFile = async (id, filename = 'archivo', setSuccess, setError, showMessage) => {
try {
+ console.log('Descargar: ',id);
const res = await fetchWithAuth(`${API_URL}/record/documents/descargar/${id}/`);
if (!res.ok) {
- alert('No autorizado o error en la descarga');
- return;
+ //alert('No autorizado o error en la descarga');
+ showMessage('No autorizado o error en la descarga.', 'error');
+ return false;
}
const blob = await res.blob();
@@ -38,7 +40,9 @@ const downloadFile = async (id, filename = 'archivo', setSuccess, setError, show
} catch (error) {
console.error('Error downloading file:', error);
showMessage('Error al descargar el archivo', 'error');
+ return false;
}
+ return true;
};
export default function Documents() {
@@ -192,33 +196,142 @@ export default function Documents() {
}
};
+ // // Función para descargar documentos seleccionados
+ // const handleDownloadSelected = async () => {
+ // if (selectedDocuments.length === 0) {
+ // showMessage('No hay documentos seleccionados para descargar', 'warning');
+ // return;
+ // }
+
+ // try {
+ // showMessage(`Iniciando descarga de ${selectedDocuments.length} documento(s)...`, 'info');
+ // const resultados = [];
+ // for (const docId of selectedDocuments) {
+ // const document = currentDocuments.find(doc => doc.id === docId);
+ // if (document) {
+ // // const exito =await downloadFile(docId, `expediente_${document.pedimento_app}`, null, null, showMessage);
+ // const exito =await downloadExpediente(docId, `expediente_${document.pedimento_app}`, null, showMessage);
+ // resultados.push(exito);
+ // // Pequeña pausa entre descargas para no sobrecargar
+ // await new Promise(resolve => setTimeout(resolve, 500));
+ // }
+ // }
+ // const todosExitosos = resultados.every(Boolean);
+ // if(todosExitosos){
+ // showMessage(`Descarga completada de ${selectedDocuments.length} documento(s)`, 'success');
+ // }else{
+ // showMessage('Algunas descargas fallaron. Revisa los archivos seleccionados.', 'warning');
+ // }
+
+ // setSelectedDocuments([]);
+ // setIsSelectAll(false);
+ // } catch (error) {
+ // showMessage('Error durante la descarga masiva', 'error');
+ // }
+ // // showMessage('Error durante la descarga masiva', 'error');
+ // };
// Función para descargar documentos seleccionados
const handleDownloadSelected = async () => {
- if (selectedDocuments.length === 0) {
- showMessage('No hay documentos seleccionados para descargar', 'warning');
- return;
- }
+ if (selectedDocuments.length === 0) {
+ showMessage('No hay documentos seleccionados para descargar', 'warning');
+ return;
+ }
- try {
- showMessage(`Iniciando descarga de ${selectedDocuments.length} documento(s)...`, 'info');
+ try {
- for (const docId of selectedDocuments) {
- const document = currentDocuments.find(doc => doc.id === docId);
- if (document) {
- await downloadFile(docId, `expediente_${document.pedimento_app}`, null, null, showMessage);
- // Pequeña pausa entre descargas para no sobrecargar
- await new Promise(resolve => setTimeout(resolve, 500));
+ showMessage(`Iniciando descarga de ${selectedDocuments.length} documento(s) selecciobado(s)...`, 'info');
+
+ const res = await postWithAuth(`${API_URL}/record/documents/multi-pedimento-zip/`, {
+ pedimento_ids: selectedDocuments
+ });
+
+ if (!res.ok){
+ showMessage('Algunas descargas fallaron. Revisa los archivos seleccionados.', 'warning');
+ }else {
+ // Leer el nombre que eligió el backend
+ const zipFileName = res.headers.get('X-Zip-Filename') || 'expedientes.zip';
+ const blob = await res.blob();
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = zipFileName;
+ a.click();
+ a.remove();
+ window.URL.revokeObjectURL(url);
+ showMessage(`Descarga completada de ${selectedDocuments.length} documento(s)`, 'success');
+
+ setSelectedDocuments([]);
+ setIsSelectAll(false);
}
- }
-
- showMessage(`Descarga completada de ${selectedDocuments.length} documento(s)`, 'success');
- setSelectedDocuments([]);
- setIsSelectAll(false);
- } catch (error) {
- showMessage('Error durante la descarga masiva', 'error');
- }
+
+ } catch (error) {
+ showMessage('Error durante la descarga masiva', 'error');
+ }
+ // showMessage('Error durante la descarga masiva', 'error');
};
+
+ // Función para descargar todo el expediente
+ const handleDownloadTodoElExpediente = async (pedimentoId, pedimentoName) => {
+
+ try {
+ showMessage(`Iniciando descarga de ${selectedDocuments.length} documento(s)...`, 'info');
+ const resultados = [];
+
+ const document = currentDocuments.find(doc => doc.id === pedimentoId);
+ if (document) {
+ const exito =await downloadExpediente(pedimentoId, `expediente_${pedimentoName}`, null, showMessage);
+ resultados.push(exito);
+ // Pequeña pausa entre descargas para no sobrecargar
+ await new Promise(resolve => setTimeout(resolve, 500));
+ }
+
+ const todosExitosos = resultados.every(Boolean);
+ if(todosExitosos){
+ showMessage(`Descarga completada de ${selectedDocuments.length} documento(s)`, 'success');
+ }else{
+ // showMessage('Algunas descargas fallaron. Revisa los archivos seleccionados.', 'warning');
+ }
+
+ setSelectedDocuments([]);
+ setIsSelectAll(false);
+ } catch (error) {
+ showMessage('Error durante la descarga masiva', 'error');
+ }
+};
+
+const downloadExpediente = async (pedimentoId, pedimentoName, setSuccess, showMessage) => {
+ try {
+ const res = await postWithAuth(`${API_URL}/record/documents/expediente-zip/`, {
+ pedimento_id: pedimentoId,
+ });
+
+ if (!res.ok) {
+ // alert('No autorizado o error en la descarga');
+ // showMessage('No autorizado o error en la descarga.', 'error');
+ const err = await res.json();
+ showMessage(err.error || 'Error al generar ZIP', 'error');
+ return false;
+ }
+
+ const blob = await res.blob();
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `${pedimentoName}.zip`;
+ // document.body.appendChild(a);
+ a.click();
+ a.remove();
+ window.URL.revokeObjectURL(url);
+ if (setSuccess) setSuccess('Descarga exitosa');
+ } catch (error) {
+ console.error('Error downloading file:', error);
+ showMessage('Error al descargar el archivo', 'error');
+ return false;
+ }
+ return true;
+};
+
// Función para eliminar documentos seleccionados
const handleDeleteSelected = async () => {
if (selectedDocuments.length === 0) {
@@ -485,10 +598,30 @@ export default function Documents() {
const uploadEndpoint = `${API_URL}/customs/pedimentos/bulk-create/`;
const result = await postFormDataWithAuth(uploadEndpoint, formData);
- showMessage(
- `${result.uploaded_count || fileCount} archivo(s) subido(s) exitosamente`,
- 'success'
- );
+ if(!result.ok){
+ let errorMsg = 'Error al intentar cargar los archivos';
+ try {
+ const errorData = await result.json();
+ errorMsg = errorData.error || errorMsg;
+ } catch {
+ // Si no es JSON válido, usar texto plano
+ const text = await result.text();
+ errorMsg = text || errorMsg;
+ }
+ showMessage(errorMsg, 'error');
+ }else{
+ showMessage(
+ `${result.uploaded_count || fileCount} archivo(s) subido(s) exitosamente`,
+ 'success'
+ );
+ }
+
+ // showMessage(
+ // `${result.uploaded_count || fileCount} archivo(s) subido(s) exitosamente`,
+ // 'success'
+ // );
+
+ // console.log(result);
// Limpiar archivos seleccionados y cerrar modal
setSelectedFiles([]);
@@ -522,47 +655,60 @@ export default function Documents() {
setIsSelectAll(false);
}, [currentPage]);
+ // función que detecta si hay filtros activos
+ const hasActiveFilters = [
+ searchFilter,
+ pedimentoFilter,
+ expedienteFilter !== 'all',
+ contribuyenteFilter,
+ curpApoderadoFilter,
+ fechaPagoFilter,
+ patenteFilter,
+ aduanaFilter,
+ tipoOperacionFilter,
+ clavePedimentoFilter,
+].some(Boolean);
// El layout principal y la tabla siempre se renderizan, loader/error/empty solo dentro del área de la tabla
return (
-
+
-
+
{/* Header mejorado y decorativo */}
-
-