✨ 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'
102 lines
3.9 KiB
PL/PgSQL
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';
|