From 6a8c889ffdf5a640c937b522774ad9a1e35c86f0 Mon Sep 17 00:00:00 2001 From: Adam Mahood Date: Fri, 10 Feb 2023 20:33:28 -0500 Subject: [PATCH] ticket/200: sign out unsigned out members in last place --- internal/services/events_service.go | 29 +++++----- internal/services/events_service_test.go | 67 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 14 deletions(-) diff --git a/internal/services/events_service.go b/internal/services/events_service.go index d23fa88..20f1279 100644 --- a/internal/services/events_service.go +++ b/internal/services/events_service.go @@ -107,26 +107,19 @@ func (es *eventService) EndEvent(eventId uint64) error { return e.Forbidden("This event has already ended, it cannot be ended again.") } - // Retrieve list of entries for the event - // Reject request with 403 if all entries are not signed out - entries := []models.Participant{} - res = es.db.Where("event_id = ?", eventId).Order("signed_out_at DESC").Find(&entries) - if err := res.Error; err != nil { - return e.InternalServerError(err.Error()) - } - - for _, entry := range entries { - if entry.SignedOutAt == nil { - return e.Forbidden("Event cannot be ended while there are still unsigned out entries.") - } - } - // Start transaction for the event update and ranking update process tx := es.db.Begin() if err := tx.Error; err != nil { return e.InternalServerError(err.Error()) } + // Update all entries who are not signed out to sign them out in last place + res = tx.Model(&models.Participant{}).Where("event_id = ? AND signed_out_at IS NULL", event.ID).Update("signed_out_at", event.StartDate) + if err := res.Error; err != nil { + tx.Rollback() + return e.InternalServerError(err.Error()) + } + // Update events state event.State = models.EventStateEnded tx.Save(&event) @@ -135,6 +128,14 @@ func (es *eventService) EndEvent(eventId uint64) error { return e.InternalServerError(err.Error()) } + // Retrieve list of entries for the event + entries := []models.Participant{} + res = tx.Where("event_id = ?", eventId).Order("signed_out_at DESC").Find(&entries) + if err := res.Error; err != nil { + tx.Rollback() + return e.InternalServerError(err.Error()) + } + // Calculate points for each entry in the event and update placements rankingService := NewRankingService(tx) eventSize := len(entries) diff --git a/internal/services/events_service_test.go b/internal/services/events_service_test.go index 752e67f..afba434 100644 --- a/internal/services/events_service_test.go +++ b/internal/services/events_service_test.go @@ -313,6 +313,73 @@ func EndEventTest() func(*testing.T) { } } +func TestEventService_EndEvent_UnsignedOutEntries(t *testing.T) { + t.Setenv("ENVIRONMENT", "TEST") + + db, err := database.OpenTestConnection() + if err != nil { + t.Fatal(err.Error()) + } + defer database.WipeDB(db) + + set, err := testhelpers.SetupSemester(db, "Fall 2022") + if err != nil { + t.Fatalf("Failed to setup test environment: %v", err) + } + + event, err := testhelpers.CreateEvent(db, "Event 1", set.Semester.ID, time.Now().UTC()) + if err != nil { + t.Fatalf("Failed to setup event: %v", err) + } + + now := time.Now().UTC() + _, err = testhelpers.CreateParticipant(db, set.Memberships[0].ID, event.ID, 0, &now, 2) + if err != nil { + t.Fatalf("Failed to add entry: %v", err) + } + + next := now.Add(time.Minute * 30) + _, err = testhelpers.CreateParticipant(db, set.Memberships[1].ID, event.ID, 0, &next, 0) + if err != nil { + t.Fatalf("Failed to add entry: %v", err) + } + + entry3, err := testhelpers.CreateParticipant(db, set.Memberships[2].ID, event.ID, 0, nil, 4) + if err != nil { + t.Fatalf("Failed to add entry: %v", err) + } + + svc := NewEventService(db) + err = svc.EndEvent(event.ID) + if err != nil { + t.Errorf("EndEvent() error = %v", err) + return + } + + // Check that entry3's signed_out_at field is set to the start time of the event + foundEntry := models.Participant{ID: entry3.ID} + res := db.First(&foundEntry) + if res.Error != nil { + t.Fatal(res.Error.Error()) + } + + // Check that the date is the same + sYear, sMonth, sDay := foundEntry.SignedOutAt.Date() + eYear, eMonth, eDay := event.StartDate.Date() + if sYear != eYear || sMonth != eMonth || sDay != eDay { + t.Errorf("SignedOutAt not equal to StartDate of event (user not signed out in last place): SignedOutAt: %v, StartDate: %v", foundEntry.SignedOutAt, event.StartDate) + return + } + + // Check that hour, min, and second are equal (milliseconds don't matter) + sHour, sMin, sSec := foundEntry.SignedOutAt.Clock() + eHour, eMin, eSec := event.StartDate.Clock() + if sHour != eHour || sMin != eMin || sSec != eSec { + t.Errorf("SignedOutAt not equal to StartDate of event (user not signed out in last place): SignedOutAt: %v, StartDate: %v", foundEntry.SignedOutAt, event.StartDate) + return + } +} + func TestEventService_EndEvent_PlacementAndRankingsUpdated(t *testing.T) { t.Setenv("ENVIRONMENT", "TEST")