Saltar al contenido
Caso · 15 / 19← Todos los trabajos

Plug Club

Un club privado en Mar del Plata: turnos de barbería, membresías mensuales con cobro automático y una cabina de DJ que se alquila por hora.

Rol
Desarrollo full-stack para un cliente
Stack
Next.js (App Router), TypeScript, Prisma + Postgres, Auth.js, MercadoPago (Checkout + subscriptions), Tailwind CSS, Resend + Twilio, Vercel
Dashboard del admin
Dashboard del adminUna cartera con libro de movimientos
(01) El problema

El club empezó como una barbería que tomaba turnos por WhatsApp. El dueño quería socios que paguen todos los meses, tengan una cantidad de cortes y horas de cabina, y puedan usarlos para invitados. Los que no son socios tenían que poder reservar y pagar un corte suelto o una hora de cabina. Los pagos van por MercadoPago, y sus avisos no siempre llegan.

Mi rolFui el único desarrollador, del modelo de datos al deploy, trabajando directo con el dueño.
(02) ResultadosContados en el código
25modelos de Prisma: turnos, pagos, planes, membresías, cartera y la cabina
70handlers de la API, cada uno revisado con sus propios permisos
31páginas entre el sitio público, la cuenta de socio, el panel del equipo y el admin
(03) Arquitectura

Tres decisiones que lo definieron.

  1. 01

    Una cartera con libro de movimientos

    Por qué. Cada socio tiene cortes y horas de cabina del plan del mes, más créditos sueltos que no vencen. Cada reserva descuenta primero del plan y después de los créditos, en una sola transacción, y deja una fila en el libro: renovación, crédito, consumo, uso de invitado o ajuste manual. Una reserva de cabina puede mezclar las dos cosas: horas de la cartera y el resto pago, y las horas se descuentan recién cuando MercadoPago aprueba el pago.

    El costo. Las membresías vencen al leerlas, no con una tarea programada. El deploy queda simple, pero cada consulta que cuenta socios activos tiene que repetir el filtro por fecha de fin.

  2. 02

    La fuente de verdad es MercadoPago, no sus avisos

    Por qué. Había socios que pagaban y se quedaban sin membresía porque el webhook rechazaba todos los avisos: el secreto de firma del servidor no era el de la integración. Ahora el webhook vuelve a leer cada pago o suscripción desde la API de MercadoPago, y una reconciliación busca las suscripciones por nuestra referencia (usuario y plan). Corre cuando el socio vuelve del checkout y desde un botón "Sincronizar MP" en el panel.

    El costo. Un aviso con firma inválida se registra y se procesa igual. Uno falso sólo puede hacernos reprocesar datos nuestros, y eso es idempotente, pero es un control más débil que rechazarlo.

  3. 03

    Páginas estáticas, permisos en cada handler

    Por qué. El panel de admin dejó de renderizarse en el servidor. Sus páginas se prerenderizan y el middleware pide rol de admin antes de que carguen. Las páginas públicas se cachean un mes y el panel las invalida cuando el dueño guarda un cambio. Como las páginas ya no miran la sesión, cada handler de la API verifica sus propios permisos.

    El costo. Los permisos se verifican dos veces, en el middleware y en el handler, y es más código para mantener a la par. Un cambio hecho por fuera del panel, directo en la base, no aparece en el sitio público hasta que vence el caché.

(04) GaleríaSeguí scrolleando →
Dashboard del admin
Dashboard del admin · Turnos, ingresos, socios activos, ingreso recurrente y cuánto se usó de las carteras este mes. Corrida local con datos de ejemplo.
Planes de membresía
Planes de membresía · El dueño define precio, cortes, horas de cabina, prioridad de reserva y beneficios por plan. Al guardar se crea su suscripción en MercadoPago.
Configuración de la cabina
Configuración de la cabina · Precio por hora para no socios, un precio aparte para las horas extra de los socios y horarios por día.
Reservar la cabina en el teléfono
Reservar la cabina en el teléfono · El socio ve las horas que le quedan en la cartera. Se usan primero; sólo se pagan las que no entran.
(05) Qué haría después
01Escribir tests para la cartera y el webhook: orden de consumo, pagos mixtos de cabina y avisos repetidos de MercadoPago. Hoy el repo no tiene.
02Cargar el secreto de firma correcto y volver a rechazar los avisos con firma inválida.
03Volver a llevar los cambios del esquema a migraciones de Prisma. El repo tiene sólo la primera, y las tablas de membresías, cartera y cabina no están en ella.
Próximo proyecto · 16 / 19
La Trencería →Turnos, tienda, cursos y puntos para un estudio de trenzas afro
Caso · 15 / 19

