espace-paie-odentas/supabase/migrations/20251023_create_avenants_table.sql
odentas 5b72941777 feat: Système complet de gestion des avenants avec signatures électroniques
 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'
2025-10-23 15:30:11 +02:00

102 lines
3.9 KiB
PL/PgSQL

-- Migration: Création de la table avenants
-- Date: 2025-10-23
-- Description: Table pour gérer les avenants aux contrats de travail
-- Création de la table avenants
CREATE TABLE IF NOT EXISTS public.avenants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Référence au contrat
contract_id UUID NOT NULL REFERENCES public.cddu_contracts(id) ON DELETE CASCADE,
-- Informations de l'avenant
numero_avenant TEXT NOT NULL, -- Ex: "AVE-001", "AVE-002"...
date_avenant DATE NOT NULL, -- Date de signature de l'avenant
date_effet DATE NOT NULL, -- Date d'effet de l'avenant
-- Type d'avenant
type_avenant TEXT NOT NULL DEFAULT 'modification', -- 'modification' ou 'annulation'
motif_avenant TEXT, -- Motif de l'avenant (texte libre)
-- Éléments avenantés (array de strings)
elements_avenantes TEXT[] NOT NULL DEFAULT '{}', -- ['objet', 'duree', 'lieu_horaire', 'remuneration']
-- Données spécifiques selon les éléments avenantés (JSONB pour flexibilité)
objet_data JSONB, -- { profession_code, profession_label, production_name, production_numero_objet }
duree_data JSONB, -- { date_debut, date_fin, nb_representations, nb_repetitions, nb_heures, dates_representations, dates_repetitions, jours_travail }
lieu_horaire_data JSONB, -- { lieu, horaires, adresse }
remuneration_data JSONB, -- { gross_pay, precisions_salaire, type_salaire }
-- Statut de l'avenant
statut TEXT NOT NULL DEFAULT 'draft', -- 'draft', 'pending', 'signed', 'cancelled'
-- URL du PDF généré
pdf_url TEXT,
pdf_s3_key TEXT,
-- Métadonnées
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id)
);
-- Index pour améliorer les performances
CREATE INDEX IF NOT EXISTS idx_avenants_contract_id ON public.avenants(contract_id);
CREATE INDEX IF NOT EXISTS idx_avenants_date_avenant ON public.avenants(date_avenant);
CREATE INDEX IF NOT EXISTS idx_avenants_statut ON public.avenants(statut);
CREATE INDEX IF NOT EXISTS idx_avenants_type_avenant ON public.avenants(type_avenant);
-- Trigger pour mettre à jour updated_at
CREATE OR REPLACE FUNCTION update_avenants_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_update_avenants_updated_at
BEFORE UPDATE ON public.avenants
FOR EACH ROW
EXECUTE FUNCTION update_avenants_updated_at();
-- RLS (Row Level Security)
ALTER TABLE public.avenants ENABLE ROW LEVEL SECURITY;
-- Policy: Les utilisateurs staff peuvent tout faire
CREATE POLICY "Staff can manage avenants"
ON public.avenants
FOR ALL
TO authenticated
USING (
EXISTS (
SELECT 1 FROM public.staff_users
WHERE staff_users.user_id = auth.uid()
AND staff_users.is_staff = true
)
);
-- Policy: Les organisations peuvent voir leurs avenants
CREATE POLICY "Organizations can view their avenants"
ON public.avenants
FOR SELECT
TO authenticated
USING (
EXISTS (
SELECT 1 FROM public.cddu_contracts c
INNER JOIN public.organization_members om ON c.org_id = om.org_id
WHERE c.id = avenants.contract_id
AND om.user_id = auth.uid()
)
);
-- Commentaires
COMMENT ON TABLE public.avenants IS 'Table des avenants aux contrats de travail';
COMMENT ON COLUMN public.avenants.contract_id IS 'Référence au contrat concerné';
COMMENT ON COLUMN public.avenants.numero_avenant IS 'Numéro de l''avenant (ex: AVE-001)';
COMMENT ON COLUMN public.avenants.date_avenant IS 'Date de signature de l''avenant';
COMMENT ON COLUMN public.avenants.date_effet IS 'Date d''effet de l''avenant';
COMMENT ON COLUMN public.avenants.type_avenant IS 'Type: modification ou annulation';
COMMENT ON COLUMN public.avenants.motif_avenant IS 'Motif de l''avenant';
COMMENT ON COLUMN public.avenants.elements_avenantes IS 'Liste des éléments modifiés par l''avenant';
COMMENT ON COLUMN public.avenants.statut IS 'Statut: draft, pending, signed, cancelled';