diff --git a/backend/api/v1/modules/a76/reports/exportacion/aviso_consolidado/task.py b/backend/api/v1/modules/a76/reports/exportacion/aviso_consolidado/task.py index 291d5a4e..d70aad60 100644 --- a/backend/api/v1/modules/a76/reports/exportacion/aviso_consolidado/task.py +++ b/backend/api/v1/modules/a76/reports/exportacion/aviso_consolidado/task.py @@ -1,3 +1,4 @@ +from fastapi import HTTPException import base64 import logging from core.celery_app import celery_app diff --git a/backend/api/v1/modules/a76/reports/exportacion/descargo/task.py b/backend/api/v1/modules/a76/reports/exportacion/descargo/task.py index 3ed57fbb..93e6738e 100644 --- a/backend/api/v1/modules/a76/reports/exportacion/descargo/task.py +++ b/backend/api/v1/modules/a76/reports/exportacion/descargo/task.py @@ -3,6 +3,7 @@ from celery import shared_task from sqlalchemy.orm import Session from core.database import CoreSessionLocal as SessionLocal from .service import DescargaReportService # FORCE RELOAD 2 +from fastapi import HTTPException import base64 import traceback diff --git a/backend/api/v1/modules/a76/reports/exportacion/transmission/MAINX30/task.py b/backend/api/v1/modules/a76/reports/exportacion/transmission/MAINX30/task.py index 7aebc5b3..a6f34be2 100644 --- a/backend/api/v1/modules/a76/reports/exportacion/transmission/MAINX30/task.py +++ b/backend/api/v1/modules/a76/reports/exportacion/transmission/MAINX30/task.py @@ -1,4 +1,5 @@ from celery import Task +from fastapi import HTTPException from core.celery_app import celery_app from core.celery_app import celery_app from core.database import get_core_db as get_db diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py index d543a5a2..cbb83926 100644 --- a/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py @@ -15,7 +15,7 @@ class ClienteSchema(BaseModel): ciudad: Optional[str] = "" estado: Optional[str] = "" pais: Optional[str] = "" - tax_id: str + tax_id: Optional[str] = "" programa: Optional[str] = "" autorizacion: Optional[str] = "" prosec: Optional[str] = "" @@ -23,7 +23,7 @@ class ClienteSchema(BaseModel): cert: Optional[str] = "" # Si llega un None, lo convertimos en "" automáticamente - @field_validator('direccion', 'nombre', mode='before') + @field_validator('direccion', 'nombre', 'tax_id', mode='before') @classmethod def prevent_none(cls, v): return v or "" diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/task.py b/backend/api/v1/modules/a76/reports/importacion/consolidados/task.py index 23e680c1..3500ac70 100644 --- a/backend/api/v1/modules/a76/reports/importacion/consolidados/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/task.py @@ -1,3 +1,4 @@ +from fastapi import HTTPException import base64 import logging from core.celery_app import celery_app @@ -43,10 +44,12 @@ def generar_pdf_consolidado_async(self, invoice_id: int, company_id: int): "media_type": media_type } + except HTTPException as e: + logger.error(f"HTTP Error en Celery Worker: {str(e.detail)}") + return {"status": "error", "message": str(e.detail)} except Exception as e: logger.error(f"Error en Celery Worker: {str(e)}") - return {"status": "error", "message": str(e)} - + return {"status": "error", "message": f"Error interno en el servidor de reportes: {str(e)}"} finally: # 5. MUY IMPORTANTE: Cerramos la conexión para no saturar Postgres db.close() diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py index f8822e66..f40c2f54 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py @@ -15,7 +15,7 @@ class ClienteSchema(BaseModel): ciudad: Optional[str] = "" estado: Optional[str] = "" pais: Optional[str] = "" - tax_id: str + tax_id: Optional[str] = "" programa: Optional[str] = "" autorizacion: Optional[str] = "" prosec: Optional[str] = "" @@ -23,7 +23,7 @@ class ClienteSchema(BaseModel): cert: Optional[str] = "" # Si llega un None, lo convertimos en "" automáticamente - @field_validator('direccion', 'nombre', mode='before') + @field_validator('direccion', 'nombre', 'tax_id', mode='before') @classmethod def prevent_none(cls, v): return v or "" diff --git a/backend/api/v1/modules/a76/reports/importacion/packing_list/schemas.py b/backend/api/v1/modules/a76/reports/importacion/packing_list/schemas.py index fcaaae40..464b5539 100644 --- a/backend/api/v1/modules/a76/reports/importacion/packing_list/schemas.py +++ b/backend/api/v1/modules/a76/reports/importacion/packing_list/schemas.py @@ -12,14 +12,14 @@ class ClienteSchema(BaseModel): ciudad: Optional[str] = "" estado: Optional[str] = "" pais: Optional[str] = "" - tax_id: str + tax_id: Optional[str] = "" programa: Optional[str] = "" autorizacion: Optional[str] = "" prosec: Optional[str] = "" reg_emp: Optional[str] = "" cert: Optional[str] = "" - @field_validator('direccion', 'nombre', mode='before') + @field_validator('direccion', 'nombre', 'tax_id', mode='before') @classmethod def prevent_none(cls, v): return v or "" diff --git a/backend/api/v1/modules/a76/reports/importacion/packing_list/task.py b/backend/api/v1/modules/a76/reports/importacion/packing_list/task.py index bf55991b..338380ba 100644 --- a/backend/api/v1/modules/a76/reports/importacion/packing_list/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/packing_list/task.py @@ -1,3 +1,4 @@ +from fastapi import HTTPException import base64 from core.celery_app import celery_app from core.database import CoreSessionLocal diff --git a/backend/api/v1/modules/a76/reports/importacion/transmission/definitive/MAINX30/task.py b/backend/api/v1/modules/a76/reports/importacion/transmission/definitive/MAINX30/task.py index 9ec7a08c..c6559af3 100644 --- a/backend/api/v1/modules/a76/reports/importacion/transmission/definitive/MAINX30/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/transmission/definitive/MAINX30/task.py @@ -1,3 +1,4 @@ +from fastapi import HTTPException from core.celery_app import celery_app from core.database import get_core_db as get_db from .service import Mainx30DefinitiveService diff --git a/backend/api/v1/modules/a76/reports/importacion/transmission/temporal/MAINX30/task.py b/backend/api/v1/modules/a76/reports/importacion/transmission/temporal/MAINX30/task.py index ae7cca36..584ea348 100644 --- a/backend/api/v1/modules/a76/reports/importacion/transmission/temporal/MAINX30/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/transmission/temporal/MAINX30/task.py @@ -1,4 +1,5 @@ from celery import Task +from fastapi import HTTPException from core.celery_app import celery_app from core.celery_app import celery_app from core.database import get_core_db as get_db diff --git a/backend/api/v1/modules/a76/reports/importacion/winsaai/invoices/task.py b/backend/api/v1/modules/a76/reports/importacion/winsaai/invoices/task.py index d21daac9..d4e14e1c 100644 --- a/backend/api/v1/modules/a76/reports/importacion/winsaai/invoices/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/winsaai/invoices/task.py @@ -1,3 +1,4 @@ +from fastapi import HTTPException from core.celery_app import celery_app from core.database import CoreSessionLocal from .service import WinsaaiService diff --git a/backend/api/v1/modules/a76/reports/importacion/winsaai/pedimentos/task.py b/backend/api/v1/modules/a76/reports/importacion/winsaai/pedimentos/task.py index 119b93d0..65ebaf31 100644 --- a/backend/api/v1/modules/a76/reports/importacion/winsaai/pedimentos/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/winsaai/pedimentos/task.py @@ -1,3 +1,4 @@ +from fastapi import HTTPException import logging from typing import List import base64 diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-aviso-consolidado.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-aviso-consolidado.ts index 363b1daf..75cc9201 100644 --- a/frontend/src/lib/api/dashboard/a76/reports/reports-aviso-consolidado.ts +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-aviso-consolidado.ts @@ -16,7 +16,19 @@ export const avisoConsolidadoReportsApi = { } }); - if (!response.ok) throw new Error('Error al iniciar la generación del Aviso Consolidado'); + if (!response.ok) { + let errorMessage = 'Error al iniciar la generación del Aviso Consolidado'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -29,7 +41,19 @@ export const avisoConsolidadoReportsApi = { headers: { 'Authorization': `Bearer ${token}` } }); - if (!response.ok) throw new Error('Error al consultar estado del Aviso Consolidado'); + if (!response.ok) { + let errorMessage = 'Error al consultar estado del Aviso Consolidado'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); } }; diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-consolidated.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-consolidated.ts index 9e6c171a..6034ed9d 100644 --- a/frontend/src/lib/api/dashboard/a76/reports/reports-consolidated.ts +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-consolidated.ts @@ -16,7 +16,19 @@ export const consolidatedReportsApi = { } }); - if (!response.ok) throw new Error('Error al iniciar la generación del consolidado'); + if (!response.ok) { + let errorMessage = 'Error al iniciar la generación del consolidado'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -29,7 +41,19 @@ export const consolidatedReportsApi = { headers: { 'Authorization': `Bearer ${token}` } }); - if (!response.ok) throw new Error('Error al consultar estado del consolidado'); + if (!response.ok) { + let errorMessage = 'Error al consultar estado del consolidado'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); } }; diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-descargo.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-descargo.ts index 993e4ff9..20a93bcf 100644 --- a/frontend/src/lib/api/dashboard/a76/reports/reports-descargo.ts +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-descargo.ts @@ -17,7 +17,19 @@ export const dischargeReportsApi = { } }); - if (!response.ok) throw new Error('Error al iniciar la generación del Reporte de Descarga'); + if (!response.ok) { + let errorMessage = 'Error al iniciar la generación del Reporte de Descarga'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -30,7 +42,19 @@ export const dischargeReportsApi = { headers: { 'Authorization': `Bearer ${token}` } }); - if (!response.ok) throw new Error('Error al consultar estado del Reporte de Descarga'); + if (!response.ok) { + let errorMessage = 'Error al consultar estado del Reporte de Descarga'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts index 313e31a7..e74a555c 100644 --- a/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts @@ -1,5 +1,4 @@ - -const BASE_URL = import.meta.env.VITE_API_URL || ''; +import { api } from '$lib/api'; export const invoicesReportsApi = { @@ -9,62 +8,33 @@ export const invoicesReportsApi = { invoice_type: invoiceType, currency_code: currency }); - const endpoint = `${BASE_URL}/v1/a76/reports/importacion/facturas/${invoiceId}/download-async?${params.toString()}`; + const endpoint = `/v1/a76/reports/importacion/facturas/${invoiceId}/download-async?${params.toString()}`; - - const token = localStorage.getItem('access_token'); - const response = await fetch(endpoint, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - }); - - if (!response.ok) throw new Error('Error al iniciar la generación'); - return await response.json(); + const res = await api.post(endpoint, {}); + if (res.error) throw new Error(res.error || 'Error al iniciar la generación'); + return res.data; }, getTaskStatus: async (taskId: string) => { - const endpoint = `${BASE_URL}/v1/a76/reports/importacion/facturas/tasks/${taskId}`; - - const token = localStorage.getItem('access_token'); - const response = await fetch(endpoint, { - method: 'GET', - headers: { 'Authorization': `Bearer ${token}` } - }); - - if (!response.ok) throw new Error('Error al consultar estado'); - return await response.json(); + const endpoint = `/v1/a76/reports/importacion/facturas/tasks/${taskId}`; + const res = await api.get(endpoint); + if (res.error) throw new Error(res.error || 'Error al consultar estado'); + return res.data; }, triggerPackingListGeneration: async (invoiceId: number, companyId: number) => { const params = new URLSearchParams({ company_id: companyId.toString() }); - const endpoint = `${BASE_URL}/v1/a76/reports/importacion/packing-lists/${invoiceId}/download-async?${params.toString()}`; + const endpoint = `/v1/a76/reports/importacion/packing-lists/${invoiceId}/download-async?${params.toString()}`; - const token = localStorage.getItem('access_token'); - const response = await fetch(endpoint, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - }); - - if (!response.ok) throw new Error('Error al iniciar la generación de Packing List'); - return await response.json(); + const res = await api.post(endpoint, {}); + if (res.error) throw new Error(res.error || 'Error al iniciar la generación de Packing List'); + return res.data; }, getPackingListTaskStatus: async (taskId: string) => { - const endpoint = `${BASE_URL}/v1/a76/reports/importacion/packing-lists/tasks/${taskId}`; - - const token = localStorage.getItem('access_token'); - const response = await fetch(endpoint, { - method: 'GET', - headers: { 'Authorization': `Bearer ${token}` } - }); - - if (!response.ok) throw new Error('Error al consultar estado de Packing List'); - return await response.json(); + const endpoint = `/v1/a76/reports/importacion/packing-lists/tasks/${taskId}`; + const res = await api.get(endpoint); + if (res.error) throw new Error(res.error || 'Error al consultar estado de Packing List'); + return res.data; } }; \ No newline at end of file diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-transmission.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-transmission.ts index f95b0ade..ac26ef7b 100644 --- a/frontend/src/lib/api/dashboard/a76/reports/reports-transmission.ts +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-transmission.ts @@ -16,7 +16,19 @@ export const reportsTransmissionApi = { body: JSON.stringify(request) }); - if (!response.ok) throw new Error('Error al iniciar la generación del archivo de transmisión'); + if (!response.ok) { + let errorMessage = 'Error al iniciar la generación del archivo de transmisión'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -29,7 +41,19 @@ export const reportsTransmissionApi = { headers: { 'Authorization': `Bearer ${token}` } }); - if (!response.ok) throw new Error('Error al consultar estado de la transmisión'); + if (!response.ok) { + let errorMessage = 'Error al consultar estado de la transmisión'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -46,7 +70,19 @@ export const reportsTransmissionApi = { body: JSON.stringify(request) }); - if (!response.ok) throw new Error('Error al iniciar la generación temporal'); + if (!response.ok) { + let errorMessage = 'Error al iniciar la generación temporal'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -59,7 +95,19 @@ export const reportsTransmissionApi = { headers: { 'Authorization': `Bearer ${token}` } }); - if (!response.ok) throw new Error('Error al consultar estado de la transmisión temporal'); + if (!response.ok) { + let errorMessage = 'Error al consultar estado de la transmisión temporal'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -76,7 +124,19 @@ export const reportsTransmissionApi = { body: JSON.stringify(request) }); - if (!response.ok) throw new Error('Error al iniciar la generación definitiva'); + if (!response.ok) { + let errorMessage = 'Error al iniciar la generación definitiva'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -89,7 +149,19 @@ export const reportsTransmissionApi = { headers: { 'Authorization': `Bearer ${token}` } }); - if (!response.ok) throw new Error('Error al consultar estado de la transmisión definitiva'); + if (!response.ok) { + let errorMessage = 'Error al consultar estado de la transmisión definitiva'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); } }; diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-winsaai.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-winsaai.ts index bfad4d0f..dffcfaab 100644 --- a/frontend/src/lib/api/dashboard/a76/reports/reports-winsaai.ts +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-winsaai.ts @@ -23,7 +23,19 @@ export const reportsWinsaaiApi = { }, body: JSON.stringify(payload) }); - if (!response.ok) throw new Error('Error al iniciar la generación WINSAAI de facturas'); + if (!response.ok) { + let errorMessage = 'Error al iniciar la generación WINSAAI de facturas'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -33,7 +45,19 @@ export const reportsWinsaaiApi = { method: 'GET', headers: { 'Authorization': `Bearer ${token}` } }); - if (!response.ok) throw new Error('Error al consultar estado WINSAAI de facturas'); + if (!response.ok) { + let errorMessage = 'Error al consultar estado WINSAAI de facturas'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -61,7 +85,19 @@ export const reportsWinsaaiApi = { is_by_class: isByClass }) }); - if (!response.ok) throw new Error('Error al iniciar la generación WINSAAI de pedimentos'); + if (!response.ok) { + let errorMessage = 'Error al iniciar la generación WINSAAI de pedimentos'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, @@ -71,7 +107,19 @@ export const reportsWinsaaiApi = { method: 'GET', headers: { 'Authorization': `Bearer ${token}` } }); - if (!response.ok) throw new Error('Error al consultar estado WINSAAI de pedimentos'); + if (!response.ok) { + let errorMessage = 'Error al consultar estado WINSAAI de pedimentos'; + try { + const errorData = await response.json(); + errorMessage = errorData.detail || errorData.message || errorMessage; + } catch (e) { + try { + const text = await response.text(); + if (text) errorMessage = text; + } catch (e2) {} + } + throw new Error(errorMessage); + } return await response.json(); }, diff --git a/frontend/src/routes/dashboard/invoices/+page.svelte b/frontend/src/routes/dashboard/invoices/+page.svelte index 60807102..49913591 100644 --- a/frontend/src/routes/dashboard/invoices/+page.svelte +++ b/frontend/src/routes/dashboard/invoices/+page.svelte @@ -776,9 +776,9 @@ currentStatusFunction = invoicesReportsApi.getTaskStatus; progressDialogTitle = m.invoice_list_progress_title_pdf(); showProgressDialog = true; - } catch (error) { + } catch (error: any) { console.error(error); - toast.error(m.invoice_list_toasts_download_start_error()); + toast.error(error.message || m.invoice_list_toasts_download_start_error()); } } @@ -1507,9 +1507,9 @@ currentTaskId = task_id; currentStatusFunction = invoicesReportsApi.getTaskStatus; showProgressDialog = true; - } catch (error) { + } catch (error: any) { console.error(error); - toast.error(m.invoice_list_toasts_download_start_error()); + toast.error(error.message || m.invoice_list_toasts_download_start_error()); } }