diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java index 1232259..479ffd7 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java @@ -2,6 +2,7 @@ import static gdsc.konkuk.platformcore.application.attendance.AttendanceServiceHelper.findAttendanceById; +import gdsc.konkuk.platformcore.application.attendance.dtos.AttendanceStatus; import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceAlreadyExistException; import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceErrorCode; import gdsc.konkuk.platformcore.application.event.exceptions.EventErrorCode; @@ -56,6 +57,12 @@ public Attendance registerAttendance(AttendanceRegisterRequest registerRequest) return newAttendance; } + public AttendanceStatus getAttendanceStatus(Long attendanceId) { + List totalParticipants = participantRepository.findAllByAttendanceId(attendanceId); + List attendedParticipants = totalParticipants.stream().filter(Participant::isAttended).toList(); + return AttendanceStatus.of(attendanceId, totalParticipants.size(), attendedParticipants.size()); + } + @Transactional public void deleteAttendance(Long attendanceId) { participantRepository.deleteAllByAttendanceId(attendanceId); diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/dtos/AttendanceStatus.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/dtos/AttendanceStatus.java new file mode 100644 index 0000000..52125fb --- /dev/null +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/dtos/AttendanceStatus.java @@ -0,0 +1,22 @@ +package gdsc.konkuk.platformcore.application.attendance.dtos; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class AttendanceStatus { + private Long attendanceId; + private int total; + private int attended; + + public static AttendanceStatus of(Long attendanceId, int total, int attended) { + return AttendanceStatus.builder() + .attendanceId(attendanceId) + .total(total) + .attended(attended) + .build(); + } +} diff --git a/src/main/java/gdsc/konkuk/platformcore/controller/attendance/AttendanceController.java b/src/main/java/gdsc/konkuk/platformcore/controller/attendance/AttendanceController.java index 2625deb..f558a95 100644 --- a/src/main/java/gdsc/konkuk/platformcore/controller/attendance/AttendanceController.java +++ b/src/main/java/gdsc/konkuk/platformcore/controller/attendance/AttendanceController.java @@ -10,6 +10,7 @@ import gdsc.konkuk.platformcore.controller.attendance.dtos.AttendSuccessResponse; import gdsc.konkuk.platformcore.controller.attendance.dtos.AttendanceRegisterRequest; import gdsc.konkuk.platformcore.controller.attendance.dtos.AttendanceResponse; +import gdsc.konkuk.platformcore.application.attendance.dtos.AttendanceStatus; import gdsc.konkuk.platformcore.domain.attendance.entity.Attendance; import gdsc.konkuk.platformcore.domain.attendance.entity.Participant; import gdsc.konkuk.platformcore.global.responses.SuccessResponse; @@ -66,6 +67,13 @@ public ResponseEntity registerAttendance( .body(SuccessResponse.of(response)); } + // TODO: 추후 WebSocket으로 변경 필요 + @GetMapping("/{attendanceId}/status") + public ResponseEntity getAttendance(@PathVariable Long attendanceId) { + AttendanceStatus attendanceStatus = attendanceService.getAttendanceStatus(attendanceId); + return ResponseEntity.ok(SuccessResponse.of(attendanceStatus)); + } + @DeleteMapping("/{attendanceId}") public ResponseEntity deleteAttendance(@PathVariable Long attendanceId) { attendanceService.deleteAttendance(attendanceId); diff --git a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/ParticipantRepository.java b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/ParticipantRepository.java index bb24cf7..e89d68f 100644 --- a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/ParticipantRepository.java +++ b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/ParticipantRepository.java @@ -25,4 +25,6 @@ public interface ParticipantRepository extends JpaRepository """) List findAllByBatchAndStartAtBetween( String batch, LocalDateTime st, LocalDateTime en); + + List findAllByAttendanceId(Long attendanceId); } diff --git a/src/test/java/gdsc/konkuk/platformcore/controller/attendance/AttendanceControllerTest.java b/src/test/java/gdsc/konkuk/platformcore/controller/attendance/AttendanceControllerTest.java index 5b456c9..ba5367b 100644 --- a/src/test/java/gdsc/konkuk/platformcore/controller/attendance/AttendanceControllerTest.java +++ b/src/test/java/gdsc/konkuk/platformcore/controller/attendance/AttendanceControllerTest.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import gdsc.konkuk.platformcore.application.attendance.AttendanceService; +import gdsc.konkuk.platformcore.application.attendance.dtos.AttendanceStatus; import gdsc.konkuk.platformcore.application.event.EventService; import gdsc.konkuk.platformcore.application.event.dtos.EventWithAttendance; import gdsc.konkuk.platformcore.controller.attendance.dtos.AttendanceRegisterRequest; @@ -203,6 +204,43 @@ void should_register_attendance_when_pass_event_id() throws Exception { .build()))); } + @Test + @DisplayName("출석 현황을 조회할 수 있다") + @WithMockUser + void should_get_attendance_status_when_pass_attendance_id() throws Exception { + // given + given(attendanceService.getAttendanceStatus(any(Long.class))) + .willReturn(AttendanceStatus.of(1L, 10, 6)); + + // when + ResultActions result = + mockMvc.perform( + RestDocumentationRequestBuilders.get("/api/v1/attendances/{attendanceId}/status", 1) + .with(csrf())); + + // then + result + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document( + "getAttendanceStatus", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + resource( + ResourceSnippetParameters.builder() + .description("출석 현황을 조회할 수 있다") + .tag("attendance") + .pathParameters(parameterWithName("attendanceId").description("출석 ID")) + .responseFields( + fieldWithPath("success").description("성공 여부"), + fieldWithPath("message").description("메시지"), + fieldWithPath("data.attendanceId").description("출석 ID"), + fieldWithPath("data.total").description("전체 인원"), + fieldWithPath("data.attended").description("출석 인원")) + .build()))); + } + @Test @DisplayName("이벤트 출석을 삭제할 수 있다") @WithMockUser