diff --git a/src/docs/asciidoc/api/challenge.adoc b/src/docs/asciidoc/api/challenge.adoc index 77a26f9d..6b8c15b5 100644 --- a/src/docs/asciidoc/api/challenge.adoc +++ b/src/docs/asciidoc/api/challenge.adoc @@ -19,6 +19,17 @@ operation::challenge/get-challenge-page[snippets='http-request,http-response,res 현재 접속한 사용자가 참여하고 있는 챌린지 목록을 반환합니다. + +챌린지 상태의 경우, 다음의 7가지 상태 중 하나가 문자열로 전달됩니다. + +[ "SCHEDULED"(진행 예정), +"IN_PROGRESS"(진행 중), +"COMPLETED_PENDING_SETTLEMENT"(완료, 정산 안 됨), +"COMPLETED_SETTLED"(완료, 정산됨), +"CANCELED"(중도 취소), +"CANCELED_SETTLED"(중도 취소, 정산됨), +"CANCELED_BEFORE_START"(시작 전 취소함) ] + operation::challenge/get-my-challenge-list[snippets='http-request,http-response,response-fields'] === 다른 멤버의 챌린지 참여 목록 조회 diff --git a/src/main/java/com/habitpay/habitpay/domain/challenge/application/ChallengeSettlementService.java b/src/main/java/com/habitpay/habitpay/domain/challenge/application/ChallengeSettlementService.java index 5079f764..55525b93 100644 --- a/src/main/java/com/habitpay/habitpay/domain/challenge/application/ChallengeSettlementService.java +++ b/src/main/java/com/habitpay/habitpay/domain/challenge/application/ChallengeSettlementService.java @@ -33,11 +33,14 @@ public SuccessResponse settleChallenge(Long challengeId, Member member) { throw new BadRequestException(ErrorCode.INVALID_CHALLENGE_SETTLEMENT_TIME); } - if (!(challenge.getState() == ChallengeState.COMPLETED_PENDING_SETTLEMENT)) { - throw new BadRequestException(ErrorCode.INVALID_CHALLENGE_STATE_FOR_SETTLEMENT); + switch (challenge.getState()) { + case COMPLETED_PENDING_SETTLEMENT -> challenge.setStateCompletedSettled(); + case COMPLETED_SETTLED -> challenge.setStateCompletedPendingSettlement(); + case CANCELED -> challenge.setStateCanceledSettled(); + case CANCELED_SETTLED -> challenge.setStateCanceled(); + default -> throw new BadRequestException(ErrorCode.INVALID_CHALLENGE_STATE_FOR_SETTLEMENT); } - challenge.setStateCompletedSettled(); challengeRepository.save(challenge); return SuccessResponse.of(SuccessCode.CHALLENGE_SETTLEMENT_SUCCESS); diff --git a/src/main/java/com/habitpay/habitpay/domain/challenge/domain/Challenge.java b/src/main/java/com/habitpay/habitpay/domain/challenge/domain/Challenge.java index 2292637c..ff08e30e 100644 --- a/src/main/java/com/habitpay/habitpay/domain/challenge/domain/Challenge.java +++ b/src/main/java/com/habitpay/habitpay/domain/challenge/domain/Challenge.java @@ -157,6 +157,7 @@ public void setStateInProgress() { } public void setStateCompletedPendingSettlement() { + this.isPaidAll = false; this.state = ChallengeState.COMPLETED_PENDING_SETTLEMENT; } @@ -165,6 +166,16 @@ public void setStateCompletedSettled() { this.state = ChallengeState.COMPLETED_SETTLED; } + public void setStateCanceledSettled() { + this.isPaidAll = true; + this.state = ChallengeState.CANCELED_SETTLED; + } + + public void setStateCanceled() { + this.isPaidAll = false; + this.state = ChallengeState.CANCELED; + } + public boolean isTodayParticipatingDay() { ZonedDateTime nowInLocal = TimeZoneConverter.convertEtcToLocalTimeZone(ZonedDateTime.now()); DayOfWeek today = nowInLocal.getDayOfWeek(); diff --git a/src/main/java/com/habitpay/habitpay/domain/challenge/domain/ChallengeState.java b/src/main/java/com/habitpay/habitpay/domain/challenge/domain/ChallengeState.java index d2d7c058..1208fe8f 100644 --- a/src/main/java/com/habitpay/habitpay/domain/challenge/domain/ChallengeState.java +++ b/src/main/java/com/habitpay/habitpay/domain/challenge/domain/ChallengeState.java @@ -9,5 +9,6 @@ public enum ChallengeState { COMPLETED_PENDING_SETTLEMENT, COMPLETED_SETTLED, CANCELED, + CANCELED_SETTLED, CANCELED_BEFORE_START; } \ No newline at end of file diff --git a/src/main/java/com/habitpay/habitpay/domain/challenge/dto/ChallengeDetailsResponse.java b/src/main/java/com/habitpay/habitpay/domain/challenge/dto/ChallengeDetailsResponse.java index 4772218c..e4036717 100644 --- a/src/main/java/com/habitpay/habitpay/domain/challenge/dto/ChallengeDetailsResponse.java +++ b/src/main/java/com/habitpay/habitpay/domain/challenge/dto/ChallengeDetailsResponse.java @@ -28,6 +28,7 @@ public class ChallengeDetailsResponse { private Boolean isHost; private Boolean isMemberEnrolledInChallenge; private Boolean isGivenUp; + private String challengeState; public static ChallengeDetailsResponse of(Member member, Challenge challenge, List enrolledMembersProfileImageList, @@ -50,6 +51,7 @@ public static ChallengeDetailsResponse of(Member member, Challenge challenge, .isHost(challenge.getHost().getId().equals(member.getId())) .isMemberEnrolledInChallenge(isMemberEnrolledInChallenge) .isGivenUp(isGivenUp) + .challengeState(String.valueOf(challenge.getState())) .build(); } } diff --git a/src/main/java/com/habitpay/habitpay/domain/challenge/dto/ChallengeEnrolledListItemResponse.java b/src/main/java/com/habitpay/habitpay/domain/challenge/dto/ChallengeEnrolledListItemResponse.java index 585f5fda..ffcd4b46 100644 --- a/src/main/java/com/habitpay/habitpay/domain/challenge/dto/ChallengeEnrolledListItemResponse.java +++ b/src/main/java/com/habitpay/habitpay/domain/challenge/dto/ChallengeEnrolledListItemResponse.java @@ -27,6 +27,7 @@ public class ChallengeEnrolledListItemResponse { private int successCount; private Boolean isTodayParticipatingDay; private Boolean isParticipatedToday; + private String challengeState; public static ChallengeEnrolledListItemResponse of(Challenge challenge, ChallengeEnrollment challengeEnrollment, ParticipationStat stat, String hostProfileImage, boolean isParticipatedToday) { return ChallengeEnrolledListItemResponse.builder() @@ -46,6 +47,7 @@ public static ChallengeEnrolledListItemResponse of(Challenge challenge, Challeng .successCount(stat.getSuccessCount()) .isTodayParticipatingDay(challenge.isTodayParticipatingDay()) .isParticipatedToday(isParticipatedToday) + .challengeState(String.valueOf(challenge.getState())) .build(); } } diff --git a/src/main/java/com/habitpay/habitpay/global/error/exception/ErrorCode.java b/src/main/java/com/habitpay/habitpay/global/error/exception/ErrorCode.java index 3dc5cb0c..956a12ef 100644 --- a/src/main/java/com/habitpay/habitpay/global/error/exception/ErrorCode.java +++ b/src/main/java/com/habitpay/habitpay/global/error/exception/ErrorCode.java @@ -47,7 +47,7 @@ public enum ErrorCode { NOT_ALLOWED_TO_CANCEL_ENROLLMENT_OF_HOST(HttpStatus.BAD_REQUEST, "챌린지 주최자는 참여 취소가 불가능 합니다."), NOT_ALLOWED_TO_DELETE_CHALLENGE(HttpStatus.FORBIDDEN, "챌린지 삭제는 챌린지 주최자만 가능합니다."), INVALID_CHALLENGE_SETTLEMENT_TIME(HttpStatus.BAD_REQUEST, "정산은 챌린지 종료 이후에 가능합니다."), - INVALID_CHALLENGE_STATE_FOR_SETTLEMENT(HttpStatus.BAD_REQUEST, "정산은 챌린지가 종료 이후 정산 대기 상태일 때만 가능합니다."), + INVALID_CHALLENGE_STATE_FOR_SETTLEMENT(HttpStatus.BAD_REQUEST, "정산 혹은 정산 취소 처리가 불가한 상태입니다."), // Challenge Participation Record RECORD_NOT_FOUND(HttpStatus.NOT_FOUND, "챌린지 참여 기록이 존재하지 않습니다."), diff --git a/src/main/java/com/habitpay/habitpay/global/response/SuccessCode.java b/src/main/java/com/habitpay/habitpay/global/response/SuccessCode.java index af67b421..b083704c 100644 --- a/src/main/java/com/habitpay/habitpay/global/response/SuccessCode.java +++ b/src/main/java/com/habitpay/habitpay/global/response/SuccessCode.java @@ -22,7 +22,7 @@ public enum SuccessCode { CANCEL_CHALLENGE_ENROLLMENT_SUCCESS("정상적으로 챌린지 등록을 취소했습니다."), GIVING_UP_CHALLENGE("정상적으로 챌린지 중도 포기 처리가 되었습니다."), DELETE_CHALLENGE_SUCCESS("정상적으로 챌린지를 삭제했습니다."), - CHALLENGE_SETTLEMENT_SUCCESS("정상적으로 챌린지 정산이 완료되었습니다."), + CHALLENGE_SETTLEMENT_SUCCESS("정상적으로 챌린지 정산 상태가 변경되었습니다."), // Post CREATE_POST_SUCCESS("정상적으로 포스트를 생성했습니다."), diff --git a/src/test/java/com/habitpay/habitpay/domain/challenge/api/ChallengeApiTest.java b/src/test/java/com/habitpay/habitpay/domain/challenge/api/ChallengeApiTest.java index cf02698c..7d3bcfd0 100644 --- a/src/test/java/com/habitpay/habitpay/domain/challenge/api/ChallengeApiTest.java +++ b/src/test/java/com/habitpay/habitpay/domain/challenge/api/ChallengeApiTest.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.habitpay.habitpay.docs.springrestdocs.AbstractRestDocsTests; import com.habitpay.habitpay.domain.challenge.application.*; +import com.habitpay.habitpay.domain.challenge.domain.ChallengeState; import com.habitpay.habitpay.domain.challenge.dto.ChallengeCreationRequest; import com.habitpay.habitpay.domain.challenge.dto.ChallengeCreationResponse; import com.habitpay.habitpay.domain.challenge.dto.ChallengeDetailsResponse; @@ -169,23 +170,24 @@ void getEnrolledChallengeList() throws Exception { // given ChallengeEnrolledListItemResponse response = ChallengeEnrolledListItemResponse.builder() - .challengeId(1L) - .title("챌린지 제목") - .description("챌린지 설명") - .startDate(ZonedDateTime.now()) - .endDate(ZonedDateTime.now().plusDays(5)) - .stopDate(null) - .totalParticipatingDaysCount(2) - .numberOfParticipants(1) - .participatingDays(1 << 2) - .totalFee(1000) - .isPaidAll(false) - .hostProfileImage("챌린지 주최자 프로필 이미지") - .isMemberGivenUp(false) - .successCount(4) - .isTodayParticipatingDay(true) - .isParticipatedToday(false) - .build(); + .challengeId(1L) + .title("챌린지 제목") + .description("챌린지 설명") + .startDate(ZonedDateTime.now()) + .endDate(ZonedDateTime.now().plusDays(5)) + .stopDate(null) + .totalParticipatingDaysCount(2) + .numberOfParticipants(1) + .participatingDays(1 << 2) + .totalFee(1000) + .isPaidAll(false) + .hostProfileImage("챌린지 주최자 프로필 이미지") + .isMemberGivenUp(false) + .successCount(4) + .isTodayParticipatingDay(true) + .isParticipatedToday(false) + .challengeState(String.valueOf(ChallengeState.IN_PROGRESS)) + .build(); given(challengeSearchService.getEnrolledChallengeList(any(Member.class))) .willReturn(SuccessResponse.of(SuccessCode.NO_MESSAGE, List.of(response))); @@ -201,24 +203,25 @@ void getEnrolledChallengeList() throws Exception { headerWithName(HttpHeaders.AUTHORIZATION).description("액세스 토큰") ), responseFields( - fieldWithPath("message").description("메세지"), - fieldWithPath("data[].challengeId").description("챌린지 ID"), - fieldWithPath("data[].title").description("챌린지 제목"), - fieldWithPath("data[].description").description("챌린지 설명"), - fieldWithPath("data[].startDate").description("챌린지 시작 일시"), - fieldWithPath("data[].endDate").description("챌린지 종료 일시"), - fieldWithPath("data[].stopDate").description("챌린지 중단 일시"), - fieldWithPath("data[].totalParticipatingDaysCount").description("챌린지 총 참여 일수"), - fieldWithPath("data[].numberOfParticipants").description("챌린지 참여 인원"), - fieldWithPath("data[].participatingDays").description("챌린지 참여 요일"), - fieldWithPath("data[].totalFee").description("나의 벌금 합계"), - fieldWithPath("data[].isPaidAll").description("최종 정산 여부"), - fieldWithPath("data[].hostProfileImage").description("챌린지 주최자 프로필 이미지"), - fieldWithPath("data[].isMemberGivenUp").description("현재 사용자의 챌린지 포기 여부"), - fieldWithPath("data[].successCount").description("챌린지 인증 성공 횟수"), - fieldWithPath("data[].isTodayParticipatingDay").description( - "오늘 요일 == 챌린지 참여 요일"), - fieldWithPath("data[].isParticipatedToday").description("오늘 챌린지 참여 여부") + fieldWithPath("message").description("메세지"), + fieldWithPath("data[].challengeId").description("챌린지 ID"), + fieldWithPath("data[].title").description("챌린지 제목"), + fieldWithPath("data[].description").description("챌린지 설명"), + fieldWithPath("data[].startDate").description("챌린지 시작 일시"), + fieldWithPath("data[].endDate").description("챌린지 종료 일시"), + fieldWithPath("data[].stopDate").description("챌린지 중단 일시"), + fieldWithPath("data[].totalParticipatingDaysCount").description("챌린지 총 참여 일수"), + fieldWithPath("data[].numberOfParticipants").description("챌린지 참여 인원"), + fieldWithPath("data[].participatingDays").description("챌린지 참여 요일"), + fieldWithPath("data[].totalFee").description("나의 벌금 합계"), + fieldWithPath("data[].isPaidAll").description("최종 정산 여부"), + fieldWithPath("data[].hostProfileImage").description("챌린지 주최자 프로필 이미지"), + fieldWithPath("data[].isMemberGivenUp").description("현재 사용자의 챌린지 포기 여부"), + fieldWithPath("data[].successCount").description("챌린지 인증 성공 횟수"), + fieldWithPath("data[].isTodayParticipatingDay").description( + "오늘 요일 == 챌린지 참여 요일"), + fieldWithPath("data[].isParticipatedToday").description("오늘 챌린지 참여 여부"), + fieldWithPath("data[].challengeState").description("챌린지 상태") ) )); } @@ -230,23 +233,24 @@ void getEnrolledChallengeListForMember() throws Exception { // given ChallengeEnrolledListItemResponse response = ChallengeEnrolledListItemResponse.builder() - .challengeId(1L) - .title("챌린지 제목") - .description("챌린지 설명") - .startDate(ZonedDateTime.now()) - .endDate(ZonedDateTime.now().plusDays(5)) - .stopDate(null) - .totalParticipatingDaysCount(2) - .numberOfParticipants(1) - .participatingDays(1 << 2) - .totalFee(1000) - .isPaidAll(false) - .hostProfileImage("챌린지 주최자 프로필 이미지") - .isMemberGivenUp(false) - .successCount(4) - .isTodayParticipatingDay(true) - .isParticipatedToday(false) - .build(); + .challengeId(1L) + .title("챌린지 제목") + .description("챌린지 설명") + .startDate(ZonedDateTime.now()) + .endDate(ZonedDateTime.now().plusDays(5)) + .stopDate(null) + .totalParticipatingDaysCount(2) + .numberOfParticipants(1) + .participatingDays(1 << 2) + .totalFee(1000) + .isPaidAll(false) + .hostProfileImage("챌린지 주최자 프로필 이미지") + .isMemberGivenUp(false) + .successCount(4) + .isTodayParticipatingDay(true) + .isParticipatedToday(false) + .challengeState(String.valueOf(ChallengeState.COMPLETED_PENDING_SETTLEMENT)) + .build(); given(challengeSearchService.getEnrolledChallengeListForMember(anyLong())) .willReturn(SuccessResponse.of(SuccessCode.NO_MESSAGE, List.of(response))); @@ -262,24 +266,25 @@ void getEnrolledChallengeListForMember() throws Exception { headerWithName(HttpHeaders.AUTHORIZATION).description("액세스 토큰") ), responseFields( - fieldWithPath("message").description("메세지"), - fieldWithPath("data[].challengeId").description("챌린지 ID"), - fieldWithPath("data[].title").description("챌린지 제목"), - fieldWithPath("data[].description").description("챌린지 설명"), - fieldWithPath("data[].startDate").description("챌린지 시작 일시"), - fieldWithPath("data[].endDate").description("챌린지 종료 일시"), - fieldWithPath("data[].stopDate").description("챌린지 중단 일시"), - fieldWithPath("data[].totalParticipatingDaysCount").description("챌린지 총 참여 일수"), - fieldWithPath("data[].numberOfParticipants").description("챌린지 참여 인원"), - fieldWithPath("data[].participatingDays").description("챌린지 참여 요일"), - fieldWithPath("data[].totalFee").description("나의 벌금 합계"), - fieldWithPath("data[].isPaidAll").description("최종 정산 여부"), - fieldWithPath("data[].hostProfileImage").description("챌린지 주최자 프로필 이미지"), - fieldWithPath("data[].isMemberGivenUp").description("현재 사용자의 챌린지 포기 여부"), - fieldWithPath("data[].successCount").description("챌린지 인증 성공 횟수"), - fieldWithPath("data[].isTodayParticipatingDay").description( - "오늘 요일 == 챌린지 참여 요일"), - fieldWithPath("data[].isParticipatedToday").description("오늘 챌린지 참여 여부") + fieldWithPath("message").description("메세지"), + fieldWithPath("data[].challengeId").description("챌린지 ID"), + fieldWithPath("data[].title").description("챌린지 제목"), + fieldWithPath("data[].description").description("챌린지 설명"), + fieldWithPath("data[].startDate").description("챌린지 시작 일시"), + fieldWithPath("data[].endDate").description("챌린지 종료 일시"), + fieldWithPath("data[].stopDate").description("챌린지 중단 일시"), + fieldWithPath("data[].totalParticipatingDaysCount").description("챌린지 총 참여 일수"), + fieldWithPath("data[].numberOfParticipants").description("챌린지 참여 인원"), + fieldWithPath("data[].participatingDays").description("챌린지 참여 요일"), + fieldWithPath("data[].totalFee").description("나의 벌금 합계"), + fieldWithPath("data[].isPaidAll").description("최종 정산 여부"), + fieldWithPath("data[].hostProfileImage").description("챌린지 주최자 프로필 이미지"), + fieldWithPath("data[].isMemberGivenUp").description("현재 사용자의 챌린지 포기 여부"), + fieldWithPath("data[].successCount").description("챌린지 인증 성공 횟수"), + fieldWithPath("data[].isTodayParticipatingDay").description( + "오늘 요일 == 챌린지 참여 요일"), + fieldWithPath("data[].isParticipatedToday").description("오늘 챌린지 참여 여부"), + fieldWithPath("data[].challengeState").description("챌린지 상태") ) )); } @@ -291,24 +296,25 @@ void getChallengeDetails() throws Exception { // given ChallengeDetailsResponse challengeDetailsResponse = ChallengeDetailsResponse.builder() - .title("챌린지 제목") - .description("챌린지 설명") - .startDate(ZonedDateTime.now()) - .endDate(ZonedDateTime.now().plusDays(5)) - .stopDate(null) - .numberOfParticipants(1) - .participatingDays(1 << 2) - .feePerAbsence(1000) - .totalAbsenceFee(0) - .isPaidAll(false) - .hostNickname("챌린지 주최자 닉네임") - .enrolledMembersProfileImageList(List.of("imageLink1", "imageLink2", "imageLink3")) - .isHost(true) - .isMemberEnrolledInChallenge(true) - .isTodayParticipatingDay(true) - .isParticipatedToday(true) - .isGivenUp(false) - .build(); + .title("챌린지 제목") + .description("챌린지 설명") + .startDate(ZonedDateTime.now()) + .endDate(ZonedDateTime.now().plusDays(5)) + .stopDate(null) + .numberOfParticipants(1) + .participatingDays(1 << 2) + .feePerAbsence(1000) + .totalAbsenceFee(0) + .isPaidAll(false) + .hostNickname("챌린지 주최자 닉네임") + .enrolledMembersProfileImageList(List.of("imageLink1", "imageLink2", "imageLink3")) + .isHost(true) + .isMemberEnrolledInChallenge(true) + .isTodayParticipatingDay(true) + .isParticipatedToday(true) + .isGivenUp(false) + .challengeState(String.valueOf(ChallengeState.SCHEDULED)) + .build(); given(challengeDetailsService.getChallengeDetails(anyLong(), any(Member.class))) .willReturn(SuccessResponse.of(SuccessCode.NO_MESSAGE, challengeDetailsResponse)); @@ -324,27 +330,28 @@ void getChallengeDetails() throws Exception { headerWithName(HttpHeaders.AUTHORIZATION).description("액세스 토큰") ), responseFields( - fieldWithPath("message").description("메세지"), - fieldWithPath("data.title").description("챌린지 제목"), - fieldWithPath("data.description").description("챌린지 설명"), - fieldWithPath("data.startDate").description("챌린지 시작 일시"), - fieldWithPath("data.endDate").description("챌린지 종료 일시"), - fieldWithPath("data.stopDate").description("챌린지 중단 일시"), - fieldWithPath("data.numberOfParticipants").description("챌린지 참여 인"), - fieldWithPath("data.participatingDays").description("챌린지 참여 요일"), - fieldWithPath("data.feePerAbsence").description("미참여 1회당 벌금"), - fieldWithPath("data.totalAbsenceFee").description("챌린지 전체 벌금"), - fieldWithPath("data.isPaidAll").description("최종 정산 여부"), - fieldWithPath("data.hostNickname").description("챌린지 주최자 닉네임"), - fieldWithPath("data.enrolledMembersProfileImageList").description( - "챌린지 참여자 프로필 이미지 (최대 3명)"), - fieldWithPath("data.isHost").description("현재 접속한 사용자 == 챌린지 주최자"), - fieldWithPath("data.isMemberEnrolledInChallenge").description( - "현재 접속한 사용자의 챌린지 참여 여부"), - fieldWithPath("data.isTodayParticipatingDay").description("금일이 챌린지 참여일인지 여부"), - fieldWithPath("data.isParticipatedToday").description( - "현재 접속한 사용자가 챌린지의 참가자일 경우, 금일 참여했는지 여부(참가자가 아니어도 false)"), - fieldWithPath("data.isGivenUp").description("챌린지 중도 포기 여부") + fieldWithPath("message").description("메세지"), + fieldWithPath("data.title").description("챌린지 제목"), + fieldWithPath("data.description").description("챌린지 설명"), + fieldWithPath("data.startDate").description("챌린지 시작 일시"), + fieldWithPath("data.endDate").description("챌린지 종료 일시"), + fieldWithPath("data.stopDate").description("챌린지 중단 일시"), + fieldWithPath("data.numberOfParticipants").description("챌린지 참여 인"), + fieldWithPath("data.participatingDays").description("챌린지 참여 요일"), + fieldWithPath("data.feePerAbsence").description("미참여 1회당 벌금"), + fieldWithPath("data.totalAbsenceFee").description("챌린지 전체 벌금"), + fieldWithPath("data.isPaidAll").description("최종 정산 여부"), + fieldWithPath("data.hostNickname").description("챌린지 주최자 닉네임"), + fieldWithPath("data.enrolledMembersProfileImageList").description( + "챌린지 참여자 프로필 이미지 (최대 3명)"), + fieldWithPath("data.isHost").description("현재 접속한 사용자 == 챌린지 주최자"), + fieldWithPath("data.isMemberEnrolledInChallenge").description( + "현재 접속한 사용자의 챌린지 참여 여부"), + fieldWithPath("data.isTodayParticipatingDay").description("금일이 챌린지 참여일인지 여부"), + fieldWithPath("data.isParticipatedToday").description( + "현재 접속한 사용자가 챌린지의 참가자일 경우, 금일 참여했는지 여부(참가자가 아니어도 false)"), + fieldWithPath("data.isGivenUp").description("챌린지 중도 포기 여부"), + fieldWithPath("data.challengeState").description("챌린지 상태") ) )); }