fix(seeder): fix FK constraints for core_companies and core_users

- jobs.company_id now references core_companies.id (UUID)
- jobs.created_by now references core_users.id (UUID)
- Fixed parameter count in all INSERT statements
- All 13 fictional companies now seed correctly
This commit is contained in:
Tiago Yamamoto 2025-12-22 23:02:58 -03:00
parent 2293fdc9d1
commit 407979c6dc
4 changed files with 68 additions and 53 deletions

View file

@ -103,7 +103,7 @@ export async function seedAcmeCorp() {
const defaultRegionId = regionsRes.rows[0]?.id || null;
// 1. Create ACME Company
const acmeSlug = 'acme-corp';
const acmeSlug = 'ACME Corporation';
const acmeCNPJ = '99.999.999/0001-99';
await pool.query(`
@ -149,18 +149,12 @@ export async function seedAcmeCorp() {
console.log(' ✓ ACME Corporation criada');
// 2. Get ACME company ID
const acmeRes = await pool.query("SELECT id FROM companies WHERE slug = 'acme-corp'");
const acmeCompanyId = acmeRes.rows[0].id;
// 2. Get ACME company ID (use coreId for FK)
const acmeCompanyId = acmeCoreId;
// 3. Get or create seed user
await pool.query(`
INSERT INTO users (identifier, password_hash, role, full_name)
VALUES ('wile_e_coyote', '$2b$10$placeholder', 'recruiter', 'Wile E. Coyote - Genius (Self-Proclaimed)')
ON CONFLICT (identifier) DO NOTHING
`);
const seedUserRes = await pool.query("SELECT id FROM users WHERE identifier IN ('wile_e_coyote', 'system_seed') LIMIT 1");
const seedUserId = seedUserRes.rows[0]?.id || 1;
// 3. Get seed user from core_users (for FK)
const seedUserRes = await pool.query("SELECT id FROM core_users LIMIT 1");
const seedUserId = seedUserRes.rows[0]?.id;
// 4. Seed 69 jobs
const workModes = ['onsite', 'hybrid', 'remote'];
@ -205,13 +199,15 @@ export async function seedAcmeCorp() {
for (let b = 0; b < 4; b++) {
selectedBenefits.push(benefits[(i + b) % benefits.length]);
}
const jobId = crypto.randomUUID();
await pool.query(`
INSERT INTO jobs (company_id, created_by, title, description,
INSERT INTO jobs (id, company_id, created_by, title, description,
salary_min, salary_max, salary_type, employment_type, working_hours,
location, requirements, benefits, visa_support, language_level, status, work_mode)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
`, [
jobId,
acmeCompanyId,
seedUserId,
title,
@ -231,6 +227,7 @@ export async function seedAcmeCorp() {
]);
}
console.log(' ✓ 69 vagas ACME criadas com sucesso');
console.log(' 🎯 Tipos de vaga: Dev, Design, Data, Infra, Liderança, Easter Eggs');
console.log(' 💀 Disclaimer: Nenhum Coiote foi ferido na criação deste seeder (mentira)');

View file

@ -1,4 +1,5 @@
import { pool } from '../db.js';
import crypto from 'crypto';
/**
* 🎬 Empresas Fictícias Épicas - Parte 2
@ -289,23 +290,24 @@ async function createCompanyAndJobs(companyData, jobs) {
ON CONFLICT (id) DO NOTHING
`, [companyData.coreId, companyData.name, companyData.cnpj]);
// Get company ID
const companyRes = await pool.query("SELECT id FROM companies WHERE slug = $1", [companyData.slug]);
const companyId = companyRes.rows[0].id;
// Get company ID (use coreId for FK reference)
const companyId = companyData.coreId;
const seedUserRes = await pool.query("SELECT id FROM users WHERE identifier IN ('system_seed', 'wile_e_coyote') LIMIT 1");
const seedUserRes = await pool.query("SELECT id FROM core_users LIMIT 1");
const seedUserId = seedUserRes.rows[0]?.id || 1;
const workModes = ['onsite', 'hybrid', 'remote'];
for (let i = 0; i < jobs.length; i++) {
const job = jobs[i];
const jobId = crypto.randomUUID();
await pool.query(`
INSERT INTO jobs (company_id, created_by, title, description,
INSERT INTO jobs (id, company_id, created_by, title, description,
salary_min, salary_max, salary_type, employment_type, working_hours,
location, requirements, benefits, visa_support, language_level, status, work_mode)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
`, [
jobId,
companyId,
seedUserId,
job.title,
@ -331,6 +333,7 @@ async function createCompanyAndJobs(companyData, jobs) {
}
}
export async function seedEpicCompanies() {
console.log('🎬 Seeding Epic Fictional Companies (Part 2)...');

View file

@ -157,7 +157,7 @@ export async function seedStarkIndustries() {
ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description
`, [
'Stark Industries',
'stark-industries',
'Stark Industries',
'company',
'77.777.777/0001-77',
'Stark Tower, 200 Park Avenue, Manhattan, New York, NY 10166',
@ -184,12 +184,11 @@ export async function seedStarkIndustries() {
ON CONFLICT (id) DO NOTHING
`, ['57575757-5757-5757-5757-575757575757', 'Stark Industries', '77.777.777/0001-77']);
// Get company ID
const companyRes = await pool.query("SELECT id FROM companies WHERE slug = 'stark-industries'");
const companyId = companyRes.rows[0].id;
// Get company ID (use coreId directly)
const companyId = '57575757-5757-5757-5757-575757575757';
// Get seed user
const seedUserRes = await pool.query("SELECT id FROM users WHERE identifier IN ('system_seed', 'wile_e_coyote') LIMIT 1");
const seedUserRes = await pool.query("SELECT id FROM core_users LIMIT 1");
const seedUserId = seedUserRes.rows[0]?.id || 1;
// Create jobs
@ -197,12 +196,14 @@ export async function seedStarkIndustries() {
for (let i = 0; i < starkJobs.length; i++) {
const job = starkJobs[i];
const jobId = crypto.randomUUID();
await pool.query(`
INSERT INTO jobs (company_id, created_by, title, description,
INSERT INTO jobs (id, company_id, created_by, title, description,
salary_min, salary_max, salary_type, employment_type, working_hours,
location, requirements, benefits, visa_support, language_level, status, work_mode)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
`, [
jobId,
companyId,
seedUserId,
job.title,
@ -242,7 +243,7 @@ export async function seedLosPollosHermanos() {
ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description
`, [
'Los Pollos Hermanos',
'los-pollos-hermanos',
'Los Pollos Hermanos',
'company',
'66.666.666/0001-66',
'308 Negra Arroyo Lane, Albuquerque, NM 87104',
@ -270,22 +271,24 @@ export async function seedLosPollosHermanos() {
`, ['66666666-6666-6666-6666-666666666666', 'Los Pollos Hermanos', '66.666.666/0001-66']);
// Get company ID
const companyRes = await pool.query("SELECT id FROM companies WHERE slug = 'los-pollos-hermanos'");
const companyId = companyRes.rows[0].id;
// Get company ID (use coreId directly)
const companyId = '66666666-6666-6666-6666-666666666666';
const seedUserRes = await pool.query("SELECT id FROM users WHERE identifier IN ('system_seed', 'wile_e_coyote') LIMIT 1");
const seedUserRes = await pool.query("SELECT id FROM core_users LIMIT 1");
const seedUserId = seedUserRes.rows[0]?.id || 1;
const benefits = ['Frango Grátis (apenas o legal)', 'Plano de Saúde Premium', 'Seguro de Vida Reforçado', 'Carro da Empresa (GPS desativado)'];
for (let i = 0; i < losPollosJobs.length; i++) {
const job = losPollosJobs[i];
const jobId = crypto.randomUUID();
await pool.query(`
INSERT INTO jobs (company_id, created_by, title, description,
INSERT INTO jobs (id, company_id, created_by, title, description,
salary_min, salary_max, salary_type, employment_type, working_hours,
location, requirements, benefits, visa_support, language_level, status, work_mode)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
`, [
jobId,
companyId,
seedUserId,
job.title,
@ -325,7 +328,7 @@ export async function seedSpringfieldNuclear() {
ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description
`, [
'Springfield Nuclear Power Plant',
'springfield-nuclear',
'Springfield Nuclear Power Plant',
'company',
'88.888.888/0001-88',
'100 Industrial Way, Springfield, State Unknown',
@ -355,22 +358,24 @@ export async function seedSpringfieldNuclear() {
`, ['88888888-8888-8888-8888-888888888888', 'Springfield Nuclear Power Plant', '88.888.888/0001-88']);
// Get company ID
const companyRes = await pool.query("SELECT id FROM companies WHERE slug = 'springfield-nuclear'");
const companyId = companyRes.rows[0].id;
// Get company ID (use coreId directly)
const companyId = '88888888-8888-8888-8888-888888888888';
const seedUserRes = await pool.query("SELECT id FROM users WHERE identifier IN ('system_seed', 'wile_e_coyote') LIMIT 1");
const seedUserRes = await pool.query("SELECT id FROM core_users LIMIT 1");
const seedUserId = seedUserRes.rows[0]?.id || 1;
const benefits = ['Tickets de Cafeteria', 'Dosímetro Pessoal', 'Desconto na Taverna do Moe', 'Estacionamento (longe do reator)'];
for (let i = 0; i < springfieldJobs.length; i++) {
const job = springfieldJobs[i];
const jobId = crypto.randomUUID();
await pool.query(`
INSERT INTO jobs (company_id, created_by, title, description,
INSERT INTO jobs (id, company_id, created_by, title, description,
salary_min, salary_max, salary_type, employment_type, working_hours,
location, requirements, benefits, visa_support, language_level, status, work_mode)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
`, [
jobId,
companyId,
seedUserId,
job.title,

View file

@ -1,4 +1,5 @@
import { pool } from '../db.js';
import crypto from 'crypto';
// Job templates for variety
const jobTemplates = [
@ -57,23 +58,29 @@ function getRandomInt(min, max) {
export async function seedJobs() {
console.log('💼 Seeding jobs (25 per company)...');
// Get company IDs
const companiesRes = await pool.query('SELECT id, name FROM companies ORDER BY id');
// Get company IDs from core_companies (jobs.company_id references core_companies.id)
const companiesRes = await pool.query('SELECT id, name FROM core_companies ORDER BY name');
const companies = companiesRes.rows;
if (companies.length === 0) {
console.log(' ⚠️ No companies found. Please seed companies first.');
console.log(' ⚠️ No core_companies found. Please seed companies first.');
return;
}
// Get or create seed user
// Get a user from core_users for created_by FK
const seedUserRes = await pool.query("SELECT id FROM core_users LIMIT 1");
if (seedUserRes.rows.length === 0) {
console.log(' ⚠️ No core_users found. Creating a system user...');
const systemUserId = crypto.randomUUID();
await pool.query(`
INSERT INTO users (identifier, password_hash, role, full_name)
VALUES ('system_seed', '$2b$10$placeholder', 'superadmin', 'System Seeder')
ON CONFLICT (identifier) DO NOTHING
`);
const seedUserRes = await pool.query("SELECT id FROM users WHERE identifier = 'system_seed'");
const seedUserId = seedUserRes.rows[0]?.id || 1;
INSERT INTO core_users (id, name, email, password_hash, status)
VALUES ($1, 'System Seeder', 'system@gohorsejobs.com', '$2b$10$placeholder', 'ACTIVE')
ON CONFLICT (id) DO NOTHING
`, [systemUserId]);
}
const userRes = await pool.query("SELECT id FROM core_users LIMIT 1");
const seedUserId = userRes.rows[0]?.id;
let totalJobs = 0;
@ -91,13 +98,15 @@ export async function seedJobs() {
const employmentTypes = ['full-time', 'part-time', 'contract'];
const employmentType = employmentTypes[i % employmentTypes.length]; // Deterministic variety
const jobId = crypto.randomUUID();
await pool.query(`
INSERT INTO jobs (company_id, created_by, title, description,
INSERT INTO jobs (id, company_id, created_by, title, description,
salary_min, salary_max, salary_type, employment_type, working_hours,
location, requirements, benefits, visa_support, language_level, status, work_mode)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
`, [
jobId,
company.id,
seedUserId,
title,
@ -116,6 +125,7 @@ const employmentTypes = ['full-time', 'part-time', 'contract'];
workMode
]);
totalJobs++;
}
}