feat: initialize Prisma schema with core business, user, and communication models and configure docker-compose for database deployment
All checks were successful
Build and Push App / build (push) Successful in 8m16s
All checks were successful
Build and Push App / build (push) Successful in 8m16s
This commit is contained in:
@@ -9,119 +9,119 @@ datasource db {
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
email String @unique
|
||||
password String
|
||||
role UserRole @default(VISITOR)
|
||||
avatar String?
|
||||
emailVerified Boolean @default(false)
|
||||
verificationToken String? @unique
|
||||
resetToken String? @unique
|
||||
resetTokenExpiry DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
bio String?
|
||||
location String?
|
||||
countryId String?
|
||||
phone String?
|
||||
isSuspended Boolean @default(false)
|
||||
suspensionReason String?
|
||||
businesses Business?
|
||||
comments Comment[]
|
||||
conversations ConversationParticipant[]
|
||||
sentMessages Message[]
|
||||
reports MessageReport[]
|
||||
ratings Rating[]
|
||||
country Country? @relation(fields: [countryId], references: [id])
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
email String @unique
|
||||
password String
|
||||
role UserRole @default(VISITOR)
|
||||
avatar String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
bio String?
|
||||
location String?
|
||||
phone String?
|
||||
isSuspended Boolean @default(false)
|
||||
suspensionReason String?
|
||||
countryId String?
|
||||
resetToken String? @unique
|
||||
resetTokenExpiry DateTime?
|
||||
emailVerified Boolean @default(false)
|
||||
verificationToken String? @unique
|
||||
businesses Business?
|
||||
comments Comment[]
|
||||
conversations ConversationParticipant[]
|
||||
sentMessages Message[]
|
||||
reports MessageReport[]
|
||||
ratings Rating[]
|
||||
country Country? @relation(fields: [countryId], references: [id])
|
||||
}
|
||||
|
||||
model Business {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
category String
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
category String
|
||||
location String
|
||||
description String
|
||||
logoUrl String
|
||||
videoUrl String?
|
||||
contactEmail String
|
||||
contactPhone String?
|
||||
socialLinks Json?
|
||||
verified Boolean @default(false)
|
||||
viewCount Int @default(0)
|
||||
rating Float @default(0.0)
|
||||
ratingCount Int @default(0)
|
||||
tags String[]
|
||||
isFeatured Boolean @default(false)
|
||||
founderName String?
|
||||
founderImageUrl String?
|
||||
keyMetric String?
|
||||
ownerId String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
slug String? @unique
|
||||
isActive Boolean @default(false)
|
||||
showEmail Boolean @default(true)
|
||||
showPhone Boolean @default(true)
|
||||
showSocials Boolean @default(true)
|
||||
websiteUrl String?
|
||||
isSuspended Boolean @default(false)
|
||||
suspensionReason String?
|
||||
plan Plan @default(STARTER)
|
||||
city String?
|
||||
countryId String?
|
||||
coverUrl String?
|
||||
coverPosition String? @default("50% 50%")
|
||||
coverZoom Float? @default(1.0)
|
||||
suggestedCategory String?
|
||||
location String
|
||||
countryId String?
|
||||
city String?
|
||||
description String
|
||||
logoUrl String
|
||||
coverUrl String?
|
||||
coverPosition String? @default("50% 50%")
|
||||
coverZoom Float? @default(1.0)
|
||||
videoUrl String?
|
||||
contactEmail String
|
||||
contactPhone String?
|
||||
socialLinks Json?
|
||||
verified Boolean @default(false)
|
||||
viewCount Int @default(0)
|
||||
rating Float @default(0.0)
|
||||
ratingCount Int @default(0)
|
||||
tags String[]
|
||||
isFeatured Boolean @default(false)
|
||||
founderName String?
|
||||
founderImageUrl String?
|
||||
keyMetric String?
|
||||
ownerId String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
slug String? @unique
|
||||
isActive Boolean @default(false)
|
||||
showEmail Boolean @default(true)
|
||||
showPhone Boolean @default(true)
|
||||
showSocials Boolean @default(true)
|
||||
websiteUrl String?
|
||||
isSuspended Boolean @default(false)
|
||||
suspensionReason String?
|
||||
plan Plan @default(STARTER)
|
||||
owner User @relation(fields: [ownerId], references: [id])
|
||||
comments Comment[]
|
||||
conversations Conversation[]
|
||||
offers Offer[]
|
||||
ratings Rating[]
|
||||
country Country? @relation(fields: [countryId], references: [id])
|
||||
categoryRef BusinessCategory? @relation(fields: [categoryId], references: [id])
|
||||
categoryId String?
|
||||
categoryId String?
|
||||
categoryRef BusinessCategory? @relation(fields: [categoryId], references: [id])
|
||||
country Country? @relation(fields: [countryId], references: [id])
|
||||
owner User @relation(fields: [ownerId], references: [id])
|
||||
comments Comment[]
|
||||
conversations Conversation[]
|
||||
offers Offer[]
|
||||
ratings Rating[]
|
||||
}
|
||||
|
||||
model BusinessCategory {
|
||||
id String @id @default(uuid())
|
||||
name String @unique
|
||||
slug String @unique
|
||||
icon String? // Lucide icon name
|
||||
icon String?
|
||||
isActive Boolean @default(true)
|
||||
businesses Business[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
businesses Business[]
|
||||
}
|
||||
|
||||
model Country {
|
||||
id String @id @default(uuid())
|
||||
name String @unique
|
||||
code String @unique // ISO alpha-2
|
||||
flag String? // Emoji or URL
|
||||
code String @unique
|
||||
flag String?
|
||||
isActive Boolean @default(true)
|
||||
description String? @db.Text
|
||||
businesses Business[]
|
||||
users User[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
description String?
|
||||
businesses Business[]
|
||||
users User[]
|
||||
}
|
||||
|
||||
model PricingPlan {
|
||||
id String @id @default(uuid())
|
||||
tier Plan @unique
|
||||
name String
|
||||
priceXOF String
|
||||
yearlyPriceXOF String?
|
||||
priceEUR String
|
||||
id String @id @default(uuid())
|
||||
tier Plan @unique
|
||||
name String
|
||||
priceXOF String
|
||||
priceEUR String
|
||||
description String
|
||||
features String[]
|
||||
offerLimit Int @default(1)
|
||||
recommended Boolean @default(false)
|
||||
color String @default("gray")
|
||||
updatedAt DateTime @updatedAt
|
||||
yearlyPriceEUR String?
|
||||
description String
|
||||
features String[]
|
||||
offerLimit Int @default(1)
|
||||
recommended Boolean @default(false)
|
||||
color String @default("gray")
|
||||
updatedAt DateTime @updatedAt
|
||||
yearlyPriceXOF String?
|
||||
}
|
||||
|
||||
model Offer {
|
||||
@@ -142,23 +142,22 @@ model Offer {
|
||||
model BlogPost {
|
||||
id String @id @default(uuid())
|
||||
title String
|
||||
slug String? @unique
|
||||
excerpt String
|
||||
content String
|
||||
author String
|
||||
date DateTime @default(now())
|
||||
imageUrl String
|
||||
tags String[] @default([])
|
||||
metaTitle String?
|
||||
metaDescription String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
metaDescription String?
|
||||
metaTitle String?
|
||||
slug String? @unique
|
||||
tags String[] @default([])
|
||||
}
|
||||
|
||||
model Interview {
|
||||
id String @id @default(uuid())
|
||||
title String
|
||||
slug String? @unique
|
||||
guestName String
|
||||
companyName String
|
||||
role String
|
||||
@@ -169,11 +168,12 @@ model Interview {
|
||||
excerpt String
|
||||
date DateTime @default(now())
|
||||
duration String?
|
||||
tags String[] @default([])
|
||||
metaTitle String?
|
||||
metaDescription String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
metaDescription String?
|
||||
metaTitle String?
|
||||
slug String? @unique
|
||||
tags String[] @default([])
|
||||
}
|
||||
|
||||
model Comment {
|
||||
@@ -194,40 +194,34 @@ model AnalyticsEvent {
|
||||
label String?
|
||||
value Float?
|
||||
metadata Json?
|
||||
ip String?
|
||||
country String?
|
||||
city String?
|
||||
createdAt DateTime @default(now())
|
||||
browser String?
|
||||
os String?
|
||||
city String?
|
||||
country String?
|
||||
device String?
|
||||
ip String?
|
||||
os String?
|
||||
referrer String?
|
||||
userId String?
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model Rating {
|
||||
id String @id @default(uuid())
|
||||
id String @id @default(uuid())
|
||||
value Int
|
||||
userId String
|
||||
businessId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
comment String?
|
||||
reply String?
|
||||
replyAt DateTime?
|
||||
status RatingStatus @default(PENDING)
|
||||
userId String
|
||||
businessId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade)
|
||||
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade)
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, businessId])
|
||||
}
|
||||
|
||||
enum RatingStatus {
|
||||
PENDING
|
||||
APPROVED
|
||||
REJECTED
|
||||
}
|
||||
|
||||
model Conversation {
|
||||
id String @id @default(uuid())
|
||||
businessId String
|
||||
@@ -272,6 +266,63 @@ model MessageReport {
|
||||
reporter User @relation(fields: [reporterId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model SiteSetting {
|
||||
id String @id @default("singleton")
|
||||
siteName String @default("Afrohub")
|
||||
siteSlogan String @default("La plateforme de référence pour l'entrepreneuriat africain.")
|
||||
contactEmail String @default("support@afrohub.com")
|
||||
contactPhone String? @default("+225 00 00 00 00 00")
|
||||
address String? @default("Abidjan, Côte d'Ivoire")
|
||||
facebookUrl String?
|
||||
twitterUrl String?
|
||||
instagramUrl String?
|
||||
linkedinUrl String?
|
||||
footerText String? @default("© 2025 Afrohub. Tous droits réservés.")
|
||||
updatedAt DateTime @updatedAt
|
||||
homeBlogCount Int @default(3)
|
||||
homeBlogShow Boolean @default(true)
|
||||
homeBlogSubtitle String @default("Toutes les actualités de l'entrepreneuriat africain.")
|
||||
homeBlogTitle String @default("Derniers Articles")
|
||||
homeBlogCategories String[] @default([])
|
||||
homeBlogIds String[] @default([])
|
||||
homeBlogSelection String @default("latest")
|
||||
homeCategories String[] @default(["Technologie & IT", "Agriculture & Agrobusiness", "Mode & Textile", "Cosmétique & Beauté"])
|
||||
resetPasswordSubject String @default("Réinitialisation de votre mot de passe - Afrohub")
|
||||
resetPasswordTemplate String @default("<div style=\"font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e5e7eb; border-radius: 8px;\"><h2 style=\"color: #0d9488; text-align: center;\">{siteName}</h2><p>Bonjour {name},</p><p>Vous avez demandé la réinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour choisir un nouveau mot de passe :</p><div style=\"text-align: center; margin: 30px 0;\"><a href=\"{resetUrl}\" style=\"background-color: #0d9488; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;\">Réinitialiser mon mot de passe</a></div><p>Ce lien expirera dans 1 heure. Si vous n'avez pas demandé cette réinitialisation, vous pouvez ignorer cet email.</p><hr style=\"border: 0; border-top: 1px solid #e5e7eb; margin: 20px 0;\"><p style=\"font-size: 12px; color: #6b7280; text-align: center;\">© 2025 {siteName}. Tous droits réservés.</p></div>")
|
||||
verifyEmailSubject String @default("Vérification de votre compte - Afrohub")
|
||||
verifyEmailTemplate String @default("<div style=\"font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e5e7eb; border-radius: 8px;\"><h2 style=\"color: #0d9488; text-align: center;\">{siteName}</h2><p>Bonjour {name},</p><p>Merci de vous être inscrit sur {siteName}. Pour finaliser la création de votre compte, merci de vérifier votre adresse email en cliquant sur le bouton ci-dessous :</p><div style=\"text-align: center; margin: 30px 0;\"><a href=\"{verifyUrl}\" style=\"background-color: #0d9488; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;\">Vérifier mon compte</a></div><p>Si vous n'avez pas créé de compte sur notre plateforme, vous pouvez ignorer cet email.</p><hr style=\"border: 0; border-top: 1px solid #e5e7eb; margin: 20px 0;\"><p style=\"font-size: 12px; color: #6b7280; text-align: center;\">© 2025 {siteName}. Tous droits réservés.</p></div>")
|
||||
}
|
||||
|
||||
model LegalDocument {
|
||||
id String @id @default(uuid())
|
||||
type String @unique
|
||||
title String
|
||||
content String
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Event {
|
||||
id String @id @default(uuid())
|
||||
title String
|
||||
description String
|
||||
date DateTime
|
||||
location String
|
||||
thumbnailUrl String
|
||||
link String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
metaDescription String?
|
||||
metaTitle String?
|
||||
slug String? @unique
|
||||
tags String[] @default([])
|
||||
}
|
||||
|
||||
enum RatingStatus {
|
||||
PENDING
|
||||
APPROVED
|
||||
REJECTED
|
||||
}
|
||||
|
||||
enum ReportStatus {
|
||||
PENDING
|
||||
RESOLVED
|
||||
@@ -299,54 +350,3 @@ enum InterviewType {
|
||||
VIDEO
|
||||
ARTICLE
|
||||
}
|
||||
|
||||
model SiteSetting {
|
||||
id String @id @default("singleton")
|
||||
siteName String @default("Afrohub")
|
||||
siteSlogan String @default("La plateforme de référence pour l'entrepreneuriat africain.")
|
||||
contactEmail String @default("support@afrohub.com")
|
||||
contactPhone String? @default("+225 00 00 00 00 00")
|
||||
address String? @default("Abidjan, Côte d'Ivoire")
|
||||
facebookUrl String?
|
||||
twitterUrl String?
|
||||
instagramUrl String?
|
||||
linkedinUrl String?
|
||||
footerText String? @default("© 2025 Afrohub. Tous droits réservés.")
|
||||
homeBlogShow Boolean @default(true)
|
||||
homeBlogTitle String @default("Derniers Articles")
|
||||
homeBlogSubtitle String @default("Toutes les actualités de l'entrepreneuriat africain.")
|
||||
homeBlogCount Int @default(3)
|
||||
homeBlogSelection String @default("latest")
|
||||
homeBlogIds String[] @default([])
|
||||
homeBlogCategories String[] @default([])
|
||||
homeCategories String[] @default(["Technologie & IT", "Agriculture & Agrobusiness", "Mode & Textile", "Cosmétique & Beauté"])
|
||||
resetPasswordSubject String @default("Réinitialisation de votre mot de passe - Afrohub")
|
||||
resetPasswordTemplate String @default("<div style=\"font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e5e7eb; border-radius: 8px;\"><h2 style=\"color: #0d9488; text-align: center;\">{siteName}</h2><p>Bonjour {name},</p><p>Vous avez demandé la réinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour choisir un nouveau mot de passe :</p><div style=\"text-align: center; margin: 30px 0;\"><a href=\"{resetUrl}\" style=\"background-color: #0d9488; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;\">Réinitialiser mon mot de passe</a></div><p>Ce lien expirera dans 1 heure. Si vous n'avez pas demandé cette réinitialisation, vous pouvez ignorer cet email.</p><hr style=\"border: 0; border-top: 1px solid #e5e7eb; margin: 20px 0;\"><p style=\"font-size: 12px; color: #6b7280; text-align: center;\">© 2025 {siteName}. Tous droits réservés.</p></div>") @db.Text
|
||||
verifyEmailSubject String @default("Vérification de votre compte - Afrohub")
|
||||
verifyEmailTemplate String @default("<div style=\"font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e5e7eb; border-radius: 8px;\"><h2 style=\"color: #0d9488; text-align: center;\">{siteName}</h2><p>Bonjour {name},</p><p>Merci de vous être inscrit sur {siteName}. Pour finaliser la création de votre compte, merci de vérifier votre adresse email en cliquant sur le bouton ci-dessous :</p><div style=\"text-align: center; margin: 30px 0;\"><a href=\"{verifyUrl}\" style=\"background-color: #0d9488; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;\">Vérifier mon compte</a></div><p>Si vous n'avez pas créé de compte sur notre plateforme, vous pouvez ignorer cet email.</p><hr style=\"border: 0; border-top: 1px solid #e5e7eb; margin: 20px 0;\"><p style=\"font-size: 12px; color: #6b7280; text-align: center;\">© 2025 {siteName}. Tous droits réservés.</p></div>") @db.Text
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model LegalDocument {
|
||||
id String @id @default(uuid())
|
||||
type String @unique // 'CGU' or 'CGV'
|
||||
title String
|
||||
content String @db.Text
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Event {
|
||||
id String @id @default(uuid())
|
||||
title String
|
||||
slug String? @unique
|
||||
description String @db.Text
|
||||
date DateTime
|
||||
location String
|
||||
thumbnailUrl String
|
||||
link String?
|
||||
tags String[] @default([])
|
||||
metaTitle String?
|
||||
metaDescription String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user