Files

313 lines
17 KiB
TypeScript

import { PrismaClient, Phase, MatchStatus } from '@prisma/client'
import bcrypt from 'bcryptjs'
const prisma = new PrismaClient()
const teams = [
// GROUP A
{ name: 'Mexico', shortName: 'MEX', isoCode: 'mx', group: 'A', groupOrder: 1, confederation: 'CONCACAF' },
{ name: 'South Africa', shortName: 'RSA', isoCode: 'za', group: 'A', groupOrder: 2, confederation: 'CAF' },
{ name: 'South Korea', shortName: 'KOR', isoCode: 'kr', group: 'A', groupOrder: 3, confederation: 'AFC' },
{ name: 'Czech Republic',shortName: 'CZE', isoCode: 'cz', group: 'A', groupOrder: 4, confederation: 'UEFA' },
// GROUP B
{ name: 'Canada', shortName: 'CAN', isoCode: 'ca', group: 'B', groupOrder: 1, confederation: 'CONCACAF' },
{ name: 'Bosnia and Herzegovina',shortName: 'BIH', isoCode: 'ba', group: 'B', groupOrder: 2, confederation: 'UEFA' },
{ name: 'Qatar', shortName: 'QAT', isoCode: 'qa', group: 'B', groupOrder: 3, confederation: 'AFC' },
{ name: 'Switzerland', shortName: 'SUI', isoCode: 'ch', group: 'B', groupOrder: 4, confederation: 'UEFA' },
// GROUP C
{ name: 'Brazil', shortName: 'BRA', isoCode: 'br', group: 'C', groupOrder: 1, confederation: 'CONMEBOL' },
{ name: 'Morocco', shortName: 'MAR', isoCode: 'ma', group: 'C', groupOrder: 2, confederation: 'CAF' },
{ name: 'Haiti', shortName: 'HAI', isoCode: 'ht', group: 'C', groupOrder: 3, confederation: 'CONCACAF' },
{ name: 'Scotland', shortName: 'SCO', isoCode: 'gb-sct', group: 'C', groupOrder: 4, confederation: 'UEFA' },
// GROUP D
{ name: 'United States', shortName: 'USA', isoCode: 'us', group: 'D', groupOrder: 1, confederation: 'CONCACAF' },
{ name: 'Paraguay', shortName: 'PAR', isoCode: 'py', group: 'D', groupOrder: 2, confederation: 'CONMEBOL' },
{ name: 'Australia', shortName: 'AUS', isoCode: 'au', group: 'D', groupOrder: 3, confederation: 'AFC' },
{ name: 'Turkey', shortName: 'TUR', isoCode: 'tr', group: 'D', groupOrder: 4, confederation: 'UEFA' },
// GROUP E
{ name: 'Germany', shortName: 'GER', isoCode: 'de', group: 'E', groupOrder: 1, confederation: 'UEFA' },
{ name: 'Curaçao', shortName: 'CUW', isoCode: 'cw', group: 'E', groupOrder: 2, confederation: 'CONCACAF' },
{ name: 'Ivory Coast', shortName: 'CIV', isoCode: 'ci', group: 'E', groupOrder: 3, confederation: 'CAF' },
{ name: 'Ecuador', shortName: 'ECU', isoCode: 'ec', group: 'E', groupOrder: 4, confederation: 'CONMEBOL' },
// GROUP F
{ name: 'Netherlands', shortName: 'NED', isoCode: 'nl', group: 'F', groupOrder: 1, confederation: 'UEFA' },
{ name: 'Japan', shortName: 'JPN', isoCode: 'jp', group: 'F', groupOrder: 2, confederation: 'AFC' },
{ name: 'Sweden', shortName: 'SWE', isoCode: 'se', group: 'F', groupOrder: 3, confederation: 'UEFA' },
{ name: 'Tunisia', shortName: 'TUN', isoCode: 'tn', group: 'F', groupOrder: 4, confederation: 'CAF' },
// GROUP G
{ name: 'Belgium', shortName: 'BEL', isoCode: 'be', group: 'G', groupOrder: 1, confederation: 'UEFA' },
{ name: 'Egypt', shortName: 'EGY', isoCode: 'eg', group: 'G', groupOrder: 2, confederation: 'CAF' },
{ name: 'Iran', shortName: 'IRN', isoCode: 'ir', group: 'G', groupOrder: 3, confederation: 'AFC' },
{ name: 'New Zealand', shortName: 'NZL', isoCode: 'nz', group: 'G', groupOrder: 4, confederation: 'OFC' },
// GROUP H
{ name: 'Spain', shortName: 'ESP', isoCode: 'es', group: 'H', groupOrder: 1, confederation: 'UEFA' },
{ name: 'Cape Verde', shortName: 'CPV', isoCode: 'cv', group: 'H', groupOrder: 2, confederation: 'CAF' },
{ name: 'Saudi Arabia', shortName: 'KSA', isoCode: 'sa', group: 'H', groupOrder: 3, confederation: 'AFC' },
{ name: 'Uruguay', shortName: 'URU', isoCode: 'uy', group: 'H', groupOrder: 4, confederation: 'CONMEBOL' },
// GROUP I
{ name: 'France', shortName: 'FRA', isoCode: 'fr', group: 'I', groupOrder: 1, confederation: 'UEFA' },
{ name: 'Senegal', shortName: 'SEN', isoCode: 'sn', group: 'I', groupOrder: 2, confederation: 'CAF' },
{ name: 'Iraq', shortName: 'IRQ', isoCode: 'iq', group: 'I', groupOrder: 3, confederation: 'AFC' },
{ name: 'Norway', shortName: 'NOR', isoCode: 'no', group: 'I', groupOrder: 4, confederation: 'UEFA' },
// GROUP J
{ name: 'Argentina', shortName: 'ARG', isoCode: 'ar', group: 'J', groupOrder: 1, confederation: 'CONMEBOL' },
{ name: 'Algeria', shortName: 'ALG', isoCode: 'dz', group: 'J', groupOrder: 2, confederation: 'CAF' },
{ name: 'Austria', shortName: 'AUT', isoCode: 'at', group: 'J', groupOrder: 3, confederation: 'UEFA' },
{ name: 'Jordan', shortName: 'JOR', isoCode: 'jo', group: 'J', groupOrder: 4, confederation: 'AFC' },
// GROUP K
{ name: 'Portugal', shortName: 'POR', isoCode: 'pt', group: 'K', groupOrder: 1, confederation: 'UEFA' },
{ name: 'DR Congo', shortName: 'COD', isoCode: 'cd', group: 'K', groupOrder: 2, confederation: 'CAF' },
{ name: 'Uzbekistan', shortName: 'UZB', isoCode: 'uz', group: 'K', groupOrder: 3, confederation: 'AFC' },
{ name: 'Colombia', shortName: 'COL', isoCode: 'co', group: 'K', groupOrder: 4, confederation: 'CONMEBOL' },
// GROUP L
{ name: 'England', shortName: 'ENG', isoCode: 'gb-eng', group: 'L', groupOrder: 1, confederation: 'UEFA' },
{ name: 'Croatia', shortName: 'CRO', isoCode: 'hr', group: 'L', groupOrder: 2, confederation: 'UEFA' },
{ name: 'Ghana', shortName: 'GHA', isoCode: 'gh', group: 'L', groupOrder: 3, confederation: 'CAF' },
{ name: 'Panama', shortName: 'PAN', isoCode: 'pa', group: 'L', groupOrder: 4, confederation: 'CONCACAF' },
]
// Fechas por grupo: cada grupo tiene 3 fechas (jornadas)
// Jornada 1: 11-16 junio | Jornada 2: 17-23 junio | Jornada 3: 25-30 junio
const groupDates: Record<string, { md1a: Date; md1b: Date; md2a: Date; md2b: Date; md3: Date }> = {
A: { md1a: new Date('2026-06-11T18:00:00Z'), md1b: new Date('2026-06-11T21:00:00Z'), md2a: new Date('2026-06-17T18:00:00Z'), md2b: new Date('2026-06-17T21:00:00Z'), md3: new Date('2026-06-25T21:00:00Z') },
B: { md1a: new Date('2026-06-12T18:00:00Z'), md1b: new Date('2026-06-12T21:00:00Z'), md2a: new Date('2026-06-18T18:00:00Z'), md2b: new Date('2026-06-18T21:00:00Z'), md3: new Date('2026-06-26T21:00:00Z') },
C: { md1a: new Date('2026-06-12T18:00:00Z'), md1b: new Date('2026-06-12T21:00:00Z'), md2a: new Date('2026-06-18T18:00:00Z'), md2b: new Date('2026-06-18T21:00:00Z'), md3: new Date('2026-06-26T18:00:00Z') },
D: { md1a: new Date('2026-06-13T18:00:00Z'), md1b: new Date('2026-06-13T21:00:00Z'), md2a: new Date('2026-06-19T18:00:00Z'), md2b: new Date('2026-06-19T21:00:00Z'), md3: new Date('2026-06-27T21:00:00Z') },
E: { md1a: new Date('2026-06-13T18:00:00Z'), md1b: new Date('2026-06-13T21:00:00Z'), md2a: new Date('2026-06-19T18:00:00Z'), md2b: new Date('2026-06-19T21:00:00Z'), md3: new Date('2026-06-27T18:00:00Z') },
F: { md1a: new Date('2026-06-14T18:00:00Z'), md1b: new Date('2026-06-14T21:00:00Z'), md2a: new Date('2026-06-20T18:00:00Z'), md2b: new Date('2026-06-20T21:00:00Z'), md3: new Date('2026-06-28T21:00:00Z') },
G: { md1a: new Date('2026-06-14T18:00:00Z'), md1b: new Date('2026-06-14T21:00:00Z'), md2a: new Date('2026-06-20T18:00:00Z'), md2b: new Date('2026-06-20T21:00:00Z'), md3: new Date('2026-06-28T18:00:00Z') },
H: { md1a: new Date('2026-06-15T18:00:00Z'), md1b: new Date('2026-06-15T21:00:00Z'), md2a: new Date('2026-06-21T18:00:00Z'), md2b: new Date('2026-06-21T21:00:00Z'), md3: new Date('2026-06-29T21:00:00Z') },
I: { md1a: new Date('2026-06-15T18:00:00Z'), md1b: new Date('2026-06-15T21:00:00Z'), md2a: new Date('2026-06-21T18:00:00Z'), md2b: new Date('2026-06-21T21:00:00Z'), md3: new Date('2026-06-29T18:00:00Z') },
J: { md1a: new Date('2026-06-16T18:00:00Z'), md1b: new Date('2026-06-16T21:00:00Z'), md2a: new Date('2026-06-22T18:00:00Z'), md2b: new Date('2026-06-22T21:00:00Z'), md3: new Date('2026-06-30T21:00:00Z') },
K: { md1a: new Date('2026-06-16T18:00:00Z'), md1b: new Date('2026-06-16T21:00:00Z'), md2a: new Date('2026-06-22T18:00:00Z'), md2b: new Date('2026-06-22T21:00:00Z'), md3: new Date('2026-06-30T18:00:00Z') },
L: { md1a: new Date('2026-06-17T18:00:00Z'), md1b: new Date('2026-06-17T21:00:00Z'), md2a: new Date('2026-06-23T18:00:00Z'), md2b: new Date('2026-06-23T21:00:00Z'), md3: new Date('2026-07-01T21:00:00Z') },
}
async function main() {
console.log('Seeding teams...')
const teamMap: Record<string, string> = {}
for (const team of teams) {
const t = await prisma.team.upsert({
where: { shortName: team.shortName },
update: team,
create: team,
})
teamMap[team.shortName] = t.id
}
console.log(`${teams.length} teams seeded.`)
// ── GROUP STAGE MATCHES ─────────────────────────────────────────────────────
console.log('Seeding group stage matches...')
const groups = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L']
for (let gi = 0; gi < groups.length; gi++) {
const g = groups[gi]
const baseMatchNum = gi * 6 + 1
const gTeams = teams.filter(t => t.group === g).sort((a, b) => a.groupOrder - b.groupOrder)
const [t1, t2, t3, t4] = gTeams
const d = groupDates[g]
const groupMatches = [
// Jornada 1
{ matchNumber: baseMatchNum, homeShort: t1.shortName, awayShort: t2.shortName, scheduledAt: d.md1a, matchday: 1 },
{ matchNumber: baseMatchNum + 1, homeShort: t3.shortName, awayShort: t4.shortName, scheduledAt: d.md1b, matchday: 1 },
// Jornada 2
{ matchNumber: baseMatchNum + 2, homeShort: t1.shortName, awayShort: t3.shortName, scheduledAt: d.md2a, matchday: 2 },
{ matchNumber: baseMatchNum + 3, homeShort: t2.shortName, awayShort: t4.shortName, scheduledAt: d.md2b, matchday: 2 },
// Jornada 3 (simultáneos)
{ matchNumber: baseMatchNum + 4, homeShort: t1.shortName, awayShort: t4.shortName, scheduledAt: d.md3, matchday: 3 },
{ matchNumber: baseMatchNum + 5, homeShort: t2.shortName, awayShort: t3.shortName, scheduledAt: d.md3, matchday: 3 },
]
for (const m of groupMatches) {
await prisma.match.upsert({
where: { matchNumber: m.matchNumber },
update: {},
create: {
matchNumber: m.matchNumber,
phase: Phase.GROUP_STAGE,
group: g,
matchday: m.matchday,
homeTeamId: teamMap[m.homeShort],
awayTeamId: teamMap[m.awayShort],
scheduledAt: m.scheduledAt,
status: MatchStatus.SCHEDULED,
},
})
}
}
// ── ROUND OF 32 (16 partidos) ────────────────────────────────────────────────
console.log('Seeding knockout matches...')
const r32Labels = [
{ home: '1° Grupo A', away: '3° Grupo B/C/D' },
{ home: '1° Grupo C', away: '3° Grupo A/B/F' },
{ home: '1° Grupo B', away: '3° Grupo A/C/D' },
{ home: '1° Grupo D', away: '3° Grupo B/C/F' },
{ home: '1° Grupo E', away: '3° Grupo A/B/E' },
{ home: '1° Grupo G', away: '3° Grupo A/C/E' },
{ home: '1° Grupo F', away: '3° Grupo A/D/E' },
{ home: '1° Grupo H', away: '3° Grupo B/D/E' },
{ home: '1° Grupo I', away: '3° Grupo C/D/F' },
{ home: '1° Grupo K', away: '3° Grupo B/E/F' },
{ home: '1° Grupo J', away: '3° Grupo C/E/F' },
{ home: '1° Grupo L', away: '3° Grupo A/E/F' },
{ home: '2° Grupo A', away: '2° Grupo B' },
{ home: '2° Grupo C', away: '2° Grupo D' },
{ home: '2° Grupo E', away: '2° Grupo F' },
{ home: '2° Grupo G', away: '2° Grupo H' },
]
const r32Dates = [
new Date('2026-07-04T18:00:00Z'), new Date('2026-07-04T21:00:00Z'),
new Date('2026-07-05T18:00:00Z'), new Date('2026-07-05T21:00:00Z'),
new Date('2026-07-06T18:00:00Z'), new Date('2026-07-06T21:00:00Z'),
new Date('2026-07-07T18:00:00Z'), new Date('2026-07-07T21:00:00Z'),
new Date('2026-07-08T18:00:00Z'), new Date('2026-07-08T21:00:00Z'),
new Date('2026-07-09T18:00:00Z'), new Date('2026-07-09T21:00:00Z'),
new Date('2026-07-10T18:00:00Z'), new Date('2026-07-10T21:00:00Z'),
new Date('2026-07-11T18:00:00Z'), new Date('2026-07-11T21:00:00Z'),
]
for (let i = 0; i < 16; i++) {
await prisma.match.upsert({
where: { matchNumber: 73 + i },
update: {},
create: {
matchNumber: 73 + i,
phase: Phase.ROUND_OF_32,
homeLabel: r32Labels[i].home,
awayLabel: r32Labels[i].away,
scheduledAt: r32Dates[i],
status: MatchStatus.SCHEDULED,
},
})
}
// ── ROUND OF 16 (8 partidos) ─────────────────────────────────────────────────
const r16Dates = [
new Date('2026-07-13T18:00:00Z'), new Date('2026-07-13T21:00:00Z'),
new Date('2026-07-14T18:00:00Z'), new Date('2026-07-14T21:00:00Z'),
new Date('2026-07-15T18:00:00Z'), new Date('2026-07-15T21:00:00Z'),
new Date('2026-07-16T18:00:00Z'), new Date('2026-07-16T21:00:00Z'),
]
for (let i = 0; i < 8; i++) {
await prisma.match.upsert({
where: { matchNumber: 89 + i },
update: {},
create: {
matchNumber: 89 + i,
phase: Phase.ROUND_OF_16,
homeLabel: `Ganador partido ${73 + i * 2}`,
awayLabel: `Ganador partido ${74 + i * 2}`,
scheduledAt: r16Dates[i],
status: MatchStatus.SCHEDULED,
},
})
}
// ── QUARTER FINALS (4 partidos) ───────────────────────────────────────────────
const qfDates = [
new Date('2026-07-18T18:00:00Z'), new Date('2026-07-18T21:00:00Z'),
new Date('2026-07-19T18:00:00Z'), new Date('2026-07-19T21:00:00Z'),
]
for (let i = 0; i < 4; i++) {
await prisma.match.upsert({
where: { matchNumber: 97 + i },
update: {},
create: {
matchNumber: 97 + i,
phase: Phase.QUARTER_FINALS,
homeLabel: `Ganador partido ${89 + i * 2}`,
awayLabel: `Ganador partido ${90 + i * 2}`,
scheduledAt: qfDates[i],
status: MatchStatus.SCHEDULED,
},
})
}
// ── SEMI FINALS (2 partidos) ──────────────────────────────────────────────────
await prisma.match.upsert({
where: { matchNumber: 101 },
update: {},
create: {
matchNumber: 101,
phase: Phase.SEMI_FINALS,
homeLabel: 'Ganador partido 97',
awayLabel: 'Ganador partido 98',
scheduledAt: new Date('2026-07-22T21:00:00Z'),
status: MatchStatus.SCHEDULED,
},
})
await prisma.match.upsert({
where: { matchNumber: 102 },
update: {},
create: {
matchNumber: 102,
phase: Phase.SEMI_FINALS,
homeLabel: 'Ganador partido 99',
awayLabel: 'Ganador partido 100',
scheduledAt: new Date('2026-07-23T21:00:00Z'),
status: MatchStatus.SCHEDULED,
},
})
// ── TERCER PUESTO ─────────────────────────────────────────────────────────────
await prisma.match.upsert({
where: { matchNumber: 103 },
update: {},
create: {
matchNumber: 103,
phase: Phase.THIRD_PLACE,
homeLabel: 'Perdedor Semi 1',
awayLabel: 'Perdedor Semi 2',
scheduledAt: new Date('2026-07-25T18:00:00Z'),
status: MatchStatus.SCHEDULED,
},
})
// ── FINAL ─────────────────────────────────────────────────────────────────────
await prisma.match.upsert({
where: { matchNumber: 104 },
update: {},
create: {
matchNumber: 104,
phase: Phase.FINAL,
homeLabel: 'Ganador Semi 1',
awayLabel: 'Ganador Semi 2',
scheduledAt: new Date('2026-07-26T20:00:00Z'),
status: MatchStatus.SCHEDULED,
},
})
console.log('104 matches seeded.')
// ── ADMIN USER ────────────────────────────────────────────────────────────────
const adminPassword = await bcrypt.hash('admin2026', 12)
await prisma.user.upsert({
where: { email: 'admin@prode.com' },
update: {},
create: {
email: 'admin@prode.com',
password: adminPassword,
name: 'Admin',
role: 'ADMIN',
},
})
console.log('Admin user: admin@prode.com / admin2026')
console.log('Seed complete!')
}
main()
.catch(e => { console.error(e); process.exit(1) })
.finally(() => prisma.$disconnect())