feat: Implement Advoware Document Sync Handler
- Added advoware_document_sync_step.py to handle 3-way merge sync for documents. - Introduced locking mechanism for per-Akte synchronization to allow parallel processing. - Integrated data fetching from EspoCRM, Windows files, and Advoware history. - Implemented 3-way merge logic for document synchronization and metadata updates. - Triggered document preview generation for new/changed documents. feat: Create Shared Steps Module - Added shared/__init__.py for shared steps across multiple modules. - Introduced generate_document_preview_step.py for generating document previews. - Implemented logic to download documents, generate previews, and upload to EspoCRM. feat: Add VMH Document xAI Sync Handler - Created document_xai_sync_step.py to manage document synchronization with xAI collections. - Handled create, update, and delete actions for documents in EspoCRM. - Integrated logic for triggering preview generation and managing xAI collections. - Implemented error handling and logging for synchronization processes.
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
"""
|
||||
VMH Document Sync Handler
|
||||
VMH Document xAI Sync Handler
|
||||
|
||||
Zentraler Sync-Handler für Documents mit xAI Collections
|
||||
Zentraler Sync-Handler für Documents mit xAI Collections.
|
||||
Triggers preview generation for new/changed files.
|
||||
|
||||
Verarbeitet:
|
||||
- vmh.document.create: Neu in EspoCRM → Prüfe ob xAI-Sync nötig
|
||||
- vmh.document.update: Geändert in EspoCRM → Prüfe ob xAI-Sync/Update nötig
|
||||
- vmh.document.delete: Gelöscht in EspoCRM → Remove from xAI Collections
|
||||
|
||||
Enqueues:
|
||||
- document.generate_preview: Bei new/changed Status
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
@@ -19,7 +23,7 @@ import hashlib
|
||||
import json
|
||||
|
||||
config = {
|
||||
"name": "VMH Document Sync Handler",
|
||||
"name": "VMH Document xAI Sync Handler",
|
||||
"description": "Zentraler Sync-Handler für Documents mit xAI Collections",
|
||||
"flows": ["vmh-documents"],
|
||||
"triggers": [
|
||||
@@ -27,7 +31,7 @@ config = {
|
||||
queue("vmh.document.update"),
|
||||
queue("vmh.document.delete")
|
||||
],
|
||||
"enqueues": []
|
||||
"enqueues": ["document.generate_preview"]
|
||||
}
|
||||
|
||||
|
||||
@@ -197,83 +201,21 @@ async def handle_create_or_update(entity_id: str, document: Dict[str, Any], sync
|
||||
if datei_status_lower in ['neu', 'geändert', 'new', 'changed']:
|
||||
ctx.logger.info("")
|
||||
ctx.logger.info("=" * 80)
|
||||
ctx.logger.info("🖼️ PREVIEW-GENERIERUNG STARTEN")
|
||||
ctx.logger.info("🖼️ TRIGGER PREVIEW-GENERIERUNG")
|
||||
ctx.logger.info(f" Datei-Status: {datei_status}")
|
||||
ctx.logger.info("=" * 80)
|
||||
|
||||
try:
|
||||
# 1. Hole Download-Informationen
|
||||
download_info = await sync_utils.get_document_download_info(entity_id, entity_type)
|
||||
|
||||
if not download_info:
|
||||
ctx.logger.warn("⚠️ Keine Download-Info verfügbar - überspringe Preview")
|
||||
else:
|
||||
ctx.logger.info(f"📥 Datei-Info:")
|
||||
ctx.logger.info(f" Filename: {download_info['filename']}")
|
||||
ctx.logger.info(f" MIME-Type: {download_info['mime_type']}")
|
||||
ctx.logger.info(f" Size: {download_info['size']} bytes")
|
||||
|
||||
# 2. Download File von EspoCRM
|
||||
ctx.logger.info(f"📥 Downloading file...")
|
||||
espocrm = sync_utils.espocrm
|
||||
file_content = await espocrm.download_attachment(download_info['attachment_id'])
|
||||
ctx.logger.info(f"✅ Downloaded {len(file_content)} bytes")
|
||||
|
||||
# 3. Speichere temporär für Preview-Generierung
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=f"_{download_info['filename']}") as tmp_file:
|
||||
tmp_file.write(file_content)
|
||||
tmp_path = tmp_file.name
|
||||
|
||||
try:
|
||||
# 4. Generiere Preview
|
||||
ctx.logger.info(f"🖼️ Generating preview (600x800 WebP)...")
|
||||
preview_data = await sync_utils.generate_thumbnail(
|
||||
tmp_path,
|
||||
download_info['mime_type'],
|
||||
max_width=600,
|
||||
max_height=800
|
||||
)
|
||||
|
||||
if preview_data:
|
||||
ctx.logger.info(f"✅ Preview generated: {len(preview_data)} bytes WebP")
|
||||
|
||||
# 5. Upload Preview zu EspoCRM und reset file status
|
||||
ctx.logger.info(f"📤 Uploading preview to EspoCRM...")
|
||||
await sync_utils.update_sync_metadata(
|
||||
entity_id,
|
||||
preview_data=preview_data,
|
||||
reset_file_status=True, # Reset status nach Preview-Generierung
|
||||
entity_type=entity_type
|
||||
)
|
||||
ctx.logger.info(f"✅ Preview uploaded successfully")
|
||||
else:
|
||||
ctx.logger.warn("⚠️ Preview-Generierung lieferte keine Daten")
|
||||
# Auch bei fehlgeschlagener Preview-Generierung Status zurücksetzen
|
||||
await sync_utils.update_sync_metadata(
|
||||
entity_id,
|
||||
reset_file_status=True,
|
||||
entity_type=entity_type
|
||||
)
|
||||
|
||||
finally:
|
||||
# Cleanup temp file
|
||||
try:
|
||||
os.remove(tmp_path)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Enqueue preview generation event
|
||||
await ctx.emit('document.generate_preview', {
|
||||
'entity_id': entity_id,
|
||||
'entity_type': entity_type
|
||||
})
|
||||
ctx.logger.info(f"✅ Preview generation event emitted for {entity_id}")
|
||||
except Exception as e:
|
||||
ctx.logger.error(f"❌ Fehler bei Preview-Generierung: {e}")
|
||||
import traceback
|
||||
ctx.logger.error(traceback.format_exc())
|
||||
ctx.logger.error(f"❌ Fehler beim Triggern der Preview-Generierung: {e}")
|
||||
# Continue - Preview ist optional
|
||||
|
||||
ctx.logger.info("")
|
||||
ctx.logger.info("=" * 80)
|
||||
ctx.logger.info("✅ PREVIEW-VERARBEITUNG ABGESCHLOSSEN")
|
||||
ctx.logger.info("=" * 80)
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
Reference in New Issue
Block a user