"""Celery tasks for PDF parsing.""" import logging import hashlib from app.core.celery_app import celery_app from app.services.pdf_text import extract_text_from_pdf, PDFExtractionError from app.services.parser import parse_incrementables, ParsingError logger = logging.getLogger(__name__) @celery_app.task(bind=True, name="parse_pdf_task") def parse_pdf_task(self, pdf_bytes_hex: str, filename: str, document_ref: str = None): """ Celery task to parse PDF incrementables asynchronously. Args: self: Celery task instance pdf_bytes_hex: PDF content as hex string (to serialize) filename: Original filename document_ref: Optional document reference Returns: Dictionary with parsed data or error information """ task_id = self.request.id logger.info(f"Starting PDF parse task {task_id} for {filename}") try: # Convert hex back to bytes pdf_bytes = bytes.fromhex(pdf_bytes_hex) # Calculate SHA256 file_hash = hashlib.sha256(pdf_bytes).hexdigest() # Extract text try: text, page_count, extraction_method = extract_text_from_pdf(pdf_bytes) logger.info(f"Task {task_id}: Extracted {len(text)} chars from {page_count} pages") except PDFExtractionError as e: logger.error(f"Task {task_id}: Extraction failed - {str(e)}") return { "status": "failed", "error": "extraction_failed", "message": str(e), "task_id": task_id } # Parse incrementables try: parsed_data = parse_incrementables(text) logger.info(f"Task {task_id}: Successfully parsed incrementables") except ParsingError as e: logger.error(f"Task {task_id}: Parsing failed - {str(e)}") return { "status": "failed", "error": "parsing_failed", "message": str(e), "task_id": task_id } # Build successful response result = { "status": "completed", "task_id": task_id, "document": { "filename": filename, "pages": page_count, "sha256": file_hash, "document_ref": document_ref }, "incrementables": { "currency": parsed_data["currency"], "fletes": parsed_data["fletes"], "seguros": parsed_data["seguros"], "almacenaje_consolidacion": parsed_data["almacenaje_consolidacion"], "regalias": parsed_data["regalias"] }, "extraction": { "method": extraction_method, "anchors_found": parsed_data["anchors_found"], "warnings": parsed_data["warnings"] } } logger.info(f"Task {task_id}: Completed successfully") return result except Exception as e: logger.error(f"Task {task_id}: Unexpected error - {str(e)}", exc_info=True) return { "status": "failed", "error": "unexpected_error", "message": str(e), "task_id": task_id }