package services import ( "time" "mgit.msbls.de/m/KanzlAI-mGMT/internal/models" ) // CalculatedDeadline holds a calculated deadline with adjustment info type CalculatedDeadline struct { RuleCode string `json:"rule_code"` RuleID string `json:"rule_id"` Title string `json:"title"` DueDate string `json:"due_date"` OriginalDueDate string `json:"original_due_date"` WasAdjusted bool `json:"was_adjusted"` } // DeadlineCalculator calculates deadlines from rules and event dates type DeadlineCalculator struct { holidays *HolidayService } // NewDeadlineCalculator creates a new calculator func NewDeadlineCalculator(holidays *HolidayService) *DeadlineCalculator { return &DeadlineCalculator{holidays: holidays} } // CalculateEndDate calculates the end date for a single deadline rule based on an event date. // Adapted from youpc.org CalculateDeadlineEndDate. func (c *DeadlineCalculator) CalculateEndDate(eventDate time.Time, rule models.DeadlineRule) (adjusted time.Time, original time.Time, wasAdjusted bool) { endDate := eventDate timing := "after" if rule.Timing != nil { timing = *rule.Timing } durationValue := rule.DurationValue durationUnit := rule.DurationUnit if timing == "before" { switch durationUnit { case "days": endDate = endDate.AddDate(0, 0, -durationValue) case "weeks": endDate = endDate.AddDate(0, 0, -durationValue*7) case "months": endDate = endDate.AddDate(0, -durationValue, 0) } } else { switch durationUnit { case "days": endDate = endDate.AddDate(0, 0, durationValue) case "weeks": endDate = endDate.AddDate(0, 0, durationValue*7) case "months": endDate = endDate.AddDate(0, durationValue, 0) } } original = endDate adjusted, _, wasAdjusted = c.holidays.AdjustForNonWorkingDays(endDate) return adjusted, original, wasAdjusted } // CalculateFromRules calculates deadlines for a set of rules given an event date. // Returns a list of calculated deadlines with due dates. func (c *DeadlineCalculator) CalculateFromRules(eventDate time.Time, rules []models.DeadlineRule) []CalculatedDeadline { results := make([]CalculatedDeadline, 0, len(rules)) for _, rule := range rules { var adjusted, original time.Time var wasAdjusted bool if rule.DurationValue > 0 { adjusted, original, wasAdjusted = c.CalculateEndDate(eventDate, rule) } else { adjusted = eventDate original = eventDate } code := "" if rule.Code != nil { code = *rule.Code } results = append(results, CalculatedDeadline{ RuleCode: code, RuleID: rule.ID.String(), Title: rule.Name, DueDate: adjusted.Format("2006-01-02"), OriginalDueDate: original.Format("2006-01-02"), WasAdjusted: wasAdjusted, }) } return results }