diff --git a/api/api_v2/modules/coves/tasks.py b/api/api_v2/modules/coves/tasks.py index 863dd18..7f17492 100644 --- a/api/api_v2/modules/coves/tasks.py +++ b/api/api_v2/modules/coves/tasks.py @@ -3,6 +3,7 @@ import logging from celery import Celery from celery_app import celery_app from typing import Dict, Any +from fastapi import HTTPException as _HTTPException from .services import consume_ws_get_cove, consume_ws_get_acuse_cove from api.api_v2.modules.tasks.services import update_task, register_task @@ -83,7 +84,9 @@ def process_cove_request(self, cove_request: Dict[str, Any]) -> Dict[str, Any]: ) except Exception as update_error: logger.error(f"No se pudo actualizar el estado de la tarea: {update_error}") - + + if isinstance(e, _HTTPException): + raise RuntimeError(f"HTTP {e.status_code}: {e.detail}") from None raise @@ -159,5 +162,7 @@ def process_acuse_cove_request(self, cove_request: Dict[str, Any]) -> Dict[str, ) except Exception as update_error: logger.error(f"No se pudo actualizar el estado de la tarea: {update_error}") - + + if isinstance(e, _HTTPException): + raise RuntimeError(f"HTTP {e.status_code}: {e.detail}") from None raise \ No newline at end of file diff --git a/api/api_v2/modules/edocs/tasks.py b/api/api_v2/modules/edocs/tasks.py index e6ba426..927b8b1 100644 --- a/api/api_v2/modules/edocs/tasks.py +++ b/api/api_v2/modules/edocs/tasks.py @@ -1,10 +1,11 @@ import asyncio import logging import time -from celery_app import celery_app +from celery_app import celery_app from typing import Dict +from fastapi import HTTPException as _HTTPException -from .services import obtener_edoc +from .services import obtener_edoc from api.api_v2.modules.tasks.services import register_task, update_task # Logger para el módulo @@ -92,7 +93,9 @@ def process_edoc_download_request(self, edoc_data: Dict) -> Dict: ) except Exception as update_error: logger.error(f"Error actualizando estado de tarea: {update_error}") - + + if isinstance(e, _HTTPException): + raise RuntimeError(f"HTTP {e.status_code}: {e.detail}") from None raise finally: # Cerrar el loop para liberar recursos diff --git a/api/api_v2/modules/partidas/tasks.py b/api/api_v2/modules/partidas/tasks.py index 91d58ab..8d959b8 100644 --- a/api/api_v2/modules/partidas/tasks.py +++ b/api/api_v2/modules/partidas/tasks.py @@ -4,6 +4,7 @@ import time from celery import Celery from celery_app import celery_app from typing import Dict, Any +from fastapi import HTTPException as _HTTPException from .services import consume_ws_get_partida from api.api_v2.modules.tasks.services import register_task, update_task @@ -89,6 +90,8 @@ def process_partida_request(self, partida_request: Dict[str, Any]) -> Dict[str, ) except Exception as update_error: logger.error(f"Error al actualizar estado de tarea: {update_error}") + if isinstance(e, _HTTPException): + raise RuntimeError(f"HTTP {e.status_code}: {e.detail}") from None raise finally: # Limpiar el event loop diff --git a/api/api_v2/modules/pedimentos/tasks.py b/api/api_v2/modules/pedimentos/tasks.py index 9169829..9aa03c8 100644 --- a/api/api_v2/modules/pedimentos/tasks.py +++ b/api/api_v2/modules/pedimentos/tasks.py @@ -1,7 +1,8 @@ -from celery_app import celery_app +from celery_app import celery_app from .services import put_pedimento_data import asyncio import logging +from fastapi import HTTPException as _HTTPException from ..tasks.services import register_task, update_task logger = logging.getLogger(__name__) @@ -84,8 +85,10 @@ def process_pedimento_completo_request(self, pedimento_data: dict): ) except Exception as update_error: logger.error(f"Error actualizando estado de tarea: {update_error}") - + # Re-lanzar la excepción para que Celery la marque como fallida + if isinstance(e, _HTTPException): + raise RuntimeError(f"HTTP {e.status_code}: {e.detail}") from None raise finally: loop.close() \ No newline at end of file diff --git a/api/api_v2/modules/remesas/services.py b/api/api_v2/modules/remesas/services.py index 23a0615..c7f802f 100644 --- a/api/api_v2/modules/remesas/services.py +++ b/api/api_v2/modules/remesas/services.py @@ -87,8 +87,33 @@ async def obtener_remesa(**kwargs) -> Dict[str, Any]: ) # Generar nombre de archivo file_name = f"vu_RM_{pedimento_data.get('pedimento_app', 'unknown')}.xml" + + # "No hay información" NO es un error — VUCEM confirma que el pedimento no tiene remesas. + # No se crea documento de error; se corrige el flag en el pedimento. + _SIN_REMESAS = 'No hay información para la búsqueda solicitada' + if hasattr(soap_response, 'text') and _SIN_REMESAS in soap_response.text: + pedimento_id = pedimento_data.get('id') + logger.info( + f"Pedimento {pedimento_data.get('pedimento_app')} no tiene remesas " + f"(confirmado por VUCEM). Corrigiendo flag remesas=False." + ) + try: + await remesa_rest_controller._make_request_async( + 'PATCH', + f'customs/pedimentos/{pedimento_id}/', + data={'remesas': False}, + ) + except Exception as patch_err: + logger.warning(f"No se pudo actualizar remesas=False para {pedimento_id}: {patch_err}") + + return create_service_response( + message="Pedimento sin remesas confirmado por VUCEM", + data={"remesas": False}, + metadata={"pedimento_app": pedimento_data.get('pedimento_app')}, + ) + if soap_error(soap_response): - + file_name = f"vu_RM_{pedimento_data.get('pedimento_app', 'unknown')}_ERROR.xml" document_response = await remesa_rest_controller.post_or_update_document( soap_response=soap_response, @@ -97,38 +122,31 @@ async def obtener_remesa(**kwargs) -> Dict[str, Any]: file_name=file_name, document_type=16, ) - - # Aquí necesitamos extraer el mensaje de error real + error_message = "Error en la respuesta del servicio SOAP" - - # Intentar extraer mensaje de error del XML de respuesta + if hasattr(soap_response, 'text') and soap_response.text: try: import xml.etree.ElementTree as ET root = ET.fromstring(soap_response.text) - - # Buscar mensajes de error comunes en respuestas SOAP de VUCEM - # Esto puede variar según el servicio, pero comúnmente buscan: + for fault in root.findall('.//{http://schemas.xmlsoap.org/soap/envelope/}Fault'): - faultcode = fault.find('.//faultcode') faultstring = fault.find('.//faultstring') if faultstring is not None and faultstring.text: error_message = faultstring.text break - - # También podría estar en una estructura de error específica de VUCEM + for error in root.findall('.//{http://www.ventanillaunica.gob.mx/common/ws/oxml/respuesta}error'): msg = error.find('.//{http://www.ventanillaunica.gob.mx/common/ws/oxml/respuesta}message') if msg is not None and msg.text: error_message = msg.text break - + except Exception as parse_error: logger.error(f"Error al parsear respuesta SOAP para extraer mensaje: {parse_error}") - - # Lanzar excepción con el mensaje de error real + raise HTTPException( - status_code=500, + status_code=500, detail=f"Error en la respuesta del servicio SOAP: {error_message}" ) # Enviar documento diff --git a/api/api_v2/modules/remesas/tasks.py b/api/api_v2/modules/remesas/tasks.py index 058f917..5d4ef39 100644 --- a/api/api_v2/modules/remesas/tasks.py +++ b/api/api_v2/modules/remesas/tasks.py @@ -2,6 +2,7 @@ from celery_app import celery_app from .services import post_remesa_data import asyncio import logging +from fastapi import HTTPException as _HTTPException from ..tasks.services import register_task, update_task logger = logging.getLogger(__name__) @@ -98,6 +99,8 @@ def process_remesa_request(self, remesa_request: dict) -> dict: logger.error(f"Error actualizando estado de tarea: {update_error}") # Re-lanzar la excepción para que Celery la marque como fallida + if isinstance(e, _HTTPException): + raise RuntimeError(f"HTTP {e.status_code}: {e.detail}") from None raise finally: diff --git a/controllers/RESTController.py b/controllers/RESTController.py index 30688ee..1263165 100644 --- a/controllers/RESTController.py +++ b/controllers/RESTController.py @@ -58,6 +58,8 @@ class APIRESTController: response = await client.post(url, json=data, headers=self.headers) elif method.upper() == 'PUT': response = await client.put(url, json=data, headers=self.headers) + elif method.upper() == 'PATCH': + response = await client.patch(url, json=data, headers=self.headers) elif method.upper() == 'DELETE': response = await client.delete(url, headers=self.headers) else: @@ -554,6 +556,8 @@ class APIController: print(f"response >>>> {response}") elif method.upper() == 'PUT': response = await client.put(url, json=data, headers=self.headers) + elif method.upper() == 'PATCH': + response = await client.patch(url, json=data, headers=self.headers) elif method.upper() == 'DELETE': response = await client.delete(url, headers=self.headers) else: