From b6938abc7c48e51911d51e711f2ff83596c41d4b Mon Sep 17 00:00:00 2001 From: laxmanhalaki Date: Tue, 28 Apr 2026 08:32:28 +0530 Subject: [PATCH] progress track isue for interview level 1 fixed --- src/common/utils/progress.ts | 102 ++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/src/common/utils/progress.ts b/src/common/utils/progress.ts index b83be80..1f1db2d 100644 --- a/src/common/utils/progress.ts +++ b/src/common/utils/progress.ts @@ -154,7 +154,7 @@ export const syncApplicationProgress = async (applicationId: string, overallStat // Statuses that imply the CURRENT stage (single or both parallel) is finished const completionStatuses = [ 'Submitted', 'Questionnaire Completed', 'Shortlisted', 'Level 1 Approved', - 'Level 2 Approved', 'Level 3 Approved', + 'Level 2 Approved', 'Level 2 Recommended', 'Level 3 Approved', 'EOR Complete', 'Inauguration', 'Approved', 'Onboarded' ]; @@ -163,46 +163,72 @@ export const syncApplicationProgress = async (applicationId: string, overallStat // Fetch application to check model-driven parallel status const application = await db.Application.findByPk(applicationId); - // Robust Sync: Prepare ALL stages for batch processing - const upsertData = []; - for (const stage of ONBOARDING_STAGES) { - let status: 'pending' | 'active' | 'completed' = 'pending'; - let percentage = 0; + // Robust Sync: Prepare ALL stages for batch processing + const upsertData: any[] = []; + for (const stage of ONBOARDING_STAGES) { + let status: 'pending' | 'active' | 'completed' = 'pending'; + let percentage = 0; - if (stage.order < currentStage.order) { - status = 'completed'; - percentage = 100; - } else if (stage.order === currentStage.order) { - status = isCurrentStageFinished ? 'completed' : 'active'; - percentage = isCurrentStageFinished ? 100 : 50; - - if (stage.name === 'Architecture Work' && application) { - status = application.architectureStatus === 'COMPLETED' ? 'completed' : - (application.architectureStatus === 'IN_PROGRESS' || currentStage.name === 'Architecture Work' || isCurrentStageFinished) ? 'active' : 'pending'; - percentage = status === 'completed' ? 100 : status === 'active' ? 50 : 0; - } - if (stage.name === 'Statutory Work' && application) { - status = application.statutoryStatus === 'COMPLETED' ? 'completed' : - (application.statutoryStatus === 'IN_PROGRESS' || currentStage.name === 'Statutory Work' || isCurrentStageFinished) ? 'active' : 'pending'; - percentage = status === 'completed' ? 100 : status === 'active' ? 50 : 0; + if (stage.order < currentStage.order) { + status = 'completed'; + percentage = 100; + } else if (stage.order === currentStage.order) { + status = isCurrentStageFinished ? 'completed' : 'active'; + percentage = isCurrentStageFinished ? 100 : 50; + + if (stage.name === 'Architecture Work' && application) { + status = application.architectureStatus === 'COMPLETED' ? 'completed' : + (application.architectureStatus === 'IN_PROGRESS' || currentStage.name === 'Architecture Work' || isCurrentStageFinished) ? 'active' : 'pending'; + percentage = status === 'completed' ? 100 : status === 'active' ? 50 : 0; + } + if (stage.name === 'Statutory Work' && application) { + status = application.statutoryStatus === 'COMPLETED' ? 'completed' : + (application.statutoryStatus === 'IN_PROGRESS' || currentStage.name === 'Statutory Work' || isCurrentStageFinished) ? 'active' : 'pending'; + percentage = status === 'completed' ? 100 : status === 'active' ? 50 : 0; + } + } + + upsertData.push({ + applicationId, + stageName: stage.name, + stageOrder: stage.order, + status, + completionPercentage: percentage, + stageStartedAt: (status === 'active' || status === 'completed') ? new Date() : null, + stageCompletedAt: status === 'completed' ? new Date() : null + }); } - } - - upsertData.push({ - applicationId, - stageName: stage.name, - stageOrder: stage.order, - status, - completionPercentage: percentage, - stageStartedAt: (status === 'active' || status === 'completed') ? new Date() : null, - stageCompletedAt: status === 'completed' ? new Date() : null - }); - } - // Use bulkCreate with updateOnDuplicate to perform an efficient batch upsert - await ApplicationProgress.bulkCreate(upsertData, { - updateOnDuplicate: ['status', 'completionPercentage', 'stageStartedAt', 'stageCompletedAt'] - }); + // DB Duplication Prevention without Schema Changes (Healing corrupted data loops) + const existingRecords = await ApplicationProgress.findAll({ where: { applicationId } }); + const seenStages = new Set(); + + // Purge any ghost duplicates created by old logic + for (const record of existingRecords) { + if (seenStages.has(record.stageName)) { + await record.destroy(); + } else { + seenStages.add(record.stageName); + } + } + + // Perform single row updates/inserts to enforce exact 1:1 mapping safely + const cleanedRecords = await ApplicationProgress.findAll({ where: { applicationId } }); + + for (const data of upsertData) { + const existing = cleanedRecords.find((r: any) => r.stageName === data.stageName); + if (existing) { + await existing.update({ + stageOrder: data.stageOrder, + status: data.status, + completionPercentage: data.completionPercentage, + stageStartedAt: data.stageStartedAt || existing.stageStartedAt, + stageCompletedAt: data.stageCompletedAt || existing.stageCompletedAt + }); + } else { + await ApplicationProgress.create(data); + } + } } } };