Files
microservice/api/api_v2/modules/partidas/services.py

221 lines
8.2 KiB
Python

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', '')
)
# Enviar documento de request a EFC
try:
file_name_request = f"vu_PT_{pedimento_app}_{partida.get('numero', '')}_REQUEST.xml"
document_response = await partida_rest_controller.post_document(
soap_response=soap_xml,
organizacion=kwargs.get('pedimento').get('organizacion'),
pedimento=kwargs.get('pedimento').get('id'),
file_name=file_name_request,
document_type=17, # Tipo de documento para petición de partidas
)
except Exception as e:
logger.error(f"Error al enviar documento request: {e}")
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