- API REST completa con Node.js + Express + TypeScript - Autenticación JWT con roles (Player/Admin) - CRUD completo de canchas - Sistema de reservas con validaciones - Base de datos SQLite con Prisma ORM - Notificaciones por email (Nodemailer) - Seed de datos de prueba - Documentación de arquitectura Endpoints implementados: - Auth: register, login, refresh, me - Courts: CRUD + disponibilidad - Bookings: CRUD + confirmación/cancelación Credenciales de prueba: - admin@padel.com / admin123 - user@padel.com / user123
122 lines
3.1 KiB
TypeScript
122 lines
3.1 KiB
TypeScript
import { PrismaClient } from '@prisma/client';
|
|
import { hashPassword } from '../src/utils/password';
|
|
import { UserRole, PlayerLevel, CourtType } from '../src/utils/constants';
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
async function main() {
|
|
console.log('🌱 Seeding database...');
|
|
|
|
// Crear usuario admin
|
|
const adminPassword = await hashPassword('admin123');
|
|
const admin = await prisma.user.upsert({
|
|
where: { email: 'admin@padel.com' },
|
|
update: {},
|
|
create: {
|
|
email: 'admin@padel.com',
|
|
password: adminPassword,
|
|
firstName: 'Admin',
|
|
lastName: 'Sistema',
|
|
role: UserRole.ADMIN,
|
|
playerLevel: PlayerLevel.PROFESSIONAL,
|
|
isActive: true,
|
|
},
|
|
});
|
|
console.log('✅ Admin creado:', admin.email);
|
|
|
|
// Crear usuario de prueba
|
|
const userPassword = await hashPassword('user123');
|
|
const user = await prisma.user.upsert({
|
|
where: { email: 'user@padel.com' },
|
|
update: {},
|
|
create: {
|
|
email: 'user@padel.com',
|
|
password: userPassword,
|
|
firstName: 'Juan',
|
|
lastName: 'García',
|
|
role: UserRole.PLAYER,
|
|
playerLevel: PlayerLevel.INTERMEDIATE,
|
|
isActive: true,
|
|
},
|
|
});
|
|
console.log('✅ Usuario creado:', user.email);
|
|
|
|
// Crear canchas
|
|
const courts = [
|
|
{
|
|
name: 'Cancha 1 - Panorámica',
|
|
description: 'Cancha panorámica premium con cristal 360°',
|
|
type: CourtType.PANORAMIC,
|
|
isIndoor: true,
|
|
hasLighting: true,
|
|
pricePerHour: 2500,
|
|
},
|
|
{
|
|
name: 'Cancha 2 - Panorámica',
|
|
description: 'Cancha panorámica premium con cristal 360°',
|
|
type: CourtType.PANORAMIC,
|
|
isIndoor: true,
|
|
hasLighting: true,
|
|
pricePerHour: 2500,
|
|
},
|
|
{
|
|
name: 'Cancha 3 - Exterior',
|
|
description: 'Cancha exterior con iluminación nocturna',
|
|
type: CourtType.OUTDOOR,
|
|
isIndoor: false,
|
|
hasLighting: true,
|
|
pricePerHour: 2000,
|
|
},
|
|
{
|
|
name: 'Cancha 4 - Cubierta',
|
|
description: 'Cancha cubierta sin cristal',
|
|
type: CourtType.INDOOR,
|
|
isIndoor: true,
|
|
hasLighting: true,
|
|
pricePerHour: 2200,
|
|
},
|
|
];
|
|
|
|
for (const courtData of courts) {
|
|
const court = await prisma.court.upsert({
|
|
where: { name: courtData.name },
|
|
update: {},
|
|
create: courtData,
|
|
});
|
|
console.log('✅ Cancha creada:', court.name);
|
|
|
|
// Crear horarios para cada cancha (Lunes a Domingo, 8:00 - 23:00)
|
|
for (let day = 0; day <= 6; day++) {
|
|
await prisma.courtSchedule.upsert({
|
|
where: {
|
|
courtId_dayOfWeek: {
|
|
courtId: court.id,
|
|
dayOfWeek: day,
|
|
},
|
|
},
|
|
update: {},
|
|
create: {
|
|
courtId: court.id,
|
|
dayOfWeek: day,
|
|
openTime: '08:00',
|
|
closeTime: '23:00',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
console.log('\n🎾 Database seeded successfully!');
|
|
console.log('\nCredenciales de prueba:');
|
|
console.log(' Admin: admin@padel.com / admin123');
|
|
console.log(' User: user@padel.com / user123');
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|