Re_Backend/src/utils/helpers.ts

109 lines
3.5 KiB
TypeScript

import { WorkflowRequest } from '@models/WorkflowRequest';
import { Op } from 'sequelize';
import logger from './logger';
/**
* Generate request number in format: REQ-YYYY-MM-XXXX
* Counter resets every month
* Example: REQ-2025-11-0001
*/
export const generateRequestNumber = async (): Promise<string> => {
const now = new Date();
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, '0'); // Month is 0-indexed, so add 1
// Build the prefix pattern for current year-month
const prefix = `REQ-${year}-${month}-`;
try {
// Find the highest counter for the current year-month
const existingRequests = await WorkflowRequest.findAll({
where: {
requestNumber: {
[Op.like]: `${prefix}%`
}
},
attributes: ['requestNumber'],
order: [['requestNumber', 'DESC']],
limit: 1
});
let counter = 1;
if (existingRequests.length > 0) {
// Extract the counter from the last request number
const lastRequestNumber = (existingRequests[0] as any).requestNumber;
const lastCounter = parseInt(lastRequestNumber.replace(prefix, ''), 10);
if (!isNaN(lastCounter)) {
counter = lastCounter + 1;
}
}
// Format counter as 4-digit number (0001, 0002, etc.)
const counterStr = counter.toString().padStart(4, '0');
return `${prefix}${counterStr}`;
} catch (error) {
// Fallback to timestamp-based counter if database query fails
logger.error('Error generating request number:', error);
const fallbackCounter = Date.now().toString().slice(-4);
return `${prefix}${fallbackCounter}`;
}
};
export const calculateTATDays = (tatHours: number): number => {
return Math.ceil(tatHours / 24);
};
export const calculateElapsedHours = (startTime: Date, endTime?: Date): number => {
const end = endTime || new Date();
const diffMs = end.getTime() - startTime.getTime();
return Math.round((diffMs / (1000 * 60 * 60)) * 100) / 100; // Round to 2 decimal places
};
export const calculateTATPercentage = (elapsedHours: number, totalTatHours: number): number => {
if (totalTatHours === 0) return 0;
return Math.min(Math.round((elapsedHours / totalTatHours) * 100), 100);
};
export const isTATBreached = (elapsedHours: number, totalTatHours: number): boolean => {
return elapsedHours > totalTatHours;
};
export const isTATApproaching = (elapsedHours: number, totalTatHours: number, threshold: number = 80): boolean => {
const percentage = calculateTATPercentage(elapsedHours, totalTatHours);
return percentage >= threshold && percentage < 100;
};
export const formatDate = (date: Date): string => {
return date.toISOString().split('T')[0];
};
export const formatDateTime = (date: Date): string => {
return date.toISOString();
};
export const isValidEmail = (email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
export const isValidUUID = (uuid: string): boolean => {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return uuidRegex.test(uuid);
};
export const sanitizeString = (str: string): string => {
return str.trim().replace(/[<>]/g, '');
};
export const generateChecksum = (data: string): string => {
const crypto = require('crypto');
return crypto.createHash('sha256').update(data).digest('hex');
};
export const sleep = (ms: number): Promise<void> => {
return new Promise(resolve => setTimeout(resolve, ms));
};