# Caso de uso - Consultar qué facturas tienen CAE desde la grilla

**URL:** <https://bc.finneg.com/t/caso-de-uso-consultar-que-facturas-tienen-cae-desde-la-grilla/6930>\
**Category:** CORE\
**Tags:** caso-de-uso, guest-code, como-se-usa, instructivo\
**Created:** [16 Junio, 2026 19:45 UTC](https://bc.finneg.com/t/caso-de-uso-consultar-que-facturas-tienen-cae-desde-la-grilla/6930 "2026-06-16T19:45:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paula](https://bc.finneg.com/user_avatar/bc.finneg.com/paula/32/27146_2.png) [@Paula](https://bc.finneg.com/u/Paula)\
**Post date:** [16 Junio, 2026 19:45 UTC](https://bc.finneg.com/t/caso-de-uso-consultar-que-facturas-tienen-cae-desde-la-grilla/6930/1 "2026-06-16T19:45:04Z")

</div>

# Uso de Guest code con bproc de viewer

_Este documento muestra cómo utilizar la herramienta guest code y un bproc de tipo viewer para consultar qué facturas tienen CAE desde la grilla de facturas de venta._

## Descripción del caso

El caso consiste en poder consultar, desde la grilla, qué facturas tienen CAE y cuáles no

## Configuraciones

Se debe configurar

**1 - Guest code:** Para realizar el script utilizamos la IA Fini. Se le indica la necesidad junto con el contexto necesario y luego de algunas iteraciones se obtiene el script deseado:

```auto
# Script para Finnegans GO Guest Code 
# Verificación de CAE en Facturas de Venta
# Fix: reemplaza os + requests por obtener_entidad de finnegans.api

import json

from finnegans.scripting import request, HTTPResponse
from finnegans.api import obtener_entidad, ApiException

# ─────────────────────────────────────────────
# CONFIGURACIÓN
# ─────────────────────────────────────────────
INVOICE_API = "facturaVenta"
CAE_FIELD = "CAE"

# ─────────────────────────────────────────────
# HELPERS — LECTURA DEL REQUEST
# ─────────────────────────────────────────────
def _get_selected_records() -> list:
    """
    Lee los registros seleccionados desde el body del request.
    Soporta payload list[dict] o dict directamente.
    """
    body_bytes = request.get_body()
    if not body_bytes:
        return []
    try:
        payload = json.loads(body_bytes.decode("utf-8"))
        if isinstance(payload, list) and payload:
            return payload[0].get("selectedRecords", [])
        if isinstance(payload, dict):
            return payload.get("selectedRecords", [])
    except Exception:
        pass
    return []

# ─────────────────────────────────────────────
# HELPERS — CLASIFICACIÓN
# ─────────────────────────────────────────────
def _clasificar_facturas(records: list) -> tuple:
    """
    Para cada registro obtiene la factura de venta via obtener_entidad
    y la clasifica según la presencia del campo CAE.
    Retorna: (con_cae, sin_cae, errores)
    """
    con_cae = []
    sin_cae = []
    errores = []

    for record in records:
        transaccion_id = str(record.get("TRANSACCIONID", "")).strip()
        numero_doc = record.get("DOCUMENTO") or transaccion_id

        if not transaccion_id:
            errores.append(("?", "No se encontro TRANSACCIONID en el registro"))
            continue

        try:
            factura = obtener_entidad(INVOICE_API, numero_doc)
            cae_val = factura.get(CAE_FIELD, "") if isinstance(factura, dict) else ""
            if cae_val and str(cae_val).strip():
                con_cae.append((transaccion_id, str(numero_doc), str(cae_val).strip()))
            else:
                sin_cae.append((transaccion_id, str(numero_doc)))
        except ApiException as e:
            errores.append((transaccion_id, f"ApiException: {str(e)}"))
        except Exception as e:
            errores.append((transaccion_id, str(e)))

    return con_cae, sin_cae, errores

# ─────────────────────────────────────────────
# HELPERS — CONSTRUCCIÓN HTML
# ─────────────────────────────────────────────
def _build_html(con_cae: list, sin_cae: list, errores: list) -> str:
    total = len(con_cae) + len(sin_cae) + len(errores)

    filas_con = "".join(
        "<tr><td>" + fid + "</td><td>" + num + "</td>"
        "<td style='color:#1a7f3c;font-weight:bold'>" + cae + "</td></tr>"
        for fid, num, cae in con_cae
    )
    filas_sin = "".join(
        "<tr><td>" + fid + "</td><td>" + num + "</td>"
        "<td style='color:#c0392b;font-weight:bold'>Sin CAE</td></tr>"
        for fid, num in sin_cae
    )
    filas_err = "".join(
        "<tr><td>" + fid + "</td>"
        "<td colspan='2' style='color:#e67e22'>" + err + "</td></tr>"
        for fid, err in errores
    )

    seccion_con = (
        "<h3 style='color:#1a7f3c'>Facturas CON CAE (" + str(len(con_cae)) + ")</h3>"
        "<table><thead><tr><th>ID</th><th>Numero Comprobante</th><th>CAE</th></tr></thead>"
        "<tbody>" + filas_con + "</tbody></table>"
    ) if con_cae else ""

    seccion_sin = (
        "<h3 style='color:#c0392b'>Facturas SIN CAE (" + str(len(sin_cae)) + ")</h3>"
        "<table><thead><tr><th>ID</th><th>Numero Comprobante</th><th>Estado</th></tr></thead>"
        "<tbody>" + filas_sin + "</tbody></table>"
    ) if sin_cae else ""

    seccion_err = (
        "<h3 style='color:#e67e22'>Errores (" + str(len(errores)) + ")</h3>"
        "<table><thead><tr><th>ID</th><th colspan='2'>Detalle</th></tr></thead>"
        "<tbody>" + filas_err + "</tbody></table>"
    ) if errores else ""

    badge_err = (
        "<span style='color:#e67e22'> Errores: <strong>" + str(len(errores)) + "</strong></span>"
    ) if errores else ""

    return (
        "<!DOCTYPE html><html lang='es'><head><meta charset='UTF-8'>"
        "<style>"
        "body{font-family:Arial,sans-serif;padding:24px;color:#333}"
        "h2{color:#2c3e50;border-bottom:2px solid #4a90d9;padding-bottom:6px}"
        "h3{margin-top:28px}"
        ".resumen{background:#eaf2fb;border-left:5px solid #4a90d9;"
        "padding:14px 18px;border-radius:4px;margin-bottom:24px}"
        ".resumen span{margin-right:20px;font-size:1.05em}"
        "table{border-collapse:collapse;width:100%;margin-top:8px}"
        "th{background:#4a90d9;color:#fff;padding:9px 14px;text-align:left}"
        "td{padding:8px 14px;border-bottom:1px solid #dde4ec}"
        "tr:hover td{background:#f4f8fe}"
        "</style></head><body>"
        "<h2>Verificacion de CAE - Facturas de Venta</h2>"
        "<div class='resumen'>"
        "<span>Total procesadas: <strong>" + str(total) + "</strong></span>"
        "<span style='color:#1a7f3c'>Con CAE: <strong>" + str(len(con_cae)) + "</strong></span>"
        "<span style='color:#c0392b'>Sin CAE: <strong>" + str(len(sin_cae)) + "</strong></span>"
        + badge_err +
        "</div>"
        + seccion_con + seccion_sin + seccion_err +
        "</body></html>"
    )

# ─────────────────────────────────────────────
# PUNTO DE ENTRADA
# ─────────────────────────────────────────────
def main():
    # 1. Leer registros seleccionados del body
    records = _get_selected_records()

    if not records:
        return HTTPResponse(
            400,
            body=json.dumps(
                {"error": "No se recibieron registros. Selecciona al menos una factura antes de ejecutar."},
                ensure_ascii=False,
            ),
        )

    # 2. Clasificar según presencia de CAE
    con_cae, sin_cae, errores = _clasificar_facturas(records)

    # 3. Construir y retornar respuesta HTML
    html = _build_html(con_cae, sin_cae, errores)

    return HTTPResponse(200, body=html)

```

**2 - Bproc:** En este caso se utilizó un bproc de tipo viewer y se seleccionó la viewer Facturas de Venta

 ![image](https://bc.finneg.com/uploads/default/original/3X/e/b/eb6062704b33448987987473c255ada497af167d.png)  
 ![image](https://bc.finneg.com/uploads/default/original/3X/8/6/863e02fac0538903eb02ef07093ed792d8b1ba18.png)

En el campo URL se pega la obtenida en el guest code

## Resultado

Desde la grilla de facturas de venta se seleccionan las facturas que se quieren consultar si tienen cae.

Se presiona el botón consultar cae

 ![image](https://bc.finneg.com/uploads/default/original/3X/9/6/96548e7df47fe7dad0cb87fc0a8d0e184096b78b.png)

 ![image](https://bc.finneg.com/uploads/default/original/3X/6/d/6d9059cbd7be8eb61768f51f987b32ecf1bc1758.png)
