251 lines
7.7 KiB
TypeScript
251 lines
7.7 KiB
TypeScript
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;
|
|
}
|