import requests from datetime import datetime from dateutil import parser import pytz import os config = { "name": "EspoCRMStatusCheck", "type": "cron", "cron": "*/1 * * * *", # Alle 5 Minuten (korrekte Feldname) "description": "Checks CVmhErstgespraech for expired nchsterAnruf and updates status", "emits": [] # Leer, da keine Events emittiert werden } async def handler(input, context): # Korrekte Signatur: input (oft None für Cron), context (erforderlich) # EspoCRM API Konfiguration api_url = "https://crm.bitbylaw.com/api/v1" api_key = os.getenv("ESPOCRM_MARVIN_API_KEY") if not api_key: context.logger.error("ESPOCRM_API_KEY not set in environment") return headers = {"X-Api-Key": api_key} # Aktuelle Zeit in UTC now = datetime.now(pytz.UTC) # Hole Einträge mit Status "Zurückgestellt" oder "Warte auf neuen Anruf" try: response = requests.get( f"{api_url}/CVmhErstgespraech", headers=headers, params={ "where": [ { "type": "or", "value": [ {"type": "equals", "attribute": "status", "value": "Zurückgestellt"}, {"type": "equals", "attribute": "status", "value": "Warte auf neuen Anruf"} ] } ], "select": "id,status,nchsterAnruf" } ) response.raise_for_status() entries = response.json().get("list", []) context.logger.info(f"Found {len(entries)} matching CVmhErstgespraech entries") except requests.RequestException as e: context.logger.error(f"Failed to fetch entries: {str(e)}") return updated_count = 0 # Prüfe und aktualisiere Einträge for entry in entries: entry_id = entry["id"] status = entry["status"] nchster_anruf = entry.get("nchsterAnruf") if not nchster_anruf: context.logger.warning(f"Entry {entry_id} has no nchsterAnruf, skipping") continue # Parse Timestamp try: nchster_anruf_dt = parser.isoparse(nchster_anruf).astimezone(pytz.UTC) except ValueError as e: context.logger.error(f"Invalid nchsterAnruf for {entry_id}: {str(e)}") continue # Prüfe, ob abgelaufen if nchster_anruf_dt < now: context.logger.info(f"Entry {entry_id} expired (nchsterAnruf: {nchster_anruf}), updating status") try: update_response = requests.put( f"{api_url}/CVmhErstgespraech/{entry_id}", headers=headers, json={"status": "Abgelaufen"} # Passe den Zielstatus an ) update_response.raise_for_status() context.logger.info(f"Updated status for {entry_id} to Abgelaufen") # Speichere im State für Tracking await context.state.set(f"crm_update_{entry_id}", { "updated_at": now.isoformat(), "old_status": status, "new_status": "Abgelaufen" }) updated_count += 1 except requests.RequestException as e: context.logger.error(f"Failed to update {entry_id}: {str(e)}") else: context.logger.debug(f"Entry {entry_id} not expired (nchsterAnruf: {nchster_anruf})") context.logger.info(f"Cron-Step completed: {updated_count} entries updated")