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
|
PORT=3000
|
||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
|
PASSWORD_DB=T4Y7c)j.L0Toq5
|
||||||
# Database Settings (PostgreSQL / Supabase)
|
# Database Settings (Supabase / PostgreSQL)
|
||||||
DATABASE_URL="postgresql://admin:supersecretpassword123@localhost:5432/App_db?schema=public"
|
# Pooled connection - para queries de la app (PgBouncer, puerto 6543)
|
||||||
# SUPABASE_URL="https://your-project.supabase.co"
|
DATABASE_URL="postgresql://postgres.szfqeppzcyavmlmmvcwl:7LtH*QUUTfBcrYf@aws-0-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true&connection_limit=1"
|
||||||
# SUPABASE_KEY="your-anon-key"
|
# 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
|
SUPABASE_PASSWORD=7LtH*QUUTfBcrYf
|
||||||
NEXT_PUBLIC_SUPABASE_URL=https://szfqeppzcyavmlmmvcwl.supabase.co
|
NEXT_PUBLIC_SUPABASE_URL=https://szfqeppzcyavmlmmvcwl.supabase.co
|
||||||
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_zmH4vijRiPtiwO_TUTleNg_R20kK235
|
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_zmH4vijRiPtiwO_TUTleNg_R20kK235
|
||||||
|
|
||||||
|
|
||||||
# Active Directory / Azure AD SSO Config
|
# Active Directory / Azure AD SSO Config
|
||||||
AD_TENANT_ID="your-azure-tenant-id"
|
AD_TENANT_ID="your-azure-tenant-id"
|
||||||
AD_CLIENT_ID="your-azure-client-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_CLIENT_ID="your-azure-client-id"
|
||||||
NG_APP_AD_TENANT_ID="your-azure-tenant-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:dev": "nest start --watch",
|
||||||
"start:prod": "node dist/main",
|
"start:prod": "node dist/main",
|
||||||
"db:migrate": "prisma migrate deploy",
|
"db:migrate": "prisma migrate deploy",
|
||||||
"db:generate": "prisma generate"
|
"db:generate": "prisma generate",
|
||||||
|
"db:seed": "ts-node prisma/seed.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/common": "^10.0.0",
|
"@nestjs/common": "^10.0.0",
|
||||||
@ -16,7 +17,7 @@
|
|||||||
"@nestjs/jwt": "^10.0.0",
|
"@nestjs/jwt": "^10.0.0",
|
||||||
"@nestjs/passport": "^10.0.0",
|
"@nestjs/passport": "^10.0.0",
|
||||||
"@nestjs/platform-express": "^10.0.0",
|
"@nestjs/platform-express": "^10.0.0",
|
||||||
"@prisma/client": "^5.0.0",
|
"@prisma/client": "5.22.0",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
@ -27,7 +28,12 @@
|
|||||||
"@nestjs/schematics": "^10.0.0",
|
"@nestjs/schematics": "^10.0.0",
|
||||||
"@types/node": "^20.0.0",
|
"@types/node": "^20.0.0",
|
||||||
"@types/passport-jwt": "^4.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"
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"seed": "ts-node prisma/seed.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,8 +3,9 @@ generator client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "postgresql"
|
provider = "postgresql"
|
||||||
url = env("DATABASE_URL")
|
url = env("DATABASE_URL")
|
||||||
|
directUrl = env("DIRECT_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
model Reserva {
|
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