← スキル一覧に戻る

prisma-conventions
by feraudet
Consultant management system for service company (SSII/ESN)
⭐ 0🍴 0📅 2026年1月15日
SKILL.md
name: prisma-conventions description: Standards Prisma et base de données. Use when "prisma", "database", "schema", "migration", "query". allowed-tools: Read, Grep, Glob, Bash
Prisma Conventions
Purpose
Standards pour utiliser Prisma dans le projet consultant-manager.
Architecture Base de Données
Modèles Principaux
model Consultant {
id String @id @default(uuid())
nom String
prenom String
email String @unique
telephone String?
competences String // JSON array
tjm Float
statut String @default("DISPONIBLE")
dateCreation DateTime @default(now())
dateModification DateTime @updatedAt
missions Mission[]
}
model Mission {
id String @id @default(uuid())
consultantId String
nomClient String
lieu String?
dateDebut DateTime
dateFin DateTime
tjmApplique Float
description String?
competencesUtilisees String? // JSON array
statutFacturation String @default("EN_ATTENTE")
dateCreation DateTime @default(now())
dateModification DateTime @updatedAt
consultant Consultant @relation(fields: [consultantId], references: [id], onDelete: Cascade)
@@index([consultantId])
@@index([dateDebut, dateFin])
}
Principes de Design
- UUIDs pour les IDs: Plus sûrs que les auto-increment
- Timestamps automatiques:
@default(now())et@updatedAt - Nullable approprié:
?uniquement si vraiment optionnel - Indexes stratégiques: Sur foreign keys et champs de recherche
- Cascade Delete: Missions supprimées si consultant supprimé
Migrations
Créer une Migration
cd backend
npx prisma migrate dev --name description_du_changement
Conventions de nommage:
init- Migration initialeadd_field_name- Ajout d'un champrename_field_x_to_y- Renommageadd_table_name- Nouvelle tablecreate_index_on_field- Nouvel index
Workflow de Migration
# 1. Modifier schema.prisma
# 2. Créer la migration
npx prisma migrate dev --name add_consultant_photo
# 3. Regénérer le client
npx prisma generate
# 4. Vérifier que tout compile
npm run build
Migration en Production
# Appliquer les migrations en prod
npx prisma migrate deploy
# Seed la base si nécessaire
npx prisma db seed
Queries Prisma
CRUD de Base
// CREATE
const consultant = await prisma.consultant.create({
data: {
nom: 'Dupont',
prenom: 'Jean',
email: 'jean@example.com',
competences: JSON.stringify(['React', 'TypeScript']),
tjm: 500,
statut: 'DISPONIBLE'
}
});
// READ avec relations
const consultant = await prisma.consultant.findUnique({
where: { id: consultantId },
include: {
missions: {
orderBy: { dateDebut: 'desc' }
}
}
});
// READ liste avec filtres
const consultants = await prisma.consultant.findMany({
where: {
statut: 'DISPONIBLE',
email: { contains: '@example.com' }
},
orderBy: { nom: 'asc' }
});
// UPDATE
const updated = await prisma.consultant.update({
where: { id: consultantId },
data: { tjm: 550 }
});
// DELETE
await prisma.consultant.delete({
where: { id: consultantId }
});
Queries Complexes
Filtres avancés:
// Consultants avec missions actives
const consultantsEnMission = await prisma.consultant.findMany({
where: {
missions: {
some: {
dateDebut: { lte: new Date() },
dateFin: { gte: new Date() }
}
}
},
include: { missions: true }
});
// Missions se terminant bientôt
const in30Days = new Date();
in30Days.setDate(in30Days.getDate() + 30);
const missionsEndingSoon = await prisma.mission.findMany({
where: {
dateFin: {
gte: new Date(),
lte: in30Days
}
},
include: { consultant: true }
});
Aggregations:
// Compter les consultants par statut
const stats = await prisma.consultant.groupBy({
by: ['statut'],
_count: true
});
// Revenus totaux
const totalRevenue = await prisma.mission.aggregate({
_sum: {
tjmApplique: true
},
where: {
statutFacturation: 'PAYEE'
}
});
Transactions:
// Créer consultant et mission en une transaction
const result = await prisma.$transaction(async (tx) => {
const consultant = await tx.consultant.create({
data: { /* ... */ }
});
const mission = await tx.mission.create({
data: {
consultantId: consultant.id,
/* ... */
}
});
return { consultant, mission };
});
Patterns Spécifiques au Projet
Gestion des JSON Fields
Competences (array):
// Écriture
await prisma.consultant.create({
data: {
competences: JSON.stringify(['React', 'Node.js'])
}
});
// Lecture
const consultant = await prisma.consultant.findUnique({ where: { id } });
const competences: string[] = JSON.parse(consultant.competences);
Calcul du Statut Consultant
interface ConsultantWithMissions {
missions: Mission[];
statut: string;
}
async function getConsultantWithRealStatus(id: string) {
const consultant = await prisma.consultant.findUnique({
where: { id },
include: {
missions: {
where: {
dateDebut: { lte: new Date() },
dateFin: { gte: new Date() }
}
}
}
});
// Si mission active, forcer EN_MISSION
const hasActiveMission = consultant.missions.length > 0;
return {
...consultant,
statut: hasActiveMission ? 'EN_MISSION' : consultant.statut
};
}
Queries Optimisées
❌ N+1 Problem:
// Mauvais: N+1 queries
const consultants = await prisma.consultant.findMany();
for (const consultant of consultants) {
const missions = await prisma.mission.findMany({
where: { consultantId: consultant.id }
});
}
✅ Solution: Include:
// Bon: 1 seule query
const consultants = await prisma.consultant.findMany({
include: { missions: true }
});
Pagination:
const page = 1;
const pageSize = 20;
const consultants = await prisma.consultant.findMany({
skip: (page - 1) * pageSize,
take: pageSize,
orderBy: { nom: 'asc' }
});
const total = await prisma.consultant.count();
Prisma Studio
Ouvrir l'Interface Graphique
cd backend
npx prisma studio
Ouvre un navigateur sur http://localhost:5555 pour:
- Visualiser les données
- Créer/Modifier/Supprimer des enregistrements
- Tester les relations
- Inspecter le schéma
Seed Data
Créer un Seed Script
// backend/prisma/seed.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
// Nettoyer
await prisma.mission.deleteMany();
await prisma.consultant.deleteMany();
// Créer des données de test
const consultant1 = await prisma.consultant.create({
data: {
nom: 'Dupont',
prenom: 'Jean',
email: 'jean.dupont@example.com',
competences: JSON.stringify(['React', 'TypeScript', 'Node.js']),
tjm: 500,
statut: 'DISPONIBLE'
}
});
const consultant2 = await prisma.consultant.create({
data: {
nom: 'Martin',
prenom: 'Marie',
email: 'marie.martin@example.com',
competences: JSON.stringify(['Python', 'Django', 'PostgreSQL']),
tjm: 450,
statut: 'DISPONIBLE'
}
});
// Créer une mission active
await prisma.mission.create({
data: {
consultantId: consultant1.id,
nomClient: 'Acme Corp',
lieu: 'Paris',
dateDebut: new Date('2026-01-01'),
dateFin: new Date('2026-06-30'),
tjmApplique: 500,
description: 'Développement application React',
competencesUtilisees: JSON.stringify(['React', 'TypeScript']),
statutFacturation: 'EN_ATTENTE'
}
});
console.log('✅ Seed completed');
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
Configurer dans package.json:
{
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
Exécuter:
npx prisma db seed
Bonnes Pratiques
Toujours Déconnecter
// À la fin du script ou au shutdown
await prisma.$disconnect();
Gérer les Erreurs
try {
const consultant = await prisma.consultant.create({ data });
} catch (error) {
if (error.code === 'P2002') {
// Unique constraint violation
throw new Error('Email déjà utilisé');
}
throw error;
}
Utiliser les Types Générés
import { Consultant, Mission, Prisma } from '@prisma/client';
// Type avec relations
type ConsultantWithMissions = Prisma.ConsultantGetPayload<{
include: { missions: true }
}>;
Checklist
Avant de commiter des changements Prisma:
- Migration créée avec nom descriptif
-
prisma generateexécuté - Schema valide (pas d'erreurs de compilation)
- Indexes ajoutés sur foreign keys
- Timestamps (
dateCreation,dateModification) présents - Cascade delete configuré si approprié
- Types TypeScript régénérés
- Tests mis à jour si schéma changé
- Seed data mis à jour si nécessaire
Commandes Utiles
# Ouvrir Prisma Studio
npx prisma studio
# Générer le client Prisma
npx prisma generate
# Créer et appliquer une migration
npx prisma migrate dev --name my_migration
# Appliquer migrations en prod
npx prisma migrate deploy
# Réinitialiser la base (dev only!)
npx prisma migrate reset
# Formater le schema
npx prisma format
# Valider le schema
npx prisma validate
# Seed la base
npx prisma db seed
Ressources
スコア
総合スコア
50/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です