feat: add Supabase connection, seed script with 69 future reservations for July 2026
This commit is contained in:
parent
08eddc1d9a
commit
45287f1dcd
14
backend/.env
14
backend/.env
@ -5,16 +5,15 @@
|
||||
# ==========================================
|
||||
PORT=3000
|
||||
NODE_ENV=development
|
||||
|
||||
# Database Settings (PostgreSQL / Supabase)
|
||||
DATABASE_URL="postgresql://admin:supersecretpassword123@localhost:5432/App_db?schema=public"
|
||||
# SUPABASE_URL="https://your-project.supabase.co"
|
||||
# SUPABASE_KEY="your-anon-key"
|
||||
PASSWORD_DB=T4Y7c)j.L0Toq5
|
||||
# Database Settings (Supabase / PostgreSQL)
|
||||
# Pooled connection - para queries de la app (PgBouncer, puerto 6543)
|
||||
DATABASE_URL="postgresql://postgres.szfqeppzcyavmlmmvcwl:7LtH*QUUTfBcrYf@aws-0-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true&connection_limit=1"
|
||||
# Direct connection - para migraciones (bypasa PgBouncer, puerto 5432)
|
||||
DIRECT_URL="postgresql://postgres.szfqeppzcyavmlmmvcwl:7LtH*QUUTfBcrYf@aws-0-us-east-1.pooler.supabase.com:5432/postgres"
|
||||
SUPABASE_PASSWORD=7LtH*QUUTfBcrYf
|
||||
NEXT_PUBLIC_SUPABASE_URL=https://szfqeppzcyavmlmmvcwl.supabase.co
|
||||
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_zmH4vijRiPtiwO_TUTleNg_R20kK235
|
||||
|
||||
|
||||
# Active Directory / Azure AD SSO Config
|
||||
AD_TENANT_ID="your-azure-tenant-id"
|
||||
AD_CLIENT_ID="your-azure-client-id"
|
||||
@ -29,4 +28,3 @@ NG_APP_API_URL="http://localhost:3000/api"
|
||||
NG_APP_AD_CLIENT_ID="your-azure-client-id"
|
||||
NG_APP_AD_TENANT_ID="your-azure-tenant-id"
|
||||
|
||||
PASSWORD_DB=T4Y7c)j.L0Toq5
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
"start:dev": "nest start --watch",
|
||||
"start:prod": "node dist/main",
|
||||
"db:migrate": "prisma migrate deploy",
|
||||
"db:generate": "prisma generate"
|
||||
"db:generate": "prisma generate",
|
||||
"db:seed": "ts-node prisma/seed.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
@ -16,7 +17,7 @@
|
||||
"@nestjs/jwt": "^10.0.0",
|
||||
"@nestjs/passport": "^10.0.0",
|
||||
"@nestjs/platform-express": "^10.0.0",
|
||||
"@prisma/client": "^5.0.0",
|
||||
"@prisma/client": "5.22.0",
|
||||
"passport": "^0.7.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
@ -27,7 +28,12 @@
|
||||
"@nestjs/schematics": "^10.0.0",
|
||||
"@types/node": "^20.0.0",
|
||||
"@types/passport-jwt": "^4.0.0",
|
||||
"prisma": "^5.0.0",
|
||||
"dotenv": "^17.4.2",
|
||||
"prisma": "5.22.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"prisma": {
|
||||
"seed": "ts-node prisma/seed.ts"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,9 @@ generator client {
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
directUrl = env("DIRECT_URL")
|
||||
}
|
||||
|
||||
model Reserva {
|
||||
|
||||
128
backend/prisma/seed.ts
Normal file
128
backend/prisma/seed.ts
Normal file
@ -0,0 +1,128 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// Recursos disponibles en la empresa
|
||||
const resources = [
|
||||
{ id: 'sala-A', name: 'Sala de Reuniones A' },
|
||||
{ id: 'sala-B', name: 'Sala de Reuniones B' },
|
||||
{ id: 'cowork-1', name: 'Espacio Coworking 1' },
|
||||
{ id: 'cowork-2', name: 'Espacio Coworking 2' },
|
||||
{ id: 'auditorio', name: 'Auditorio Principal' },
|
||||
];
|
||||
|
||||
// Autores del equipo
|
||||
const authors = [
|
||||
'Jessica Orozco',
|
||||
'Carlos Méndez',
|
||||
'Ana Torres',
|
||||
'Luis Herrera',
|
||||
'María López',
|
||||
];
|
||||
|
||||
// Slots de horario (horas laborales)
|
||||
const slots = [
|
||||
{ start: '09:00', end: '10:00' },
|
||||
{ start: '10:00', end: '11:00' },
|
||||
{ start: '11:00', end: '12:00' },
|
||||
{ start: '14:00', end: '15:00' },
|
||||
{ start: '15:00', end: '16:00' },
|
||||
{ start: '16:00', end: '17:00' },
|
||||
{ start: '17:00', end: '18:00' },
|
||||
];
|
||||
|
||||
// Genera fechas futuras en julio 2026 (días hábiles: lunes a viernes)
|
||||
function getFutureDates(): string[] {
|
||||
const dates: string[] = [];
|
||||
// Desde mañana (02/07) hasta fin de julio (31/07)
|
||||
const start = new Date('2026-07-02');
|
||||
const end = new Date('2026-07-31');
|
||||
|
||||
for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
|
||||
const dayOfWeek = d.getDay();
|
||||
if (dayOfWeek !== 0 && dayOfWeek !== 6) {
|
||||
// excluir sábado y domingo
|
||||
dates.push(d.toISOString().split('T')[0]);
|
||||
}
|
||||
}
|
||||
return dates;
|
||||
}
|
||||
|
||||
function getRandom<T>(arr: T[]): T {
|
||||
return arr[Math.floor(Math.random() * arr.length)];
|
||||
}
|
||||
|
||||
function getRandomNotes(): string | undefined {
|
||||
const notes = [
|
||||
'Reunión de planificación sprint',
|
||||
'Demo con cliente',
|
||||
'Sesión de diseño',
|
||||
'Revisión de métricas',
|
||||
'Workshop de onboarding',
|
||||
'Retrospectiva del equipo',
|
||||
undefined,
|
||||
undefined, // 2/8 chance de sin notas
|
||||
];
|
||||
return getRandom(notes);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🌱 Iniciando seed de reservas futuras en Supabase...\n');
|
||||
|
||||
const dates = getFutureDates();
|
||||
console.log(`📅 Fechas a cubrir: ${dates[0]} → ${dates[dates.length - 1]} (${dates.length} días hábiles)`);
|
||||
|
||||
let created = 0;
|
||||
let skipped = 0;
|
||||
|
||||
for (const date of dates) {
|
||||
// 2-4 reservas por día para simular uso real
|
||||
const reservasDelDia = Math.floor(Math.random() * 3) + 2;
|
||||
|
||||
// Shuffle slots para no repetir
|
||||
const shuffledSlots = [...slots].sort(() => Math.random() - 0.5);
|
||||
|
||||
for (let i = 0; i < reservasDelDia; i++) {
|
||||
const slot = shuffledSlots[i];
|
||||
const resource = getRandom(resources);
|
||||
const author = getRandom(authors);
|
||||
|
||||
try {
|
||||
await prisma.reserva.create({
|
||||
data: {
|
||||
resourceId: resource.id,
|
||||
resourceName: resource.name,
|
||||
date,
|
||||
startTime: slot.start,
|
||||
endTime: slot.end,
|
||||
author,
|
||||
notes: getRandomNotes(),
|
||||
},
|
||||
});
|
||||
created++;
|
||||
console.log(` ✅ ${date} ${slot.start}-${slot.end} | ${resource.name} | ${author}`);
|
||||
} catch (e: any) {
|
||||
// Conflicto de unique constraint: mismo recurso + fecha + hora
|
||||
if (e.code === 'P2002') {
|
||||
skipped++;
|
||||
} else {
|
||||
console.error(` ❌ Error inesperado: ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n📊 Resultado:`);
|
||||
console.log(` ✅ Creadas: ${created} reservas`);
|
||||
console.log(` ⏭️ Omitidas por conflicto: ${skipped}`);
|
||||
console.log(`\n🎉 Seed completado. Datos disponibles en Supabase.`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('❌ Error en el seed:', e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user