2eme commit
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
import { readFileSync } from 'fs'
|
||||
|
||||
const SUPABASE_URL = 'http://192.168.2.220:8000'
|
||||
const ANON_KEY = readFileSync('/home/tophe/10-Projets/DevOps/OpenCode/GestionDesCompetences/.env', 'utf8')
|
||||
.split('\n')
|
||||
.find(l => l.startsWith('VITE_SUPABASE_ANON_KEY='))
|
||||
?.split('=').slice(1).join('=')
|
||||
const SERVICE_ROLE_KEY = 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJmMzI4YWViLTYwMWYtNGEzZC04MjdiLTY1MTZlZTY0MWViMyJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoic3VwYWJhc2UiLCJpYXQiOjE3NzkzMDAyNDMsImV4cCI6MTkzNjk4MDI0M30.qt2IKVgwaQQkHIZVWH4tEcrozU0mT3F9dNC9Yo83UidKwsoxHRqZz8hBWjreRPsThUcCgjxOmhwxeTB7Zd7RFA'
|
||||
|
||||
const headers = {
|
||||
'apikey': ANON_KEY,
|
||||
'Authorization': `Bearer ${SERVICE_ROLE_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Prefer': 'return=representation',
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
const url = `${SUPABASE_URL}${path}`
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
if (!res.ok) {
|
||||
throw new Error(`${method} ${path} → ${res.status}: ${text.slice(0, 200)}`)
|
||||
}
|
||||
try { return JSON.parse(text) } catch { return text }
|
||||
}
|
||||
|
||||
const COLLABORATORS = [
|
||||
{ name: 'Alice Martin', email: 'alice.martin@example.com' },
|
||||
{ name: 'Bob Bernard', email: 'bob.bernard@example.com' },
|
||||
{ name: 'Chloé Dubois', email: 'chloe.dubois@example.com' },
|
||||
{ name: 'David Petit', email: 'david.petit@example.com' },
|
||||
{ name: 'Emma Leroy', email: 'emma.leroy@example.com' },
|
||||
{ name: 'François Moreau', email: 'francois.moreau@example.com' },
|
||||
{ name: 'Gaëlle Lambert', email: 'gaelle.lambert@example.com' },
|
||||
{ name: 'Hugo Girard', email: 'hugo.girard@example.com' },
|
||||
{ name: 'Inès Roux', email: 'ines.roux@example.com' },
|
||||
{ name: 'Jules Vincent', email: 'jules.vincent@example.com' },
|
||||
{ name: 'Karine Fournier', email: 'karine.fournier@example.com' },
|
||||
{ name: 'Lucas Morel', email: 'lucas.morel@example.com' },
|
||||
{ name: 'Manon Lefebvre', email: 'manon.lefebvre@example.com' },
|
||||
{ name: 'Nathan Mercier', email: 'nathan.mercier@example.com' },
|
||||
{ name: 'Océane Caron', email: 'oceane.caron@example.com' },
|
||||
{ name: 'Pierre Gauthier', email: 'pierre.gauthier@example.com' },
|
||||
{ name: 'Quitterie Perrin', email: 'quitterie.perrin@example.com' },
|
||||
{ name: 'Romain Boucher', email: 'romain.boucher@example.com' },
|
||||
{ name: 'Sarah Dumont', email: 'sarah.dumont@example.com' },
|
||||
{ name: 'Thomas Giraud', email: 'thomas.giraud@example.com' },
|
||||
]
|
||||
|
||||
const SKILLS_BY_CATEGORY = {
|
||||
'Réseau': ['Routage & Switching', 'Firewall', 'VPN', 'Wireshark / Analyse'],
|
||||
'Système': ['Linux', 'Windows Server', 'Virtualisation (Proxmox)', 'Ansible'],
|
||||
'Cloud': ['AWS', 'Azure', 'GCP', 'Terraform'],
|
||||
'Sécurité': ['Pentest', 'SOC / SIEM', 'PKI', 'ISO 27001'],
|
||||
'Base de données': ['PostgreSQL', 'MySQL', 'MongoDB', 'Admin BDD'],
|
||||
'Monitoring': ['Prometheus', 'Grafana', 'ELK Stack', 'Zabbix'],
|
||||
'Stockage': ['SAN / NAS', 'Backup (Veeam)', 'Ceph', 'Minio'],
|
||||
}
|
||||
|
||||
function randomLevel() {
|
||||
return Math.floor(Math.random() * 4) + 1
|
||||
}
|
||||
|
||||
function pickRandom(arr) {
|
||||
return arr[Math.floor(Math.random() * arr.length)]
|
||||
}
|
||||
|
||||
async function delay(ms) {
|
||||
return new Promise(r => setTimeout(r, ms))
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('=== Début du seed ===\n')
|
||||
|
||||
// 1. Récupérer les catégories
|
||||
console.log('1. Récupération des catégories...')
|
||||
const categories = await api('GET', '/rest/v1/categories')
|
||||
console.log(` → ${categories.length} catégories trouvées`)
|
||||
|
||||
// 2. Créer les skills
|
||||
console.log('\n2. Création des skills...')
|
||||
const skillIds = []
|
||||
for (const cat of categories) {
|
||||
const skills = SKILLS_BY_CATEGORY[cat.name]
|
||||
if (!skills) { console.log(` ⚠ Pas de skills pour "${cat.name}"`); continue }
|
||||
for (const skillName of skills) {
|
||||
const existing = await api('GET', `/rest/v1/skills?name=eq.${encodeURIComponent(skillName)}&category_id=eq.${cat.id}`)
|
||||
if (existing.length > 0) {
|
||||
skillIds.push(existing[0].id)
|
||||
console.log(` ⏩ ${skillName} (${cat.name}) — existe déjà`)
|
||||
continue
|
||||
}
|
||||
const data = await api('POST', '/rest/v1/skills', { name: skillName, category_id: cat.id })
|
||||
skillIds.push(data[0].id)
|
||||
console.log(` ✓ ${skillName} (${cat.name})`)
|
||||
}
|
||||
}
|
||||
console.log(` → ${skillIds.length} skills prêts`)
|
||||
|
||||
// 3. Récupérer l'admin
|
||||
console.log('\n3. Recherche de l\'admin...')
|
||||
const members = await api('GET', '/rest/v1/members')
|
||||
const adminId = members.find(m => m.role === 'admin')?.id
|
||||
if (!adminId) { console.error('Aucun admin trouvé'); return }
|
||||
console.log(` ✓ Admin: ${members.find(m => m.id === adminId)?.full_name} (${adminId})`)
|
||||
|
||||
// 4. Créer les utilisateurs Auth
|
||||
console.log('\n4. Création des collaborateurs (Auth)...')
|
||||
const memberIds = []
|
||||
const defaultPassword = 'password123'
|
||||
|
||||
for (const collab of COLLABORATORS) {
|
||||
const existing = await api('GET', `/rest/v1/members?email=eq.${encodeURIComponent(collab.email)}`)
|
||||
if (existing.length > 0) {
|
||||
console.log(` ⏩ ${collab.name} — existe déjà (member ID: ${existing[0].id})`)
|
||||
memberIds.push(existing[0].id)
|
||||
continue
|
||||
}
|
||||
|
||||
const user = await api('POST', '/auth/v1/admin/users', {
|
||||
email: collab.email,
|
||||
password: defaultPassword,
|
||||
email_confirm: true,
|
||||
user_metadata: { full_name: collab.name },
|
||||
})
|
||||
|
||||
console.log(` ✓ ${collab.name} (${collab.email})`)
|
||||
memberIds.push(user.id)
|
||||
}
|
||||
console.log(` → ${memberIds.length} collaborateurs`)
|
||||
|
||||
// Attendre que le trigger crée les members
|
||||
console.log('\n Attente de la création des membres par le trigger...')
|
||||
await delay(3000)
|
||||
|
||||
// Vérifier que tous les membres ont été créés
|
||||
for (const memberId of memberIds) {
|
||||
const m = await api('GET', `/rest/v1/members?id=eq.${memberId}`)
|
||||
if (m.length === 0) {
|
||||
console.log(` ⚠ Membre manquant pour ${memberId}, création manuelle...`)
|
||||
const collab = COLLABORATORS.find(c => {
|
||||
// On ne peut pas matcher facilement, on va juste récupérer l'email depuis auth
|
||||
return true
|
||||
})
|
||||
const userInfo = await api('GET', `/auth/v1/admin/users/${memberId}`)
|
||||
await api('POST', '/rest/v1/members', {
|
||||
id: memberId,
|
||||
email: userInfo.email,
|
||||
full_name: userInfo.user_metadata?.full_name || '',
|
||||
role: 'member',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Assigner des niveaux
|
||||
console.log('\n5. Assignation des niveaux...')
|
||||
let levelCount = 0
|
||||
for (const memberId of memberIds) {
|
||||
for (const skillId of skillIds) {
|
||||
const level = randomLevel()
|
||||
const existing = await api('GET', `/rest/v1/skill_levels?member_id=eq.${memberId}&skill_id=eq.${skillId}`)
|
||||
if (existing.length > 0) {
|
||||
await api('PATCH', `/rest/v1/skill_levels?member_id=eq.${memberId}&skill_id=eq.${skillId}`, { level })
|
||||
} else {
|
||||
await api('POST', '/rest/v1/skill_levels', { member_id: memberId, skill_id: skillId, level })
|
||||
}
|
||||
levelCount++
|
||||
}
|
||||
}
|
||||
console.log(` → ${levelCount} niveaux assignés`)
|
||||
|
||||
// 6. Créer un historique pour les 10 premiers
|
||||
console.log('\n6. Création de l\'historique...')
|
||||
let historyCount = 0
|
||||
for (let i = 0; i < Math.min(10, memberIds.length); i++) {
|
||||
const memberId = memberIds[i]
|
||||
const numChanges = Math.floor(Math.random() * 5) + 2
|
||||
for (let j = 0; j < numChanges; j++) {
|
||||
const skillId = pickRandom(skillIds)
|
||||
const oldLevel = randomLevel()
|
||||
const newLevel = Math.min(oldLevel + Math.floor(Math.random() * 2) + 1, 4)
|
||||
if (newLevel === oldLevel) continue
|
||||
|
||||
const daysAgo = Math.floor(Math.random() * 30) + 1
|
||||
const createdAt = new Date(Date.now() - daysAgo * 86400000).toISOString()
|
||||
|
||||
await api('POST', '/rest/v1/skill_history', {
|
||||
member_id: memberId,
|
||||
skill_id: skillId,
|
||||
old_level: oldLevel,
|
||||
new_level: newLevel,
|
||||
changed_by: adminId,
|
||||
created_at: createdAt,
|
||||
})
|
||||
historyCount++
|
||||
}
|
||||
}
|
||||
console.log(` → ${historyCount} entrées d\'historique`)
|
||||
|
||||
// Résumé
|
||||
const finalCategories = await api('GET', '/rest/v1/categories')
|
||||
const finalSkills = await api('GET', '/rest/v1/skills')
|
||||
const finalMembers = await api('GET', '/rest/v1/members')
|
||||
const finalLevels = await api('GET', '/rest/v1/skill_levels')
|
||||
const finalHistory = await api('GET', '/rest/v1/skill_history')
|
||||
|
||||
console.log('\n=== Seed terminé ===')
|
||||
console.log(` ${finalCategories.length} catégories`)
|
||||
console.log(` ${finalSkills.length} skills`)
|
||||
console.log(` ${finalMembers.length} membres (dont ${finalMembers.filter(m => m.role === 'admin').length} admin)`)
|
||||
console.log(` ${finalLevels.length} niveaux assignés`)
|
||||
console.log(` ${finalHistory.length} entrées d'historique`)
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error('ERREUR:', err.message)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,218 @@
|
||||
-- ============================================
|
||||
-- Seed : 20 collaborateurs fictifs + compétences
|
||||
-- À exécuter dans Supabase Studio → SQL Editor
|
||||
-- ============================================
|
||||
|
||||
-- Fonction utilitaire pour générer un hash bcrypt (mot de passe: password123)
|
||||
-- Le hash est pré-généré pour éviter d'avoir besoin de pgcrypto
|
||||
|
||||
-- 1. Créer les skills manquants
|
||||
DO $$
|
||||
DECLARE
|
||||
cat_rec RECORD;
|
||||
skill_id_var uuid;
|
||||
BEGIN
|
||||
-- Réseau
|
||||
FOR cat_rec IN SELECT id FROM categories WHERE name = 'Réseau' LOOP
|
||||
INSERT INTO skills (name, category_id) VALUES ('Routage & Switching', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Firewall', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('VPN', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Wireshark / Analyse', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
END LOOP;
|
||||
-- Système
|
||||
FOR cat_rec IN SELECT id FROM categories WHERE name = 'Système' LOOP
|
||||
INSERT INTO skills (name, category_id) VALUES ('Linux', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Windows Server', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Virtualisation (Proxmox)', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Ansible', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
END LOOP;
|
||||
-- Cloud
|
||||
FOR cat_rec IN SELECT id FROM categories WHERE name = 'Cloud' LOOP
|
||||
INSERT INTO skills (name, category_id) VALUES ('AWS', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Azure', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('GCP', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Terraform', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
END LOOP;
|
||||
-- Sécurité
|
||||
FOR cat_rec IN SELECT id FROM categories WHERE name = 'Sécurité' LOOP
|
||||
INSERT INTO skills (name, category_id) VALUES ('Pentest', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('SOC / SIEM', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('PKI', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('ISO 27001', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
END LOOP;
|
||||
-- Base de données
|
||||
FOR cat_rec IN SELECT id FROM categories WHERE name = 'Base de données' LOOP
|
||||
INSERT INTO skills (name, category_id) VALUES ('PostgreSQL', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('MySQL', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('MongoDB', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Admin BDD', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
END LOOP;
|
||||
-- Monitoring
|
||||
FOR cat_rec IN SELECT id FROM categories WHERE name = 'Monitoring' LOOP
|
||||
INSERT INTO skills (name, category_id) VALUES ('Prometheus', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Grafana', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('ELK Stack', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Zabbix', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
END LOOP;
|
||||
-- Stockage
|
||||
FOR cat_rec IN SELECT id FROM categories WHERE name = 'Stockage' LOOP
|
||||
INSERT INTO skills (name, category_id) VALUES ('SAN / NAS', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Backup (Veeam)', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Ceph', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
INSERT INTO skills (name, category_id) VALUES ('Minio', cat_rec.id) ON CONFLICT (name, category_id) DO NOTHING;
|
||||
END LOOP;
|
||||
END $$;
|
||||
|
||||
-- 2. Créer les utilisateurs dans auth.users et members
|
||||
|
||||
-- Extension pgcrypto pour le hash des mots de passe
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
-- Insérer les utilisateurs
|
||||
DO $$
|
||||
DECLARE
|
||||
users_data text[][] := ARRAY[
|
||||
['alice.martin@example.com', 'Alice Martin'],
|
||||
['bob.bernard@example.com', 'Bob Bernard'],
|
||||
['chloe.dubois@example.com', 'Chloé Dubois'],
|
||||
['david.petit@example.com', 'David Petit'],
|
||||
['emma.leroy@example.com', 'Emma Leroy'],
|
||||
['francois.moreau@example.com', 'François Moreau'],
|
||||
['gaelle.lambert@example.com', 'Gaëlle Lambert'],
|
||||
['hugo.girard@example.com', 'Hugo Girard'],
|
||||
['ines.roux@example.com', 'Inès Roux'],
|
||||
['jules.vincent@example.com', 'Jules Vincent'],
|
||||
['karine.fournier@example.com', 'Karine Fournier'],
|
||||
['lucas.morel@example.com', 'Lucas Morel'],
|
||||
['manon.lefebvre@example.com', 'Manon Lefebvre'],
|
||||
['nathan.mercier@example.com', 'Nathan Mercier'],
|
||||
['oceane.caron@example.com', 'Océane Caron'],
|
||||
['pierre.gauthier@example.com', 'Pierre Gauthier'],
|
||||
['quitterie.perrin@example.com', 'Quitterie Perrin'],
|
||||
['romain.boucher@example.com', 'Romain Boucher'],
|
||||
['sarah.dumont@example.com', 'Sarah Dumont'],
|
||||
['thomas.giraud@example.com', 'Thomas Giraud']
|
||||
];
|
||||
i int;
|
||||
user_email text;
|
||||
user_name text;
|
||||
new_user_id uuid;
|
||||
existing_id uuid;
|
||||
BEGIN
|
||||
FOR i IN 1..array_length(users_data, 1) LOOP
|
||||
user_email := users_data[i][1];
|
||||
user_name := users_data[i][2];
|
||||
|
||||
-- Vérifier si le membre existe déjà
|
||||
SELECT id INTO existing_id FROM members WHERE email = user_email;
|
||||
IF existing_id IS NOT NULL THEN
|
||||
RAISE NOTICE '⏩ % existe déjà (id: %)', user_name, existing_id;
|
||||
CONTINUE;
|
||||
END IF;
|
||||
|
||||
-- Vérifier si l'utilisateur auth existe déjà
|
||||
SELECT id INTO existing_id FROM auth.users WHERE email = user_email;
|
||||
IF existing_id IS NOT NULL THEN
|
||||
RAISE NOTICE '⏩ % existe dans auth.users, création du member manquant...', user_name;
|
||||
INSERT INTO members (id, email, full_name, role)
|
||||
VALUES (existing_id, user_email, user_name, 'member')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
CONTINUE;
|
||||
END IF;
|
||||
|
||||
-- Créer l'utilisateur auth
|
||||
new_user_id := gen_random_uuid();
|
||||
INSERT INTO auth.users (
|
||||
id, instance_id, aud, role, email,
|
||||
encrypted_password, email_confirmed_at,
|
||||
raw_user_meta_data, created_at, updated_at,
|
||||
confirmation_token, email_change, email_change_token_new, recovery_token, is_super_admin
|
||||
) VALUES (
|
||||
new_user_id,
|
||||
'00000000-0000-0000-0000-000000000000',
|
||||
'authenticated',
|
||||
'authenticated',
|
||||
user_email,
|
||||
crypt('password123', gen_salt('bf')),
|
||||
now(),
|
||||
jsonb_build_object('full_name', user_name),
|
||||
now(),
|
||||
now(),
|
||||
'', '', '', '',
|
||||
false
|
||||
);
|
||||
|
||||
-- Créer la ligne dans members manuellement
|
||||
INSERT INTO members (id, email, full_name, role)
|
||||
VALUES (new_user_id, user_email, user_name, 'member');
|
||||
|
||||
RAISE NOTICE '✓ % créé (id: %)', user_name, new_user_id;
|
||||
END LOOP;
|
||||
END $$;
|
||||
|
||||
-- 3. Assigner des niveaux de compétence aléatoires
|
||||
DO $$
|
||||
DECLARE
|
||||
member_rec RECORD;
|
||||
skill_rec RECORD;
|
||||
level_val int;
|
||||
BEGIN
|
||||
FOR member_rec IN SELECT id FROM members WHERE role = 'member' LOOP
|
||||
FOR skill_rec IN SELECT id FROM skills LOOP
|
||||
level_val := floor(random() * 4) + 1;
|
||||
INSERT INTO skill_levels (member_id, skill_id, level)
|
||||
VALUES (member_rec.id, skill_rec.id, level_val)
|
||||
ON CONFLICT (member_id, skill_id) DO UPDATE SET level = level_val;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
RAISE NOTICE 'Niveaux assignés à tous les membres';
|
||||
END $$;
|
||||
|
||||
-- 4. Créer un historique pour les 10 premiers membres
|
||||
DO $$
|
||||
DECLARE
|
||||
member_rec RECORD;
|
||||
skill_rec RECORD;
|
||||
admin_id uuid;
|
||||
skill_ids uuid[];
|
||||
old_lvl int;
|
||||
new_lvl int;
|
||||
num_changes int;
|
||||
days_ago int;
|
||||
BEGIN
|
||||
-- Récupérer l'ID de l'admin
|
||||
SELECT id INTO admin_id FROM members WHERE role = 'admin' LIMIT 1;
|
||||
IF admin_id IS NULL THEN
|
||||
RAISE NOTICE '⚠ Aucun admin trouvé, historique ignoré';
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
-- Récupérer tous les skill IDs
|
||||
SELECT array_agg(id) INTO skill_ids FROM skills;
|
||||
|
||||
FOR member_rec IN SELECT id FROM members WHERE role = 'member' ORDER BY created_at LIMIT 10 LOOP
|
||||
num_changes := floor(random() * 5) + 2;
|
||||
FOR i IN 1..num_changes LOOP
|
||||
skill_rec := (SELECT s FROM unnest(skill_ids) AS s ORDER BY random() LIMIT 1);
|
||||
old_lvl := floor(random() * 3) + 1;
|
||||
new_lvl := old_lvl + floor(random() * (4 - old_lvl)) + 1;
|
||||
days_ago := floor(random() * 30) + 1;
|
||||
|
||||
INSERT INTO skill_history (member_id, skill_id, old_level, new_level, changed_by, created_at)
|
||||
VALUES (member_rec.id, skill_rec, old_lvl, new_lvl, admin_id, now() - (days_ago || ' days')::interval);
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
RAISE NOTICE 'Historique créé';
|
||||
END $$;
|
||||
|
||||
-- 5. Afficher le résumé
|
||||
SELECT 'RÉSULTAT DU SEED' AS "";
|
||||
SELECT 'Catégories' AS "Table", count(*) AS "Total" FROM categories
|
||||
UNION ALL
|
||||
SELECT 'Skills', count(*) FROM skills
|
||||
UNION ALL
|
||||
SELECT 'Membres', count(*) FROM members
|
||||
UNION ALL
|
||||
SELECT 'Niveaux', count(*) FROM skill_levels
|
||||
UNION ALL
|
||||
SELECT 'Historique', count(*) FROM skill_history;
|
||||
Reference in New Issue
Block a user