basecode.com.ar

Propio · 2026

SaaS multi-agencia para agencias de turismo en colectivo: mostrador, cobros y backoffice.

Demo interactiva próximamente. Escribime y te la muestro en vivo.Ver el flujo del cobroCódigo privado

Estado
En producción · lo usa Rooming
Rol
Diseño y desarrollo, solo
Período
Feb 2026 – hoy
endpoints
213
API en Bun, Hono y TypeScript, en 20 routers
pantallas del panel
46
Next.js 14 con roles: dueño, administrador, editor y vendedor
funciones PL/pgSQL
31
la plata se mueve dentro de la base, con bloqueos
aserciones de prueba
+2.000
sobre un PostgreSQL embebido, sin tocar producción; se corren a mano

El proyecto en 30 segundos

  1. El problema

    Una agencia de turismo en colectivo vende en el mostrador y en su web, cobra en cuotas y rinde cada viaje, casi siempre entre planillas, mensajes y cuentas sueltas.

  2. Lo que armé

    Un SaaS multi-agencia: venta de mostrador sobre el mapa de butacas con cuotas, pagarés y recibos; cobros con Mercado Pago en la cuenta de cada agencia; un coordinador que pasa lista sin señal; un mercado de reventa entre agencias y un backoffice con roles y auditoría.

  3. En qué quedó

    Está en producción y el sitio de Rooming Viajes y Turismo cobra a través de él. Todavía no tiene agencias que paguen una suscripción.

Qué pasa cuando se paga en el sitio de una agencia

  1. Sitio de la agencia
    Cotiza

    Pide el precio de un viaje y de sus pasajeros; no manda ningún monto.

  2. Back (Hono)
    Firma

    Calcula el precio, lo firma con HMAC (30 minutos) y toma la agencia del paquete.

  3. Mercado Pago
    Cobra

    Cobra con el token OAuth de esa agencia, con una clave de idempotencia derivada de la cotización.

  4. Base (Postgres)
    Registra

    Guarda la reserva y el pago en una función de la base, con índices únicos contra el duplicado.


Resultado: El monto sale del servidor, el pago entra en la cuenta de la agencia y la reserva queda registrada.

Sobre el proyecto

Una agencia de turismo en colectivo vende en el mostrador y en su web, cobra en cuotas y rinde cada viaje. Diseñé y construí solo basecode.com.ar, un SaaS multi-agencia que junta ese trabajo: venta de mostrador sobre el mapa de butacas, con cuotas, pagarés y recibos; cobros con Mercado Pago en la cuenta de cada agencia, conectada por OAuth; un link para que el coordinador pase lista sin señal; un mercado de reventa entre agencias y un backoffice con roles y auditoría. Hoy lo usa Rooming como backend de su sitio. Lo desarrollé con Claude Code, con planes y pruebas al lado de cada paso.

Para tener en cuenta

El bot de WhatsApp con Claude y la factura electrónica de ARCA están implementados y todavía sin probar en producción: el bot solo se probó contra una API simulada, y ARCA solo en homologación. Ninguna agencia tiene WhatsApp conectado. No hay CI: las pruebas las corro a mano antes de cada merge, y el build de Vercel y de Railway es el único control automático. Las migraciones se aplican a mano y no quedan versionadas en el repo. El antifraude del cobro web guarda sus contadores en memoria, así que se reinician en cada deploy. No hay cifras de rendimiento: no medí latencias ni hice pruebas de carga. Es el único proyecto mío con otras agencias como destino, pero no tengo agencias que paguen una suscripción: hoy lo usa Rooming como backend de su sitio.

A · Cobros

Cobro web contra el doble cobro

El navegador nunca decide cuánto se cobra, y un reintento no cobra dos veces.

30 minvigencia de la cotización firmada con HMAC: el precio sale del servidor y vuelve firmado
  • Cotización firmada: el precio se calcula en el servidor y vuelve como un token HMAC-SHA256. El cobro verifica paquete, pasajeros, moneda y extras antes de cobrar.
  • Cobra con el token OAuth de la agencia: la plata de cada venta entra directo a su cuenta de Mercado Pago, sin un token de respaldo.
  • Idempotencia: la clave sale de la cotización y del token de la tarjeta. Si no hay respuesta de Mercado Pago contesta «en proceso», y el próximo intento busca el pago por referencia antes de cobrar.
  • Webhook firmado: verifica la firma en tiempo constante, vuelve a leer el pago en vez de creerle al cuerpo, ignora avisos más viejos que lo guardado y rearma la reserva si el back se cayó entre cobrar y guardar.
  • Freno al testeo de tarjetas con dos ventanas: el sexto intento por cotización y 30 rechazos por agencia dan 429.
  • Devoluciones desde el panel, hasta la liberación de una reserva con plata cobrada, con lo devuelto y lo retenido.
