nuevos
This commit is contained in:
@@ -18,6 +18,8 @@ from .controllers import coves_vu_controller, coves_rest_controller
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Logica de negocio para consumir el servicio SOAP de VUCEM y procesar la respuesta
|
# Logica de negocio para consumir el servicio SOAP de VUCEM y procesar la respuesta
|
||||||
|
|
||||||
|
|
||||||
async def consume_ws_get_cove(**kwargs):
|
async def consume_ws_get_cove(**kwargs):
|
||||||
"""
|
"""
|
||||||
Consume el servicio SOAP para obtener un COVE y procesar la respuesta.
|
Consume el servicio SOAP para obtener un COVE y procesar la respuesta.
|
||||||
@@ -40,7 +42,8 @@ async def consume_ws_get_cove(**kwargs):
|
|||||||
cove = kwargs['cove'].get('cove', None)
|
cove = kwargs['cove'].get('cove', None)
|
||||||
|
|
||||||
if not credenciales or not username or not cove:
|
if not credenciales or not username or not cove:
|
||||||
raise Exception("Credenciales o COVE no proporcionados correctamente")
|
raise Exception(
|
||||||
|
"Credenciales o COVE no proporcionados correctamente")
|
||||||
|
|
||||||
logger.info(f"Procesando COVE: {cove} para usuario: {username}")
|
logger.info(f"Procesando COVE: {cove} para usuario: {username}")
|
||||||
|
|
||||||
@@ -139,22 +142,18 @@ async def consume_ws_get_acuse_cove(**kwargs):
|
|||||||
'Accept-Encoding': 'gzip,deflate',
|
'Accept-Encoding': 'gzip,deflate',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
soap_xml = coves_vu_controller.generate_acuse_template(
|
soap_xml = coves_vu_controller.generate_acuse_template(
|
||||||
username=credenciales.get('user'),
|
username=credenciales.get('user'),
|
||||||
password=credenciales.get('password'),
|
password=credenciales.get('password'),
|
||||||
cove=kwargs['cove'].get('cove', None),
|
cove=kwargs['cove'].get('cove', None),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
response = await coves_vu_controller.make_request_async(
|
response = await coves_vu_controller.make_request_async(
|
||||||
"ventanilla-acuses-HA/ConsultaAcusesServiceWS?wsdl",
|
"ventanilla-acuses-HA/ConsultaAcusesServiceWS?wsdl",
|
||||||
data=soap_xml,
|
data=soap_xml,
|
||||||
headers=soap_headers
|
headers=soap_headers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if response is None:
|
if response is None:
|
||||||
raise Exception("No se obtuvo respuesta del servicio SOAP.")
|
raise Exception("No se obtuvo respuesta del servicio SOAP.")
|
||||||
|
|
||||||
@@ -175,11 +174,14 @@ async def consume_ws_get_acuse_cove(**kwargs):
|
|||||||
acuse_base64 = _extract_acuse_data(response.text)
|
acuse_base64 = _extract_acuse_data(response.text)
|
||||||
|
|
||||||
if acuse_base64 is None:
|
if acuse_base64 is None:
|
||||||
logger.error("No se encontró elemento acuseDocumento en la respuesta")
|
logger.error(
|
||||||
logger.debug(f"Contenido de respuesta (primeros 1000 chars): {response.text}")
|
"No se encontró elemento acuseDocumento en la respuesta")
|
||||||
|
logger.debug(
|
||||||
|
f"Contenido de respuesta (primeros 1000 chars): {response.text}")
|
||||||
else:
|
else:
|
||||||
logger.error("Error en respuesta SOAP o soap_error detectado")
|
logger.error("Error en respuesta SOAP o soap_error detectado")
|
||||||
logger.debug(f"Contenido de respuesta con error: {response.text if response else 'No response'}")
|
logger.debug(
|
||||||
|
f"Contenido de respuesta con error: {response.text if response else 'No response'}")
|
||||||
|
|
||||||
if acuse_base64 is None:
|
if acuse_base64 is None:
|
||||||
# Log de la respuesta SOAP para debugging
|
# Log de la respuesta SOAP para debugging
|
||||||
@@ -189,17 +191,16 @@ async def consume_ws_get_acuse_cove(**kwargs):
|
|||||||
detail="No se pudo extraer el acuse del documento de la respuesta SOAP. Verifique el log para más detalles."
|
detail="No se pudo extraer el acuse del documento de la respuesta SOAP. Verifique el log para más detalles."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
pdf_bytes = _decode_acuse_base64_content(acuse_base64)
|
pdf_bytes = _decode_acuse_base64_content(acuse_base64)
|
||||||
|
|
||||||
if not pdf_bytes:
|
if not pdf_bytes:
|
||||||
raise HTTPException(status_code=500, detail="No se pudo decodificar el documento del acuse")
|
raise HTTPException(
|
||||||
|
status_code=500, detail="No se pudo decodificar el documento del acuse")
|
||||||
|
|
||||||
# Validar que el PDF sea válido
|
# Validar que el PDF sea válido
|
||||||
if not pdf_bytes.startswith(b'%PDF'):
|
if not pdf_bytes.startswith(b'%PDF'):
|
||||||
logger.warning("El contenido decodificado no parece ser un PDF válido")
|
logger.warning("El contenido decodificado no parece ser un PDF válido")
|
||||||
|
|
||||||
|
|
||||||
# Mejorar el nombre del archivo usando todos los datos relevantes
|
# Mejorar el nombre del archivo usando todos los datos relevantes
|
||||||
pedimento = kwargs.get('pedimento', {})
|
pedimento = kwargs.get('pedimento', {})
|
||||||
pedimento_num = pedimento.get('pedimento', '')
|
pedimento_num = pedimento.get('pedimento', '')
|
||||||
@@ -230,6 +231,7 @@ async def consume_ws_get_acuse_cove(**kwargs):
|
|||||||
"acuse_update": acuse_status
|
"acuse_update": acuse_status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _decode_acuse_base64_content(base64_content): # Testeado
|
def _decode_acuse_base64_content(base64_content): # Testeado
|
||||||
"""
|
"""
|
||||||
Decodifica el contenido Base64 del acuse y limpia caracteres especiales.
|
Decodifica el contenido Base64 del acuse y limpia caracteres especiales.
|
||||||
@@ -254,7 +256,6 @@ def _decode_acuse_base64_content(base64_content): # Testeado
|
|||||||
# Remover caracteres no válidos para Base64
|
# Remover caracteres no válidos para Base64
|
||||||
cleaned_content = re.sub(r'[^A-Za-z0-9+/=]', '', cleaned_content)
|
cleaned_content = re.sub(r'[^A-Za-z0-9+/=]', '', cleaned_content)
|
||||||
|
|
||||||
|
|
||||||
# Agregar padding si es necesario
|
# Agregar padding si es necesario
|
||||||
missing_padding = len(cleaned_content) % 4
|
missing_padding = len(cleaned_content) % 4
|
||||||
if missing_padding:
|
if missing_padding:
|
||||||
@@ -274,6 +275,7 @@ def _decode_acuse_base64_content(base64_content): # Testeado
|
|||||||
except Exception as e2:
|
except Exception as e2:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _extract_acuse_data(soap_response_text: str) -> str:
|
def _extract_acuse_data(soap_response_text: str) -> str:
|
||||||
"""
|
"""
|
||||||
Extrae el contenido base64 del acuse desde la respuesta SOAP.
|
Extrae el contenido base64 del acuse desde la respuesta SOAP.
|
||||||
@@ -308,7 +310,8 @@ def _extract_acuse_data(soap_response_text: str) -> str:
|
|||||||
|
|
||||||
# Log de la estructura XML para debugging
|
# Log de la estructura XML para debugging
|
||||||
logger.debug(f"Elemento raíz: {root.tag}")
|
logger.debug(f"Elemento raíz: {root.tag}")
|
||||||
logger.debug(f"Namespaces encontrados: {root.nsmap if hasattr(root, 'nsmap') else 'No disponible'}")
|
logger.debug(
|
||||||
|
f"Namespaces encontrados: {root.nsmap if hasattr(root, 'nsmap') else 'No disponible'}")
|
||||||
|
|
||||||
# Buscar el elemento acuseDocumento con diferentes estrategias
|
# Buscar el elemento acuseDocumento con diferentes estrategias
|
||||||
namespaces = {
|
namespaces = {
|
||||||
@@ -319,11 +322,13 @@ def _extract_acuse_data(soap_response_text: str) -> str:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Estrategia 1: Con namespace ns3
|
# Estrategia 1: Con namespace ns3
|
||||||
acuse_elemento = root.find('.//ns3:responseConsultaAcuses/acuseDocumento', namespaces)
|
acuse_elemento = root.find(
|
||||||
|
'.//ns3:responseConsultaAcuses/acuseDocumento', namespaces)
|
||||||
|
|
||||||
if acuse_elemento is None:
|
if acuse_elemento is None:
|
||||||
# Estrategia 2: Con namespace ns1
|
# Estrategia 2: Con namespace ns1
|
||||||
acuse_elemento = root.find('.//ns1:responseConsultaAcuses/acuseDocumento', namespaces)
|
acuse_elemento = root.find(
|
||||||
|
'.//ns1:responseConsultaAcuses/acuseDocumento', namespaces)
|
||||||
|
|
||||||
if acuse_elemento is None:
|
if acuse_elemento is None:
|
||||||
# Estrategia 3: Sin namespace específico
|
# Estrategia 3: Sin namespace específico
|
||||||
@@ -341,28 +346,34 @@ def _extract_acuse_data(soap_response_text: str) -> str:
|
|||||||
|
|
||||||
if acuse_elemento is None:
|
if acuse_elemento is None:
|
||||||
# Log de todos los elementos para debugging
|
# Log de todos los elementos para debugging
|
||||||
logger.error("No se encontró elemento acuseDocumento. Elementos disponibles:")
|
logger.error(
|
||||||
|
"No se encontró elemento acuseDocumento. Elementos disponibles:")
|
||||||
for elem in root.iter():
|
for elem in root.iter():
|
||||||
logger.error(f" - {elem.tag}: {elem.text[:50] if elem.text else 'Sin contenido'}...")
|
logger.error(
|
||||||
|
f" - {elem.tag}: {elem.text[:50] if elem.text else 'Sin contenido'}...")
|
||||||
if 'acuse' in elem.tag.lower():
|
if 'acuse' in elem.tag.lower():
|
||||||
logger.error(f"Elemento similar encontrado: {elem.tag}")
|
logger.error(f"Elemento similar encontrado: {elem.tag}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if acuse_elemento is not None and acuse_elemento.text:
|
if acuse_elemento is not None and acuse_elemento.text:
|
||||||
logger.debug(f"Acuse encontrado, longitud: {len(acuse_elemento.text)} caracteres")
|
logger.debug(
|
||||||
|
f"Acuse encontrado, longitud: {len(acuse_elemento.text)} caracteres")
|
||||||
return acuse_elemento.text.strip()
|
return acuse_elemento.text.strip()
|
||||||
else:
|
else:
|
||||||
logger.error("Elemento acuseDocumento encontrado pero sin contenido de texto")
|
logger.error(
|
||||||
|
"Elemento acuseDocumento encontrado pero sin contenido de texto")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except ET.ParseError as e:
|
except ET.ParseError as e:
|
||||||
logger.error(f"Error parseando XML: {e}")
|
logger.error(f"Error parseando XML: {e}")
|
||||||
logger.debug(f"Contenido XML problemático: {xml_content[:500] if 'xml_content' in locals() else 'No disponible'}")
|
logger.debug(
|
||||||
|
f"Contenido XML problemático: {xml_content[:500] if 'xml_content' in locals() else 'No disponible'}")
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error general extrayendo acuse: {e}")
|
logger.error(f"Error general extrayendo acuse: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _get_file_name(**kwargs) -> dict:
|
def _get_file_name(**kwargs) -> dict:
|
||||||
pedimento = kwargs.get('pedimento', {})
|
pedimento = kwargs.get('pedimento', {})
|
||||||
pedimento_app = pedimento.get('pedimento_app', 'N/A')
|
pedimento_app = pedimento.get('pedimento_app', 'N/A')
|
||||||
@@ -371,7 +382,6 @@ def _get_file_name(**kwargs) -> dict:
|
|||||||
return _file_name
|
return _file_name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def change_cove_status(cove: dict, status: bool, pedimento: dict):
|
async def change_cove_status(cove: dict, status: bool, pedimento: dict):
|
||||||
data = {
|
data = {
|
||||||
"id": cove.get("id"),
|
"id": cove.get("id"),
|
||||||
@@ -385,6 +395,7 @@ async def change_cove_status(cove: dict, status: bool, pedimento: dict):
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
async def change_acuse_status(cove: dict, status: bool, pedimento: dict):
|
async def change_acuse_status(cove: dict, status: bool, pedimento: dict):
|
||||||
data = {
|
data = {
|
||||||
"id": cove.get("id"),
|
"id": cove.get("id"),
|
||||||
@@ -399,6 +410,7 @@ async def change_acuse_status(cove: dict, status: bool, pedimento: dict):
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
async def fetch_sign_and_cer(cadena_original: str, username: str, credenciales: dict):
|
async def fetch_sign_and_cer(cadena_original: str, username: str, credenciales: dict):
|
||||||
"""
|
"""
|
||||||
Obtiene certificado y llave, genera la firma para la cadena original.
|
Obtiene certificado y llave, genera la firma para la cadena original.
|
||||||
@@ -420,7 +432,8 @@ async def fetch_sign_and_cer(cadena_original: str, username: str, credenciales:
|
|||||||
# Obtener certificado como bytes
|
# Obtener certificado como bytes
|
||||||
cer = await coves_rest_controller.get_cer(credenciales['id'])
|
cer = await coves_rest_controller.get_cer(credenciales['id'])
|
||||||
if cer is None:
|
if cer is None:
|
||||||
raise Exception("No se pudo obtener el certificado para firmar el COVE")
|
raise Exception(
|
||||||
|
"No se pudo obtener el certificado para firmar el COVE")
|
||||||
|
|
||||||
# Convertir certificado a base64 string
|
# Convertir certificado a base64 string
|
||||||
certificado = base64.b64encode(cer).decode('utf-8')
|
certificado = base64.b64encode(cer).decode('utf-8')
|
||||||
@@ -430,23 +443,27 @@ async def fetch_sign_and_cer(cadena_original: str, username: str, credenciales:
|
|||||||
logger.debug("Obteniendo llave privada desde API")
|
logger.debug("Obteniendo llave privada desde API")
|
||||||
key_bytes = await coves_rest_controller.get_key(credenciales['id'])
|
key_bytes = await coves_rest_controller.get_key(credenciales['id'])
|
||||||
if key_bytes is None:
|
if key_bytes is None:
|
||||||
raise Exception("No se pudo obtener la llave privada para firmar el COVE")
|
raise Exception(
|
||||||
|
"No se pudo obtener la llave privada para firmar el COVE")
|
||||||
|
|
||||||
# Crear archivo temporal para la llave (requerido por cryptography)
|
# Crear archivo temporal para la llave (requerido por cryptography)
|
||||||
with tempfile.NamedTemporaryFile(delete=False, mode='wb') as tmp_key_file:
|
with tempfile.NamedTemporaryFile(delete=False, mode='wb') as tmp_key_file:
|
||||||
tmp_key_file.write(key_bytes)
|
tmp_key_file.write(key_bytes)
|
||||||
tmp_key_path = tmp_key_file.name
|
tmp_key_path = tmp_key_file.name
|
||||||
|
|
||||||
logger.debug(f"Llave privada guardada temporalmente en: {tmp_key_path}")
|
logger.debug(
|
||||||
|
f"Llave privada guardada temporalmente en: {tmp_key_path}")
|
||||||
|
|
||||||
# Generar firma usando el archivo temporal
|
# Generar firma usando el archivo temporal
|
||||||
firma = sign_chain_original(tmp_key_path, credenciales['efirma'], cadena_original)
|
firma = sign_chain_original(
|
||||||
|
tmp_key_path, credenciales['efirma'], cadena_original)
|
||||||
logger.debug("Firma generada exitosamente")
|
logger.debug("Firma generada exitosamente")
|
||||||
|
|
||||||
return firma, certificado, tmp_key_path
|
return firma, certificado, tmp_key_path
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error obteniendo certificado/llave o generando firma: {e}")
|
logger.error(
|
||||||
|
f"Error obteniendo certificado/llave o generando firma: {e}")
|
||||||
# Limpiar archivo temporal si existe
|
# Limpiar archivo temporal si existe
|
||||||
if 'tmp_key_path' in locals() and os.path.exists(tmp_key_path):
|
if 'tmp_key_path' in locals() and os.path.exists(tmp_key_path):
|
||||||
try:
|
try:
|
||||||
@@ -494,4 +511,3 @@ def sign_chain_original(key_path: str, password: str, cadena_original: str) -> s
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error firmando cadena original: {e}")
|
logger.error(f"Error firmando cadena original: {e}")
|
||||||
raise Exception(f"Error en sign_chain_original: {str(e)}")
|
raise Exception(f"Error en sign_chain_original: {str(e)}")
|
||||||
|
|
||||||
|
|||||||
@@ -165,12 +165,7 @@ async def put_pedimento_data(**kwargs) -> Dict[str, Any]:
|
|||||||
logger.error(f"Error inesperado al consumir servicio web: {e}")
|
logger.error(f"Error inesperado al consumir servicio web: {e}")
|
||||||
raise HTTPException(status_code=500, detail=f"Error al obtener datos del pedimento: {str(e)}")
|
raise HTTPException(status_code=500, detail=f"Error al obtener datos del pedimento: {str(e)}")
|
||||||
|
|
||||||
# Actualizar información del pedimento (crítico)
|
|
||||||
try:
|
|
||||||
result["pedimento_actualizado"] = await _update_pedimento_info(kwargs, xml_content)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error crítico al actualizar pedimento: {e}")
|
|
||||||
raise HTTPException(status_code=500, detail=f"Error al actualizar el pedimento: {str(e)}")
|
|
||||||
|
|
||||||
# Procesar COVEs (no crítico)
|
# Procesar COVEs (no crítico)
|
||||||
try:
|
try:
|
||||||
@@ -186,6 +181,13 @@ async def put_pedimento_data(**kwargs) -> Dict[str, Any]:
|
|||||||
logger.warning(f"Error al procesar documentos digitalizados: {e}")
|
logger.warning(f"Error al procesar documentos digitalizados: {e}")
|
||||||
result["edocuments_error"] = str(e)
|
result["edocuments_error"] = str(e)
|
||||||
|
|
||||||
|
# Actualizar información del pedimento (crítico)
|
||||||
|
try:
|
||||||
|
result["pedimento_actualizado"] = await _update_pedimento_info(kwargs, xml_content)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error crítico al actualizar pedimento: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=f"Error al actualizar el pedimento: {str(e)}")
|
||||||
|
|
||||||
logger.info("Procesamiento de pedimento completo finalizado")
|
logger.info("Procesamiento de pedimento completo finalizado")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user