Dealer_Onboarding_Backend/src/common/utils/progress.ts

121 lines
4.7 KiB
TypeScript

import db from '../../database/models/index.js';
const { ApplicationProgress } = db;
export const ONBOARDING_STAGES = [
{ name: 'Submitted', order: 1 },
{ name: 'Questionnaire', order: 2 },
{ name: 'Shortlist', order: 3 },
{ name: '1st Level Interview', order: 4 },
{ name: '2nd Level Interview', order: 5 },
{ name: '3rd Level Interview', order: 6 },
{ name: 'FDD', order: 7 },
{ name: 'LOI Approval', order: 8 },
{ name: 'Security Details', order: 9 },
{ name: 'LOI Issue', order: 10 },
{ name: 'Dealer Code Generation', order: 11 },
{ name: 'LOA', order: 12 },
{ name: 'EOR Complete', order: 13 },
{ name: 'Inauguration', order: 14 },
{ name: 'Onboarded', order: 15 }
];
/**
* Updates application progress for a specific stage
*/
export const updateApplicationProgress = async (applicationId: string, stageName: string, status: 'pending' | 'active' | 'completed', percentage: number = 0) => {
try {
const stage = ONBOARDING_STAGES.find(s => s.name === stageName);
if (!stage) return;
const [progress, created] = await ApplicationProgress.findOrCreate({
where: { applicationId, stageName },
defaults: {
stageOrder: stage.order,
status,
completionPercentage: percentage,
stageStartedAt: status === 'active' ? new Date() : null,
stageCompletedAt: status === 'completed' ? new Date() : null
}
});
if (!created) {
const updates: any = { status, completionPercentage: percentage };
if (status === 'active' && !progress.stageStartedAt) {
updates.stageStartedAt = new Date();
}
if (status === 'completed' && !progress.stageCompletedAt) {
updates.stageCompletedAt = new Date();
}
await progress.update(updates);
}
// Mark previous stages as completed if this one is completed
if (status === 'completed') {
await ApplicationProgress.update(
{ status: 'completed', completionPercentage: 100 },
{
where: {
applicationId,
stageOrder: { [db.Sequelize.Op.lt]: stage.order },
status: { [db.Sequelize.Op.ne]: 'completed' }
}
}
);
}
return progress;
} catch (error) {
console.error('Error updating application progress:', error);
}
};
/**
* Syncs all progress stages based on current overall status
*/
export const syncApplicationProgress = async (applicationId: string, overallStatus: string) => {
// Map overallStatus to stage names
const statusToStageMap: Record<string, string> = {
'Submitted': 'Submitted',
'Questionnaire Completed': 'Questionnaire',
'Shortlisted': 'Shortlist',
'Level 1 Interview Pending': '1st Level Interview',
'Level 1 Approved': '1st Level Interview',
'Level 2 Interview Pending': '2nd Level Interview',
'Level 2 Approved': '2nd Level Interview',
'Level 2 Recommended': '2nd Level Interview',
'Level 3 Interview Pending': '3rd Level Interview',
'Level 3 Approved': '3rd Level Interview',
'FDD Verification': 'FDD',
'LOI In Progress': 'LOI Approval',
'Payment Pending': 'Security Details',
'LOI Issued': 'LOI Issue',
'Statutory LOI Ack': 'LOI Issue',
'Dealer Code Generation': 'Dealer Code Generation',
'Architecture Team Assigned': 'Dealer Code Generation',
'Architecture Document Upload': 'Dealer Code Generation',
'Architecture Team Completion': 'Dealer Code Generation',
'Statutory GST': 'Dealer Code Generation',
'LOA Pending': 'LOA',
'EOR In Progress': 'LOA',
'EOR Complete': 'EOR Complete',
'Inauguration': 'Inauguration',
'Approved': 'Inauguration',
'Onboarded': 'Onboarded'
};
const currentStageName = statusToStageMap[overallStatus];
if (currentStageName) {
const stage = ONBOARDING_STAGES.find(s => s.name === currentStageName);
if (stage) {
// Determine status for this stage
// If the status IS exactly the target "Complete" status for a stage, mark it as completed
const isCompleted = [
'Submitted', 'Questionnaire Completed', 'Shortlisted', 'Level 3 Approved',
'LOI Issued', 'EOR Complete', 'Approved', 'Onboarded'
].includes(overallStatus);
await updateApplicationProgress(applicationId, currentStageName, isCompleted ? 'completed' : 'active', isCompleted ? 100 : 50);
}
}
};