313 lines
17 KiB
TypeScript
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())
|