fix: peticiones.py usa pedimento_app + post_or_update_document (T2025-09-004)

El stack viejo de descarga (utils/peticiones.py, via api_v1 + signal en backend)
armaba el nombre con campos crudos en vez de pedimento_app (vu_EDC, app 042_240_...)
y posteaba con post_document (sin reemplazar) -> documentos sin ligar la FK y
partidas duplicadas.

Las 8 funciones get_soap_* (pedimento_completo, remesas, partidas, acuse,
acuseCOVE, estado, edocument, cove) ahora arman el nombre con pedimento_app
(identico a api_v2) y postean con post_or_update_document + identifier.
Corrige tambien el prefijo vu_EDC -> vu_ED.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 15:26:41 -06:00
parent 1e06d1a2bf
commit 95b63f32b5
3 changed files with 134 additions and 24 deletions

View File

@@ -340,10 +340,61 @@ class APIController:
"""
return await self._make_request_async('PUT', f'customs/pedimentos/{pedimento_id}/', data=data)
async def post_or_update_document(
self, soap_response=None, organizacion: str = None,
pedimento: str = None, file_name: str = None,
document_type: int = None, fuente: int = 2,
identifier: str = None, binary_content: bytes = None,
) -> Dict[str, Any]:
"""
Guarda un documento VU creando PRIMERO el nuevo y, solo si se guardó con
éxito, eliminando los previos del mismo tipo/pedimento/identificador. Así
se evitan duplicados en ejecuciones recurrentes (T2025-09-004). Mismo
comportamiento que la otra clase del módulo; aquí lo usa peticiones.py.
identifier: cadena única del documento dentro del pedimento (número de
cove / e-document) usada como filtro archivo__icontains.
"""
new_document = await self.post_document(
soap_response=soap_response,
binary_content=binary_content,
organizacion=organizacion,
pedimento=pedimento,
file_name=file_name,
document_type=document_type,
fuente=fuente,
)
if not new_document:
logger.error(f"post_or_update_document: no se guardó el documento nuevo (document_type={document_type}, identifier={identifier}); se conservan los previos")
return new_document
new_id = new_document.get('id') if isinstance(new_document, dict) else None
if not new_id:
logger.warning(f"post_or_update_document: respuesta sin id, se omite limpieza de previos (document_type={document_type}, identifier={identifier})")
return new_document
try:
query = f'record/documents/?pedimento={pedimento}&document_type={document_type}'
if identifier:
query += f'&archivo__icontains={identifier}'
existing = await self._make_request_async('GET', query)
if existing:
results = existing.get('results', existing) if isinstance(existing, dict) else existing
if isinstance(results, list):
for previous in results:
previous_id = previous.get('id')
if previous_id and previous_id != new_id:
await self._make_request_async('DELETE', f'record/documents/{previous_id}/')
logger.info(f"Documento VU previo eliminado: id={previous_id}, document_type={document_type}, identifier={identifier}")
except Exception as e:
logger.warning(f"No se pudo verificar/eliminar documento VU existente (document_type={document_type}, identifier={identifier}): {e}")
return new_document
async def post_document(self, soap_response=None, organizacion: str = None, pedimento: str = None, file_name: str = None, document_type: int = 2, binary_content: bytes = None, fuente: int = 2) -> Dict[str, Any]:
"""
Método para enviar documentos (XML, PDF, etc.) a la API.
Args:
soap_response: Respuesta del servicio SOAP (para archivos XML)
organizacion: UUID de la organización (requerido)