Files
quasar/docs/01-conceptos/data-model.md
Benito Rodríguez 0c9c408564
Some checks failed
CI / lint (push) Failing after 1m4s
CI / test-backend (push) Has been skipped
CI / test-frontend (push) Has been skipped
CI / test-e2e (push) Has been skipped
Refactor code structure for improved readability and maintainability
2026-02-22 18:18:46 +01:00

4.8 KiB
Raw Permalink Blame History

Modelo de datos — Entidades y esquema sugerido

Diagrama ER (texto)

Game ↔ RomFile (1N) Game ↔ Artwork (1N) Game ↔ Platform (NN) Game ↔ Tag (NN) Game ↔ Purchase (1N) Game ↔ PriceHistory (1N)


Entidades principales (campos sugeridos)

Game

  • id (cuid) — identificador.
  • title (string) — nombre principal.
  • slug (string) — único, legible.
  • description (text) — opcional.
  • releaseDate (DateTime?) — fecha principal.
  • igdbId, rawgId, thegamesdbId (Int?) — ids externos.
  • extra (String?) — JSON serializado (compatible con SQLite); usar JSON.parse/JSON.stringify al leer/escribir.
  • createdAt, updatedAt.

Platform

  • id, name, slug, generation.

RomFile

  • id, path, filename, checksum (unique), size (int), format, hashes (String? — JSON serializado, ej.: {"crc32":"...","md5":"..."}), status (active/missing), addedAt, lastSeenAt, gameId.

Artwork

  • id, gameId, type (cover/screenshot), sourceUrl, localPath, width, height, fetchedAt.

Purchase

  • id, gameId, priceCents (int), currency, store, date, receiptPath.

PriceHistory

  • id, gameId, priceCents, currency, recordedAt, source.

Tag

  • id, name (unique), color.

User (opcional)

  • id, name, email (unique), passwordHash, role.

Índices y constraints recomendados

  • RomFile.checksumUNIQUE (detectar duplicados).
  • Game: índice por title y slug (slug único).
  • Composite unique sugerido: [primaryPlatformId, title, releaseDate] para evitar duplicados de una misma versión/plataforma.
  • Índices para búsquedas frecuentes (title, platform, tags).

Fragmento schema.prisma (ejemplo)

datasource db {
  provider = "sqlite" // usar SQLite para desarrollo; cambiar a postgresql en producción si se necesita JSON nativo
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model Game {
  id             String    @id @default(cuid())
  title          String
  slug           String    @unique
  description    String?
  releaseDate    DateTime?
  igdbId         Int?      @unique
  rawgId         Int?      @unique
  thegamesdbId   Int?      @unique
  platforms      Platform[]
  romFiles       RomFile[]
  artworks       Artwork[]
  tags           Tag[]
  extra          String?   // JSON serializado (usar JSON.parse/JSON.stringify para leer y escribir)
  createdAt      DateTime  @default(now())
  updatedAt      DateTime  @updatedAt
  @@index([title])
  @@unique([slug])
}

model Platform {
  id    String @id @default(cuid())
  name  String @unique
  slug  String @unique
  games Game[]
}

model RomFile {
  id         String   @id @default(cuid())
  path       String
  filename   String
  checksum   String   @unique
  size       Int
  format     String
  hashes     String?  // JSON serializado (ej.: {"crc32":"...","md5":"..."})
  game       Game?    @relation(fields: [gameId], references: [id])
  gameId     String?
  addedAt    DateTime @default(now())
  lastSeenAt DateTime?
  status     String   @default("active")
  @@index([checksum])
}

model Artwork {
  id        String   @id @default(cuid())
  game      Game     @relation(fields: [gameId], references: [id])
  gameId    String
  type      String
  sourceUrl String
  localPath String?
  width     Int?
  height    Int?
  fetchedAt DateTime @default(now())
}

model Purchase {
  id         String   @id @default(cuid())
  game       Game     @relation(fields: [gameId], references: [id])
  gameId     String
  priceCents Int
  currency   String
  store      String?
  date       DateTime
  receiptPath String?
}

model PriceHistory {
  id         String   @id @default(cuid())
  game       Game     @relation(fields: [gameId], references: [id])
  gameId     String
  priceCents Int
  currency   String
  recordedAt DateTime @default(now())
  source     String?
}

model Tag {
  id    String @id @default(cuid())
  name  String @unique
  games Game[]
}

Nota: para monedas se recomienda almacenar priceCents (int) para compatibilidad; si se usa Postgres se puede optar por Decimal. Nota: SQLite no soporta tipos JSON nativos; en este ejemplo se usan String para JSON serializado. Si migras a Postgres, puedes usar Json/JsonB para campos flexibles.


Migraciones y evolución del esquema

  • Usar Prisma Migrate para versionar cambios.
  • Preferir migraciones no destructivas (añadir columnas NULL y rellenarlas en background).
  • Mantener seeds de desarrollo para pruebas manuales y reproducibles.

Fuentes

  • Prisma schema conventions, patterns para modelado relacional y técnicas de deduplicación de archivos.

Metadatos Autor: Quasar (investigación automatizada) Última actualización: 2026-02-07