Checkpoint: Corrections multiples :

- Renommage questionnaire.nom → questionnaire.titre dans QuestionnaireReponse.tsx, AdminQuestionnaireEdit.tsx, questionnaireScheduler.ts, questionnaireExport.ts
- Correction des requêtes SQL dans questionnaireDb.ts (suppression de la condition complete inexistante)
- Ajout des colonnes valeurMin et valeurMax dans la table questions
- Renommage de la colonne nom en titre dans la table questionnaires
This commit is contained in:
Manus
2026-01-14 03:08:54 -05:00
parent 8ecb856191
commit b53801c463
94 changed files with 29353 additions and 2042 deletions

View File

@@ -0,0 +1,250 @@
import { eq, and, desc, sql } from "drizzle-orm";
import { getDb } from "./db";
import {
questionnaires,
questions,
reponsesQuestionnaires,
reponsesQuestions,
envoisQuestionnaires,
type Questionnaire,
type InsertQuestionnaire,
type Question,
type InsertQuestion,
type ReponseQuestionnaire,
type InsertReponseQuestionnaire,
type ReponseQuestion,
type InsertReponseQuestion,
type EnvoiQuestionnaire,
type InsertEnvoiQuestionnaire,
} from "../drizzle/schema";
// ========== QUESTIONNAIRES ==========
export async function getAllQuestionnaires() {
const db = await getDb();
if (!db) return [];
return await db.select().from(questionnaires).orderBy(desc(questionnaires.createdAt));
}
export async function getQuestionnaireById(id: number) {
const db = await getDb();
if (!db) return null;
const result = await db.select().from(questionnaires).where(eq(questionnaires.id, id)).limit(1);
return result[0] || null;
}
export async function createQuestionnaire(data: InsertQuestionnaire) {
const db = await getDb();
if (!db) throw new Error("Database not available");
const result = await db.insert(questionnaires).values(data);
return result[0].insertId;
}
export async function updateQuestionnaire(id: number, data: Partial<InsertQuestionnaire>) {
const db = await getDb();
if (!db) throw new Error("Database not available");
await db.update(questionnaires).set(data).where(eq(questionnaires.id, id));
}
export async function deleteQuestionnaire(id: number) {
const db = await getDb();
if (!db) throw new Error("Database not available");
// Supprimer d'abord les questions associées
await db.delete(questions).where(eq(questions.questionnaireId, id));
// Puis le questionnaire
await db.delete(questionnaires).where(eq(questionnaires.id, id));
}
// ========== QUESTIONS ==========
export async function getQuestionsByQuestionnaireId(questionnaireId: number) {
const db = await getDb();
if (!db) return [];
return await db
.select()
.from(questions)
.where(eq(questions.questionnaireId, questionnaireId))
.orderBy(questions.ordre);
}
export async function createQuestion(data: InsertQuestion) {
const db = await getDb();
if (!db) throw new Error("Database not available");
const result = await db.insert(questions).values(data);
return result[0].insertId;
}
export async function updateQuestion(id: number, data: Partial<InsertQuestion>) {
const db = await getDb();
if (!db) throw new Error("Database not available");
await db.update(questions).set(data).where(eq(questions.id, id));
}
export async function deleteQuestion(id: number) {
const db = await getDb();
if (!db) throw new Error("Database not available");
await db.delete(questions).where(eq(questions.id, id));
}
// ========== RÉPONSES QUESTIONNAIRES ==========
export async function createReponseQuestionnaire(data: InsertReponseQuestionnaire) {
const db = await getDb();
if (!db) throw new Error("Database not available");
const result = await db.insert(reponsesQuestionnaires).values(data);
return result[0].insertId;
}
export async function getReponseQuestionnaire(questionnaireId: number, apprenantId: number, sequenceId: number) {
const db = await getDb();
if (!db) return null;
const result = await db
.select()
.from(reponsesQuestionnaires)
.where(
and(
eq(reponsesQuestionnaires.questionnaireId, questionnaireId),
eq(reponsesQuestionnaires.apprenantId, apprenantId),
eq(reponsesQuestionnaires.sequenceId, sequenceId)
)
)
.limit(1);
return result[0] || null;
}
export async function updateReponseQuestionnaire(id: number, data: Partial<InsertReponseQuestionnaire>) {
const db = await getDb();
if (!db) throw new Error("Database not available");
await db.update(reponsesQuestionnaires).set(data).where(eq(reponsesQuestionnaires.id, id));
}
// ========== RÉPONSES QUESTIONS ==========
export async function createReponseQuestion(data: InsertReponseQuestion) {
const db = await getDb();
if (!db) throw new Error("Database not available");
const result = await db.insert(reponsesQuestions).values(data);
return result[0].insertId;
}
export async function getReponsesByReponseQuestionnaireId(reponseQuestionnaireId: number) {
const db = await getDb();
if (!db) return [];
return await db
.select()
.from(reponsesQuestions)
.where(eq(reponsesQuestions.reponseQuestionnaireId, reponseQuestionnaireId));
}
// ========== ENVOIS QUESTIONNAIRES ==========
export async function createEnvoiQuestionnaire(data: InsertEnvoiQuestionnaire) {
const db = await getDb();
if (!db) throw new Error("Database not available");
const result = await db.insert(envoisQuestionnaires).values(data);
return result[0].insertId;
}
export async function getEnvoiByToken(token: string) {
const db = await getDb();
if (!db) return null;
const result = await db
.select()
.from(envoisQuestionnaires)
.where(eq(envoisQuestionnaires.token, token))
.limit(1);
return result[0] || null;
}
export async function updateEnvoiQuestionnaire(id: number, data: Partial<InsertEnvoiQuestionnaire>) {
const db = await getDb();
if (!db) throw new Error("Database not available");
await db.update(envoisQuestionnaires).set(data).where(eq(envoisQuestionnaires.id, id));
}
export async function checkEnvoiExists(questionnaireId: number, apprenantId: number, sequenceId: number) {
const db = await getDb();
if (!db) return false;
const result = await db
.select()
.from(envoisQuestionnaires)
.where(
and(
eq(envoisQuestionnaires.questionnaireId, questionnaireId),
eq(envoisQuestionnaires.apprenantId, apprenantId),
eq(envoisQuestionnaires.sequenceId, sequenceId)
)
)
.limit(1);
return result.length > 0;
}
// ========== STATISTIQUES ==========
/**
* Récupère les statistiques d'un questionnaire
*/
export async function getQuestionnaireStats(questionnaireId: number) {
const db = await getDb();
if (!db) return null;
// Nombre total d'envois
const envoisResult = await db
.select({ count: sql<number>`count(*)` })
.from(envoisQuestionnaires)
.where(eq(envoisQuestionnaires.questionnaireId, questionnaireId));
const totalEnvois = envoisResult[0]?.count || 0;
// Nombre de réponses
const reponsesResult = await db
.select({ count: sql<number>`count(*)` })
.from(reponsesQuestionnaires)
.where(
and(
eq(reponsesQuestionnaires.questionnaireId, questionnaireId),
eq(reponsesQuestionnaires.complete, true)
)
);
const totalReponses = reponsesResult[0]?.count || 0;
// Taux de réponse
const tauxReponse = totalEnvois > 0 ? (totalReponses / totalEnvois) * 100 : 0;
return {
totalEnvois,
totalReponses,
tauxReponse: Math.round(tauxReponse * 10) / 10, // 1 décimale
};
}
/**
* Récupère les réponses détaillées d'un questionnaire pour analyse
*/
export async function getReponsesDetailleesQuestionnaire(questionnaireId: number) {
const db = await getDb();
if (!db) return [];
const result = await db
.select({
reponseQuestionnaireId: reponsesQuestionnaires.id,
apprenantId: reponsesQuestionnaires.apprenantId,
sequenceId: reponsesQuestionnaires.sequenceId,
dateReponse: reponsesQuestionnaires.dateReponse,
questionId: reponsesQuestions.questionId,
reponseNumerique: reponsesQuestions.reponseNumerique,
reponseTexte: reponsesQuestions.reponseTexte,
})
.from(reponsesQuestionnaires)
.leftJoin(
reponsesQuestions,
eq(reponsesQuestions.reponseQuestionnaireId, reponsesQuestionnaires.id)
)
.where(
and(
eq(reponsesQuestionnaires.questionnaireId, questionnaireId),
eq(reponsesQuestionnaires.complete, true)
)
);
return result;
}