277 lines
8.8 KiB
Go
277 lines
8.8 KiB
Go
package services_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"cs-agent/internal/models"
|
|
"cs-agent/internal/pkg/dto"
|
|
"cs-agent/internal/pkg/dto/request"
|
|
"cs-agent/internal/pkg/enums"
|
|
"cs-agent/internal/services"
|
|
|
|
"github.com/glebarez/sqlite"
|
|
"github.com/mlogclub/simple/sqls"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/schema"
|
|
)
|
|
|
|
func TestAgentTeamScheduleServiceFindCalendarSchedulesReturnsIntersectingSchedules(t *testing.T) {
|
|
db := setupAgentTeamScheduleTestDB(t)
|
|
createAgentTeamScheduleTestData(t, db)
|
|
|
|
list, err := services.AgentTeamScheduleService.FindCalendarSchedules(request.AgentTeamScheduleCalendarRequest{
|
|
StartAt: "2026-04-27 00:00:00",
|
|
EndAt: "2026-05-04 00:00:00",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("FindCalendarSchedules() error = %v", err)
|
|
}
|
|
|
|
if len(list) != 3 {
|
|
t.Fatalf("expected 3 intersecting schedules, got %d: %+v", len(list), list)
|
|
}
|
|
gotIDs := make([]int64, 0, len(list))
|
|
for _, item := range list {
|
|
gotIDs = append(gotIDs, item.ID)
|
|
}
|
|
wantIDs := []int64{1, 2, 3}
|
|
for i, want := range wantIDs {
|
|
if gotIDs[i] != want {
|
|
t.Fatalf("expected ids %v, got %v", wantIDs, gotIDs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAgentTeamScheduleServiceFindCalendarSchedulesFiltersTeamID(t *testing.T) {
|
|
db := setupAgentTeamScheduleTestDB(t)
|
|
createAgentTeamScheduleTestData(t, db)
|
|
|
|
list, err := services.AgentTeamScheduleService.FindCalendarSchedules(request.AgentTeamScheduleCalendarRequest{
|
|
StartAt: "2026-04-27 00:00:00",
|
|
EndAt: "2026-05-04 00:00:00",
|
|
TeamID: 2,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("FindCalendarSchedules() error = %v", err)
|
|
}
|
|
|
|
if len(list) != 1 {
|
|
t.Fatalf("expected 1 schedule for team 2, got %d: %+v", len(list), list)
|
|
}
|
|
if list[0].ID != 3 || list[0].TeamID != 2 {
|
|
t.Fatalf("unexpected schedule: %+v", list[0])
|
|
}
|
|
}
|
|
|
|
func TestAgentTeamScheduleServiceFindCalendarSchedulesValidatesTimeRange(t *testing.T) {
|
|
setupAgentTeamScheduleTestDB(t)
|
|
|
|
_, err := services.AgentTeamScheduleService.FindCalendarSchedules(request.AgentTeamScheduleCalendarRequest{
|
|
StartAt: "2026-05-04 00:00:00",
|
|
EndAt: "2026-04-27 00:00:00",
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected invalid time range to fail")
|
|
}
|
|
}
|
|
|
|
func TestAgentTeamScheduleServiceCreateRejectsCrossDaySchedule(t *testing.T) {
|
|
setupAgentTeamScheduleTestDB(t)
|
|
createAgentTeamScheduleTestTeams(t, sqls.DB())
|
|
|
|
tomorrow := time.Now().AddDate(0, 0, 1)
|
|
_, err := services.AgentTeamScheduleService.CreateAgentTeamSchedule(request.CreateAgentTeamScheduleRequest{
|
|
TeamID: 1,
|
|
StartAt: formatTestDateTime(tomorrow, "22:00:00"),
|
|
EndAt: formatTestDateTime(tomorrow.AddDate(0, 0, 1), "08:00:00"),
|
|
SourceType: "manual",
|
|
}, testOperator())
|
|
if err == nil {
|
|
t.Fatalf("expected cross-day schedule to fail")
|
|
}
|
|
if !strings.Contains(err.Error(), "不能跨天") {
|
|
t.Fatalf("expected cross-day error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAgentTeamScheduleServiceCreateRejectsHistoricalScheduleByDay(t *testing.T) {
|
|
setupAgentTeamScheduleTestDB(t)
|
|
createAgentTeamScheduleTestTeams(t, sqls.DB())
|
|
|
|
yesterday := time.Now().AddDate(0, 0, -1)
|
|
_, err := services.AgentTeamScheduleService.CreateAgentTeamSchedule(request.CreateAgentTeamScheduleRequest{
|
|
TeamID: 1,
|
|
StartAt: formatTestDateTime(yesterday, "09:00:00"),
|
|
EndAt: formatTestDateTime(yesterday, "18:00:00"),
|
|
SourceType: "manual",
|
|
}, testOperator())
|
|
if err == nil {
|
|
t.Fatalf("expected historical schedule to fail")
|
|
}
|
|
if !strings.Contains(err.Error(), "历史日期") {
|
|
t.Fatalf("expected historical date error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAgentTeamScheduleServiceCreateAllowsTodayEarlierThanCurrentTime(t *testing.T) {
|
|
setupAgentTeamScheduleTestDB(t)
|
|
createAgentTeamScheduleTestTeams(t, sqls.DB())
|
|
|
|
today := time.Now()
|
|
item, err := services.AgentTeamScheduleService.CreateAgentTeamSchedule(request.CreateAgentTeamScheduleRequest{
|
|
TeamID: 1,
|
|
StartAt: formatTestDateTime(today, "00:00:00"),
|
|
EndAt: formatTestDateTime(today, "01:00:00"),
|
|
SourceType: "manual",
|
|
}, testOperator())
|
|
if err != nil {
|
|
t.Fatalf("expected today's schedule to pass, got %v", err)
|
|
}
|
|
if item == nil || item.ID == 0 {
|
|
t.Fatalf("expected created schedule, got %+v", item)
|
|
}
|
|
}
|
|
|
|
func TestAgentTeamScheduleServiceUpdateRejectsCrossDaySchedule(t *testing.T) {
|
|
db := setupAgentTeamScheduleTestDB(t)
|
|
createAgentTeamScheduleTestTeams(t, db)
|
|
existingID := createFutureAgentTeamSchedule(t, db)
|
|
tomorrow := time.Now().AddDate(0, 0, 1)
|
|
|
|
err := services.AgentTeamScheduleService.UpdateAgentTeamSchedule(request.UpdateAgentTeamScheduleRequest{
|
|
ID: existingID,
|
|
CreateAgentTeamScheduleRequest: request.CreateAgentTeamScheduleRequest{
|
|
TeamID: 1,
|
|
StartAt: formatTestDateTime(tomorrow, "22:00:00"),
|
|
EndAt: formatTestDateTime(tomorrow.AddDate(0, 0, 1), "08:00:00"),
|
|
SourceType: "manual",
|
|
},
|
|
}, testOperator())
|
|
if err == nil {
|
|
t.Fatalf("expected cross-day update to fail")
|
|
}
|
|
if !strings.Contains(err.Error(), "不能跨天") {
|
|
t.Fatalf("expected cross-day error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAgentTeamScheduleServiceUpdateRejectsHistoricalScheduleByDay(t *testing.T) {
|
|
db := setupAgentTeamScheduleTestDB(t)
|
|
createAgentTeamScheduleTestTeams(t, db)
|
|
existingID := createFutureAgentTeamSchedule(t, db)
|
|
yesterday := time.Now().AddDate(0, 0, -1)
|
|
|
|
err := services.AgentTeamScheduleService.UpdateAgentTeamSchedule(request.UpdateAgentTeamScheduleRequest{
|
|
ID: existingID,
|
|
CreateAgentTeamScheduleRequest: request.CreateAgentTeamScheduleRequest{
|
|
TeamID: 1,
|
|
StartAt: formatTestDateTime(yesterday, "09:00:00"),
|
|
EndAt: formatTestDateTime(yesterday, "18:00:00"),
|
|
SourceType: "manual",
|
|
},
|
|
}, testOperator())
|
|
if err == nil {
|
|
t.Fatalf("expected historical update to fail")
|
|
}
|
|
if !strings.Contains(err.Error(), "历史日期") {
|
|
t.Fatalf("expected historical date error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func setupAgentTeamScheduleTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
|
|
dbName := strings.NewReplacer("/", "_", " ", "_").Replace(t.Name())
|
|
db, err := gorm.Open(sqlite.Open("file:"+dbName+"?mode=memory&cache=shared"), &gorm.Config{
|
|
NamingStrategy: schema.NamingStrategy{
|
|
TablePrefix: "t_",
|
|
SingularTable: true,
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite error = %v", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
sqlDB, err := db.DB()
|
|
if err == nil {
|
|
_ = sqlDB.Close()
|
|
}
|
|
})
|
|
if err := db.AutoMigrate(&models.AgentTeam{}, &models.AgentTeamSchedule{}); err != nil {
|
|
t.Fatalf("auto migrate error = %v", err)
|
|
}
|
|
sqls.SetDB(db)
|
|
return db
|
|
}
|
|
|
|
func createAgentTeamScheduleTestData(t *testing.T, db *gorm.DB) {
|
|
t.Helper()
|
|
|
|
createAgentTeamScheduleTestTeams(t, db)
|
|
|
|
parse := func(value string) time.Time {
|
|
t.Helper()
|
|
ret, err := time.ParseInLocation(time.DateTime, value, time.Local)
|
|
if err != nil {
|
|
t.Fatalf("parse time %q error = %v", value, err)
|
|
}
|
|
return ret
|
|
}
|
|
schedules := []models.AgentTeamSchedule{
|
|
{ID: 1, TeamID: 1, StartAt: parse("2026-04-26 20:00:00"), EndAt: parse("2026-04-27 10:00:00"), SourceType: "manual", Status: enums.StatusOk},
|
|
{ID: 2, TeamID: 1, StartAt: parse("2026-04-28 09:00:00"), EndAt: parse("2026-04-28 18:00:00"), SourceType: "manual", Status: enums.StatusOk},
|
|
{ID: 3, TeamID: 2, StartAt: parse("2026-05-03 20:00:00"), EndAt: parse("2026-05-04 08:00:00"), SourceType: "manual", Status: enums.StatusOk},
|
|
{ID: 4, TeamID: 1, StartAt: parse("2026-04-20 09:00:00"), EndAt: parse("2026-04-20 18:00:00"), SourceType: "manual", Status: enums.StatusOk},
|
|
{ID: 5, TeamID: 2, StartAt: parse("2026-05-04 09:00:00"), EndAt: parse("2026-05-04 18:00:00"), SourceType: "manual", Status: enums.StatusOk},
|
|
}
|
|
if err := db.Create(&schedules).Error; err != nil {
|
|
t.Fatalf("create schedules error = %v", err)
|
|
}
|
|
}
|
|
|
|
func createAgentTeamScheduleTestTeams(t *testing.T, db *gorm.DB) {
|
|
t.Helper()
|
|
teams := []models.AgentTeam{
|
|
{ID: 1, Name: "售前组", Status: enums.StatusOk},
|
|
{ID: 2, Name: "售后组", Status: enums.StatusOk},
|
|
}
|
|
if err := db.Create(&teams).Error; err != nil {
|
|
t.Fatalf("create teams error = %v", err)
|
|
}
|
|
}
|
|
|
|
func formatTestDateTime(date time.Time, clock string) string {
|
|
return date.Format(time.DateOnly) + " " + clock
|
|
}
|
|
|
|
func createFutureAgentTeamSchedule(t *testing.T, db *gorm.DB) int64 {
|
|
t.Helper()
|
|
tomorrow := time.Now().AddDate(0, 0, 1)
|
|
item := models.AgentTeamSchedule{
|
|
TeamID: 1,
|
|
StartAt: parseTestDateTime(t, formatTestDateTime(tomorrow, "09:00:00")),
|
|
EndAt: parseTestDateTime(t, formatTestDateTime(tomorrow, "18:00:00")),
|
|
SourceType: "manual",
|
|
Status: enums.StatusOk,
|
|
}
|
|
if err := db.Create(&item).Error; err != nil {
|
|
t.Fatalf("create future schedule error = %v", err)
|
|
}
|
|
return item.ID
|
|
}
|
|
|
|
func parseTestDateTime(t *testing.T, value string) time.Time {
|
|
t.Helper()
|
|
ret, err := time.ParseInLocation(time.DateTime, value, time.Local)
|
|
if err != nil {
|
|
t.Fatalf("parse time %q error = %v", value, err)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func testOperator() *dto.AuthPrincipal {
|
|
return &dto.AuthPrincipal{UserID: 1, Username: "tester", Status: enums.StatusOk}
|
|
}
|