Schema Prisma
O schema Prisma define todos os modelos, relacionamentos e tipos do banco de dados.
Localização
prisma/
├── schema.prisma # Schema principal
├── migrations/ # Histórico de migrations
└── seed.ts # Dados iniciaisModelos Principais
User
prisma
model User {
id BigInt @id
// Steam
steamId String @unique
username String
avatarUrl String?
// Contato
email String? @unique
phone String?
// Saldo (cache - Source of Truth são as transações)
balanceCents BigInt @default(0)
// Status
status UserStatus @default(ACTIVE)
isAdmin Boolean @default(false)
adminRole AdminRole?
// 2FA
twoFactorEnabled Boolean @default(false)
twoFactorSecret String?
// Ban
bannedAt DateTime?
bannedReason String?
bannedUntil DateTime?
bannedBy BigInt?
// Relações
transactions Transaction[]
caseOpenings CaseOpening[]
battles BattlePlayer[]
deposits Deposit[]
withdrawals Withdrawal[]
inventory UserInventory[]
sessions Session[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
lastLoginAt DateTime?
@@index([steamId])
@@index([status])
@@index([createdAt])
}
enum UserStatus {
ACTIVE
BANNED
SUSPENDED
}
enum AdminRole {
SUPER_ADMIN
ADMIN
MODERATOR
SUPPORT
FINANCIAL
}Transaction
prisma
model Transaction {
id BigInt @id
// Usuário e contraparte (double-entry)
userId BigInt
relatedUserId BigInt?
// Valor
amountCents BigInt
// Tipo e estado
type TransactionType
status TransactionStatus @default(COMPLETED)
// Motivo e vínculo do par débito/crédito
reason String
relatedTransactionId BigInt? @unique
// Metadados
metadata Json?
// Relações
user User @relation(...)
// Timestamps
createdAt DateTime @default(now())
@@index([userId, type, status])
@@index([reason])
@@index([createdAt])
}
enum TransactionType {
DEBIT
CREDIT
}
enum TransactionStatus {
PENDING
COMPLETED
FAILED
CANCELLED
}Case e CaseItem
prisma
model Case {
id BigInt @id
// Identificação
name String
slug String @unique
description String?
imageUrl String
// Preço
priceCents BigInt
// Configuração
category CaseCategory
isActive Boolean @default(true)
isFeatured Boolean @default(false)
houseEdge Float @default(0.10)
// Relações
items CaseItem[]
openings CaseOpening[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([isActive])
@@index([category])
}
enum CaseCategory {
CHEAP
MEDIUM
EXPENSIVE
PREMIUM
EVENT
}
model CaseItem {
id BigInt @id
caseId BigInt
itemId BigInt
// Probabilidade
dropChance Float
hashRangeStart Int
hashRangeEnd Int
// Relações
case Case @relation(...)
item Item @relation(...)
@@index([caseId])
@@unique([caseId, itemId])
}Item
prisma
model Item {
id BigInt @id
// Identificação
name String
marketHashName String @unique
slug String @unique
description String?
imageUrl String
// Classificação
rarity Rarity
category WeaponCategory
// Valor (valueCents em USD = referência; valueCentsBrl em BRL = source of truth interno)
valueCents BigInt
valueCentsBrl BigInt @default(0)
// Configuração
isActive Boolean @default(true)
isUpgradable Boolean @default(true)
isTradable Boolean @default(true)
// Relações
caseItems CaseItem[]
inventory UserInventory[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([rarity])
@@index([valueCents])
}
enum Rarity {
CONSUMER
INDUSTRIAL
MIL_SPEC
RESTRICTED
CLASSIFIED
COVERT
EXTRAORDINARY
}
enum WeaponCategory {
PISTOL
RIFLE
SMG
SNIPER
SHOTGUN
HEAVY
KNIFE
GLOVE
OTHER
}CaseOpening
prisma
model CaseOpening {
id BigInt @id
// Referências
caseId BigInt
userId BigInt
itemId BigInt
// Provably Fair
serverSeed String
serverSeedHash String
clientSeed String
nonce Int
roll Int
// FLIP
isFlip Boolean @default(false)
flipServerSeed String?
flipClientSeed String?
flipNonce Int?
flipRoll Int?
// Valores
pricePaidCents BigInt
itemValueCents BigInt
profitCents BigInt
// Relações
case Case @relation(...)
user User @relation(...)
item Item @relation(...)
// Timestamps
createdAt DateTime @default(now())
@@index([userId, createdAt])
@@index([caseId])
@@index([createdAt])
}Battle e BattlePlayer
prisma
model Battle {
id BigInt @id
// Configuração
caseId BigInt
creatorId BigInt
mode BattleMode
type BattleType
status BattleStatus
// Valores
entryPriceCents BigInt
totalPotCents BigInt
roundCount Int @default(1)
// Provably Fair
serverSeed String
serverSeedHash String
// Resultado
winnerTeam Int?
// Relações
case Case @relation(...)
creator User @relation(...)
participants BattlePlayer[]
rounds BattleRound[]
settlements BattleSettlement[]
// Timestamps
createdAt DateTime @default(now())
startedAt DateTime?
finishedAt DateTime?
@@index([status])
@@index([creatorId])
@@index([createdAt])
}
enum BattleMode {
NORMAL
FLIP
SHARED
}
enum BattleType {
ONE_VS_ONE
TWO_VS_TWO
THREE_VS_THREE
FOUR_VS_FOUR
ONE_VS_ONE_VS_ONE
ONE_VS_ONE_VS_ONE_VS_ONE
}
enum BattleStatus {
WAITING
READY
COUNTDOWN
RUNNING
FINISHED
CANCELLED
}
model BattlePlayer {
id BigInt @id
battleId BigInt
userId BigInt
// Posição
team Int
slot Int
// Provably Fair
clientSeed String
nonce Int
// Resultado
totalValueCents BigInt @default(0)
isWinner Boolean @default(false)
// Relações
battle Battle @relation(...)
user User @relation(...)
rounds BattleRound[]
@@unique([battleId, userId])
@@index([battleId])
}
model BattleRound {
id BigInt @id
battleId BigInt
participantId BigInt
roundNumber Int
// Resultado
roll Int
itemId BigInt
itemValueCents BigInt
// FLIP
isFlip Boolean @default(false)
flipRoll Int?
// Relações
battle Battle @relation(...)
participant BattlePlayer @relation(...)
item Item @relation(...)
@@unique([battleId, participantId, roundNumber])
}
model BattleSettlement {
id BigInt @id
battleId BigInt
userId BigInt?
itemId BigInt
// Tipo
type BattleSettlementType
valueCents BigInt
roundNumber Int?
// Relações
battle Battle @relation(...)
user User? @relation(...)
item Item @relation(...)
// Timestamps
createdAt DateTime @default(now())
@@index([battleId])
}
enum BattleSettlementType {
DROPPED
REMOVED_TO_POOL
ADDED_FROM_POOL
}Deposit e Withdrawal
prisma
model Deposit {
id BigInt @id
userId BigInt
// Valores
amountCents BigInt
// Pagamento
paymentMethod String
externalId String? @unique
// Status
status DepositStatus
// Relações
user User @relation(...)
// Timestamps
createdAt DateTime @default(now())
confirmedAt DateTime?
@@index([userId])
@@index([status])
@@index([externalId])
}
enum DepositStatus {
PENDING
CONFIRMED
FAILED
EXPIRED
}
model Withdrawal {
id BigInt @id
userId BigInt
// Valores
amountCents BigInt
// Pagamento
paymentMethod String
paymentDetails String // Encrypted
// Status
status WithdrawalStatus
twoFactorCode String?
expiresAt DateTime?
// Admin
approvedBy BigInt?
approvedAt DateTime?
rejectedBy BigInt?
rejectedAt DateTime?
rejectionReason String?
adminNotes String?
// Processamento
externalId String?
// Relações
user User @relation(...)
// Timestamps
createdAt DateTime @default(now())
completedAt DateTime?
@@index([userId])
@@index([status])
}
enum WithdrawalStatus {
PENDING_2FA
PENDING
APPROVED
PROCESSING
COMPLETED
REJECTED
CANCELLED
FAILED
}UserInventory
prisma
model UserInventory {
id BigInt @id
userId BigInt
itemId BigInt
// Status
status InventoryItemStatus @default(AVAILABLE)
// Origem
sourceType String // CASE_OPENING, BATTLE, etc.
sourceId BigInt
// Relações
user User @relation(...)
item Item @relation(...)
// Timestamps
createdAt DateTime @default(now())
@@index([userId, status])
@@index([itemId])
}
enum InventoryItemStatus {
AVAILABLE
LOCKED
SOLD
WITHDRAWN
USED_IN_UPGRADE
USED_IN_BATTLE
IN_SWAP
IN_CRASH
USED_IN_CRASH
IN_MINES
USED_IN_MINES
}Session
prisma
model Session {
id String @id
userId BigInt
// Metadados
ipAddress String
userAgent String
deviceFingerprint String?
// Timestamps
createdAt DateTime @default(now())
expiresAt DateTime
lastActivity DateTime @default(now())
// Relações
user User @relation(...)
@@index([userId])
@@index([expiresAt])
}AuditLog
prisma
model AuditLog {
id BigInt @id
// Ator
userId BigInt?
adminId BigInt?
// Ação
action String
resourceType String
resourceId BigInt?
// Dados
previousValue Json?
newValue Json?
metadata Json?
// Contexto
ipAddress String
userAgent String
// Integridade
hash String
previousHash String?
// Timestamps
createdAt DateTime @default(now())
@@index([userId])
@@index([adminId])
@@index([action])
@@index([resourceType, resourceId])
@@index([createdAt])
}Relacionamentos
Diagrama Completo
Validações
O Prisma Client valida automaticamente:
- Tipos de dados
- Campos obrigatórios
- Unicidade
- Relacionamentos
Validações adicionais são feitas nos DTOs com class-validator.
