Saltar al contenido principal

Tablas dinámicas (WebApp Tables)

¿Necesita guardar en Zauru información que el sistema no maneja de fábrica —un catálogo propio, el historial de versiones de un registro o un listado de opciones para su webapp? Las tablas dinámicas (WebApp Tables) le permiten ampliar cualquier funcionalidad que su operación requiera, sin esperar a que el sistema la incluya. Cada tabla incluye su CRUD completo (crear, editar, eliminar y listar), acepta estructuras de números y texto, y puede crecer tanto como usted la necesite.

Creación y edición de WebApp Table

Para crear una WebApp table basta con dirigirnos en el menú a la opción: WebApps => Tablas => New WebApp Table

WebAppTable listado 1

En el siguiente ejemplo, una empresa desea almacenar en Zauru los diferentes tipos de moneda que pueden recibir, por ejemplo (moneda local, moneda de plata, moneda de oro, etc...), en este caso hipotético, este listado no se maneja explicitamente en Zauru, por lo cual recurrimos a la ayuda de una webapp table en donde podemos definir una estructura para ese listado.

Nuestro listado se llamará "Tipos de monedas", el cuál necesitamos que almacene el nombre y un estado.

No preocuparse por el id único para cada opción, ya que automáticamente zauru le creará un id único a cada registro de nuestra webapp table.

New webapp table example

Con nuestra estructura lista, podemos ahora dar en la opción (Crear WebApp Table)

Con eso nuestra webapp table se creará y ya la tendremos lista para ser utilizada.

example newwebapp table created

Ahora podemos hacer uso de nuestra nueva webapp table para ingresar registros, o actualizar los ya existentes.

EjemploListadoRegistrosWebAppTable

Con esto, su tabla dinámica queda creada y lista para recibir registros. Lo que sigue naturalmente es llenarla desde el sistema o conectarla con su webapp personalizada; más adelante, si sus aplicaciones la consultan con frecuencia, también podrá sincronizarla con una base de datos externa.

Tipos de datos de las columnas

Cada columna admite uno de estos tipos de datos:

TipoValor en la APIDescripción
NumerointNúmeros enteros. Se muestran con separador de miles.
TextostringTexto libre.
CondiciónbooleanValores de verdadero o falso, mostrados con un ícono. Se interpretan como verdaderos los valores true, t, 1, yes, y y si.
FechadateFechas. Aceptan formato ISO (2026-08-27), dd/mm/yyyy y otros formatos comunes; se muestran en formato largo.
DecimaldecimalNúmeros con decimales, mostrados con separadores de miles y decimales, sin ceros finales.
JSONjsonEstructuras JSON (objetos o arreglos), mostradas formateadas.
JSON (jsonb)jsonbIgual que JSON; se almacena como tipo jsonb en la base de datos.
JSON (URLs de archivos)jsonb_urlsUna URL o un listado de URLs. En el show de un documento vinculado, cada URL se muestra como imagen en miniatura si apunta a una imagen (jpg, png, gif, webp, svg, entre otras extensiones) o como botón de descarga en cualquier otro caso.

Configuración de la tabla y sus columnas

  • Cargar en show del documento relacionado: si está habilitado, la tabla se muestra en el show de los documentos vinculados (órdenes de compra, facturas, entre otros).
  • Título en show: título que se muestra para la columna en el show de los documentos vinculados. Si se deja vacío, se usa el nombre de la columna.
  • Ocultar en show: si está marcado, la columna no se muestra en el show de los documentos vinculados; el dato se sigue guardando y la API lo sigue devolviendo.

Al editar una tabla existente se pueden agregar columnas nuevas, renombrarlas, cambiar su tipo y eliminarlas. Los cambios se aplican a los registros existentes: las columnas renombradas conservan sus datos, las columnas nuevas quedan con valor vacío y al eliminar una columna se borran sus datos en todos los registros. La eliminación pide confirmación y no se puede deshacer.

Uso de la API

Como en todos los casos, aquí también tenemos acceso a una API para gestionar todo en relación al CRUD de las webapp tables y sus registros.

La ruta utilizada para acceder a la API es la siguiente:

https://app.zauru.com/apps/webapp_tables

Obtener listado de webapp tables

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables.json

Esto devolverá un JSON similar a este:

[]

Obtener detalle de una webapp table

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/1.json

Esto devolverá un JSON similar a este:

