- Remplacer PDFMonkey par Gotenberg (auto-hébergé sur VPS)
- Créer template Handlebars pour contrats (lib/templates/contract.hbs)
- Créer formateur de données (lib/contract-data-formatter.ts)
- Ajouter helpers Handlebars pour conditions et transformations
- Mettre à jour API route generate-pdf pour utiliser Gotenberg
- Ajouter GOTENBERG_URL dans .env.local (http://localhost:3001 pour dev)
- Créer script tunnel-gotenberg.sh pour dev local
- Ajouter documentation MIGRATION_GOTENBERG.md
Avantages:
- Souveraineté des données (pas d'API externe)
- Performance (génération locale)
- Coût (0€ vs abonnement PDFMonkey)
- Sécurité (Gotenberg non exposé publiquement)
- Ajout helpers Handlebars pour remplacer filtres Liquid
- Conversion template CDDU de Liquid vers Handlebars
- Nouvelle API route /api/generate-contract-pdf pour Gotenberg
- Configuration Docker Compose pour auto-héberger Gotenberg
- Documentation complète de migration
- Variables d'environnement exemple
Note: Le bouton 'Créer PDF' utilise encore PDFMonkey.
Pour activer Gotenberg, modifier l'appel dans ContractEditor.tsx
Problème: Le système supposait l'année basée sur le contexte, ce qui causait des erreurs.
Solution:
- Ajout de formatDateFrWithYear() pour retourner DD/MM/YYYY
- Le calendrier DatePickerCalendar retourne maintenant des dates avec l'année complète
- parseFrenchedDate() supporte maintenant DD/MM/YYYY et DD/MM
- Si l'année est dans la date (DD/MM/YYYY), elle est utilisée directement
- Plus besoin de supposer l'année basée sur oct/nov/déc -> jan/fev/mar
- Les dates de début et fin se calculent correctement à partir des vraies dates ISO
Cela garantit que:
1. Les dates en janvier 2026 restent bien en 2026
2. Les champs date début/date fin se remplissent avec les bonnes années
3. Aucune supposition erronée n'est faite
Problème: Quand on sélectionnait des dates en janvier 2026 depuis un contrat en décembre 2025, les dates étaient converties en janvier 2025.
Solution: Amélioration de la fonction parseFrenchedDate pour détecter automatiquement si une date est dans l'année suivante:
- Si le mois de la date est janvier/février/mars (1-3)
- ET que le mois du contexte (dateDebut/dateFin) est oct/nov/déc (10-12)
- Alors on utilise l'année suivante
Exemple: Contrat du 15/12/2025 au 20/01/2026
- Les dates de janvier seront correctement converties en 2026 au lieu de 2025
- Ajout du type 'contract-note-added' dans le système email universel v2
- Email automatique envoyé à paie@odentas.fr quand un client ajoute une note
- Fonctionne pour tous les types de contrats (CDDU mono, multi, RG)
- Email contient: organisation, code employeur, n° contrat, utilisateur, contenu note
- Lien direct vers le contrat dans l'interface staff
- Gestion des erreurs: note créée même si email échoue
- Documentation complète dans NOTIFICATION_NOTES_CONTRAT.md
- Ajout de la création d'utilisateurs staff (STAFF et SUPER_STAFF)
- Email de notification avec lien d'activation (paie.odentas.fr)
- API de révocation/restauration des utilisateurs staff
- Sécurité: SUPER_STAFF ne peut pas être révoqué
- Sécurité: Seul SUPER_STAFF peut créer d'autres SUPER_STAFF
- Tableau des utilisateurs clients avec filtres (organisation, niveau, statut)
- Tri dynamique sur toutes les colonnes (prénom, email, organisation, niveau, date)
- Utilisation du client admin pour contourner les RLS
- Interface avec recherche et filtres avancés
- Ajout de 2 nouveaux champs de texte dans ContractEditor.tsx
- Sauvegarde des champs autreprecision_duree et autreprecision_salaire dans Supabase
- Mise à jour des types ContratCDDUData avec les nouveaux champs
- Envoi des données à PDFMonkey via generate-pdf et generate-pdf-test
- Les champs sont disponibles dans l'interface staff/contrats/[id]
- Créé sendInvitationWithActivationEmail() pour unifier les invitations
- Modifié /api/staff/users/invite pour utiliser generateLink + email
- Modifié /api/access/nouveau pour envoyer email d'activation
- Modifié /api/access POST pour remplacer pending_invites par système direct
- Template account-activation mis à jour :
* Titre 'Activez votre compte'
* Encart avec infos : invitant (statut), organisation, niveau d'accès
* Message de contact formaté comme autres emails
* Renommage 'Odentas Paie' → 'Espace Paie Odentas'
- Fix page /activate : délai 100ms pour hash fragment + redirection 1s
- Liens d'activation forcés vers paie.odentas.fr (tests depuis localhost)
- Messages UI cohérents : 'Invitation envoyée' au lieu de 'Compte créé'
- Créer route publique /api/public/invoices/[id]/download pour générer liens S3 à la volée
- Supprimer code employeur de l'infoCard pour factures studio
- Adapter texte bouton CTA (Télécharger vs Voir la facture)
- Rediriger vers page de téléchargement au lieu de l'Espace Paie pour clients studio
- Lien pré-signé S3 valable 15 minutes (suffisant pour téléchargement)
- Email employeur: ajout code_employeur, correction structure détails document
- Email salarié: ajout matricule, type contrat, profession, date début
- Séparation PDF préliminaire/signé (signed_pdf_s3_key) pour éviter timing issues
- Correction UI: grammaire et libellés conditionnels (avenant/contrat)
- Standardisation source notes: 'Client' au lieu de 'Espace Paie'
- Ajout note automatique pour paniers repas avec détails
- Calcul automatique total heures depuis modale jours de travail
- Migration SQL: ajout colonne signed_pdf_s3_key + migration données existantes
- Ajout sous-header total net à payer sur page virements-salaires
- Migration transfer_done_at pour tracking précis des virements
- Nouvelle page saisie tableau pour création factures en masse
- APIs bulk pour mise à jour dates signature et jours technicien
- API demande mandat SEPA avec email template
- Webhook DocuSeal pour signature contrats (mode TEST)
- Composants modaux détails et vérification PDF fiches de paie
- Upload/suppression/remplacement PDFs dans PayslipsGrid
- Amélioration affichage colonnes et filtres grilles contrats/paies
- Template email mandat SEPA avec sous-texte CTA
- APIs bulk facturation (création, update statut/date paiement)
- API clients sans facture pour période donnée
- Corrections calculs dates et montants avec auto-remplissage
- Programme de parrainage (referrals):
* Page /parrainage pour clients et staff
* API /api/referrals (GET, POST)
* Table referrals avec tracking complet
* Email template avec design orange/gradient
* Réductions: 30€ HT parrain, 20€ HT filleul
- Bannières promotionnelles (promo_banners):
* Page staff /staff/offres-promo pour gérer les bannières
* API /api/promo-banners (CRUD complet)
* Composant PromoBanner affiché en haut de l'espace
* Compte à rebours optionnel
* Customisation couleurs (gradient, texte, CTA)
- Déduplication des webhooks DocuSeal:
* Table webhook_events pour tracker les webhooks traités
* Helper checkAndMarkWebhookProcessed()
* Intégré dans docuseal-amendment et docuseal-amendment-completed
* Prévient les doublons d'emails
- Avenants signés:
* API GET /api/contrats/[id]/avenants
* Affichage des avenants signés dans DocumentsCard
* Génération d'URLs presignées S3
- Brouillons d'emails groupés:
* Table bulk_email_drafts pour sauvegarder les brouillons
* Template HTML bulk-email-template.html
- Améliorations ContractsGrid:
* Ajout filtre par production (dépendant de la structure)
* Tri par production
- Templates emails:
* referral-template.html (parrainage)
* bulk-email-template.html (emails groupés staff)
- Header: Ajout 3ème ligne de statut (Caisses & orga.) avec descriptions détaillées
- Tooltips: Affichage riche avec titre, voyant coloré et contenu markdown formaté
- Éditeur markdown: Nouveau composant RichTextEditor avec toolbar (gras, italique, liens, listes)
- Modal staff: StatusEditModal étendu avec onglets et éditeur de descriptions
- Migration: Ajout colonnes status_*_description dans maintenance_status
- API: Routes GET/PUT enrichies pour gérer les 9 champs de statut
- Navigation: Redirection /compte/securite → /securite (nouvelle page centralisée)
- Breadcrumb: Support contrats RG/CDDU multi + labels dynamiques salariés
- UX Documents: Bouton 'Nouvel onglet / Télécharger' au lieu de téléchargement forcé
- Contrats staff: Pagination paies (6/page) pour RG et CDDU multi-mois avec vue compacte
- PayslipCard: Bouton cliquable 'Ouvrir le PDF' pour accès direct aux bulletins
- Tous les clients repliés par défaut à l'ouverture du modal
- Boutons 'Tout replier' / 'Tout déplier' pour gérer tous les clients
- Section factures repliable avec bouton Afficher/Masquer
- Affichage résumé facture sélectionnée quand section repliée
- Nouveau client déplié automatiquement pour faciliter la saisie
- Améliore la lisibilité pour NAA avec nombreux clients
- Ajout bouton calculatrice avec gradient bleu-indigo
- Ajout bouton Minima avec gradient émeraude-teal et lien vers /minima-ccn
- Correction focus trap : autoriser liens target=_blank
- Ajout champs conditionnels panier repas (nombre, CCN, montant personnalisé)
- DatePickerCalendar : initialisation sur date de début contrat si pas de dates sélectionnées
- DatesQuantityModal : option 'Ne pas appliquer...' pour tous types (repré/répét/heures)
- DatesQuantityModal : adaptation texte selon type (représentations/répétitions/heures)
- DatesQuantityModal : champ 'Appliquer à toutes les dates' pour saisie rapide
- DatesQuantityModal : reset quantités quand option 'Ne pas appliquer' cochée
- DatesQuantityModal : aperçu sans détails quand option cochée
- Intégration durée répétitions dans formatage dates (3h ou 4h, avec 'chacun' si >1)
- Notification paiement salaires : nouvel email 'salary-transfer-payment-confirmation'
- Notification paiement salaires : API route /api/staff/virements-salaires/[id]/notify-payment-sent
- Notification paiement salaires : modal NotifyPaymentSentModal avec détails paiement
- Notification paiement salaires : tracking avec payment_notification_sent/sent_at
- Notification paiement salaires : affichage statut dans modal virements
- Template email : support detailsCardDisclaimer pour mentions légales
- Page publique /verify/[id] affichant Odentas Seal, TSA, certificat
- API /api/signatures/create-verification pour créer preuves
- Générateur PDF de preuve avec QR code (jsPDF)
- Hook useSignatureProof() pour intégration facile
- Table Supabase signature_verifications avec RLS public
- Page de test /test-signature-verification
- Documentation complète du système
Les signataires peuvent scanner le QR code ou visiter l'URL pour vérifier l'authenticité et l'intégrité de leur document signé.
- Ajout type 'production-declared' dans système email universel V2
- Template email avec infoCard et detailsCard
- Endpoint API /api/staff/productions/[id]/notify
- Bouton notification dans page staff/gestion-productions
- Modal de confirmation d'envoi
- Emails depuis organization_details (email_notifs, email_notifs_cc)
- Gestionnaire en dur: Renaud BREVIERE-ABRAHAM
- Ajout champs heures totales et minutes pour répétitions dans AmendmentDureeForm
- Intégration DatesQuantityModal pour saisie heures par jour de répétition
- Ajout type 'heures_repetitions' dans dateFormatter et DatesQuantityModal
- Correction envoi precisions_salaire à PDFMonkey pour les avenants
- Ajout champs séparés dates_representations_detail et dates_repetitions_detail
- Correction logique dates_repetitions_heures pour éviter doublons dans PDF
Webhook avenant completed:
- Récupération du slug depuis avenant.employee_docuseal_slug
- Évite l'extraction incorrecte depuis submission_url
- Corrige le 404 sur /signature-salarie pour les avenants signés
Avenant signature:
- Stockage de employee_docuseal_slug lors de la signature employeur
- Permet au salarié d'accéder à la page signature-salarie
Email employeur avenant:
- Prénom depuis organization_details.prenom_signataire
- Email vers organization_details.email_signature
- Message: 'Le document est disponible dans la fiche contrat'
- Ajout mise à jour cddu_contracts.avenant_signe = true
- Ajout cddu_contracts.avenant_signe_date avec timestamp
- Correction emails avenants (profession, infoCard employeur, URL salarié)
- Extraction docuseal_id depuis submission_url pour lien salarié
- Webhook avenant: utiliser les données du contrat depuis Supabase quand Lambda envoie 'Non spécifié'
- Ajout des types d'emails manquants dans EmailType (signature-request-employee-amendment, etc.)
- Les emails d'avenant seront maintenant loggés correctement dans email_logs
Note: Exécuter dans Supabase SQL:
ALTER TYPE email_type ADD VALUE IF NOT EXISTS 'signature-request-employee-amendment';
ALTER TYPE email_type ADD VALUE IF NOT EXISTS 'signature-request-salarie';
ALTER TYPE email_type ADD VALUE IF NOT EXISTS 'contribution-notification';
ALTER TYPE email_type ADD VALUE IF NOT EXISTS 'support-reply';
ALTER TYPE email_type ADD VALUE IF NOT EXISTS 'support-ticket-created';
ALTER TYPE email_type ADD VALUE IF NOT EXISTS 'support-ticket-reply';
ALTER TYPE email_type ADD VALUE IF NOT EXISTS 'contact-support';
✨ Nouvelles fonctionnalités
- Page de gestion des avenants (/staff/avenants)
- Page de détail d'un avenant (/staff/avenants/[id])
- Création d'avenants (objet, durée, rémunération)
- Génération automatique de PDF d'avenant
- Signature électronique via DocuSeal (employeur puis salarié)
- Changement manuel du statut d'un avenant
- Suppression d'avenants
🔧 Routes API
- POST /api/staff/amendments/create - Créer un avenant
- POST /api/staff/amendments/generate-pdf - Générer le PDF
- POST /api/staff/amendments/[id]/send-signature - Envoyer en signature
- POST /api/staff/amendments/[id]/change-status - Changer le statut
- POST /api/webhooks/docuseal-amendment - Webhook après signature employeur
- GET /api/signatures-electroniques/avenants - Liste des avenants en signature
📧 Système email universel v2
- Migration vers le système universel v2 pour les emails d'avenants
- Template 'signature-request-employee-amendment' pour salariés
- Insertion automatique dans DynamoDB pour la Lambda
- Mise à jour automatique du statut dans Supabase
🗄️ Base de données
- Table 'avenants' avec tous les champs (objet, durée, rémunération)
- Colonnes de notification (last_employer_notification_at, last_employee_notification_at)
- Liaison avec cddu_contracts
🎨 Composants
- AvenantDetailPageClient - Détail complet d'un avenant
- ChangeStatusModal - Changement de statut manuel
- SendSignatureModal - Envoi en signature
- DeleteAvenantModal - Suppression avec confirmation
- AvenantSuccessModal - Confirmation de création
📚 Documentation
- AVENANT_EMAIL_SYSTEM_MIGRATION.md - Guide complet de migration
🐛 Corrections
- Fix parsing défensif dans Lambda AWS
- Fix récupération des données depuis DynamoDB
- Fix statut MFA !== 'verified' au lieu de === 'unverified'
- Création de /lib/dateFormatter.ts avec utilities de parsing/formatting des dates
* Parsing format input (DD/MM) en ISO (YYYY-MM-DD)
* Groupement automatique des dates consécutives
* Formatage smart: 'le xx/xx' pour isolées, 'du xx/xx au xx/xx' pour plages
* Détection automatique du multi-mois
* Format pour PDFMonkey: 'le 12/10 ; du 14/10 au 17/10.'
- Création de /components/DatePickerCalendar.tsx
* Composant modal draggable et multi-select
* Prévisualisation du formatage PDFMonkey
* Limites de plage (minDate/maxDate)
* Warning multi-mois
* Retour des données au format input et pdfFormatted
- Intégration dans /components/contrats/NouveauCDDUForm.tsx
* Remplacement des inputs texte par calendriers pour dates_representations, dates_repetitions, jours_travail
* Auto-détection multi-mois et set isMultiMois = 'Oui' si >1 mois
* Pré-remplissage du calendrier lors de la duplication
* Affichage lisible du formatage smart
- Intégration dans /components/staff/contracts/ContractEditor.tsx
* Ajout du calendrier pour zone 'Dates travaillées'
* Affichage du format smart au lieu du texte brut
Closes #calendar-dates-picker