8.5 KiB
8.5 KiB
Business Days Calculation - Current Issues & Recommendations
🔴 CRITICAL ISSUE: TAT Processor Using Wrong Calculation
Current Problem:
In Re_Backend/src/queues/tatProcessor.ts (lines 64-65), the TAT calculation uses simple calendar hours:
const elapsedMs = now.getTime() - new Date(levelStartTime).getTime();
const elapsedHours = elapsedMs / (1000 * 60 * 60);
This is WRONG because:
- ❌ Counts ALL hours (24/7), including nights, weekends, holidays
- ❌ Doesn't respect working hours (9 AM - 6 PM)
- ❌ Doesn't exclude weekends for STANDARD priority
- ❌ Doesn't exclude holidays
- ❌ Causes incorrect TAT breach alerts
✅ Solution Available:
You already have a proper function calculateElapsedWorkingHours() in tatTimeUtils.ts that:
- ✅ Respects working hours (9 AM - 6 PM)
- ✅ Excludes weekends for STANDARD priority
- ✅ Excludes holidays
- ✅ Handles EXPRESS vs STANDARD differently
- ✅ Uses minute-by-minute precision
🔧 Fix Required:
Update tatProcessor.ts to use proper working hours calculation:
// BEFORE (WRONG):
const elapsedMs = now.getTime() - new Date(levelStartTime).getTime();
const elapsedHours = elapsedMs / (1000 * 60 * 60);
// AFTER (CORRECT):
import { calculateElapsedWorkingHours } from '@utils/tatTimeUtils';
const priority = ((workflow as any).priority || 'STANDARD').toString().toLowerCase();
const elapsedHours = await calculateElapsedWorkingHours(levelStartTime, now, priority);
📊 Business Days Calculation for Workflow Aging Report
Current Situation:
- ✅ You have
calculateElapsedWorkingHours()- calculates hours - ❌ You DON'T have
calculateBusinessDays()- calculates days
Need:
For the Workflow Aging Report, you need to show "Days Open" as business days (excluding weekends and holidays), not calendar days.
🔧 Solution: Add Business Days Function
Add this function to Re_Backend/src/utils/tatTimeUtils.ts:
/**
* Calculate business days between two dates
* Excludes weekends and holidays
* @param startDate - Start date
* @param endDate - End date (defaults to now)
* @param priority - 'express' or 'standard' (express includes weekends, standard excludes)
* @returns Number of business days
*/
export async function calculateBusinessDays(
startDate: Date | string,
endDate: Date | string | null = null,
priority: string = 'standard'
): Promise<number> {
await loadWorkingHoursCache();
await loadHolidaysCache();
let start = dayjs(startDate).startOf('day');
const end = dayjs(endDate || new Date()).startOf('day');
// In test mode, use calendar days
if (isTestMode()) {
return end.diff(start, 'day') + 1;
}
const config = workingHoursCache || {
startHour: TAT_CONFIG.WORK_START_HOUR,
endHour: TAT_CONFIG.WORK_END_HOUR,
startDay: TAT_CONFIG.WORK_START_DAY,
endDay: TAT_CONFIG.WORK_END_DAY
};
let businessDays = 0;
let current = start;
// Count each day from start to end (inclusive)
while (current.isBefore(end) || current.isSame(end, 'day')) {
const dayOfWeek = current.day(); // 0 = Sunday, 6 = Saturday
const dateStr = current.format('YYYY-MM-DD');
// For express priority: count all days (including weekends) but exclude holidays
// For standard priority: count only working days (Mon-Fri) and exclude holidays
const isWorkingDay = priority === 'express'
? true // Express includes weekends
: (dayOfWeek >= config.startDay && dayOfWeek <= config.endDay);
const isNotHoliday = !holidaysCache.has(dateStr);
if (isWorkingDay && isNotHoliday) {
businessDays++;
}
current = current.add(1, 'day');
// Safety check to prevent infinite loops
if (current.diff(start, 'day') > 730) { // 2 years
console.error('[TAT] Safety break - exceeded 2 years in business days calculation');
break;
}
}
return businessDays;
}
📋 Summary of Issues & Fixes
Issue 1: TAT Processor Using Calendar Hours ✅ FIXED
- File:
Re_Backend/src/queues/tatProcessor.ts - Line: 64-65 (now 66-77)
- Problem: Uses simple calendar hours instead of working hours
- Impact: Incorrect TAT breach calculations
- Fix: ✅ Replaced with
calculateElapsedWorkingHours()andaddWorkingHours()/addWorkingHoursExpress() - Status: ✅ COMPLETED - Now uses proper working hours calculation
Issue 2: Missing Business Days Function ✅ FIXED
- File:
Re_Backend/src/utils/tatTimeUtils.ts - Problem: No function to calculate business days count
- Impact: Workflow Aging Report shows calendar days instead of business days
- Fix: ✅ Added
calculateBusinessDays()function (lines 697-758) - Status: ✅ COMPLETED - Function implemented and exported
Issue 3: Workflow Aging Report Using Calendar Days ✅ FIXED
- File:
Re_Backend/src/services/dashboard.service.ts - Problem: Will use calendar days if not fixed
- Impact: Incorrect "Days Open" calculation
- Fix: ✅ Uses
calculateBusinessDays()in report endpoint (getWorkflowAgingReport method) - Status: ✅ COMPLETED - Report now uses business days calculation
🛠️ Implementation Steps ✅ ALL COMPLETED
Step 1: Fix TAT Processor (CRITICAL) ✅ DONE
- ✅ Opened
Re_Backend/src/queues/tatProcessor.ts - ✅ Imported
calculateElapsedWorkingHours,addWorkingHours,addWorkingHoursExpressfrom@utils/tatTimeUtils - ✅ Replaced lines 64-65 with proper working hours calculation (now lines 66-77)
- ✅ Gets priority from workflow
- ⏳ TODO: Test TAT breach alerts
Step 2: Add Business Days Function ✅ DONE
- ✅ Opened
Re_Backend/src/utils/tatTimeUtils.ts - ✅ Added
calculateBusinessDays()function (lines 697-758) - ✅ Exported the function
- ⏳ TODO: Test with various date ranges
Step 3: Update Workflow Aging Report ✅ DONE
- ✅ Built report endpoint using
calculateBusinessDays() - ✅ Filters requests where
businessDays > threshold - ✅ Displays business days instead of calendar days
✅ What's Already Working
- ✅
calculateElapsedWorkingHours()- Properly calculates working hours - ✅
calculateSLAStatus()- Comprehensive SLA calculation - ✅ Working hours configuration (from admin settings)
- ✅ Holiday support (from database)
- ✅ Priority-based calculation (express vs standard)
- ✅ Used correctly in
approval.service.tsanddashboard.service.ts
🎯 Priority Order
- 🔴 CRITICAL: Fix TAT Processor (affects all TAT calculations)
- 🟡 HIGH: Add Business Days Function (needed for reports)
- 🟡 HIGH: Update Workflow Aging Report to use business days
📝 Code Example: Fixed TAT Processor
// In tatProcessor.ts, around line 60-70
import { calculateElapsedWorkingHours } from '@utils/tatTimeUtils';
// ... existing code ...
const tatHours = Number((approvalLevel as any).tatHours || 0);
const levelStartTime = (approvalLevel as any).levelStartTime || (approvalLevel as any).createdAt;
const now = new Date();
// FIXED: Use proper working hours calculation
const priority = ((workflow as any).priority || 'STANDARD').toString().toLowerCase();
const elapsedHours = await calculateElapsedWorkingHours(levelStartTime, now, priority);
const remainingHours = Math.max(0, tatHours - elapsedHours);
const expectedCompletionTime = dayjs(levelStartTime).add(tatHours, 'hour').toDate();
// ... rest of code ...
🧪 Testing Recommendations
-
Test TAT Breach Calculation:
- Create a request with 8-hour TAT
- Submit on Friday 5 PM
- Should NOT breach until Monday 1 PM (next working hour)
- Currently will breach on Saturday 1 AM (wrong!)
-
Test Business Days:
- Start: Monday, Jan 1
- End: Friday, Jan 5
- Should return: 5 business days (not 5 calendar days if there are holidays)
-
Test Express vs Standard:
- Express: Should count weekends
- Standard: Should exclude weekends
📚 Related Files
Re_Backend/src/queues/tatProcessor.ts- ✅ FIXED - Now usescalculateElapsedWorkingHours()and proper deadline calculationRe_Backend/src/utils/tatTimeUtils.ts- ✅ FIXED - AddedcalculateBusinessDays()functionRe_Backend/src/services/approval.service.ts- ✅ Already using correct calculationRe_Backend/src/services/dashboard.service.ts- ✅ FIXED - UsescalculateBusinessDays()in Workflow Aging ReportRe_Backend/src/services/workflow.service.ts- ✅ Already using correct calculation