{
"id": "153",
"zid": "2",
"entity_id": "1303",
"name": "Actualizaciones Ordenes de Trabajo",
"structure": "{\"image_s3_urls\": \"jsonb_urls\", \"observaciones\": \"string\", \"production_work_order_id\": \"int\"}",
"creator_id": "2512",
"updater_id": "2512",
"created_at": "2026-06-22 21:45:41.980008",
"updated_at": "2026-07-07 19:39:37.3826",
"hidden_in_show_columns": "[]",
"show_column_titles": "{}",
"load_in_rowable_show": false
}

Crear webapp table

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X POST \
-d '{
"webapp_table": {
"name": "Tipos de monedas",
"rows_structure": ["nombre", "estado"],
"rows_type": ["string", "boolean"]
}
}' \
https://app.zauru.com/apps/webapp_tables.json

Esto devolverá un JSON similar a este:

{
"id": 1,
"zid": 1,
"entity_id": 2,
"name": "Tipos de monedas",
"structure": {
"nombre": "string",
"estado": "boolean"
},
"creator_id": 3,
"updater_id": null,
"created_at": "2026-08-06T04:16:14.949Z",
"updated_at": "2026-08-06T04:16:14.949Z",
"hidden_in_show_columns": [],
"show_column_titles": {},
"load_in_rowable_show": false
}

Actualizar webapp table

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X PATCH \
-d '{
"webapp_table": {
"name": "Tipos de monedas actualizado"
}
}' \
https://app.zauru.com/apps/webapp_tables/1.json

Esto devolverá un JSON similar a este:

{
"id": "153",
"zid": "2",
"entity_id": "1303",
"name": "Actualizaciones Ordenes de Trabajo",
"structure": "{\"image_s3_urls\": \"jsonb_urls\", \"observaciones\": \"string\", \"production_work_order_id\": \"int\"}",
"creator_id": "2512",
"updater_id": "2512",
"created_at": "2026-06-22 21:45:41.980008",
"updated_at": "2026-07-07 19:39:37.3826",
"hidden_in_show_columns": "[]",
"show_column_titles": "{}",
"load_in_rowable_show": false
}

Eliminar webapp table

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X DELETE \
https://app.zauru.com/apps/webapp_tables/1.json

En caso de exito, retorna un codigo HTTP 204 No Content (sin cuerpo).

Nueva webapp table (prellenado)

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/new.json

Esto devolverá un JSON similar a este:

{
"webapp_table": {
"id": null,
"zid": null,
"entity_id": 1,
"name": null,
"structure": null,
"creator_id": null,
"updater_id": null,
"created_at": null,
"updated_at": null,
"hidden_in_show_columns": [],
"show_column_titles": {},
"load_in_rowable_show": false
},
"types": [
[
"Numero",
"int"
],
[
"Texto",
"string"
],
[
"Condición",
"boolean"
],
[
"Fecha",
"date"
],
[
"Decimal",
"decimal"
],
[
"JSON",
"json"
],
[
"JSON (jsonb)",
"jsonb"
],
[
"JSON (URLs de archivos)",
"jsonb_urls"
]
]
}

Editar webapp table

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/1/edit.json

Esto devolverá un JSON similar a este:

{
"id": "153",
"zid": "2",
"entity_id": "1303",
"name": "Actualizaciones Ordenes de Trabajo",
"structure": "{\"image_s3_urls\": \"jsonb_urls\", \"observaciones\": \"string\", \"production_work_order_id\": \"int\"}",
"creator_id": "2512",
"updater_id": "2512",
"created_at": "2026-06-22 21:45:41.980008",
"updated_at": "2026-07-07 19:39:37.3826",
"hidden_in_show_columns": "[]",
"show_column_titles": "{}",
"load_in_rowable_show": false
}

Obtener filas asociables (rowables) de una webapp table

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/1/rowables.json

Asociar filas a documentos (create_rowables)

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X POST \
-d '{
"webapp_table": {
"rowables_id": ["1", "2"],
"rowables_type": ["Invoice", "Shipment"],
"rowables_doc_id": ["10", "20"]
}
}' \
https://app.zauru.com/apps/webapp_tables/1/create_rowables.json

API de Filas (Webapp Rows)

Las filas de una webapp table se gestionan a través de rutas anidadas.

Obtener listado de filas

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows.json

