tab filters in differnt module changes and amount update from F&F fixed checking for the dues update from two placeds finance & normal departmental response need to finalisre one

This commit is contained in:
laxman h 2026-04-16 17:44:14 +05:30
parent 96edda54d9
commit 7fbf134cf1
4 changed files with 307 additions and 246 deletions

View File

@ -310,7 +310,9 @@ export const approveResignation = async (req: AuthRequest, res: Response, next:
[RESIGNATION_STAGES.DD_LEAD]: RESIGNATION_STAGES.NBH, [RESIGNATION_STAGES.DD_LEAD]: RESIGNATION_STAGES.NBH,
[RESIGNATION_STAGES.NBH]: RESIGNATION_STAGES.DD_ADMIN, [RESIGNATION_STAGES.NBH]: RESIGNATION_STAGES.DD_ADMIN,
[RESIGNATION_STAGES.DD_ADMIN]: RESIGNATION_STAGES.LEGAL, [RESIGNATION_STAGES.DD_ADMIN]: RESIGNATION_STAGES.LEGAL,
[RESIGNATION_STAGES.LEGAL]: RESIGNATION_STAGES.FNF_INITIATED, // Legal approval should complete only the Legal stage.
// F&F initiation is explicitly triggered via `pushfnf` action (with LWD/force gates).
[RESIGNATION_STAGES.LEGAL]: RESIGNATION_STAGES.LEGAL,
[RESIGNATION_STAGES.FNF_INITIATED]: RESIGNATION_STAGES.COMPLETED [RESIGNATION_STAGES.FNF_INITIATED]: RESIGNATION_STAGES.COMPLETED
}; };
@ -320,6 +322,22 @@ export const approveResignation = async (req: AuthRequest, res: Response, next:
return res.status(400).json({ success: false, message: 'Cannot move to next stage from current state' }); return res.status(400).json({ success: false, message: 'Cannot move to next stage from current state' });
} }
// Guard before transition: F&F initiation is allowed only on/after LWD unless forced.
if (nextStage === RESIGNATION_STAGES.FNF_INITIATED) {
const today = new Date();
const lwd = resignation.lastOperationalDateServices || resignation.lastOperationalDateSales;
const { force } = req.body;
if (!force && lwd && today < new Date(lwd)) {
await transaction.rollback();
return res.status(400).json({
success: false,
message: `F&F can only be initiated on or after the Last Working Day (${lwd}).`,
canForce: true
});
}
}
// Sequence guard: resignation can be marked completed only after F&F settlement is complete. // Sequence guard: resignation can be marked completed only after F&F settlement is complete.
if ( if (
resignation.currentStage === RESIGNATION_STAGES.FNF_INITIATED && resignation.currentStage === RESIGNATION_STAGES.FNF_INITIATED &&
@ -340,7 +358,8 @@ export const approveResignation = async (req: AuthRequest, res: Response, next:
// Transition via Workflow Service // Transition via Workflow Service
await ResignationWorkflowService.transitionResignation(resignation, nextStage, req.user.id, { await ResignationWorkflowService.transitionResignation(resignation, nextStage, req.user.id, {
remarks, remarks,
status: getResignationStatusForStage(nextStage) status: getResignationStatusForStage(nextStage),
transaction
}); });
// Special logic for F&F and Completion // Special logic for F&F and Completion
@ -351,19 +370,8 @@ export const approveResignation = async (req: AuthRequest, res: Response, next:
} }
if (nextStage === RESIGNATION_STAGES.FNF_INITIATED) { if (nextStage === RESIGNATION_STAGES.FNF_INITIATED) {
const today = new Date(); const existingFnF = await db.FnF.findOne({ where: { resignationId: resignation.id }, transaction });
const lwd = resignation.lastOperationalDateServices || resignation.lastOperationalDateSales; if (!existingFnF) {
const { force } = req.body;
if (!force && lwd && today < new Date(lwd)) {
await transaction.rollback();
return res.status(400).json({
success: false,
message: `F&F can only be initiated on or after the Last Working Day (${lwd}).`,
canForce: true
});
}
const sapDues = await ExternalMocksService.mockGetFinancialDuesFromSap((resignation as any).outlet.code); const sapDues = await ExternalMocksService.mockGetFinancialDuesFromSap((resignation as any).outlet.code);
const dealerProfileId = (resignation as any).dealer?.dealerId; const dealerProfileId = (resignation as any).dealer?.dealerId;
@ -393,6 +401,7 @@ export const approveResignation = async (req: AuthRequest, res: Response, next:
{ transaction } { transaction }
); );
} }
}
await transaction.commit(); await transaction.commit();
@ -409,7 +418,11 @@ export const approveResignation = async (req: AuthRequest, res: Response, next:
logger.error('[resignation] workflow worknote (approve):', wnErr); logger.error('[resignation] workflow worknote (approve):', wnErr);
} }
res.json({ success: true, message: 'Resignation approved successfully', nextStage, resignation }); const message = (sourceStage === RESIGNATION_STAGES.LEGAL && nextStage === RESIGNATION_STAGES.LEGAL)
? 'Legal stage approved successfully. Use Push to F&F to initiate settlement as per LWD rules.'
: 'Resignation approved successfully';
res.json({ success: true, message, nextStage, resignation });
} catch (error) { } catch (error) {
if (transaction) await transaction.rollback(); if (transaction) await transaction.rollback();
logger.error('Error approving resignation:', error); logger.error('Error approving resignation:', error);

View File

@ -385,13 +385,51 @@ export const updateClearance = async (req: AuthRequest, res: Response) => {
try { try {
const { id, clearanceId } = req.params; const { id, clearanceId } = req.params;
const body = (req.body || {}) as Record<string, any>; const body = (req.body || {}) as Record<string, any>;
const { status, remarks, documentId, supportingDocument } = body; const { status, remarks, documentId, supportingDocument, amount, type } = body;
const clearance = await FffClearance.findOne({ where: { id: clearanceId, fnfId: id } }); const clearance = await FffClearance.findOne({ where: { id: clearanceId, fnfId: id } });
if (!clearance) return res.status(404).json({ success: false, message: 'Clearance record not found' }); if (!clearance) return res.status(404).json({ success: false, message: 'Clearance record not found' });
const uploadedSupportingDocument = req.file ? `/uploads/documents/${req.file.filename}` : undefined; const uploadedSupportingDocument = req.file ? `/uploads/documents/${req.file.filename}` : undefined;
const enteredAmount = Math.abs(Number(amount) || 0);
const clearanceType = String(type || '').toLowerCase();
const itemType = clearanceType === 'payable'
? 'Payable'
: clearanceType === 'deduction'
? 'Deduction'
: 'Receivable';
const syntheticDescription = 'Department Clearance - Manual Update';
const normalizedStatus = normalizeClearanceStatus(status || clearance.status, Number(clearance.amount || 0)); // Persist amount/type as F&F line item so UI totals and department amount reflect user input.
const existingSyntheticLine = await FnFLineItem.findOne({
where: {
fnfId: id,
department: clearance.department,
description: syntheticDescription
}
});
if (enteredAmount > 0) {
if (existingSyntheticLine) {
await existingSyntheticLine.update({
itemType,
amount: enteredAmount,
addedBy: req.user?.id || existingSyntheticLine.addedBy
});
} else {
await FnFLineItem.create({
fnfId: id,
itemType,
description: syntheticDescription,
department: clearance.department,
amount: enteredAmount,
addedBy: req.user?.id || null
});
}
} else if (existingSyntheticLine) {
await existingSyntheticLine.destroy();
}
const normalizedStatus = normalizeClearanceStatus(status || clearance.status, enteredAmount);
await clearance.update({ await clearance.update({
status: normalizedStatus, status: normalizedStatus,
remarks: remarks || clearance.remarks, remarks: remarks || clearance.remarks,
@ -413,7 +451,12 @@ export const updateClearance = async (req: AuthRequest, res: Response) => {
fnfId: id, fnfId: id,
action: 'CLEARANCE_UPDATED', action: 'CLEARANCE_UPDATED',
remarks: remarks || 'No remarks', remarks: remarks || 'No remarks',
details: { department: clearance.department, status: normalizedStatus } details: {
department: clearance.department,
status: normalizedStatus,
amount: enteredAmount,
type: itemType
}
}); });
} catch (auditError) { } catch (auditError) {
console.error('[SettlementController] Local FnFAudit creation failed:', auditError); console.error('[SettlementController] Local FnFAudit creation failed:', auditError);
@ -433,7 +476,12 @@ export const updateClearance = async (req: AuthRequest, res: Response) => {
[parentKey]: parentId, [parentKey]: parentId,
action: 'STAKEHOLDER_CLEARANCE_UPDATED', action: 'STAKEHOLDER_CLEARANCE_UPDATED',
remarks: `Automated sync from F&F: ${remarks || 'No remarks'}`, remarks: `Automated sync from F&F: ${remarks || 'No remarks'}`,
details: { department: clearance.department, status: normalizedStatus } details: {
department: clearance.department,
status: normalizedStatus,
amount: enteredAmount,
type: itemType
}
}); });
} catch (parentAuditError) { } catch (parentAuditError) {
console.error('[SettlementController] Parent Audit creation failed:', parentAuditError); console.error('[SettlementController] Parent Audit creation failed:', parentAuditError);

View File

@ -12,7 +12,7 @@ export class ResignationWorkflowService {
* Standardized method to transition a resignation request status * Standardized method to transition a resignation request status
*/ */
static async transitionResignation(resignation: any, targetStage: string, userId: string | null = null, metadata: any = {}) { static async transitionResignation(resignation: any, targetStage: string, userId: string | null = null, metadata: any = {}) {
const { action, remarks, status } = metadata; const { action, remarks, status, transaction } = metadata;
const sourceStage = resignation.currentStage; const sourceStage = resignation.currentStage;
const updateData: any = { const updateData: any = {
@ -38,7 +38,7 @@ export class ResignationWorkflowService {
await resignation.update({ await resignation.update({
...updateData, ...updateData,
timeline: updatedTimeline timeline: updatedTimeline
}); }, transaction ? { transaction } : undefined);
// 3. Create Audit Log // 3. Create Audit Log
let auditAction: any = AUDIT_ACTIONS.APPROVED; let auditAction: any = AUDIT_ACTIONS.APPROVED;
@ -52,7 +52,7 @@ export class ResignationWorkflowService {
action: auditAction, action: auditAction,
remarks: remarks || '', remarks: remarks || '',
details: { status: updateData.status, stage: sourceStage, targetStage: targetStage } details: { status: updateData.status, stage: sourceStage, targetStage: targetStage }
}); }, transaction ? { transaction } : undefined);
console.log(`[ResignationWorkflowService] Transitioned Resignation ${resignation.resignationId} to ${targetStage}`); console.log(`[ResignationWorkflowService] Transitioned Resignation ${resignation.resignationId} to ${targetStage}`);
@ -85,7 +85,7 @@ export class ResignationWorkflowService {
await user.update({ await user.update({
status: 'deactivated', status: 'deactivated',
isActive: false isActive: false
}); }, transaction ? { transaction } : undefined);
} }
} else { } else {
logger.warn(`[ResignationWorkflowService] No user account found with dealerId ${resignation.dealerId}`); logger.warn(`[ResignationWorkflowService] No user account found with dealerId ${resignation.dealerId}`);

View File

@ -347,229 +347,229 @@ async function triggerWorkflow() {
await delay(); await delay();
// 6.3 FDD ASSIGNMENT // 6.3 FDD ASSIGNMENT
// log(6.3, 'Admin Assigning Application to FDD Agency...'); log(6.3, 'Admin Assigning Application to FDD Agency...');
// const fddUser = users.data.find(u => u.email === EMAILS.FDD); const fddUser = users.data.find(u => u.email === EMAILS.FDD);
// await apiRequest('/fdd/assign', 'POST', { await apiRequest('/fdd/assign', 'POST', {
// applicationId: applicationUUID, applicationId: applicationUUID,
// assignedToAgency: fddUser.id assignedToAgency: fddUser.id
// }, adminToken); }, adminToken);
// log(6.3, 'FDD Agency assigned successfully.'); log(6.3, 'FDD Agency assigned successfully.');
// await delay(); await delay();
// // 7. FDD MILESTONE // 7. FDD MILESTONE
// log(7, 'FDD Agency Discovery & Report Upload...'); log(7, 'FDD Agency Discovery & Report Upload...');
// const fddToken = await login(EMAILS.FDD); const fddToken = await login(EMAILS.FDD);
// // FETCH ASSIGNMENT ID // FETCH ASSIGNMENT ID
// const assignmentRes = await apiRequest(`/fdd/${applicationUUID}`, 'GET', null, fddToken); const assignmentRes = await apiRequest(`/fdd/${applicationUUID}`, 'GET', null, fddToken);
// const assignmentId = assignmentRes.data.id; const assignmentId = assignmentRes.data.id;
// log(7, `Found Assignment ID: ${assignmentId}`); log(7, `Found Assignment ID: ${assignmentId}`);
// await apiRequest('/fdd/report', 'POST', { await apiRequest('/fdd/report', 'POST', {
// assignmentId, assignmentId,
// findings: 'Finance records clean.', findings: 'Finance records clean.',
// recommendation: 'Approved' recommendation: 'Approved'
// }, fddToken); }, fddToken);
// log(7.1, 'Admin Approving FDD Final Stage...'); log(7.1, 'Admin Approving FDD Final Stage...');
// await apiRequest('/assessment/stage-decision', 'POST', { await apiRequest('/assessment/stage-decision', 'POST', {
// applicationId: applicationUUID, applicationId: applicationUUID,
// stageCode: 'FDD_VERIFICATION', stageCode: 'FDD_VERIFICATION',
// decision: 'Approved', decision: 'Approved',
// remarks: 'FDD documents verified.' remarks: 'FDD documents verified.'
// }, adminToken); }, adminToken);
// log(7, 'FDD Milestone Complete.'); log(7, 'FDD Milestone Complete.');
// await delay(); await delay();
// log(7.4, 'Uploading mandatory documents prior to LOI generation...'); log(7.4, 'Uploading mandatory documents prior to LOI generation...');
// const requiredDocs = ['CIBIL Report', 'Proposed Site City Map', 'Bank Statement', 'GST Certificate', 'PAN Card']; const requiredDocs = ['CIBIL Report', 'Proposed Site City Map', 'Bank Statement', 'GST Certificate', 'PAN Card'];
// for (const doc of requiredDocs) { for (const doc of requiredDocs) {
// await mockUploadDocument(applicationUUID, adminToken, doc); await mockUploadDocument(applicationUUID, adminToken, doc);
// } }
// await delay(1000); await delay(1000);
// // 7.5 LOI APPROVAL // 7.5 LOI APPROVAL
// log(7.5, 'LOI Generation & Approval...'); log(7.5, 'LOI Generation & Approval...');
// const loiRes = await apiRequest('/loi/request', 'POST', { applicationId: applicationUUID }, adminToken); const loiRes = await apiRequest('/loi/request', 'POST', { applicationId: applicationUUID }, adminToken);
// const loiRequestId = loiRes.data.id; const loiRequestId = loiRes.data.id;
// // Head Approval // Head Approval
// await apiRequest(`/loi/request/${loiRequestId}/approve`, 'POST', { await apiRequest(`/loi/request/${loiRequestId}/approve`, 'POST', {
// action: 'Approved', action: 'Approved',
// remarks: 'Head Authorization for LOI' remarks: 'Head Authorization for LOI'
// }, headToken); }, headToken);
// // NBH Approval // NBH Approval
// await apiRequest(`/loi/request/${loiRequestId}/approve`, 'POST', { await apiRequest(`/loi/request/${loiRequestId}/approve`, 'POST', {
// action: 'Approved', action: 'Approved',
// remarks: 'NBH Authorization for LOI' remarks: 'NBH Authorization for LOI'
// }, nbhToken); }, nbhToken);
// log(7.5, 'LOI Milestone Complete.'); log(7.5, 'LOI Milestone Complete.');
// await delay(); await delay();
// // 8. PAYMENT GATE (SECURITY DEPOSIT FIRST AS PER CURRENT FLOW) // 8. PAYMENT GATE (SECURITY DEPOSIT FIRST AS PER CURRENT FLOW)
// log(8, 'Finance Verifying SECURITY_DEPOSIT to unlock LOI Issued...'); log(8, 'Finance Verifying SECURITY_DEPOSIT to unlock LOI Issued...');
// const financeToken = await login(EMAILS.FINANCE); const financeToken = await login(EMAILS.FINANCE);
// await apiRequest('/loa/security-deposit', 'POST', { await apiRequest('/loa/security-deposit', 'POST', {
// applicationId: applicationUUID, applicationId: applicationUUID,
// amount: 500000, amount: 500000,
// paymentReference: 'PAY-888999', paymentReference: 'PAY-888999',
// depositType: 'SECURITY_DEPOSIT', depositType: 'SECURITY_DEPOSIT',
// status: 'Verified' status: 'Verified'
// }, financeToken); }, financeToken);
// log(8, 'Security Deposit Verified.') log(8, 'Security Deposit Verified.')
// // 9. GENERATE DEALER CODES (align with backend gate: LOI Issued required) // 9. GENERATE DEALER CODES (align with backend gate: LOI Issued required)
// let statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken); let statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken);
// log(9, `Current status before code generation: ${statusBeforeCodeGen}`); log(9, `Current status before code generation: ${statusBeforeCodeGen}`);
// log(9, 'Ensuring mandatory PAN/GST/Bank fields before code generation...'); log(9, 'Ensuring mandatory PAN/GST/Bank fields before code generation...');
// await ensureMandatoryCodeGenFields(applicationUUID, adminToken); await ensureMandatoryCodeGenFields(applicationUUID, adminToken);
// await delay(300); await delay(300);
// if (statusBeforeCodeGen === 'Security Details') { if (statusBeforeCodeGen === 'Security Details') {
// log(9, 'Status is Security Details; re-verifying Security Deposit to move to LOI Issued...'); log(9, 'Status is Security Details; re-verifying Security Deposit to move to LOI Issued...');
// await apiRequest('/loa/security-deposit', 'POST', { await apiRequest('/loa/security-deposit', 'POST', {
// applicationId: applicationUUID, applicationId: applicationUUID,
// amount: 500000, amount: 500000,
// paymentReference: `PAY-RETRY-${Date.now()}`, paymentReference: `PAY-RETRY-${Date.now()}`,
// depositType: 'SECURITY_DEPOSIT', depositType: 'SECURITY_DEPOSIT',
// status: 'Verified' status: 'Verified'
// }, financeToken); }, financeToken);
// await delay(); await delay();
// statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken); statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken);
// log(9, `Status after re-verify: ${statusBeforeCodeGen}`); log(9, `Status after re-verify: ${statusBeforeCodeGen}`);
// } }
// // Current backend flow keeps app at "Security Details" until explicit admin transition. // Current backend flow keeps app at "Security Details" until explicit admin transition.
// if (statusBeforeCodeGen === 'Security Details') { if (statusBeforeCodeGen === 'Security Details') {
// log(9, 'Applying admin transition from Security Details -> LOI Issued...'); log(9, 'Applying admin transition from Security Details -> LOI Issued...');
// await apiRequest(`/onboarding/applications/${applicationUUID}/status`, 'PUT', { await apiRequest(`/onboarding/applications/${applicationUUID}/status`, 'PUT', {
// status: 'LOI Issued', status: 'LOI Issued',
// stage: 'LOI', stage: 'LOI',
// reason: 'E2E script alignment: unlock dealer code generation after Security Details checks.' reason: 'E2E script alignment: unlock dealer code generation after Security Details checks.'
// }, adminToken); }, adminToken);
// await delay(); await delay();
// statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken); statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken);
// log(9, `Status after admin transition: ${statusBeforeCodeGen}`); log(9, `Status after admin transition: ${statusBeforeCodeGen}`);
// } }
// if (statusBeforeCodeGen !== 'LOI Issued' && statusBeforeCodeGen !== 'Dealer Code Generation') { if (statusBeforeCodeGen !== 'LOI Issued' && statusBeforeCodeGen !== 'Dealer Code Generation') {
// throw new Error(`Cannot generate codes: expected LOI Issued/Dealer Code Generation, got ${statusBeforeCodeGen}`); throw new Error(`Cannot generate codes: expected LOI Issued/Dealer Code Generation, got ${statusBeforeCodeGen}`);
// } }
// log(9, 'Admin Generating SAP Dealer Codes...'); log(9, 'Admin Generating SAP Dealer Codes...');
// await apiRequest(`/onboarding/applications/${applicationUUID}/generate-codes`, 'POST', {}, adminToken); await apiRequest(`/onboarding/applications/${applicationUUID}/generate-codes`, 'POST', {}, adminToken);
// log(9, 'Dealer Codes Generated.'); log(9, 'Dealer Codes Generated.');
// await delay(); await delay();
// // 10. FIRST FILL (POST CODE-GENERATION) // 10. FIRST FILL (POST CODE-GENERATION)
// log(10, 'Finance Verifying FIRST FILL (₹15L)...'); log(10, 'Finance Verifying FIRST FILL (₹15L)...');
// await apiRequest('/loa/security-deposit', 'POST', { await apiRequest('/loa/security-deposit', 'POST', {
// applicationId: applicationUUID, applicationId: applicationUUID,
// amount: 1500000, amount: 1500000,
// paymentReference: 'PAY-FIN-999', paymentReference: 'PAY-FIN-999',
// depositType: 'FIRST_FILL', depositType: 'FIRST_FILL',
// status: 'Verified' status: 'Verified'
// }, financeToken); }, financeToken);
// log(10, 'Final Security Deposit Verified.'); log(10, 'Final Security Deposit Verified.');
// await delay(); await delay();
// // 11. ADMIN UPDATING STATUTORY & BANK DETAILS // 11. ADMIN UPDATING STATUTORY & BANK DETAILS
// log(11, 'Admin Updating Statutory & Bank Details for LOA Approval Gate...'); log(11, 'Admin Updating Statutory & Bank Details for LOA Approval Gate...');
// await apiRequest(`/onboarding/applications/${applicationUUID}`, 'PUT', { await apiRequest(`/onboarding/applications/${applicationUUID}`, 'PUT', {
// accountHolderName: 'Ramesh Automobiles Private Limited', accountHolderName: 'Ramesh Automobiles Private Limited',
// panNumber: 'ABCDE1234F', panNumber: 'ABCDE1234F',
// gstNumber: '07ABCDE1234F1Z5', gstNumber: '07ABCDE1234F1Z5',
// bankName: 'HDFC Bank', bankName: 'HDFC Bank',
// accountNumber: '50100223344556', accountNumber: '50100223344556',
// ifscCode: 'HDFC0001234' ifscCode: 'HDFC0001234'
// }, adminToken); }, adminToken);
// log(11, 'Statutory & Bank details updated.'); log(11, 'Statutory & Bank details updated.');
// await delay(); await delay();
// // 12. FINAL LOA APPROVAL // 12. FINAL LOA APPROVAL
// log(12, 'NBH & Head Approving Final LOA...'); log(12, 'NBH & Head Approving Final LOA...');
// const loaRes = await apiRequest('/loa/request', 'POST', { applicationId: applicationUUID }, headToken); const loaRes = await apiRequest('/loa/request', 'POST', { applicationId: applicationUUID }, headToken);
// const finalLoaRequestId = loaRes.data.id; const finalLoaRequestId = loaRes.data.id;
// await apiRequest(`/loa/request/${finalLoaRequestId}/approve`, 'POST', { await apiRequest(`/loa/request/${finalLoaRequestId}/approve`, 'POST', {
// action: 'Approved', action: 'Approved',
// remarks: 'Head Authorization (Level 1)' remarks: 'Head Authorization (Level 1)'
// }, headToken); }, headToken);
// await apiRequest(`/loa/request/${finalLoaRequestId}/approve`, 'POST', { await apiRequest(`/loa/request/${finalLoaRequestId}/approve`, 'POST', {
// action: 'Approved', action: 'Approved',
// remarks: 'NBH Approval (Level 2)' remarks: 'NBH Approval (Level 2)'
// }, nbhToken); }, nbhToken);
// log(12, 'LOA Fully Approved.'); log(12, 'LOA Fully Approved.');
// await delay(); await delay();
// // 13. EOR (EVIDENCE OF READINESS) CHECKLIST VERIFICATION // 13. EOR (EVIDENCE OF READINESS) CHECKLIST VERIFICATION
// log(13, 'Admin Initializing EOR Checklist (100% Readiness Requirement)...'); log(13, 'Admin Initializing EOR Checklist (100% Readiness Requirement)...');
// const eorInit = await apiRequest('/eor', 'POST', { applicationId: applicationUUID }, adminToken); const eorInit = await apiRequest('/eor', 'POST', { applicationId: applicationUUID }, adminToken);
// const checklistId = eorInit.data.id; const checklistId = eorInit.data.id;
// log(13, `EOR Checklist Created (ID: ${checklistId})`); log(13, `EOR Checklist Created (ID: ${checklistId})`);
// log(13.1, 'Auditor Verifying all 12 mandatory EOR items as COMPLIANT...'); log(13.1, 'Auditor Verifying all 12 mandatory EOR items as COMPLIANT...');
// const eorItems = [ const eorItems = [
// { itemType: 'Sales', description: 'Sales Standards' }, { itemType: 'Sales', description: 'Sales Standards' },
// { itemType: 'Service', description: 'Service & Spares' }, { itemType: 'Service', description: 'Service & Spares' },
// { itemType: 'IT', description: 'DMS infra' }, { itemType: 'IT', description: 'DMS infra' },
// { itemType: 'Training', description: 'Manpower Training' }, { itemType: 'Training', description: 'Manpower Training' },
// { itemType: 'Statutory', description: 'Trade certificate with test ride bikes registration' }, { itemType: 'Statutory', description: 'Trade certificate with test ride bikes registration' },
// { itemType: 'Statutory', description: 'GST certificate including Accessories & Apparels billing' }, { itemType: 'Statutory', description: 'GST certificate including Accessories & Apparels billing' },
// { itemType: 'Finance', description: 'Inventory Funding' }, { itemType: 'Finance', description: 'Inventory Funding' },
// { itemType: 'IT', description: 'Virtual code availability' }, { itemType: 'IT', description: 'Virtual code availability' },
// { itemType: 'Finance', description: 'Vendor payments' }, { itemType: 'Finance', description: 'Vendor payments' },
// { itemType: 'Marketing', description: 'Details for website submission' }, { itemType: 'Marketing', description: 'Details for website submission' },
// { itemType: 'Insurance', description: 'Infra Insurance both Showroom and Service center' }, { itemType: 'Insurance', description: 'Infra Insurance both Showroom and Service center' },
// { itemType: 'IT', description: 'Auto ordering' } { itemType: 'IT', description: 'Auto ordering' }
// ]; ];
// for (const item of eorItems) { for (const item of eorItems) {
// process.stdout.write(`.`); // Visual progress process.stdout.write(`.`); // Visual progress
// await apiRequest(`/eor/item/${checklistId}`, 'POST', { await apiRequest(`/eor/item/${checklistId}`, 'POST', {
// ...item, ...item,
// isCompliant: true, isCompliant: true,
// remarks: 'Verified by Auditor - Compliant' remarks: 'Verified by Auditor - Compliant'
// }, adminToken); }, adminToken);
// } }
// console.log('\n[STEP 13.1] All EOR items marked as compliant.'); console.log('\n[STEP 13.1] All EOR items marked as compliant.');
// log(13.2, 'Auditor Submitting Final EOR Audit...'); log(13.2, 'Auditor Submitting Final EOR Audit...');
// await apiRequest(`/eor/audit/${checklistId}`, 'POST', { await apiRequest(`/eor/audit/${checklistId}`, 'POST', {
// status: 'Completed', status: 'Completed',
// overallComments: 'Dealer is 100% ready for inauguration. All infra and statutory items verified.' overallComments: 'Dealer is 100% ready for inauguration. All infra and statutory items verified.'
// }, adminToken); }, adminToken);
// // Status check // Status check
// const finalAppStatus = await apiRequest(`/onboarding/applications/${applicationUUID}`, 'GET', null, adminToken); const finalAppStatus = await apiRequest(`/onboarding/applications/${applicationUUID}`, 'GET', null, adminToken);
// log(13.2, `Application Status after EOR: ${finalAppStatus.data.overallStatus}`); log(13.2, `Application Status after EOR: ${finalAppStatus.data.overallStatus}`);
// await delay(); await delay();
// // 14. FINAL ONBOARDING // 14. FINAL ONBOARDING
// log(14, 'Admin Finalizing Dealer Onboarding...'); log(14, 'Admin Finalizing Dealer Onboarding...');
// await apiRequest('/dealers', 'POST', { applicationId: applicationUUID }, adminToken); await apiRequest('/dealers', 'POST', { applicationId: applicationUUID }, adminToken);
// await delay(); await delay();
// // 15. VERIFICATION // 15. VERIFICATION
// log(15, 'Verifying Dealer Record Creation...'); log(15, 'Verifying Dealer Record Creation...');
// const dealerRes = await apiRequest(`/dealers/application/${applicationUUID}`, 'GET', null, adminToken); const dealerRes = await apiRequest(`/dealers/application/${applicationUUID}`, 'GET', null, adminToken);
// if (!dealerRes.success || !dealerRes.data) { if (!dealerRes.success || !dealerRes.data) {
// throw new Error('Verification Failed: Dealer record not found after onboarding.'); throw new Error('Verification Failed: Dealer record not found after onboarding.');
// } }
// log(15, `Dealer Found: ${dealerRes.data.legalName} (${dealerRes.data.id})`); log(15, `Dealer Found: ${dealerRes.data.legalName} (${dealerRes.data.id})`);
// log(15.1, 'Verifying User Account Role Update...'); log(15.1, 'Verifying User Account Role Update...');
// const userRes = await apiRequest(`/admin/users`, 'GET', null, adminToken); const userRes = await apiRequest(`/admin/users`, 'GET', null, adminToken);
// const dealerUser = userRes.data.find(u => u.email === PROSPECT_EMAIL); const dealerUser = userRes.data.find(u => u.email === PROSPECT_EMAIL);
// if (!dealerUser || dealerUser.roleCode !== 'Dealer') { if (!dealerUser || dealerUser.roleCode !== 'Dealer') {
// throw new Error(`Verification Failed: User role not updated to 'Dealer'. Current role: ${dealerUser?.roleCode}`); throw new Error(`Verification Failed: User role not updated to 'Dealer'. Current role: ${dealerUser?.roleCode}`);
// } }
// log(15.1, `User role confirmed: ${dealerUser.roleCode}`); log(15.1, `User role confirmed: ${dealerUser.roleCode}`);
// log(15.2, '--- WORKFLOW COMPLETED SUCCESSFULLY! ---'); log(15.2, '--- WORKFLOW COMPLETED SUCCESSFULLY! ---');
// log(15.2, `The application ${applicationId} is now at 'ONBOARDED' status and Dealer profile is active.`); log(15.2, `The application ${applicationId} is now at 'ONBOARDED' status and Dealer profile is active.`);
} }
/** /**