Re_Backend/Business_Days_Calculation_Recommendations.md

242 lines
8.5 KiB
Markdown

# 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<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()` 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