Esto devolverá un JSON similar a este:

[
{
"id": "15171",
"webapp_table_id": "6",
"data": "{\"Otras_razones\": \"\", \"Razon_primaria\": \"Mancha Café\", \"Razon_terciaria\": \"\", \"Razon_secundaria\": \"\"}",
"creator_id": "2472",
"updater_id": null,
"created_at": "2023-10-04 23:47:39.990827",
"updated_at": "2023-10-04 23:47:39.990827"
}
]

Obtener listado de filas con paginación

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows.json?page=1&per_page=25

Esto devolverá un JSON similar a este:

[
{
"id": "15171",
"webapp_table_id": "6",
"data": "{\"Otras_razones\": \"\", \"Razon_primaria\": \"Mancha Café\", \"Razon_terciaria\": \"\", \"Razon_secundaria\": \"\"}",
"creator_id": "2472",
"updater_id": null,
"created_at": "2023-10-04 23:47:39.990827",
"updated_at": "2023-10-04 23:47:39.990827"
}
]

Obtener detalle de una fila

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows/1.json

Esto devolverá un JSON similar a este:

{
"id": "15171",
"webapp_table_id": "6",
"data": "{\"Otras_razones\": \"\", \"Razon_primaria\": \"Mancha Café\", \"Razon_terciaria\": \"\", \"Razon_secundaria\": \"\"}",
"creator_id": "2472",
"updater_id": null,
"created_at": "2023-10-04 23:47:39.990827",
"updated_at": "2023-10-04 23:47:39.990827"
}

Crear fila

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X POST \
-d '{
"webapp_row": {
"data": {
"nombre": "Quetzal",
"estado": true
}
}
}' \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows.json

Esto devolverá un JSON similar a este:

{
"id": "15171",
"webapp_table_id": "6",
"data": "{\"Otras_razones\": \"\", \"Razon_primaria\": \"Mancha Café\", \"Razon_terciaria\": \"\", \"Razon_secundaria\": \"\"}",
"creator_id": "2472",
"updater_id": null,
"created_at": "2023-10-04 23:47:39.990827",
"updated_at": "2023-10-04 23:47:39.990827"
}

Actualizar fila

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X PATCH \
-d '{
"webapp_row": {
"data": {
"nombre": "Dolar",
"estado": true
}
}
}' \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows/1.json

Esto devolverá un JSON similar a este:

{
"id": "15171",
"webapp_table_id": "6",
"data": "{\"Otras_razones\": \"\", \"Razon_primaria\": \"Mancha Café\", \"Razon_terciaria\": \"\", \"Razon_secundaria\": \"\"}",
"creator_id": "2472",
"updater_id": null,
"created_at": "2023-10-04 23:47:39.990827",
"updated_at": "2023-10-04 23:47:39.990827"
}

Eliminar fila

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X DELETE \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows/1.json

En caso de exito, retorna un codigo HTTP 204 No Content (sin cuerpo).

Nueva fila (prellenado)

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows/new.json

Esto devolverá un JSON similar a este:

{
"id": "15171",
"webapp_table_id": "6",
"data": "{\"Otras_razones\": \"\", \"Razon_primaria\": \"Mancha Café\", \"Razon_terciaria\": \"\", \"Razon_secundaria\": \"\"}",
"creator_id": "2472",
"updater_id": null,
"created_at": "2023-10-04 23:47:39.990827",
"updated_at": "2023-10-04 23:47:39.990827"
}

Editar fila

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows/1/edit.json

Esto devolverá un JSON similar a este:

{
"id": "15171",
"webapp_table_id": "6",
"data": "{\"Otras_razones\": \"\", \"Razon_primaria\": \"Mancha Café\", \"Razon_terciaria\": \"\", \"Razon_secundaria\": \"\"}",
"creator_id": "2472",
"updater_id": null,
"created_at": "2023-10-04 23:47:39.990827",
"updated_at": "2023-10-04 23:47:39.990827"
}

Asociar una fila a un documento

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X POST \
-d '{
"temp_invoice_id": "10"
}' \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows/1/associate.json

Esto devolverá un JSON similar a este:

{
"status": "ok"
}

Desasociar una fila de un documento

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X DELETE \
-d '{"temp_invoice_id": "10"}' \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows/1/dissociate.json

Esto devolverá un JSON similar a este:

{
"status": "ok"
}

