TAT calculation enhanced
This commit is contained in:
parent
1aa7fb9056
commit
c76b799cf7
@ -365,8 +365,8 @@ export const updateConfiguration = async (req: Request, res: Response): Promise<
|
||||
// If working hours config was updated, also clear working hours cache
|
||||
const workingHoursKeys = ['WORK_START_HOUR', 'WORK_END_HOUR', 'WORK_START_DAY', 'WORK_END_DAY'];
|
||||
if (workingHoursKeys.includes(configKey)) {
|
||||
clearWorkingHoursCache();
|
||||
logger.info(`[Admin] Working hours configuration '${configKey}' updated - cache cleared`);
|
||||
await clearWorkingHoursCache();
|
||||
logger.info(`[Admin] Working hours configuration '${configKey}' updated - cache cleared and reloaded`);
|
||||
} else {
|
||||
logger.info(`[Admin] Configuration '${configKey}' updated and cache cleared`);
|
||||
}
|
||||
@ -407,8 +407,8 @@ export const resetConfiguration = async (req: Request, res: Response): Promise<v
|
||||
// If working hours config was reset, also clear working hours cache
|
||||
const workingHoursKeys = ['WORK_START_HOUR', 'WORK_END_HOUR', 'WORK_START_DAY', 'WORK_END_DAY'];
|
||||
if (workingHoursKeys.includes(configKey)) {
|
||||
clearWorkingHoursCache();
|
||||
logger.info(`[Admin] Working hours configuration '${configKey}' reset to default - cache cleared`);
|
||||
await clearWorkingHoursCache();
|
||||
logger.info(`[Admin] Working hours configuration '${configKey}' reset to default - cache cleared and reloaded`);
|
||||
} else {
|
||||
logger.info(`[Admin] Configuration '${configKey}' reset to default and cache cleared`);
|
||||
}
|
||||
|
||||
@ -37,10 +37,10 @@ export async function getConfigValue(configKey: string, defaultValue: string = '
|
||||
const value = (result[0] as any).config_value;
|
||||
configCache.set(configKey, value);
|
||||
|
||||
// Set cache expiry if not set
|
||||
if (!cacheExpiry) {
|
||||
// Always update cache expiry when loading from database
|
||||
cacheExpiry = new Date(Date.now() + CACHE_DURATION_MS);
|
||||
}
|
||||
|
||||
logger.info(`[ConfigReader] Loaded config '${configKey}' = '${value}' from database (cached for 5min)`);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -39,6 +39,8 @@ async function loadWorkingHoursCache(): Promise<void> {
|
||||
};
|
||||
workingHoursCacheExpiry = dayjs().add(5, 'minute').toDate();
|
||||
|
||||
console.log(`[TAT Utils] ✅ Working hours loaded from admin config: ${hours.startHour}:00 - ${hours.endHour}:00 (Days: ${startDay}-${endDay})`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('[TAT] Error loading working hours:', error);
|
||||
// Fallback to default values from TAT_CONFIG
|
||||
@ -48,7 +50,7 @@ async function loadWorkingHoursCache(): Promise<void> {
|
||||
startDay: TAT_CONFIG.WORK_START_DAY,
|
||||
endDay: TAT_CONFIG.WORK_END_DAY
|
||||
};
|
||||
console.log('[TAT Utils] Using fallback working hours from TAT_CONFIG');
|
||||
console.log(`[TAT Utils] ⚠️ Using fallback working hours from system config: ${TAT_CONFIG.WORK_START_HOUR}:00 - ${TAT_CONFIG.WORK_END_HOUR}:00`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,6 +146,37 @@ export async function addWorkingHours(start: Date | string, hoursToAdd: number):
|
||||
await loadWorkingHoursCache();
|
||||
await loadHolidaysCache();
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
// If start time is before working hours or outside working days/holidays,
|
||||
// advance to the next working hour start (reset to clean hour)
|
||||
const originalStart = current.format('YYYY-MM-DD HH:mm:ss');
|
||||
const wasOutsideWorkingHours = !isWorkingTime(current);
|
||||
|
||||
while (!isWorkingTime(current)) {
|
||||
const hour = current.hour();
|
||||
const day = current.day();
|
||||
|
||||
// If before work start hour on a working day, jump to work start hour
|
||||
if (day >= config.startDay && day <= config.endDay && !isHoliday(current) && hour < config.startHour) {
|
||||
current = current.hour(config.startHour);
|
||||
} else {
|
||||
// After working hours or non-working day - advance to next working period
|
||||
current = current.add(1, 'hour');
|
||||
}
|
||||
}
|
||||
|
||||
// If start time was outside working hours, reset to clean work start time (no minutes)
|
||||
if (wasOutsideWorkingHours) {
|
||||
current = current.minute(0).second(0).millisecond(0);
|
||||
console.log(`[TAT Utils] Start time ${originalStart} was outside working hours, advanced to ${current.format('YYYY-MM-DD HH:mm:ss')}`);
|
||||
}
|
||||
|
||||
let remaining = hoursToAdd;
|
||||
|
||||
while (remaining > 0) {
|
||||
@ -181,6 +214,19 @@ export async function addWorkingHoursExpress(start: Date | string, hoursToAdd: n
|
||||
endDay: TAT_CONFIG.WORK_END_DAY
|
||||
};
|
||||
|
||||
// If start time is outside working hours, advance to work start hour (reset to clean hour)
|
||||
const originalStart = current.format('YYYY-MM-DD HH:mm:ss');
|
||||
const currentHour = current.hour();
|
||||
if (currentHour < config.startHour) {
|
||||
// Before working hours - reset to clean work start
|
||||
current = current.hour(config.startHour).minute(0).second(0).millisecond(0);
|
||||
console.log(`[TAT Utils Express] Start time ${originalStart} was before working hours, advanced to ${current.format('YYYY-MM-DD HH:mm:ss')}`);
|
||||
} else if (currentHour >= config.endHour) {
|
||||
// After working hours - reset to clean start of next day
|
||||
current = current.add(1, 'day').hour(config.startHour).minute(0).second(0).millisecond(0);
|
||||
console.log(`[TAT Utils Express] Start time ${originalStart} was after working hours, advanced to ${current.format('YYYY-MM-DD HH:mm:ss')}`);
|
||||
}
|
||||
|
||||
let remaining = hoursToAdd;
|
||||
|
||||
while (remaining > 0) {
|
||||
@ -188,7 +234,7 @@ export async function addWorkingHoursExpress(start: Date | string, hoursToAdd: n
|
||||
const hour = current.hour();
|
||||
|
||||
// For express: count ALL days (including weekends/holidays)
|
||||
// But only during working hours (9 AM - 6 PM)
|
||||
// But only during working hours (configured start - end hour)
|
||||
if (hour >= config.startHour && hour < config.endHour) {
|
||||
remaining -= 1;
|
||||
}
|
||||
@ -234,6 +280,32 @@ export function addWorkingHoursSync(start: Date | string, hoursToAdd: number): D
|
||||
endDay: TAT_CONFIG.WORK_END_DAY
|
||||
};
|
||||
|
||||
// If start time is before working hours or outside working days,
|
||||
// advance to the next working hour start (reset to clean hour)
|
||||
const originalStart = current.format('YYYY-MM-DD HH:mm:ss');
|
||||
let hour = current.hour();
|
||||
let day = current.day();
|
||||
|
||||
// Check if originally outside working hours
|
||||
const wasOutsideWorkingHours = !(day >= config.startDay && day <= config.endDay && hour >= config.startHour && hour < config.endHour);
|
||||
|
||||
// If before work start hour on a working day, jump to work start hour
|
||||
if (day >= config.startDay && day <= config.endDay && hour < config.startHour) {
|
||||
current = current.hour(config.startHour);
|
||||
} else {
|
||||
// Advance to next working hour
|
||||
while (!(day >= config.startDay && day <= config.endDay && hour >= config.startHour && hour < config.endHour)) {
|
||||
current = current.add(1, 'hour');
|
||||
day = current.day();
|
||||
hour = current.hour();
|
||||
}
|
||||
}
|
||||
|
||||
// If start time was outside working hours, reset to clean work start time
|
||||
if (wasOutsideWorkingHours) {
|
||||
current = current.minute(0).second(0).millisecond(0);
|
||||
}
|
||||
|
||||
let remaining = hoursToAdd;
|
||||
|
||||
while (remaining > 0) {
|
||||
@ -260,11 +332,15 @@ export async function initializeHolidaysCache(): Promise<void> {
|
||||
|
||||
/**
|
||||
* Clear working hours cache (call when admin updates configuration)
|
||||
* Also immediately reloads the cache with new values
|
||||
*/
|
||||
export function clearWorkingHoursCache(): void {
|
||||
export async function clearWorkingHoursCache(): Promise<void> {
|
||||
workingHoursCache = null;
|
||||
workingHoursCacheExpiry = null;
|
||||
// Cache cleared
|
||||
console.log('[TAT Utils] Working hours cache cleared - reloading from database...');
|
||||
|
||||
// Immediately reload the cache with new values
|
||||
await loadWorkingHoursCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,7 +508,7 @@ export async function calculateElapsedWorkingHours(
|
||||
await loadWorkingHoursCache();
|
||||
await loadHolidaysCache();
|
||||
|
||||
const start = dayjs(startDate);
|
||||
let start = dayjs(startDate);
|
||||
const end = dayjs(endDateParam || new Date());
|
||||
|
||||
// In test mode, use raw minutes for 1:1 conversion
|
||||
@ -447,6 +523,54 @@ export async function calculateElapsedWorkingHours(
|
||||
endDay: TAT_CONFIG.WORK_END_DAY
|
||||
};
|
||||
|
||||
// CRITICAL FIX: If start time is outside working hours, advance to next working period
|
||||
// This ensures we only count elapsed time when TAT is actually running
|
||||
const originalStart = start.format('YYYY-MM-DD HH:mm:ss');
|
||||
|
||||
// For standard priority, check working days and hours
|
||||
if (priority !== 'express') {
|
||||
const wasOutsideWorkingHours = !isWorkingTime(start);
|
||||
|
||||
while (!isWorkingTime(start)) {
|
||||
const hour = start.hour();
|
||||
const day = start.day();
|
||||
|
||||
// If before work start hour on a working day, jump to work start hour
|
||||
if (day >= config.startDay && day <= config.endDay && !isHoliday(start) && hour < config.startHour) {
|
||||
start = start.hour(config.startHour);
|
||||
} else {
|
||||
// Otherwise, advance by 1 hour and check again
|
||||
start = start.add(1, 'hour');
|
||||
}
|
||||
}
|
||||
|
||||
// If start time was outside working hours, reset to clean work start time
|
||||
if (wasOutsideWorkingHours) {
|
||||
start = start.minute(0).second(0).millisecond(0);
|
||||
}
|
||||
} else {
|
||||
// For express priority, only check working hours (not days)
|
||||
const hour = start.hour();
|
||||
if (hour < config.startHour) {
|
||||
// Before hours - reset to clean start
|
||||
start = start.hour(config.startHour).minute(0).second(0).millisecond(0);
|
||||
} else if (hour >= config.endHour) {
|
||||
// After hours - reset to clean start of next day
|
||||
start = start.add(1, 'day').hour(config.startHour).minute(0).second(0).millisecond(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Log if we advanced the start time for elapsed calculation
|
||||
if (start.format('YYYY-MM-DD HH:mm:ss') !== originalStart) {
|
||||
console.log(`[TAT Utils] Elapsed time calculation: Start ${originalStart} was outside working hours, advanced to ${start.format('YYYY-MM-DD HH:mm:ss')}`);
|
||||
}
|
||||
|
||||
// If end time is before adjusted start time, return 0 (TAT hasn't started yet)
|
||||
if (end.isBefore(start)) {
|
||||
console.log(`[TAT Utils] Current time is before TAT start time - elapsed hours: 0`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
let totalWorkingMinutes = 0;
|
||||
let currentDate = start.startOf('day');
|
||||
const endDay = end.startOf('day');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user