diff --git a/.manus/db/db-query-1768464612603.json b/.manus/db/db-query-1768464612603.json
new file mode 100644
index 0000000..694ac4b
--- /dev/null
+++ b/.manus/db/db-query-1768464612603.json
@@ -0,0 +1,9 @@
+{
+ "query": "DELETE FROM emailTemplates WHERE type NOT IN ('inscription', 'teaser', 'rappel', 'rappelJ1', 'rappel3', 'rappel4', 'rappel5', 'rappel6');",
+ "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 DELETE FROM emailTemplates WHERE type NOT IN ('inscription', 'teaser', 'rappel', 'rappelJ1', 'rappel3', 'rappel4', 'rappel5', 'rappel6');",
+ "rows": [],
+ "messages": [],
+ "stdout": "",
+ "stderr": "",
+ "execution_time_ms": 108
+}
\ No newline at end of file
diff --git a/.manus/db/db-query-1768464704023.json b/.manus/db/db-query-1768464704023.json
new file mode 100644
index 0000000..aae9e4d
--- /dev/null
+++ b/.manus/db/db-query-1768464704023.json
@@ -0,0 +1,9 @@
+{
+ "query": "ALTER TABLE emailTemplates MODIFY COLUMN type ENUM('inscription', 'teaser', 'rappel', 'rappelJ1', 'rappel3', 'rappel4', 'rappel5', 'rappel6', 'reset_password') 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 emailTemplates MODIFY COLUMN type ENUM('inscription', 'teaser', 'rappel', 'rappelJ1', 'rappel3', 'rappel4', 'rappel5', 'rappel6', 'reset_password') NOT NULL;",
+ "rows": [],
+ "messages": [],
+ "stdout": "",
+ "stderr": "",
+ "execution_time_ms": 191
+}
\ No newline at end of file
diff --git a/.manus/db/db-query-1768464712457.json b/.manus/db/db-query-1768464712457.json
new file mode 100644
index 0000000..90a4c62
--- /dev/null
+++ b/.manus/db/db-query-1768464712457.json
@@ -0,0 +1,9 @@
+{
+ "query": "INSERT INTO emailTemplates (type, titre, bodyContent, couleurPrincipale, couleurSecondaire, piedDePage) VALUES\n('reset_password', 'Réinitialisation de votre mot de passe', '
Bonjour {{prenomApprenant}} {{nomApprenant}},
Vous avez demandé la réinitialisation de votre mot de passe.
Cliquez sur le lien ci-dessous pour définir un nouveau mot de passe :
Réinitialiser mon mot de passe
Ce lien est valable pendant 24 heures.
Si vous n\\'avez pas demandé cette réinitialisation, ignorez cet email.
', '#283581', '#0578BE', '© 2024 Itinova - Tous droits réservés');",
+ "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 INSERT INTO emailTemplates (type, titre, bodyContent, couleurPrincipale, couleurSecondaire, piedDePage) VALUES\n('reset_password', 'Réinitialisation de votre mot de passe', 'Bonjour {{prenomApprenant}} {{nomApprenant}},
Vous avez demandé la réinitialisation de votre mot de passe.
Cliquez sur le lien ci-dessous pour définir un nouveau mot de passe :
Réinitialiser mon mot de passe
Ce lien est valable pendant 24 heures.
Si vous n\\'avez pas demandé cette réinitialisation, ignorez cet email.
', '#283581', '#0578BE', '© 2024 Itinova - Tous droits réservés');",
+ "rows": [],
+ "messages": [],
+ "stdout": "",
+ "stderr": "",
+ "execution_time_ms": 69
+}
\ No newline at end of file
diff --git a/.manus/db/db-query-1768464822745.json b/.manus/db/db-query-1768464822745.json
new file mode 100644
index 0000000..bad128e
--- /dev/null
+++ b/.manus/db/db-query-1768464822745.json
@@ -0,0 +1,9 @@
+{
+ "query": "ALTER TABLE `emailTemplates` MODIFY COLUMN `type` enum('inscription','teaser','rappel','rappelJ1','rappel3','rappel4','rappel5','rappel6','reset_password') 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 `emailTemplates` MODIFY COLUMN `type` enum('inscription','teaser','rappel','rappelJ1','rappel3','rappel4','rappel5','rappel6','reset_password') NOT NULL;",
+ "rows": [],
+ "messages": [],
+ "stdout": "",
+ "stderr": "",
+ "execution_time_ms": 180
+}
\ No newline at end of file
diff --git a/.manus/db/db-query-1768464838613.json b/.manus/db/db-query-1768464838613.json
new file mode 100644
index 0000000..b02368e
--- /dev/null
+++ b/.manus/db/db-query-1768464838613.json
@@ -0,0 +1,25 @@
+{
+ "query": "SELECT * FROM emailTemplates WHERE type = 'reset_password';",
+ "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 SELECT * FROM emailTemplates WHERE type = 'reset_password';",
+ "rows": [
+ {
+ "id": "90001",
+ "type": "reset_password",
+ "titre": "Réinitialisation de votre mot de passe",
+ "logoUrl": "NULL",
+ "headerTextColor": "#ffffff",
+ "headerTitle": "Formation Manager Itinova",
+ "bodyContent": "Bonjour {{prenomApprenant}} {{nomApprenant}},
Vous avez demandé la réinitialisation de votre mot de passe.
Cliquez sur le lien ci-dessous pour définir un nouveau mot de passe :
Réinitialiser mon mot de passe
Ce lien est valable pendant 24 heures.
Si vous n'avez pas demandé cette réinitialisation, ignorez cet email.
",
+ "active": "1",
+ "createdAt": "2026-01-15 08:11:52",
+ "updatedAt": "2026-01-15 08:11:52",
+ "couleurPrincipale": "#283581",
+ "couleurSecondaire": "#0578BE",
+ "piedDePage": "© 2024 Itinova - Tous droits réservés"
+ }
+ ],
+ "messages": [],
+ "stdout": "id\ttype\ttitre\tlogoUrl\theaderTextColor\theaderTitle\tbodyContent\tactive\tcreatedAt\tupdatedAt\tcouleurPrincipale\tcouleurSecondaire\tpiedDePage\n90001\treset_password\tRéinitialisation de votre mot de passe\tNULL\t#ffffff\tFormation Manager Itinova\tBonjour {{prenomApprenant}} {{nomApprenant}},
Vous avez demandé la réinitialisation de votre mot de passe.
Cliquez sur le lien ci-dessous pour définir un nouveau mot de passe :
Réinitialiser mon mot de passe
Ce lien est valable pendant 24 heures.
Si vous n'avez pas demandé cette réinitialisation, ignorez cet email.
\t1\t2026-01-15 08:11:52\t2026-01-15 08:11:52\t#283581\t#0578BE\t© 2024 Itinova - Tous droits réservés\n",
+ "stderr": "",
+ "execution_time_ms": 53
+}
\ No newline at end of file
diff --git a/.manus/db/db-query-error-1768464834426.json b/.manus/db/db-query-error-1768464834426.json
new file mode 100644
index 0000000..42d8c1b
--- /dev/null
+++ b/.manus/db/db-query-error-1768464834426.json
@@ -0,0 +1,8 @@
+{
+ "query": "INSERT INTO emailTemplates (type, titre, bodyContent, couleurPrincipale, couleurSecondaire, piedDePage)\nVALUES (\n 'reset_password',\n 'Réinitialisation de votre mot de passe',\n 'Bonjour {{prenom}} {{nom}},
\\n\\nVous avez demandé la réinitialisation de votre mot de passe pour votre compte sur la plateforme de gestion des formations Itinova.
\\n\\nPour réinitialiser votre mot de passe, veuillez cliquer sur le lien ci-dessous :
\\n\\nRéinitialiser mon mot de passe
\\n\\nCe lien est valable pendant 24 heures.
\\n\\nSi vous n\\'avez pas demandé cette réinitialisation, vous pouvez ignorer cet email en toute sécurité.
\\n\\nCordialement, L\\'équipe Itinova
',\n '#283581',\n '#0578BE',\n 'Itinova - Gestion des Formations | contact@itinova.fr '\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 INSERT INTO emailTemplates (type, titre, bodyContent, couleurPrincipale, couleurSecondaire, piedDePage)\nVALUES (\n 'reset_password',\n 'Réinitialisation de votre mot de passe',\n 'Bonjour {{prenom}} {{nom}},
\\n\\nVous avez demandé la réinitialisation de votre mot de passe pour votre compte sur la plateforme de gestion des formations Itinova.
\\n\\nPour réinitialiser votre mot de passe, veuillez cliquer sur le lien ci-dessous :
\\n\\nRéinitialiser mon mot de passe
\\n\\nCe lien est valable pendant 24 heures.
\\n\\nSi vous n\\'avez pas demandé cette réinitialisation, vous pouvez ignorer cet email en toute sécurité.
\\n\\nCordialement, L\\'équipe Itinova
',\n '#283581',\n '#0578BE',\n 'Itinova - Gestion des Formations | contact@itinova.fr '\n);",
+ "returncode": 1,
+ "logs": [
+ "ERROR 1062 (23000) at line 1: Duplicate entry '?' for key 'emailTemplates.emailTemplates_type_unique'"
+ ]
+}
\ No newline at end of file
diff --git a/client/src/pages/AdminEmailTemplates.tsx b/client/src/pages/AdminEmailTemplates.tsx
index b695f54..3fdad19 100644
--- a/client/src/pages/AdminEmailTemplates.tsx
+++ b/client/src/pages/AdminEmailTemplates.tsx
@@ -38,16 +38,12 @@ export default function AdminEmailTemplates() {
const [selectedType, setSelectedType] = useState("inscription");
const [showPreviewModal, setShowPreviewModal] = useState(false);
const [formData, setFormData] = useState({
- type: "inscription",
- name: "",
- logoUrl: "",
- primaryColor: "#2563eb",
- headerBgColor: "#2563eb",
- headerTextColor: "#ffffff",
- headerTitle: "Formation Manager Itinova",
+ type: "inscription" as "inscription" | "teaser" | "rappel" | "rappelJ1" | "rappel3" | "rappel4" | "rappel5" | "rappel6" | "reset_password",
+ titre: "",
bodyContent: "",
- footerText: "",
- active: true,
+ couleurPrincipale: "#283581",
+ couleurSecondaire: "#0578BE",
+ piedDePage: "",
});
const { data: templates, refetch } = trpc.emailTemplates.list.useQuery();
@@ -96,16 +92,12 @@ export default function AdminEmailTemplates() {
useEffect(() => {
if (currentTemplate) {
const newData = {
- type: currentTemplate.type,
- name: currentTemplate.name,
- logoUrl: currentTemplate.logoUrl || "",
- primaryColor: currentTemplate.primaryColor,
- headerBgColor: currentTemplate.headerBgColor,
- headerTextColor: currentTemplate.headerTextColor,
- headerTitle: currentTemplate.headerTitle,
+ type: currentTemplate.type as "inscription" | "teaser" | "rappel" | "rappelJ1" | "rappel3" | "rappel4" | "rappel5" | "rappel6" | "reset_password",
+ titre: currentTemplate.titre,
bodyContent: currentTemplate.bodyContent || "",
- footerText: currentTemplate.footerText || "",
- active: currentTemplate.active,
+ couleurPrincipale: currentTemplate.couleurPrincipale,
+ couleurSecondaire: currentTemplate.couleurSecondaire,
+ piedDePage: currentTemplate.piedDePage || "",
};
setFormData(newData);
// Mettre à jour le contenu de l'éditeur
@@ -117,27 +109,28 @@ export default function AdminEmailTemplates() {
const handleSave = () => {
upsertMutation.mutate({
- ...formData,
- logoUrl: formData.logoUrl || null,
- bodyContent: formData.bodyContent || null,
- footerText: formData.footerText || null,
+ type: formData.type,
+ titre: formData.titre,
+ bodyContent: formData.bodyContent,
+ couleurPrincipale: formData.couleurPrincipale,
+ couleurSecondaire: formData.couleurSecondaire,
+ piedDePage: formData.piedDePage || null,
});
};
const handleReset = () => {
if (currentTemplate) {
setFormData({
- type: currentTemplate.type,
- name: currentTemplate.name,
- logoUrl: currentTemplate.logoUrl || "",
- primaryColor: currentTemplate.primaryColor,
- headerBgColor: currentTemplate.headerBgColor,
- headerTextColor: currentTemplate.headerTextColor,
- headerTitle: currentTemplate.headerTitle,
+ type: currentTemplate.type as "inscription" | "teaser" | "rappel" | "rappelJ1" | "rappel3" | "rappel4" | "rappel5" | "rappel6" | "reset_password",
+ titre: currentTemplate.titre,
bodyContent: currentTemplate.bodyContent || "",
- footerText: currentTemplate.footerText || "",
- active: currentTemplate.active,
+ couleurPrincipale: currentTemplate.couleurPrincipale,
+ couleurSecondaire: currentTemplate.couleurSecondaire,
+ piedDePage: currentTemplate.piedDePage || "",
});
+ if (editor) {
+ editor.commands.setContent(currentTemplate.bodyContent || "");
+ }
}
};
@@ -150,24 +143,27 @@ export default function AdminEmailTemplates() {
// Générer la prévisualisation HTML avec variables remplacées
const generatePreviewWithVariables = () => {
// Remplacer les variables par des données d'exemple
- const replaceVariables = (text: string) => {
+ const replaceVariables = (text: string | null | undefined): string => {
+ if (!text) return '';
return text
- .replace(/\{\{nomApprenant\}\}/g, 'Dupont')
- .replace(/\{\{prenomApprenant\}\}/g, 'Marie')
+ .replace(/\{\{nom\}\}/g, 'Dupont')
+ .replace(/\{\{prenom\}\}/g, 'Marie')
.replace(/\{\{nomFormation\}\}/g, 'Formation Management')
.replace(/\{\{nomSequence\}\}/g, 'Séquence 1 - Introduction')
.replace(/\{\{dateDebut\}\}/g, '15/01/2025')
.replace(/\{\{dateFin\}\}/g, '17/01/2025')
.replace(/\{\{lieu\}\}/g, 'Salle de formation A - Bâtiment principal')
.replace(/\{\{formateur\}\}/g, 'Jean Martin')
+ .replace(/\{\{couleurPrincipale\}\}/g, formData.couleurPrincipale)
+ .replace(/\{\{couleurSecondaire\}\}/g, formData.couleurSecondaire)
+ .replace(/\{\{lienReinitialisation\}\}/g, 'https://formations.itinova.org/reset-password/token123')
.replace(/\{\{datesHTML\}\}/g, 'Date 1 : lundi 15 janvier 2025
Date 2 : mardi 16 janvier 2025
');
};
const bodyWithVars = formData.bodyContent ? replaceVariables(formData.bodyContent) : `
Saisissez le contenu de votre email dans le champ "Corps du message" pour voir la prévisualisation ici...
`;
- const headerWithVars = replaceVariables(formData.headerTitle);
- const footerWithVars = formData.footerText ? replaceVariables(formData.footerText) : 'Texte du pied de page';
+ const footerWithVars = formData.piedDePage ? replaceVariables(formData.piedDePage) : 'Texte du pied de page';
return `
@@ -177,21 +173,19 @@ export default function AdminEmailTemplates() {
${bodyWithVars}
@@ -205,46 +199,6 @@ export default function AdminEmailTemplates() {
`.trim();
};
- // Générer la prévisualisation HTML
- const generatePreview = () => {
- return `
-
-
-
-
-
-
-
-
-
-
- ${formData.bodyContent ? formData.bodyContent.replace(/\n/g, '
') : `
-
Saisissez le contenu de votre email dans le champ "Corps du message" pour voir la prévisualisation ici...
- `}
-
-
-
-
-
- `.trim();
- };
-
const templateTypes = [
{ value: "inscription", label: "Confirmation d'inscription" },
{ value: "teaser", label: "Email teaser" },
@@ -279,364 +233,199 @@ export default function AdminEmailTemplates() {
+
{initMutation.isPending ? "Initialisation..." : "Initialiser les templates par défaut"}
)}
-
- {/* Éditeur */}
+
+ {/* Liste des templates */}
- Éditeur de template
+ Types de templates
- Modifiez les paramètres du template sélectionné
+ Sélectionnez un template à modifier
-
-
- Type de template
- {
- setSelectedType(value);
- setFormData((prev) => ({ ...prev, type: value }));
- }}
- >
-
-
-
-
- {templateTypes.map((type) => (
-
- {type.label}
-
- ))}
-
-
-
-
-
- Nom du template
- setFormData({ ...formData, name: e.target.value })}
- placeholder="Ex: Confirmation d'inscription"
- />
-
-
-
- URL du logo (optionnel)
- setFormData({ ...formData, logoUrl: e.target.value })}
- placeholder="https://exemple.com/logo.png"
- />
-
-
-
-
-
Couleur fond en-tête
-
- setFormData({ ...formData, headerBgColor: e.target.value })}
- className="w-16 h-10 p-1"
- />
- setFormData({ ...formData, headerBgColor: e.target.value })}
- placeholder="#2563eb"
- />
-
-
-
-
-
Couleur texte en-tête
-
- setFormData({ ...formData, headerTextColor: e.target.value })}
- className="w-16 h-10 p-1"
- />
- setFormData({ ...formData, headerTextColor: e.target.value })}
- placeholder="#ffffff"
- />
-
-
-
-
-
-
Couleur principale
-
- setFormData({ ...formData, primaryColor: e.target.value })}
- className="w-16 h-10 p-1"
- />
- setFormData({ ...formData, primaryColor: e.target.value })}
- placeholder="#2563eb"
- />
-
-
- Utilisée pour les boutons et les accents
-
-
-
-
- Titre de l'en-tête
- setFormData({ ...formData, headerTitle: e.target.value })}
- placeholder="Formation Manager Itinova"
- />
-
-
-
-
Corps du message
-
- {/* Boutons de variables dynamiques */}
-
-
editor?.chain().focus().insertContent('{{nomApprenant}}').run()}
- >
-
- Nom apprenant
-
-
editor?.chain().focus().insertContent('{{prenomApprenant}}').run()}
- >
-
- Prénom apprenant
-
-
editor?.chain().focus().insertContent('{{nomFormation}}').run()}
- >
-
- Nom formation
-
-
editor?.chain().focus().insertContent('{{nomSequence}}').run()}
- >
-
- Nom séquence
-
-
editor?.chain().focus().insertContent('{{dateDebut}}').run()}
- >
-
- Date début
-
-
editor?.chain().focus().insertContent('{{lieu}}').run()}
- >
-
- Lieu
-
-
editor?.chain().focus().insertContent('{{formateur}}').run()}
- >
-
- Formateur
-
-
editor?.chain().focus().insertContent('{{datesHTML}}').run()}
- >
-
- Dates (HTML)
-
-
-
- {/* Éditeur WYSIWYG TipTap */}
-
- {/* Barre d'outils */}
- {editor && (
-
-
editor.chain().focus().toggleBold().run()}
- className={editor.isActive('bold') ? 'bg-muted' : ''}
- >
- B
-
-
editor.chain().focus().toggleItalic().run()}
- className={editor.isActive('italic') ? 'bg-muted' : ''}
- >
- I
-
-
editor.chain().focus().toggleStrike().run()}
- className={editor.isActive('strike') ? 'bg-muted' : ''}
- >
- S
-
-
-
editor.chain().focus().toggleHeading({ level: 2 }).run()}
- className={editor.isActive('heading', { level: 2 }) ? 'bg-muted' : ''}
- >
- H2
-
-
editor.chain().focus().toggleHeading({ level: 3 }).run()}
- className={editor.isActive('heading', { level: 3 }) ? 'bg-muted' : ''}
- >
- H3
-
-
-
editor.chain().focus().toggleBulletList().run()}
- className={editor.isActive('bulletList') ? 'bg-muted' : ''}
- >
- • Liste
-
-
editor.chain().focus().toggleOrderedList().run()}
- className={editor.isActive('orderedList') ? 'bg-muted' : ''}
- >
- 1. Liste
-
-
- )}
- {/* Zone d'édition */}
-
-
-
-
-
- Le contenu du corps du message. Utilisez les boutons ci-dessus pour insérer des variables dynamiques.
-
-
-
-
- Texte du pied de page
-
-
-
-
-
- {upsertMutation.isPending ? "Enregistrement..." : "Enregistrer"}
-
-
setShowPreviewModal(true)} variant="secondary">
-
- Aperçu email
-
-
-
- Réinitialiser
-
+
+
+ {templateTypes.map((templateType) => {
+ const template = templates?.find((t) => t.type === templateType.value);
+ return (
+ setSelectedType(templateType.value)}
+ >
+
+ {templateType.label}
+ {template && (
+ ✓
+ )}
+
+ );
+ })}
- {/* Modal d'aperçu email */}
-
-
-
- Aperçu de l'email final
-
- Cet aperçu montre comment l'email apparaîtra avec des données d'exemple.
- Les variables (nomApprenant, nomFormation, datesHTML, etc.) sont remplacées par des valeurs de test.
-
-
-
-
-
-
-
-
- {/* Prévisualisation */}
-
+ {/* Formulaire d'édition */}
+
-
-
- Prévisualisation en temps réel
-
+ Éditer le template
- Aperçu de votre template avec les paramètres actuels
+ Personnalisez le contenu et l'apparence de l'email
-
-
-
+
+
+
+ Type de template
+
+ setFormData({ ...formData, type: value as typeof formData.type })
+ }
+ >
+
+
+
+
+ {templateTypes.map((type) => (
+
+ {type.label}
+
+ ))}
+
+
+
+
+
+ Titre du template
+ setFormData({ ...formData, titre: e.target.value })}
+ placeholder="Ex: Confirmation d'inscription"
+ />
+
+
+
+
+
+
Corps du message
+
+
+
+
+ Variables disponibles : {"{"}{"{"} nom {"}"}{"}"}, {"{"}{"{"} prenom {"}"}{"}"}, {"{"}{"{"} nomFormation {"}"}{"}"}, {"{"}{"{"} nomSequence {"}"}{"}"}, {"{"}{"{"} dateDebut {"}"}{"}"}, {"{"}{"{"} dateFin {"}"}{"}"}, {"{"}{"{"} lieu {"}"}{"}"}, {"{"}{"{"} formateur {"}"}{"}"}, {"{"}{"{"} lienReinitialisation {"}"}{"}"}
+
+
+
+
+ Pied de page
+
+
+
+
+
+
+ {upsertMutation.isPending ? "Enregistrement..." : "Enregistrer"}
+
+
+
+ Réinitialiser
+
+ setShowPreviewModal(true)}
+ >
+
+ Prévisualiser
+
+
+ {/* Modal de prévisualisation */}
+
+
+
+ Prévisualisation de l'email
+
+ Aperçu avec les variables remplacées par des exemples
+
+
+
+
+
+
+
);
}
diff --git a/drizzle/meta/0001_snapshot.json b/drizzle/meta/0001_snapshot.json
new file mode 100644
index 0000000..1045e5b
--- /dev/null
+++ b/drizzle/meta/0001_snapshot.json
@@ -0,0 +1,2123 @@
+{
+ "version": "5",
+ "dialect": "mysql",
+ "id": "c1d1d859-4855-4848-8513-854c36b8bf1a",
+ "prevId": "aa771876-44ab-4786-a5db-87b71c6e5674",
+ "tables": {
+ "apprenants": {
+ "name": "apprenants",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "nom": {
+ "name": "nom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "prenom": {
+ "name": "prenom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "codeEtablissement": {
+ "name": "codeEtablissement",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "fonction": {
+ "name": "fonction",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "apprenants_id": {
+ "name": "apprenants_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "apprenants_email_unique": {
+ "name": "apprenants_email_unique",
+ "columns": [
+ "email"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "attestations": {
+ "name": "attestations",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "apprenantId": {
+ "name": "apprenantId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "inscriptionId": {
+ "name": "inscriptionId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "urlPdf": {
+ "name": "urlPdf",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "s3Key": {
+ "name": "s3Key",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "documentUrl": {
+ "name": "documentUrl",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "documentS3Key": {
+ "name": "documentS3Key",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "uploadedBy": {
+ "name": "uploadedBy",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "uploadedAt": {
+ "name": "uploadedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "emailEnvoye": {
+ "name": "emailEnvoye",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "dateEnvoiEmail": {
+ "name": "dateEnvoiEmail",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "dateGeneration": {
+ "name": "dateGeneration",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "attestations_id": {
+ "name": "attestations_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "configAttestation": {
+ "name": "configAttestation",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "texteAttestation": {
+ "name": "texteAttestation",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "nomSignataire": {
+ "name": "nomSignataire",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fonctionSignataire": {
+ "name": "fonctionSignataire",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "logoUrl": {
+ "name": "logoUrl",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "logoS3Key": {
+ "name": "logoS3Key",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "signatureUrl": {
+ "name": "signatureUrl",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "signatureS3Key": {
+ "name": "signatureS3Key",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "configAttestation_id": {
+ "name": "configAttestation_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "datesFormation": {
+ "name": "datesFormation",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "ordre": {
+ "name": "ordre",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateDebut": {
+ "name": "dateDebut",
+ "type": "datetime",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateFin": {
+ "name": "dateFin",
+ "type": "datetime",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "datesFormation_id": {
+ "name": "datesFormation_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "emailConfig": {
+ "name": "emailConfig",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "provider": {
+ "name": "provider",
+ "type": "enum('resend','smtp','simulation')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'simulation'"
+ },
+ "resendApiKey": {
+ "name": "resendApiKey",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "smtpHost": {
+ "name": "smtpHost",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "smtpPort": {
+ "name": "smtpPort",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "smtpSecure": {
+ "name": "smtpSecure",
+ "type": "enum('tls','ssl','none')",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "smtpUser": {
+ "name": "smtpUser",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "smtpPassword": {
+ "name": "smtpPassword",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "fromEmail": {
+ "name": "fromEmail",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fromName": {
+ "name": "fromName",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "mode": {
+ "name": "mode",
+ "type": "enum('simulation','production')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'simulation'"
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "emailConfig_id": {
+ "name": "emailConfig_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "emailTemplates": {
+ "name": "emailTemplates",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "type": {
+ "name": "type",
+ "type": "enum('inscription','teaser','rappel','rappelJ1','rappel3','rappel4','rappel5','rappel6','reset_password')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "titre": {
+ "name": "titre",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "bodyContent": {
+ "name": "bodyContent",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "couleurPrincipale": {
+ "name": "couleurPrincipale",
+ "type": "varchar(7)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'#283581'"
+ },
+ "couleurSecondaire": {
+ "name": "couleurSecondaire",
+ "type": "varchar(7)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'#0578BE'"
+ },
+ "piedDePage": {
+ "name": "piedDePage",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "emailTemplates_id": {
+ "name": "emailTemplates_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "emailTemplates_type_unique": {
+ "name": "emailTemplates_type_unique",
+ "columns": [
+ "type"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "envoisQuestionnaires": {
+ "name": "envoisQuestionnaires",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "questionnaireId": {
+ "name": "questionnaireId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apprenantId": {
+ "name": "apprenantId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateEnvoi": {
+ "name": "dateEnvoi",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "dateReponse": {
+ "name": "dateReponse",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "statut": {
+ "name": "statut",
+ "type": "enum('envoye','repondu')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'envoye'"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "envoisQuestionnaires_id": {
+ "name": "envoisQuestionnaires_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "envoisQuestionnaires_token_unique": {
+ "name": "envoisQuestionnaires_token_unique",
+ "columns": [
+ "token"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "formateurs": {
+ "name": "formateurs",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "nom": {
+ "name": "nom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "formateurs_id": {
+ "name": "formateurs_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "formations": {
+ "name": "formations",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "nom": {
+ "name": "nom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "lienUnique": {
+ "name": "lienUnique",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "actif": {
+ "name": "actif",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": true
+ },
+ "modeAttestation": {
+ "name": "modeAttestation",
+ "type": "enum('auto','manuel')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'auto'"
+ },
+ "modeEnvoi": {
+ "name": "modeEnvoi",
+ "type": "enum('auto','manuel')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'manuel'"
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "formations_id": {
+ "name": "formations_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "formations_lienUnique_unique": {
+ "name": "formations_lienUnique_unique",
+ "columns": [
+ "lienUnique"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "historiqueAttestations": {
+ "name": "historiqueAttestations",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apprenantId": {
+ "name": "apprenantId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateEnvoi": {
+ "name": "dateEnvoi",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "statut": {
+ "name": "statut",
+ "type": "enum('envoye','erreur')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "messageErreur": {
+ "name": "messageErreur",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "urlAttestation": {
+ "name": "urlAttestation",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "historiqueAttestations_id": {
+ "name": "historiqueAttestations_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "historiqueParametres": {
+ "name": "historiqueParametres",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "userName": {
+ "name": "userName",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "champModifie": {
+ "name": "champModifie",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "ancienneValeur": {
+ "name": "ancienneValeur",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "nouvelleValeur": {
+ "name": "nouvelleValeur",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "dateModification": {
+ "name": "dateModification",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "historiqueParametres_id": {
+ "name": "historiqueParametres_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "inscriptions": {
+ "name": "inscriptions",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apprenantId": {
+ "name": "apprenantId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "statut": {
+ "name": "statut",
+ "type": "enum('confirmee','en_attente','annulee')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'confirmee'"
+ },
+ "dateInscription": {
+ "name": "dateInscription",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "inscriptions_id": {
+ "name": "inscriptions_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "logsNotifications": {
+ "name": "logsNotifications",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "type": {
+ "name": "type",
+ "type": "enum('inscription','annulation','capacite_atteinte','place_disponible','remerciement','formateur_inscription','formateur_annulation')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "destinataire": {
+ "name": "destinataire",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "apprenantId": {
+ "name": "apprenantId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "statut": {
+ "name": "statut",
+ "type": "enum('succes','echec')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "messageErreur": {
+ "name": "messageErreur",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "dateEnvoi": {
+ "name": "dateEnvoi",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "logsNotifications_id": {
+ "name": "logsNotifications_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "logsRappels": {
+ "name": "logsRappels",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "rappelId": {
+ "name": "rappelId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apprenantId": {
+ "name": "apprenantId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "type": {
+ "name": "type",
+ "type": "enum('rappel','rappelJ1','rappel3','rappel4','rappel5','rappel6')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "statut": {
+ "name": "statut",
+ "type": "enum('succes','echec')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "messageErreur": {
+ "name": "messageErreur",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "nbTentatives": {
+ "name": "nbTentatives",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "prochainEssai": {
+ "name": "prochainEssai",
+ "type": "datetime",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "dateEnvoi": {
+ "name": "dateEnvoi",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "logsRappels_id": {
+ "name": "logsRappels_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "parametres": {
+ "name": "parametres",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "urlPublique": {
+ "name": "urlPublique",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'https://formations.itinova.org'"
+ },
+ "delaiExpirationQR": {
+ "name": "delaiExpirationQR",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 30
+ },
+ "dureeValiditeToken": {
+ "name": "dureeValiditeToken",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 24
+ },
+ "notificationsActives": {
+ "name": "notificationsActives",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": true
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "parametres_id": {
+ "name": "parametres_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "passwordResetTokens": {
+ "name": "passwordResetTokens",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "userId": {
+ "name": "userId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expiresAt": {
+ "name": "expiresAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "passwordResetTokens_id": {
+ "name": "passwordResetTokens_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "passwordResetTokens_token_unique": {
+ "name": "passwordResetTokens_token_unique",
+ "columns": [
+ "token"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "presences": {
+ "name": "presences",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "inscriptionId": {
+ "name": "inscriptionId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateFormationId": {
+ "name": "dateFormationId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "heurePresence": {
+ "name": "heurePresence",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "modeValidation": {
+ "name": "modeValidation",
+ "type": "enum('qrcode','manuel')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "validateurId": {
+ "name": "validateurId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "presences_id": {
+ "name": "presences_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "questionnaires": {
+ "name": "questionnaires",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "titre": {
+ "name": "titre",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "type": {
+ "name": "type",
+ "type": "enum('satisfaction','evaluation_pre','evaluation_post')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "actif": {
+ "name": "actif",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": true
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "questionnaires_id": {
+ "name": "questionnaires_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "questions": {
+ "name": "questions",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "questionnaireId": {
+ "name": "questionnaireId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "texte": {
+ "name": "texte",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "typeQuestion": {
+ "name": "typeQuestion",
+ "type": "enum('choix_multiple','echelle','texte_libre','oui_non')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "options": {
+ "name": "options",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "valeurMin": {
+ "name": "valeurMin",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "valeurMax": {
+ "name": "valeurMax",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "obligatoire": {
+ "name": "obligatoire",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "ordre": {
+ "name": "ordre",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "questions_id": {
+ "name": "questions_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "rappelDates": {
+ "name": "rappelDates",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "rappelId": {
+ "name": "rappelId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateFormationId": {
+ "name": "dateFormationId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "rappelDates_id": {
+ "name": "rappelDates_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "rappels": {
+ "name": "rappels",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "nom": {
+ "name": "nom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "templateType": {
+ "name": "templateType",
+ "type": "enum('rappel','rappelJ1','rappel3','rappel4','rappel5','rappel6')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "joursAvant": {
+ "name": "joursAvant",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "heureEnvoi": {
+ "name": "heureEnvoi",
+ "type": "varchar(5)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'09:00'"
+ },
+ "timing": {
+ "name": "timing",
+ "type": "enum('pre_formation','post_formation')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'pre_formation'"
+ },
+ "nomFichier": {
+ "name": "nomFichier",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "urlFichier": {
+ "name": "urlFichier",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "s3Key": {
+ "name": "s3Key",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "typeFichier": {
+ "name": "typeFichier",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "tailleFichier": {
+ "name": "tailleFichier",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "actif": {
+ "name": "actif",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": true
+ },
+ "derniereExecution": {
+ "name": "derniereExecution",
+ "type": "datetime",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "rappels_id": {
+ "name": "rappels_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "reponsesQuestionnaires": {
+ "name": "reponsesQuestionnaires",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "questionnaireId": {
+ "name": "questionnaireId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "apprenantId": {
+ "name": "apprenantId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateReponse": {
+ "name": "dateReponse",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "reponsesQuestionnaires_id": {
+ "name": "reponsesQuestionnaires_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "reponsesQuestions": {
+ "name": "reponsesQuestions",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "reponseQuestionnaireId": {
+ "name": "reponseQuestionnaireId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "questionId": {
+ "name": "questionId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "reponseTexte": {
+ "name": "reponseTexte",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "reponseNumerique": {
+ "name": "reponseNumerique",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "reponsesQuestions_id": {
+ "name": "reponsesQuestions_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "sequences": {
+ "name": "sequences",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "formationId": {
+ "name": "formationId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "nom": {
+ "name": "nom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "lieu": {
+ "name": "lieu",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "capaciteMax": {
+ "name": "capaciteMax",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "statut": {
+ "name": "statut",
+ "type": "enum('ouverte','bloquee','terminee','fermee','annulee')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'ouverte'"
+ },
+ "publicCible": {
+ "name": "publicCible",
+ "type": "enum('directeur','chef_service','autre','tous')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'tous'"
+ },
+ "formateurId": {
+ "name": "formateurId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "qrCodeToken": {
+ "name": "qrCodeToken",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "sequences_id": {
+ "name": "sequences_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "sequences_qrCodeToken_unique": {
+ "name": "sequences_qrCodeToken_unique",
+ "columns": [
+ "qrCodeToken"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "supportsFormation": {
+ "name": "supportsFormation",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "sequenceId": {
+ "name": "sequenceId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "formateurId": {
+ "name": "formateurId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "nomFichier": {
+ "name": "nomFichier",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "typeFichier": {
+ "name": "typeFichier",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "tailleFichier": {
+ "name": "tailleFichier",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "urlFichier": {
+ "name": "urlFichier",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "s3Key": {
+ "name": "s3Key",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "supportsFormation_id": {
+ "name": "supportsFormation_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "users": {
+ "name": "users",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "openId": {
+ "name": "openId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "username": {
+ "name": "username",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "password": {
+ "name": "password",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "loginMethod": {
+ "name": "loginMethod",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "role": {
+ "name": "role",
+ "type": "enum('user','admin','formateur')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'user'"
+ },
+ "isActive": {
+ "name": "isActive",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": true
+ },
+ "formateurId": {
+ "name": "formateurId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ },
+ "lastSignedIn": {
+ "name": "lastSignedIn",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "users_id": {
+ "name": "users_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "users_openId_unique": {
+ "name": "users_openId_unique",
+ "columns": [
+ "openId"
+ ]
+ },
+ "users_username_unique": {
+ "name": "users_username_unique",
+ "columns": [
+ "username"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ }
+ },
+ "views": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "tables": {},
+ "indexes": {}
+ }
+}
\ No newline at end of file
diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json
index 6f7b99a..bc492a3 100644
--- a/drizzle/meta/_journal.json
+++ b/drizzle/meta/_journal.json
@@ -8,6 +8,13 @@
"when": 1768296151204,
"tag": "0000_clean_justice",
"breakpoints": true
+ },
+ {
+ "idx": 1,
+ "version": "5",
+ "when": 1768464808933,
+ "tag": "0001_dark_shadow_king",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/drizzle/schema.ts b/drizzle/schema.ts
index e0d9b2d..9af1298 100644
--- a/drizzle/schema.ts
+++ b/drizzle/schema.ts
@@ -179,8 +179,8 @@ export type InsertEmailConfig = typeof emailConfig.$inferInsert;
*/
export const emailTemplates = mysqlTable("emailTemplates", {
id: int("id").autoincrement().primaryKey(),
- /** Type de template (inscription, teaser, rappel, rappelJ1, rappel3, rappel4, rappel5, rappel6) */
- type: mysqlEnum("type", ["inscription", "teaser", "rappel", "rappelJ1", "rappel3", "rappel4", "rappel5", "rappel6"]).notNull().unique(),
+ /** Type de template (inscription, teaser, rappel, rappelJ1, rappel3, rappel4, rappel5, rappel6, reset_password) */
+ type: mysqlEnum("type", ["inscription", "teaser", "rappel", "rappelJ1", "rappel3", "rappel4", "rappel5", "rappel6", "reset_password"]).notNull().unique(),
titre: varchar("titre", { length: 255 }).notNull(),
/** Corps du message avec variables dynamiques */
bodyContent: text("bodyContent").notNull(),
diff --git a/server/db.ts b/server/db.ts
index dc0b2b3..25f7e02 100644
--- a/server/db.ts
+++ b/server/db.ts
@@ -692,15 +692,11 @@ export async function upsertEmailTemplate(template: InsertEmailTemplate) {
// Mise à jour
await db.update(emailTemplates)
.set({
- name: template.name,
- logoUrl: template.logoUrl,
- primaryColor: template.primaryColor,
- headerBgColor: template.headerBgColor,
- headerTextColor: template.headerTextColor,
- headerTitle: template.headerTitle,
+ titre: template.titre,
bodyContent: template.bodyContent,
- footerText: template.footerText,
- active: template.active,
+ couleurPrincipale: template.couleurPrincipale,
+ couleurSecondaire: template.couleurSecondaire,
+ piedDePage: template.piedDePage,
updatedAt: new Date(),
})
.where(eq(emailTemplates.type, template.type));
diff --git a/server/routers.ts b/server/routers.ts
index 5ee1383..22b272d 100644
--- a/server/routers.ts
+++ b/server/routers.ts
@@ -1168,16 +1168,12 @@ export const appRouter = router({
upsert: adminProcedure
.input(z.object({
- type: z.string(),
- name: z.string(),
- logoUrl: z.string().nullable(),
- primaryColor: z.string(),
- headerBgColor: z.string(),
- headerTextColor: z.string(),
- headerTitle: z.string(),
- bodyContent: z.string().nullable(),
- footerText: z.string().nullable(),
- active: z.boolean(),
+ type: z.enum(["inscription", "teaser", "rappel", "rappelJ1", "rappel3", "rappel4", "rappel5", "rappel6", "reset_password"]),
+ titre: z.string(),
+ bodyContent: z.string(),
+ couleurPrincipale: z.string(),
+ couleurSecondaire: z.string(),
+ piedDePage: z.string().nullable(),
}))
.mutation(async ({ input }) => {
return db.upsertEmailTemplate(input);
diff --git a/todo.md b/todo.md
index ed1dad5..72f9266 100644
--- a/todo.md
+++ b/todo.md
@@ -790,3 +790,14 @@
- [x] Corriger les erreurs TypeScript liées aux types templateType dans les rappels
- [x] Nettoyer les fichiers de migration Drizzle pour éviter les conflits
- [x] Créer un guide utilisateur pour la configuration des attestations
+
+## Bug : Erreur replaceVariables
+
+- [x] Corriger l'erreur "Cannot read properties of undefined (reading 'replace')" dans AdminEmailTemplates.tsx
+
+## Ajout template Réinitialisation mot de passe
+
+- [ ] Ajouter le type reset_password au schéma Drizzle
+- [ ] Modifier l'enum dans la base de données
+- [ ] Mettre à jour le code frontend
+- [ ] Créer le template par défaut