Files

128 lines
2.9 KiB
Go
Raw Permalink Normal View History

2026-04-02 10:57:36 -04:00
package sla
import (
"context"
"log"
"time"
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
)
// DefaultSLACalculator implements the SLACalculator interface
type DefaultSLACalculator struct {
Timezone string
BusinessStart int
BusinessEnd int
Holidays map[string]bool
}
// NewSLACalculator returns the interface
func NewSLACalculator() domain.SLACalculator {
return &DefaultSLACalculator{
Timezone: "UTC",
BusinessStart: 9,
BusinessEnd: 17,
Holidays: make(map[string]bool),
}
}
// CalculateDueDate for the finding based on SLA
func (c *DefaultSLACalculator) CalculateDueDate(severity string) *time.Time {
var days int
switch severity {
case "Critical":
days = 3
case "High":
days = 14
case "Medium":
days = 30
case "Low":
days = 90
default:
days = 30
}
loc, err := time.LoadLocation(c.Timezone)
if err != nil {
log.Printf("Warning: Invalid timezone '%s', falling back to UTC", c.Timezone)
loc = time.UTC
}
nowLocal := time.Now().In(loc)
dueDate := c.AddBusinessDays(nowLocal, days)
return &dueDate
}
// AddBusinessDays for working days not weekends and some holidays
func (c *DefaultSLACalculator) AddBusinessDays(start time.Time, businessDays int) time.Time {
current := start
added := 0
for added < businessDays {
current = current.AddDate(0, 0, 1)
weekday := current.Weekday()
dateStr := current.Format("2006-01-02")
if weekday != time.Saturday && weekday != time.Sunday && !c.Holidays[dateStr] {
added++
}
}
return current
}
// CalculateTrueSLAHours based on the time of action for ticket
func (c *DefaultSLACalculator) CalculateTrueSLAHours(ctx context.Context, ticketID int, store domain.Store) (float64, error) {
appConfig, err := store.GetAppConfig(ctx)
if err != nil {
return 0, err
}
ticket, err := store.GetTicketByID(ctx, ticketID)
if err != nil {
return 0, err
}
end := time.Now()
if ticket.PatchedAt != nil {
end = *ticket.PatchedAt
}
totalActiveBusinessHours := c.calculateBusinessHoursBetween(ticket.CreatedAt, end, appConfig)
return totalActiveBusinessHours, nil
}
// calculateBusinessHoursBetween calculates strict working hours between two timestamps
func (c *DefaultSLACalculator) calculateBusinessHoursBetween(start, end time.Time, config domain.AppConfig) float64 {
loc, _ := time.LoadLocation(config.Timezone)
start = start.In(loc)
end = end.In(loc)
if start.After(end) {
return 0
}
var activeHours float64
current := start
for current.Before(end) {
nextHour := current.Add(time.Hour)
if nextHour.After(end) {
nextHour = end
}
weekday := current.Weekday()
dateStr := current.Format("2006-01-02")
hour := current.Hour()
isWeekend := weekday == time.Saturday || weekday == time.Sunday
isHoliday := c.Holidays[dateStr]
isBusinessHour := hour >= config.BusinessStart && hour < config.BusinessEnd
if !isWeekend && !isHoliday && isBusinessHour {
activeHours += nextHour.Sub(current).Hours()
}
current = nextHour
}
return activeHours
}