Sistema completo de reservas de cine con bloqueo de butacas en tiempo real (concurrencia) y lógica de precios dinámicos.
CineFlow es un motor de reservas de cine de nivel producción construido con Laravel 12. Resuelve el problema más difícil de cualquier sistema de venta de entradas: evitar que dos personas compren la misma butaca a la vez. Lo hace combinando bloqueos temporales de asiento en tiempo real con bloqueo pesimista a nivel de base de datos dentro de transacciones atómicas.
Demo en vivo: (pendiente de desplegar — ver Despliegue)
- 🔒 Bloqueo de butacas en tiempo real (concurrencia). Cuando un usuario selecciona un asiento se crea un
SeatLocktemporal (8 minutos) ligado a su usuario/sesión. Otros usuarios ven la butaca ocupada al instante vía polling AJAX. - ⚔️ Prevención de doble reserva con bloqueo pesimista. La confirmación de la compra corre dentro de
DB::transaction(attempts: 3)usandolockForUpdate(), de modo que dos compras simultáneas de la misma butaca se serializan y la segunda falla limpiamente en lugar de crear un overbooking. - 💶 Precios dinámicos. El precio se calcula sobre el
preu_basede la sesión aplicando factores por tipo de entrada: Adulto ×1.00, Reducida ×0.80, Familia ×0.82, Senior +65 ×0.70. - 💳 Pagos con Stripe Checkout (modo test) + fallback simulado. Si hay claves de Stripe configuradas, el pago con tarjeta usa la página de Checkout alojada de Stripe (tarjeta de prueba
4242 4242 4242 4242). Sin claves, cae automáticamente a un flujo de pago simulado para poder probar la app sin cuenta de Stripe. - 🎟️ Entradas con QR firmado (HMAC) y panel de cliente con historial de reservas.
- 🗂️ Zero-config para desplegar. Por defecto usa SQLite (sin servidor de BD que provisionar); compatible con MySQL para desarrollo/producción.
| Capa | Tecnología |
|---|---|
| Backend | PHP 8.4, Laravel 12, Eloquent |
| Pagos | Stripe Checkout (stripe/stripe-php) |
| Frontend | Blade, Tailwind CSS, Vite, JavaScript (polling AJAX de butacas) |
| Base de datos | SQLite (por defecto) / MySQL |
| Infra | Docker multi-stage, Render / Railway / Fly.io |
| Tests | PHPUnit (38 tests, incluye tests de concurrencia y carrera) |
Usuario A ──┐ ┌── SeatLock (temporal, 8 min)
├─► /comprar/step2 ────────┤
Usuario B ──┘ (selección butaca) └── polling AJAX /seat/status
Confirmación:
DB::transaction(attempts: 3)
└─► SELECT ... FOR UPDATE (lockForUpdate)
├─ butaca libre ──► crea Reserva + ReservaSeat, libera locks
└─ butaca tomada ──► SeatAlreadyReservedException ──► vuelve a step2
El resultado: imposible vender la misma butaca dos veces, incluso bajo peticiones concurrentes (cubierto por ConcurrentPurchaseTest).
docker compose up --build
# App en http://localhost:8000El contenedor genera la clave de app, crea la base SQLite, ejecuta migraciones y seeders automáticamente.
composer install
npm ci && npm run build
cp .env.example .env
php artisan key:generate
touch database/database.sqlite
php artisan migrate --seed
php artisan serve| Rol | Contraseña | |
|---|---|---|
| Admin | admin@cineflow.test |
admin1234 |
| Taquilla | taquilla@cineflow.test |
taquilla1234 |
| Cliente | cliente@cineflow.test |
cliente1234 |
Añade a tu .env:
STRIPE_KEY=pk_test_xxx
STRIPE_SECRET=sk_test_xxx
STRIPE_CURRENCY=eurSin estas claves, el pago con tarjeta usa el flujo simulado. Con ellas, usa Stripe Checkout real en modo test.
php artisan testCorre 38 tests sobre SQLite: flujo completo de compra, expiración de locks, prevención de condiciones de carrera, bloqueo pesimista, autenticación y perfil.
El repo incluye blueprints listos para varias plataformas:
- Render →
render.yaml - Railway →
railway.json - Fly.io →
fly.toml - Docker →
Dockerfile+docker/entrypoint.sh
Todas usan SQLite por defecto (cero configuración de base de datos). Para producción con MySQL, configura las variables DB_* en la plataforma.
CineFlow es la evolución para portafolio de un proyecto final de ciclo (módulo M0616) originalmente desarrollado en equipo:
- Ayman Charoui
- Ismael Achamrouk
- Danna Guevara
Este repositorio reempaqueta, moderniza (Stripe real, despliegue, CI) y documenta ese trabajo. La documentación técnica original se conserva en docs/.
MIT.