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
|
// 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'];
|
const workingHoursKeys = ['WORK_START_HOUR', 'WORK_END_HOUR', 'WORK_START_DAY', 'WORK_END_DAY'];
|
||||||
if (workingHoursKeys.includes(configKey)) {
|
if (workingHoursKeys.includes(configKey)) {
|
||||||
clearWorkingHoursCache();
|
await clearWorkingHoursCache();
|
||||||
logger.info(`[Admin] Working hours configuration '${configKey}' updated - cache cleared`);
|
logger.info(`[Admin] Working hours configuration '${configKey}' updated - cache cleared and reloaded`);
|
||||||
} else {
|
} else {
|
||||||
logger.info(`[Admin] Configuration '${configKey}' updated and cache cleared`);
|
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
|
// 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'];
|
const workingHoursKeys = ['WORK_START_HOUR', 'WORK_END_HOUR', 'WORK_START_DAY', 'WORK_END_DAY'];
|
||||||
if (workingHoursKeys.includes(configKey)) {
|
if (workingHoursKeys.includes(configKey)) {
|
||||||
clearWorkingHoursCache();
|
await clearWorkingHoursCache();
|
||||||
logger.info(`[Admin] Working hours configuration '${configKey}' reset to default - cache cleared`);
|
logger.info(`[Admin] Working hours configuration '${configKey}' reset to default - cache cleared and reloaded`);
|
||||||
} else {
|
} else {
|
||||||
logger.info(`[Admin] Configuration '${configKey}' reset to default and cache cleared`);
|
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;
|
const value = (result[0] as any).config_value;
|
||||||
configCache.set(configKey, value);
|
configCache.set(configKey, value);
|
||||||
|
|
||||||
// Set cache expiry if not set
|
// Always update cache expiry when loading from database
|
||||||
if (!cacheExpiry) {
|
cacheExpiry = new Date(Date.now() + CACHE_DURATION_MS);
|
||||||
cacheExpiry = new Date(Date.now() + CACHE_DURATION_MS);
|
|
||||||
}
|
logger.info(`[ConfigReader] Loaded config '${configKey}' = '${value}' from database (cached for 5min)`);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,8 @@ async function loadWorkingHoursCache(): Promise<void> {
|
|||||||
};
|
};
|
||||||
workingHoursCacheExpiry = dayjs().add(5, 'minute').toDate();
|
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) {
|
} catch (error) {
|
||||||
console.error('[TAT] Error loading working hours:', error);
|
console.error('[TAT] Error loading working hours:', error);
|
||||||
// Fallback to default values from TAT_CONFIG
|
// Fallback to default values from TAT_CONFIG
|
||||||
@ -48,7 +50,7 @@ async function loadWorkingHoursCache(): Promise<void> {
|
|||||||
startDay: TAT_CONFIG.WORK_START_DAY,
|
startDay: TAT_CONFIG.WORK_START_DAY,
|
||||||
endDay: TAT_CONFIG.WORK_END_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 loadWorkingHoursCache();
|
||||||
await loadHolidaysCache();
|
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;
|
let remaining = hoursToAdd;
|
||||||
|
|
||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
@ -181,6 +214,19 @@ export async function addWorkingHoursExpress(start: Date | string, hoursToAdd: n
|
|||||||
endDay: TAT_CONFIG.WORK_END_DAY
|
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;
|
let remaining = hoursToAdd;
|
||||||
|
|
||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
@ -188,7 +234,7 @@ export async function addWorkingHoursExpress(start: Date | string, hoursToAdd: n
|
|||||||
const hour = current.hour();
|
const hour = current.hour();
|
||||||
|
|
||||||
// For express: count ALL days (including weekends/holidays)
|
// 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) {
|
if (hour >= config.startHour && hour < config.endHour) {
|
||||||
remaining -= 1;
|
remaining -= 1;
|
||||||
}
|
}
|
||||||
@ -234,6 +280,32 @@ export function addWorkingHoursSync(start: Date | string, hoursToAdd: number): D
|
|||||||
endDay: TAT_CONFIG.WORK_END_DAY
|
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;
|
let remaining = hoursToAdd;
|
||||||
|
|
||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
@ -260,11 +332,15 @@ export async function initializeHolidaysCache(): Promise<void> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear working hours cache (call when admin updates configuration)
|
* 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;
|
workingHoursCache = null;
|
||||||
workingHoursCacheExpiry = 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 loadWorkingHoursCache();
|
||||||
await loadHolidaysCache();
|
await loadHolidaysCache();
|
||||||
|
|
||||||
const start = dayjs(startDate);
|
let start = dayjs(startDate);
|
||||||
const end = dayjs(endDateParam || new Date());
|
const end = dayjs(endDateParam || new Date());
|
||||||
|
|
||||||
// In test mode, use raw minutes for 1:1 conversion
|
// In test mode, use raw minutes for 1:1 conversion
|
||||||
@ -447,6 +523,54 @@ export async function calculateElapsedWorkingHours(
|
|||||||
endDay: TAT_CONFIG.WORK_END_DAY
|
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 totalWorkingMinutes = 0;
|
||||||
let currentDate = start.startOf('day');
|
let currentDate = start.startOf('day');
|
||||||
const endDay = end.startOf('day');
|
const endDay = end.startOf('day');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user