# 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**: ```typescript 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:** ```typescript // 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`: ```typescript /** * 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 { 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()` and `addWorkingHours()`/`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** 1. โœ… Opened `Re_Backend/src/queues/tatProcessor.ts` 2. โœ… Imported `calculateElapsedWorkingHours`, `addWorkingHours`, `addWorkingHoursExpress` from `@utils/tatTimeUtils` 3. โœ… Replaced lines 64-65 with proper working hours calculation (now lines 66-77) 4. โœ… Gets priority from workflow 5. โณ **TODO:** Test TAT breach alerts ### Step 2: Add Business Days Function โœ… **DONE** 1. โœ… Opened `Re_Backend/src/utils/tatTimeUtils.ts` 2. โœ… Added `calculateBusinessDays()` function (lines 697-758) 3. โœ… Exported the function 4. โณ **TODO:** Test with various date ranges ### Step 3: Update Workflow Aging Report โœ… **DONE** 1. โœ… Built report endpoint using `calculateBusinessDays()` 2. โœ… Filters requests where `businessDays > threshold` 3. โœ… 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.ts` and `dashboard.service.ts` --- ## ๐ŸŽฏ **Priority Order** 1. **๐Ÿ”ด CRITICAL:** Fix TAT Processor (affects all TAT calculations) 2. **๐ŸŸก HIGH:** Add Business Days Function (needed for reports) 3. **๐ŸŸก HIGH:** Update Workflow Aging Report to use business days --- ## ๐Ÿ“ **Code Example: Fixed TAT Processor** ```typescript // 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** 1. **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!) 2. **Test Business Days:** - Start: Monday, Jan 1 - End: Friday, Jan 5 - Should return: 5 business days (not 5 calendar days if there are holidays) 3. **Test Express vs Standard:** - Express: Should count weekends - Standard: Should exclude weekends --- ## ๐Ÿ“š **Related Files** - `Re_Backend/src/queues/tatProcessor.ts` - โœ… **FIXED** - Now uses `calculateElapsedWorkingHours()` and proper deadline calculation - `Re_Backend/src/utils/tatTimeUtils.ts` - โœ… **FIXED** - Added `calculateBusinessDays()` function - `Re_Backend/src/services/approval.service.ts` - โœ… Already using correct calculation - `Re_Backend/src/services/dashboard.service.ts` - โœ… **FIXED** - Uses `calculateBusinessDays()` in Workflow Aging Report - `Re_Backend/src/services/workflow.service.ts` - โœ… Already using correct calculation