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 = { 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 = {} 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())