Skip to content

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 iniciais

Modelos 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.

Documentação Técnica - ProCases