134 lines
5.3 KiB
TypeScript
134 lines
5.3 KiB
TypeScript
import 'dotenv/config';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import db from '../src/database/models/index.js';
|
|
import { syncLocationManagers, syncRegionManager, syncZoneManager } from '../src/modules/master/syncHierarchy.service.js';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
async function run() {
|
|
console.log('--- Seeding Real Geo Data (District -> Area Hierarchy) ---');
|
|
try {
|
|
await db.sequelize.authenticate();
|
|
|
|
// Read the source seeder file
|
|
const seederPath = path.join(__dirname, '../seeders/20240127-seed-geo-data.js');
|
|
const content = fs.readFileSync(seederPath, 'utf8');
|
|
|
|
// Extract arrays using regex
|
|
const zonesMatch = content.match(/const ZONES_DATA = \[([\s\S]*?)\];/);
|
|
const statesMatch = content.match(/const STATES_DATA = \[([\s\S]*?)\];/);
|
|
const citiesMatch = content.match(/const CITIES_DATA = \[([\s\S]*?)\];/);
|
|
|
|
if (!zonesMatch || !statesMatch || !citiesMatch) {
|
|
throw new Error('Could not parse geo data arrays from seeder file!');
|
|
}
|
|
|
|
// Eval helper (data is trusted since it's our own seeder)
|
|
const ZONES_DATA = eval(`[${zonesMatch[1]}]`);
|
|
const STATES_DATA = eval(`[${statesMatch[1]}]`);
|
|
const CITIES_DATA = eval(`[${citiesMatch[1]}]`);
|
|
|
|
console.log(`Extracted ${ZONES_DATA.length} Zones, ${STATES_DATA.length} States, and ${CITIES_DATA.length} Cities.`);
|
|
|
|
const { Zone, State, District, Location, Opportunity } = db;
|
|
|
|
// 1. Seed Zones
|
|
const zoneIdMap = new Map(); // Name -> UUID
|
|
for (const z of ZONES_DATA) {
|
|
const [zoneRecord] = await Zone.findOrCreate({
|
|
where: { name: z.name },
|
|
defaults: { name: z.name, code: z.code }
|
|
});
|
|
zoneIdMap.set(z.name, zoneRecord.id);
|
|
}
|
|
console.log('Zones seeded.');
|
|
|
|
// 2. Seed States and link to Zones
|
|
const stateIdMap = new Map(); // Legacy ID -> { id, zoneId }
|
|
for (const s of STATES_DATA) {
|
|
const parentZoneData = ZONES_DATA.find((z: any) => z.states.includes(s.name));
|
|
const zoneId = parentZoneData ? zoneIdMap.get(parentZoneData.name) : null;
|
|
|
|
const [stateRecord] = await State.findOrCreate({
|
|
where: { name: s.name },
|
|
defaults: { name: s.name, zoneId: zoneId }
|
|
});
|
|
|
|
stateIdMap.set(s.id, { id: stateRecord.id, zoneId: zoneId });
|
|
}
|
|
console.log('States seeded.');
|
|
|
|
// 3. Seed Districts and Areas (Locations)
|
|
let districtCount = 0;
|
|
let areaCount = 0;
|
|
let opportunityCount = 0;
|
|
|
|
for (const c of CITIES_DATA) {
|
|
const parentStateData = stateIdMap.get(c.state_id);
|
|
if (parentStateData) {
|
|
// a. Create District (Primary territory entity)
|
|
const [districtRecord] = await District.findOrCreate({
|
|
where: { name: c.name, stateId: parentStateData.id },
|
|
defaults: {
|
|
name: c.name,
|
|
stateId: parentStateData.id,
|
|
zoneId: parentStateData.zoneId
|
|
}
|
|
});
|
|
districtCount++;
|
|
|
|
// b. Create Area (Granular Location record)
|
|
const [areaRecord] = await Location.findOrCreate({
|
|
where: { name: c.name, districtId: districtRecord.id },
|
|
defaults: {
|
|
name: c.name,
|
|
city: c.name,
|
|
districtId: districtRecord.id,
|
|
isActive: true
|
|
}
|
|
});
|
|
areaCount++;
|
|
|
|
// c. Create associated Opportunity
|
|
const [oppRecord, created] = await Opportunity.findOrCreate({
|
|
where: { areaId: areaRecord.id },
|
|
defaults: {
|
|
districtId: districtRecord.id,
|
|
areaId: areaRecord.id, // Linking to Area!
|
|
city: c.name,
|
|
status: 'inactive',
|
|
opportunityType: 'New Dealership',
|
|
capacity: 'Standard',
|
|
priority: 'Medium',
|
|
notes: 'Automatically generated from district seed'
|
|
}
|
|
});
|
|
if (created) opportunityCount++;
|
|
}
|
|
}
|
|
console.log(`✅ Seeded ${districtCount} Districts, ${areaCount} Areas, and ${opportunityCount} Opportunities.`);
|
|
|
|
console.log('--- Triggering Hierarchy Synchronization ---');
|
|
const districts = await District.findAll({ attributes: ['id'] });
|
|
for (const d of districts) await syncLocationManagers(d.id);
|
|
|
|
const regions = await db.Region.findAll({ attributes: ['id'] });
|
|
for (const r of regions) await syncRegionManager(r.id);
|
|
|
|
const zonesArr = await Zone.findAll({ attributes: ['id'] });
|
|
for (const z of zonesArr) await syncZoneManager(z.id);
|
|
|
|
console.log('--- Synchronization Complete ---');
|
|
process.exit(0);
|
|
|
|
} catch (e: any) {
|
|
console.error('❌ Failed:', e.message);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
run();
|