Ver detalle técnico
  • Los índices únicos parciales frenan el duplicado en la base aunque falle todo lo anterior; dos pedidos simultáneos comparten la misma promesa.
  • El token de cada agencia se guarda cifrado con AES-256-GCM y la agencia como dato asociado: copiado a otra agencia, no se descifra. Se renueva solo y, si falla, el panel lo muestra y los dueños reciben un mail.
  • Plata de Mercado Pago: cuánto se quedó cada cobro (comisión, cuotas, impuestos) y cuándo se libera, con las tasas públicas leídas y versionadas cada 12 horas.
  • Mercado Pago
  • HMAC
  • Idempotencia
  • PL/pgSQL
  • AES-256-GCM
B · Multi-agencia

Permisos verificados y auditoría

Una agencia nunca ve los datos de otra, y hay un test que lo pide en cada ruta.

112 de 113rutas con id probadas pidiendo datos de otra agencia; el barrido encontró y cerró una fuga real
  • La agencia sale de la sesión, no del navegador; el rol (dueño, administrador, editor o vendedor) se busca en la base en cada pedido.
  • Barrido de aislamiento: lee las rutas de Hono y pide cada una con los ids de otra agencia, con un control positivo antes de cada caso. Encontró una fuga en las cuentas del mercado y se cerró.
  • Auditoría: un middleware anota cada escritura exitosa, sin el cuerpo (trae datos personales); las funciones que mueven plata escriben el antes y el después en la misma transacción.
  • Pantalla de Actividad con filtros por persona, entidad y fechas, con paginación por cursor.
  • «Ver panel» para soporte: la plataforma mira una agencia en solo lectura, con un cartel, sin operar como ella.
  • Login sin contraseñas: código por mail, solo para quien integra un equipo, con topes en Postgres.
Ver detalle técnico
  • Llaves de API separadas para el panel, las integraciones y la administración de la plataforma.
  • Solo un dueño puede tocar a otro dueño, y una persona puede estar en varias agencias.
  • Multi-tenant
  • Roles
  • Auditoría
  • Zod
  • Hono
C · Venta y mercado

Mostrador, cuotas y mercado entre agencias

Un dominio completo de punta a punta, de la butaca al recibo.

4hojas listas para imprimir: recibo, pagaré, factura con QR y lista de la salida
  • Venta de mostrador sobre el mapa de butacas: las butacas chocan en la base en vez de pisarse.
  • Seña y plan de cuotas: la base no guarda «cuota pagada», guarda el plan y los cobros, y el estado de cada cuota sale de repartir lo cobrado en orden.
  • Recibo numerado por agencia con el importe en letras, y un pagaré por cada cuota que queda debiendo.
  • Vencimientos con el aviso al cliente por mail o WhatsApp: la misma lista alimenta la pantalla y el mail automático.
  • Mercado de reventa: un mayorista publica una salida con comisión y otra agencia la vende con el plano a la vista; la venta entra como solicitud con las butacas retenidas y el mayorista la confirma o la rechaza.
  • Convenios y cuentas corrientes entre agencias, con estados y motivos: abierta, pausada, suspendida o solo para socios.
Ver detalle técnico
  • Tarifarios por temporada con adulto, menor e infante y suplementos por categoría de butaca; vendedores y promotores con comisión congelada en la reserva.
  • Los planos de butacas los trae del sistema de gestión de Virgen del Milagro, con su mismo modelo, por una API con clave. El endpoint está implementado; no consta todavía su uso en producción.
  • Butacas
  • Cuotas
  • Mercado B2B
  • PL/pgSQL
D · Coordinador

El coordinador en viaje, sin señal

La lista de embarque se marca en modo avión y se sincroniza al volver.

500marcas por lote al sincronizar, cada una con la hora del toque; la plata nunca se encola
  • Un link en el teléfono, sin entrar al panel: pasajeros, paradas, datos para el viaje y gastos. La agencia lo crea y lo corta desde la salida.
  • Sin señal: un service worker con red primero para la página y caché primero para el código; cada marca se guarda en el teléfono y se manda en lotes.
  • Cobra saldos en efectivo o transferencia (sale el recibo), con un QR en su pantalla o el link del cliente por WhatsApp.
  • Ventas en viaje con comisión: una excursión cobrada en el momento o dejada a cuenta.
  • Gastos del viaje con la foto del ticket, en un bucket privado con link firmado de pocos minutos.
  • Fondo, rendición y cuenta corriente: todo es una lista de movimientos con signo, y la suma es lo que tiene que rendir.
  • Service worker
  • Offline
  • Rendiciones
  • Next.js 14
E · Bot, ARCA y calidad

IA en el producto, factura electrónica y pruebas

Un LLM detrás de herramientas acotadas, y todo con pruebas al lado.

