"""CRUD de SQL snippets de Metabase. Un snippet es un fragmento SQL reutilizable que se referencia en queries nativas con la sintaxis {{snippet: nombre}}. Ideal para CTEs comunes que se repiten en multiples cards. """ from .client import MetabaseClient def metabase_list_snippets(client: MetabaseClient, archived: bool = False) -> list[dict]: """Lista SQL snippets de Metabase. Endpoint: GET /api/native-query-snippet. Args: client: Cliente autenticado. archived: Si True, incluye snippets archivados. Returns: Lista de dicts con: id, name, content, description, collection_id, creator_id, archived, created_at, updated_at. Example: >>> snippets = metabase_list_snippets(client) >>> for s in snippets: ... print(s["name"], len(s["content"])) """ params = {} if archived: params["archived"] = "true" return client.request("GET", "/api/native-query-snippet", params=params) def metabase_get_snippet(client: MetabaseClient, snippet_id: int) -> dict: """Obtiene un SQL snippet de Metabase por su ID. Endpoint: GET /api/native-query-snippet/:id. Args: client: Cliente autenticado. snippet_id: ID numerico del snippet. Returns: Dict con campos completos del snippet: id, name, content, description, collection_id, creator_id, archived, created_at, updated_at. Raises: httpx.HTTPStatusError: 404 si el snippet no existe. Example: >>> snippet = metabase_get_snippet(client, 42) >>> print(snippet["name"], snippet["content"]) """ return client.request("GET", f"/api/native-query-snippet/{snippet_id}") def metabase_create_snippet( client: MetabaseClient, name: str, content: str, description: str = "", collection_id: int = 0, ) -> dict: """Crea un nuevo SQL snippet en Metabase. Endpoint: POST /api/native-query-snippet. Args: client: Cliente autenticado. name: Nombre del snippet. Se usa en queries con {{snippet: nombre}}. content: SQL del snippet. Puede ser una CTE completa, una subquery, o cualquier fragmento SQL reutilizable. description: Descripcion opcional del snippet. collection_id: ID de la coleccion donde guardar el snippet. Si es 0, se guarda en la raiz (Our analytics). Returns: Dict con el snippet creado, incluyendo el campo "id" asignado por Metabase. Raises: httpx.HTTPStatusError: 400 si el nombre ya existe o el SQL es invalido. Example: >>> snippet = metabase_create_snippet( ... client, ... "supply_orders_cte", ... '''WITH supply_full AS ( ... SELECT so.id, so.service_request_id ... FROM supply_orders so ... LEFT JOIN service_requests sr ON so.service_request_id = sr.id ... )''', ... description="CTE base de supply_orders con JOINs para cruce con NAV", ... ) >>> print(snippet["id"], snippet["name"]) >>> # Usar en una card: >>> # "{{snippet: supply_orders_cte}} SELECT ... FROM supply_full" """ body: dict = {"name": name, "content": content} if description: body["description"] = description if collection_id: body["collection_id"] = collection_id return client.request("POST", "/api/native-query-snippet", json=body) def metabase_update_snippet( client: MetabaseClient, snippet_id: int, **fields, ) -> dict: """Actualiza campos de un SQL snippet en Metabase. Endpoint: PUT /api/native-query-snippet/:id. Args: client: Cliente autenticado. snippet_id: ID numerico del snippet a actualizar. **fields: Campos a modificar. Campos validos: - name (str): Nuevo nombre del snippet. - content (str): Nuevo SQL del snippet. - description (str): Nueva descripcion. - collection_id (int): Nueva coleccion. - archived (bool): True para archivar, False para desarchivar. Returns: Dict con el snippet actualizado. Raises: httpx.HTTPStatusError: 404 si el snippet no existe. httpx.HTTPStatusError: 400 si los campos son invalidos. Example: >>> updated = metabase_update_snippet( ... client, 42, ... content="WITH supply_full AS (SELECT * FROM supply_orders)", ... description="Version simplificada", ... ) >>> print(updated["updated_at"]) """ valid_fields = {"name", "content", "description", "collection_id", "archived"} body = {k: v for k, v in fields.items() if k in valid_fields} return client.request("PUT", f"/api/native-query-snippet/{snippet_id}", json=body) def metabase_archive_snippet(client: MetabaseClient, snippet_id: int) -> dict: """Archiva un SQL snippet en Metabase. Wrapper sobre metabase_update_snippet con archived=True. Los snippets archivados no aparecen en el autocomplete de queries pero sus referencias existentes siguen funcionando. Endpoint: PUT /api/native-query-snippet/:id. Args: client: Cliente autenticado. snippet_id: ID numerico del snippet a archivar. Returns: Dict con el snippet archivado. Raises: httpx.HTTPStatusError: 404 si el snippet no existe. Example: >>> result = metabase_archive_snippet(client, 42) >>> print(result["archived"]) # True """ return metabase_update_snippet(client, snippet_id, archived=True)