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

182 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.checksum`**UNIQUE** (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)
```prisma
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