Oracle3
Open-source trading engine and MCP server for prediction markets. Fee-aware no-arbitrage trading across related contracts, live on Kalshi, Polymarket and Solana or on paper.
Automatización de cobros residenciales con WhatsApp, OCR, validación, conciliación y control de cartera.
Translation pending
FinanceTypeScript · CSSGitHub @sistemas-pagosOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Plataforma de automatización de cobros residenciales por WhatsApp con OCR, validación de transacciones, control de cartera y dashboard administrativo. Importante: un comprobante leído por OCR no demuestra que el dinero exista. El sistema separa explícitamente comprobante recibido de pago verificado. En la primera etapa un encargado revisa el movimiento directamente en el banco y pulsa Verificar; una fuente bancaria automatizada puede integrarse después.Read the full README ↗
Cobro de la cuota residencial por WhatsApp: el vecino manda su comprobante, el sistema lo lee, lo verifica contra el extracto del banco y le devuelve un recibo numerado. El cobrador registra el efectivo desde su teléfono.
El documento que manda es docs/PLAN.md. Cuando este README y el plan no
coincidan, gana el plan.
Recibido no es verificado. Un comprobante leído por OCR no demuestra que el dinero exista. Una transferencia solo queda
VERIFICADOcuando un movimiento del extracto del banco la respalda, y un movimiento verifica un solo pago.
Las imágenes no se guardan. Se descargan de WhatsApp, se validan, se les calcula el hash, se procesan con OCR y se descartan. Queda el SHA-256 para reconocer un reenvío exacto, nunca la imagen ni un identificador que permita abrirla.
Vecino ──WhatsApp──► Vercel /api/whatsapp/webhook
valida la firma, guarda el mensaje, responde 200
GitHub Actions ─► procesar-comprobantes ─► Turso ─► enviar-recibos ─► WhatsApp
─► mantenimiento / cierre-mes
Turso es la única fuente de verdad. Vercel solo aloja el webhook y el panel; el trabajo pesado —OCR, conciliación, envíos— corre en GitHub Actions, donde un proceso puede tardar minutos sin que nadie espere una respuesta HTTP.
El efectivo y el extracto del banco entran por otros dos caminos: el cobrador registra el cobro en el panel desde su teléfono, y el tesorero manda el CSV del banco por WhatsApp desde un número autorizado.
Las catorce invariantes están en docs/PLAN.md sección 3. Las que más se
notan al usar el sistema:
E1B4C18). Nunca se deduce del teléfono ni del
nombre del depositante.VERIFICADO (transferencia) o EFECTIVO_COBRADO /
VERIFICADO (efectivo).ajustes de tipo SALDO_INICIAL.VERIFICADO y no
reservado por uno pendiente. Nunca un mes futuro.eventos, que no se puede editar
ni borrar.La cuota vigente vive en la tabla cuotas con su vigente_desde, así que un mes viejo cuesta
lo que costaba entonces. EXPECTED_PAYMENT_AMOUNT es solo el respaldo cuando esa tabla todavía
no tiene fila.
Entrada por WhatsApp. Webhook con verificación de challenge y firma X-Hub-Signature-256,
validación de MIME, magic bytes y tamaño antes del OCR, y descarte del reintento de Meta por
message_id antes de volver a descargar la media.
Lectura del comprobante. Tesseract.js con modelo español y preprocesamiento con Sharp, todo server-side: el comprobante no se le manda a ningún proveedor de IA. Parser de BAC para banco, depositante, fecha, hora, monto, detalle, referencia, beneficiario y cuenta destino.
Verificación contra el banco. El tesorero manda el CSV del extracto por WhatsApp desde un
número que está en usuarios con rol ADMIN o TESORERO. El sistema importa los movimientos sin
duplicarlos, manda un resumen y aplica al recibir la confirmación, que expira. Un movimiento
verifica un solo pago, y lo garantiza una restricción UNIQUE.
Efectivo. El cobrador entra a /cobros desde su teléfono, busca la casa con filtros de
etapa, bloque, casa, estado, método y mes, y marca los meses que paga: el monto no se
escribe, sale de la cuota de cada mes. El pago, la reserva de los meses, el recibo y su envío
nacen en una sola transacción. La pantalla se instala como app.
Entrega. El cobrador ve su hoja de entrega; el tesorero cuenta y cierra la caja en
/admin/caja. Nadie recibe lo que él mismo cobró —lo impide el esquema— y la diferencia entre
lo esperado y lo entregado se guarda tal cual.
Recibos. Uno por pago, emitido en la misma transacción que la verificación, enviado con
plantilla aprobada de Meta y con una cola que reintenta. /admin/recibos muestra los que no le
llegaron al vecino.
Panel. Dashboard mensual, vistas por etapa y bloque, historial por vivienda, bandejas de excepciones, corrección de vivienda y mes sin repetir OCR, y la bandeja de notas del cobrador —que no puede corregir un pago, pero sí dejar escrito lo que vio.
Usuarios. Cada persona entra con su usuario y su rol (ADMIN, TESORERO, COBRADOR). Las claves
van con scrypt y la sesión lleva firmado quién es y con qué rol.
.
├── app/ # panel, pantalla de cobros y Route Handlers
├── migrations/ # NNN_*.sql, aplicadas solo por el workflow `migraciones`
├── scripts/ # lo que corre en Actions (con `npx tsx`, no con `node`)
├── src/
│ ├── auth/ # claves, sesión, roles y defensa de origen
│ ├── bank/ # lectura del CSV del banco
│ ├── config/ # contrato de variables de entorno
│ ├── demo/ # datos sintéticos
│ ├── domain/ # estados, períodos, vivienda, duplicados, recibo
│ ├── ocr/ # Sharp + Tesseract.js
│ ├── parsers/bac/ # parsers desacoplados por banco
│ ├── security/ # archivos, firmas y logging enmascarado
│ ├── services/ # procesamiento, meses, dashboard, conciliación, cobros
│ ├── storage/ # Turso y memoria para la demo
│ └── whatsapp/ # payload, cliente Cloud API y dispatch
├── tests/
├── docs/
└── .github/workflows/
Demo (APP_MODE=demo): sin Meta, sin base de datos y sin credenciales. Usa solo datos
ficticios y no acepta el webhook real. Sirve para mostrar el panel, el parser y las reglas sin
exponer nada.
Producción (APP_MODE=production): requiere las variables en Vercel y los secretos del
Environment pagos-produccion en GitHub. Copiar .env.example como referencia y nunca
llenarlo y subirlo.
Variables principales:
| Variable | Para qué |
|---|---|
PAGOS_TURSO_URL, PAGOS_TURSO_TOKEN | la base, que es la fuente de verdad |
AUTH_SESSION_SECRET | firma de la sesión del panel |
WHATSAPP_VERIFY_TOKEN, WHATSAPP_ACCESS_TOKEN, WHATSAPP_PHONE_NUMBER_ID, META_APP_SECRET | WhatsApp Cloud API |
WHATSAPP_TEMPLATE_RECIBO, WHATSAPP_TEMPLATE_IDIOMA | la plantilla aprobada del recibo |
PAGOS_GITHUB_REPO, PAGOS_DISPATCH_TOKEN | repository_dispatch hacia Actions |
EXPECTED_BENEFICIARY, EXPECTED_ACCOUNT_LAST4 | obligatorias en producción (invariante 4) |
ADMIN_ACCESS_KEY | transición: abre el panel mientras esté configurada |
ADMIN_ACCESS_KEY es la clave compartida anterior a los usuarios por persona. Existe solo
mientras la variable esté puesta: al borrarla de Vercel, ese camino desaparece sin tocar código.
Una sesión creada con ella no es una persona, así que no puede recibir una caja.
Requiere Node.js 22.
npm install
npm run dev
Los cuatro checks, que son los mismos que corre CI en cada pull request y en main:
npm run lint
npm run typecheck
npm test
npm run build
Las pruebas corren contra SQLite en memoria usando los archivos reales de migrations/, así
que una restricción UNIQUE o un trigger que se rompa en producción se rompe también en la suite.
El repositorio es público por diseño. Está prohibido versionar tokens, claves, service-account JSON, comprobantes reales, teléfonos o nombres de vecinos, números de cuenta o referencias reales, y cualquier archivo exportado de producción.
Los logs de Actions nunca muestran teléfonos, Etapa/Bloque/Casa, montos por casa, referencias ni nombres, y ningún workflow sube artifacts con datos.
Ver docs/SECURITY.md.
Este proyecto vivía en el monorepo Jchernand3z19/Portafolio
bajo pagos-whatsapp-residencial/. Se extrajo a este repositorio con su historial intacto.