EN|ES
← proyectos/
pargo.nest.tsMVP en demos

Pargo

SaaS POS multi-tenant para restaurantes y hoteles de la Costa Caribe

empresa:
Proyecto personal
periodo:
Jul 2026 — en curso
  • NestJS 12
  • Fastify
  • TypeScript
  • PostgreSQL (RLS)
  • Valkey
  • React
  • TanStack Query
  • Next.js
  • Turborepo + pnpm
  • Zod
  • OpenTelemetry
  • Docker
  • Testcontainers
  • Playwright
  • Anthropic / OpenAI / Gemini

// problema

Los restaurantes de la Costa Caribe trabajan con cortes de internet frecuentes, facturación electrónica obligatoria y POS genéricos que no descuentan inventario ni cuadran la caja. Los proyectos de referencia que analicé tenían fallas graves: el cliente fijaba los totales, cualquiera podía registrarse como admin y los webhooks de pago no eran idempotentes.

// mi rol

Lo diseño y construyo de punta a punta: plan técnico, 11 ADRs, modelo de datos PostgreSQL multi-tenant, API NestJS, caja POS y backoffice en React, web pública en Next.js, paquete de IA multiproveedor, infraestructura Docker endurecida y una verificación local que corre en cada push. Es mi proyecto personal y lo construí con desarrollo asistido por IA: la IA acelera la implementación, mientras que la arquitectura, el modelo de datos y cada decisión técnica son míos, documentados y justificados en los ADRs.

// arquitectura

Caja POSPWA · offline firmado
BackofficeReact · TanStack Query
Carta QR / webNext.js
APINestJS 12 · Fastify
public-apisolo lectura
Workerfacturas · IA · correo
Valkeyrate limit · sesiones
PostgreSQLRLS multi-tenant
Factus (DIAN)factura electrónica
IA multiproveedorreseñas · reputación

Monolito modular: un mismo código desplegado en tres procesos con permisos de base de datos distintos. La facturación electrónica corre hoy contra un proveedor simulado mientras se integra Factus.

// decisiones técnicas

Multi-tenancy con Row Level Security que falla cerrado

Cada tabla tiene RLS ENABLE + FORCE y llaves foráneas compuestas (tenant_id, id); los roles de la base no son superusuarios ni pueden saltarse RLS, y la API se niega a arrancar si su rol podría hacerlo. Sin contexto de negocio una consulta no devuelve nada, y hay tests de aislamiento A↔B para leer, modificar, borrar, insertar y referenciar.

POS offline con concesión y eventos firmados

Con conexión, la caja pide una concesión de 24 h con una foto del catálogo y un tope de ventas. Sin conexión, cada venta es un evento firmado con una clave ECDSA no exportable del dispositivo, guardado cifrado en IndexedDB. Al sincronizar, el servidor verifica la firma y recalcula los precios con la foto guardada, nunca con los que envía la tablet; los casos sospechosos se marcan para revisión del gerente en vez de perder dinero que sí se cobró.

Inventario como ledger con recetas y costo promedio

Cada venta descuenta insumos según la receta de la variante y sus modificadores (un pargo grande con patacón no consume lo mismo que uno mediano con arroz con coco). Compras, mermas, ajustes y conteos físicos son movimientos de un ledger por sede, así que el stock siempre se puede reconstruir y auditar.

IA multiproveedor con puntaje determinista

El análisis de reseñas devuelve salidas estructuradas validadas con Zod sobre Anthropic, OpenAI o Gemini. El puntaje de reputación se calcula de forma determinista con los datos guardados, no lo estima el modelo; las respuestas a reseñas siempre requieren aprobación humana, cada negocio tiene un presupuesto y hay una suite de evaluación contra prompt injection.

Desarrollo asistido por IA, decisiones propias

Usé la IA como pair programmer para avanzar más rápido siendo un solo desarrollador, pero cada decisión parte de una restricción real y queda registrada en un ADR: monolito modular porque una sola persona puede desplegarlo y operarlo, con límites entre módulos que permiten separarlo más adelante; RLS para que el aislamiento entre negocios lo garantice la base de datos y no dependa de que cada consulta recuerde un filtro; caja offline porque los cortes de internet en la costa no pueden detener las ventas; e inventario como ledger para que el stock sea auditable. Ningún cambio entra sin pruebas contra PostgreSQL real, que es como verifico que el código generado hace lo que se decidió.

// impacto

Tests automatizados
751

+ 8 E2E con Playwright contra el stack real

Decisiones documentadas
11 ADRs
Venta sin internet
24 h

concesión firmada con tope de ventas

Procesos
3

api · public-api · worker

// capturas

Caja: plano del salón por zonas con mesas ocupadas
Caja: plano del salón por zonas con mesas ocupadas
Pedido: configurar el pargo (tamaño y acompañante)
Pedido: configurar el pargo (tamaño y acompañante)
Pantalla de cocina con las comandas en tiempo real
Pantalla de cocina con las comandas en tiempo real
Cobro: dividir la cuenta entre comensales
Cobro: dividir la cuenta entre comensales
Cierre de caja: reporte Z que cuadra tras el conteo ciego
Cierre de caja: reporte Z que cuadra tras el conteo ciego
Facturación electrónica aceptada
Facturación electrónica aceptada
Receta del pargo rojo frito por variante
Receta del pargo rojo frito por variante
Backoffice: resumen del día y alertas de inventario
Backoffice: resumen del día y alertas de inventario
Carta digital pública que abre el cliente con el QR

Proyecto personal en repositorio privado, construido con desarrollo asistido por IA. Las capturas son del restaurante de demostración, con datos ficticios.