5 toolsdel bot de WhatsApp, sin parámetros de identidad: el back las resuelve con el número de quien escribe
  • Bot de WhatsApp con Claude: busca viajes, muestra las reservas de quien escribe, manda el link de pago y deriva a una persona con el motivo. Tiene timeout, reintentos, un menú fijo como plan B, tokens registrados por llamada y topes por agencia y por conversación. Implementado; solo probado contra una API simulada.
  • «Probar el bot» desde el panel: la agencia le escribe como si fuera un cliente, sin WhatsApp ni Meta, antes de prenderlo.
  • Factura electrónica de ARCA (WSAA y WSFEv1 por SOAP) como módulo documentado para reusarlo: una emisión a la vez por agencia con un lease en la base y conciliación con la consulta del comprobante antes de reintentar. Implementada, probada en homologación.
  • Cola outbox en Postgres para los avisos de WhatsApp: toma atómica, backoff, máximo de intentos, estado de error y deduplicación por clave.
  • Pruebas en tres niveles: reglas puras, SQL contra PGlite (31 pasos y 143 caminos de error) y el back entero con servicios simulados, con la respuesta perdida, Mercado Pago caído y el doble clic.
Ver detalle técnico
  • Cada migración se aplica dos veces en PGlite para probar que es idempotente, antes de tocar producción.
  • Logs JSON con un request id por pedido y una auditoría durable.
  • Claude API
  • WhatsApp Cloud API
  • ARCA
  • PGlite
  • Outbox

Decisiones y qué resignan

Seguridad

El precio lo firma el servidor

Elegí
Cotización con HMAC de 30 minutos, y el cobro verifica todo contra ella.

Resigné
Un paso más en la compra y un token que vence.
Por qué

En mi marketplace anterior el monto llegaba del navegador. Acá el navegador nunca decide cuánto se cobra, y el pedido de cobro no lleva ningún importe.

Consistencia

La plata se mueve dentro de la base

Elegí
31 funciones PL/pgSQL con bloqueos, orden fijo de bloqueo e índices únicos parciales.

Resigné
Más lógica en SQL, difícil de depurar, y una prueba en una sola conexión no prueba bloqueos reales.
Por qué

Cobros, devoluciones, pagarés y rendiciones son atómicos y escriben su auditoría en la misma transacción. Fuera de esas funciones hay escrituras de varios pasos sin transacción, que son deuda conocida.

Seguridad

El aislamiento entre agencias lo hace la aplicación

Elegí
Filtro por agencia en cada consulta, más un barrido que lo prueba ruta por ruta.

Resigné
RLS prendido sin políticas: un descuido en una consulta es una fuga, y solo el test lo atrapa.
Por qué

Hay 203 filtros por agencia y 26 parámetros en las funciones. El barrido encontró y cerró una fuga real; la protección depende de correrlo.

Pruebas

Postgres embebido para probar

Elegí
PGlite para probar funciones y migraciones sin tocar producción.

Resigné
Tiene una sola conexión: no prueba carreras ni bloqueos reales.
Por qué

La única base de datos es la de producción, así que cada migración se prueba dos veces en PGlite antes de aplicarla. La concurrencia se prueba con pedidos simultáneos contra la capa HTTP.

Control

Un LLM con herramientas acotadas

Elegí
Cinco tools sin parámetros de identidad, con topes, plan B y derivación a una persona.

Resigné
Menos libertad para el modelo y un menú fijo que atender.
Por qué

El back resuelve quién escribe y a qué agencia pertenece; el modelo no puede pedir los datos de otra persona. Si el modelo falla, la charla sigue con el menú fijo.

Lo que sigue

En este orden y por esta razón: primero poder cambiar sin miedo, después cerrar deudas, recién entonces medir.

  1. Ahora

    Hoy las pruebas se corren a mano: sin CI, nada impide que una regresión llegue a producción.


    • GitHub Actions que corra las pruebas de SQL, cuentas, cobros y accesos, el chequeo de tipos y el de diseño en cada push.
    • Volcar el esquema completo y versionar las migraciones en orden.
  2. Después

    Cierra lo que hoy está implementado sin probar.


    • Probar el bot contra la API real de WhatsApp y registrar latencia y costo.
    • Emitir un comprobante real de ARCA y no solo de homologación.
    • Pasar los contadores del antifraude a Postgres y registrar cada pausa en la auditoría.
  3. Más adelante

    Hoy no hay cifras de rendimiento y no las invento.


    • Una prueba de carga del catálogo y la cotización, con p95 y el plan de ejecución de la auditoría y la búsqueda por teléfono.
    • Una instancia de demo con datos inventados para quien evalúa.

Cómo usé IA

Lo desarrollé con Claude Code, con planes aprobados antes de codear y un CLAUDE.md que evoluciona con el código, más cinco reglas que se cargan según la ruta del archivo. Cada paso generado trae sus pruebas al lado: 112 de los 113 commits de código con trailer tienen un commit de pruebas a menos de una hora, y una corrección mía («no toques nada de la base») se volvió el método de PGlite. Las decisiones quedan registradas con su autor, persona o agente, y lo no probado se escribe. El design system lo porté del sistema de gestión de Virgen del Milagro, con la procedencia escrita y una regla propia de chequeo.