🗂️ Esquema de Base de Datos
La base de datos de Rial AI está modelada de manera relacional en PostgreSQL y representa las relaciones entre compañías, marcas, usuarios, prendas, proyectos de generación, imágenes, modelos virtuales, publicaciones y control de créditos.
📊 Estructura General
Todos los modelos en nuestra base de datos siguen un patrón consistente que incluye:
id: Identificador incremental para uso interno del desarrolladorpublicId: UUID (identificador único) que se puede compartir con el usuario y frontend de forma seguracreatedAt: Timestamp de creación del registroupdatedAt: Timestamp de última actualización
¿Por qué dos IDs? El
idinterno es secuencial y optimizado para consultas de base de datos, mientras que elpublicIdes un UUID que no revela información sobre la cantidad de registros y es seguro para exponer públicamente.
🏢 Modelos de Organización
Company (Compañía)
Representa a una empresa que puede tener múltiples marcas. Las empresas pueden operar con o sin sistema de créditos.
model Company {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String @unique
logo String
credits Int @default(0)
brands Brand[]
users User[]
folders ProjectFolder[]
models Model[]
}Campos Clave
name: Nombre único de la compañíalogo: URL del logo corporativocredits: Saldo actual de créditos (default: 0)- Nota: Por ahora no manejamos activamente el sistema de créditos
Relaciones
brands[]: Una compañía puede tener múltiples marcasusers[]: Una compañía puede tener múltiples usuariosfolders[]: Carpetas de proyectos de la compañíamodels[]: Modelos virtuales asociados a la compañía
Brand (Marca)
Cada marca pertenece a una compañía y contiene sus propias prendas, proyectos, usuarios y modelos virtuales. El par (name, companyId) es único.
model Brand {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String
logo String
companyId Int
company Company @relation(fields: [companyId], references: [id])
garments Garment[]
projects Project[]
users User[] // N:M con User
models Model[] // N:M con Model
}
// Índice único: (name, companyId)Campos Clave
name: Nombre de la marca (único por compañía)logo: URL del logo de la marcacompanyId: Referencia a la compañía propietaria
Relaciones
company: Pertenece a una compañíausers[]: Usuarios asignados a la marcagarments[]: Prendas de la marcaprojects[]: Proyectos de generaciónmodels[]: Modelos virtuales personalizados
User (Usuario)
Representa a un miembro de la plataforma con diferentes niveles de acceso, permisos granulares y asociación a marcas mediante relación N:M.
model User {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
nickname String @default("")
email String @unique
phoneNumber String?
notificationsEnabled NotificationTemplateType[]
role UserRole @default(COMPANY_ADMIN)
companyId Int?
sessionId String @unique
transactions CreditTransaction[]
company Company? @relation(fields: [companyId], references: [id])
approvals GeneratedImage[]
apiKey ApiKey?
brands Brand[]
permissions RolePermission[]
allowedModelSexes Gender[]
}
enum UserRole {
ADMIN
COMPANY_ADMIN
BRAND_ADMIN
}
enum RolePermission { // Permisos del usuario
PROJECT_CREATOR // Puede crear proyectos
REVIEWER // Puede revisar imágenes
DOWNLOADER // Puede descargar imágenes
PERMISSION_ADMIN // Puede manejar permisos de otros usuarios
VIEWER // Puede ver el detalle de las imágenes
}Campos Clave
email: Email único del usuario (usado para autenticación)nickname: Nombre para mostrar (Actualmente usado cuando se envían notificaciones)phoneNumber: Teléfono (opcional, usado para el envío de notificaciones)notificationsEnabled: Tipos de notificación que el usuario tiene habilitadosrole: Nivel de acceso del usuarioADMIN: Acceso completo a toda la plataformaCOMPANY_ADMIN: Administrador de una compañía específicaBRAND_ADMIN: Administrador de marcas en específico
permissions: Permisos granularesallowedModelSexes: Géneros de modelo permitidos para este usuariosessionId: Identificador único de sesión (relacionado con autenticación Supabase)companyId: Referencia a compañía (para usuarios de tipo COMPANY_ADMIN y BRAND_ADMIN)
Relaciones
company: Compañía asociada (para usuarios de tipo BRAND_ADMIN o COMPANY_ADMIN)brands[]: Marcas a las que tiene acceso (para usuarios de tipo BRAND_ADMIN)apiKey: API key asociada si existe (opcional)transactions[]: Transacciones de créditos del usuarioapprovals[]: Imágenes generadas que revisó este usuario
ApiKey (Clave de API)
Almacena claves de API para autenticación de integraciones. Cada usuario puede tener como máximo una API key.
model ApiKey {
id Int @id @default(autoincrement())
publicId String @unique
name String
prefix String @unique // Primeros caracteres visibles para identificación
hash String // Hash de la clave (nunca se almacena en claro)
ownerId Int @unique
owner User @relation(fields: [ownerId], references: [id])
isDisabled Boolean @default(false)
lastUsedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Campos Clave
name: Nombre descriptivo de la clave (ej. “Integración Excel”)prefix: Prefijo visible de la clave para que el usuario identifique cuál eshash: Hash de la clave secreta (no se almacena el valor en claro)ownerId: Usuario propietario (relación 1:1)isDisabled: Si está deshabilitada no se puede usar para autenticaciónlastUsedAt: Última vez que se usó la clave (auditoría)
Relaciones
owner: Usuario propietario de la API key
👕 Gestión de Prendas
Garment (Prenda)
Representa las prendas subidas por las marcas para ser utilizadas en los proyectos de generación.
model Garment {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
season String?
type GarmentType
brandId Int?
brand Brand? @relation(fields: [brandId], references: [id])
images GarmentImage[]
projects ProjectImage[] // N:M: prendas usadas en una entrada de proyecto
result GeneratedImage[] // N:M: imágenes generadas que incluyen esta prenda
}
enum GarmentType {
FOOTWEAR // Zapatos, botas, sandalias
UPPER_TRUNK // Camisetas, blusas, chaquetas
LOWER_TRUNK // Pantalones, faldas, shorts
FULL_BODY // Conjuntos completos
FACESWAP // Imágenes para proyectos de tipo faceswap
}Campos Clave
name: Nombre descriptivo de la prendatype: Categoría de la prendaFOOTWEAR: Zapatos, botas, sandalias, etc.UPPER_TRUNK: Camisetas, blusas, chaquetas, etc.LOWER_TRUNK: Pantalones, faldas, shorts, etc.FULL_BODY: Conjuntos completosFACESWAP: Imágenes para proyectos de tipo faceswap
season: Temporada asociada (opcional) - ej: “Verano 2024”, “Otoño/Invierno 2024”brandId: Referencia opcional a la marca propietaria
Relaciones
brand: Marca propietaria de la prenda (opcional)images[]: Imágenes asociadas a la prendaprojects[]: Entradas de proyecto (ProjectImage) donde se utiliza la prenda (N:M)result[]: Imágenes generadas que incluyen esta prenda (N:M)
GarmentImage (Imagen de Prenda)
Almacena las imágenes originales de las prendas subidas por las marcas.
model GarmentImage {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
url String
garmentId Int
garment Garment @relation(fields: [garmentId], references: [id])
}Campos Clave
url: URL de la imagen almacenada en Google Cloud StoragegarmentId: Referencia a la prenda asociada
Relaciones
garment: Prenda a la que pertenece la imagen
🎯 Sistema de Proyectos
ProjectFolder (Carpeta de Proyectos)
Agrupa proyectos bajo un nombre, tipo, temporada y descripción. La compañía organiza su trabajo en carpetas; cada carpeta tiene estados visibles para admin y para cliente.
model ProjectFolder {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String
projectType ProjectType
season String?
description String?
adminStatus AdminStatus @default(CREATING)
clientStatus ClientStatus @default(CREATING)
companyId Int
company Company @relation(fields: [companyId], references: [id])
projects Project[]
notifications Notification[]
}
// Índice único: (companyId, name)
enum ProjectType {
LIFESTYLE
BATCH
LOOKBOOK
FACESWAP
}
enum AdminStatus {
CREATING
IN_PROGRESS
WAITING_APPROVAL
REJECTED
COMPLETED
CANCELLED
}
enum ClientStatus {
CREATING
IN_PROGRESS
PENDING_APPROVAL
IN_REVIEW
PENDING_DOWNLOAD
COMPLETED
CANCELLED
}Campos Clave
name: Nombre de la carpeta (único por compañía)projectType: Tipo de caso/proyectoLIFESTYLE: Generación contextualizada con escenarios personalizadosBATCH: Generación masiva de prendas individualesLOOKBOOK: Generación de conjuntos completosFACESWAP: Reemplazo de rostros
season: Temporada asociada (opcional)description: Descripción de la carpetaadminStatus: Estado visible para administradores (flujo interno)clientStatus: Estado visible para el cliente (flujo de aprobación/descarga)
Relaciones
company: Compañía propietaria de la carpetaprojects[]: Proyectos contenidos en la carpetanotifications[]: Notificaciones asociadas a esta carpeta
Project (Proyecto)
Un proyecto define una generación concreta dentro de una carpeta: opciones en JSON, marca y carpeta. No tiene nombre propio; el nombre, temporada y descripción están en la carpeta.
model Project {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
adminStatus AdminStatus @default(CREATING)
clientStatus ClientStatus @default(CREATING)
statusRank Int @default(99) // Orden para vistas por estado
statusRankAdmin Int @default(99)
brandId Int
options Json
folderId Int
brand Brand @relation(fields: [brandId], references: [id])
folder ProjectFolder @relation(fields: [folderId], references: [id])
images GeneratedImage[]
uploads ProjectImage[]
}
// Índice único: (options, brandId, folderId)Campos Clave
adminStatus/clientStatus: Estados del proyecto (mismos enums que ProjectFolder)statusRank/statusRankAdmin: Orden para mostrar proyectos por estado (cliente y admin)options: Configuración en JSON con parámetros específicos del tipo de proyectobrandId: Marca propietaria del proyectofolderId: Carpeta a la que pertenece el proyecto
Relaciones
brand: Marca propietaria del proyectofolder: Carpeta que agrupa este proyectouploads[]: Imágenes de entrada (ProjectImage)images[]: Imágenes generadas en el proyecto
ProjectImage (Imagen de Proyecto)
Representa una entrada de generación dentro de un proyecto, es decir, un SKU. Tiene estados separados para vista admin y cliente.
model ProjectImage {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
settings Json
projectId Int
project Project @relation(fields: [projectId], references: [id])
images GeneratedImage[]
garments Garment[] // N:M: prendas usadas en esta entrada
SKU String
adminStatus AdminStatus @default(IN_PROGRESS)
clientStatus ClientStatus @default(IN_PROGRESS)
}Campos Clave
settings: Configuración específica en JSON (pose, fondo, modelo, etc.)SKU: Código de identificación del productoadminStatus: Estado para administradores (mismo enum AdminStatus)clientStatus: Estado para el cliente (mismo enum ClientStatus)projectId: Referencia al proyecto
Relaciones
project: Proyecto al que pertenecegarments[]: Prendas utilizadas en esta generación (N:M)images[]: Imágenes generadas para esta entrada
🖼️ Gestión de Imágenes
GeneratedImage (Imagen Generada)
Almacena las imágenes generadas por IA con sistema de versionado, aprobación y relación N:M con prendas.
model GeneratedImage {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
name String
url String
status ImageStatus @default(INCOMPLETE)
reason String?
uploadId Int
projectId Int
project Project @relation(fields: [projectId], references: [id])
upload ProjectImage @relation(fields: [uploadId], references: [id])
previous GeneratedImage? @relation("PreviousImages", fields: [previousId], references: [id])
previousId Int? @unique
next GeneratedImage? @relation("PreviousImages")
isFinal Boolean @default(true)
version Int @default(1)
garments Garment[] // N:M: prendas que aparecen en esta imagen
approvedBy User? @relation(fields: [approvedById], references: [id])
approvedById Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum ImageStatus {
PENDING
INCOMPLETE
PENDING_APPROVAL
APPROVED
REJECTED
}Campos Clave
name: Nombre del archivo o imagenurl: URL de la imagen generada (a bucket en GCP)status: Estado en el flujo de aprobación (incluye INCOMPLETE mientras no esté completo el SKU)reason: Razón de rechazo (si estado es REJECTED)isFinal: Indica si es la versión finalversion: Número de versión (para versionado)previousId: Referencia a imagen anterior (cadena de versiones)approvedById: Usuario que revisó la imagen
Sistema de Versionado
Las imágenes pueden tener múltiples versiones. Cuando se solicita una mejora o corrección:
- Se crea una nueva
GeneratedImage - Se establece
previousIdapuntando a la versión anterior - Solo la imagen final puede tener
isFinal = true. El campoversionayuda a ordenar y mostrar la versión actual.
Relaciones
project: Proyecto al que perteneceupload: SKU al cual se relaciona (ProjectImage)previous/next: Cadena de versionesgarments[]: Prendas que aparecen en esta imagen (N:M)approvedBy: Usuario que aprobó la imagen
👤 Modelos
Model (Modelo)
Representa los modelos del catálogo Rial. Pertenecen a una compañía y se asocian a marcas mediante relación N:M (un modelo puede usarse en varias marcas).
model Model {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String
gender Gender
age Int
image String
companyId Int?
company Company? @relation(fields: [companyId], references: [id])
brands Brand[] // N:M con Brand
}
enum Gender {
MALE
FEMALE
OTHER
}Campos Clave
name: Nombre del modelogender: Género del modeloage: Edad aproximada del modeloimage: URL de la imagen de referencia del modelocompanyId: Referencia a la compañía (opcional; si es null, el modelo puede ser público)
Tipos de Modelos
- Los modelos se asocian a marcas mediante la relación N:M (
brands[]). Una compañía tiene sus modelos y cada modelo puede estar en una o más marcas.
Relaciones
company: Compañía a la que pertenece el modelo (opcional)brands[]: Marcas en las que está disponible este modelo (N:M)
🔔 Notificaciones
Notification (Notificación)
Registra notificaciones enviadas a usuarios (email, WhatsApp, etc.), asociadas a una carpeta de proyectos y generadas a partir de una plantilla.
model Notification {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
title String
description String
link String
folderId Int?
folder ProjectFolder? @relation(fields: [folderId], references: [id])
isRead Boolean @default(false)
templateId Int
template NotificationTemplate @relation(fields: [templateId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Campos Clave
title: Título de la notificacióndescription: Cuerpo o descripción del mensajelink: Enlace asociado de rial-ai.comfolderId: Al caso que se relaciona la notificación (si es que aplica)isRead: Si el usuario ya leyó la notificacióntemplateId: Plantilla con la que se generó el mensaje
Relaciones
folder: Carpeta de proyectos asociada (opcional)template: Plantilla de notificación usada
NotificationTemplate (Plantilla de Notificación)
Define plantillas reutilizables para notificaciones (email, WhatsApp). El publicId identifica el tipo de evento (enum).
model NotificationTemplate {
id Int @id @default(autoincrement())
publicId NotificationTemplateType @unique
title String
body String
variables String[]
twilioTemplateSid String
role UserRole
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
notifications Notification[]
}
enum NotificationTemplateType {
ADMIN_PROJECT_CREATED // Notificación para administrador cuando se crea un proyecto/caso nuevo
ADMIN_NEW_REJECTIONS // Notificación para administrador cuando se rechazan imágenes
COMPANY_PROJECT_CREATED // Notificación para cliente cuando se termina de crear un proyecto nuevo
COMPANY_PROJECT_PENDING_APPROVAL // Notificación para cliente cuando se generan nuevas imágenes
COMPANY_PROJECT_READY_FOR_DOWNLOAD // Notificación para cliente cuando se completa/aprueba un caso/proyecto
}Campos Clave
publicId: Tipo de notificación (enum); identifica el evento que dispara esta plantillatitle/body: Texto de la plantillavariables: Lista de nombres de variables que se reemplazan al enviar (ej. nombre de carpeta, link)twilioTemplateSid: ID de la plantilla en Twilio para mensajes WhatsApprole: Rol del usuario al que va dirigida (ADMIN, COMPANY_ADMIN, BRAND_ADMIN)
Relaciones
notifications[]: Notificaciones generadas con esta plantilla
💳 Sistema de Créditos
Nota: Este sistema está definido en la base de datos pero aún no está implementado en la aplicación.
CreditTransaction (Transacción de Créditos)
Registra todas las compras y usos de créditos en el sistema.
model CreditTransaction {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
amount Int
transactionType TransactionType
userId Int
user User @relation(fields: [userId], references: [id])
}
enum TransactionType {
PURCHASE
USAGE
}Campos Clave
amount: Cantidad de créditostransactionType: Tipo de transacciónPURCHASE: Compra de créditosUSAGE: Uso de créditos para generación
userId: Usuario que realizó la transacción
Relaciones
user: Usuario asociado a la transacción
📰 Gestión de Contenido
Post (Publicación)
Sistema de publicaciones y contenido de prensa para el sitio web y blog.
model Post {
id Int @id @default(autoincrement())
publicId String @unique @default(uuid())
title String
description String
publicationDate DateTime?
image String
file String
tags String[]
type PostType
isPublished Boolean @default(false)
authorName String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum PostType {
PUBLICATION
PRESS
}Campos Clave
title: Título de la publicacióndescription: Contenido o descripción del postpublicationDate: Fecha de publicación programadaimage: URL de imagen destacadafile: URL del archivo asociadotags: Array de etiquetas para categorizacióntype: Tipo de publicaciónPUBLICATION: Artículos del blogPRESS: Notas de prensa
isPublished: Estado de publicaciónauthorName: Nombre del autor
🔗 Diagrama de Relaciones
El diagrama de relaciones se encuentra en el siguiente enlace: Diagrama de Relaciones .
