From ce64c72f007c7ea9970fb60df2a0ca19258f9977 Mon Sep 17 00:00:00 2001 From: Manus Date: Mon, 12 Jan 2026 13:54:18 -0500 Subject: [PATCH] =?UTF-8?q?Checkpoint:=20Am=C3=A9liorations=20de=20la=20ge?= =?UTF-8?q?stion=20des=20attestations=20de=20formation=20:=20-=20Ajout=20d?= =?UTF-8?q?u=20param=C3=A8tre=20d'envoi=20automatique=20des=20attestations?= =?UTF-8?q?=20dans=20la=20page=20Param=C3=A8tres=20-=20Ajout=20de=20la=20p?= =?UTF-8?q?r=C3=A9visualisation=20du=20mod=C3=A8le=20d'attestation=20avec?= =?UTF-8?q?=20g=C3=A9n=C3=A9ration=20PDF=20-=20Cr=C3=A9ation=20de=20la=20p?= =?UTF-8?q?age=20Historique=20des=20attestations=20dans=20la=20section=20T?= =?UTF-8?q?ra=C3=A7abilit=C3=A9=20-=20Cr=C3=A9ation=20de=20la=20table=20hi?= =?UTF-8?q?storiqueAttestations=20pour=20tracer=20les=20envois=20-=20Ajout?= =?UTF-8?q?=20des=20proc=C3=A9dures=20tRPC=20pour=20l'historique=20et=20la?= =?UTF-8?q?=20pr=C3=A9visualisation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .manus/db/db-query-1768243292659.json | 9 + .manus/db/db-query-1768243299627.json | 9 + client/src/App.tsx | 2 + client/src/components/DashboardLayout.tsx | 1 + client/src/pages/AdminParametres.tsx | 20 +++ client/src/pages/HistoriqueAttestations.tsx | 166 +++++++++++++++++++ client/src/pages/admin/AdminAttestations.tsx | 80 ++++++--- drizzle/schema.ts | 20 +++ server/attestationService.ts | 134 +++++++++++++++ server/attestationsDb.ts | 93 +++++++++++ server/parametresDb.ts | 1 + server/routers.ts | 25 +++ todo.md | 22 +++ 13 files changed, 563 insertions(+), 19 deletions(-) create mode 100644 .manus/db/db-query-1768243292659.json create mode 100644 .manus/db/db-query-1768243299627.json create mode 100644 client/src/pages/HistoriqueAttestations.tsx create mode 100644 server/attestationsDb.ts diff --git a/.manus/db/db-query-1768243292659.json b/.manus/db/db-query-1768243292659.json new file mode 100644 index 0000000..1808947 --- /dev/null +++ b/.manus/db/db-query-1768243292659.json @@ -0,0 +1,9 @@ +{ + "query": "ALTER TABLE parametres ADD COLUMN envoiAutomatiqueAttestations BOOLEAN DEFAULT true NOT NULL;", + "command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute ALTER TABLE parametres ADD COLUMN envoiAutomatiqueAttestations BOOLEAN DEFAULT true NOT NULL;", + "rows": [], + "messages": [], + "stdout": "", + "stderr": "", + "execution_time_ms": 1061 +} \ No newline at end of file diff --git a/.manus/db/db-query-1768243299627.json b/.manus/db/db-query-1768243299627.json new file mode 100644 index 0000000..d6d259e --- /dev/null +++ b/.manus/db/db-query-1768243299627.json @@ -0,0 +1,9 @@ +{ + "query": "CREATE TABLE historiqueAttestations (\n id INT AUTO_INCREMENT PRIMARY KEY,\n sequenceId INT NOT NULL,\n apprenantId INT NOT NULL,\n dateEnvoi TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n statut ENUM('envoye', 'erreur') NOT NULL,\n messageErreur TEXT NULL,\n urlAttestation VARCHAR(500) NULL,\n createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sequenceId) REFERENCES sequences(id) ON DELETE CASCADE,\n FOREIGN KEY (apprenantId) REFERENCES apprenants(id) ON DELETE CASCADE\n);", + "command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute CREATE TABLE historiqueAttestations (\n id INT AUTO_INCREMENT PRIMARY KEY,\n sequenceId INT NOT NULL,\n apprenantId INT NOT NULL,\n dateEnvoi TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n statut ENUM('envoye', 'erreur') NOT NULL,\n messageErreur TEXT NULL,\n urlAttestation VARCHAR(500) NULL,\n createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (sequenceId) REFERENCES sequences(id) ON DELETE CASCADE,\n FOREIGN KEY (apprenantId) REFERENCES apprenants(id) ON DELETE CASCADE\n);", + "rows": [], + "messages": [], + "stdout": "", + "stderr": "", + "execution_time_ms": 261 +} \ No newline at end of file diff --git a/client/src/App.tsx b/client/src/App.tsx index 59688d4..fa1087e 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -30,6 +30,7 @@ import AdminRappelsStats from "./pages/admin/AdminRappelsStats"; import AdminFormateurs from "./pages/admin/AdminFormateurs"; import AdminNotifications from "./pages/admin/AdminNotifications"; import AdminAttestations from "./pages/admin/AdminAttestations"; +import HistoriqueAttestations from "./pages/HistoriqueAttestations"; import AdminParametres from "./pages/AdminParametres"; import QuestionnaireReponse from "./pages/QuestionnaireReponse"; import Inscription from "./pages/Inscription"; @@ -56,6 +57,7 @@ function Router() { + diff --git a/client/src/components/DashboardLayout.tsx b/client/src/components/DashboardLayout.tsx index ec686ec..20513e5 100644 --- a/client/src/components/DashboardLayout.tsx +++ b/client/src/components/DashboardLayout.tsx @@ -77,6 +77,7 @@ const menuSections = [ { icon: Mail, label: "Notifications", path: "/admin/notifications" }, { icon: TrendingUp, label: "Suivi Questionnaires", path: "/admin/questionnaires/suivi" }, { icon: Bell, label: "Rappels", path: "/admin/rappels/historique" }, + { icon: FileText, label: "Historique Attestations", path: "/admin/historique-attestations" }, ] }, { diff --git a/client/src/pages/AdminParametres.tsx b/client/src/pages/AdminParametres.tsx index c3fc98b..771f24b 100644 --- a/client/src/pages/AdminParametres.tsx +++ b/client/src/pages/AdminParametres.tsx @@ -19,6 +19,7 @@ export default function AdminParametres() { const [delaiExpirationQR, setDelaiExpirationQR] = useState(30); const [dureeValiditeToken, setDureeValiditeToken] = useState(24); const [notificationsActives, setNotificationsActives] = useState(true); + const [envoiAutomatiqueAttestations, setEnvoiAutomatiqueAttestations] = useState(true); const [testUrlStatus, setTestUrlStatus] = useState<{ loading: boolean; result?: { accessible: boolean; message: string } }>({ loading: false }); // Initialiser les valeurs quand les données sont chargées @@ -28,6 +29,7 @@ export default function AdminParametres() { setDelaiExpirationQR(parametres.delaiExpirationQR); setDureeValiditeToken(parametres.dureeValiditeToken); setNotificationsActives(parametres.notificationsActives); + setEnvoiAutomatiqueAttestations(parametres.envoiAutomatiqueAttestations); } }, [parametres]); @@ -72,6 +74,7 @@ export default function AdminParametres() { delaiExpirationQR, dureeValiditeToken, notificationsActives, + envoiAutomatiqueAttestations, }); }; @@ -221,6 +224,23 @@ export default function AdminParametres() { /> + {/* Envoi automatique des attestations */} +
+
+ +

+ Envoyer automatiquement les attestations de formation aux apprenants à la fin de chaque séquence +

+
+ +
+
- + +
+ + +
+ + {/* Prévisualisation PDF */} + {previewUrl && ( + + + Prévisualisation du modèle + + Aperçu du PDF d'attestation avec des données fictives + + + +