Ajout verif date de naissance esign
This commit is contained in:
parent
2b945dec70
commit
3eb696b45d
12 changed files with 1112 additions and 9 deletions
|
|
@ -92,7 +92,7 @@ vercel --prod
|
||||||
|
|
||||||
| Key | Value | Description |
|
| Key | Value | Description |
|
||||||
|-----|-------|-------------|
|
|-----|-------|-------------|
|
||||||
| `ESPACE_PAIE_URL` | `https://staging.paie.odentas.fr` | URL de l'Espace Paie (staging ou prod) |
|
| `ESPACE_PAIE_URL` | `https://paie.odentas.fr` | URL de l'Espace Paie (production) |
|
||||||
| `ESPACE_PAIE_API_KEY` | `<votre_clé_générée>` | **La même clé qu'à l'étape 1** |
|
| `ESPACE_PAIE_API_KEY` | `<votre_clé_générée>` | **La même clé qu'à l'étape 1** |
|
||||||
|
|
||||||
6. Cliquer sur **Save**
|
6. Cliquer sur **Save**
|
||||||
|
|
@ -170,7 +170,7 @@ curl -X POST https://paie.odentas.fr/api/emails/signature-salarie \
|
||||||
|
|
||||||
#### Dans l'Espace Paie
|
#### Dans l'Espace Paie
|
||||||
|
|
||||||
1. Aller sur : `https://staging.paie.odentas.fr/staff/email-logs`
|
1. Aller sur : `https://paie.odentas.fr/staff/email-logs`
|
||||||
2. Filtrer par type : **signature-request-salarie**
|
2. Filtrer par type : **signature-request-salarie**
|
||||||
3. Vérifier le statut : **sent**
|
3. Vérifier le statut : **sent**
|
||||||
4. Cliquer sur une ligne pour voir le contenu HTML
|
4. Cliquer sur une ligne pour voir le contenu HTML
|
||||||
|
|
|
||||||
116
CHANGEMENT_URL_PRODUCTION.md
Normal file
116
CHANGEMENT_URL_PRODUCTION.md
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
# ✅ Modification effectuée : URLs de production
|
||||||
|
|
||||||
|
## 🎯 Ce qui a été changé
|
||||||
|
|
||||||
|
Le lien de signature dans les emails envoyés aux salariés a été mis à jour pour utiliser l'URL de **production** au lieu de staging.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📧 Dans l'email au salarié
|
||||||
|
|
||||||
|
### Avant
|
||||||
|
```
|
||||||
|
https://staging.paie.odentas.fr/odentas-sign?docuseal_id=abc123
|
||||||
|
```
|
||||||
|
|
||||||
|
### Après ✅
|
||||||
|
```
|
||||||
|
https://paie.odentas.fr/signature-salarie/?docuseal_id=abc123
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Changements techniques
|
||||||
|
|
||||||
|
### 1. Code Lambda (ligne 82)
|
||||||
|
|
||||||
|
**Fichier** : `LAMBDA_SIGNATURE_SALARIE_UPDATED.js`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// AVANT
|
||||||
|
const signatureLink = `https://staging.paie.odentas.fr/odentas-sign?docuseal_id=${employeeSlug}`;
|
||||||
|
|
||||||
|
// APRÈS ✅
|
||||||
|
const signatureLink = `https://paie.odentas.fr/signature-salarie/?docuseal_id=${employeeSlug}`;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Documentation mise à jour
|
||||||
|
|
||||||
|
✅ `LAMBDA_EMAIL_SIGNATURE_SALARIE_GUIDE.md`
|
||||||
|
- Variable `ESPACE_PAIE_URL` : `https://paie.odentas.fr`
|
||||||
|
- Exemple de payload avec nouvelle URL
|
||||||
|
|
||||||
|
✅ `ACTIONS_A_FAIRE.md`
|
||||||
|
- Instructions de configuration avec URL de production
|
||||||
|
- Commandes de test avec bonne URL
|
||||||
|
|
||||||
|
✅ `LAMBDA_EMAIL_SIGNATURE_CHANGELOG.md` (nouveau)
|
||||||
|
- Historique des versions
|
||||||
|
- Guide de mise à jour
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Pour déployer ce changement
|
||||||
|
|
||||||
|
Si vous avez déjà déployé l'ancienne version :
|
||||||
|
|
||||||
|
### Option 1 : Déploiement complet (recommandé)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Copier le nouveau code Lambda
|
||||||
|
# Copier LAMBDA_SIGNATURE_SALARIE_UPDATED.js dans AWS Lambda
|
||||||
|
|
||||||
|
# 2. Mettre à jour la variable d'environnement
|
||||||
|
# AWS Console → Lambda → Configuration → Environment variables
|
||||||
|
# ESPACE_PAIE_URL = https://paie.odentas.fr
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2 : Modification minimale
|
||||||
|
|
||||||
|
Modifier uniquement la ligne 82 dans le code Lambda existant :
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const signatureLink = `https://paie.odentas.fr/signature-salarie/?docuseal_id=${employeeSlug}`;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Résultat
|
||||||
|
|
||||||
|
Après déploiement :
|
||||||
|
|
||||||
|
📧 **Les salariés reçoivent un email avec :**
|
||||||
|
- ✅ URL de production : `https://paie.odentas.fr/signature-salarie/`
|
||||||
|
- ✅ Chemin plus clair et professionnel
|
||||||
|
- ✅ Fonctionne immédiatement en environnement de production
|
||||||
|
|
||||||
|
🔍 **Dans les logs** :
|
||||||
|
- Le `signatureLink` dans le payload API affiche la nouvelle URL
|
||||||
|
- Les emails loggés contiennent le bon lien
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Comparaison
|
||||||
|
|
||||||
|
| Aspect | Staging | Production ✅ |
|
||||||
|
|--------|---------|---------------|
|
||||||
|
| **Domaine** | `staging.paie.odentas.fr` | `paie.odentas.fr` |
|
||||||
|
| **Chemin** | `/odentas-sign` | `/signature-salarie/` |
|
||||||
|
| **URL complète** | `https://staging.paie.odentas.fr/odentas-sign?docuseal_id=xxx` | `https://paie.odentas.fr/signature-salarie/?docuseal_id=xxx` |
|
||||||
|
| **Environnement** | Test/Développement | Production |
|
||||||
|
| **Recommandé pour** | Tests internes | Clients et salariés réels |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎉 C'est prêt !
|
||||||
|
|
||||||
|
Les fichiers ont été mis à jour. Il ne reste plus qu'à :
|
||||||
|
|
||||||
|
1. ✅ Copier le code de `LAMBDA_SIGNATURE_SALARIE_UPDATED.js` dans AWS Lambda
|
||||||
|
2. ✅ Mettre à jour `ESPACE_PAIE_URL` dans les variables d'environnement
|
||||||
|
3. ✅ Déployer
|
||||||
|
4. ✅ Tester avec un vrai webhook
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Modification effectuée le 15 octobre 2025*
|
||||||
94
LAMBDA_EMAIL_SIGNATURE_CHANGELOG.md
Normal file
94
LAMBDA_EMAIL_SIGNATURE_CHANGELOG.md
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
# 📝 Changelog - Email Signature Salarié
|
||||||
|
|
||||||
|
## Version 1.1 - 15 octobre 2025
|
||||||
|
|
||||||
|
### ✅ Mise à jour des URLs
|
||||||
|
|
||||||
|
**Changement** : Passage de l'environnement staging vers production
|
||||||
|
|
||||||
|
#### URLs modifiées
|
||||||
|
|
||||||
|
| Élément | Avant | Après |
|
||||||
|
|---------|-------|-------|
|
||||||
|
| **Lien de signature dans l'email** | `https://staging.paie.odentas.fr/odentas-sign?docuseal_id=xxx` | `https://paie.odentas.fr/signature-salarie/?docuseal_id=xxx` |
|
||||||
|
| **URL API Espace Paie (Lambda)** | `https://staging.paie.odentas.fr` | `https://paie.odentas.fr` |
|
||||||
|
|
||||||
|
#### Fichiers modifiés
|
||||||
|
|
||||||
|
- ✅ `LAMBDA_SIGNATURE_SALARIE_UPDATED.js` - Ligne 82
|
||||||
|
- ✅ `LAMBDA_EMAIL_SIGNATURE_SALARIE_GUIDE.md` - Documentation
|
||||||
|
- ✅ `ACTIONS_A_FAIRE.md` - Guide de déploiement
|
||||||
|
|
||||||
|
#### Impact
|
||||||
|
|
||||||
|
- ✅ Les salariés reçoivent maintenant un lien vers l'URL de production
|
||||||
|
- ✅ L'URL est plus claire : `/signature-salarie/` au lieu de `/odentas-sign`
|
||||||
|
- ✅ Cohérence avec l'environnement de production
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version 1.0 - 15 octobre 2025
|
||||||
|
|
||||||
|
### 🎉 Version initiale
|
||||||
|
|
||||||
|
**Migration complète** : Envoi d'emails depuis Lambda → API Espace Paie → Système Universel v2
|
||||||
|
|
||||||
|
#### Fonctionnalités
|
||||||
|
|
||||||
|
- ✅ Route API `/api/emails/signature-salarie` avec authentification
|
||||||
|
- ✅ Type d'email `signature-request-salarie` dans le système universel
|
||||||
|
- ✅ Template email avec cartes info et détails
|
||||||
|
- ✅ Logs automatiques dans `email_logs`
|
||||||
|
- ✅ Interface de visualisation dans `/staff/email-logs`
|
||||||
|
|
||||||
|
#### Avantages
|
||||||
|
|
||||||
|
- ✅ Centralisation de tous les emails
|
||||||
|
- ✅ Logs unifiés dans Supabase
|
||||||
|
- ✅ Template cohérent avec les autres emails
|
||||||
|
- ✅ Maintenance simplifiée
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
|
||||||
|
- 📚 `LAMBDA_EMAIL_SIGNATURE_SALARIE_GUIDE.md` - Guide complet
|
||||||
|
- 📋 `LAMBDA_EMAIL_SIGNATURE_SALARIE_SUMMARY.md` - Résumé
|
||||||
|
- 🎯 `ACTIONS_A_FAIRE.md` - Guide de déploiement
|
||||||
|
- 📝 `LAMBDA_SIGNATURE_SALARIE_UPDATED.js` - Code Lambda
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Actions à effectuer pour la mise à jour 1.1
|
||||||
|
|
||||||
|
Si vous avez déjà déployé la version 1.0, voici ce qu'il faut faire :
|
||||||
|
|
||||||
|
### 1. Mettre à jour la Lambda AWS
|
||||||
|
|
||||||
|
1. Aller dans AWS Console → Lambda → `postDocuSealSalarie`
|
||||||
|
2. Onglet "Code"
|
||||||
|
3. Modifier la ligne 82 de `index.js` :
|
||||||
|
```javascript
|
||||||
|
// AVANT
|
||||||
|
const signatureLink = `https://staging.paie.odentas.fr/odentas-sign?docuseal_id=${employeeSlug}`;
|
||||||
|
|
||||||
|
// APRÈS
|
||||||
|
const signatureLink = `https://paie.odentas.fr/signature-salarie/?docuseal_id=${employeeSlug}`;
|
||||||
|
```
|
||||||
|
4. Cliquer sur "Deploy"
|
||||||
|
|
||||||
|
### 2. Mettre à jour la variable d'environnement (optionnel mais recommandé)
|
||||||
|
|
||||||
|
1. Onglet "Configuration" → "Environment variables"
|
||||||
|
2. Modifier `ESPACE_PAIE_URL` :
|
||||||
|
- Ancienne valeur : `https://staging.paie.odentas.fr`
|
||||||
|
- Nouvelle valeur : `https://paie.odentas.fr`
|
||||||
|
3. Cliquer sur "Save"
|
||||||
|
|
||||||
|
### 3. Tester
|
||||||
|
|
||||||
|
1. Déclencher un webhook DocuSeal
|
||||||
|
2. Vérifier que l'email contient le nouveau lien
|
||||||
|
3. Cliquer sur le lien pour vérifier qu'il fonctionne
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Dernière mise à jour : 15 octobre 2025*
|
||||||
|
|
@ -36,7 +36,7 @@ SUPABASE_SERVICE_ROLE=xxxxx
|
||||||
ZAPIER_WEBHOOK_URL=https://hooks.zapier.com/xxxxx
|
ZAPIER_WEBHOOK_URL=https://hooks.zapier.com/xxxxx
|
||||||
|
|
||||||
# NOUVELLES variables à ajouter
|
# NOUVELLES variables à ajouter
|
||||||
ESPACE_PAIE_URL=https://staging.paie.odentas.fr
|
ESPACE_PAIE_URL=https://paie.odentas.fr
|
||||||
ESPACE_PAIE_API_KEY=<générer une clé secrète forte>
|
ESPACE_PAIE_API_KEY=<générer une clé secrète forte>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -153,7 +153,7 @@ vercel --prod
|
||||||
- Aller dans AWS Lambda → `postDocuSealSalarie`
|
- Aller dans AWS Lambda → `postDocuSealSalarie`
|
||||||
- Onglet "Configuration" → "Environment variables"
|
- Onglet "Configuration" → "Environment variables"
|
||||||
- Ajouter :
|
- Ajouter :
|
||||||
- `ESPACE_PAIE_URL` = `https://staging.paie.odentas.fr` (ou prod)
|
- `ESPACE_PAIE_URL` = `https://paie.odentas.fr`
|
||||||
- `ESPACE_PAIE_API_KEY` = `<votre clé générée>`
|
- `ESPACE_PAIE_API_KEY` = `<votre clé générée>`
|
||||||
- Supprimer les anciennes variables (optionnel mais recommandé)
|
- Supprimer les anciennes variables (optionnel mais recommandé)
|
||||||
|
|
||||||
|
|
@ -241,7 +241,7 @@ vercel --prod
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"employeeEmail": "salarie@example.com",
|
"employeeEmail": "salarie@example.com",
|
||||||
"signatureLink": "https://staging.paie.odentas.fr/odentas-sign?docuseal_id=abc123",
|
"signatureLink": "https://paie.odentas.fr/signature-salarie/?docuseal_id=abc123",
|
||||||
"reference": "CDDU-2025-001",
|
"reference": "CDDU-2025-001",
|
||||||
"firstName": "Jean",
|
"firstName": "Jean",
|
||||||
"organizationName": "Théâtre National",
|
"organizationName": "Théâtre National",
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ LAMBDA_API_KEY=<générer une clé de 64 caractères hex>
|
||||||
|
|
||||||
```env
|
```env
|
||||||
# À AJOUTER
|
# À AJOUTER
|
||||||
ESPACE_PAIE_URL=https://staging.paie.odentas.fr # ou production
|
ESPACE_PAIE_URL=https://paie.odentas.fr
|
||||||
ESPACE_PAIE_API_KEY=<même clé que LAMBDA_API_KEY>
|
ESPACE_PAIE_API_KEY=<même clé que LAMBDA_API_KEY>
|
||||||
|
|
||||||
# À CONSERVER (pour Supabase, DocuSeal, Zapier)
|
# À CONSERVER (pour Supabase, DocuSeal, Zapier)
|
||||||
|
|
@ -164,7 +164,7 @@ vercel --prod
|
||||||
1. Aller dans AWS Console → Lambda → `postDocuSealSalarie`
|
1. Aller dans AWS Console → Lambda → `postDocuSealSalarie`
|
||||||
2. Configuration → Environment variables
|
2. Configuration → Environment variables
|
||||||
3. Ajouter :
|
3. Ajouter :
|
||||||
- `ESPACE_PAIE_URL` = `https://staging.paie.odentas.fr`
|
- `ESPACE_PAIE_URL` = `https://paie.odentas.fr`
|
||||||
- `ESPACE_PAIE_API_KEY` = `<clé_générée>` (la même)
|
- `ESPACE_PAIE_API_KEY` = `<clé_générée>` (la même)
|
||||||
4. Code → Remplacer par `LAMBDA_SIGNATURE_SALARIE_UPDATED.js`
|
4. Code → Remplacer par `LAMBDA_SIGNATURE_SALARIE_UPDATED.js`
|
||||||
5. Deploy
|
5. Deploy
|
||||||
|
|
@ -183,7 +183,7 @@ vercel --prod
|
||||||
### ✅ L'API fonctionne
|
### ✅ L'API fonctionne
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST https://staging.paie.odentas.fr/api/emails/signature-salarie \
|
curl -X POST https://paie.odentas.fr/api/emails/signature-salarie \
|
||||||
-H "X-API-Key: votre_cle" \
|
-H "X-API-Key: votre_cle" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ exports.handler = async (event) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Génération du lien de signature
|
// Génération du lien de signature
|
||||||
const signatureLink = `https://staging.paie.odentas.fr/odentas-sign?docuseal_id=${employeeSlug}`;
|
const signatureLink = `https://paie.odentas.fr/signature-salarie/?docuseal_id=${employeeSlug}`;
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// NOUVEAU : Appel API Espace Paie au lieu d'envoi direct SES
|
// NOUVEAU : Appel API Espace Paie au lieu d'envoi direct SES
|
||||||
|
|
|
||||||
55
README_CHANGEMENT_URL.md
Normal file
55
README_CHANGEMENT_URL.md
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
# ✅ Modification terminée - URLs de production
|
||||||
|
|
||||||
|
## Ce qui a changé
|
||||||
|
|
||||||
|
Le lien dans l'email au salarié utilise maintenant l'URL de production :
|
||||||
|
|
||||||
|
```
|
||||||
|
https://paie.odentas.fr/signature-salarie/?docuseal_id=xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
Au lieu de :
|
||||||
|
```
|
||||||
|
https://staging.paie.odentas.fr/odentas-sign?docuseal_id=xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fichiers mis à jour
|
||||||
|
|
||||||
|
✅ **`LAMBDA_SIGNATURE_SALARIE_UPDATED.js`** (ligne 82)
|
||||||
|
- Génération du lien avec la nouvelle URL
|
||||||
|
|
||||||
|
✅ **`LAMBDA_EMAIL_SIGNATURE_SALARIE_GUIDE.md`**
|
||||||
|
- Variable `ESPACE_PAIE_URL` mise à jour
|
||||||
|
- Exemples avec la nouvelle URL
|
||||||
|
|
||||||
|
✅ **`ACTIONS_A_FAIRE.md`**
|
||||||
|
- Instructions de déploiement mises à jour
|
||||||
|
|
||||||
|
✅ **`LAMBDA_EMAIL_SIGNATURE_SALARIE_SUMMARY.md`**
|
||||||
|
- Documentation mise à jour
|
||||||
|
|
||||||
|
✅ **`LAMBDA_EMAIL_SIGNATURE_CHANGELOG.md`** (nouveau)
|
||||||
|
- Historique des versions
|
||||||
|
- Guide de migration
|
||||||
|
|
||||||
|
✅ **`CHANGEMENT_URL_PRODUCTION.md`** (nouveau)
|
||||||
|
- Résumé visuel des changements
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pour déployer
|
||||||
|
|
||||||
|
Il suffit de copier le nouveau code de `LAMBDA_SIGNATURE_SALARIE_UPDATED.js` dans votre Lambda AWS.
|
||||||
|
|
||||||
|
La ligne modifiée (82) :
|
||||||
|
```javascript
|
||||||
|
const signatureLink = `https://paie.odentas.fr/signature-salarie/?docuseal_id=${employeeSlug}`;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**C'est tout ! 🎉**
|
||||||
|
|
||||||
|
Les emails contiendront maintenant le bon lien de production.
|
||||||
421
SIGNATURE_SALARIE_BIRTHDATE_VERIFICATION.md
Normal file
421
SIGNATURE_SALARIE_BIRTHDATE_VERIFICATION.md
Normal file
|
|
@ -0,0 +1,421 @@
|
||||||
|
# 🔐 Sécurisation Signature Salarié - Vérification Date de Naissance
|
||||||
|
|
||||||
|
## 📋 Vue d'ensemble
|
||||||
|
|
||||||
|
Un système de vérification par date de naissance a été ajouté à la page `/signature-salarie/` pour sécuriser l'accès aux documents de signature électronique.
|
||||||
|
|
||||||
|
### Fonctionnement
|
||||||
|
|
||||||
|
Lorsqu'un salarié clique sur le lien de signature reçu par email :
|
||||||
|
|
||||||
|
1. 🔒 Un **modal de sécurité moderne** s'affiche automatiquement
|
||||||
|
2. 📅 Le salarié doit **saisir sa date de naissance**
|
||||||
|
3. ✅ Le système vérifie dans la base de données (table `salaries`)
|
||||||
|
4. 📝 Si la date correspond, le **formulaire DocuSeal s'affiche**
|
||||||
|
5. ❌ Sinon, un message d'erreur apparaît et le formulaire reste bloqué
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Interface utilisateur
|
||||||
|
|
||||||
|
### Modal de vérification
|
||||||
|
|
||||||
|
- **Design moderne** avec gradient bleu et animations fluides
|
||||||
|
- **Header** avec icône Shield et titre explicite
|
||||||
|
- **Input date** avec validation HTML5
|
||||||
|
- **Messages d'erreur** clairs et animés
|
||||||
|
- **Footer informatif** sur la protection des données
|
||||||
|
- **Bouton désactivé** jusqu'à saisie d'une date valide
|
||||||
|
- **Loader animé** pendant la vérification
|
||||||
|
|
||||||
|
### Expérience utilisateur
|
||||||
|
|
||||||
|
- 🎯 **Simple** : Un seul champ à remplir
|
||||||
|
- 🚀 **Rapide** : Vérification en moins d'une seconde
|
||||||
|
- 💬 **Pédagogique** : Messages d'aide après 2 tentatives échouées
|
||||||
|
- 🎭 **Animations** : Entrées/sorties fluides pour une UX moderne
|
||||||
|
- 📱 **Responsive** : Adapté mobile et desktop
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Architecture technique
|
||||||
|
|
||||||
|
### Fichiers créés
|
||||||
|
|
||||||
|
#### 1. **API de vérification**
|
||||||
|
```
|
||||||
|
app/api/signature-salarie/verify-birthdate/route.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fonctionnalités :**
|
||||||
|
- ✅ Authentification via `docuseal_id`
|
||||||
|
- ✅ Recherche du contrat dans `cddu_contracts`
|
||||||
|
- ✅ Récupération du salarié via `employee_id`
|
||||||
|
- ✅ Vérification de la `date_naissance` dans table `salaries`
|
||||||
|
- ✅ Comparaison des dates (format normalisé YYYY-MM-DD)
|
||||||
|
- ✅ Gestion des cas edge (date manquante = acceptation)
|
||||||
|
- ✅ Logs détaillés pour debug
|
||||||
|
|
||||||
|
**Endpoint :**
|
||||||
|
```
|
||||||
|
POST /api/signature-salarie/verify-birthdate
|
||||||
|
```
|
||||||
|
|
||||||
|
**Body :**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"docuseal_id": "abc123xyz",
|
||||||
|
"birthdate": "1990-05-15"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Réponses :**
|
||||||
|
```json
|
||||||
|
// Succès
|
||||||
|
{
|
||||||
|
"verified": true,
|
||||||
|
"message": "Date de naissance vérifiée"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Échec
|
||||||
|
{
|
||||||
|
"verified": false,
|
||||||
|
"error": "Date de naissance incorrecte"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. **Composant Modal**
|
||||||
|
```
|
||||||
|
app/signature-salarie/BirthdateVerificationModal.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
**Props :**
|
||||||
|
```typescript
|
||||||
|
interface BirthdateVerificationModalProps {
|
||||||
|
docuseal_id: string;
|
||||||
|
onVerified: () => void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features :**
|
||||||
|
- ✅ Input type="date" avec validation HTML5
|
||||||
|
- ✅ Limite date max = aujourd'hui
|
||||||
|
- ✅ Gestion des états (loading, error, success)
|
||||||
|
- ✅ Compteur de tentatives
|
||||||
|
- ✅ Message d'aide après 2 échecs
|
||||||
|
- ✅ Animations Tailwind (animate-in, fade-in, etc.)
|
||||||
|
- ✅ Design avec gradient et icônes Lucide
|
||||||
|
|
||||||
|
#### 3. **Intégration dans la page**
|
||||||
|
```
|
||||||
|
app/signature-salarie/SignatureSalarieContent.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
**Modifications :**
|
||||||
|
- ✅ Import du composant `BirthdateVerificationModal`
|
||||||
|
- ✅ Ajout de l'état `isVerified` (défaut: `false`)
|
||||||
|
- ✅ Affichage conditionnel du modal (`!isVerified`)
|
||||||
|
- ✅ Callback `onVerified` pour fermer le modal
|
||||||
|
- ✅ Le formulaire DocuSeal ne se charge que si vérifié
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Flux de données
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Utilisateur arrive sur /signature-salarie/?docuseal_id=xxx
|
||||||
|
↓
|
||||||
|
2. Page charge avec modal affiché (isVerified = false)
|
||||||
|
↓
|
||||||
|
3. Utilisateur saisit sa date de naissance
|
||||||
|
↓
|
||||||
|
4. Click sur "Vérifier et accéder au document"
|
||||||
|
↓
|
||||||
|
5. Appel API : POST /api/signature-salarie/verify-birthdate
|
||||||
|
↓
|
||||||
|
6. API cherche le contrat via docuseal_id
|
||||||
|
↓
|
||||||
|
7. API récupère le salarié via employee_id
|
||||||
|
↓
|
||||||
|
8. API compare date saisie vs date_naissance en base
|
||||||
|
↓
|
||||||
|
9a. Si match → { verified: true }
|
||||||
|
↓
|
||||||
|
Modal se ferme (isVerified = true)
|
||||||
|
↓
|
||||||
|
Formulaire DocuSeal s'affiche
|
||||||
|
|
||||||
|
9b. Si pas de match → { verified: false, error: "..." }
|
||||||
|
↓
|
||||||
|
Message d'erreur affiché
|
||||||
|
↓
|
||||||
|
Input réinitialisé
|
||||||
|
↓
|
||||||
|
Tentatives incrémentées
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Cas d'usage
|
||||||
|
|
||||||
|
### Scénario 1 : Date correcte
|
||||||
|
```
|
||||||
|
1. Salarié reçoit email avec lien
|
||||||
|
2. Clique sur le lien
|
||||||
|
3. Modal s'affiche
|
||||||
|
4. Saisit sa vraie date de naissance : "15/05/1990"
|
||||||
|
5. Clique sur "Vérifier"
|
||||||
|
6. ✅ Modal se ferme
|
||||||
|
7. ✅ Formulaire DocuSeal apparaît
|
||||||
|
8. ✅ Peut signer son contrat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scénario 2 : Date incorrecte (1ère tentative)
|
||||||
|
```
|
||||||
|
1. Salarié saisit une mauvaise date : "01/01/2000"
|
||||||
|
2. Clique sur "Vérifier"
|
||||||
|
3. ❌ Erreur : "Date de naissance incorrecte"
|
||||||
|
4. Input se vide
|
||||||
|
5. Peut réessayer
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scénario 3 : Date incorrecte (3e tentative)
|
||||||
|
```
|
||||||
|
1. Salarié échoue 2 fois
|
||||||
|
2. Échoue une 3e fois
|
||||||
|
3. ❌ Message : "Date de naissance incorrecte"
|
||||||
|
4. ℹ️ Message additionnel : "Besoin d'aide ? Contactez-nous à paie@odentas.fr"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scénario 4 : Date manquante en base
|
||||||
|
```
|
||||||
|
1. API détecte que date_naissance = null dans salaries
|
||||||
|
2. ⚠️ Log : "Date de naissance non renseignée"
|
||||||
|
3. ✅ Accepte quand même (pour ne pas bloquer)
|
||||||
|
4. ✅ Modal se ferme
|
||||||
|
5. ℹ️ À corriger dans la base pour la prochaine fois
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Sécurité
|
||||||
|
|
||||||
|
### Protection mise en place
|
||||||
|
|
||||||
|
| Aspect | Détail |
|
||||||
|
|--------|--------|
|
||||||
|
| **Authentification** | Via `docuseal_id` (slug unique et secret) |
|
||||||
|
| **Vérification** | Comparaison stricte des dates |
|
||||||
|
| **Données sensibles** | Date de naissance jamais exposée au client |
|
||||||
|
| **Service Role** | Accès base de données avec droits admin |
|
||||||
|
| **Logs** | Toutes les tentatives sont loggées |
|
||||||
|
| **Limite** | Pas de limite de tentatives (volontaire) |
|
||||||
|
|
||||||
|
### Points d'attention
|
||||||
|
|
||||||
|
⚠️ **Données manquantes** : Si un salarié n'a pas de `date_naissance` en base, il peut quand même accéder (pour éviter de bloquer des signatures légitimes).
|
||||||
|
|
||||||
|
💡 **Recommandation** : S'assurer que tous les salariés ont une date de naissance renseignée dans la table `salaries`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Base de données
|
||||||
|
|
||||||
|
### Tables utilisées
|
||||||
|
|
||||||
|
#### `cddu_contracts`
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
employee_id,
|
||||||
|
salarie_email,
|
||||||
|
docuseal_employee_slug
|
||||||
|
FROM cddu_contracts
|
||||||
|
WHERE docuseal_employee_slug = 'abc123';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `salaries`
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
prenom,
|
||||||
|
nom,
|
||||||
|
date_naissance
|
||||||
|
FROM salaries
|
||||||
|
WHERE id = '<employee_id>';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Champ requis
|
||||||
|
|
||||||
|
| Table | Colonne | Type | Requis | Remarques |
|
||||||
|
|-------|---------|------|--------|-----------|
|
||||||
|
| `cddu_contracts` | `docuseal_employee_slug` | `text` | ✅ | Slug DocuSeal unique |
|
||||||
|
| `cddu_contracts` | `employee_id` | `uuid` | ✅ | FK vers salaries |
|
||||||
|
| `salaries` | `date_naissance` | `date` | ⚠️ | Si null, accepte quand même |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Tests
|
||||||
|
|
||||||
|
### Test manuel
|
||||||
|
|
||||||
|
1. **Créer un contrat test**
|
||||||
|
- Avec un salarié ayant une date de naissance connue
|
||||||
|
|
||||||
|
2. **Générer une signature DocuSeal**
|
||||||
|
- Récupérer le `docuseal_employee_slug`
|
||||||
|
|
||||||
|
3. **Accéder à l'URL**
|
||||||
|
```
|
||||||
|
https://paie.odentas.fr/signature-salarie/?docuseal_id=<slug>
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Tester différents scénarios**
|
||||||
|
- ✅ Date correcte
|
||||||
|
- ❌ Date incorrecte
|
||||||
|
- 📅 Date future (bloquée par HTML5)
|
||||||
|
- 🔄 Plusieurs tentatives
|
||||||
|
|
||||||
|
### Test API (cURL)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST https://paie.odentas.fr/api/signature-salarie/verify-birthdate \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"docuseal_id": "abc123xyz",
|
||||||
|
"birthdate": "1990-05-15"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Réponse attendue :**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"verified": true,
|
||||||
|
"message": "Date de naissance vérifiée"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Logs
|
||||||
|
|
||||||
|
### Console API
|
||||||
|
|
||||||
|
```
|
||||||
|
=== API Vérification Date de Naissance Salarié ===
|
||||||
|
🔍 Vérification pour docuseal_id: abc123xyz
|
||||||
|
📄 Contrat trouvé: { employee_id: '...', salarie_email: '...' }
|
||||||
|
👤 Salarié trouvé: { prenom: 'Jean', nom: 'Dupont', date_naissance: '1990-05-15' }
|
||||||
|
📅 Comparaison dates: { db: '1990-05-15', input: '1990-05-15', match: true }
|
||||||
|
✅ Date de naissance vérifiée avec succès
|
||||||
|
```
|
||||||
|
|
||||||
|
### Console Frontend
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// En cas d'erreur
|
||||||
|
console.error('Erreur lors de la vérification:', err);
|
||||||
|
|
||||||
|
// L'état du composant change
|
||||||
|
isVerifying: false → true → false
|
||||||
|
error: null → "Date de naissance incorrecte"
|
||||||
|
attempts: 0 → 1 → 2 → 3...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Déploiement
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
|
||||||
|
- ✅ Colonne `docuseal_employee_slug` existe dans `cddu_contracts`
|
||||||
|
- ✅ Colonne `date_naissance` existe dans `salaries`
|
||||||
|
- ✅ Relation FK `employee_id` configurée
|
||||||
|
|
||||||
|
### Checklist
|
||||||
|
|
||||||
|
- [x] API créée : `/api/signature-salarie/verify-birthdate/route.ts`
|
||||||
|
- [x] Composant modal créé : `BirthdateVerificationModal.tsx`
|
||||||
|
- [x] Intégration dans : `SignatureSalarieContent.tsx`
|
||||||
|
- [ ] Tests manuels effectués
|
||||||
|
- [ ] Vérifier que les salariés ont des dates de naissance
|
||||||
|
- [ ] Déployer sur Vercel
|
||||||
|
- [ ] Tester en production avec un vrai contrat
|
||||||
|
|
||||||
|
### Déploiement
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Les fichiers sont déjà prêts
|
||||||
|
# Il suffit de commit et push
|
||||||
|
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: Ajout vérification date de naissance signature salarié"
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
# Vercel déploie automatiquement
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Design
|
||||||
|
|
||||||
|
### Couleurs utilisées
|
||||||
|
|
||||||
|
- **Primary** : `from-blue-600 to-blue-700` (gradient)
|
||||||
|
- **Hover** : `from-blue-700 to-blue-800`
|
||||||
|
- **Background info** : `bg-blue-50` / `border-blue-200`
|
||||||
|
- **Error** : `bg-red-50` / `text-red-900`
|
||||||
|
- **Text** : `text-gray-700` / `text-gray-900`
|
||||||
|
|
||||||
|
### Icônes (Lucide)
|
||||||
|
|
||||||
|
- 🛡️ `Shield` : Sécurité
|
||||||
|
- 📅 `Calendar` : Date
|
||||||
|
- ⚠️ `AlertCircle` : Erreur
|
||||||
|
- ⏳ `Loader2` : Chargement (animate-spin)
|
||||||
|
|
||||||
|
### Animations
|
||||||
|
|
||||||
|
- `animate-in fade-in duration-200` : Apparition modal
|
||||||
|
- `animate-in zoom-in-95 duration-300` : Entrée carte
|
||||||
|
- `animate-in slide-in-from-top-2 duration-200` : Message erreur
|
||||||
|
- `animate-spin` : Loader
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Maintenance
|
||||||
|
|
||||||
|
### Problèmes possibles
|
||||||
|
|
||||||
|
| Problème | Cause | Solution |
|
||||||
|
|----------|-------|----------|
|
||||||
|
| Date toujours refusée | Format date incorrect | Vérifier format en base (YYYY-MM-DD) |
|
||||||
|
| Salarié introuvable | `employee_id` incorrect | Vérifier la relation FK |
|
||||||
|
| Slug invalide | `docuseal_employee_slug` null | Vérifier l'intégration DocuSeal |
|
||||||
|
| Modal ne se ferme pas | Callback non appelé | Vérifier `onVerified()` |
|
||||||
|
|
||||||
|
### Amélioration future
|
||||||
|
|
||||||
|
- [ ] Ajouter un captcha après X tentatives
|
||||||
|
- [ ] Envoyer un email après 5 échecs
|
||||||
|
- [ ] Logger les tentatives dans une table dédiée
|
||||||
|
- [ ] Ajouter une vérification supplémentaire (email ou code SMS)
|
||||||
|
- [ ] Mode "debug" pour bypasser en développement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 Support
|
||||||
|
|
||||||
|
En cas de problème, le salarié voit :
|
||||||
|
|
||||||
|
> Besoin d'aide ? Contactez-nous à [paie@odentas.fr](mailto:paie@odentas.fr)
|
||||||
|
|
||||||
|
Le support peut :
|
||||||
|
1. Vérifier que la date de naissance est correcte en base
|
||||||
|
2. Vérifier les logs CloudWatch ou Vercel
|
||||||
|
3. Tester manuellement l'API avec cURL
|
||||||
|
4. Envoyer un nouveau lien si nécessaire
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Fonctionnalité ajoutée le 15 octobre 2025*
|
||||||
|
*Sécurisation des signatures électroniques - Odentas Espace Paie*
|
||||||
105
SIGNATURE_VERIFICATION_SUMMARY.md
Normal file
105
SIGNATURE_VERIFICATION_SUMMARY.md
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# ✅ Vérification Date de Naissance - Signature Salarié
|
||||||
|
|
||||||
|
## 🎯 Ce qui a été ajouté
|
||||||
|
|
||||||
|
Un **modal de sécurité moderne** qui demande la date de naissance avant d'accéder au formulaire de signature DocuSeal.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Fichiers créés
|
||||||
|
|
||||||
|
### 1. API de vérification
|
||||||
|
```
|
||||||
|
app/api/signature-salarie/verify-birthdate/route.ts
|
||||||
|
```
|
||||||
|
- Vérifie la date de naissance dans la table `salaries`
|
||||||
|
- Utilise le `docuseal_id` pour retrouver le salarié
|
||||||
|
|
||||||
|
### 2. Composant modal
|
||||||
|
```
|
||||||
|
app/signature-salarie/BirthdateVerificationModal.tsx
|
||||||
|
```
|
||||||
|
- Modal moderne avec gradient bleu
|
||||||
|
- Input de date avec validation
|
||||||
|
- Messages d'erreur animés
|
||||||
|
- Design responsive
|
||||||
|
|
||||||
|
### 3. Intégration
|
||||||
|
```
|
||||||
|
app/signature-salarie/SignatureSalarieContent.tsx (modifié)
|
||||||
|
```
|
||||||
|
- Ajout de l'état `isVerified`
|
||||||
|
- Affichage du modal au chargement
|
||||||
|
- Blocage du formulaire DocuSeal jusqu'à vérification
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Aperçu du modal
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ 🛡️ Vérification de sécurité │
|
||||||
|
│ Protection de vos données │
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ℹ️ Pour accéder à votre document │
|
||||||
|
│ veuillez confirmer votre date │
|
||||||
|
│ de naissance. │
|
||||||
|
│ │
|
||||||
|
│ 📅 Date de naissance │
|
||||||
|
│ ┌───────────────────────────────────┐ │
|
||||||
|
│ │ jj/mm/aaaa │ │
|
||||||
|
│ └───────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌───────────────────────────────────┐ │
|
||||||
|
│ │ 🛡️ Vérifier et accéder au document│ │
|
||||||
|
│ └───────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ 🔒 Vos données sont protégées... │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Flux d'utilisation
|
||||||
|
|
||||||
|
1. Salarié clique sur lien email
|
||||||
|
2. Page charge avec **modal affiché**
|
||||||
|
3. Salarié saisit sa date de naissance
|
||||||
|
4. Click sur "Vérifier"
|
||||||
|
5. ✅ Si correcte → Modal disparaît, formulaire DocuSeal apparaît
|
||||||
|
6. ❌ Si incorrecte → Message d'erreur, peut réessayer
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Vérification technique
|
||||||
|
|
||||||
|
**Base de données :**
|
||||||
|
- Table : `salaries`
|
||||||
|
- Colonne : `date_naissance`
|
||||||
|
- Type : `date`
|
||||||
|
|
||||||
|
**Lookup :**
|
||||||
|
1. `docuseal_id` → `cddu_contracts.docuseal_employee_slug`
|
||||||
|
2. → `cddu_contracts.employee_id`
|
||||||
|
3. → `salaries.id`
|
||||||
|
4. → Compare `salaries.date_naissance`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎉 C'est prêt !
|
||||||
|
|
||||||
|
Le système est opérationnel. À tester en accédant à :
|
||||||
|
```
|
||||||
|
https://paie.odentas.fr/signature-salarie/?docuseal_id=<slug>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Documentation complète
|
||||||
|
|
||||||
|
Voir : `SIGNATURE_SALARIE_BIRTHDATE_VERIFICATION.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Ajouté le 15 octobre 2025*
|
||||||
139
app/api/signature-salarie/verify-birthdate/route.ts
Normal file
139
app/api/signature-salarie/verify-birthdate/route.ts
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { createSbServiceRole } from '@/lib/supabaseServer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/signature-salarie/verify-birthdate
|
||||||
|
*
|
||||||
|
* Vérifie la date de naissance d'un salarié avant de lui permettre d'accéder à la signature
|
||||||
|
*
|
||||||
|
* Body: {
|
||||||
|
* docuseal_id: string,
|
||||||
|
* birthdate: string (format YYYY-MM-DD)
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
console.log('=== API Vérification Date de Naissance Salarié ===');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { docuseal_id, birthdate } = await request.json();
|
||||||
|
|
||||||
|
// Validation des paramètres
|
||||||
|
if (!docuseal_id || !birthdate) {
|
||||||
|
console.error('❌ Paramètres manquants:', { docuseal_id, birthdate });
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Paramètres manquants', verified: false },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔍 Vérification pour docuseal_id:', docuseal_id);
|
||||||
|
|
||||||
|
// Créer le client Supabase avec service role
|
||||||
|
const supabase = createSbServiceRole();
|
||||||
|
|
||||||
|
// 1. Récupérer l'email du salarié depuis la soumission DocuSeal
|
||||||
|
// On cherche dans cddu_contracts pour trouver le contrat lié au slug DocuSeal
|
||||||
|
const { data: contract, error: contractError } = await supabase
|
||||||
|
.from('cddu_contracts')
|
||||||
|
.select('employee_id, salarie_email')
|
||||||
|
.eq('docuseal_employee_slug', docuseal_id)
|
||||||
|
.maybeSingle();
|
||||||
|
|
||||||
|
if (contractError) {
|
||||||
|
console.error('❌ Erreur lors de la récupération du contrat:', contractError);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Erreur lors de la vérification', verified: false },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!contract) {
|
||||||
|
console.error('❌ Aucun contrat trouvé pour docuseal_id:', docuseal_id);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Document introuvable', verified: false },
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('📄 Contrat trouvé:', {
|
||||||
|
employee_id: contract.employee_id,
|
||||||
|
salarie_email: contract.salarie_email
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Récupérer la date de naissance du salarié depuis la table salaries
|
||||||
|
const { data: salarie, error: salarieError } = await supabase
|
||||||
|
.from('salaries')
|
||||||
|
.select('date_naissance, prenom, nom')
|
||||||
|
.eq('id', contract.employee_id)
|
||||||
|
.maybeSingle();
|
||||||
|
|
||||||
|
if (salarieError) {
|
||||||
|
console.error('❌ Erreur lors de la récupération du salarié:', salarieError);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Erreur lors de la vérification', verified: false },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!salarie) {
|
||||||
|
console.error('❌ Salarié introuvable pour employee_id:', contract.employee_id);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Salarié introuvable', verified: false },
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!salarie.date_naissance) {
|
||||||
|
console.warn('⚠️ Date de naissance non renseignée pour le salarié');
|
||||||
|
// Si pas de date de naissance en base, on accepte quand même (pour ne pas bloquer)
|
||||||
|
return NextResponse.json({
|
||||||
|
verified: true,
|
||||||
|
message: 'Vérification acceptée (date de naissance non renseignée)'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('👤 Salarié trouvé:', {
|
||||||
|
prenom: salarie.prenom,
|
||||||
|
nom: salarie.nom,
|
||||||
|
date_naissance: salarie.date_naissance
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Comparer les dates de naissance
|
||||||
|
// Normaliser les dates pour la comparaison (format YYYY-MM-DD)
|
||||||
|
const dbBirthdate = new Date(salarie.date_naissance).toISOString().split('T')[0];
|
||||||
|
const inputBirthdate = new Date(birthdate).toISOString().split('T')[0];
|
||||||
|
|
||||||
|
console.log('📅 Comparaison dates:', {
|
||||||
|
db: dbBirthdate,
|
||||||
|
input: inputBirthdate,
|
||||||
|
match: dbBirthdate === inputBirthdate
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dbBirthdate === inputBirthdate) {
|
||||||
|
console.log('✅ Date de naissance vérifiée avec succès');
|
||||||
|
return NextResponse.json({
|
||||||
|
verified: true,
|
||||||
|
message: 'Date de naissance vérifiée'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('❌ Date de naissance incorrecte');
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: 'Date de naissance incorrecte',
|
||||||
|
verified: false
|
||||||
|
},
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erreur lors de la vérification de la date de naissance:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: 'Erreur serveur lors de la vérification',
|
||||||
|
verified: false
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
163
app/signature-salarie/BirthdateVerificationModal.tsx
Normal file
163
app/signature-salarie/BirthdateVerificationModal.tsx
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Calendar, Shield, AlertCircle, Loader2 } from "lucide-react";
|
||||||
|
|
||||||
|
interface BirthdateVerificationModalProps {
|
||||||
|
docuseal_id: string;
|
||||||
|
onVerified: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function BirthdateVerificationModal({
|
||||||
|
docuseal_id,
|
||||||
|
onVerified
|
||||||
|
}: BirthdateVerificationModalProps) {
|
||||||
|
const [birthdate, setBirthdate] = useState("");
|
||||||
|
const [isVerifying, setIsVerifying] = useState(false);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [attempts, setAttempts] = useState(0);
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setError(null);
|
||||||
|
setIsVerifying(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/signature-salarie/verify-birthdate', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
docuseal_id,
|
||||||
|
birthdate
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.verified) {
|
||||||
|
// Succès ! On ferme le modal
|
||||||
|
onVerified();
|
||||||
|
} else {
|
||||||
|
// Échec de vérification
|
||||||
|
setAttempts(prev => prev + 1);
|
||||||
|
setError(data.error || 'Date de naissance incorrecte');
|
||||||
|
setBirthdate("");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Erreur lors de la vérification:', err);
|
||||||
|
setError('Erreur lors de la vérification. Veuillez réessayer.');
|
||||||
|
} finally {
|
||||||
|
setIsVerifying(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
|
||||||
|
<div className="w-full max-w-md bg-white rounded-2xl shadow-2xl border border-gray-200 overflow-hidden animate-in zoom-in-95 duration-300">
|
||||||
|
{/* Header avec gradient */}
|
||||||
|
<div className="bg-gradient-to-r from-blue-600 to-blue-700 px-6 py-5">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="p-2 bg-white/20 rounded-lg backdrop-blur-sm">
|
||||||
|
<Shield className="w-6 h-6 text-white" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2 className="text-xl font-semibold text-white">
|
||||||
|
Vérification de sécurité
|
||||||
|
</h2>
|
||||||
|
<p className="text-blue-100 text-sm mt-0.5">
|
||||||
|
Protection de vos données personnelles
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Corps du modal */}
|
||||||
|
<form onSubmit={handleSubmit} className="p-6 space-y-5">
|
||||||
|
{/* Message d'explication */}
|
||||||
|
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||||
|
<p className="text-sm text-blue-900 leading-relaxed">
|
||||||
|
Pour accéder à votre document de signature, veuillez confirmer votre identité en renseignant votre <strong>date de naissance</strong>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Input date de naissance */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<label
|
||||||
|
htmlFor="birthdate"
|
||||||
|
className="block text-sm font-medium text-gray-700 flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<Calendar className="w-4 h-4 text-gray-500" />
|
||||||
|
Date de naissance
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="birthdate"
|
||||||
|
type="date"
|
||||||
|
value={birthdate}
|
||||||
|
onChange={(e) => {
|
||||||
|
setBirthdate(e.target.value);
|
||||||
|
setError(null);
|
||||||
|
}}
|
||||||
|
max={new Date().toISOString().split('T')[0]}
|
||||||
|
required
|
||||||
|
disabled={isVerifying}
|
||||||
|
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all disabled:bg-gray-100 disabled:cursor-not-allowed text-base"
|
||||||
|
placeholder="jj/mm/aaaa"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Message d'erreur */}
|
||||||
|
{error && (
|
||||||
|
<div className="bg-red-50 border border-red-200 rounded-lg p-3 animate-in slide-in-from-top-2 duration-200">
|
||||||
|
<div className="flex items-start gap-2">
|
||||||
|
<AlertCircle className="w-5 h-5 text-red-600 flex-shrink-0 mt-0.5" />
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-medium text-red-900">{error}</p>
|
||||||
|
{attempts >= 2 && (
|
||||||
|
<p className="text-xs text-red-700 mt-1">
|
||||||
|
Besoin d'aide ? Contactez-nous à{' '}
|
||||||
|
<a
|
||||||
|
href="mailto:paie@odentas.fr"
|
||||||
|
className="underline hover:text-red-900"
|
||||||
|
>
|
||||||
|
paie@odentas.fr
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Bouton de validation */}
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={isVerifying || !birthdate}
|
||||||
|
className="w-full bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2 shadow-lg hover:shadow-xl"
|
||||||
|
>
|
||||||
|
{isVerifying ? (
|
||||||
|
<>
|
||||||
|
<Loader2 className="w-5 h-5 animate-spin" />
|
||||||
|
Vérification en cours...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Shield className="w-5 h-5" />
|
||||||
|
Vérifier et accéder au document
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Footer avec info */}
|
||||||
|
<div className="pt-4 border-t border-gray-200">
|
||||||
|
<p className="text-xs text-gray-500 text-center leading-relaxed">
|
||||||
|
🔒 Vos données sont protégées et ne sont utilisées que pour vérifier votre identité.
|
||||||
|
Cette étape garantit que seul vous pouvez accéder à votre contrat.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -5,12 +5,14 @@ import { useSearchParams } from "next/navigation";
|
||||||
import { AlertTriangle } from "lucide-react";
|
import { AlertTriangle } from "lucide-react";
|
||||||
import { usePageTitle } from "@/hooks/usePageTitle";
|
import { usePageTitle } from "@/hooks/usePageTitle";
|
||||||
import Script from "next/script";
|
import Script from "next/script";
|
||||||
|
import BirthdateVerificationModal from "./BirthdateVerificationModal";
|
||||||
|
|
||||||
export default function SignatureSalarieContent() {
|
export default function SignatureSalarieContent() {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const docusealId = searchParams.get("docuseal_id");
|
const docusealId = searchParams.get("docuseal_id");
|
||||||
const [showError, setShowError] = useState(false);
|
const [showError, setShowError] = useState(false);
|
||||||
const [docusealLoaded, setDocusealLoaded] = useState(false);
|
const [docusealLoaded, setDocusealLoaded] = useState(false);
|
||||||
|
const [isVerified, setIsVerified] = useState(false);
|
||||||
|
|
||||||
// Définir le titre de la page
|
// Définir le titre de la page
|
||||||
usePageTitle("Signature électronique");
|
usePageTitle("Signature électronique");
|
||||||
|
|
@ -107,6 +109,14 @@ export default function SignatureSalarieContent() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* Modal de vérification de la date de naissance */}
|
||||||
|
{!isVerified && docusealId && (
|
||||||
|
<BirthdateVerificationModal
|
||||||
|
docuseal_id={docusealId}
|
||||||
|
onVerified={() => setIsVerified(true)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Charger le script DocuSeal */}
|
{/* Charger le script DocuSeal */}
|
||||||
<Script
|
<Script
|
||||||
src="https://cdn.docuseal.com/js/form.js"
|
src="https://cdn.docuseal.com/js/form.js"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue