From 4e1e91ff05532d41e28c7d328480798ee5147c46 Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Wed, 21 Aug 2024 18:51:36 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20Attendance=20Status=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendance/AttendanceService.java | 7 ++++++ .../attendance/dtos/AttendanceStatus.java | 22 +++++++++++++++++++ .../attendance/AttendanceController.java | 8 +++++++ .../repository/ParticipantRepository.java | 2 ++ 4 files changed, 39 insertions(+) create mode 100644 src/main/java/gdsc/konkuk/platformcore/application/attendance/dtos/AttendanceStatus.java 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); } From 7119b42ca82c6016d221fee913fde14f8d09fc35 Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Wed, 21 Aug 2024 19:03:33 +0900 Subject: [PATCH 2/2] =?UTF-8?q?test:=20Attendance=20Status=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20Test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendance/AttendanceControllerTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) 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