CognxSafeTrack commited on
Commit
a66a580
·
1 Parent(s): d8ac16e

fix: re-validate COMPLETED→PENDING for text exercise responses + guard businessProfile.upsert at Day 10+

Browse files
apps/api/src/services/whatsapp.ts CHANGED
@@ -459,6 +459,23 @@ export class WhatsAppService {
459
  return;
460
  }
461
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  const pendingProgress = await prisma.userProgress.findFirst({
463
  where: { userId: user.id, exerciseStatus: { in: ['PENDING', 'PENDING_REMEDIATION', 'PENDING_DEEPDIVE'] }, trackId: activeEnrollment.trackId },
464
  });
 
459
  return;
460
  }
461
 
462
+ // 🚨 TEXT RE-VALIDATION: Mirror the Worker-side `shouldForceRevalidation` logic.
463
+ // Image/Audio flows reset PENDING via WhatsAppLogic. For text, we do it here.
464
+ const userProgressState = await prisma.userProgress.findUnique({
465
+ where: { userId_trackId: { userId: user.id, trackId: activeEnrollment.trackId } }
466
+ });
467
+ const tenMinutesAgo = new Date(Date.now() - 10 * 60 * 1000);
468
+ const isRecentlyCompleted = userProgressState?.exerciseStatus === 'COMPLETED'
469
+ && userProgressState.updatedAt > tenMinutesAgo;
470
+
471
+ if (isRecentlyCompleted && !audioUrl && !imageUrl && text.length > 5 && !isSystemCommand) {
472
+ console.log(`[TXT-FLOW] 🔄 Re-validation User ${user.id} Day ${activeEnrollment.currentDay} (COMPLETED → PENDING)`);
473
+ await prisma.userProgress.update({
474
+ where: { id: userProgressState!.id },
475
+ data: { exerciseStatus: 'PENDING' }
476
+ });
477
+ }
478
+
479
  const pendingProgress = await prisma.userProgress.findFirst({
480
  where: { userId: user.id, exerciseStatus: { in: ['PENDING', 'PENDING_REMEDIATION', 'PENDING_DEEPDIVE'] }, trackId: activeEnrollment.trackId },
481
  });
apps/whatsapp-worker/src/index.ts CHANGED
@@ -227,11 +227,15 @@ const worker = new Worker('whatsapp-queue', async (job: Job) => {
227
  updatePayload.teamMembers = [...existingTeam, ...(feedbackData as any).teamMembers];
228
  }
229
 
230
- await (prisma as any).businessProfile.upsert({
231
- where: { userId },
232
- update: updatePayload,
233
- create: { userId, ...updatePayload }
234
- });
 
 
 
 
235
  }
236
  } else {
237
  // Success! Award Badges & Mark Completed (or keep Pending for Deep Dive)
@@ -275,11 +279,15 @@ const worker = new Worker('whatsapp-queue', async (job: Job) => {
275
  updatePayload.teamMembers = [...existingTeam, ...(feedbackData as any).teamMembers];
276
  }
277
 
278
- await (prisma as any).businessProfile.upsert({
279
- where: { userId },
280
- update: updatePayload,
281
- create: { userId, ...updatePayload }
282
- });
 
 
 
 
283
  }
284
 
285
  // If we were in a remediation day (fractional) -> move to next integer day
 
227
  updatePayload.teamMembers = [...existingTeam, ...(feedbackData as any).teamMembers];
228
  }
229
 
230
+ try {
231
+ await (prisma as any).businessProfile.upsert({
232
+ where: { userId },
233
+ update: updatePayload,
234
+ create: { userId, ...updatePayload }
235
+ });
236
+ } catch (bpErr: unknown) {
237
+ console.error('[WORKER] BusinessProfile upsert failed (non-fatal, REMEDIATION path):', (bpErr as Error).message);
238
+ }
239
  }
240
  } else {
241
  // Success! Award Badges & Mark Completed (or keep Pending for Deep Dive)
 
279
  updatePayload.teamMembers = [...existingTeam, ...(feedbackData as any).teamMembers];
280
  }
281
 
282
+ try {
283
+ await (prisma as any).businessProfile.upsert({
284
+ where: { userId },
285
+ update: updatePayload,
286
+ create: { userId, ...updatePayload }
287
+ });
288
+ } catch (bpErr: unknown) {
289
+ console.error('[WORKER] BusinessProfile upsert failed (non-fatal, SUCCESS path):', (bpErr as Error).message);
290
+ }
291
  }
292
 
293
  // If we were in a remediation day (fractional) -> move to next integer day