import fs from 'fs'; const BASE_URL = 'http://localhost:5000/api'; const PASSWORD = 'Admin@123'; const EMAILS = { DD_ADMIN: 'lince@gmail.com', ASM: 'asm.sdelhi@royalenfield.com', RBM: 'rbm.ncr@royalenfield.com', ZBH: 'yashwin@gmail.com', DD_LEAD: 'ddlead@royalenfield.com', LEGAL: 'legal@royalenfield.com', NBH: 'nbh@royalenfield.com', CCO: 'cco@royalenfield.com', CEO: 'ceo@royalenfield.com', SALES: 'sales@royalenfield.com', SERVICE: 'service@royalenfield.com', SPARES: 'spares@royalenfield.com', ACCOUNTS: 'accounts@royalenfield.com', WARRANTY: 'warranty@royalenfield.com', MARKETING: 'marketing@royalenfield.com', HR: 'hr@royalenfield.com', IT: 'it@royalenfield.com', LOGISTICS: 'logistics@royalenfield.com', QUALITY: 'quality@royalenfield.com', APPAREL: 'apparel@royalenfield.com', DMS: 'dms@royalenfield.com' }; async function apiRequest(endpoint, method = 'GET', body = null, token = null) { const headers = { 'Content-Type': 'application/json' }; if (token) headers['Authorization'] = `Bearer ${token}`; const config = { method, headers }; if (body) config.body = JSON.stringify(body); const response = await fetch(`${BASE_URL}${endpoint}`, config); const data = await response.json(); if (!response.ok) { throw new Error(`API Error ${method} ${endpoint}: ${JSON.stringify(data)}`); } return data; } async function login(email) { const data = await apiRequest('/auth/login', 'POST', { email, password: PASSWORD }); return data.token; } const delay = (ms = 500) => new Promise(res => setTimeout(res, ms)); const log = (step, msg) => console.log(`[STEP ${step}] ${msg}`); async function run() { try { console.log('--- STARTING DEALER TERMINATION E2E FLOW ---'); const adminToken = await login(EMAILS.DD_ADMIN); const dealersRes = await apiRequest('/dealer', 'GET', null, adminToken); const targetDealer = dealersRes.data[0]; if (!targetDealer) throw new Error('No dealer profiles found for termination test. Run seed first.'); console.log(`Targeting Dealer: ${targetDealer.legalName} (${targetDealer.id})`); // STEP 1: Submission (ASM) console.log('[STEP 1] ASM Initiating Termination...'); const asmToken = await login(EMAILS.ASM); const createRes = await apiRequest('/termination', 'POST', { dealerId: targetDealer.id, category: 'Performance', reason: 'Consistently failed to meet commitment targets.', proposedLwd: new Date().toISOString(), comments: 'Auto termination for testing flow ending with Legal Team, CCO, CEO.' }, asmToken); const terminationId = createRes.termination.id; console.log(`[STEP 1] Termination Request Created. ID: ${terminationId}`); const approvals = [ { name: 'RBM Review', email: EMAILS.RBM, remarks: 'Performance concerns validated on-ground. Proceed with termination.' }, { name: 'ZBH Review', email: EMAILS.ZBH, remarks: 'Strategic decision aligned with regional growth targets. Approved.' }, { name: 'DD Lead Review', email: EMAILS.DD_LEAD, remarks: 'Contractual breaches documented. Verified.' }, { name: 'Legal Verification', email: EMAILS.LEGAL, remarks: 'Legal audit complete. Case is legally sound.' }, { name: 'DD Head Review', email: EMAILS.NBH, remarks: 'Strategic impact assessed. Proceeding with SCN approval.' }, { name: 'NBH Evaluation', email: EMAILS.NBH, remarks: 'Functional teams aligned. SCN to be issued.' }, { name: 'SCN Issued', email: EMAILS.NBH, remarks: 'Show Cause Notice formally dispatched.' }, { name: 'Personal Hearing Outcome', email: EMAILS.DD_LEAD, remarks: 'Hearing completed. Dealer defense not sufficient.' }, { name: 'NBH Final Approval', email: EMAILS.NBH, remarks: 'Final recommendation for termination sent to CEO.' }, { name: 'CCO Approval', email: EMAILS.CCO, remarks: 'Commercial impact assessed. Approved.' }, { name: 'CEO Final Approval', email: EMAILS.CEO, remarks: 'Final authorization granted. Issue termination letter.' }, { name: 'Legal Termination Letter', email: EMAILS.LEGAL, remarks: 'Termination letter shared via registered mail.' }, { name: 'Final Terminated Status', email: EMAILS.DD_ADMIN, remarks: 'Closure completed.' } ]; let currentStep = 2; for (const actor of approvals) { log(currentStep, `${actor.name} (${actor.email}) processing approval...`); const token = await login(actor.email); await apiRequest(`/termination/${terminationId}/status`, 'PUT', { action: 'approve', remarks: actor.remarks }, token); log(currentStep, `${actor.name} Result: SUCCESS`); currentStep++; await delay(); } // --- NEW: F&F CLEARANCE LOOP (16 DEPARTMENTS) --- log(13, 'Starting 16-Department F&F Clearance Flow for Termination...'); const terminationData = await apiRequest(`/termination/${terminationId}`, 'GET', null, adminToken); const fnfId = terminationData.termination.fnfSettlement?.id; if (!fnfId) { log('SKIP', 'FnF Settlement not initialized for this termination case.'); } else { const departments = [ { name: 'Warranty Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'No pending claims.' }, { name: 'Accessories Department', status: 'Dues', amount: 15000, type: 'Recovery', remarks: 'Shortage in accessory stock.' }, { name: 'Sales Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'Allocations transferred.' }, { name: 'RTO Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'No dues.' }, { name: 'Service Department', status: 'Dues', amount: 8000, type: 'Recovery', remarks: 'Loaner vehicle damange charges.' }, { name: 'Parts Department', status: 'Dues', amount: 20000, type: 'Payable', remarks: 'Return parts credit.' }, { name: 'Finance Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'No interest dues.' }, { name: 'Insurance Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'No dues.' }, { name: 'Inventory Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'Inventory handed over.' }, { name: 'Marketing Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'No dues.' }, { name: 'HR Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'Staff settlement clear.' }, { name: 'IT Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'Hardware recovered.' }, { name: 'Legal Department', status: 'Dues', amount: 50000, type: 'Recovery', remarks: 'Litigation cost recovery as per agreement.' }, { name: 'Quality Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'No dues.' }, { name: 'Logistics Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'No dues.' }, { name: 'Customer Relations Department', status: 'Cleared', amount: 0, type: 'Recovery', remarks: 'No dues.' } ]; for (const dept of departments) { log('13.1', `Clearing Dept: ${dept.name} [${dept.status}] - ${dept.remarks}`); await apiRequest(`/termination/${terminationId}/clearance`, 'PUT', { department: dept.name, status: dept.status, remarks: dept.remarks, amount: dept.amount, type: dept.type }, adminToken); await delay(100); } log(13, 'All 16 Departments Cleared for Termination.'); await delay(); } console.log('[FINAL STEP] Verifying Terminated Status & Account Deactivation...'); const finalDetails = await apiRequest(`/termination/${terminationId}`, 'GET', null, adminToken); console.log(`Final Stage REACHED: ${finalDetails.termination.currentStage}`); // Fetch user data to verify deactivation const userRes = await apiRequest(`/admin/users`, 'GET', null, adminToken); const dealerUser = userRes.data.find(u => u.dealerId === targetDealer.id); if (dealerUser && !dealerUser.isActive && dealerUser.status === 'deactivated') { console.log(`[VERIFICATION] Account ${dealerUser.email} successfully DEACTIVATED.`); } else { console.error(`[VERIFICATION] Failed: Account ${dealerUser?.email} is still active. Status: ${dealerUser?.status}`); throw new Error('Automated account deactivation check failed.'); } console.log('\n--- VERIFICATION SUCCESSFUL ---'); console.log('Outcome: DEALER TERMINATED & PORTAL ACCESS REVOKED'); process.exit(0); } catch (error) { console.error('Workflow failed:', error.message); process.exit(1); } } run();