Para desasociar todas las relaciones de una fila, use "all": true:

curl -v \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H "X-User-Email: prueba@zauru.com" \
-H "X-User-Token: XSDFKK09238487DLFS" \
-X DELETE \
-d '{"all": true}' \
https://app.zauru.com/apps/webapp_tables/1/webapp_rows/1/dissociate.json

Esto devolverá un JSON similar a este:

{
"status": "ok"
}

Ejemplo de caso de uso: programaciones de Agrocréditos

La webapp de Agrocréditos de 4 Pinos administra programaciones de siembra y cosecha por socio. Zauru no maneja programaciones de fábrica y varias aplicaciones necesitan los mismos registros: Agrocréditos los crea y consulta, la webapp de recepciones los necesita al registrar recepciones, y los usuarios de Zauru los consultan desde el CRUD de WebApps => Tablas. Una webapp table centraliza el dato en Zauru y evita duplicarlo entre aplicaciones.

Estructura de la tabla

La webapp table "programaciones" guarda, entre otras, estas columnas:

  • payee_id: id del socio dueño de la programación.
  • item_id: id de la verdura sembrada.
  • variedad: variedad del cultivo.
  • fecha_siembra: fecha de siembra planeada.
  • fecha_cosecha_inicio y fecha_cosecha_fin: ventana de cosecha calculada a partir del ciclo del cultivo.
  • cantidad_medida: cantidad sembrada, en cuerdas o pilones.
  • porcentaje_entrega_cosecha: porcentaje de entrega esperado al momento de la cosecha.
  • prestamo_maximo_pos_gtq: tope de préstamo en punto de venta, calculado con la tasa de Agrocréditos y las cuerdas equivalentes.
  • estado: estado de la programación ("en_curso", "completada" o "eliminada").
  • purchase_orders: listado JSON de las órdenes de compra (recepciones) asociadas a la programación.
  • observaciones: notas libres.

Cómo escribe la webapp en la tabla

Agrocréditos crea y actualiza programaciones con los endpoints de la API de filas documentados arriba: POST a /apps/webapp_tables/151/webapp_rows.json para crear y PATCH a /apps/webapp_tables/151/webapp_rows/:id.json para actualizar. Al crear una fila, Zauru devuelve el id real del registro y la webapp lo guarda como referencia. Las programaciones no se eliminan físicamente: la webapp marca la columna "estado" como "eliminada" para conservar la auditoría del registro.

Sincronización de la webapp table a Appocus (AppSync)

Las webapps de Appocus no consultan la API de Zauru para leer; trabajan sobre una copia de los datos en una base de datos Postgres propia, sincronizada desde Zauru. La copia se configura con un AppSync:

  1. Ir a "WebApps" => "AppSyncs".
  2. Click sobre "add AppSync".
  3. Ingresar el nombre de la aplicación en "AppName" y marcar "Active?".
  4. En el listado de tablas, marcar la tabla "webapp_rows" y, en la columna "Options", seleccionar las webapp tables a sincronizar (en este ejemplo, "programaciones").
  5. Guardar. Zauru crea en la base de datos de Appocus una tabla por cada webapp table seleccionada, llamada webapp_table_<nombre>_<id> (por ejemplo, webapp_table_programaciones_151), con columnas tipadas según la estructura de la webapp table: int como entero, boolean como booleano, json, jsonb y jsonb_urls como JSONB, y los demás tipos como texto.

El flujo habitual no requiere intervención: al crear, editar o eliminar una fila de la webapp table, Zauru encola el cambio y un job programado lo replica a la tabla remota. La pestaña "AppSyncIdsToSync" muestra la cola de cambios pendientes y permite sincronizar de inmediato; el botón "Full Refresh" del detalle de un AppSync recrea las tablas remotas desde cero.

Consumo entre webapps

La webapp de recepciones lee la tabla sincronizada de programaciones para preseleccionar la programación del socio y de la verdura al registrar una recepción, y escribe las órdenes de compra registradas en la columna "purchase_orders" de la fila. Agrocréditos usa ese dato para bloquear la edición de una programación que ya tiene recepciones, mostrar cuántas recepciones tiene y calcular los pagos de crédito sobre las órdenes de compra registradas.

Con una sola webapp table como fuente, Zauru queda como dueño del dato y ninguna aplicación duplica la información.

¿Le fue útil esta guía?