136 lines
6.6 KiB
JavaScript
136 lines
6.6 KiB
JavaScript
import { pool } from '../db.js';
|
|
import crypto from 'crypto';
|
|
|
|
// Job templates for variety
|
|
// Job templates for variety (Funny & Serious mix)
|
|
const jobTemplates = [
|
|
// Tech Roles
|
|
{ title: 'Senior Stack Overflow Copy-Paster', skills: ['Ctrl+C', 'Ctrl+V', 'Google Fu'], salaryRange: [120000, 180000] }, // High salary
|
|
{ title: 'Full Stack Overflow Engineer', skills: ['JavaScript', 'Python', 'Chaos Engineering'], salaryRange: [90000, 150000] },
|
|
{ title: 'Frontend Div Centerer', skills: ['CSS', 'Flexbox', 'Patience'], salaryRange: [70000, 120000] },
|
|
{ title: 'Backend JSON Mover', skills: ['Node.js', 'Go', 'REST'], salaryRange: [85000, 140000] },
|
|
{ title: 'Kubernetes YAML Herder', skills: ['Docker', 'K8s', 'Indentations'], salaryRange: [130000, 200000] },
|
|
{ title: 'AI Prompt Whisperer', skills: ['ChatGPT', 'English', 'Imagination'], salaryRange: [60000, 300000] }, // Volatile salary
|
|
{ title: 'Legacy Code Archaeologist', skills: ['COBOL', 'Fortran', 'Dusting'], salaryRange: [150000, 250000] },
|
|
|
|
// Management & Product
|
|
{ title: 'Chief Meeting Scheduler', skills: ['Calendar', 'Zoom', 'Talking'], salaryRange: [100000, 160000] },
|
|
{ title: 'Scrum Master of Puppets', skills: ['Jira', 'Whips', 'Post-its'], salaryRange: [90000, 140000] },
|
|
{ title: 'Product Visionary (Dreamer)', skills: ['Keynote', 'Buzzwords', 'Optimism'], salaryRange: [110000, 190000] },
|
|
|
|
// Design
|
|
{ title: 'Pixel Perfect Pedant', skills: ['Figma', 'Zoom 800%', 'Eye Drops'], salaryRange: [80000, 130000] },
|
|
{ title: 'UX Dark Pattern Architect', skills: ['Psychology', 'Manipulation', 'CSS'], salaryRange: [95000, 155000] },
|
|
|
|
// Financial (The "Banco Desaster" influence)
|
|
{ title: 'Creative Accountant', skills: ['Excel', 'Creativity', 'Obfuscation'], salaryRange: [100000, 500000] },
|
|
{ title: 'High-Frequency Front-Runner', skills: ['C++', 'Low Latency', 'Moral Flexibility'], salaryRange: [200000, 800000] },
|
|
{ title: 'Offshore Database Admin', skills: ['SQL', 'Boat Driving', 'Secrecy'], salaryRange: [120000, 180000] },
|
|
{ title: 'Risk Ignoring Manager', skills: ['Coin Toss', 'Gut Feeling', 'Blindfolds'], salaryRange: [150000, 300000] }
|
|
];
|
|
|
|
const internationalLocations = [
|
|
'New York, NY', 'San Francisco, CA', 'London, UK', 'Berlin, DE', 'Remote (Global)',
|
|
'Silicon Valley, CA', 'Austin, TX', 'Amsterdam, NL', 'Tokyo, JP', 'Singapore, SG',
|
|
'Dubai, UAE', 'Cayman Islands'
|
|
];
|
|
|
|
const workModes = ['onsite', 'hybrid', 'remote'];
|
|
const levels = ['Junior', 'Mid-Level', 'Senior', 'Lead'];
|
|
const benefits = [
|
|
'Health Insurance', 'Dental Plan', 'Gym Membership', 'Stock Options',
|
|
'Remote Work', 'Flexible Hours', 'Annual Bonus', 'Education Budget',
|
|
'Meal Allowance', 'Transport Allowance', 'Home Office Setup', 'Wellness Program'
|
|
];
|
|
|
|
function getRandomItems(arr, count) {
|
|
const shuffled = [...arr].sort(() => 0.5 - Math.random());
|
|
return shuffled.slice(0, count);
|
|
}
|
|
|
|
function getRandomInt(min, max) {
|
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
}
|
|
|
|
export async function seedJobs() {
|
|
console.log('💼 Seeding jobs (25 per company)...');
|
|
|
|
// 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 core_companies found. Please seed companies first.');
|
|
return;
|
|
}
|
|
|
|
|
|
// 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 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;
|
|
|
|
try {
|
|
for (const company of companies) {
|
|
// Generate 25 jobs per company
|
|
for (let i = 0; i < 25; i++) {
|
|
const template = jobTemplates[i % jobTemplates.length];
|
|
const level = levels[i % levels.length];
|
|
const workMode = workModes[i % 3]; // Even distribution: onsite, hybrid, remote
|
|
|
|
const title = i < 33 ? `${level} ${template.title}` : template.title;
|
|
const salaryMin = template.salaryRange[0] + getRandomInt(-2000, 2000);
|
|
const salaryMax = template.salaryRange[1] + getRandomInt(-2000, 3000);
|
|
|
|
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 (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, $17)
|
|
`, [
|
|
jobId,
|
|
company.id,
|
|
seedUserId,
|
|
title,
|
|
`We are looking for a talented ${title} to join our ${company.name} team. Your role as ${level} will be crucial.`,
|
|
salaryMin,
|
|
salaryMax,
|
|
'monthly',
|
|
employmentType,
|
|
workMode === 'remote' ? 'Flexible' : '9:00-18:00',
|
|
workMode === 'remote' ? 'Remote (Global)' : internationalLocations[i % internationalLocations.length],
|
|
JSON.stringify(template.skills),
|
|
JSON.stringify(getRandomItems(benefits, 4)),
|
|
i % 5 === 0, // 20% offer visa support
|
|
'beginner',
|
|
'open',
|
|
workMode
|
|
]);
|
|
|
|
|
|
totalJobs++;
|
|
}
|
|
}
|
|
|
|
console.log(` ✓ ${totalJobs} jobs seeded across ${companies.length} companies`);
|
|
console.log(` 📊 Work mode distribution: ~33% onsite, ~33% hybrid, ~33% remote`);
|
|
} catch (error) {
|
|
console.error(' ❌ Error seeding jobs:', error.message);
|
|
throw error;
|
|
}
|
|
}
|