219 lines
11 KiB
TypeScript
219 lines
11 KiB
TypeScript
/**
|
|
* Seed script to initialize interview configurations
|
|
* with the existing system-default questions.
|
|
*
|
|
* Run: npx tsx scripts/seed-interview-configs.ts
|
|
*/
|
|
|
|
import 'dotenv/config';
|
|
import db from '../src/database/models/index.js';
|
|
|
|
async function seedInterviewConfigs() {
|
|
const { sequelize, InterviewConfig, InterviewConfigItem, InterviewConfigItemOption } = db as any;
|
|
await sequelize.authenticate();
|
|
console.log('Database connected.');
|
|
|
|
// Ensure tables exist
|
|
await sequelize.sync({ alter: true });
|
|
console.log('Tables synced.');
|
|
|
|
// --- KT Matrix ---
|
|
const ktMatrixItems = [
|
|
{ itemKey: 'age', label: 'Age', weight: 5, maxScore: 10, order: 1, options: [
|
|
{ optionLabel: '20 to 40 years old', optionValue: '20-40', score: 10, order: 1 },
|
|
{ optionLabel: '40 to 50 years old', optionValue: '40-50', score: 5, order: 2 },
|
|
{ optionLabel: 'Above 50 years old', optionValue: 'above-50', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'qualification', label: 'Qualification', weight: 5, maxScore: 10, order: 2, options: [
|
|
{ optionLabel: 'Post Graduate', optionValue: 'post-graduate', score: 10, order: 1 },
|
|
{ optionLabel: 'Graduate', optionValue: 'graduate', score: 5, order: 2 },
|
|
{ optionLabel: 'SSLC', optionValue: 'sslc', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'localKnowledge', label: 'Local Knowledge and Influence', weight: 5, maxScore: 10, order: 3, options: [
|
|
{ optionLabel: 'Excellent PR', optionValue: 'excellent', score: 10, order: 1 },
|
|
{ optionLabel: 'Good PR', optionValue: 'good', score: 5, order: 2 },
|
|
{ optionLabel: 'Poor PR', optionValue: 'poor', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'baseLocation', label: 'Base Location vs Applied Location', weight: 10, maxScore: 10, order: 4, options: [
|
|
{ optionLabel: 'Native of the Applied location', optionValue: 'native', score: 10, order: 1 },
|
|
{ optionLabel: 'Willing to relocate', optionValue: 'relocate', score: 5, order: 2 },
|
|
{ optionLabel: 'Will manage remotely with occasional visits', optionValue: 'remote', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'whyInterested', label: 'Why Interested in Royal Enfield Business?', weight: 10, maxScore: 10, order: 5, options: [
|
|
{ optionLabel: 'Passion', optionValue: 'passion', score: 10, order: 1 },
|
|
{ optionLabel: 'Business expansion / Status symbol', optionValue: 'business', score: 5, order: 2 },
|
|
]},
|
|
{ itemKey: 'passionRe', label: 'Passion for Royal Enfield', weight: 10, maxScore: 10, order: 6, options: [
|
|
{ optionLabel: 'Currently owns a Royal Enfield', optionValue: 'owns', score: 10, order: 1 },
|
|
{ optionLabel: 'Owned by Immediate Relative', optionValue: 'relative', score: 5, order: 2 },
|
|
{ optionLabel: 'Does not own Royal Enfield', optionValue: 'none', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'passionRides', label: 'Passion For Rides', weight: 10, maxScore: 10, order: 7, options: [
|
|
{ optionLabel: 'Goes for long rides regularly', optionValue: 'regular', score: 10, order: 1 },
|
|
{ optionLabel: 'Goes for long rides rarely', optionValue: 'rarely', score: 5, order: 2 },
|
|
{ optionLabel: "Doesn't go for rides", optionValue: 'never', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'partnering', label: 'With Whom Partnering?', weight: 5, maxScore: 10, order: 8, options: [
|
|
{ optionLabel: 'Within family', optionValue: 'family', score: 10, order: 1 },
|
|
{ optionLabel: 'Outside family', optionValue: 'outside', score: 0, order: 2 },
|
|
]},
|
|
{ itemKey: 'whoManages', label: 'Who Will Manage the Firm?', weight: 10, maxScore: 10, order: 9, options: [
|
|
{ optionLabel: 'Owner managed', optionValue: 'owner', score: 10, order: 1 },
|
|
{ optionLabel: 'Partly owner / partly manager model', optionValue: 'partly', score: 5, order: 2 },
|
|
{ optionLabel: 'Fully manager model', optionValue: 'manager', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'businessAcumen', label: 'Business Acumen', weight: 5, maxScore: 10, order: 10, options: [
|
|
{ optionLabel: 'Has similar automobile experience', optionValue: 'automobile', score: 10, order: 1 },
|
|
{ optionLabel: 'Has successful business but not automobile', optionValue: 'other-business', score: 5, order: 2 },
|
|
{ optionLabel: 'No business experience', optionValue: 'no-experience', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'timeAvailability', label: 'Time Availability', weight: 5, maxScore: 10, order: 11, options: [
|
|
{ optionLabel: 'Full Time Availability for RE Business', optionValue: 'full-time', score: 10, order: 1 },
|
|
{ optionLabel: 'Part Time Availability for RE Business', optionValue: 'part-time', score: 5, order: 2 },
|
|
{ optionLabel: 'Not Available personally, Manager will handle', optionValue: 'manager', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'propertyOwnership', label: 'Property Ownership', weight: 5, maxScore: 10, order: 12, options: [
|
|
{ optionLabel: 'Has own property in proposed location', optionValue: 'own', score: 10, order: 1 },
|
|
{ optionLabel: 'Will rent / lease', optionValue: 'rent', score: 0, order: 2 },
|
|
]},
|
|
{ itemKey: 'investment', label: 'Investment in the Business', weight: 5, maxScore: 10, order: 13, options: [
|
|
{ optionLabel: 'Full own funds', optionValue: 'own-funds', score: 10, order: 1 },
|
|
{ optionLabel: 'Partially from the bank', optionValue: 'partial-bank', score: 5, order: 2 },
|
|
{ optionLabel: 'Completely bank funded', optionValue: 'full-bank', score: 0, order: 3 },
|
|
]},
|
|
{ itemKey: 'expandOtherOems', label: 'Will Expand to Other 2W/4W OEMs?', weight: 5, maxScore: 10, order: 14, options: [
|
|
{ optionLabel: 'No', optionValue: 'no', score: 10, order: 1 },
|
|
{ optionLabel: 'Yes', optionValue: 'yes', score: 0, order: 2 },
|
|
]},
|
|
{ itemKey: 'expansionPlans', label: 'Plans of Expansion with RE', weight: 5, maxScore: 10, order: 15, options: [
|
|
{ optionLabel: 'Immediate blood relation will join & expand', optionValue: 'blood-relation', score: 10, order: 1 },
|
|
{ optionLabel: 'Wants to expand by himself into more clusters', optionValue: 'self-expand', score: 5, order: 2 },
|
|
{ optionLabel: 'No plans for expansion', optionValue: 'no-plans', score: 0, order: 3 },
|
|
]},
|
|
];
|
|
|
|
// --- Level 2 Feedback ---
|
|
const level2Items = [
|
|
{ itemKey: 'strategicVision', label: 'Strategic Vision', type: 'textarea' as const, isRequired: true, order: 1 },
|
|
{ itemKey: 'managementCapabilities', label: 'Management Capabilities', type: 'textarea' as const, isRequired: true, order: 2 },
|
|
{ itemKey: 'operationalUnderstanding', label: 'Operational Understanding', type: 'textarea' as const, isRequired: true, order: 3 },
|
|
{ itemKey: 'keyStrengths', label: 'Key Strengths', type: 'textarea' as const, isRequired: true, order: 4 },
|
|
{ itemKey: 'areasOfConcern', label: 'Areas of Concern', type: 'textarea' as const, isRequired: true, order: 5 },
|
|
{ itemKey: 'additionalComments', label: 'Additional Comments', type: 'textarea' as const, isRequired: false, order: 6 },
|
|
];
|
|
|
|
// --- Level 3 Feedback ---
|
|
const level3Items = [
|
|
{ itemKey: 'strategicVision', label: 'Business Vision & Strategy', type: 'textarea' as const, isRequired: true, order: 1 },
|
|
{ itemKey: 'managementCapabilities', label: 'Leadership & Decision Making', type: 'textarea' as const, isRequired: true, order: 2 },
|
|
{ itemKey: 'operationalUnderstanding', label: 'Operational & Financial Readiness', type: 'textarea' as const, isRequired: true, order: 3 },
|
|
{ itemKey: 'brandAlignment', label: 'Brand Alignment', type: 'textarea' as const, isRequired: true, order: 4 },
|
|
{ itemKey: 'keyStrengths', label: 'Key Strengths', type: 'textarea' as const, isRequired: true, order: 5 },
|
|
{ itemKey: 'areasOfConcern', label: 'Areas of Concern', type: 'textarea' as const, isRequired: true, order: 6 },
|
|
{ itemKey: 'executiveSummary', label: 'Executive Summary', type: 'textarea' as const, isRequired: true, order: 7 },
|
|
{ itemKey: 'additionalComments', label: 'Additional Comments', type: 'textarea' as const, isRequired: false, order: 8 },
|
|
];
|
|
|
|
const transaction = await sequelize.transaction();
|
|
|
|
try {
|
|
// Deactivate any existing configs
|
|
await InterviewConfig.update({ isActive: false }, { where: {}, transaction });
|
|
|
|
// Create KT Matrix Config
|
|
const ktConfig = await InterviewConfig.create({
|
|
configType: 'KT_MATRIX',
|
|
name: 'System Default KT Matrix',
|
|
version: 'v1.0',
|
|
isActive: true,
|
|
}, { transaction });
|
|
|
|
for (const item of ktMatrixItems) {
|
|
const createdItem = await InterviewConfigItem.create({
|
|
configId: ktConfig.id,
|
|
itemKey: item.itemKey,
|
|
label: item.label,
|
|
type: 'select',
|
|
order: item.order,
|
|
isRequired: true,
|
|
weight: item.weight,
|
|
maxScore: item.maxScore,
|
|
}, { transaction });
|
|
|
|
if (item.options) {
|
|
await InterviewConfigItemOption.bulkCreate(
|
|
item.options.map((o: any) => ({
|
|
itemId: createdItem.id,
|
|
optionLabel: o.optionLabel,
|
|
optionValue: o.optionValue,
|
|
score: o.score,
|
|
order: o.order,
|
|
})),
|
|
{ transaction }
|
|
);
|
|
}
|
|
}
|
|
|
|
// Create Level 2 Config
|
|
const l2Config = await InterviewConfig.create({
|
|
configType: 'LEVEL2_FEEDBACK',
|
|
name: 'System Default Level 2 Feedback',
|
|
version: 'v1.0',
|
|
isActive: true,
|
|
}, { transaction });
|
|
|
|
await InterviewConfigItem.bulkCreate(
|
|
level2Items.map((item) => ({
|
|
configId: l2Config.id,
|
|
itemKey: item.itemKey,
|
|
label: item.label,
|
|
type: item.type,
|
|
order: item.order,
|
|
isRequired: item.isRequired,
|
|
weight: null,
|
|
maxScore: null,
|
|
})),
|
|
{ transaction }
|
|
);
|
|
|
|
// Create Level 3 Config
|
|
const l3Config = await InterviewConfig.create({
|
|
configType: 'LEVEL3_FEEDBACK',
|
|
name: 'System Default Level 3 Feedback',
|
|
version: 'v1.0',
|
|
isActive: true,
|
|
}, { transaction });
|
|
|
|
await InterviewConfigItem.bulkCreate(
|
|
level3Items.map((item) => ({
|
|
configId: l3Config.id,
|
|
itemKey: item.itemKey,
|
|
label: item.label,
|
|
type: item.type,
|
|
order: item.order,
|
|
isRequired: item.isRequired,
|
|
weight: null,
|
|
maxScore: null,
|
|
})),
|
|
{ transaction }
|
|
);
|
|
|
|
await transaction.commit();
|
|
console.log('Interview configurations seeded successfully.');
|
|
console.log(` - KT Matrix: ${ktMatrixItems.length} criteria`);
|
|
console.log(` - Level 2 Feedback: ${level2Items.length} fields`);
|
|
console.log(` - Level 3 Feedback: ${level3Items.length} fields`);
|
|
} catch (error) {
|
|
await transaction.rollback();
|
|
console.error('Seeding failed:', error);
|
|
throw error;
|
|
} finally {
|
|
await sequelize.close();
|
|
}
|
|
}
|
|
|
|
seedInterviewConfigs().catch((err) => {
|
|
console.error(err);
|
|
process.exit(1);
|
|
});
|