From a468ada0e141e2fbc769c1584df13ad18019111e Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 13:48:25 +0900 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20=ED=95=99=EA=B3=BC=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/entity/Member.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/gdsc/konkuk/platformcore/domain/member/entity/Member.java b/src/main/java/gdsc/konkuk/platformcore/domain/member/entity/Member.java index 669ed27..c3ecaf1 100644 --- a/src/main/java/gdsc/konkuk/platformcore/domain/member/entity/Member.java +++ b/src/main/java/gdsc/konkuk/platformcore/domain/member/entity/Member.java @@ -46,6 +46,9 @@ public class Member { @Column(name = "profile_image_url") private String profileImageUrl; + @Column(name = "department") + private String department; + @Column(name = "is_activated") private boolean isActivated = true; @@ -80,19 +83,21 @@ public Boolean isMemberActivated() { @Builder public Member( - Long id, - String memberId, - String password, - String name, - String email, - String profileImageUrl, - String batch) { + Long id, + String memberId, + String password, + String name, + String email, + String profileImageUrl, + String department, + String batch) { this.id = id; this.memberId = validateNotNull(memberId, "memberId"); this.password = validateNotNull(password, "password"); this.name = validateNotNull(name, "name"); this.email = validateNotNull(email, "email"); this.profileImageUrl = profileImageUrl; + this.department = department; this.batch = batch; } } From 6b94f297aa8fb74ea09780d5566d63865f0f8ed8 Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 13:50:05 +0900 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20`AttendanceInfo`=20DTO,=20query?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendance/AttendanceInfo.java | 19 +++++++++++++++++++ .../repository/AttendanceRepository.java | 16 +++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceInfo.java diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceInfo.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceInfo.java new file mode 100644 index 0000000..06f7ae8 --- /dev/null +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceInfo.java @@ -0,0 +1,19 @@ +package gdsc.konkuk.platformcore.application.attendance; + +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +@AllArgsConstructor +public class AttendanceInfo { + private Long attendanceId; + private Long eventId; + private Long memberId; + private LocalDateTime attendanceDate; + private boolean attendance; +} diff --git a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java index a4f58ac..3550b4d 100644 --- a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java +++ b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java @@ -1,8 +1,22 @@ package gdsc.konkuk.platformcore.domain.attendance.repository; +import gdsc.konkuk.platformcore.application.attendance.AttendanceInfo; import gdsc.konkuk.platformcore.domain.attendance.entity.Attendance; - +import java.time.LocalDateTime; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; public interface AttendanceRepository extends JpaRepository { + @Query( + """ + SELECT new gdsc.konkuk.platformcore.application.attendance.AttendanceInfo( + a.id, a.eventId, p.memberId, e.startAt, p.attendance + ) + FROM Attendance a + LEFT JOIN Event e ON a.eventId = e.id + LEFT JOIN Participant p ON a.id = p.attendanceId + WHERE e.startAt BETWEEN :st AND :en + """) + List findAllAttendanceInfoByStartAtBetween(LocalDateTime st, LocalDateTime en); } From b77f638cb8ae3bbe2cc2f39533298bf1d089925a Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 14:41:43 +0900 Subject: [PATCH 03/15] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=EC=A1=B0=ED=9A=8C=20Controller=20&=20Test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/MemberAttendanceInfo.java | 52 ++++++ .../controller/member/MemberController.java | 24 ++- .../member/MemberControllerTest.java | 153 ++++++++++++++++++ 3 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java diff --git a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java new file mode 100644 index 0000000..bd43543 --- /dev/null +++ b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java @@ -0,0 +1,52 @@ +package gdsc.konkuk.platformcore.application.member; + +import gdsc.konkuk.platformcore.application.attendance.AttendanceInfo; +import gdsc.konkuk.platformcore.domain.member.entity.Member; +import gdsc.konkuk.platformcore.domain.member.entity.MemberRole; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +@AllArgsConstructor +public class MemberAttendanceInfo { + @NotNull private Long memberId; + @NotEmpty private String memberName; + @NotNull private MemberRole memberRole; + private String profileImageUrl; + @NotEmpty private String department; + @NotNull List attendanceInfoList; + + public static List from( + List batchMemberList, List attendanceInfoList) { + Map memberAttendanceInfoMap = new HashMap<>(); + for (Member member : batchMemberList) { + memberAttendanceInfoMap.put( + member.getId(), + MemberAttendanceInfo.builder() + .memberId(member.getId()) + .memberName(member.getName()) + .memberRole(member.getRole()) + .profileImageUrl(member.getProfileImageUrl()) + .department(member.getDepartment()) + .attendanceInfoList(List.of()) + .build()); + } + for (AttendanceInfo attendanceInfo : attendanceInfoList) { + MemberAttendanceInfo memberAttendanceInfo = + memberAttendanceInfoMap.get(attendanceInfo.getMemberId()); + memberAttendanceInfo.getAttendanceInfoList().add(attendanceInfo); + } + return memberAttendanceInfoMap.values().stream().toList(); + } +} diff --git a/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java b/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java index 748d8e2..bb1cd9e 100644 --- a/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java +++ b/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java @@ -1,12 +1,18 @@ package gdsc.konkuk.platformcore.controller.member; import java.net.URI; +import java.time.LocalDate; +import java.util.List; +import gdsc.konkuk.platformcore.application.member.MemberAttendanceInfo; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; @@ -26,10 +32,10 @@ public class MemberController { @PostMapping() public ResponseEntity signup( - @RequestBody @Valid MemberRegisterRequest registerRequest) { + @RequestBody @Valid MemberRegisterRequest registerRequest) { Member registeredMember = memberService.register(registerRequest); return ResponseEntity.created(getCreatedURI(registeredMember.getId())) - .body(SuccessResponse.messageOnly()); + .body(SuccessResponse.messageOnly()); } @DeleteMapping() @@ -39,10 +45,18 @@ public ResponseEntity withdraw() { return ResponseEntity.noContent().build(); } + @GetMapping("/{batch}/attendances") + public ResponseEntity getAttendances( + @PathVariable String batch, @RequestParam Integer year, @RequestParam Integer month) { + List memberAttendanceInfoList = + memberService.getMemberAttendanceInfo(batch, LocalDate.of(year, month, 1)); + return ResponseEntity.ok(SuccessResponse.of(memberAttendanceInfoList)); + } + private URI getCreatedURI(Long memberId) { return ServletUriComponentsBuilder.fromCurrentRequest() - .path("/{id}") - .buildAndExpand(memberId) - .toUri(); + .path("/{id}") + .buildAndExpand(memberId) + .toUri(); } } diff --git a/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java b/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java index 61c898d..efc3201 100644 --- a/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java +++ b/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java @@ -11,6 +11,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import gdsc.konkuk.platformcore.application.attendance.AttendanceInfo; +import gdsc.konkuk.platformcore.application.member.MemberAttendanceInfo; +import gdsc.konkuk.platformcore.domain.member.entity.MemberRole; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -35,6 +38,9 @@ import gdsc.konkuk.platformcore.application.member.exceptions.UserAlreadyExistException; import gdsc.konkuk.platformcore.domain.member.entity.Member; +import java.time.LocalDateTime; +import java.util.List; + @SpringBootTest @ExtendWith({RestDocumentationExtension.class}) class MemberControllerTest { @@ -165,4 +171,151 @@ void should_success_when_delete_member() throws Exception { .tag("member") .build()))); } + + @Test + @DisplayName("특정 배치의 특정 월의 멤버 출석 정보 조회 성공") + @CustomMockUser + void should_success_when_get_attendances_by_batch() throws Exception { + // given + // TODO: fixture로 변경 + given(memberService.getMemberAttendanceInfo(anyString(), any())) + .willReturn( + List.of( + MemberAttendanceInfo.builder() + .memberId(0L) + .memberName("홍길동") + .department("컴퓨터공학과") + .memberRole(MemberRole.MEMBER) + .attendanceInfoList( + List.of( + AttendanceInfo.builder() + .attendanceId(1L) + .memberId(0L) + .eventId(1L) + .attendanceDate(LocalDateTime.of(2024, 7, 3, 0, 0)) + .attendance(true) + .build(), + AttendanceInfo.builder() + .attendanceId(2L) + .memberId(0L) + .eventId(2L) + .attendanceDate(LocalDateTime.of(2024, 7, 5, 0, 0)) + .attendance(false) + .build(), + AttendanceInfo.builder() + .attendanceId(3L) + .memberId(0L) + .eventId(3L) + .attendanceDate(LocalDateTime.of(2024, 7, 8, 0, 0)) + .attendance(true) + .build())) + .build(), + MemberAttendanceInfo.builder() + .memberId(1L) + .memberName("전우치") + .department("기술경영학과") + .memberRole(MemberRole.MEMBER) + .attendanceInfoList( + List.of( + AttendanceInfo.builder() + .attendanceId(1L) + .memberId(1L) + .eventId(1L) + .attendanceDate(LocalDateTime.of(2024, 7, 3, 0, 0)) + .attendance(true) + .build(), + AttendanceInfo.builder() + .attendanceId(2L) + .memberId(1L) + .eventId(2L) + .attendanceDate(LocalDateTime.of(2024, 7, 5, 0, 0)) + .attendance(false) + .build(), + AttendanceInfo.builder() + .attendanceId(3L) + .memberId(1L) + .eventId(3L) + .attendanceDate(LocalDateTime.of(2024, 7, 8, 0, 0)) + .attendance(false) + .build())) + .build(), + MemberAttendanceInfo.builder() + .memberId(2L) + .memberName("이순신") + .department("컴퓨터공학과") + .memberRole(MemberRole.MEMBER) + .attendanceInfoList( + List.of( + AttendanceInfo.builder() + .attendanceId(1L) + .memberId(2L) + .eventId(1L) + .attendanceDate(LocalDateTime.of(2024, 7, 3, 0, 0)) + .attendance(true) + .build(), + AttendanceInfo.builder() + .attendanceId(2L) + .memberId(2L) + .eventId(2L) + .attendanceDate(LocalDateTime.of(2024, 7, 5, 0, 0)) + .attendance(false) + .build(), + AttendanceInfo.builder() + .attendanceId(3L) + .memberId(2L) + .eventId(3L) + .attendanceDate(LocalDateTime.of(2024, 7, 8, 0, 0)) + .attendance(true) + .build())) + .build())); + + // when + ResultActions result = + mockMvc.perform( + RestDocumentationRequestBuilders.get("/api/v1/members/{batch}/attendances", "24-25") + .param("year", "2024") + .param("month", "7") + .contentType(APPLICATION_JSON) + .with(csrf())); + + // then + result + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document( + "member/attendances", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + resource( + ResourceSnippetParameters.builder() + .description("특정 달의 멤버 출석 정보 조회") + .tag("member") + .pathParameters(parameterWithName("batch").description("조회할 멤버 기수")) + .queryParameters( + parameterWithName("year").description("조회할 년도"), + parameterWithName("month").description("조회할 월"), + parameterWithName("_csrf").ignored()) + .responseFields( + fieldWithPath("success").description(true), + fieldWithPath("message").description("멤버 출석 정보 조회 성공"), + fieldWithPath("data").description("멤버 출석 정보 리스트"), + fieldWithPath("data[].memberId").description("멤버 아이디"), + fieldWithPath("data[].memberName").description("멤버 이름"), + fieldWithPath("data[].memberRole").description("멤버 역할"), + fieldWithPath("data[].profileImageUrl").description("멤버 프로필 이미지"), + fieldWithPath("data[].department").description("멤버 학과"), + fieldWithPath("data[].attendanceInfoList").description("멤버 출석 정보 리스트"), + fieldWithPath("data[].attendanceInfoList[].attendanceId") + .description("출석 아이디"), + fieldWithPath("data[].attendanceInfoList[].memberId") + .description("멤버 아이디"), + fieldWithPath("data[].attendanceInfoList[].eventId") + .description("이벤트 아이디"), + fieldWithPath("data[].attendanceInfoList[].attendanceDate") + .description("출석 날짜"), + fieldWithPath("data[].attendanceInfoList[].attendance") + .description("출석 여부")) + .build()))); + } } From 931b8aa6a0754815f9c43dac132f41aafa6a218e Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 14:44:00 +0900 Subject: [PATCH 04/15] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=EC=A1=B0=ED=9A=8C=20Service?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/member/MemberService.java | 21 +++++++++++++++++-- .../application/member/MemberServiceTest.java | 6 +++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java index 7552e80..6eb3a82 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java @@ -1,7 +1,12 @@ package gdsc.konkuk.platformcore.application.member; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.List; import java.util.Optional; +import gdsc.konkuk.platformcore.application.attendance.AttendanceInfo; +import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,6 +26,7 @@ public class MemberService { private final PasswordEncoder passwordEncoder; private final MemberRepository memberRepository; + private final AttendanceRepository attendanceRepository; @Transactional public Member register(MemberRegisterRequest registerRequest) { @@ -37,11 +43,22 @@ public Member register(MemberRegisterRequest registerRequest) { @Transactional public void withdraw(Long currentId) { - Member member = memberRepository.findById(currentId) - .orElseThrow(() -> UserNotFoundException.of(MemberErrorCode.USER_NOT_FOUND)); + Member member = + memberRepository + .findById(currentId) + .orElseThrow(() -> UserNotFoundException.of(MemberErrorCode.USER_NOT_FOUND)); member.withdraw(); } + public List getMemberAttendanceInfo(String batch, LocalDate month) { + List batchMemberList = memberRepository.findAllByBatch(batch); + List attendanceInfoList = + attendanceRepository.findAllAttendanceInfoByStartAtBetween( + month.withDayOfMonth(1).atStartOfDay(), + month.withDayOfMonth(month.lengthOfMonth()).atTime(LocalTime.MAX)); + return MemberAttendanceInfo.from(batchMemberList, attendanceInfoList); + } + private boolean checkMemberExistWithMemberId(String memberId) { Optional member = memberRepository.findByMemberId(memberId); return member.isPresent(); diff --git a/src/test/java/gdsc/konkuk/platformcore/application/member/MemberServiceTest.java b/src/test/java/gdsc/konkuk/platformcore/application/member/MemberServiceTest.java index 5de187f..372c7e1 100644 --- a/src/test/java/gdsc/konkuk/platformcore/application/member/MemberServiceTest.java +++ b/src/test/java/gdsc/konkuk/platformcore/application/member/MemberServiceTest.java @@ -5,6 +5,7 @@ import java.util.Optional; +import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -30,13 +31,16 @@ class MemberServiceTest { @Mock private MemberRepository memberRepository; + @Mock + private AttendanceRepository attendanceRepository; + @Mock private PasswordEncoder passwordEncoder; @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); - subject = new MemberService(passwordEncoder, memberRepository); + subject = new MemberService(passwordEncoder, memberRepository, attendanceRepository); } @Test From ea6c8cac26a79e1cd8852ae01f50141fdd38b5ab Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 14:55:56 +0900 Subject: [PATCH 05/15] =?UTF-8?q?feat:=20`AttendanceInfo`=EC=97=90=20parti?= =?UTF-8?q?cipantId=20field=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/attendance/AttendanceInfo.java | 1 + .../attendance/repository/AttendanceRepository.java | 2 +- .../controller/member/MemberControllerTest.java | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceInfo.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceInfo.java index 06f7ae8..e66f66e 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceInfo.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceInfo.java @@ -14,6 +14,7 @@ public class AttendanceInfo { private Long attendanceId; private Long eventId; private Long memberId; + private Long participantId; private LocalDateTime attendanceDate; private boolean attendance; } diff --git a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java index 3550b4d..94f8805 100644 --- a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java +++ b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java @@ -11,7 +11,7 @@ public interface AttendanceRepository extends JpaRepository { @Query( """ SELECT new gdsc.konkuk.platformcore.application.attendance.AttendanceInfo( - a.id, a.eventId, p.memberId, e.startAt, p.attendance + a.id, a.eventId, p.memberId, p.id, e.startAt, p.attendance ) FROM Attendance a LEFT JOIN Event e ON a.eventId = e.id diff --git a/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java b/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java index efc3201..66c351b 100644 --- a/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java +++ b/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java @@ -192,6 +192,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(1L) .memberId(0L) .eventId(1L) + .participantId(1L) .attendanceDate(LocalDateTime.of(2024, 7, 3, 0, 0)) .attendance(true) .build(), @@ -199,6 +200,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(2L) .memberId(0L) .eventId(2L) + .participantId(2L) .attendanceDate(LocalDateTime.of(2024, 7, 5, 0, 0)) .attendance(false) .build(), @@ -206,6 +208,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(3L) .memberId(0L) .eventId(3L) + .participantId(3L) .attendanceDate(LocalDateTime.of(2024, 7, 8, 0, 0)) .attendance(true) .build())) @@ -221,6 +224,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(1L) .memberId(1L) .eventId(1L) + .participantId(4L) .attendanceDate(LocalDateTime.of(2024, 7, 3, 0, 0)) .attendance(true) .build(), @@ -228,6 +232,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(2L) .memberId(1L) .eventId(2L) + .participantId(5L) .attendanceDate(LocalDateTime.of(2024, 7, 5, 0, 0)) .attendance(false) .build(), @@ -235,6 +240,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(3L) .memberId(1L) .eventId(3L) + .participantId(6L) .attendanceDate(LocalDateTime.of(2024, 7, 8, 0, 0)) .attendance(false) .build())) @@ -250,6 +256,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(1L) .memberId(2L) .eventId(1L) + .participantId(7L) .attendanceDate(LocalDateTime.of(2024, 7, 3, 0, 0)) .attendance(true) .build(), @@ -257,6 +264,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(2L) .memberId(2L) .eventId(2L) + .participantId(8L) .attendanceDate(LocalDateTime.of(2024, 7, 5, 0, 0)) .attendance(false) .build(), @@ -264,6 +272,7 @@ void should_success_when_get_attendances_by_batch() throws Exception { .attendanceId(3L) .memberId(2L) .eventId(3L) + .participantId(9L) .attendanceDate(LocalDateTime.of(2024, 7, 8, 0, 0)) .attendance(true) .build())) @@ -312,6 +321,8 @@ void should_success_when_get_attendances_by_batch() throws Exception { .description("멤버 아이디"), fieldWithPath("data[].attendanceInfoList[].eventId") .description("이벤트 아이디"), + fieldWithPath("data[].attendanceInfoList[].participantId") + .description("참가자 아이디"), fieldWithPath("data[].attendanceInfoList[].attendanceDate") .description("출석 날짜"), fieldWithPath("data[].attendanceInfoList[].attendance") From f380623b462681e5bc3be9be691a9138e91ff62a Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 15:29:27 +0900 Subject: [PATCH 06/15] =?UTF-8?q?fix:=20=EC=B6=9C=EC=84=9D=20=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=EC=A1=B0=ED=9A=8C=EC=97=90=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EC=99=B8=EC=9D=98=20=EC=9D=B8=EC=9B=90=EC=9D=B4=20=EC=B6=9C?= =?UTF-8?q?=EC=84=9D=ED=95=9C=20=EA=B2=BD=EC=9A=B0=20error=EA=B0=80=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platformcore/application/member/MemberAttendanceInfo.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java index bd43543..e43d027 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java @@ -43,6 +43,7 @@ public static List from( .build()); } for (AttendanceInfo attendanceInfo : attendanceInfoList) { + if (!memberAttendanceInfoMap.containsKey(attendanceInfo.getMemberId())) continue; MemberAttendanceInfo memberAttendanceInfo = memberAttendanceInfoMap.get(attendanceInfo.getMemberId()); memberAttendanceInfo.getAttendanceInfoList().add(attendanceInfo); From 6ec3684b03515f820ca835afd9e2a1d5124e0d48 Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 15:31:31 +0900 Subject: [PATCH 07/15] =?UTF-8?q?feat:=20=EB=A9=A4=EB=B2=84=20=EC=B6=9C?= =?UTF-8?q?=EC=84=9D=20=ED=98=84=ED=99=A9=20=EC=88=98=EC=A0=95=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/member/MemberService.java | 25 +++++++++++++++++++ .../domain/attendance/entity/Participant.java | 4 +++ .../repository/ParticipantRepository.java | 15 +++++++++++ .../application/member/MemberServiceTest.java | 8 +++++- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java index 6eb3a82..e5ad510 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java @@ -3,10 +3,14 @@ import java.time.LocalDate; import java.time.LocalTime; import java.util.List; +import java.util.Map; import java.util.Optional; import gdsc.konkuk.platformcore.application.attendance.AttendanceInfo; +import gdsc.konkuk.platformcore.controller.member.AttendanceUpdateRequest; +import gdsc.konkuk.platformcore.domain.attendance.entity.Participant; import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository; +import gdsc.konkuk.platformcore.domain.attendance.repository.ParticipantRepository; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,6 +23,9 @@ import gdsc.konkuk.platformcore.domain.member.repository.MemberRepository; import lombok.RequiredArgsConstructor; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -27,6 +34,7 @@ public class MemberService { private final PasswordEncoder passwordEncoder; private final MemberRepository memberRepository; private final AttendanceRepository attendanceRepository; + private final ParticipantRepository participantRepository; @Transactional public Member register(MemberRegisterRequest registerRequest) { @@ -59,6 +67,23 @@ public List getMemberAttendanceInfo(String batch, LocalDat return MemberAttendanceInfo.from(batchMemberList, attendanceInfoList); } + @Transactional + public void updateAttendances( + String batch, LocalDate month, List attendanceUpdateRequests) { + Map participantMap = + participantRepository + .findAllByBatchAndStartAtBetween( + batch, + month.withDayOfMonth(1).atStartOfDay(), + month.withDayOfMonth(month.lengthOfMonth()).atTime(LocalTime.MAX)) + .stream() + .collect(toMap(Participant::getId, identity())); + for (AttendanceUpdateRequest attendanceUpdateRequest : attendanceUpdateRequests) { + Participant participant = participantMap.get(attendanceUpdateRequest.getParticipantId()); + participant.updateAttendance(attendanceUpdateRequest.isAttendance()); + } + } + private boolean checkMemberExistWithMemberId(String memberId) { Optional member = memberRepository.findByMemberId(memberId); return member.isPresent(); diff --git a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/entity/Participant.java b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/entity/Participant.java index 575272e..9a10e15 100644 --- a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/entity/Participant.java +++ b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/entity/Participant.java @@ -38,4 +38,8 @@ public Participant(Long id, Long attendanceId, Long memberId, boolean attendance public void attend() { this.attendance = true; } + + public void updateAttendance(boolean attendance) { + this.attendance = attendance; + } } 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 78ca8cd..1a0b31f 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 @@ -3,11 +3,26 @@ import gdsc.konkuk.platformcore.domain.attendance.entity.Participant; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; public interface ParticipantRepository extends JpaRepository { void deleteAllByAttendanceId(Long attendanceId); Optional findByMemberIdAndAttendanceId(Long memberId, Long attendanceId); + + @Query( + """ + SELECT p + FROM Member m + LEFT JOIN Participant p ON m.id = p.memberId + LEFT JOIN Attendance a ON p.attendanceId = a.id + LEFT JOIN Event e ON a.eventId = e.id + WHERE m.batch = :batch AND e.startAt BETWEEN :st AND :en + """) + List findAllByBatchAndStartAtBetween( + String batch, LocalDateTime st, LocalDateTime en); } diff --git a/src/test/java/gdsc/konkuk/platformcore/application/member/MemberServiceTest.java b/src/test/java/gdsc/konkuk/platformcore/application/member/MemberServiceTest.java index 372c7e1..11c7a17 100644 --- a/src/test/java/gdsc/konkuk/platformcore/application/member/MemberServiceTest.java +++ b/src/test/java/gdsc/konkuk/platformcore/application/member/MemberServiceTest.java @@ -6,6 +6,7 @@ import java.util.Optional; import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository; +import gdsc.konkuk.platformcore.domain.attendance.repository.ParticipantRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -34,13 +35,18 @@ class MemberServiceTest { @Mock private AttendanceRepository attendanceRepository; + @Mock + private ParticipantRepository participantRepository; + @Mock private PasswordEncoder passwordEncoder; @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); - subject = new MemberService(passwordEncoder, memberRepository, attendanceRepository); + subject = + new MemberService( + passwordEncoder, memberRepository, attendanceRepository, participantRepository); } @Test From 3a598944a9d96e3a2fed8f0532480819096bbf9e Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 15:40:10 +0900 Subject: [PATCH 08/15] =?UTF-8?q?feat:=20=EB=A9=A4=EB=B2=84=20=EC=B6=9C?= =?UTF-8?q?=EC=84=9D=20=ED=98=84=ED=99=A9=20=EC=88=98=EC=A0=95=20controlle?= =?UTF-8?q?r=20=EC=9E=91=EC=84=B1=20=EB=B0=8F=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/AttendanceUpdateRequest.java | 14 ++ .../controller/member/MemberController.java | 11 + .../member/MemberControllerTest.java | 200 +++++++++++------- 3 files changed, 149 insertions(+), 76 deletions(-) create mode 100644 src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateRequest.java diff --git a/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateRequest.java b/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateRequest.java new file mode 100644 index 0000000..cbdf000 --- /dev/null +++ b/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateRequest.java @@ -0,0 +1,14 @@ +package gdsc.konkuk.platformcore.controller.member; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class AttendanceUpdateRequest { + @NotNull private Long participantId; + @NotNull private boolean attendance; +} diff --git a/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java b/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java index bb1cd9e..47bffe3 100644 --- a/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java +++ b/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java @@ -8,6 +8,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -53,6 +54,16 @@ public ResponseEntity getAttendances( return ResponseEntity.ok(SuccessResponse.of(memberAttendanceInfoList)); } + @PatchMapping("/{batch}/attendances") + public ResponseEntity updateAttendances( + @PathVariable String batch, + @RequestParam Integer year, + @RequestParam Integer month, + @RequestBody @Valid List attendanceUpdateRequests) { + memberService.updateAttendances(batch, LocalDate.of(year, month, 1), attendanceUpdateRequests); + return ResponseEntity.ok(SuccessResponse.messageOnly()); + } + private URI getCreatedURI(Long memberId) { return ServletUriComponentsBuilder.fromCurrentRequest() .path("/{id}") diff --git a/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java b/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java index 66c351b..af0e46a 100644 --- a/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java +++ b/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java @@ -47,24 +47,21 @@ class MemberControllerTest { MockMvc mockMvc; - @Mock - Member member; + @Mock Member member; - @MockBean - private MemberService memberService; + @MockBean private MemberService memberService; - @Autowired - private ObjectMapper objectMapper; + @Autowired private ObjectMapper objectMapper; @BeforeEach void setUp( - WebApplicationContext webApplicationContext, - RestDocumentationContextProvider restDocumentation) { + WebApplicationContext webApplicationContext, + RestDocumentationContextProvider restDocumentation) { mockMvc = - MockMvcBuilders.webAppContextSetup(webApplicationContext) - .apply(springSecurity()) - .apply(documentationConfiguration(restDocumentation)) - .build(); + MockMvcBuilders.webAppContextSetup(webApplicationContext) + .apply(springSecurity()) + .apply(documentationConfiguration(restDocumentation)) + .build(); } @Test @@ -72,48 +69,48 @@ void setUp( void should_success_when_newMember() throws Exception { // given MemberRegisterRequest memberRegisterRequest = - MemberRegisterRequest.builder() - .memberId("202011288") - .password("password") - .email("example@konkuk.ac.kr") - .name("홍길동") - .batch("24-25") - .build(); + MemberRegisterRequest.builder() + .memberId("202011288") + .password("password") + .email("example@konkuk.ac.kr") + .name("홍길동") + .batch("24-25") + .build(); given(memberService.register(any(MemberRegisterRequest.class))).willReturn(member); // when ResultActions result = - mockMvc.perform( - RestDocumentationRequestBuilders.post("/api/v1/members") - .contentType(APPLICATION_JSON) - .content(objectMapper.writeValueAsString(memberRegisterRequest)) - .with(csrf())); + mockMvc.perform( + RestDocumentationRequestBuilders.post("/api/v1/members") + .contentType(APPLICATION_JSON) + .content(objectMapper.writeValueAsString(memberRegisterRequest)) + .with(csrf())); // then result - .andDo(print()) - .andExpect(status().isCreated()) - .andDo( - document( - "member/register", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - resource( - ResourceSnippetParameters.builder() - .description("새로운 멤버 회원 가입 성공") - .tag("member") - .responseHeaders(headerWithName("Location").description("등록한 Member URI")) - .requestFields( - fieldWithPath("memberId").description("회원 아이디"), - fieldWithPath("password").description("비밀번호"), - fieldWithPath("email").description("이메일"), - fieldWithPath("name").description("이름"), - fieldWithPath("batch").description("배치")) - .responseFields( - fieldWithPath("success").description(true), - fieldWithPath("message").description("회원 가입 성공"), - fieldWithPath("data").description("null")) - .build()))); + .andDo(print()) + .andExpect(status().isCreated()) + .andDo( + document( + "member/register", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + resource( + ResourceSnippetParameters.builder() + .description("새로운 멤버 회원 가입 성공") + .tag("member") + .responseHeaders(headerWithName("Location").description("등록한 Member URI")) + .requestFields( + fieldWithPath("memberId").description("회원 아이디"), + fieldWithPath("password").description("비밀번호"), + fieldWithPath("email").description("이메일"), + fieldWithPath("name").description("이름"), + fieldWithPath("batch").description("배치")) + .responseFields( + fieldWithPath("success").description(true), + fieldWithPath("message").description("회원 가입 성공"), + fieldWithPath("data").description("null")) + .build()))); } @Test @@ -121,23 +118,23 @@ void should_success_when_newMember() throws Exception { void should_fail_when_existingMember() throws Exception { // given MemberRegisterRequest memberRegisterRequest = - MemberRegisterRequest.builder() - .memberId("202011288") - .password("password") - .email("example@konkuk.ac.kr") - .name("홍길동") - .batch("24-25") - .build(); + MemberRegisterRequest.builder() + .memberId("202011288") + .password("password") + .email("example@konkuk.ac.kr") + .name("홍길동") + .batch("24-25") + .build(); given(memberService.register(any(MemberRegisterRequest.class))) - .willThrow(UserAlreadyExistException.class); + .willThrow(UserAlreadyExistException.class); // when ResultActions result = - mockMvc.perform( - RestDocumentationRequestBuilders.post("/api/v1/members") - .contentType(APPLICATION_JSON) - .content(objectMapper.writeValueAsString(memberRegisterRequest)) - .with(csrf())); + mockMvc.perform( + RestDocumentationRequestBuilders.post("/api/v1/members") + .contentType(APPLICATION_JSON) + .content(objectMapper.writeValueAsString(memberRegisterRequest)) + .with(csrf())); // then result.andDo(print()).andExpect(status().isBadRequest()); @@ -151,25 +148,25 @@ void should_success_when_delete_member() throws Exception { // when ResultActions result = - mockMvc.perform( - RestDocumentationRequestBuilders.delete("/api/v1/members") - .contentType(APPLICATION_JSON) - .with(csrf())); + mockMvc.perform( + RestDocumentationRequestBuilders.delete("/api/v1/members") + .contentType(APPLICATION_JSON) + .with(csrf())); // then result - .andDo(print()) - .andExpect(status().isNoContent()) - .andDo( - document( - "member/delete", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - resource( - ResourceSnippetParameters.builder() - .description("존재하는 회원 탈퇴") - .tag("member") - .build()))); + .andDo(print()) + .andExpect(status().isNoContent()) + .andDo( + document( + "member/delete", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + resource( + ResourceSnippetParameters.builder() + .description("존재하는 회원 탈퇴") + .tag("member") + .build()))); } @Test @@ -329,4 +326,55 @@ void should_success_when_get_attendances_by_batch() throws Exception { .description("출석 여부")) .build()))); } + + @Test + @DisplayName("특정 배치의 특정 월의 멤버 출석 정보 수정 성공") + @CustomMockUser + void should_success_when_update_attendances_by_batch() throws Exception { + // given + List attendanceUpdateRequests = + List.of( + AttendanceUpdateRequest.builder().participantId(1L).attendance(true).build(), + AttendanceUpdateRequest.builder().participantId(2L).attendance(false).build(), + AttendanceUpdateRequest.builder().participantId(3L).attendance(true).build()); + doNothing().when(memberService).updateAttendances(anyString(), any(), any()); + + // when + ResultActions result = + mockMvc.perform( + RestDocumentationRequestBuilders.patch("/api/v1/members/{batch}/attendances", "24-25") + .param("year", "2024") + .param("month", "7") + .contentType(APPLICATION_JSON) + .content(objectMapper.writeValueAsString(attendanceUpdateRequests)) + .with(csrf())); + + // then + result + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document( + "member/update_attendances", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + resource( + ResourceSnippetParameters.builder() + .description("특정 달의 멤버 출석 정보 수정") + .tag("member") + .pathParameters(parameterWithName("batch").description("수정할 멤버 기수")) + .queryParameters( + parameterWithName("year").description("수정할 년도"), + parameterWithName("month").description("수정할 월"), + parameterWithName("_csrf").ignored()) + .requestFields( + fieldWithPath("[]").description("출석 정보 수정 리스트"), + fieldWithPath("[].participantId").description("참가자 아이디"), + fieldWithPath("[].attendance").description("출석 여부")) + .responseFields( + fieldWithPath("success").description(true), + fieldWithPath("message").description("멤버 출석 정보 수정 성공"), + fieldWithPath("data").description("null")) + .build()))); + } } From 5f7ed46c3b9e73aeda2fbae0fc757c49b7c319ca Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 16:10:59 +0900 Subject: [PATCH 09/15] =?UTF-8?q?fix:=20DTO=20=EC=A0=84=ED=99=98=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=95=EC=97=90=EC=84=9C=20immutable=20list?= =?UTF-8?q?=EB=A1=9C=20=EC=B4=88=EA=B8=B0=ED=99=94=EB=90=98=EC=96=B4=20?= =?UTF-8?q?=EC=9D=B4=ED=9B=84=20=EC=88=98=EC=A0=95=EC=9D=B4=20=EB=B6=88?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=96=88=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platformcore/application/member/MemberAttendanceInfo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java index e43d027..94df2ad 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberAttendanceInfo.java @@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -39,7 +40,7 @@ public static List from( .memberRole(member.getRole()) .profileImageUrl(member.getProfileImageUrl()) .department(member.getDepartment()) - .attendanceInfoList(List.of()) + .attendanceInfoList(new ArrayList<>()) .build()); } for (AttendanceInfo attendanceInfo : attendanceInfoList) { From 6a30a8b06be064e5ed935478accc3b1d8fadd66a Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 16:12:19 +0900 Subject: [PATCH 10/15] =?UTF-8?q?fix:=20=EC=9C=A0=ED=9A=A8=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=80=20`participantId`=EC=9D=98=20?= =?UTF-8?q?=EC=B6=9C=EC=84=9D=20=EC=88=98=EC=A0=95=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?exception=20handling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platformcore/application/member/MemberService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java index e5ad510..00e5238 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java @@ -7,6 +7,8 @@ import java.util.Optional; import gdsc.konkuk.platformcore.application.attendance.AttendanceInfo; +import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceErrorCode; +import gdsc.konkuk.platformcore.application.attendance.exceptions.ParticipantNotFoundException; import gdsc.konkuk.platformcore.controller.member.AttendanceUpdateRequest; import gdsc.konkuk.platformcore.domain.attendance.entity.Participant; import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository; @@ -79,6 +81,10 @@ public void updateAttendances( .stream() .collect(toMap(Participant::getId, identity())); for (AttendanceUpdateRequest attendanceUpdateRequest : attendanceUpdateRequests) { + if (!participantMap.containsKey(attendanceUpdateRequest.getParticipantId())) { + throw ParticipantNotFoundException.of(AttendanceErrorCode.PARTICIPANT_NOT_FOUND); + } + Participant participant = participantMap.get(attendanceUpdateRequest.getParticipantId()); participant.updateAttendance(attendanceUpdateRequest.isAttendance()); } From af2acc225c61777a108366c03360308ca77e7054 Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 16:21:30 +0900 Subject: [PATCH 11/15] =?UTF-8?q?fix:=20Event=EC=97=90=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=20=EC=B6=9C=EC=84=9D=EC=9D=B4=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=A0=20=EA=B2=BD=EC=9A=B0,=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9D=84=20=EB=A7=89=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendance/AttendanceService.java | 54 +++++++++++-------- .../AttendanceAlreadyExistException.java | 14 +++++ .../exceptions/AttendanceErrorCode.java | 1 + .../repository/AttendanceRepository.java | 4 ++ 4 files changed, 51 insertions(+), 22 deletions(-) create mode 100644 src/main/java/gdsc/konkuk/platformcore/application/attendance/exceptions/AttendanceAlreadyExistException.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 27a713b..c22acae 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java @@ -1,5 +1,6 @@ package gdsc.konkuk.platformcore.application.attendance; +import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceAlreadyExistException; import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceErrorCode; import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceNotFoundException; import gdsc.konkuk.platformcore.application.attendance.exceptions.QrInvalidException; @@ -12,6 +13,7 @@ import gdsc.konkuk.platformcore.domain.attendance.entity.Participant; import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository; import gdsc.konkuk.platformcore.domain.attendance.repository.ParticipantRepository; +import gdsc.konkuk.platformcore.domain.event.entity.Event; import gdsc.konkuk.platformcore.domain.event.repository.EventRepository; import gdsc.konkuk.platformcore.domain.member.entity.Member; import gdsc.konkuk.platformcore.domain.member.repository.MemberRepository; @@ -35,14 +37,14 @@ public class AttendanceService { @Transactional public Participant attend(String memberEmail, Long attendanceId, String qrUuid) { Member member = - memberRepository - .findByEmail(memberEmail) - .orElseThrow(() -> UserNotFoundException.of(MemberErrorCode.USER_NOT_FOUND)); + memberRepository + .findByEmail(memberEmail) + .orElseThrow(() -> UserNotFoundException.of(MemberErrorCode.USER_NOT_FOUND)); Attendance attendance = - attendanceRepository - .findById(attendanceId) - .orElseThrow( - () -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND)); + attendanceRepository + .findById(attendanceId) + .orElseThrow( + () -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND)); if (!attendance.isActiveQr(qrUuid)) { throw QrInvalidException.of(AttendanceErrorCode.INVALID_QR_UUID); } @@ -52,15 +54,19 @@ public Participant attend(String memberEmail, Long attendanceId, String qrUuid) @Transactional public Long registerAttendance(AttendanceRegisterRequest registerRequest) { - checkEventExist(registerRequest.getEventId()); + Event event = + eventRepository + .findById(registerRequest.getEventId()) + .orElseThrow(() -> EventNotFoundException.of(EventErrorCode.EVENT_NOT_FOUND)); + checkAttendanceAlreadyExist(event); Attendance newAttendance = AttendanceRegisterRequest.toEntity(registerRequest); attendanceRepository.saveAndFlush(newAttendance); List members = memberRepository.findAllByBatch(registerRequest.getBatch()); List participants = - MemberToParticipantMapper.mapMemberListToParticipantList( - members, newAttendance.getId(), false); + MemberToParticipantMapper.mapMemberListToParticipantList( + members, newAttendance.getId(), false); participantRepository.saveAll(participants); return newAttendance.getId(); @@ -75,20 +81,20 @@ public void deleteAttendance(Long attendanceId) { @Transactional public String generateQr(Long attendanceId) { Attendance attendance = - attendanceRepository - .findById(attendanceId) - .orElseThrow( - () -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND)); + attendanceRepository + .findById(attendanceId) + .orElseThrow( + () -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND)); return attendance.generateQr(); } @Transactional public void expireQr(Long attendanceId, String qrUuid) { Attendance attendance = - attendanceRepository - .findById(attendanceId) - .orElseThrow( - () -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND)); + attendanceRepository + .findById(attendanceId) + .orElseThrow( + () -> AttendanceNotFoundException.of(AttendanceErrorCode.ATTENDANCE_NOT_FOUND)); if (!attendance.isActiveQr(qrUuid)) { throw QrInvalidException.of(AttendanceErrorCode.INVALID_QR_UUID); } @@ -96,9 +102,13 @@ public void expireQr(Long attendanceId, String qrUuid) { attendance.expireQr(); } - private void checkEventExist(Long eventId) { - eventRepository - .findById(eventId) - .orElseThrow(() -> EventNotFoundException.of(EventErrorCode.EVENT_NOT_FOUND)); + private void checkAttendanceAlreadyExist(Event event) { + attendanceRepository + .findByEventId(event.getId()) + .ifPresent( + attendance -> { + throw AttendanceAlreadyExistException.of( + AttendanceErrorCode.ATTENDANCE_ALREADY_EXIST); + }); } } diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/exceptions/AttendanceAlreadyExistException.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/exceptions/AttendanceAlreadyExistException.java new file mode 100644 index 0000000..a5616f2 --- /dev/null +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/exceptions/AttendanceAlreadyExistException.java @@ -0,0 +1,14 @@ +package gdsc.konkuk.platformcore.application.attendance.exceptions; + +import gdsc.konkuk.platformcore.global.exceptions.BusinessException; +import gdsc.konkuk.platformcore.global.exceptions.CustomErrorCode; + +public class AttendanceAlreadyExistException extends BusinessException { + protected AttendanceAlreadyExistException(CustomErrorCode errorCode, String logMessage) { + super(errorCode, logMessage); + } + + public static AttendanceAlreadyExistException of(CustomErrorCode errorCode) { + return new AttendanceAlreadyExistException(errorCode, errorCode.getMessage()); + } +} diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/exceptions/AttendanceErrorCode.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/exceptions/AttendanceErrorCode.java index 5be705f..1ae6d74 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/attendance/exceptions/AttendanceErrorCode.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/exceptions/AttendanceErrorCode.java @@ -6,6 +6,7 @@ @RequiredArgsConstructor public enum AttendanceErrorCode implements CustomErrorCode { ATTENDANCE_NOT_FOUND("출석 정보가 존재하지 않습니다", "[ERROR] : 출석 정보를 찾을 수 없음"), + ATTENDANCE_ALREADY_EXIST("출석 정보가 이미 존재합니다", "[ERROR] : 이미 존재하는 출석 정보"), INVALID_QR_UUID("유효하지 않은 QR 코드입니다", "[ERROR] : 유효하지 않은 QR 코드"), PARTICIPANT_NOT_FOUND("참가자 정보가 존재하지 않습니다", "[ERROR] : 참가자 정보를 찾을 수 없음"); diff --git a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java index 94f8805..dd32fd7 100644 --- a/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java +++ b/src/main/java/gdsc/konkuk/platformcore/domain/attendance/repository/AttendanceRepository.java @@ -4,10 +4,14 @@ import gdsc.konkuk.platformcore.domain.attendance.entity.Attendance; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; public interface AttendanceRepository extends JpaRepository { + Optional findByEventId(Long aLong); + @Query( """ SELECT new gdsc.konkuk.platformcore.application.attendance.AttendanceInfo( From 43e20d8cc51c9b72ab6b916c6c6321cb5f9b08ec Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 16:37:58 +0900 Subject: [PATCH 12/15] chore: gradle task `openapi3`, type casting --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 141cb7c..eedd359 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,4 @@ +import io.swagger.v3.oas.models.servers.Server import org.hidetake.gradle.swagger.generator.GenerateSwaggerUI import org.springframework.boot.gradle.tasks.bundling.BootJar @@ -69,7 +70,7 @@ dependencies { openapi3 { servers = [ { url = 'http://localhost:8080' }, - ] + ] as List> title = 'Post Service API' description = 'Post Service API description' version = '1.0.0' From 482c29b28fafaa52f12bac9e6831e77222489239 Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 22:44:38 +0900 Subject: [PATCH 13/15] =?UTF-8?q?style:=20`MemberToParticipantMapper`?= =?UTF-8?q?=EC=97=90=EC=84=9C=20`ParticipantMapper`=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendance/AttendanceService.java | 3 +-- .../attendance/MemberToParticipantMapper.java | 21 ------------------- .../attendance/ParticipantMapper.java | 21 +++++++++++++++++++ 3 files changed, 22 insertions(+), 23 deletions(-) delete mode 100644 src/main/java/gdsc/konkuk/platformcore/application/attendance/MemberToParticipantMapper.java create mode 100644 src/main/java/gdsc/konkuk/platformcore/application/attendance/ParticipantMapper.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 c22acae..dc28939 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java @@ -65,8 +65,7 @@ public Long registerAttendance(AttendanceRegisterRequest registerRequest) { List members = memberRepository.findAllByBatch(registerRequest.getBatch()); List participants = - MemberToParticipantMapper.mapMemberListToParticipantList( - members, newAttendance.getId(), false); + ParticipantMapper.mapMemberListToParticipantList(members, newAttendance.getId(), false); participantRepository.saveAll(participants); return newAttendance.getId(); diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/MemberToParticipantMapper.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/MemberToParticipantMapper.java deleted file mode 100644 index 192a24b..0000000 --- a/src/main/java/gdsc/konkuk/platformcore/application/attendance/MemberToParticipantMapper.java +++ /dev/null @@ -1,21 +0,0 @@ -package gdsc.konkuk.platformcore.application.attendance; - -import gdsc.konkuk.platformcore.domain.attendance.entity.Participant; -import gdsc.konkuk.platformcore.domain.member.entity.Member; - -import java.util.List; - -public class MemberToParticipantMapper { - public static List mapMemberListToParticipantList( - List members, Long attendanceId, boolean attendance) { - return members.stream() - .map( - member -> - Participant.builder() - .attendanceId(attendanceId) - .memberId(member.getId()) - .attendance(attendance) - .build()) - .toList(); - } -} diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/ParticipantMapper.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/ParticipantMapper.java new file mode 100644 index 0000000..a0ad5b2 --- /dev/null +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/ParticipantMapper.java @@ -0,0 +1,21 @@ +package gdsc.konkuk.platformcore.application.attendance; + +import gdsc.konkuk.platformcore.domain.attendance.entity.Participant; +import gdsc.konkuk.platformcore.domain.member.entity.Member; + +import java.util.List; + +public class ParticipantMapper { + public static List mapMemberListToParticipantList( + List members, Long attendanceId, boolean attendance) { + return members.stream() + .map( + member -> + Participant.builder() + .attendanceId(attendanceId) + .memberId(member.getId()) + .attendance(attendance) + .build()) + .toList(); + } +} From 2bc000b0224a5fd4640bb8984555ea7c7764d63c Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Fri, 26 Jul 2024 23:02:58 +0900 Subject: [PATCH 14/15] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=EC=88=98=EC=A0=95=20request=20payload=20=ED=98=95?= =?UTF-8?q?=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/member/MemberService.java | 13 ++++++----- .../member/AttendanceUpdateInfo.java | 14 ++++++++++++ .../member/AttendanceUpdateRequest.java | 10 +++++++-- .../controller/member/MemberController.java | 5 +++-- .../member/MemberControllerTest.java | 22 ++++++++++++------- 5 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateInfo.java diff --git a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java index 00e5238..ec99eea 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/member/MemberService.java @@ -9,7 +9,7 @@ import gdsc.konkuk.platformcore.application.attendance.AttendanceInfo; import gdsc.konkuk.platformcore.application.attendance.exceptions.AttendanceErrorCode; import gdsc.konkuk.platformcore.application.attendance.exceptions.ParticipantNotFoundException; -import gdsc.konkuk.platformcore.controller.member.AttendanceUpdateRequest; +import gdsc.konkuk.platformcore.controller.member.AttendanceUpdateInfo; import gdsc.konkuk.platformcore.domain.attendance.entity.Participant; import gdsc.konkuk.platformcore.domain.attendance.repository.AttendanceRepository; import gdsc.konkuk.platformcore.domain.attendance.repository.ParticipantRepository; @@ -71,7 +71,7 @@ public List getMemberAttendanceInfo(String batch, LocalDat @Transactional public void updateAttendances( - String batch, LocalDate month, List attendanceUpdateRequests) { + String batch, LocalDate month, List attendanceUpdateInfoList) { Map participantMap = participantRepository .findAllByBatchAndStartAtBetween( @@ -80,13 +80,14 @@ public void updateAttendances( month.withDayOfMonth(month.lengthOfMonth()).atTime(LocalTime.MAX)) .stream() .collect(toMap(Participant::getId, identity())); - for (AttendanceUpdateRequest attendanceUpdateRequest : attendanceUpdateRequests) { - if (!participantMap.containsKey(attendanceUpdateRequest.getParticipantId())) { + + for (AttendanceUpdateInfo attendanceUpdateInfo : attendanceUpdateInfoList) { + if (!participantMap.containsKey(attendanceUpdateInfo.getParticipantId())) { throw ParticipantNotFoundException.of(AttendanceErrorCode.PARTICIPANT_NOT_FOUND); } - Participant participant = participantMap.get(attendanceUpdateRequest.getParticipantId()); - participant.updateAttendance(attendanceUpdateRequest.isAttendance()); + Participant participant = participantMap.get(attendanceUpdateInfo.getParticipantId()); + participant.updateAttendance(attendanceUpdateInfo.isAttendance()); } } diff --git a/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateInfo.java b/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateInfo.java new file mode 100644 index 0000000..97fae41 --- /dev/null +++ b/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateInfo.java @@ -0,0 +1,14 @@ +package gdsc.konkuk.platformcore.controller.member; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class AttendanceUpdateInfo { + @NotNull private Long participantId; + @NotNull private boolean attendance; +} diff --git a/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateRequest.java b/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateRequest.java index cbdf000..4927534 100644 --- a/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateRequest.java +++ b/src/main/java/gdsc/konkuk/platformcore/controller/member/AttendanceUpdateRequest.java @@ -1,14 +1,20 @@ package gdsc.konkuk.platformcore.controller.member; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.List; + @Getter @Setter @Builder +@NoArgsConstructor +@AllArgsConstructor public class AttendanceUpdateRequest { - @NotNull private Long participantId; - @NotNull private boolean attendance; + @NotNull @Valid private List attendanceUpdateInfoList; } diff --git a/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java b/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java index 47bffe3..260e526 100644 --- a/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java +++ b/src/main/java/gdsc/konkuk/platformcore/controller/member/MemberController.java @@ -59,8 +59,9 @@ public ResponseEntity updateAttendances( @PathVariable String batch, @RequestParam Integer year, @RequestParam Integer month, - @RequestBody @Valid List attendanceUpdateRequests) { - memberService.updateAttendances(batch, LocalDate.of(year, month, 1), attendanceUpdateRequests); + @RequestBody @Valid AttendanceUpdateRequest attendanceUpdateRequest) { + memberService.updateAttendances( + batch, LocalDate.of(year, month, 1), attendanceUpdateRequest.getAttendanceUpdateInfoList()); return ResponseEntity.ok(SuccessResponse.messageOnly()); } diff --git a/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java b/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java index af0e46a..523389d 100644 --- a/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java +++ b/src/test/java/gdsc/konkuk/platformcore/controller/member/MemberControllerTest.java @@ -332,11 +332,15 @@ void should_success_when_get_attendances_by_batch() throws Exception { @CustomMockUser void should_success_when_update_attendances_by_batch() throws Exception { // given - List attendanceUpdateRequests = + List attendanceUpdateInfoList = List.of( - AttendanceUpdateRequest.builder().participantId(1L).attendance(true).build(), - AttendanceUpdateRequest.builder().participantId(2L).attendance(false).build(), - AttendanceUpdateRequest.builder().participantId(3L).attendance(true).build()); + AttendanceUpdateInfo.builder().participantId(1L).attendance(true).build(), + AttendanceUpdateInfo.builder().participantId(2L).attendance(false).build(), + AttendanceUpdateInfo.builder().participantId(3L).attendance(true).build()); + AttendanceUpdateRequest attendanceUpdateRequest = + AttendanceUpdateRequest.builder() + .attendanceUpdateInfoList(attendanceUpdateInfoList) + .build(); doNothing().when(memberService).updateAttendances(anyString(), any(), any()); // when @@ -346,7 +350,7 @@ void should_success_when_update_attendances_by_batch() throws Exception { .param("year", "2024") .param("month", "7") .contentType(APPLICATION_JSON) - .content(objectMapper.writeValueAsString(attendanceUpdateRequests)) + .content(objectMapper.writeValueAsString(attendanceUpdateRequest)) .with(csrf())); // then @@ -368,9 +372,11 @@ void should_success_when_update_attendances_by_batch() throws Exception { parameterWithName("month").description("수정할 월"), parameterWithName("_csrf").ignored()) .requestFields( - fieldWithPath("[]").description("출석 정보 수정 리스트"), - fieldWithPath("[].participantId").description("참가자 아이디"), - fieldWithPath("[].attendance").description("출석 여부")) + fieldWithPath("attendanceUpdateInfoList[]").description("출석 정보 수정 리스트"), + fieldWithPath("attendanceUpdateInfoList[].participantId") + .description("참가자 아이디"), + fieldWithPath("attendanceUpdateInfoList[].attendance") + .description("출석 여부")) .responseFields( fieldWithPath("success").description(true), fieldWithPath("message").description("멤버 출석 정보 수정 성공"), From 701bd9a910b3b1c5aa18276cf272f51f2d06dad7 Mon Sep 17 00:00:00 2001 From: WhitePiano Date: Sun, 28 Jul 2024 20:04:26 +0900 Subject: [PATCH 15/15] =?UTF-8?q?refactor:=20`Member`=20To`=20Participant`?= =?UTF-8?q?=20Mapping=20=EA=B3=BC=EC=A0=95=EC=97=90=EC=84=9C=20`Member`?= =?UTF-8?q?=EC=97=90=20=EC=A1=B4=EC=9E=AC=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8D=98=20`attendance`=20field=EB=A5=BC=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20false=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/attendance/AttendanceService.java | 2 +- .../application/attendance/ParticipantMapper.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) 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 dc28939..b7144e8 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/AttendanceService.java @@ -65,7 +65,7 @@ public Long registerAttendance(AttendanceRegisterRequest registerRequest) { List members = memberRepository.findAllByBatch(registerRequest.getBatch()); List participants = - ParticipantMapper.mapMemberListToParticipantList(members, newAttendance.getId(), false); + ParticipantMapper.mapMemberListToAbsentParticipantList(members, newAttendance.getId()); participantRepository.saveAll(participants); return newAttendance.getId(); diff --git a/src/main/java/gdsc/konkuk/platformcore/application/attendance/ParticipantMapper.java b/src/main/java/gdsc/konkuk/platformcore/application/attendance/ParticipantMapper.java index a0ad5b2..e1ce6ab 100644 --- a/src/main/java/gdsc/konkuk/platformcore/application/attendance/ParticipantMapper.java +++ b/src/main/java/gdsc/konkuk/platformcore/application/attendance/ParticipantMapper.java @@ -6,15 +6,15 @@ import java.util.List; public class ParticipantMapper { - public static List mapMemberListToParticipantList( - List members, Long attendanceId, boolean attendance) { + public static List mapMemberListToAbsentParticipantList( + List members, Long attendanceId) { return members.stream() .map( member -> Participant.builder() .attendanceId(attendanceId) .memberId(member.getId()) - .attendance(attendance) + .attendance(false) .build()) .toList(); }