feat(schema): enhance Guild model with new relationships and embed configurations; add Economy models for item management and transactions
This commit is contained in:
@@ -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])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user