Sistema de registro diario de producción para gallinas ponedoras.
Autor: Andrés Lazo Escobar, Médico Veterinario · avivet.cl
Guía paso a paso en lenguaje simple para quienes usan la app:
docs/MANUAL.md — versión de texto (se lee en GitHub)docs/manual.html — versión con la marca AviVet, lista para imprimir o guardar como PDF. Publicada en http://avivet.cl/registro-productivo-avicola/docs/manual.htmldocs/guia-bodega-pedidos.html — guía rápida de los módulos Bodega, Pedidos y Ventas. Publicada en http://avivet.cl/registro-productivo-avicola/docs/guia-bodega-pedidos.htmlEste repositorio incluye un CLAUDE.md en la raíz con el stack, la arquitectura y comportamientos no obvios del proyecto. Claude Code lo carga automáticamente al trabajar en el repo, reduciendo el contexto necesario en cada sesión.
El sistema está en transición de Google Apps Script (GAS) + Google Sheets a una arquitectura centralizada en Supabase.
| Etapa | Estado |
|---|---|
Nueva app Supabase (src/supabase/) |
✅ Lista |
| Schema + RLS en Supabase | ✅ Activo desde 2026-04-29 |
| Migración historial Avícola GH | ⏳ Pendiente |
| Migración historial Avícola Clarita | ⏳ Pendiente |
| Migración historial Praderas de Ranco | ⏳ Pendiente |
| Migración historial Reinhard | ⏳ Pendiente |
| Productores usando nueva app | ⏳ En proceso |
| Problema actual (GAS) | Solución nueva (Supabase) |
|---|---|
| Un Sheet y una URL por productor → deploy manual de 15–20 min | Una URL para todos, crear productor = 2 min en Supabase Auth |
Sin autenticación real (URL pública con ?productor=X) |
Login email/contraseña con Row Level Security |
| Cada productor ve solo su propio Sheet pero no hay restricción técnica | RLS garantiza aislamiento a nivel de base de datos |
| Escalar requiere copiar y configurar archivos | Nuevo productor = crear usuario, no tocar código |
| Datos históricos atrapados en Sheets individuales | Todo en PostgreSQL, consultable centralmente |
src/supabase/)src/shared.js ← Código común a producción y módulo: cliente Supabase, sesión,
cuenta compartida (resolverOwner) y helpers (hoy, fmtFecha, toast)
src/supabase/
├── index.html ← App de producción (todos los productores)
└── supabase-schema.sql ← Esquema base SOLO para instalación nueva (tiene DROP TABLE)
src/ventas/
└── index.html ← App de bodega, alimento, pedidos y ventas (opcional por productor)
migrations/ ← Migraciones SQL numeradas (000…009) + README.md (ledger).
Cada una es idempotente, exige la anterior y se registra en schema_migrations
supabase/functions/ ← Edge Functions: alerta-produccion, aviso-invitacion (index.ts)
URLs:
Supabase project: xewujmpycclqjhlmiica.supabase.co (mismo proyecto que pesaje-pollitas)
Producción es la base; bodega/pedidos/ventas son módulos que nacen de ella. La app de producción enlaza a este módulo (nav → 📦 Bodega) y el módulo enlaza de vuelta a producción, con las mismas cuentas y proyecto Supabase. Es opcional: solo la usan los productores que venden. Tiene 3 pestañas, en orden de importancia (abre en Bodega):
- 📦 Bodega (principal) — inventario acumulado total:
stock físico = vendibles producidos − vendidos ± ajustesystock libre = físico − pedidos pendientes. Permite registrar mermas, autoconsumo, regalos, entradas y correcciones (tablaajustes_stock). Muestra el stock separado por tamaño (Chico…Jumbo + «Sin especificar») en una tabla Físico/Reservado/Libre; los tamaños producidos salen de las columnas deregistros. Todo se muestra también convertido a cajas de 180 (= 6 bandejas).- 📋 Pedidos — reservas de clientes con estado
pendiente. Al marcar entregado se genera la venta automáticamente (el huevo se cuenta una sola vez); mientras está pendiente compromete stock libre.- 🌾 Alimento — stock de alimento concentrado (insumo).
stock = Σ recepciones − consumo (registros.kg_alimento) ± ajustes. Recepciones con proveedor (alta rápida), N° de lote, precio/kg y N° documento; ingreso en kilos o sacos de 25 kg (conversión automática). Muestra kg en bodega, autonomía en días (según consumo reciente), costo/kg promedio y alerta de stock bajo. Tablasproveedores,alimento_recepciones,alimento_ajustes.- 💰 Ventas (secundario) — registra ventas por bandejas y cuadra por periodo (mes/anterior/todo) los huevos vendibles (
n_huevos − sucios − rotos − trizados − sangre, tablaregistros) contra lo vendido (tablaventas).
| Tabla | Descripción |
|---|---|
productores |
Nombre legible del plantel por usuario; lectura pública (autenticados) para el dashboard |
ubicaciones |
Catálogo de espacios físicos por usuario (Carro 1, Pabellón 2, etc.) |
lotes |
Lotes por usuario (nombre, fecha nac, n° aves, línea genética, ubicación opcional) |
pesajes |
Pesaje semanal en crianza (semanas 1–19) |
registros |
Un registro por día por lote (producción + clasificación + KPIs) |
ventas |
Ventas de huevos por usuario (bandejas, huevos, precio, total) — cuadra contra registros |
pedidos |
Pedidos/reservas de clientes por usuario, con estado (pendiente/entregado/anulado); al entregar enlaza la ventas.id generada. Incluye tamano y cajas |
ajustes_stock |
Movimientos de bodega por usuario (merma, autoconsumo, regalo, entrada, ajuste); huevos es un delta con signo. Incluye tamano |
proveedores |
Proveedores de alimento por usuario (nombre, teléfono); alta rápida desde el módulo Alimento |
alimento_recepciones |
Compras/entradas de alimento por usuario (fecha, proveedor, lote, kg, sacos, precio/kg, N° documento) |
alimento_ajustes |
Mermas/correcciones del stock de alimento por usuario; kg es un delta con signo |
user_config |
Preferencias por usuario en JSONB (no vendibles, alertas, correcciones de nombres del asesor) |
equipo |
Acceso compartido: dueno_id → email_invitado activo/inactivo. Un correo invitado ve y edita la cuenta del dueño (Etapa 1: rol editor) |
Cuenta compartida (equipo): la función tiene_acceso(owner) centraliza la regla de acceso: un dato con user_id = X es visible/editable si auth.uid() = X o tu correo está invitado y activo en la cuenta X. Todas las tablas de datos usan tiene_acceso(user_id) en sus políticas RLS. Es retrocompatible: sin invitaciones, equivale a user_id = auth.uid(). Las apps calculan al entrar el ownerId (mi cuenta, o la de quien me invitó) y trabajan sobre ella. El dueño gestiona los correos en Producción → Lotes → 👥 Equipo.
Todas las tablas tienen Row Level Security activado: cada usuario ve y modifica solo sus propios datos. Excepción: productores permite a cualquier usuario autenticado leer los nombres (solo el nombre, sin datos productivos), para que el dashboard del asesor identifique a cada productor.
src/supabase/supabase-schema.sql (solo proyecto vacío), luego migrations/000_ledger.sql y las migraciones 001 → 009 en orden (ver migrations/README.md)Cada PR y cada push a main corre scripts/validar-apps.py mediante GitHub Actions (.github/workflows/validar.yml). Revisa las tres apps (src/supabase/index.html, src/ventas/index.html, dashboard.html):
<script> (node --check)<div> abiertos vs cerrados e IDs duplicadosonclick que apuntan a funciones inexistentesgetElementById('x') sin ningún id="x" (cuenta también los asignados desde JS)Para correrlo localmente antes de subir: python3 scripts/validar-apps.py. No usa npm ni dependencias.
Las carpetas src/avicolas/ se mantienen como archivo histórico. Cada una tiene:
src/avicolas/<nombre>/
├── code.gs ← Backend GAS (doGet, guardarDatos, getDashboard…)
├── index.html ← App móvil con gráficos y exportar PDF
└── NOTAS.md ← URL del Sheet, URL web app, contacto del productor
| Productor | Carpeta | Línea genética |
|---|---|---|
| Avícola GH | src/avicolas/avicola-gh/ |
ver Sheet |
| Avícola Clarita | src/avicolas/avicola-clarita/ |
ver Sheet |
| Praderas de Ranco | src/avicolas/praderas-de-ranco/ |
ver Sheet |
| Reinhard | src/avicolas/reinhard/ |
ver Sheet |
| Roberto Santelices | src/avicolas/roberto-santelices/ |
ver Sheet |
| Vicente Abogabir | src/avicolas/Vicente-Abogabir/ |
ver Sheet |
| Copihue Real | src/avicolas/Copihue real/ |
ver Sheet |
Código.gs y/o index.htmldashboard.html en la raíz del repo, publicado en http://avivet.cl/registro-productivo-avicola/dashboard.html. Lee directo de Supabase con la cuenta del asesor (política RLS vet_admin_* que permite ver los lotes y registros de todos los productores; cada productor sigue viendo solo lo suyo en su app).
Alazoe/avivet-respaldos corre una GitHub Action cada lunes ~03:00 (Chile) que exporta todas las tablas de Supabase a CSV (con service_role, bypassa RLS) y las commitea; el historial de git conserva cada versión semanal. Requiere el secret SUPABASE_SERVICE_ROLE_KEY configurado en ese repo (instrucciones en su README). También se puede ejecutar a mano desde su pestaña Actions.| Fecha | Cambio |
|---|---|
| 2026-10 | Rediseño — Etapa 3b: Historial. La tabla ancha se reemplaza por días agrupados por semana de vida (con promedio de la semana), cada día con barra de postura y la marca de la curva, 📝 si tiene nota, días sin registro en rosado con Completar y Registrar para hoy; tocar un día lo abre para editar. Chips de lote, «Ver semanas anteriores» y botón ⬇ CSV (historial del lote, separador ; para Excel en español) |
| 2026-10 | Rediseño — Etapa 3a: Tendencia. La pestaña Gráficos pasa a llamarse Tendencia: período 7 días / 30 días / todo el lote con 4 indicadores (postura vs curva, mortalidad, conversión, no vendibles) y su cambio contra el período anterior; un gráfico principal con selector (Postura, Mortalidad, Tamaños, Distribución, No vend., Acumulado, Semanas); Hitos del lote (mejor semana, días seguidos sin bajas, huevos acumulados y próximo hito de 50 mil); el detalle completo de indicadores y el costo de alimentación quedan plegables. Gráficos con tipografía de la marca, leyenda abajo y eje Y de postura ajustado a los datos |
| 2026-10 | Notas por lote y nota general del día. Corregido: al cambiar de lote o de día el formulario conservaba los datos y la nota anteriores, y se guardaban repetidos en otro lote. Ahora cada día sin registro parte en blanco (aves = las del día anterior de ese lote). Nueva nota general del día para todo el plantel (tabla notas_dia, migración 010); la nota del lote sigue en registros.observaciones. El dashboard muestra Notas del productor · últimos 30 días (generales y por lote) en el detalle y en «Todos los lotes» |
| 2026-10 | Dashboard — Etapa 2 del rediseño: constancia y WhatsApp. Tarjeta Constancia de registro (últimos 30 días, cuadritos por día: registrado / sin registro / hoy pendiente, «X de Y días», días seguidos y fechas faltantes) en la vista de cada lote y en «Todos los lotes»; columna Constancia 30 d en el Resumen. Sin rankings entre productores. Nuevo periodo Últimos 7 días (hasta ayer; queda por defecto). «Copiar texto» reescrito para WhatsApp: saludo al productor filtrado, 2–3 líneas por lote (huevos, postura vs esperado, bajas vs periodo anterior, consumo en el mes) y cierre con los días registrados del periodo y la racha si es ≥ 7 días |
| 2026-10 | Rediseño de la app de producción — Etapa 1 (Registro), estilo minimalista con la misma paleta: barra de navegación inferior (Registro · Tendencia · Historial · Plantel), menú en el avatar (Bodega, Pedidos, Ventas, Manual, salir), saludo que avisa “Faltan los datos de hoy” y, ya registrado, muestra un dato positivo rotativo (huevos del día, días sin bajas, sobre la curva, hitos de 50 mil). Tarjeta de postura con anillo vs curva, tira de 7 días con faltantes y botón Completar, huevos como campo grande con % postura en vivo, aves/mortalidad/alimento con − / +, clasificación con huevos a escala y barra, nota plegable y hoja “¡Día guardado!” al guardar. Al guardar salta al siguiente día pendiente (nunca a una fecha futura). Prototipos en docs/propuesta-rediseno/ |
| 2026-09 | Migraciones con registro: carpeta migrations/ numerada (000–009) con guarda de orden, auto-registro en schema_migrations y ledger en migrations/README.md; el CI valida numeración/guarda/registro. Edge Functions movidas a supabase/functions/<nombre>/index.ts + scripts/deploy-functions.sh (opcional) |
| 2026-09 | Rendimiento del módulo: función SQL stock_resumen(owner, desde, hasta, hoy) (security invoker, RLS intacta) que devuelve en un JSON los agregados de bodega por tamaño, cuadre del periodo y alimento. El módulo deja de descargar el historial de registros (antes 3 veces por acción) y lanza las listas en paralelo. Requiere ejecutar stock-resumen.sql una vez; si falta, la app lo avisa |
| 2026-09 | src/shared.js: se extrajo el código duplicado entre producción y módulo (sesión, recuperación de clave, resolverOwner, banner de cuenta, hoy, fmtFecha, toast). De paso se corrigió hoy() en producción, que aún usaba UTC (toISOString) y desde ~21:00 daba el día siguiente. El validador del CI comprueba ahora shared + app juntos |
| 2026-09 | CI de validación: GitHub Action (.github/workflows/validar.yml) que corre scripts/validar-apps.py en cada PR y push a main — sintaxis JS, <div> balanceados, IDs duplicados, handlers sin función y getElementById sin elemento. Sin npm |
| 2026-09 | Dashboard: revisión de proceso y diseño — fechas en hora local (antes UTC: desde las 21:00 marcaba lotes al día como atrasados), token de sesión que se renueva solo (antes HTTP 401 tras 1 h), carga de lotes en paralelo, «Copiar texto» con los mismos KPIs de la tabla y respetando el productor filtrado, hoja de estilos de impresión para el PDF del resumen, lista de lotes incompletos con días registrados, «Mes cerrado» = último mes completo con gracia, mortalidad «alta» relativa al lote, identidad visual avivet.cl (Fraunces + DM Sans) y layout para pantalla angosta |
| 2026-07 | Gráfico de Postura con toggle Diario / Semanal: agrupa por semana de vida (postura = Σhuevos/Σaves; esperado = promedio de la semana) |
| 2026-07 | Alertas: el asesor (AviVet, ALERTA_EMAIL) recibe siempre copia de las alertas de todos los productores, aunque el productor haya apagado sus propias alertas. Se quitó el toggle de copia al asesor |
| 2026-07 | Gráficos: nueva pestaña ☠️ Mortalidad (por semana + acumulada) y ⚠️ No vendibles (% de sucios/rotos/trizados/sangre y total, por semana de vida; usa los nombres personalizados del productor) |
| 2026-07 | Respaldos: Action semanal en repo privado avivet-respaldos (CSV de todas las tablas, historial en git) + botón “⬇ Exportar todo” (ZIP) en el dashboard |
| 2026-07 | Aviso de invitación: al dar acceso a un correo en 👥 Equipo, una Edge Function (aviso-invitacion, Resend) avisa al administrador para que cree la cuenta del invitado |
| 2026-07 | Unidad docena (12) agregada en Ventas, Pedidos y ajuste de Bodega (junto a cajas 180, bandejas 30 y sueltos). Los huevos se pueden colocar en cajas, docenas o bandejas. Sin cambios de BD (el total se guarda en huevos, empaque canónico) |
| 2026-07 | Bodega: el ajuste de stock se ingresa en cajas (180) / bandejas (30) / huevos (antes solo huevos), con su tamaño — para agregar cajas extra, cargar stock inicial o corregir. Muestra el total y el equivalente en cajas |
| 2026-07 | Cuenta compartida (equipo) — Etapa 1: el dueño invita correos (Producción → Lotes → 👥 Equipo) que ven y editan la misma información. RLS centralizada en tiene_acceso(user_id); las apps resuelven el ownerId al entrar. Retrocompatible. equipo-schema.sql |
| 2026-07 | Módulo 🌾 Alimento en Bodega: stock de alimento = recepciones − consumo diario (registros.kg_alimento) ± ajustes; recepción con proveedor (alta rápida), lote, precio/kg y sacos de 25 kg; autonomía en días, costo/kg y alerta de stock bajo. Tablas proveedores, alimento_recepciones, alimento_ajustes (alimento-schema.sql) |
| 2026-07 | Stock por tamaño y cajas de 180: Bodega muestra Físico/Reservado/Libre por tamaño (Chico…Jumbo + Sin especificar); ventas, pedidos y ajustes registran tamaño; se puede ingresar y ver todo en cajas de 180 (= 6 bandejas). Migración migration-tamanos-cajas.sql (columnas tamano, cajas) |
| 2026-07 | Dashboard: opción “★ Todos los lotes” al seleccionar un productor — vista combinada con la curva de postura de todos sus lotes por semana de vida y una tabla-resumen por lote (clic en una fila abre su detalle) |
| 2026-07 | Dashboard: indicadores del lote agregan Consumo de alimento (g/ave/día + kg/día) y Costo alim/huevo, calculado con el precio del kg de alimento por productor (guardado por productor en el navegador) |
| 2026-07 | Dashboard: panel “Comparar por semana de vida” — compara postura de lotes marcables (con “Todos”), agrupados por estación de nacimiento (verano/otoño/invierno/primavera, hemisferio sur) o por avícola, normalizando al eje de semana de vida |
| 2026-07 | Navegación entre módulos: la app de Producción enlaza directo a Bodega/Pedidos/Ventas (../ventas/#tab) y el módulo abre en la pestaña del enlace (recuerda el módulo en la URL) |
| 2026-07 | App de ventas: pestañas Pedidos (reservas de clientes que al entregarse generan la venta) y Bodega (inventario acumulado con mermas/autoconsumo/ajustes y stock libre). El cuadre pasa a usar huevos vendibles en vez del total clasificado. Tablas pedidos y ajustes_stock |
| 2026-06 | Dashboard: agrupación del resumen por 1/4 semanas o mes cerrado, y gráficos de postura bajo demanda (curva por lote y curva combinada de los lotes de un productor) |
| 2026-06 | Dashboard: resumen semanal con tarjetas generales, filtro por productor y KPIs por lote (postura vs estándar, mortalidad semanal y anterior, consumo g/ave, huevos) |
| 2026-06 | KPI de consumo de alimento (g/ave/día, hoy y promedio 7 días) en la pestaña Gráficos |
| 2026-06 | App de ventas (src/ventas/): registra ventas en bandejas y cuadra huevos vendidos vs producidos por periodo, mismo Supabase y cuenta |
| 2026-06 | Recuperación de contraseña (¿Olvidaste tu contraseña?) en app y dashboard |
| 2026-06 | Nombres de productor en el dashboard (tabla productores): el productor se nombra en su app y el asesor corrige desde el monitor, sin más UUIDs |
| 2026-06 | Alertas por email configurables por productor (destino, umbrales, copia al asesor) |
| 2026-06 | Rediseño visual alineado a marca avivet.cl (Fraunces + DM Sans, paleta crema/verde/dorado) |
| 2026-06 | Selector de lote en tab Gráficos + no vendibles configurables por productor |
| 2026-05 | Ubicaciones físicas por lote (carro, pabellón, galpón) |
| 2026-05 | Curva Dominat agregada + curvas extendidas a semana 150 |
| 2026-05 | CLAUDE.md + URL GitHub Pages configurada |
| 2026-04-29 | Alerta por email activa y verificada (Resend + Supabase Edge Function → andres.lazomv@outlook.com) |
| 2026-04 | Nueva app Supabase + herramienta de importación CSV |
| 2026-04 | Inicio migración GAS → Supabase |
| 2026-04 | Exportar PDF semanal con gráfico y tabla |
| 2026-04 | Dashboard central multi-granja |
| 2025-03 | Versión inicial GAS |