espace-paie-odentas/supabase/migrations/20251031_create_webhook_deduplication.sql
odentas 6170365fc0 feat: Ajout programme de parrainage, bannières promo, déduplication webhooks et avenants signés
- 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)
2025-10-31 23:31:53 +01:00

62 lines
2.5 KiB
PL/PgSQL

-- Migration: Création de la table de déduplication des webhooks
-- Date: 2025-10-31
-- Description: Empêcher les doublons d'emails quand DocuSeal envoie le même webhook plusieurs fois
-- Créer la table webhook_events
CREATE TABLE IF NOT EXISTS public.webhook_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Identifiant unique du webhook (submission_id + timestamp + event_type)
webhook_key TEXT NOT NULL UNIQUE,
-- Type de webhook (avenant_signature, contrat_signature, etc.)
event_type TEXT NOT NULL,
-- ID de la soumission DocuSeal
submission_id TEXT NOT NULL,
-- Données du webhook (pour debug)
payload JSONB,
-- Timestamps
processed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Index pour recherche rapide
CREATE INDEX IF NOT EXISTS idx_webhook_events_key ON public.webhook_events(webhook_key);
CREATE INDEX IF NOT EXISTS idx_webhook_events_submission_id ON public.webhook_events(submission_id);
CREATE INDEX IF NOT EXISTS idx_webhook_events_event_type ON public.webhook_events(event_type);
CREATE INDEX IF NOT EXISTS idx_webhook_events_created_at ON public.webhook_events(created_at DESC);
-- RLS (Row Level Security)
ALTER TABLE public.webhook_events ENABLE ROW LEVEL SECURITY;
-- Policy: Seul le service role peut écrire (les webhooks)
-- Pas besoin de lecture publique
CREATE POLICY "Service role can manage webhook_events"
ON public.webhook_events
FOR ALL
TO service_role
USING (true)
WITH CHECK (true);
-- Commentaires
COMMENT ON TABLE public.webhook_events IS 'Table de déduplication des webhooks pour éviter les doublons d''emails';
COMMENT ON COLUMN public.webhook_events.webhook_key IS 'Clé unique composée de submission_id + timestamp + event_type';
COMMENT ON COLUMN public.webhook_events.event_type IS 'Type de webhook: avenant_employer_signed, avenant_completed, etc.';
COMMENT ON COLUMN public.webhook_events.submission_id IS 'ID de la soumission DocuSeal';
COMMENT ON COLUMN public.webhook_events.payload IS 'Données brutes du webhook (pour debug)';
-- Nettoyage automatique des vieux événements (> 30 jours)
-- Créer une fonction pour nettoyer
CREATE OR REPLACE FUNCTION clean_old_webhook_events()
RETURNS void AS $$
BEGIN
DELETE FROM public.webhook_events
WHERE created_at < NOW() - INTERVAL '30 days';
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Commentaire sur la fonction
COMMENT ON FUNCTION clean_old_webhook_events() IS 'Nettoie les événements webhook de plus de 30 jours';