MIGRATION VERS GITEA

This commit is contained in:
mathis committed 2026-08-25 01:23:13 +02:00
commit 5f9d991c15
333 files changed
+108514

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
-- Migration : Ajout de la colonne fh_url à la table lignes
-- Stocke l'URL publique du PDF de la fiche horaire associée à la ligne
ALTER TABLE lignes
ADD COLUMN IF NOT EXISTS fh_url TEXT DEFAULT NULL;
COMMENT ON COLUMN lignes.fh_url IS 'URL publique du fichier PDF de la fiche horaire de la ligne (stocké dans Supabase Storage)';
@@ -0,0 +1,88 @@
-- Migration: create table horaires_substitutions
-- Cette table est utilisée par l'API front-end (src/api/horairesSubstitutions.js)
CREATE TABLE IF NOT EXISTS horaires_substitutions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Référence éventuelle vers un horaire source
horaire_id UUID REFERENCES horaires(id) ON DELETE SET NULL,
-- Région (filtrage RBAC)
region_id UUID,
region VARCHAR(255),
-- Informations générales (copie similaire à `horaires`)
numero_train VARCHAR(50),
type_train VARCHAR(100),
type_train_id BIGINT,
gare_depart_id UUID,
gare_depart_nom VARCHAR(255),
heure_depart TIME,
gare_arrivee_id UUID,
gare_arrivee_nom VARCHAR(255),
heure_arrivee TIME,
-- Période de validité de la substitution
date_debut TIMESTAMP WITH TIME ZONE,
date_fin TIMESTAMP WITH TIME ZONE,
-- Jours / exceptions
circule_lundi BOOLEAN DEFAULT true,
circule_mardi BOOLEAN DEFAULT true,
circule_mercredi BOOLEAN DEFAULT true,
circule_jeudi BOOLEAN DEFAULT true,
circule_vendredi BOOLEAN DEFAULT true,
circule_samedi BOOLEAN DEFAULT true,
circule_dimanche BOOLEAN DEFAULT true,
circule_jours_feries BOOLEAN DEFAULT false,
jours_personnalises JSONB DEFAULT '[]'::jsonb,
jours_non_circulation JSONB DEFAULT '[]'::jsonb,
materiel_roulant_id BIGINT,
ligne_id UUID,
ligne_nom VARCHAR(255),
service_annuel_id UUID,
service_annuel_nom VARCHAR(255),
-- Indique qu'il s'agit d'une substitution
est_substitution BOOLEAN DEFAULT true,
motif_substitution VARCHAR(255),
-- Snapshot des gares desservies et composition
gares_desservies JSONB DEFAULT '[]'::jsonb,
composition_train JSONB DEFAULT '[]'::jsonb,
-- Métadonnées
actif BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
-- Indexes utiles
CREATE INDEX IF NOT EXISTS idx_horaires_substitutions_region ON horaires_substitutions(region_id);
CREATE INDEX IF NOT EXISTS idx_horaires_substitutions_horaire ON horaires_substitutions(horaire_id);
CREATE INDEX IF NOT EXISTS idx_horaires_substitutions_actif ON horaires_substitutions(actif) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_horaires_substitutions_datefin ON horaires_substitutions(date_fin);
-- Trigger pour updated_at si la fonction existe
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'update_updated_at_column') THEN
DROP TRIGGER IF EXISTS update_horaires_substitutions_updated_at ON horaires_substitutions;
CREATE TRIGGER update_horaires_substitutions_updated_at
BEFORE UPDATE ON horaires_substitutions
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
END IF;
END$$;
COMMENT ON TABLE horaires_substitutions IS 'Table des horaires de substitution (autocar / remplacement)';
COMMENT ON COLUMN horaires_substitutions.gares_desservies IS 'Liste JSON des gares desservies par la substitution';
COMMENT ON COLUMN horaires_substitutions.composition_train IS 'Composition JSON du matériel roulant (position, id, nom)';
COMMENT ON COLUMN horaires_substitutions.date_fin IS 'Date/heure de fin de validité de la substitution';
@@ -0,0 +1,18 @@
-- ============================================================================
-- MIGRATION : Ajout de la colonne composition_train (JSONB) dans la table horaires
-- Date : 2026-03-01
-- Description : Stocke la composition complète et ordonnée des matériels roulants
-- affectés à un horaire (sillon). Chaque élément contient l'id,
-- le nom, le nom technique, l'URL de l'image et la position.
--
-- ⚠️ À EXÉCUTER dans l'éditeur SQL Supabase :
-- https://supabase.com/dashboard → votre projet → SQL Editor
-- ============================================================================
ALTER TABLE public.horaires
ADD COLUMN IF NOT EXISTS composition_train JSONB DEFAULT '[]'::jsonb;
COMMENT ON COLUMN public.horaires.composition_train IS
'Composition ordonnée du train : liste JSON des matériels roulants affectés au sillon. '
'Format : [{"materiel_id": 1, "materiel_nom": "Régiolis", "materiel_nom_technique": "X73500", "materiel_image_url": "https://...", "position": 1}, ...]';
@@ -0,0 +1,54 @@
-- ============================================================================
-- MIGRATION : Ajout de la colonne informations (JSONB) dans la table gares
-- Date : 2026-03-01
-- Description : Stocke toutes les informations enrichies d'une gare :
-- adresse, horaires, accessibilité, services, voiture, vélo,
-- et lignes de transports en commun (bus, métro, tramway, car régional).
--
-- ⚠️ À EXÉCUTER dans l'éditeur SQL Supabase :
-- https://supabase.com/dashboard → votre projet → SQL Editor
-- ============================================================================
ALTER TABLE public.gares
ADD COLUMN IF NOT EXISTS informations JSONB DEFAULT '{}'::jsonb;
COMMENT ON COLUMN public.gares.informations IS
'Informations enrichies de la gare au format JSON. Structure :
{
-- Informations Générales
"adresse": "20 Bd Diderot, 75012 Paris",
"horaires_guichet": "6h00 - 21h30",
"horaires_gare": "5h00 - 00h30",
"distributeur_ter": true,
-- Accessibilité
"service_assistance": true,
-- Services
"espace_attente": true,
"distributeur_tgv": false,
"objets_trouves": true,
"toilettes": true,
"wifi_gratuit": true,
"photomaton": false,
"defibrillateur": true,
"galeries_marchandes": false,
-- Voiture
"depose_minute": true,
"espace_taxis": true,
"espace_vtc": false,
"location_voiture": false,
"parking": true,
-- Vélo
"velo_libre_service": true,
"parking_velos": true,
-- Transports en commun enrichis
"lignes_bus": [{"nom": "29", "terminus_a": "Gare Saint-Lazare", "terminus_b": "Montempoivre"}],
"lignes_metro": [{"nom": "1", "terminus_a": "La Défense", "terminus_b": "Château de Vincennes"}],
"lignes_tramway": [],
"lignes_car_regional": []
}';
@@ -0,0 +1,88 @@
-- ============================================================================
-- MIGRATION : Ajout de la colonne gares_desservies (JSONB) dans la table horaires
-- Date : 2026-03-01
-- Description : Ajoute une colonne JSONB "gares_desservies" dans la table horaires
-- afin de stocker un snapshot dénormalisé des gares desservies.
-- Cette colonne est alimentée à chaque création/modification d'horaire
-- et est synchronisée avec la table relationnelle horaires_gares_desservies.
-- ============================================================================
-- Ajout de la colonne si elle n'existe pas encore
ALTER TABLE public.horaires
ADD COLUMN IF NOT EXISTS gares_desservies JSONB DEFAULT '[]'::jsonb;
-- Commentaire explicatif sur la colonne
COMMENT ON COLUMN public.horaires.gares_desservies IS
'Snapshot JSON des gares desservies (copie dénormalisée synchronisée avec horaires_gares_desservies). '
'Format : [{"gare_id": "uuid", "gare_nom": "Nom Gare", "heure_arrivee": "HH:MM", "heure_depart": "HH:MM", "ordre": 1}, ...]';
-- ============================================================================
-- Rétro-remplissage : synchroniser la colonne JSON depuis la table relationnelle
-- pour tous les horaires existants ayant déjà des gares desservies.
-- ============================================================================
UPDATE public.horaires h
SET gares_desservies = (
SELECT COALESCE(
jsonb_agg(
jsonb_build_object(
'gare_id', gd.gare_id,
'gare_nom', gd.gare_nom,
'heure_arrivee', gd.heure_arrivee,
'heure_depart', gd.heure_depart,
'ordre', gd.ordre
) ORDER BY gd.ordre
),
'[]'::jsonb
)
FROM public.horaires_gares_desservies gd
WHERE gd.horaire_id = h.id
)
WHERE EXISTS (
SELECT 1 FROM public.horaires_gares_desservies gd WHERE gd.horaire_id = h.id
);
-- ============================================================================
-- (Optionnel) Trigger pour maintenir automatiquement la colonne JSON à jour
-- à chaque INSERT / UPDATE / DELETE dans horaires_gares_desservies.
-- Décommenter si vous souhaitez une synchronisation automatique côté base.
-- ============================================================================
-- CREATE OR REPLACE FUNCTION public.sync_horaire_gares_desservies_json()
-- RETURNS trigger LANGUAGE plpgsql AS $$
-- DECLARE
-- v_horaire_id UUID;
-- BEGIN
-- IF TG_OP = 'DELETE' THEN
-- v_horaire_id := OLD.horaire_id;
-- ELSE
-- v_horaire_id := NEW.horaire_id;
-- END IF;
--
-- UPDATE public.horaires
-- SET gares_desservies = (
-- SELECT COALESCE(
-- jsonb_agg(
-- jsonb_build_object(
-- 'gare_id', gd.gare_id,
-- 'gare_nom', gd.gare_nom,
-- 'heure_arrivee', gd.heure_arrivee,
-- 'heure_depart', gd.heure_depart,
-- 'ordre', gd.ordre
-- ) ORDER BY gd.ordre
-- ),
-- '[]'::jsonb
-- )
-- FROM public.horaires_gares_desservies gd
-- WHERE gd.horaire_id = v_horaire_id
-- )
-- WHERE id = v_horaire_id;
--
-- RETURN NULL;
-- END;
-- $$;
--
-- DROP TRIGGER IF EXISTS tr_sync_gares_desservies_json ON public.horaires_gares_desservies;
-- CREATE TRIGGER tr_sync_gares_desservies_json
-- AFTER INSERT OR UPDATE OR DELETE ON public.horaires_gares_desservies
-- FOR EACH ROW EXECUTE FUNCTION public.sync_horaire_gares_desservies_json();
+9
View File
@@ -0,0 +1,9 @@
-- Migration : ajout de la colonne jours_perturbation à la table perturbations
-- Permet de stocker plusieurs jours uniques ou périodes pour une perturbation
ALTER TABLE perturbations
ADD COLUMN IF NOT EXISTS jours_perturbation JSONB DEFAULT NULL;
COMMENT ON COLUMN perturbations.jours_perturbation IS
'Liste des jours/périodes de perturbation. Format : [{type: "jour"|"periode", date: "YYYY-MM-DD", dateDebut: "YYYY-MM-DD", dateFin: "YYYY-MM-DD"}]';
@@ -0,0 +1,9 @@
-- Ajoute un champ JSONB pour stocker les permissions par fonctionnalite.
ALTER TABLE IF EXISTS public.utilisateurs
ADD COLUMN IF NOT EXISTS permissions jsonb NOT NULL DEFAULT '{}'::jsonb;
-- Securise les lignes existantes si la colonne etait nullable.
UPDATE public.utilisateurs
SET permissions = '{}'::jsonb
WHERE permissions IS NULL;
@@ -0,0 +1,35 @@
-- ============================================================================
-- MIGRATION : Ajout de la colonne perturbations_arrets (JSONB) dans perturbations
-- Date : 2026-03-01
-- Description : Stocke l'état complet des perturbations par arrêt tel que
-- configuré dans le formulaire de création / modification.
-- Ceci permet au formulaire d'édition de restaurer exactement
-- le même état que le formulaire de création.
--
-- ⚠️ À EXÉCUTER dans l'éditeur SQL Supabase :
-- https://supabase.com/dashboard → votre projet → SQL Editor
-- ============================================================================
ALTER TABLE public.perturbations
ADD COLUMN IF NOT EXISTS perturbations_arrets JSONB DEFAULT NULL;
COMMENT ON COLUMN public.perturbations.perturbations_arrets IS
'Snapshot complet des perturbations par arrêt (état du formulaire). '
'Format : [{
"index": 0,
"gare_nom": "Paris Gare de Lyon",
"heure_arrivee": null,
"heure_depart": "07:30",
"type_perturbation": "retard",
"retard_minutes": 15,
"retard_cumule": 0,
"arret_prolonge_minutes": 0,
"cause_arret": "Incident technique",
"is_nouveau_terminus": false,
"is_nouvelle_origine": false,
"isFirst": true,
"isLast": false,
"manual_retard": true,
"manual_arret_prolonge": false
}, ...]';
+109
View File
@@ -0,0 +1,109 @@
-- ============================================================================
-- MIGRATION: Ajout du système de gestion des perturbations
-- Date: 2026-02-06
-- Description: Ajoute les tables nécessaires pour gérer les perturbations
-- affectant les horaires de trains
-- ============================================================================
-- Vérifier que les tables n'existent pas déjà
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'perturbations') THEN
RAISE NOTICE 'La table perturbations existe déjà, migration annulée';
RETURN;
END IF;
END $$;
-- Exécuter le script principal
supabase_perturbations_tables.sql
-- Vérification post-migration
DO $$
DECLARE
perturbations_count INTEGER;
modifications_count INTEGER;
BEGIN
-- Vérifier que les tables ont été créées
SELECT COUNT(*) INTO perturbations_count
FROM information_schema.tables
WHERE table_name = 'perturbations';
SELECT COUNT(*) INTO modifications_count
FROM information_schema.tables
WHERE table_name = 'perturbations_modifications_parcours';
IF perturbations_count = 1 AND modifications_count = 1 THEN
RAISE NOTICE '✓ Migration réussie : Tables créées avec succès';
ELSE
RAISE EXCEPTION '✗ Échec de la migration : Les tables n''ont pas été créées correctement';
END IF;
-- Afficher les colonnes créées
RAISE NOTICE 'Colonnes de la table perturbations:';
FOR rec IN (
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'perturbations'
ORDER BY ordinal_position
) LOOP
RAISE NOTICE ' - % (%)', rec.column_name, rec.data_type;
END LOOP;
END $$;
-- Test d'insertion (rollback automatique)
DO $$
DECLARE
test_horaire_id UUID;
test_perturbation_id UUID;
BEGIN
-- Récupérer un horaire existant pour le test
SELECT id INTO test_horaire_id FROM horaires LIMIT 1;
IF test_horaire_id IS NULL THEN
RAISE NOTICE 'Aucun horaire disponible pour le test';
RETURN;
END IF;
-- Test d'insertion d'une perturbation
INSERT INTO perturbations (
horaire_id,
type_perturbation,
duree_retard_minutes,
cause,
cause_details,
actif
) VALUES (
test_horaire_id,
'retard',
15,
'incident_technique',
'Test de migration',
false
) RETURNING id INTO test_perturbation_id;
IF test_perturbation_id IS NOT NULL THEN
RAISE NOTICE '✓ Test d''insertion réussi';
-- Supprimer le test
DELETE FROM perturbations WHERE id = test_perturbation_id;
ELSE
RAISE EXCEPTION '✗ Échec du test d''insertion';
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE '✗ Erreur lors du test : %', SQLERRM;
END $$;
-- Afficher un résumé
SELECT
'Migration terminée' as statut,
NOW() as date_migration,
(SELECT COUNT(*) FROM perturbations) as nombre_perturbations,
(SELECT COUNT(*) FROM perturbations_modifications_parcours) as nombre_modifications;
-- ============================================================================
-- ROLLBACK (à utiliser en cas de problème)
-- ============================================================================
-- DROP TABLE IF EXISTS perturbations_modifications_parcours CASCADE;
-- DROP TABLE IF EXISTS perturbations CASCADE;
+18
View File
@@ -0,0 +1,18 @@
-- ============================================================================
-- Migration : Ajout du champ "quai" dans horaires_gares_desservies
-- Date : 2026-03-02
-- ============================================================================
-- 1. Ajouter la colonne quai à la table horaires_gares_desservies
ALTER TABLE horaires_gares_desservies
ADD COLUMN IF NOT EXISTS quai VARCHAR(50) DEFAULT NULL;
COMMENT ON COLUMN horaires_gares_desservies.quai IS 'Numéro ou nom du quai attribué à cet arrêt (ex: "Voie 3", "Quai A")';
-- 2. Mettre à jour l'index pour accélérer les recherches par gare_id
CREATE INDEX IF NOT EXISTS idx_hgd_gare_id ON horaires_gares_desservies(gare_id);
CREATE INDEX IF NOT EXISTS idx_hgd_horaire_id ON horaires_gares_desservies(horaire_id);
-- Note : Le snapshot JSONB horaires.gares_desservies sera mis à jour
-- automatiquement via l'application lors de la sauvegarde des quais.
+20
View File
@@ -0,0 +1,20 @@
-- ============================================================================
-- MIGRATION : Ajout de la colonne quais_hall (JSONB) dans la table gares
-- Date : 2026-06-10
-- Description : Stocke l'association entre les halls et les quais au format JSON.
-- Structure :
-- {
-- "hall": {
-- "Nom du hall": ["Voie A", "Voie B"]
-- }
-- }
--
-- ⚠️ À EXÉCUTER dans l'éditeur SQL Supabase :
-- https://supabase.com/dashboard → votre projet → SQL Editor
-- ============================================================================
ALTER TABLE public.gares
ADD COLUMN IF NOT EXISTS quais_hall JSONB DEFAULT '{"hall": {}}'::jsonb;
COMMENT ON COLUMN public.gares.quais_hall IS
'Association des quais aux halls sous forme JSON : {"hall": {"Nom du Hall": ["Quai 1", "Quai 2"]}}';
@@ -0,0 +1,4 @@
-- Ajout du champ region_id (slug) à la table menus_regionaux
ALTER TABLE menus_regionaux ADD COLUMN IF NOT EXISTS region_id VARCHAR(64);
-- Index pour accélérer la recherche par région
CREATE INDEX IF NOT EXISTS idx_menus_regionaux_region_id ON menus_regionaux(region_id);
@@ -0,0 +1,32 @@
-- Migration: Ajouter la colonne "region" à la table lignes
-- et créer la table "parametres" pour les paramètres du site
-- 1. Ajout de la colonne region à la table lignes
ALTER TABLE lignes ADD COLUMN IF NOT EXISTS region VARCHAR(100);
-- 2. Création de la table parametres
CREATE TABLE IF NOT EXISTS parametres (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
cle VARCHAR(100) NOT NULL UNIQUE,
valeur JSONB,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
-- Insérer les paramètres par défaut
INSERT INTO parametres (cle, valeur) VALUES
('general', '{"nom_site": "", "description_site": "", "region": "", "logo_header_url": ""}'),
('tarifs', '{"billets": [], "abonnements": [], "remises": []}')
ON CONFLICT (cle) DO NOTHING;
-- 3. Ajout de la colonne quai_defaut à horaires_gares_desservies (pour attribution des quais)
ALTER TABLE horaires_gares_desservies ADD COLUMN IF NOT EXISTS quai_id UUID REFERENCES gare_quais(id);
-- 4. Politique RLS pour parametres (accès complet pour les utilisateurs authentifiés)
ALTER TABLE parametres ENABLE ROW LEVEL SECURITY;
CREATE POLICY "parametres_select_all" ON parametres FOR SELECT USING (true);
CREATE POLICY "parametres_insert_all" ON parametres FOR INSERT WITH CHECK (true);
CREATE POLICY "parametres_update_all" ON parametres FOR UPDATE USING (true);
CREATE POLICY "parametres_delete_all" ON parametres FOR DELETE USING (true);
+3
View File
@@ -0,0 +1,3 @@
ALTER TABLE tarifs
ADD COLUMN IF NOT EXISTS details JSONB;
+18
View File
@@ -0,0 +1,18 @@
-- Migration : table menus_regionaux
CREATE TABLE IF NOT EXISTS menus_regionaux (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
nom VARCHAR(200) NOT NULL,
description TEXT,
actif BOOLEAN DEFAULT false,
structure JSONB DEFAULT '[]'::jsonb,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
-- RLS
ALTER TABLE menus_regionaux ENABLE ROW LEVEL SECURITY;
CREATE POLICY "menus_select" ON menus_regionaux FOR SELECT USING (true);
CREATE POLICY "menus_insert" ON menus_regionaux FOR INSERT WITH CHECK (true);
CREATE POLICY "menus_update" ON menus_regionaux FOR UPDATE USING (true);
CREATE POLICY "menus_delete" ON menus_regionaux FOR DELETE USING (true);
+90
View File
@@ -0,0 +1,90 @@
-- Tables de messagerie interne (V1)
CREATE TABLE IF NOT EXISTS public.messagerie_threads (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS public.messagerie_participants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
thread_id UUID NOT NULL REFERENCES public.messagerie_threads(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES public.utilisateurs(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(thread_id, user_id)
);
CREATE TABLE IF NOT EXISTS public.messagerie_messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
thread_id UUID NOT NULL REFERENCES public.messagerie_threads(id) ON DELETE CASCADE,
sender_id UUID NOT NULL REFERENCES public.utilisateurs(id) ON DELETE CASCADE,
contenu TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_messagerie_participants_user_id ON public.messagerie_participants(user_id);
CREATE INDEX IF NOT EXISTS idx_messagerie_messages_thread_id ON public.messagerie_messages(thread_id);
CREATE INDEX IF NOT EXISTS idx_messagerie_messages_created_at ON public.messagerie_messages(created_at DESC);
-- RLS simple: participant du thread uniquement
ALTER TABLE public.messagerie_threads ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.messagerie_participants ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.messagerie_messages ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS messagerie_threads_select ON public.messagerie_threads;
CREATE POLICY messagerie_threads_select ON public.messagerie_threads
FOR SELECT TO anon
USING (
EXISTS (
SELECT 1 FROM public.messagerie_participants p
WHERE p.thread_id = messagerie_threads.id
)
);
DROP POLICY IF EXISTS messagerie_threads_insert ON public.messagerie_threads;
CREATE POLICY messagerie_threads_insert ON public.messagerie_threads
FOR INSERT TO anon
WITH CHECK (true);
DROP POLICY IF EXISTS messagerie_threads_update ON public.messagerie_threads;
CREATE POLICY messagerie_threads_update ON public.messagerie_threads
FOR UPDATE TO anon
USING (
EXISTS (
SELECT 1 FROM public.messagerie_participants p
WHERE p.thread_id = messagerie_threads.id
)
)
WITH CHECK (true);
DROP POLICY IF EXISTS messagerie_participants_select ON public.messagerie_participants;
CREATE POLICY messagerie_participants_select ON public.messagerie_participants
FOR SELECT TO anon
USING (true);
DROP POLICY IF EXISTS messagerie_participants_insert ON public.messagerie_participants;
CREATE POLICY messagerie_participants_insert ON public.messagerie_participants
FOR INSERT TO anon
WITH CHECK (true);
DROP POLICY IF EXISTS messagerie_messages_select ON public.messagerie_messages;
CREATE POLICY messagerie_messages_select ON public.messagerie_messages
FOR SELECT TO anon
USING (
EXISTS (
SELECT 1 FROM public.messagerie_participants p
WHERE p.thread_id = messagerie_messages.thread_id
)
);
DROP POLICY IF EXISTS messagerie_messages_insert ON public.messagerie_messages;
CREATE POLICY messagerie_messages_insert ON public.messagerie_messages
FOR INSERT TO anon
WITH CHECK (
EXISTS (
SELECT 1 FROM public.messagerie_participants p
WHERE p.thread_id = messagerie_messages.thread_id
AND p.user_id = messagerie_messages.sender_id
)
);
@@ -0,0 +1,55 @@
-- ============================================================================
-- MIGRATION : Création du bucket Storage "materiel-roulant"
-- Date : 2026-03-01
-- Description : Crée le bucket public "materiel-roulant" dans Supabase Storage
-- et configure les policies RLS.
--
-- ⚠️ IMPORTANT — Authentification custom :
-- Cette application utilise une auth custom (RPC authenticate_user + localStorage)
-- et NON supabase.auth.signInWithPassword(). Par conséquent auth.uid() est
-- toujours NULL côté Supabase. Les policies utilisent donc le rôle "anon"
-- (clé publique anonyme) pour autoriser les opérations Storage depuis le front.
--
-- ⚠️ À EXÉCUTER UNE SEULE FOIS dans l'éditeur SQL de votre projet Supabase
-- (https://supabase.com/dashboard → votre projet → SQL Editor)
-- ============================================================================
-- 1. Créer le bucket s'il n'existe pas encore
INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
VALUES (
'materiel-roulant',
'materiel-roulant',
true,
10485760,
ARRAY['image/jpeg','image/png','image/webp','image/gif','image/svg+xml']
)
ON CONFLICT (id) DO NOTHING;
-- ============================================================================
-- 2. Policies RLS sur storage.objects
-- ============================================================================
-- Lecture publique
DROP POLICY IF EXISTS "materiel-roulant - lecture publique" ON storage.objects;
CREATE POLICY "materiel-roulant - lecture publique"
ON storage.objects FOR SELECT
USING (bucket_id = 'materiel-roulant');
-- Upload (anon car auth custom — auth.uid() toujours NULL)
DROP POLICY IF EXISTS "materiel-roulant - upload authentifié" ON storage.objects;
CREATE POLICY "materiel-roulant - upload authentifié"
ON storage.objects FOR INSERT
WITH CHECK (bucket_id = 'materiel-roulant');
-- Mise à jour
DROP POLICY IF EXISTS "materiel-roulant - update authentifié" ON storage.objects;
CREATE POLICY "materiel-roulant - update authentifié"
ON storage.objects FOR UPDATE
USING (bucket_id = 'materiel-roulant');
-- Suppression
DROP POLICY IF EXISTS "materiel-roulant - delete authentifié" ON storage.objects;
CREATE POLICY "materiel-roulant - delete authentifié"
ON storage.objects FOR DELETE
USING (bucket_id = 'materiel-roulant');
+19
View File
@@ -0,0 +1,19 @@
-- Création de la table "tarifs" pour gérer les offres de billets, abonnements, remises par région
CREATE TABLE IF NOT EXISTS tarifs (
id SERIAL PRIMARY KEY,
nom VARCHAR(255) NOT NULL,
type VARCHAR(50) NOT NULL, -- billet, abonnement, remise
description TEXT,
prix_minimum NUMERIC(10,2),
prix_par_km NUMERIC(10,3),
age_maximum INTEGER,
regions TEXT[] NOT NULL, -- tableau d'identifiants de régions
date_debut DATE,
date_fin DATE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Index pour recherche rapide par région
CREATE INDEX IF NOT EXISTS idx_tarifs_regions ON tarifs USING GIN (regions);
+16
View File
@@ -0,0 +1,16 @@
-- v2: add trigger to keep updated_at in sync
CREATE OR REPLACE FUNCTION touch_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS trg_touch_tarifs_updated_at ON tarifs;
CREATE TRIGGER trg_touch_tarifs_updated_at
BEFORE UPDATE ON tarifs
FOR EACH ROW
EXECUTE PROCEDURE touch_updated_at();
+83
View File
@@ -0,0 +1,83 @@
-- ============================================================================
-- CRÉATION DES TABLES POUR LA GESTION DES TRAVAUX
-- ============================================================================
-- Table principale des travaux
CREATE TABLE IF NOT EXISTS travaux (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
titre TEXT NOT NULL,
description TEXT,
date_debut DATE NOT NULL,
date_fin DATE NOT NULL,
jours_travaux TEXT[] NOT NULL, -- ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']
heure_debut TIME NOT NULL,
heure_fin TIME NOT NULL,
actif BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
deleted_at TIMESTAMP WITH TIME ZONE,
CONSTRAINT valid_dates CHECK (date_fin >= date_debut),
CONSTRAINT valid_hours CHECK (heure_fin > heure_debut)
);
-- Table de liaison entre travaux et sillons de substitution
CREATE TABLE IF NOT EXISTS travaux_substitutions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
travaux_id UUID NOT NULL REFERENCES travaux(id) ON DELETE CASCADE,
horaire_id UUID NOT NULL REFERENCES horaires(id) ON DELETE CASCADE,
ordre INTEGER DEFAULT 0, -- Ordre d'affichage des substitutions
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
UNIQUE(travaux_id, horaire_id)
);
-- Index pour améliorer les performances
CREATE INDEX IF NOT EXISTS idx_travaux_dates ON travaux(date_debut, date_fin);
CREATE INDEX IF NOT EXISTS idx_travaux_actif ON travaux(actif);
CREATE INDEX IF NOT EXISTS idx_travaux_deleted ON travaux(deleted_at);
CREATE INDEX IF NOT EXISTS idx_travaux_substitutions_travaux ON travaux_substitutions(travaux_id);
CREATE INDEX IF NOT EXISTS idx_travaux_substitutions_horaire ON travaux_substitutions(horaire_id);
-- Fonction pour mettre à jour updated_at automatiquement
CREATE OR REPLACE FUNCTION update_travaux_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger pour mettre à jour updated_at
DROP TRIGGER IF EXISTS trigger_update_travaux_updated_at ON travaux;
CREATE TRIGGER trigger_update_travaux_updated_at
BEFORE UPDATE ON travaux
FOR EACH ROW
EXECUTE FUNCTION update_travaux_updated_at();
-- Commentaires sur les tables
COMMENT ON TABLE travaux IS 'Table principale pour la gestion des travaux sur les lignes';
COMMENT ON TABLE travaux_substitutions IS 'Table de liaison entre travaux et horaires de substitution';
COMMENT ON COLUMN travaux.jours_travaux IS 'Jours de la semaine où les travaux ont lieu';
COMMENT ON COLUMN travaux.actif IS 'Indique si les travaux sont actifs';
COMMENT ON COLUMN travaux.deleted_at IS 'Date de suppression (soft delete)';
COMMENT ON COLUMN travaux_substitutions.ordre IS 'Ordre d''affichage des substitutions';
-- ============================================================================
-- DONNÉES DE TEST (optionnel)
-- ============================================================================
-- Exemple de travaux
INSERT INTO travaux (titre, description, date_debut, date_fin, jours_travaux, heure_debut, heure_fin, actif)
VALUES
('Travaux ligne Paris-Lyon', 'Rénovation des voies', '2026-03-01', '2026-03-31', ARRAY['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi'], '09:00', '17:00', true),
('Maintenance gare de Lyon', 'Travaux de maintenance planifiés', '2026-04-15', '2026-04-20', ARRAY['samedi', 'dimanche'], '06:00', '22:00', true)
ON CONFLICT DO NOTHING;
-- Afficher le résultat
SELECT
'Tables travaux créées avec succès' as statut,
(SELECT COUNT(*) FROM travaux) as nombre_travaux,
(SELECT COUNT(*) FROM travaux_substitutions) as nombre_substitutions;
@@ -0,0 +1,80 @@
-- ============================================================================
-- CORRECTIF : Policies RLS du bucket "banque-annonces" et des tables SQL
-- Date : 2026-07-02
--
-- Problème : L'application utilise la clé anon et une authentification custom. Les
-- policies de banque_mots et de storage.objects qui exigent un utilisateur
-- authentifié (TO authenticated) bloquent l'INSERT/UPDATE/DELETE et provoquent
-- l'erreur "new row violates row-level security policy".
--
-- Solution : Recréer des policies pour permettre SELECT, INSERT, UPDATE, DELETE
-- sur le bucket 'banque-annonces' et sur les tables de la base de données.
--
-- ⚠️ À EXÉCUTER dans l'éditeur SQL Supabase :
-- https://app.supabase.com → votre projet → SQL Editor
-- ============================================================================
-- 1. Réglage des politiques RLS pour les tables de base de données
-- ============================================================================
-- Table: banque_mots
DROP POLICY IF EXISTS "Authenticated users can read banque_mots" ON public.banque_mots;
DROP POLICY IF EXISTS "Authenticated users can insert banque_mots" ON public.banque_mots;
DROP POLICY IF EXISTS "Authenticated users can update banque_mots" ON public.banque_mots;
CREATE POLICY "Public read banque_mots" ON public.banque_mots FOR SELECT USING (deleted_at IS NULL);
CREATE POLICY "Public insert banque_mots" ON public.banque_mots FOR INSERT WITH CHECK (true);
CREATE POLICY "Public update banque_mots" ON public.banque_mots FOR UPDATE USING (true);
CREATE POLICY "Public delete banque_mots" ON public.banque_mots FOR DELETE USING (true);
-- Table: annonces_templates
DROP POLICY IF EXISTS "Authenticated users can read templates" ON public.annonces_templates;
DROP POLICY IF EXISTS "Authenticated users can insert templates" ON public.annonces_templates;
DROP POLICY IF EXISTS "Authenticated users can update templates" ON public.annonces_templates;
CREATE POLICY "Public read templates" ON public.annonces_templates FOR SELECT USING (deleted_at IS NULL);
CREATE POLICY "Public insert templates" ON public.annonces_templates FOR INSERT WITH CHECK (true);
CREATE POLICY "Public update templates" ON public.annonces_templates FOR UPDATE USING (true);
CREATE POLICY "Public delete templates" ON public.annonces_templates FOR DELETE USING (true);
-- Table: annonces_enregistrees
DROP POLICY IF EXISTS "Authenticated users can read annonces" ON public.annonces_enregistrees;
DROP POLICY IF EXISTS "Authenticated users can insert annonces" ON public.annonces_enregistrees;
DROP POLICY IF EXISTS "Authenticated users can update annonces" ON public.annonces_enregistrees;
CREATE POLICY "Public read annonces" ON public.annonces_enregistrees FOR SELECT USING (deleted_at IS NULL);
CREATE POLICY "Public insert annonces" ON public.annonces_enregistrees FOR INSERT WITH CHECK (true);
CREATE POLICY "Public update annonces" ON public.annonces_enregistrees FOR UPDATE USING (true);
CREATE POLICY "Public delete annonces" ON public.annonces_enregistrees FOR DELETE USING (true);
-- 2. Réglage des politiques RLS du Bucket Storage "banque-annonces"
-- ============================================================================
-- Supprimer les anciennes politiques storage si elles existent
DROP POLICY IF EXISTS "Public read access on banque-annonces" ON storage.objects;
DROP POLICY IF EXISTS "Authenticated users can upload to banque-annonces" ON storage.objects;
DROP POLICY IF EXISTS "Authenticated users can delete from banque-annonces" ON storage.objects;
DROP POLICY IF EXISTS "Public upload access on banque-annonces" ON storage.objects;
DROP POLICY IF EXISTS "Public update access on banque-annonces" ON storage.objects;
DROP POLICY IF EXISTS "Public delete access on banque-annonces" ON storage.objects;
-- Lecture publique pour tous
CREATE POLICY "Public read access on banque-annonces"
ON storage.objects FOR SELECT
USING (bucket_id = 'banque-annonces');
-- Insertion publique (Upload)
CREATE POLICY "Public upload access on banque-annonces"
ON storage.objects FOR INSERT
WITH CHECK (bucket_id = 'banque-annonces');
-- Mise à jour publique (Upsert)
CREATE POLICY "Public update access on banque-annonces"
ON storage.objects FOR UPDATE
USING (bucket_id = 'banque-annonces');
-- Suppression publique (Delete)
CREATE POLICY "Public delete access on banque-annonces"
ON storage.objects FOR DELETE
USING (bucket_id = 'banque-annonces');
@@ -0,0 +1,43 @@
-- ============================================================================
-- CORRECTIF : Policies RLS du bucket "fiches-horaires"
-- Date : 2026-03-01
--
-- Problème : L'application utilise la clé anon et une authentification custom. Les
-- policies de storage.objects qui exigent auth.uid() bloquent l'INSERT
-- et provoquent l'erreur "new row violates row-level security policy".
--
-- Solution : Recréer des policies pour permettre l'INSERT/UPDATE/DELETE/SELECT
-- sur le bucket 'fiches-horaires' en se basant sur bucket_id seulement.
--
-- ⚠️ À EXÉCUTER dans l'éditeur SQL Supabase :
-- https://app.supabase.com → votre projet → SQL Editor
-- ============================================================================
-- Supprimer d'abord les policies existantes (si elles existent)
DROP POLICY IF EXISTS "fiches-horaires - lecture publique" ON storage.objects;
DROP POLICY IF EXISTS "fiches-horaires - upload" ON storage.objects;
DROP POLICY IF EXISTS "fiches-horaires - update" ON storage.objects;
DROP POLICY IF EXISTS "fiches-horaires - delete" ON storage.objects;
-- Créer des policies permissives basées sur le bucket_id
CREATE POLICY "fiches-horaires - lecture publique"
ON storage.objects FOR SELECT
USING (bucket_id = 'fiches-horaires');
CREATE POLICY "fiches-horaires - upload"
ON storage.objects FOR INSERT
WITH CHECK (bucket_id = 'fiches-horaires');
CREATE POLICY "fiches-horaires - update"
ON storage.objects FOR UPDATE
USING (bucket_id = 'fiches-horaires');
CREATE POLICY "fiches-horaires - delete"
ON storage.objects FOR DELETE
USING (bucket_id = 'fiches-horaires');
-- Note : Si vous souhaitez restreindre les uploads aux utilisateurs authentifiés,
-- remplacez la clause WITH CHECK (bucket_id = 'fiches-horaires') par
-- WITH CHECK (bucket_id = 'fiches-horaires' AND auth.uid() IS NOT NULL)
-- et assurez-vous que vos utilisateurs sont bien authentifiés côté front.
@@ -0,0 +1,41 @@
-- ============================================================================
-- CORRECTIF : Policies RLS du bucket "materiel-roulant"
-- Date : 2026-03-01
--
-- Problème : L'application utilise une authentification custom (RPC authenticate_user
-- + localStorage). supabase.auth.signIn() n'est jamais appelé, donc
-- auth.uid() est toujours NULL → la policy WITH CHECK auth.uid() IS NOT NULL
-- bloque tous les uploads.
--
-- Solution : Policies ouvertes sur le bucket (accès par clé anon publique).
-- Le bucket est déjà créé — ce script corrige uniquement les policies.
--
-- ⚠️ À EXÉCUTER dans l'éditeur SQL Supabase :
-- https://supabase.com/dashboard → votre projet → SQL Editor
-- ============================================================================
-- Supprimer toutes les policies existantes du bucket
DROP POLICY IF EXISTS "materiel-roulant - lecture publique" ON storage.objects;
DROP POLICY IF EXISTS "materiel-roulant - upload authentifié" ON storage.objects;
DROP POLICY IF EXISTS "materiel-roulant - update authentifié" ON storage.objects;
DROP POLICY IF EXISTS "materiel-roulant - delete authentifié" ON storage.objects;
-- Recréer les policies sans condition auth.uid()
-- (l'app utilise la clé anon, auth.uid() est toujours NULL)
CREATE POLICY "materiel-roulant - lecture publique"
ON storage.objects FOR SELECT
USING (bucket_id = 'materiel-roulant');
CREATE POLICY "materiel-roulant - upload authentifié"
ON storage.objects FOR INSERT
WITH CHECK (bucket_id = 'materiel-roulant');
CREATE POLICY "materiel-roulant - update authentifié"
ON storage.objects FOR UPDATE
USING (bucket_id = 'materiel-roulant');
CREATE POLICY "materiel-roulant - delete authentifié"
ON storage.objects FOR DELETE
USING (bucket_id = 'materiel-roulant');
Whitespace-only changes.
+62
View File
@@ -0,0 +1,62 @@
-- Migration: repair foreign key between horaires_gares_desservies.horaire_id and horaires.id
-- This script will:
-- 1) check the column types of horaires.id and horaires_gares_desservies.horaire_id
-- 2) if types match and FK doesn't exist, create the FK constraint
-- 3) otherwise, print a NOTICE explaining the mismatch for manual resolution
DO $$
DECLARE
t_horaire TEXT;
t_horaire_fk TEXT;
cnt INT;
BEGIN
-- ensure target tables exist
IF NOT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'horaires' AND relkind = 'r') THEN
RAISE NOTICE 'Table public.horaires does not exist in this database/schema.';
RETURN;
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'horaires_gares_desservies' AND relkind = 'r') THEN
RAISE NOTICE 'Table public.horaires_gares_desservies does not exist in this database/schema.';
RETURN;
END IF;
-- get formatted types
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO t_horaire
FROM pg_attribute a
WHERE a.attrelid = 'public.horaires'::regclass AND a.attname = 'id';
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO t_horaire_fk
FROM pg_attribute a
WHERE a.attrelid = 'public.horaires_gares_desservies'::regclass AND a.attname = 'horaire_id';
RAISE NOTICE 'Detected types -> horaires.id: %, horaires_gares_desservies.horaire_id: %', t_horaire, t_horaire_fk;
-- check existing FK from horaires_gares_desservies to horaires
SELECT count(*) INTO cnt
FROM pg_constraint c
WHERE c.conrelid = 'public.horaires_gares_desservies'::regclass
AND c.confrelid = 'public.horaires'::regclass
AND c.contype = 'f';
IF cnt > 0 THEN
RAISE NOTICE 'A foreign-key constraint from horaires_gares_desservies to horaires already exists (count=%). No action taken.', cnt;
RETURN;
END IF;
-- If types match, create the FK
IF t_horaire IS NOT NULL AND t_horaire_fk IS NOT NULL AND t_horaire = t_horaire_fk THEN
EXECUTE 'ALTER TABLE public.horaires_gares_desservies
ADD CONSTRAINT fk_horaires_gares_horaire_id
FOREIGN KEY (horaire_id)
REFERENCES public.horaires(id)
ON DELETE CASCADE';
RAISE NOTICE 'Foreign key constraint fk_horaires_gares_horaire_id created successfully.';
ELSE
RAISE NOTICE 'Column types do not match or could not be determined. Manual intervention required.';
RAISE NOTICE 'Detected types -> horaires.id: %, horaires_gares_desservies.horaire_id: %', t_horaire, t_horaire_fk;
RAISE NOTICE 'If both should be UUID, consider converting [or recreating] the columns and then re-run this script.';
RAISE NOTICE 'If both should be BIGINT, consider altering types to bigint. Do not run automatic conversion without backup.';
END IF;
END $$;
+204
View File
@@ -0,0 +1,204 @@
-- ============================================================================
-- DONNÉES DE TEST: Perturbations
-- Description: Jeux de données pour tester le système de perturbations
-- ============================================================================
-- Note: Ces données sont à insérer APRÈS avoir des horaires existants dans la base
-- Exemple 1: Retard sur un train
-- Remplacer 'HORAIRE_ID_1' par un véritable ID d'horaire existant
INSERT INTO perturbations (
horaire_id,
type_perturbation,
duree_retard_minutes,
cause,
cause_details,
date_debut,
date_fin,
actif,
notes
) VALUES (
(SELECT id FROM horaires LIMIT 1), -- Premier horaire de la base
'retard',
25,
'incident_technique',
'Panne de signalisation à Paris-Montparnasse',
NOW(),
NOW() + INTERVAL '2 hours',
true,
'Retard estimé de 25 minutes sur l''ensemble du parcours'
);
-- Exemple 2: Suppression de train avec substitution
INSERT INTO perturbations (
horaire_id,
type_perturbation,
duree_retard_minutes,
cause,
cause_details,
sillon_substitution_id,
date_debut,
date_fin,
actif,
notes
) VALUES (
(SELECT id FROM horaires LIMIT 1 OFFSET 1), -- Deuxième horaire
'suppression',
NULL,
'mouvement_social',
'Grève nationale du personnel roulant',
(SELECT id FROM horaires LIMIT 1 OFFSET 2), -- Train de substitution
NOW(),
NOW() + INTERVAL '1 day',
true,
'Train supprimé - Report sur le train suivant disponible'
);
-- Exemple 3: Modification de parcours
DO $$
DECLARE
v_perturbation_id UUID;
v_horaire_id UUID;
BEGIN
-- Récupérer un horaire avec des gares desservies
SELECT h.id INTO v_horaire_id
FROM horaires h
WHERE EXISTS (
SELECT 1 FROM horaires_gares_desservies hgd
WHERE hgd.horaire_id = h.id
)
LIMIT 1;
IF v_horaire_id IS NULL THEN
RAISE NOTICE 'Aucun horaire avec gares desservies trouvé, test ignoré';
RETURN;
END IF;
-- Créer la perturbation
INSERT INTO perturbations (
horaire_id,
type_perturbation,
duree_retard_minutes,
cause,
cause_details,
date_debut,
actif,
notes
) VALUES (
v_horaire_id,
'modification_parcours',
NULL,
'travaux',
'Travaux de maintenance sur la voie entre Lyon et Valence',
NOW(),
true,
'Modification du parcours : certaines gares ne seront pas desservies'
) RETURNING id INTO v_perturbation_id;
-- Ajouter des modifications de parcours
-- Supprimer une gare du parcours
INSERT INTO perturbations_modifications_parcours (
perturbation_id,
type_modification,
gare_id,
gare_nom,
ordre
) SELECT
v_perturbation_id,
'gare_supprimee',
gare_id,
gare_nom,
ordre
FROM horaires_gares_desservies
WHERE horaire_id = v_horaire_id
LIMIT 1;
RAISE NOTICE 'Perturbation de modification de parcours créée avec succès';
END $$;
-- Exemple 4: Retard causé par les conditions météorologiques
INSERT INTO perturbations (
horaire_id,
type_perturbation,
duree_retard_minutes,
cause,
cause_details,
date_debut,
date_fin,
actif,
notes
) VALUES (
(SELECT id FROM horaires LIMIT 1 OFFSET 3),
'retard',
45,
'conditions_meteorologiques',
'Fortes chutes de neige en Auvergne-Rhône-Alpes',
NOW(),
NOW() + INTERVAL '4 hours',
true,
'Circulation ralentie sur l''ensemble des lignes'
);
-- Exemple 5: Perturbation inactive (historique)
INSERT INTO perturbations (
horaire_id,
type_perturbation,
duree_retard_minutes,
cause,
cause_details,
date_debut,
date_fin,
actif,
notes
) VALUES (
(SELECT id FROM horaires LIMIT 1 OFFSET 4),
'retard',
10,
'affluence',
'Affluence exceptionnelle lors du départ',
NOW() - INTERVAL '1 day',
NOW() - INTERVAL '1 day' + INTERVAL '30 minutes',
false,
'Perturbation terminée - Retard résorbé'
);
-- Afficher un résumé des perturbations de test créées
SELECT
'Données de test créées' as statut,
COUNT(*) as nombre_perturbations_test,
COUNT(*) FILTER (WHERE actif = true) as perturbations_actives,
COUNT(*) FILTER (WHERE actif = false) as perturbations_inactives
FROM perturbations
WHERE notes LIKE '%test%' OR notes LIKE '%Test%';
-- Afficher les perturbations créées
SELECT
p.id,
p.type_perturbation,
p.duree_retard_minutes,
p.cause,
p.actif,
h.numero_train,
h.gare_depart_nom,
h.gare_arrivee_nom
FROM perturbations p
JOIN horaires h ON p.horaire_id = h.id
ORDER BY p.created_at DESC
LIMIT 10;
-- ============================================================================
-- NETTOYAGE DES DONNÉES DE TEST
-- ============================================================================
-- Décommenter pour supprimer toutes les données de test
/*
DELETE FROM perturbations_modifications_parcours
WHERE perturbation_id IN (
SELECT id FROM perturbations
WHERE notes LIKE '%test%' OR notes LIKE '%Test%'
);
DELETE FROM perturbations
WHERE notes LIKE '%test%' OR notes LIKE '%Test%';
SELECT 'Données de test supprimées' as statut;
*/