from asgiref.sync import async_to_sync from channels.layers import get_channel_layer from commerce.models import IntegrationConnection, IntegrationSyncRun COMMERCE_CONNECTIONS_GROUP = "commerce_connections" def _iso(value): return value.isoformat() if value else None def _run_payload(run: IntegrationSyncRun | None): if run is None: return None return { "id": str(run.pk), "connection": str(run.connection_id), "status": run.status, "task_id": run.task_id, "stage": run.stage, "stage_processed": run.stage_processed, "stage_total": run.stage_total, "last_progress_at": _iso(run.last_progress_at), "processed": run.processed, "created_products": run.created_products, "matched_products": run.matched_products, "stock_snapshots": run.stock_snapshots, "images": run.images, "image_errors": run.image_errors, "sales": run.sales, "costs": run.costs, "error": run.error, "started_at": _iso(run.started_at), "finished_at": _iso(run.finished_at), "created_at": _iso(run.created_at), } def build_connection_update( connection: IntegrationConnection, *, run: IntegrationSyncRun | None = None, ): return { "id": str(connection.pk), "status": connection.status, "account_name": connection.account_name, "last_error": connection.last_error, "last_tested_at": _iso(connection.last_tested_at), "last_sync_started_at": _iso(connection.last_sync_started_at), "last_sync_finished_at": _iso(connection.last_sync_finished_at), "last_stats": connection.last_stats, "task_id": connection.task_id, "auto_sync": connection.auto_sync, "sync_interval_minutes": connection.sync_interval_minutes, "next_sync_at": _iso(connection.next_sync_at), "updated_at": _iso(connection.updated_at), "recent_run": _run_payload(run), } def send_connection_update( connection: IntegrationConnection, *, run: IntegrationSyncRun | None = None, ): channel_layer = get_channel_layer() if channel_layer is None: return async_to_sync(channel_layer.group_send)( COMMERCE_CONNECTIONS_GROUP, { "type": "commerce_connection_updated", "connection": build_connection_update(connection, run=run), }, )