Files
KanzlAI-mGMT/backend/internal/services/deadline_calculator_test.go
m 42a62d45bf feat: add deadline CRUD, calculator, and holiday services (Phase 1C)
- Holiday service with German federal holidays, Easter calculation, DB loading
- Deadline calculator adapted from youpc.org (duration calc + non-working day adjustment)
- Deadline CRUD service (tenant-scoped: list, create, update, complete, delete)
- Deadline rule service (list, filter by proceeding type, hierarchical rule trees)
- HTTP handlers for all endpoints with tenant resolution via X-Tenant-ID header
- Router wired with all new endpoints under /api/
- Tests for holiday and calculator services (8 passing)
2026-03-25 13:31:29 +01:00

142 lines
3.8 KiB
Go

package services
import (
"testing"
"time"
"github.com/google/uuid"
"mgit.msbls.de/m/KanzlAI-mGMT/internal/models"
)
func TestCalculateEndDateAfterDays(t *testing.T) {
holidays := NewHolidayService(nil)
calc := NewDeadlineCalculator(holidays)
eventDate := time.Date(2026, 3, 25, 0, 0, 0, 0, time.UTC) // Wednesday
timing := "after"
rule := models.DeadlineRule{
ID: uuid.New(),
Name: "Test 10 days",
DurationValue: 10,
DurationUnit: "days",
Timing: &timing,
}
adjusted, original, wasAdjusted := calc.CalculateEndDate(eventDate, rule)
// 25 March + 10 days = 4 April 2026 (Saturday)
// Apr 5 = Easter Sunday (holiday), Apr 6 = Easter Monday (holiday) -> adjusted to 7 April (Tuesday)
expectedOriginal := time.Date(2026, 4, 4, 0, 0, 0, 0, time.UTC)
expectedAdjusted := time.Date(2026, 4, 7, 0, 0, 0, 0, time.UTC)
if original != expectedOriginal {
t.Errorf("original should be %s, got %s", expectedOriginal, original)
}
if adjusted != expectedAdjusted {
t.Errorf("adjusted should be %s, got %s", expectedAdjusted, adjusted)
}
if !wasAdjusted {
t.Error("should have been adjusted (Saturday)")
}
}
func TestCalculateEndDateBeforeMonths(t *testing.T) {
holidays := NewHolidayService(nil)
calc := NewDeadlineCalculator(holidays)
eventDate := time.Date(2026, 6, 15, 0, 0, 0, 0, time.UTC) // Monday
timing := "before"
rule := models.DeadlineRule{
ID: uuid.New(),
Name: "Test 2 months before",
DurationValue: 2,
DurationUnit: "months",
Timing: &timing,
}
adjusted, original, wasAdjusted := calc.CalculateEndDate(eventDate, rule)
// 15 June - 2 months = 15 April 2026 (Wednesday)
expected := time.Date(2026, 4, 15, 0, 0, 0, 0, time.UTC)
if original != expected {
t.Errorf("original should be %s, got %s", expected, original)
}
if adjusted != expected {
t.Errorf("adjusted should be %s (not a holiday/weekend), got %s", expected, adjusted)
}
if wasAdjusted {
t.Error("should not have been adjusted (Wednesday)")
}
}
func TestCalculateEndDateWeeks(t *testing.T) {
holidays := NewHolidayService(nil)
calc := NewDeadlineCalculator(holidays)
eventDate := time.Date(2026, 3, 25, 0, 0, 0, 0, time.UTC) // Wednesday
timing := "after"
rule := models.DeadlineRule{
ID: uuid.New(),
Name: "Test 2 weeks",
DurationValue: 2,
DurationUnit: "weeks",
Timing: &timing,
}
adjusted, original, _ := calc.CalculateEndDate(eventDate, rule)
// 25 March + 14 days = 8 April 2026 (Wednesday)
expected := time.Date(2026, 4, 8, 0, 0, 0, 0, time.UTC)
if original != expected {
t.Errorf("original should be %s, got %s", expected, original)
}
if adjusted != expected {
t.Errorf("adjusted should be %s, got %s", expected, adjusted)
}
}
func TestCalculateFromRules(t *testing.T) {
holidays := NewHolidayService(nil)
calc := NewDeadlineCalculator(holidays)
eventDate := time.Date(2026, 3, 25, 0, 0, 0, 0, time.UTC)
timing := "after"
code := "TEST-1"
rules := []models.DeadlineRule{
{
ID: uuid.New(),
Code: &code,
Name: "Rule A",
DurationValue: 7,
DurationUnit: "days",
Timing: &timing,
},
{
ID: uuid.New(),
Name: "Rule B (zero duration)",
DurationValue: 0,
DurationUnit: "days",
},
}
results := calc.CalculateFromRules(eventDate, rules)
if len(results) != 2 {
t.Fatalf("expected 2 results, got %d", len(results))
}
// Rule A: 25 March + 7 = 1 April (Wednesday)
if results[0].DueDate != "2026-04-01" {
t.Errorf("Rule A due date should be 2026-04-01, got %s", results[0].DueDate)
}
if results[0].RuleCode != "TEST-1" {
t.Errorf("Rule A code should be TEST-1, got %s", results[0].RuleCode)
}
// Rule B: zero duration -> event date
if results[1].DueDate != "2026-03-25" {
t.Errorf("Rule B due date should be 2026-03-25, got %s", results[1].DueDate)
}
}