import logging from fastapi import HTTPException from utils.helpers import soap_error from .controllers import partida_rest_controller, partida_vu_controller from ..common import create_service_response, create_error_response # Logger para el módulo logger = logging.getLogger(__name__) # Logica de negocio para consumir el servicio SOAP de VUCEM y procesar la respuesta async def consume_ws_get_partida(**kwargs): """ Consume el servicio SOAP para obtener un partida y procesar la respuesta. Args: **kwargs: Debe contener 'credencial', 'pedimento' y 'partida' Returns: Dict serializable con 'documento' y 'partida_put_response' Raises: Exception: Si hay errores en el procesamiento """ logger.info("Iniciando procesamiento de partidas") credenciales = kwargs.get('credencial') username = credenciales.get('user') pedimento_app = kwargs.get('pedimento', {}).get('pedimento_app', 'N/A') partida = kwargs.get('partida', {}) if not credenciales or not username or not partida: logger.error("Credenciales o Partida faltantes") raise HTTPException( status_code=400, detail=create_error_response( message="Datos incompletos para procesar la partida", errors=["Credenciales o datos de partida no proporcionados correctamente"], metadata={ "has_credentials": bool(credenciales), "has_username": bool(username), "has_partida": bool(partida) } ) ) logger.info(f"Procesando Partida {partida.get('numero', 'N/A')} para usuario {username}") # Generar template SOAP soap_xml = partida_vu_controller.generate_partidas_template( username=username, password=credenciales.get('password'), aduana=kwargs.get('pedimento', {}).get('aduana', 'N/A'), patente=kwargs.get('pedimento', {}).get('patente', 'N/A'), pedimento=kwargs.get('pedimento', {}).get('pedimento', 'N/A'), numero_operacion=kwargs.get('pedimento', {}).get('numero_operacion', ''), partida=partida.get('numero', '') ) soap_headers = { 'Content-Type': 'text/xml; charset=utf-8' } logger.info("Enviando petición SOAP a VUCEM") soap_response = await partida_vu_controller.make_request_async( "/ventanilla-ws-pedimentos/ConsultarPartidaService", data=soap_xml, headers=soap_headers ) if not soap_response: logger.error("No se recibió respuesta del servicio SOAP") raise HTTPException( status_code=500, detail=create_error_response( message="Error al contactar el servicio SOAP", errors=["No se obtuvo respuesta del servicio"], metadata={ "partida_numero": partida.get('numero'), "username": username } ) ) if soap_error(soap_response): error_file_name = f"vu_PT_{pedimento_app}_{partida.get('numero', '')}_ERROR.xml" try: document_response = await partida_rest_controller.post_document( soap_response=soap_response, organizacion=kwargs.get('pedimento').get('organizacion'), pedimento=kwargs.get('pedimento').get('id'), file_name=error_file_name, document_type=10, ) except Exception as e: logger.error(f"Error al guardar la respuesta de error: {e}") # Continuamos con el error original logger.error("Error en la respuesta del servicio SOAP") raise HTTPException( status_code=500, detail=create_error_response( message="Error en la respuesta del servicio SOAP", errors=["La respuesta contiene un error de VUCEM"], data={"soap_response": soap_response.text[:500] if hasattr(soap_response, 'text') else None}, metadata={ "partida_numero": partida.get('numero'), "error_file": error_file_name } ) ) logger.info("Respuesta SOAP exitosa, enviando documento") # Enviar documento _file_name = f"vu_PT_{pedimento_app}_{partida.get('numero', '')}.xml" try: document_response = await partida_rest_controller.post_document( soap_response=soap_response, organizacion=kwargs.get('pedimento').get('organizacion'), pedimento=kwargs.get('pedimento').get('id'), file_name=_file_name, document_type=1, ) except Exception as e: logger.error(f"Error al enviar documento: {e}") raise HTTPException( status_code=500, detail=create_error_response( message="Error al guardar el documento", errors=[str(e)], metadata={ "file_name": _file_name, "partida_numero": partida.get('numero') } ) ) logger.info("Documento enviado, actualizando status de Partida") # Actualizar status de la partida try: partida_status_response = await change_partida_status( partida=kwargs.get('partida'), status=True, pedimento=kwargs.get('pedimento') ) except Exception as e: logger.warning(f"Error al actualizar estado de la partida: {e}") # No fallamos aquí porque el documento ya se guardó exitosamente partida_status_response = None logger.info(f"Partida {partida.get('numero', '')} procesada exitosamente") return create_service_response( message=f"Partida {partida.get('numero', '')} procesada exitosamente", data={ "documento": document_response, "partida_update_response": partida_status_response, "file_name": _file_name }, metadata={ "document_type": 1, "pedimento_app": pedimento_app, "organizacion": kwargs.get('pedimento').get('organizacion'), "content_type": "application/xml" } ) async def change_partida_status(partida: dict, status: bool, pedimento: dict): """ Actualiza el estado de una partida. """ if not partida or not pedimento: logger.error("Datos insuficientes para actualizar estado de partida") raise HTTPException( status_code=400, detail=create_error_response( message="Datos incompletos para actualizar estado", errors=["Faltan datos de partida o pedimento"], metadata={ "has_partida": bool(partida), "has_pedimento": bool(pedimento) } ) ) data = { "id": partida.get("id"), "numero_partida": partida.get("numero"), "descargado": status, "pedimento": pedimento.get("id"), "organizacion": pedimento.get("organizacion"), } response = await partida_rest_controller.put_partida(partida_id=partida.get("id"), data=data) if not response: logger.error("Error al actualizar estado de la partida") raise HTTPException( status_code=500, detail=create_error_response( message="Error al actualizar estado de la partida", errors=["No se recibió respuesta del servicio"], metadata={"partida_id": partida.get("id")} ) ) return response