first commit
This commit is contained in:
252
prisma/schema.prisma
Normal file
252
prisma/schema.prisma
Normal file
@@ -0,0 +1,252 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum Role {
|
||||
USER
|
||||
ADMIN
|
||||
}
|
||||
|
||||
enum Position {
|
||||
GK
|
||||
DEF
|
||||
MID
|
||||
FWD
|
||||
}
|
||||
|
||||
enum MatchStage {
|
||||
GROUP
|
||||
ROUND_OF_16
|
||||
QUARTER_FINAL
|
||||
SEMI_FINAL
|
||||
THIRD_PLACE
|
||||
FINAL
|
||||
}
|
||||
|
||||
enum MatchStatus {
|
||||
SCHEDULED
|
||||
LIVE
|
||||
FINISHED
|
||||
}
|
||||
|
||||
enum TeamStatus {
|
||||
ACTIVE
|
||||
INACTIVE
|
||||
}
|
||||
|
||||
enum PaymentStatus {
|
||||
PENDING
|
||||
SUCCESS
|
||||
FAILED
|
||||
}
|
||||
|
||||
enum EventType {
|
||||
GOAL
|
||||
ASSIST
|
||||
YELLOW_CARD
|
||||
RED_CARD
|
||||
SECOND_YELLOW
|
||||
SUBSTITUTION_IN
|
||||
SUBSTITUTION_OUT
|
||||
INJURY_NO_SUB
|
||||
CLEAN_SHEET
|
||||
PENALTY_SAVED
|
||||
PENALTY_MISSED
|
||||
OWN_GOAL
|
||||
EXTRA_TIME_BONUS
|
||||
MOTM
|
||||
}
|
||||
|
||||
model Country {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
code String @unique
|
||||
flagUrl String?
|
||||
defaultFormation String @default("4-3-3")
|
||||
group Group? @relation(fields: [groupId], references: [id])
|
||||
groupId String?
|
||||
isEliminated Boolean @default(false)
|
||||
players Player[]
|
||||
homeMatches Match[] @relation("HomeTeam")
|
||||
awayMatches Match[] @relation("AwayTeam")
|
||||
}
|
||||
|
||||
model Group {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
countries Country[]
|
||||
}
|
||||
|
||||
model Player {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
position Position
|
||||
countryId String
|
||||
country Country @relation(fields: [countryId], references: [id])
|
||||
price Float @default(5.0)
|
||||
totalPoints Int @default(0)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
matchStats PlayerMatchStat[]
|
||||
teamPlayers TeamPlayer[]
|
||||
events MatchEvent[]
|
||||
}
|
||||
|
||||
model Match {
|
||||
id String @id @default(cuid())
|
||||
homeTeamId String
|
||||
awayTeamId String
|
||||
homeTeam Country @relation("HomeTeam", fields: [homeTeamId], references: [id])
|
||||
awayTeam Country @relation("AwayTeam", fields: [awayTeamId], references: [id])
|
||||
homeScore Int?
|
||||
awayScore Int?
|
||||
stage MatchStage @default(GROUP)
|
||||
status MatchStatus @default(SCHEDULED)
|
||||
matchDate DateTime
|
||||
roundId String?
|
||||
round Round? @relation(fields: [roundId], references: [id])
|
||||
playerStats PlayerMatchStat[]
|
||||
events MatchEvent[]
|
||||
lineups MatchLineup[]
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model Round {
|
||||
id String @id @default(cuid())
|
||||
number Int @unique
|
||||
name String
|
||||
isActive Boolean @default(false)
|
||||
deadline DateTime
|
||||
matches Match[]
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model MatchEvent {
|
||||
id String @id @default(cuid())
|
||||
matchId String
|
||||
playerId String
|
||||
match Match @relation(fields: [matchId], references: [id], onDelete: Cascade)
|
||||
player Player @relation(fields: [playerId], references: [id], onDelete: Cascade)
|
||||
type EventType
|
||||
minute Int?
|
||||
extraInfo String?
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model MatchLineup {
|
||||
id String @id @default(cuid())
|
||||
matchId String
|
||||
countryId String
|
||||
match Match @relation(fields: [matchId], references: [id], onDelete: Cascade)
|
||||
formation String
|
||||
playerIds String[]
|
||||
}
|
||||
|
||||
model PlayerMatchStat {
|
||||
id String @id @default(cuid())
|
||||
playerId String
|
||||
matchId String
|
||||
player Player @relation(fields: [playerId], references: [id], onDelete: Cascade)
|
||||
match Match @relation(fields: [matchId], references: [id], onDelete: Cascade)
|
||||
goals Int @default(0)
|
||||
assists Int @default(0)
|
||||
yellowCards Int @default(0)
|
||||
redCards Int @default(0)
|
||||
minutesPlayed Int @default(0)
|
||||
cleanSheet Boolean @default(false)
|
||||
penaltySaved Int @default(0)
|
||||
penaltyMissed Int @default(0)
|
||||
ownGoals Int @default(0)
|
||||
isMotm Boolean @default(false)
|
||||
extraTimeBonus Int @default(0)
|
||||
points Int @default(0)
|
||||
|
||||
@@unique([playerId, matchId])
|
||||
}
|
||||
|
||||
model ScoringRule {
|
||||
id String @id @default(cuid())
|
||||
position Position
|
||||
eventType EventType
|
||||
points Int
|
||||
updatedAt DateTime @updatedAt
|
||||
updatedBy String?
|
||||
|
||||
@@unique([position, eventType])
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
name String?
|
||||
email String @unique
|
||||
password String
|
||||
role Role @default(USER)
|
||||
createdAt DateTime @default(now())
|
||||
team Team?
|
||||
sessions Session[]
|
||||
payments Payment[]
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @default(cuid())
|
||||
sessionToken String @unique
|
||||
userId String
|
||||
expires DateTime
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model Team {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
userId String @unique
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
budget Float @default(100.0)
|
||||
totalPoints Int @default(0)
|
||||
formation String @default("4-3-3")
|
||||
status TeamStatus @default(INACTIVE)
|
||||
createdAt DateTime @default(now())
|
||||
players TeamPlayer[]
|
||||
}
|
||||
|
||||
model TeamPlayer {
|
||||
teamId String
|
||||
playerId String
|
||||
isCaptain Boolean @default(false)
|
||||
isViceCaptain Boolean @default(false)
|
||||
isBench Boolean @default(false)
|
||||
positionIndex Int @default(0)
|
||||
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
||||
player Player @relation(fields: [playerId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([teamId, playerId])
|
||||
}
|
||||
|
||||
model Package {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
budgetBonus Float
|
||||
price Int
|
||||
description String?
|
||||
isActive Boolean @default(true)
|
||||
payments Payment[]
|
||||
}
|
||||
|
||||
model Payment {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
packageId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
package Package @relation(fields: [packageId], references: [id])
|
||||
amount Int
|
||||
authority String? @unique
|
||||
refId String?
|
||||
status PaymentStatus @default(PENDING)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
235
prisma/seed.ts
Normal file
235
prisma/seed.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
// DEFAULT_RULES رو مستقیم اینجا تعریف میکنیم تا از @/ alias استفاده نکنیم
|
||||
const DEFAULT_RULES = {
|
||||
GK: { GOAL: 10, ASSIST: 3, YELLOW_CARD: -1, RED_CARD: -3, SECOND_YELLOW: -3, CLEAN_SHEET: 6, PENALTY_SAVED: 5, PENALTY_MISSED: -2, OWN_GOAL: -2, MOTM: 3, EXTRA_TIME_BONUS: 1, INJURY_NO_SUB: -1 },
|
||||
DEF: { GOAL: 8, ASSIST: 3, YELLOW_CARD: -1, RED_CARD: -3, SECOND_YELLOW: -3, CLEAN_SHEET: 4, PENALTY_SAVED: 0, PENALTY_MISSED: -2, OWN_GOAL: -2, MOTM: 3, EXTRA_TIME_BONUS: 1, INJURY_NO_SUB: -1 },
|
||||
MID: { GOAL: 5, ASSIST: 3, YELLOW_CARD: -2, RED_CARD: -3, SECOND_YELLOW: -3, CLEAN_SHEET: 1, PENALTY_SAVED: 0, PENALTY_MISSED: -2, OWN_GOAL: -2, MOTM: 3, EXTRA_TIME_BONUS: 1, INJURY_NO_SUB: -1 },
|
||||
FWD: { GOAL: 4, ASSIST: 3, YELLOW_CARD: -1, RED_CARD: -3, SECOND_YELLOW: -3, CLEAN_SHEET: 0, PENALTY_SAVED: 0, PENALTY_MISSED: -2, OWN_GOAL: -2, MOTM: 3, EXTRA_TIME_BONUS: 1, INJURY_NO_SUB: -1 },
|
||||
} as const;
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// ترکیب پیشفرض تیمهای ملی معروف (بر اساس آخرین اطلاعات)
|
||||
const COUNTRY_FORMATIONS: Record<string, string> = {
|
||||
BRA: "4-3-3", FRA: "4-3-3", ARG: "4-3-3", ENG: "4-3-3",
|
||||
ESP: "4-3-3", GER: "4-2-3-1", POR: "4-3-3", NED: "4-3-3",
|
||||
BEL: "4-3-3", CRO: "4-3-3", MAR: "4-3-3", IRN: "4-5-1",
|
||||
URU: "4-3-3", SEN: "4-3-3", KOR: "4-3-3", JPN: "4-3-3",
|
||||
MEX: "4-3-3", USA: "4-3-3", CAN: "4-3-3", AUS: "4-3-3",
|
||||
POL: "4-3-3", DEN: "4-3-3", SUI: "4-2-3-1", SRB: "3-4-3",
|
||||
WAL: "5-3-2", TUN: "4-3-3", CMR: "4-3-3", GHA: "4-2-3-1",
|
||||
ECU: "4-3-3", QAT: "5-3-2", KSA: "4-3-3", CRC: "5-4-1",
|
||||
};
|
||||
|
||||
const COUNTRIES = [
|
||||
{ name: "برزیل", code: "BRA", flag: "🇧🇷", group: "G" },
|
||||
{ name: "سربیا", code: "SRB", flag: "🇷🇸", group: "G" },
|
||||
{ name: "سوئیس", code: "SUI", flag: "🇨🇭", group: "G" },
|
||||
{ name: "کامرون", code: "CMR", flag: "🇨🇲", group: "G" },
|
||||
{ name: "فرانسه", code: "FRA", flag: "🇫🇷", group: "D" },
|
||||
{ name: "استرالیا", code: "AUS", flag: "🇦🇺", group: "D" },
|
||||
{ name: "دانمارک", code: "DEN", flag: "🇩🇰", group: "D" },
|
||||
{ name: "تونس", code: "TUN", flag: "🇹🇳", group: "D" },
|
||||
{ name: "آرژانتین", code: "ARG", flag: "🇦🇷", group: "C" },
|
||||
{ name: "عربستان", code: "KSA", flag: "🇸🇦", group: "C" },
|
||||
{ name: "مکزیک", code: "MEX", flag: "🇲🇽", group: "C" },
|
||||
{ name: "لهستان", code: "POL", flag: "🇵🇱", group: "C" },
|
||||
{ name: "ایران", code: "IRN", flag: "🇮🇷", group: "B" },
|
||||
{ name: "انگلیس", code: "ENG", flag: "🏴", group: "B" },
|
||||
{ name: "آمریکا", code: "USA", flag: "🇺🇸", group: "B" },
|
||||
{ name: "ولز", code: "WAL", flag: "🏴", group: "B" },
|
||||
{ name: "آلمان", code: "GER", flag: "🇩🇪", group: "E" },
|
||||
{ name: "ژاپن", code: "JPN", flag: "🇯🇵", group: "E" },
|
||||
{ name: "اسپانیا", code: "ESP", flag: "🇪🇸", group: "E" },
|
||||
{ name: "کاستاریکا", code: "CRC", flag: "🇨🇷", group: "E" },
|
||||
{ name: "بلژیک", code: "BEL", flag: "🇧🇪", group: "F" },
|
||||
{ name: "کانادا", code: "CAN", flag: "🇨🇦", group: "F" },
|
||||
{ name: "مراکش", code: "MAR", flag: "🇲🇦", group: "F" },
|
||||
{ name: "کرواسی", code: "CRO", flag: "🇭🇷", group: "F" },
|
||||
{ name: "پرتغال", code: "POR", flag: "🇵🇹", group: "H" },
|
||||
{ name: "غنا", code: "GHA", flag: "🇬🇭", group: "H" },
|
||||
{ name: "اروگوئه", code: "URU", flag: "🇺🇾", group: "H" },
|
||||
{ name: "کره جنوبی", code: "KOR", flag: "🇰🇷", group: "H" },
|
||||
{ name: "هلند", code: "NED", flag: "🇳🇱", group: "A" },
|
||||
{ name: "سنگال", code: "SEN", flag: "🇸🇳", group: "A" },
|
||||
{ name: "اکوادور", code: "ECU", flag: "🇪🇨", group: "A" },
|
||||
{ name: "قطر", code: "QAT", flag: "🇶🇦", group: "A" },
|
||||
];
|
||||
|
||||
const PLAYERS_DATA = [
|
||||
{ name: "آلیسون بکر", pos: "GK", code: "BRA", price: 6.0, pts: 42 },
|
||||
{ name: "تیاگو سیلوا", pos: "DEF", code: "BRA", price: 6.5, pts: 38 },
|
||||
{ name: "مارکینیوس", pos: "DEF", code: "BRA", price: 6.0, pts: 35 },
|
||||
{ name: "کاسمیرو", pos: "MID", code: "BRA", price: 8.0, pts: 52 },
|
||||
{ name: "نیمار", pos: "FWD", code: "BRA", price: 11.5, pts: 68 },
|
||||
{ name: "وینیسیوس جونیور", pos: "FWD", code: "BRA", price: 10.5, pts: 72 },
|
||||
{ name: "ریچارلیسون", pos: "FWD", code: "BRA", price: 8.5, pts: 55 },
|
||||
{ name: "هوگو لوریس", pos: "GK", code: "FRA", price: 6.0, pts: 40 },
|
||||
{ name: "رافائل واران", pos: "DEF", code: "FRA", price: 6.5, pts: 36 },
|
||||
{ name: "کیلیان امباپه", pos: "FWD", code: "FRA", price: 12.5, pts: 88 },
|
||||
{ name: "آنتوان گریزمان", pos: "MID", code: "FRA", price: 9.5, pts: 62 },
|
||||
{ name: "اولیویه ژیرو", pos: "FWD", code: "FRA", price: 7.5, pts: 48 },
|
||||
{ name: "اوسمان دمبله", pos: "FWD", code: "FRA", price: 8.0, pts: 44 },
|
||||
{ name: "امیلیانو مارتینز", pos: "GK", code: "ARG", price: 6.5, pts: 55 },
|
||||
{ name: "لیونل مسی", pos: "FWD", code: "ARG", price: 12.5, pts: 92 },
|
||||
{ name: "خولیان آلوارز", pos: "FWD", code: "ARG", price: 8.5, pts: 60 },
|
||||
{ name: "رودریگو دپاول", pos: "MID", code: "ARG", price: 7.5, pts: 45 },
|
||||
{ name: "نیکولاس اوتامندی", pos: "DEF", code: "ARG", price: 5.5, pts: 32 },
|
||||
{ name: "جوردن پیکفورد", pos: "GK", code: "ENG", price: 5.5, pts: 38 },
|
||||
{ name: "جود بلینگهام", pos: "MID", code: "ENG", price: 10.5, pts: 75 },
|
||||
{ name: "هری کین", pos: "FWD", code: "ENG", price: 11.0, pts: 70 },
|
||||
{ name: "بوکایو ساکا", pos: "MID", code: "ENG", price: 8.5, pts: 58 },
|
||||
{ name: "فیل فودن", pos: "MID", code: "ENG", price: 9.0, pts: 62 },
|
||||
{ name: "جان استونز", pos: "DEF", code: "ENG", price: 6.0, pts: 34 },
|
||||
{ name: "اونای سیمون", pos: "GK", code: "ESP", price: 5.5, pts: 36 },
|
||||
{ name: "پدری", pos: "MID", code: "ESP", price: 9.0, pts: 60 },
|
||||
{ name: "گاوی", pos: "MID", code: "ESP", price: 8.5, pts: 55 },
|
||||
{ name: "آلوارو موراتا", pos: "FWD", code: "ESP", price: 7.5, pts: 46 },
|
||||
{ name: "دنی اولمو", pos: "MID", code: "ESP", price: 7.0, pts: 42 },
|
||||
{ name: "مانوئل نویر", pos: "GK", code: "GER", price: 6.0, pts: 38 },
|
||||
{ name: "توماس مولر", pos: "MID", code: "GER", price: 8.0, pts: 50 },
|
||||
{ name: "کای هاورتز", pos: "MID", code: "GER", price: 8.5, pts: 52 },
|
||||
{ name: "یامله موسیالا", pos: "MID", code: "GER", price: 9.0, pts: 65 },
|
||||
{ name: "آنتونیو رودیگر", pos: "DEF", code: "GER", price: 5.5, pts: 30 },
|
||||
{ name: "دیوگو کوستا", pos: "GK", code: "POR", price: 5.5, pts: 35 },
|
||||
{ name: "کریستیانو رونالدو", pos: "FWD", code: "POR", price: 11.0, pts: 65 },
|
||||
{ name: "برونو فرناندز", pos: "MID", code: "POR", price: 10.0, pts: 70 },
|
||||
{ name: "رافائل لئائو", pos: "FWD", code: "POR", price: 8.5, pts: 55 },
|
||||
{ name: "روبن دیاز", pos: "DEF", code: "POR", price: 6.0, pts: 36 },
|
||||
{ name: "علیرضا بیرانوند", pos: "GK", code: "IRN", price: 5.0, pts: 28 },
|
||||
{ name: "مهدی طارمی", pos: "FWD", code: "IRN", price: 8.0, pts: 50 },
|
||||
{ name: "سردار آزمون", pos: "FWD", code: "IRN", price: 7.5, pts: 44 },
|
||||
{ name: "علی کریمی", pos: "MID", code: "IRN", price: 6.0, pts: 32 },
|
||||
{ name: "رامین رضاییان", pos: "DEF", code: "IRN", price: 5.0, pts: 22 },
|
||||
{ name: "یاسین بونو", pos: "GK", code: "MAR", price: 6.5, pts: 58 },
|
||||
{ name: "اشرف حکیمی", pos: "DEF", code: "MAR", price: 8.0, pts: 62 },
|
||||
{ name: "حکیم زیاش", pos: "MID", code: "MAR", price: 7.5, pts: 48 },
|
||||
{ name: "یوسف النصیری", pos: "FWD", code: "MAR", price: 7.0, pts: 45 },
|
||||
{ name: "دومینیک لیواکوویچ", pos: "GK", code: "CRO", price: 6.0, pts: 50 },
|
||||
{ name: "لوکا مودریچ", pos: "MID", code: "CRO", price: 9.5, pts: 68 },
|
||||
{ name: "ایوان پریشیچ", pos: "MID", code: "CRO", price: 7.5, pts: 48 },
|
||||
{ name: "آندره کراماریچ", pos: "FWD", code: "CRO", price: 7.0, pts: 44 },
|
||||
{ name: "آندریس نوپرت", pos: "GK", code: "NED", price: 5.5, pts: 36 },
|
||||
{ name: "ویرخیل فان دایک", pos: "DEF", code: "NED", price: 7.0, pts: 48 },
|
||||
{ name: "دنزل دامفریس", pos: "DEF", code: "NED", price: 7.5, pts: 52 },
|
||||
{ name: "کودی گاکپو", pos: "FWD", code: "NED", price: 8.0, pts: 58 },
|
||||
{ name: "تیبو کورتوا", pos: "GK", code: "BEL", price: 6.5, pts: 44 },
|
||||
{ name: "کوین دبروینه", pos: "MID", code: "BEL", price: 11.0, pts: 72 },
|
||||
{ name: "رومله لوکاکو", pos: "FWD", code: "BEL", price: 9.5, pts: 55 },
|
||||
];
|
||||
|
||||
async function main() {
|
||||
console.log("🌱 Seeding...");
|
||||
|
||||
// ─── ادمین و کاربران ─────────────────────────────────
|
||||
const adminPwd = await bcrypt.hash("admin123", 10);
|
||||
await prisma.user.upsert({ where: { email: "admin@worldcup.com" }, update: {},
|
||||
create: { email: "admin@worldcup.com", name: "ادمین", password: adminPwd, role: "ADMIN" } });
|
||||
|
||||
const userPwd = await bcrypt.hash("user123", 10);
|
||||
const users = [];
|
||||
for (const u of [{ email: "ali@test.com", name: "علی احمدی" }, { email: "sara@test.com", name: "سارا رضایی" }, { email: "reza@test.com", name: "رضا محمدی" }]) {
|
||||
const user = await prisma.user.upsert({ where: { email: u.email }, update: {}, create: { ...u, password: userPwd } });
|
||||
users.push(user);
|
||||
}
|
||||
|
||||
// ─── گروهها ──────────────────────────────────────────
|
||||
const groupMap: Record<string, string> = {};
|
||||
for (const name of ["A","B","C","D","E","F","G","H"]) {
|
||||
const g = await prisma.group.upsert({ where: { name }, update: {}, create: { name } });
|
||||
groupMap[name] = g.id;
|
||||
}
|
||||
|
||||
// ─── تیمهای ملی ─────────────────────────────────────
|
||||
const countryMap: Record<string, string> = {};
|
||||
for (const c of COUNTRIES) {
|
||||
const country = await prisma.country.upsert({ where: { code: c.code }, update: { flagUrl: c.flag, defaultFormation: COUNTRY_FORMATIONS[c.code] ?? "4-3-3" },
|
||||
create: { name: c.name, code: c.code, flagUrl: c.flag, groupId: groupMap[c.group], defaultFormation: COUNTRY_FORMATIONS[c.code] ?? "4-3-3" } });
|
||||
countryMap[c.code] = country.id;
|
||||
}
|
||||
|
||||
// ─── بازیکنان ─────────────────────────────────────────
|
||||
for (const p of PLAYERS_DATA) {
|
||||
const countryId = countryMap[p.code];
|
||||
if (!countryId) continue;
|
||||
await prisma.player.create({ data: { name: p.name, position: p.pos as any, countryId, price: p.price, totalPoints: p.pts } });
|
||||
}
|
||||
|
||||
// ─── قوانین امتیازدهی پیشفرض ────────────────────────
|
||||
const positions = ["GK", "DEF", "MID", "FWD"] as const;
|
||||
for (const pos of positions) {
|
||||
const rules = DEFAULT_RULES[pos];
|
||||
for (const [eventType, points] of Object.entries(rules)) {
|
||||
await prisma.scoringRule.upsert({
|
||||
where: { position_eventType: { position: pos, eventType: eventType as any } },
|
||||
update: { points: points as number },
|
||||
create: { position: pos, eventType: eventType as any, points: points as number },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ─── دورها ────────────────────────────────────────────
|
||||
const round1 = await prisma.round.upsert({ where: { number: 1 }, update: {},
|
||||
create: { number: 1, name: "دور اول - مرحله گروهی", isActive: true, deadline: new Date("2026-06-15T10:00:00Z") } });
|
||||
const round2 = await prisma.round.upsert({ where: { number: 2 }, update: {},
|
||||
create: { number: 2, name: "دور دوم - مرحله گروهی", deadline: new Date("2026-06-22T10:00:00Z") } });
|
||||
const round3 = await prisma.round.upsert({ where: { number: 3 }, update: {},
|
||||
create: { number: 3, name: "دور سوم - مرحله گروهی", deadline: new Date("2026-06-29T10:00:00Z") } });
|
||||
const round4 = await prisma.round.upsert({ where: { number: 4 }, update: {},
|
||||
create: { number: 4, name: "دور چهارم - یکهشتم نهایی", deadline: new Date("2026-07-05T10:00:00Z") } });
|
||||
|
||||
// ─── بازیها ──────────────────────────────────────────
|
||||
const matchesData = [
|
||||
// دور اول - بازی اول هر تیم
|
||||
{ home: "QAT", away: "ECU", hS: 0, aS: 2, st: "FINISHED", date: "2026-06-20T16:00:00Z", rId: round1.id },
|
||||
{ home: "ENG", away: "IRN", hS: 6, aS: 2, st: "FINISHED", date: "2026-06-21T13:00:00Z", rId: round1.id },
|
||||
{ home: "ARG", away: "KSA", hS: 1, aS: 2, st: "FINISHED", date: "2026-06-22T10:00:00Z", rId: round1.id },
|
||||
{ home: "FRA", away: "AUS", hS: 4, aS: 1, st: "FINISHED", date: "2026-06-22T19:00:00Z", rId: round1.id },
|
||||
{ home: "GER", away: "JPN", hS: 1, aS: 2, st: "FINISHED", date: "2026-06-23T13:00:00Z", rId: round1.id },
|
||||
{ home: "ESP", away: "CRC", hS: 7, aS: 0, st: "FINISHED", date: "2026-06-23T19:00:00Z", rId: round1.id },
|
||||
{ home: "BEL", away: "CAN", hS: 1, aS: 0, st: "FINISHED", date: "2026-06-23T16:00:00Z", rId: round1.id },
|
||||
{ home: "BRA", away: "SRB", hS: 2, aS: 0, st: "FINISHED", date: "2026-06-24T19:00:00Z", rId: round1.id },
|
||||
{ home: "POR", away: "GHA", hS: 3, aS: 2, st: "FINISHED", date: "2026-06-24T16:00:00Z", rId: round1.id },
|
||||
{ home: "MAR", away: "CRO", hS: 0, aS: 0, st: "FINISHED", date: "2026-06-23T10:00:00Z", rId: round1.id },
|
||||
{ home: "NED", away: "SEN", hS: 2, aS: 0, st: "FINISHED", date: "2026-06-21T16:00:00Z", rId: round1.id },
|
||||
// دور دوم - بازی دوم هر تیم
|
||||
{ home: "IRN", away: "WAL", hS: 2, aS: 0, st: "FINISHED", date: "2026-06-25T13:00:00Z", rId: round2.id },
|
||||
{ home: "FRA", away: "DEN", hS: 2, aS: 1, st: "FINISHED", date: "2026-06-26T19:00:00Z", rId: round2.id },
|
||||
{ home: "ARG", away: "MEX", hS: 2, aS: 0, st: "FINISHED", date: "2026-06-26T22:00:00Z", rId: round2.id },
|
||||
{ home: "BRA", away: "SUI", hS: 1, aS: 0, st: "FINISHED", date: "2026-06-28T19:00:00Z", rId: round2.id },
|
||||
{ home: "ENG", away: "USA", hS: 0, aS: 0, st: "FINISHED", date: "2026-06-25T19:00:00Z", rId: round2.id },
|
||||
// دور سوم - بازی سوم گروهی
|
||||
{ home: "BRA", away: "CMR", hS: 1, aS: 0, st: "SCHEDULED", date: "2026-07-02T19:00:00Z", rId: round3.id },
|
||||
{ home: "FRA", away: "TUN", hS: null, aS: null, st: "SCHEDULED", date: "2026-07-01T16:00:00Z", rId: round3.id },
|
||||
// دور چهارم - یکهشتم
|
||||
{ home: "NED", away: "ARG", hS: 2, aS: 2, st: "FINISHED", date: "2026-12-09T19:00:00Z", rId: round4.id, stage: "ROUND_OF_16" },
|
||||
{ home: "FRA", away: "ENG", hS: 2, aS: 1, st: "FINISHED", date: "2026-12-10T19:00:00Z", rId: round4.id, stage: "ROUND_OF_16" },
|
||||
{ home: "ARG", away: "FRA", hS: 3, aS: 3, st: "FINISHED", date: "2026-12-18T15:00:00Z", rId: round4.id, stage: "FINAL" },
|
||||
];
|
||||
|
||||
for (const m of matchesData) {
|
||||
const homeId = countryMap[m.home], awayId = countryMap[m.away];
|
||||
if (!homeId || !awayId) continue;
|
||||
await prisma.match.create({ data: {
|
||||
homeTeamId: homeId, awayTeamId: awayId,
|
||||
homeScore: m.hS ?? null, awayScore: m.aS ?? null,
|
||||
status: m.st as any, stage: (m.stage ?? "GROUP") as any,
|
||||
matchDate: new Date(m.date), roundId: m.rId,
|
||||
}});
|
||||
}
|
||||
|
||||
// ─── پکیجها ──────────────────────────────────────────
|
||||
for (const pkg of [
|
||||
{ id: "pkg-silver", name: "پکیج نقرهای", budgetBonus: 10, price: 50000, description: "۱۰ میلیون به بودجه اضافه کن" },
|
||||
{ id: "pkg-gold", name: "پکیج طلایی", budgetBonus: 20, price: 90000, description: "۲۰ میلیون به بودجه اضافه کن" },
|
||||
{ id: "pkg-diamond", name: "پکیج الماس", budgetBonus: 30, price: 120000, description: "۳۰ میلیون به بودجه اضافه کن" },
|
||||
]) {
|
||||
await prisma.package.upsert({ where: { id: pkg.id }, update: {}, create: pkg });
|
||||
}
|
||||
|
||||
console.log("✅ Seed done! admin@worldcup.com / admin123 | ali@test.com / user123");
|
||||
}
|
||||
|
||||
main().catch(console.error).finally(() => prisma.$disconnect());
|
||||
Reference in New Issue
Block a user