import 'dotenv/config'; import db from '../src/database/models/index.js'; import bcrypt from 'bcryptjs'; import { syncLocationManagers, syncRegionManager, syncZoneManager } from '../src/modules/master/syncHierarchy.service.js'; import { APPLICATION_STAGES, APPLICATION_STATUS, BUSINESS_TYPES } from '../src/common/config/constants.js'; const { Role, Zone, Region, State, District, User, UserRole } = db; async function seed() { console.log('--- Seeding Comprehensive Golden Path Data ---'); await db.sequelize.authenticate(); await db.sequelize.sync({ alter: false }); const hashedPassword = await bcrypt.hash('Admin@123', 10); // 1. Ensure Roles exist const roles = [ { roleCode: 'NBH', roleName: 'National Business Head', category: 'NATIONAL' }, { roleCode: 'DD Head', roleName: 'DD Head', category: 'NATIONAL' }, { roleCode: 'ZBH', roleName: 'Zonal Business Head', category: 'ZONAL' }, { roleCode: 'DD Lead', roleName: 'DD Lead', category: 'ZONAL' }, { roleCode: 'RBM', roleName: 'Regional Business Manager', category: 'REGIONAL' }, { roleCode: 'DD-ZM', roleName: 'DD Zonal Manager', category: 'ZONAL' }, { roleCode: 'ASM', roleName: 'Area Sales Manager', category: 'AREA' }, { roleCode: 'Super Admin', roleName: 'Super Admin', category: 'NATIONAL' }, { roleCode: 'Finance', roleName: 'Finance', category: 'DEPARTMENT' }, { roleCode: 'Dealer', roleName: 'Dealer', category: 'EXTERNAL' }, { roleCode: 'DD Admin', roleName: 'DD Admin', category: 'ADMIN' }, { roleCode: 'ARCHITECTURE', roleName: 'Architecture Team', category: 'DEPARTMENT' }, { roleCode: 'FDD', roleName: 'FDD Team', category: 'EXTERNAL' } ]; for (const r of roles) { await Role.findOrCreate({ where: { roleCode: r.roleCode }, defaults: r }); } const mapUserRole = async (userRec: any, roleCode: string, assignment: any = {}) => { const role = await Role.findOne({ where: { roleCode } }); if (role) { await UserRole.findOrCreate({ where: { userId: userRec.id, roleId: role.id, ...assignment }, defaults: { userId: userRec.id, roleId: role.id, ...assignment, isActive: true, isPrimary: true } }); } }; // 2. Create Hierarchical Structure // Zones const zones = [ { name: 'North Zone', code: 'ZONE-N' }, { name: 'South Zone', code: 'ZONE-S' } ]; const zoneMap: Record = {}; for (const z of zones) { const [zone] = await Zone.findOrCreate({ where: { name: z.name }, defaults: z }); zoneMap[z.name] = zone; } // Regions const regions = [ { name: 'NCR Region', zoneName: 'North Zone' }, { name: 'Punjab Region', zoneName: 'North Zone' }, { name: 'Karnataka Region', zoneName: 'South Zone' }, { name: 'Tamil Nadu Region', zoneName: 'South Zone' } ]; const regionMap: Record = {}; for (const r of regions) { const zone = zoneMap[r.zoneName]; const [region] = await Region.findOrCreate({ where: { name: r.name }, defaults: { name: r.name, zoneId: zone.id } }); regionMap[r.name] = region; } // 3. States & Districts (Mapping South Delhi to NCR) const ncrRegion = regionMap['NCR Region']; const [delhiState] = await State.findOrCreate({ where: { name: 'DELHI' }, defaults: { name: 'DELHI', zoneId: ncrRegion.zoneId } }); const [southDelhi] = await District.findOrCreate({ where: { name: 'South Delhi' }, defaults: { name: 'South Delhi', stateId: delhiState.id, regionId: ncrRegion.id, zoneId: ncrRegion.zoneId, isActive: true } }); // Ensure it's explicitly under NCR await southDelhi.update({ regionId: ncrRegion.id }); console.log('✅ Mapping: South Delhi -> NCR Region'); // 3. Create Key Management Users // National / Administrative const nationalUsers = [ { email: 'nbh@royalenfield.com', name: 'Alwyn John', role: 'NBH' }, { email: 'ddhead@royalenfield.com', name: 'Vikram Singh', role: 'DD Head' }, { email: 'finance@royalenfield.com', name: 'Rahul Verma', role: 'Finance' }, { email: 'admin@royalenfield.com', name: 'Laxman H', role: 'Super Admin' }, { email: 'lince@gmail.com', name: 'Lince', role: 'DD Admin' }, { email: 'fdd@royalenfield.com', name: 'FDD Partner', role: 'FDD' }, { email: 'architecture@royalenfield.com', name: 'RE Architect', role: 'ARCHITECTURE' } ]; for (const u of nationalUsers) { const [user] = await User.findOrCreate({ where: { email: u.email }, defaults: { fullName: u.name, roleCode: u.role, password: hashedPassword, status: 'active' } }); await mapUserRole(user, u.role); } // Frontend Mock Users for Quick Login (Ensuring exact matches) const frontendMocks = [ { email: 'ddlead@royalenfield.com', name: 'Meera Iyer', role: 'DD Lead', zone: 'North Zone' }, { email: 'yashwin@gmail.com', name: 'Yashwin', role: 'ZBH', zone: 'North Zone' }, { email: 'kenil@gmail.com', name: 'Kenil', role: 'DD Lead', zone: 'North Zone' }, { email: 'dealer@royalenfield.com', name: 'Amit Sharma', role: 'Dealer', district: 'South Delhi' } ]; for (const m of frontendMocks) { const assignment: any = {}; if (m.zone) assignment.zoneId = zoneMap[m.zone].id; if (m.district) { const d = await District.findOne({ where: { name: m.district } }); if (d) { assignment.districtId = d.id; assignment.zoneId = d.zoneId; assignment.regionId = d.regionId; } } const [user] = await User.findOrCreate({ where: { email: m.email }, defaults: { fullName: m.name, roleCode: m.role, password: hashedPassword, status: 'active' } }); await mapUserRole(user, m.role, assignment); } // Zonal Business Heads (Additional) const zbhUsers = [ { email: 'zbh.south@royalenfield.com', name: 'Srinivasan K', zone: 'South Zone' } ]; for (const u of zbhUsers) { const zone = zoneMap[u.zone]; const [user] = await User.findOrCreate({ where: { email: u.email }, defaults: { fullName: u.name, roleCode: 'ZBH', password: hashedPassword, status: 'active' } }); await mapUserRole(user, 'ZBH', { zoneId: zone.id }); } // Regional Managers (RBMs) const rbmUsers = [ { email: 'rbm.ncr@royalenfield.com', name: 'Sanjay Dutt', region: 'NCR Region' }, { email: 'rbm.punjab@royalenfield.com', name: 'Harpreet Singh', region: 'Punjab Region' }, { email: 'rbm.kar@royalenfield.com', name: 'Manish Kumar', region: 'Karnataka Region' } ]; for (const u of rbmUsers) { const region = regionMap[u.region]; const [user] = await User.findOrCreate({ where: { email: u.email }, defaults: { fullName: u.name, roleCode: 'RBM', password: hashedPassword, status: 'active' } }); await mapUserRole(user, 'RBM', { regionId: region.id, zoneId: region.zoneId }); } // Zonal Managers (DD-ZM) - Assigned to Regions const zmUsers = [ { email: 'zm.ncr@royalenfield.com', name: 'Rajesh Khanna', region: 'NCR Region' }, { email: 'zm.south@royalenfield.com', name: 'Kartik Subbaraj', region: 'Karnataka Region' } ]; for (const u of zmUsers) { const region = regionMap[u.region]; const [user] = await User.findOrCreate({ where: { email: u.email }, defaults: { fullName: u.name, roleCode: 'DD-ZM', password: hashedPassword, status: 'active' } }); await mapUserRole(user, 'DD-ZM', { regionId: region.id, zoneId: region.zoneId }); } // ASMs (Assigned to Districts) const asmUsers = [ { email: 'asm.sdelhi@royalenfield.com', name: 'Arun Jaitley', district: 'South Delhi' }, { email: 'asm.noida@royalenfield.com', name: 'Kishan Reddy', district: 'NOIDA' }, { email: 'asm.bangalore@royalenfield.com', name: 'Vishnu Dev', district: 'Bangalore Urban' } ]; for (const u of asmUsers) { const district = await District.findOne({ where: { name: u.district } }); if (district) { const [user] = await User.findOrCreate({ where: { email: u.email }, defaults: { fullName: u.name, roleCode: 'ASM', password: hashedPassword, status: 'active' } }); await mapUserRole(user, 'ASM', { districtId: district.id, zoneId: district.zoneId, regionId: district.regionId }); } } // 10. Create Test Dealer for Offboarding Workflows console.log('🌱 Creating Test Dealer for Offboarding...'); const dealerUser = await User.findOne({ where: { email: 'dealer@royalenfield.com' } }); const asmUser = await User.findOne({ where: { email: 'asm.sdelhi@royalenfield.com' } }); if (dealerUser && southDelhi) { // 1. Create Placeholder Application (The "Golden Path" root) const [application] = await db.Application.findOrCreate({ where: { applicationId: 'APP-TEST-001' }, defaults: { applicationId: 'APP-TEST-001', applicantName: 'Amit Sharma', email: 'dealer@royalenfield.com', phone: '9876543210', businessType: BUSINESS_TYPES.DEALERSHIP, submittedBy: dealerUser.id, // Corrected: Prospect/Applicant initiates the request constitutionType: 'Private Limited', currentStage: APPLICATION_STAGES.APPROVED, overallStatus: APPLICATION_STATUS.ONBOARDED, progressPercentage: 100, isShortlisted: true, districtId: southDelhi.id, documents: [] } }); // 2. Create SAP/Dealer Codes (Dependency for Dealer Profile) const [dealerCodeRecord] = await db.DealerCode.findOrCreate({ where: { dealerCode: 'D1001' }, defaults: { dealerCode: 'D1001', applicationId: application.id, salesCode: 'S1001', serviceCode: 'V1001', gmaCode: 'G1001', gearCode: 'GE1001', sapMasterId: 'SAP-999', status: 'active' } }); // 3. Create Dealer Profile (Linked to App and Code) const [dealerProfile] = await db.Dealer.findOrCreate({ where: { applicationId: application.id }, defaults: { applicationId: application.id, dealerCodeId: dealerCodeRecord.id, legalName: 'Amit Sharma Dealership Pvt Ltd', businessName: 'Royal Enfield South Delhi', constitutionType: 'Private Limited', status: 'active', onboardedAt: new Date() } }); // 4. Update Dealer User to link to the Dealer Profile await dealerUser.update({ dealerId: dealerProfile.id }); // 5. Create Main Outlet // Note: As per Outlet model, dealerId refers to the User ID (Owner) await db.Outlet.findOrCreate({ where: { code: 'O001' }, defaults: { dealerId: dealerUser.id, // Linked to the User ID as owner name: 'Main Outlet - South Delhi', code: 'O001', type: 'Dealership', address: '123, MG Road, South Delhi', city: 'Delhi', state: 'Delhi', pincode: '110001', establishedDate: new Date('2020-01-01'), districtId: southDelhi.id, status: 'Active' } }); console.log('✅ Successfully seeded Golden Path: Application -> DealerCode -> Dealer Profile -> User -> Outlet'); } console.log('--- Triggering Hierarchy Synchronization ---'); // ... (rest same) console.log('--- Golden Path Seeding Complete ---'); } seed().catch(err => { console.error(err); process.exit(1); }).then(() => process.exit(0));