79 lines
3.1 KiB
TypeScript
79 lines
3.1 KiB
TypeScript
import db from '../database/models/index.js';
|
|
const { SLATracking, SLAConfiguration, SLABreach, Application, User } = db;
|
|
import { Op } from 'sequelize';
|
|
import { NotificationService } from './NotificationService.js';
|
|
|
|
export class SLAService {
|
|
/**
|
|
* Periodically check for SLA breaches across all active tracking records
|
|
*/
|
|
static async checkBreaches() {
|
|
console.log('[SLA Service] Starting breach check...');
|
|
|
|
// Find all active tracking records that are still 'In Progress' (not concluded)
|
|
const activeTracking = await SLATracking.findAll({
|
|
where: { isActive: true, isBreached: false, endTime: null },
|
|
include: [
|
|
{ model: Application, as: 'application' }
|
|
]
|
|
});
|
|
|
|
const now = new Date();
|
|
|
|
for (const track of activeTracking) {
|
|
// Fetch SLA configuration for this specific stage and entity type
|
|
const config = await SLAConfiguration.findOne({
|
|
where: {
|
|
stageName: track.stageName,
|
|
entityType: track.entityType,
|
|
isActive: true
|
|
}
|
|
});
|
|
|
|
if (!config) continue;
|
|
|
|
const startTime = new Date(track.startTime);
|
|
const slaHours = config.slaHours;
|
|
const deadline = new Date(startTime.getTime() + (slaHours * 60 * 60 * 1000));
|
|
|
|
if (now > deadline) {
|
|
// BREACH DETECTED
|
|
console.log(`[SLA Service] Breach detected for ${track.entityType}: ${track.application?.applicationId || track.entityId}, Stage: ${track.stageName}`);
|
|
|
|
// Update tracking record
|
|
await track.update({ isBreached: true });
|
|
|
|
// Create Breach Record
|
|
await SLABreach.create({
|
|
trackingId: track.id,
|
|
applicationId: track.applicationId,
|
|
stageCode: track.stageName,
|
|
breachedAt: now,
|
|
severity: 'High',
|
|
status: 'Open'
|
|
});
|
|
|
|
// Notify Stakeholders (Escalation)
|
|
await this.notifyEscalated(track);
|
|
}
|
|
}
|
|
console.log(`[SLA Service] Breach check completed at ${now.toISOString()}`);
|
|
}
|
|
|
|
private static async notifyEscalated(track: any) {
|
|
// Find the assigned user to notify them and potentially their manager
|
|
const application = await Application.findByPk(track.applicationId, {
|
|
include: [{ model: User, as: 'assignedToUser' }]
|
|
});
|
|
|
|
if (application?.assignedToUser) {
|
|
await NotificationService.notify(application.assignedTo, application.assignedToUser.email, {
|
|
title: `SLA BREACH: ${track.stageName}`,
|
|
message: `The application ${application.applicationId} has breached the SLA for ${track.stageName}. Current stage: ${application.currentStage}.`,
|
|
channels: ['email', 'system'],
|
|
metadata: { type: 'error', applicationId: application.id }
|
|
});
|
|
}
|
|
}
|
|
}
|