feat(schema): enhance Guild model with new relationships and embed configurations; add Economy models for item management and transactions

This commit is contained in:
2025-10-05 00:03:52 -05:00
parent 862f0ad993
commit 581b7b1bd2

View File

@@ -13,11 +13,11 @@ datasource db {
url = env("DATABASE_URL")
}
/*
/**
* -----------------------------------------------------------------------------
* Modelo para el Servidor (Guild)
* -----------------------------------------------------------------------------
*/
*/
model Guild {
id String @id
name String
@@ -35,13 +35,20 @@ model Guild {
// ✅ NUEVAS RELACIONES
allianceChannels AllianceChannel[]
pointsHistory PointHistory[]
EconomyItem EconomyItem[]
InventoryEntry InventoryEntry[]
ShopOffer ShopOffer[]
ItemMutation ItemMutation[]
EconomyWallet EconomyWallet[]
ShopPurchase ShopPurchase[]
}
/*
/**
* -----------------------------------------------------------------------------
* Modelo para el Usuario
* -----------------------------------------------------------------------------
* Representa a un usuario de Discord de manera global.
*/
*/
model User {
id String @id
@@ -50,15 +57,18 @@ model User {
createdAlliances Alliance[]
// ✅ NUEVA RELACIÓN
pointsHistory PointHistory[]
InventoryEntry InventoryEntry[]
EconomyWallet EconomyWallet[]
ShopPurchase ShopPurchase[]
}
/*
/**
* -----------------------------------------------------------------------------
* Modelo para las Estadísticas de Alianza (Leaderboard)
* -----------------------------------------------------------------------------
* Almacena los puntos de un usuario EN UN SERVIDOR específico.
* Se gana 1 punto por mensaje en los canales registrados.
*/
*/
model PartnershipStats {
// Puntos acumulados totales.
totalPoints Int @default(0)
@@ -83,13 +93,13 @@ model PartnershipStats {
@@id([userId, guildId])
}
/*
/**
* -----------------------------------------------------------------------------
* Modelo para la Alianza (El mensaje publicado)
* -----------------------------------------------------------------------------
* Guarda la referencia al mensaje de alianza, pero no su contenido.
* El contenido se construye dinámicamente usando EmbedConfig y PartnershipStats.
*/
*/
model Alliance {
id String @id @default(cuid())
channelId String
@@ -103,13 +113,12 @@ model Alliance {
creatorId String
}
/*
/**
* -----------------------------------------------------------------------------
* Modelo para Canales de Alianza
* -----------------------------------------------------------------------------
* Gestiona qué canales están configurados para otorgar puntos y qué bloque enviar
*/
*/
model AllianceChannel {
id String @id @default(cuid())
channelId String @unique // ID del canal de Discord
@@ -133,12 +142,12 @@ model AllianceChannel {
@@unique([guildId, channelId])
}
/*
/**
* -----------------------------------------------------------------------------
* Modelo para Historial de Puntos
* -----------------------------------------------------------------------------
* Registra cada vez que un usuario gana puntos con fecha y hora
*/
*/
model PointHistory {
id String @id @default(cuid())
@@ -158,12 +167,11 @@ model PointHistory {
channelId String
}
/*
/**
* -----------------------------------------------------------------------------
* Modelo para la Configuración del Embed
* -----------------------------------------------------------------------------
*/
*/
model EmbedConfig {
id String @id @default(cuid())
@@ -196,11 +204,11 @@ model EmbedConfig {
@@unique([guildId, name])
}
/*
/**
* -----------------------------------------------------------------------------
* Modelo para la Configuración de Bloques V2
* -----------------------------------------------------------------------------
*/
*/
model BlockV2Config {
id String @id @default(cuid())
@@ -210,7 +218,6 @@ model BlockV2Config {
// Configuración en JSON (embed + componentes, botones, etc.)
config Json
// Relación con el servidor
guild Guild @relation(fields: [guildId], references: [id])
guildId String
@@ -218,3 +225,244 @@ model BlockV2Config {
// 🔒 Asegura que un nombre no se repita dentro del mismo servidor
@@unique([guildId, name])
}
/**
* -----------------------------------------------------------------------------
* Economía: Catálogo de Ítems
* -----------------------------------------------------------------------------
* - Definición global o por servidor (guildId opcional)
* - Uso masivo de JSON para banderas y configuraciones opcionales
* - Campos de fecha para disponibilidad/adquisición/uso
* - maxPerInventory permite limitar cuántos puede tener un usuario
*/
model EconomyItem {
id String @id @default(cuid())
// Clave estable única por servidor (o global si guildId es null)
key String
name String
description String?
category String?
icon String?
// Si es apilable (stackable). Si es false, puedes manejar instancias en state JSON del inventario
stackable Boolean @default(true)
// Límite duro por inventario (p. ej. 1 o 2); null = ilimitado
maxPerInventory Int?
// Ámbito opcional por servidor. Si es null, el ítem es global
guildId String?
guild Guild? @relation(fields: [guildId], references: [id])
// Ventanas de disponibilidad (para adquirir) y de uso (para poder usarse)
availableFrom DateTime?
availableTo DateTime?
usableFrom DateTime?
usableTo DateTime?
// Etiquetas libres (requiere PostgreSQL)
tags String[]
// Propiedades dinámicas: banderas como breakable/craftable, chestRewards, eventCurrency, passiveEffects, shop, etc.
props Json?
// Cualquier metadato adicional (para extensiones futuras)
metadata Json?
// Relaciones
recipes ItemRecipe[]
inventories InventoryEntry[]
shopOffers ShopOffer[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
RecipeIngredient RecipeIngredient[]
@@unique([guildId, key])
@@index([guildId])
}
/**
* -----------------------------------------------------------------------------
* Economía: Inventario por Usuario x Servidor x Ítem
* -----------------------------------------------------------------------------
* - "state" JSON permite almacenar durabilidad, instancias, efectos/mutaciones aplicadas, expiraciones, etc.
* - Clave única por (userId, guildId, itemId) para stacks; id sintético para relaciones hijas
*/
model InventoryEntry {
id String @id @default(cuid())
userId String
guildId String
itemId String
quantity Int @default(0)
// JSON flexible: { instances:[{ durability: 50, effects:[...], expiresAt:null }], notes:"..." }
state Json?
acquiredAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relaciones
user User @relation(fields: [userId], references: [id])
guild Guild @relation(fields: [guildId], references: [id])
item EconomyItem @relation(fields: [itemId], references: [id])
mutations InventoryItemMutation[]
@@unique([userId, guildId, itemId])
@@index([userId, guildId])
}
/**
* -----------------------------------------------------------------------------
* Economía: Recetas de Crafteo
* -----------------------------------------------------------------------------
*/
model ItemRecipe {
id String @id @default(cuid())
// Ítem resultante de la receta y su cantidad
productItemId String
productQuantity Int @default(1)
product EconomyItem @relation(fields: [productItemId], references: [id])
ingredients RecipeIngredient[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Una receta por ítem resultante (si necesitas variantes, añade un campo "variant" en metadata)
@@unique([productItemId])
}
model RecipeIngredient {
id String @id @default(cuid())
recipeId String
itemId String
quantity Int
recipe ItemRecipe @relation(fields: [recipeId], references: [id])
item EconomyItem @relation(fields: [itemId], references: [id])
@@unique([recipeId, itemId])
}
/**
* -----------------------------------------------------------------------------
* Economía: Ofertas de Tienda por Servidor
* -----------------------------------------------------------------------------
* - price en JSON permite monedas nativas y/o ítems como pago mixto
* Ejemplo: { "coins": 500, "items": [{ "itemKey": "iron", "qty": 3 }] }
*/
model ShopOffer {
id String @id @default(cuid())
guildId String
itemId String
enabled Boolean @default(true)
price Json // { coins?: number, items?: [{ itemKey?: string, itemId?: string, qty: number }], extra?: any }
startAt DateTime?
endAt DateTime?
// Límite de compras por usuario (null = sin límite)
perUserLimit Int?
// Stock global de la oferta (null = ilimitado)
stock Int?
metadata Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
guild Guild @relation(fields: [guildId], references: [id])
item EconomyItem @relation(fields: [itemId], references: [id])
ShopPurchase ShopPurchase[]
// Evita duplicados del mismo ítem en ventana exacta (puedes ajustar según tu flujo)
@@unique([guildId, itemId, startAt, endAt])
@@index([guildId])
}
/**
* -----------------------------------------------------------------------------
* Economía: Mutaciones/Efectos adicionales aplicables a ítems
* -----------------------------------------------------------------------------
* - Catálogo de mutaciones opcional (global o por servidor)
* - Pueden vincularse a entradas de inventario
*/
model ItemMutation {
id String @id @default(cuid())
key String
name String
description String?
effects Json // Definición de efectos/bonos: libre
metadata Json?
guildId String?
guild Guild? @relation(fields: [guildId], references: [id])
inventories InventoryItemMutation[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([guildId, key])
}
model InventoryItemMutation {
id String @id @default(cuid())
inventoryId String
mutationId String
appliedAt DateTime @default(now())
data Json?
inventory InventoryEntry @relation(fields: [inventoryId], references: [id])
mutation ItemMutation @relation(fields: [mutationId], references: [id])
@@index([inventoryId])
}
/**
* -----------------------------------------------------------------------------
* Economía: Billetera por Usuario x Servidor (moneda base)
* -----------------------------------------------------------------------------
*/
model EconomyWallet {
id String @id @default(cuid())
userId String
guildId String
coins Int @default(0)
metadata Json?
user User @relation(fields: [userId], references: [id])
guild Guild @relation(fields: [guildId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([userId, guildId])
@@index([guildId])
}
/**
* -----------------------------------------------------------------------------
* Economía: Historial de compras de la tienda
* -----------------------------------------------------------------------------
*/
model ShopPurchase {
id String @id @default(cuid())
offerId String
userId String
guildId String
qty Int @default(1)
offer ShopOffer @relation(fields: [offerId], references: [id])
user User @relation(fields: [userId], references: [id])
guild Guild @relation(fields: [guildId], references: [id])
createdAt DateTime @default(now())
@@index([offerId])
@@index([userId, guildId])
}