Plug Club

Un club privado en Mar del Plata: turnos de barbería, membresías mensuales con cobro automático y una cabina de DJ que se alquila por hora.

Rol
Desarrollo full-stack para un cliente
Stack
Next.js (App Router), TypeScript, Prisma + Postgres, Auth.js, MercadoPago (Checkout + subscriptions), Tailwind CSS, Resend + Twilio, Vercel
Plug Club
(01) El problema

El club empezó como una barbería que tomaba turnos por WhatsApp. El dueño quería socios que paguen todos los meses, tengan una cantidad de cortes y horas de cabina, y puedan usarlos para invitados. Los que no son socios tenían que poder reservar y pagar un corte suelto o una hora de cabina. Los pagos van por MercadoPago, y sus avisos no siempre llegan.

Mi rolFui el único desarrollador, del modelo de datos al deploy, trabajando directo con el dueño.
(02) Resultados
25modelos de Prisma: turnos, pagos, planes, membresías, cartera y la cabina
70handlers de la API, cada uno revisado con sus propios permisos
31páginas entre el sitio público, la cuenta de socio, el panel del equipo y el admin
(03) Arquitectura

Tres decisiones que lo definieron.

01

Una cartera con libro de movimientos

Por qué. Cada socio tiene cortes y horas de cabina del plan del mes, más créditos sueltos que no vencen. Cada reserva descuenta primero del plan y después de los créditos, en una sola transacción, y deja una fila en el libro: renovación, crédito, consumo, uso de invitado o ajuste manual. Una reserva de cabina puede mezclar las dos cosas: horas de la cartera y el resto pago, y las horas se descuentan recién cuando MercadoPago aprueba el pago.

El costo. Las membresías vencen al leerlas, no con una tarea programada. El deploy queda simple, pero cada consulta que cuenta socios activos tiene que repetir el filtro por fecha de fin.

02

La fuente de verdad es MercadoPago, no sus avisos

Por qué. Había socios que pagaban y se quedaban sin membresía porque el webhook rechazaba todos los avisos: el secreto de firma del servidor no era el de la integración. Ahora el webhook vuelve a leer cada pago o suscripción desde la API de MercadoPago, y una reconciliación busca las suscripciones por nuestra referencia (usuario y plan). Corre cuando el socio vuelve del checkout y desde un botón "Sincronizar MP" en el panel.

El costo. Un aviso con firma inválida se registra y se procesa igual. Uno falso sólo puede hacernos reprocesar datos nuestros, y eso es idempotente, pero es un control más débil que rechazarlo.

03

Páginas estáticas, permisos en cada handler

Por qué. El panel de admin dejó de renderizarse en el servidor. Sus páginas se prerenderizan y el middleware pide rol de admin antes de que carguen. Las páginas públicas se cachean un mes y el panel las invalida cuando el dueño guarda un cambio. Como las páginas ya no miran la sesión, cada handler de la API verifica sus propios permisos.

El costo. Los permisos se verifican dos veces, en el middleware y en el handler, y es más código para mantener a la par. Un cambio hecho por fuera del panel, directo en la base, no aparece en el sitio público hasta que vence el caché.

(04) Galería
Dashboard del admin
Dashboard del admin · Turnos, ingresos, socios activos, ingreso recurrente y cuánto se usó de las carteras este mes. Corrida local con datos de ejemplo.
Planes de membresía
Planes de membresía · El dueño define precio, cortes, horas de cabina, prioridad de reserva y beneficios por plan. Al guardar se crea su suscripción en MercadoPago.
Configuración de la cabina
Configuración de la cabina · Precio por hora para no socios, un precio aparte para las horas extra de los socios y horarios por día.
Reservar la cabina en el teléfono
Reservar la cabina en el teléfono · El socio ve las horas que le quedan en la cartera. Se usan primero; sólo se pagan las que no entran.
(05) Qué haría después
01Escribir tests para la cartera y el webhook: orden de consumo, pagos mixtos de cabina y avisos repetidos de MercadoPago. Hoy el repo no tiene.
02Cargar el secreto de firma correcto y volver a rechazar los avisos con firma inválida.
03Volver a llevar los cambios del esquema a migraciones de Prisma. El repo tiene sólo la primera, y las tablas de membresías, cartera y cabina no están en ella.
Próximo proyectoLa Trencería →
Nahuel SantillánES