Skip to Content
Wagoo SaaS 1.0.25 is released 🎉
02 ArchitectureBase de DonnéesBase de Données

Base de Données

Schéma Prisma

Modèles Principaux

model User { id String @id @default(cuid()) email String @unique name String? password String @default("") image String? emailVerified Boolean @default(false) // Relations ownedProjects Project[] @relation("owner") projectMemberships ProjectMember[] tickets Ticket[] reviews Review[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Project { id String @id @default(cuid()) name String description String? slug String @unique customDomain String? @unique // Owner ownerId String owner User @relation("owner", fields: [ownerId], references: [id], onDelete: Cascade) // Relations members ProjectMember[] articles Article[] reviews Review[] festival Festival? tickets Ticket[] // Settings isPublic Boolean @default(true) status ProjectStatus @default(ACTIVE) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([ownerId]) @@index([slug]) } enum ProjectStatus { ACTIVE INACTIVE ARCHIVED } model ProjectMember { id String @id @default(cuid()) projectId String userId String role MemberRole @default(MEMBER) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @@unique([projectId, userId]) @@index([projectId]) @@index([userId]) } enum MemberRole { OWNER MEMBER } model Article { id String @id @default(cuid()) projectId String title String slug String content String @db.Text excerpt String? status ArticleStatus @default(DRAFT) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt publishedAt DateTime? @@unique([projectId, slug]) @@index([projectId]) } enum ArticleStatus { DRAFT PUBLISHED ARCHIVED } model Review { id String @id @default(cuid()) projectId String authorId String rating Int // 1-5 title String content String @db.Text isPublished Boolean @default(false) status ReviewStatus @default(PENDING) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) author User @relation(fields: [authorId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([projectId]) @@index([authorId]) } enum ReviewStatus { PENDING APPROVED REJECTED } model Festival { id String @id @default(cuid()) projectId String @unique name String description String? @db.Text location String? startDate DateTime endDate DateTime isActive Boolean @default(true) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) periods FestivalPeriod[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([projectId]) } model FestivalPeriod { id String @id @default(cuid()) festivalId String name String // "Week 1", "Phase A", etc. description String? startDate DateTime endDate DateTime festival Festival @relation(fields: [festivalId], references: [id], onDelete: Cascade) artists FestivalArtist[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([festivalId]) } model FestivalArtist { id String @id @default(cuid()) periodId String name String description String? imageUrl String? period FestivalPeriod @relation(fields: [periodId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([periodId]) } model Ticket { id String @id @default(cuid()) projectId String? // Optionnel title String description String @db.Text priority TicketPriority @default(MEDIUM) status TicketStatus @default(OPEN) authorId String assignedToId String? author User @relation(fields: [authorId], references: [id], onDelete: Cascade) assignedTo User? @relation("TicketAssignee", fields: [assignedToId], references: [id]) project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull) messages TicketMessage[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt closedAt DateTime? @@index([projectId]) @@index([authorId]) @@index([assignedToId]) } enum TicketStatus { OPEN IN_PROGRESS CLOSED } enum TicketPriority { LOW MEDIUM HIGH URGENT } model TicketMessage { id String @id @default(cuid()) ticketId String content String @db.Text isPublic Boolean @default(true) authorId String ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade) author User @relation("TicketMessages", fields: [authorId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([ticketId]) @@index([authorId]) } model StripeCustomer { id String @id @default(cuid()) userId String @unique stripeCustomerId String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model StripeSubscription { id String @id @default(cuid()) projectId String stripeSubscriptionId String @unique status String currentPeriodStart DateTime currentPeriodEnd DateTime project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([projectId]) }

Relations Principales

User (1) ──── (N) ProjectMember ──── (1) Project │ ├── (1) ──── (N) Article │ ├── (1) ──── (N) Review │ ├── (1) ──── (N) Ticket │ └── (1) ──── (N) TicketMessage Project (1) ──── (N) Article Project (1) ──── (N) Review Project (1) ──── (N) Ticket Project (1) ──── (1) Festival (optionnel) Project (1) ──── (N) StripeSubscription

Énumérations

ProjectStatus

  • ACTIVE : Projet actif
  • INACTIVE : Projet inactif
  • ARCHIVED : Projet archivĂ©

MemberRole

  • OWNER : PropriĂ©taire (permissions complètes)
  • MEMBER : Membre (permissions restreintes)

ArticleStatus

  • DRAFT : Brouillon (non-public)
  • PUBLISHED : PubliĂ©
  • ARCHIVED : ArchivĂ©

ReviewStatus

  • PENDING : En attente de modĂ©ration
  • APPROVED : ApprouvĂ©
  • REJECTED : RejetĂ©

TicketStatus

  • OPEN : Nouveau
  • IN_PROGRESS : En cours de traitement
  • CLOSED : FermĂ©

TicketPriority

  • LOW : Basse prioritĂ©
  • MEDIUM : PrioritĂ© normale
  • HIGH : Haute prioritĂ©
  • URGENT : Très urgent

Migration

Pour appliquer ce schéma :

# Créer les migrations pnpm prisma migrate dev --name init # Mettre à jour Prisma Client pnpm prisma generate # Visualiser les données pnpm prisma studio

Indexation

Les index amélioren la performance des requêtes :

@@index([ownerId]) # Requêtes sur les projets d'un user @@index([projectId]) # Requêtes sur les articles d'un projet @@unique([email]) # Éviter les doublons de mail

Diagramme ER

[User] ──one-to-many── [ProjectMember] ──many-to-one── [Project] │ ├─ one-to-many ── [Article] ├─ one-to-many ── [Review] ├─ one-to-many ── [Ticket] └─ one-to-many ── [TicketMessage] [Project] ├─ one-to-many ── [Article] ├─ one-to-many ── [Review] ├─ one-to-many ── [Ticket] ├─ one-to-one ── [Festival] └─ one-to-many ── [StripeSubscription] [Festival] ──one-to-many── [FestivalPeriod] ──one-to-many── [FestivalArtist]

Voir Système d’authentification pour les tables better-auth.

Last updated on