From 9c2c5526a8cff5e32009854770842a149eed3daa Mon Sep 17 00:00:00 2001 From: Songyi Kim Date: Sat, 26 Oct 2024 22:16:45 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EB=AF=B8=EC=85=98=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=B0=B0?= =?UTF-8?q?=EC=B9=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../mission/MissionMemberService.java | 38 +++++++++----- .../application/mission/MissionService.java | 5 ++ .../mission/dto/response/MissionResponse.java | 5 +- .../dto/response/MissionsResponse.java | 7 +-- .../goalpanzi/domain/mission/Mission.java | 20 +++++++- .../domain/mission/MissionMember.java | 17 ++++++- .../domain/mission/MissionStatus.java | 51 ++++++++++++++----- .../goalpanzi/exception/ErrorCode.java | 1 + .../mission/MissionMemberController.java | 3 +- .../mission/MissionMemberControllerDocs.java | 4 +- .../goalpanzi/schedule/AbstractJob.java | 30 +++++++++++ .../schedule/CustomAutomationJob.java | 10 ++++ .../goalpanzi/schedule/MissionStatusJob.java | 45 ++++++++++++++++ .../goalpanzi/schedule/SchedulerConfig.java | 37 ++++++++++++++ src/main/resources/application-dev.yml | 15 ++++++ src/main/resources/application-prod.yml | 16 +++++- src/main/resources/application.yml | 15 ++++++ .../V5__add_mission_member_status_col.sql | 5 ++ src/main/resources/logback-spring.xml | 11 +--- .../MissionMemberAcceptanceTest.java | 2 +- 21 files changed, 289 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/nexters/goalpanzi/schedule/AbstractJob.java create mode 100644 src/main/java/com/nexters/goalpanzi/schedule/CustomAutomationJob.java create mode 100644 src/main/java/com/nexters/goalpanzi/schedule/MissionStatusJob.java create mode 100644 src/main/java/com/nexters/goalpanzi/schedule/SchedulerConfig.java create mode 100644 src/main/resources/db/migration/V5__add_mission_member_status_col.sql diff --git a/build.gradle b/build.gradle index f868569e..bab728b5 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.3' implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation("org.springframework.boot:spring-boot-starter-quartz") testImplementation 'org.springframework.boot:spring-boot-starter-test' // swagger diff --git a/src/main/java/com/nexters/goalpanzi/application/mission/MissionMemberService.java b/src/main/java/com/nexters/goalpanzi/application/mission/MissionMemberService.java index 170d79e1..d8d443ab 100644 --- a/src/main/java/com/nexters/goalpanzi/application/mission/MissionMemberService.java +++ b/src/main/java/com/nexters/goalpanzi/application/mission/MissionMemberService.java @@ -1,6 +1,5 @@ package com.nexters.goalpanzi.application.mission; -import com.nexters.goalpanzi.application.mission.dto.request.MissionFilter; import com.nexters.goalpanzi.application.mission.dto.response.MemberRankResponse; import com.nexters.goalpanzi.application.mission.dto.response.MissionDetailResponse; import com.nexters.goalpanzi.application.mission.dto.response.MissionsResponse; @@ -22,7 +21,6 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; -import java.util.Objects; @Transactional(readOnly = true) @RequiredArgsConstructor @@ -60,23 +58,22 @@ private void validateAlreadyJoin(final Member member, final Mission mission) { }); } - public MissionsResponse findAllByMemberId(final Long memberId, final List filter) { + public MissionsResponse findAllByMemberId(final Long memberId, final List filter) { Member member = memberRepository.getMember(memberId); - List missionMembers = missionMemberRepository.findAllWithMissionByMemberId(memberId) + List missionMembers = missionMemberRepository.findAllWithMissionByMemberId(memberId); + if (filter == null || filter.isEmpty()) { + return MissionsResponse.of(member, missionMembers); + } + + List filteredMissionMembers = missionMembers .stream() - .filter(it -> isMissionStatusMatching(filter, it.getMission())) + .filter(it -> isMissionStatusMatching(filter, it)) .toList(); - return MissionsResponse.of(member, missionMembers); + return MissionsResponse.of(member, filteredMissionMembers); } - private boolean isMissionStatusMatching(final List filters, final Mission mission) { - for (MissionFilter filter : filters) { - MissionStatus missionStatus = filter.toMissionStatus(); - if (missionStatus != null && Objects.equals(missionStatus, MissionStatus.fromMission(mission))) { - return true; - } - } - return filters.isEmpty(); + private boolean isMissionStatusMatching(final List filters, final MissionMember missionMember) { + return filters.contains(missionMember.getMissionStatus()); } @Transactional @@ -99,4 +96,17 @@ public MemberRankResponse getMissionRank(final Long missionId, final Long member return MemberRankResponse.from(memberRanks.getRankByMember(member)); } + + @Transactional + public void batchUpdateStatus() { + List missions = missionRepository.findAll(); + missions.forEach(mission -> { + List missionMembers = missionMemberRepository.findAllByMissionId(mission.getId()); + int memberCount = missionMembers.size(); + missionMembers + .forEach(missionMember -> { + missionMember.updateMissionStatus(mission, memberCount); + }); + }); + } } diff --git a/src/main/java/com/nexters/goalpanzi/application/mission/MissionService.java b/src/main/java/com/nexters/goalpanzi/application/mission/MissionService.java index f8ad37b3..26f2faf1 100644 --- a/src/main/java/com/nexters/goalpanzi/application/mission/MissionService.java +++ b/src/main/java/com/nexters/goalpanzi/application/mission/MissionService.java @@ -84,4 +84,9 @@ private void validateAuthority(final Long memberId, final Mission mission) { throw new ForbiddenException(ErrorCode.CANNOT_DELETE_MISSION); } } + + @Transactional + public void batchUpdate(final Long missionId) { + + } } diff --git a/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionResponse.java b/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionResponse.java index 64d81ffe..19607946 100644 --- a/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionResponse.java +++ b/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionResponse.java @@ -1,11 +1,14 @@ package com.nexters.goalpanzi.application.mission.dto.response; +import com.nexters.goalpanzi.domain.mission.MissionStatus; import io.swagger.v3.oas.annotations.media.Schema; public record MissionResponse( @Schema(description = "미션 ID", requiredMode = Schema.RequiredMode.REQUIRED) Long missionId, @Schema(description = "목표 행동", requiredMode = Schema.RequiredMode.REQUIRED) - String description + String description, + @Schema(description = "미션 상태", requiredMode = Schema.RequiredMode.REQUIRED) + MissionStatus missionStatus ) { } \ No newline at end of file diff --git a/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionsResponse.java b/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionsResponse.java index b932480b..ea6ebf5f 100644 --- a/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionsResponse.java +++ b/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionsResponse.java @@ -14,13 +14,14 @@ public record MissionsResponse( List missions ) { - public static MissionsResponse of(Member member, List missionVerifications) { + public static MissionsResponse of(Member member, List missionMembers) { return new MissionsResponse( new ProfileResponse(member.getNickname(), member.getCharacterType()), - missionVerifications.stream() + missionMembers.stream() .map(missionVerification -> new MissionResponse( missionVerification.getMission().getId(), - missionVerification.getMission().getDescription()) + missionVerification.getMission().getDescription(), + missionVerification.getMissionStatus()) ) .toList() ); diff --git a/src/main/java/com/nexters/goalpanzi/domain/mission/Mission.java b/src/main/java/com/nexters/goalpanzi/domain/mission/Mission.java index 9449e26a..790ed110 100644 --- a/src/main/java/com/nexters/goalpanzi/domain/mission/Mission.java +++ b/src/main/java/com/nexters/goalpanzi/domain/mission/Mission.java @@ -1,5 +1,6 @@ package com.nexters.goalpanzi.domain.mission; +import com.nexters.goalpanzi.common.time.TimeUtil; import com.nexters.goalpanzi.domain.common.BaseEntity; import com.nexters.goalpanzi.infrastructure.jpa.DaysOfWeekConverter; import jakarta.persistence.*; @@ -113,8 +114,11 @@ private void validateMission() { } public boolean isMissionPeriod() { - LocalDate today = LocalDate.now(); - return !today.isBefore(this.missionStartDate.toLocalDate()) && !today.isAfter(missionEndDate.toLocalDate()); + LocalDateTime missionStart = getMissionUploadStartDateTime(); + LocalDateTime missionEnd = getMissionUploadEndDateTime(); + + LocalDateTime today = LocalDateTime.now(); + return !today.isBefore(missionStart) && !today.isAfter(missionEnd); } public boolean isMissionDay() { @@ -131,6 +135,18 @@ public boolean isExpired() { return today.isAfter(missionEndDate.toLocalDate()); } + public LocalDateTime getMissionUploadStartDateTime() { + return TimeUtil.combineDateAndTime( + missionStartDate, TimeUtil.of(uploadStartTime) + ); + } + + public LocalDateTime getMissionUploadEndDateTime() { + return TimeUtil.combineDateAndTime( + missionEndDate, TimeUtil.of(uploadEndTime) + ); + } + @Override public boolean equals(final Object o) { if (this == o) return true; diff --git a/src/main/java/com/nexters/goalpanzi/domain/mission/MissionMember.java b/src/main/java/com/nexters/goalpanzi/domain/mission/MissionMember.java index bd2eef83..bbec6e95 100644 --- a/src/main/java/com/nexters/goalpanzi/domain/mission/MissionMember.java +++ b/src/main/java/com/nexters/goalpanzi/domain/mission/MissionMember.java @@ -4,6 +4,8 @@ import com.nexters.goalpanzi.domain.member.Member; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -19,7 +21,6 @@ import java.util.Objects; import static com.nexters.goalpanzi.exception.ErrorCode.CAN_NOT_JOIN_MISSION; -import static com.nexters.goalpanzi.exception.ErrorCode.EXCEED_MAX_PERSONNEL; @Entity @SQLRestriction("deleted_at is NULL") @@ -44,6 +45,13 @@ public class MissionMember extends BaseEntity { @Column(name = "verification_count") private Integer verificationCount; + @Column(name = "check_completed") + private Boolean checkCompleted; + + @Enumerated(EnumType.STRING) + @Column(name = "mission_status") + private MissionStatus missionStatus; + public MissionMember(final Member member, final Mission mission, final Integer verificationCount) { this.member = member; this.mission = mission; @@ -61,6 +69,13 @@ public void verify() { this.verificationCount++; } + public void updateMissionStatus( + final Mission mission, + final Integer currentMemberCount + ) { + missionStatus = MissionStatus.fromMission(mission, currentMemberCount, this); + } + @Override public boolean equals(final Object o) { if (this == o) return true; diff --git a/src/main/java/com/nexters/goalpanzi/domain/mission/MissionStatus.java b/src/main/java/com/nexters/goalpanzi/domain/mission/MissionStatus.java index 0c3d7d9d..f388d1fc 100644 --- a/src/main/java/com/nexters/goalpanzi/domain/mission/MissionStatus.java +++ b/src/main/java/com/nexters/goalpanzi/domain/mission/MissionStatus.java @@ -4,12 +4,23 @@ import lombok.Getter; import java.time.LocalDateTime; +import java.util.List; + +import static com.nexters.goalpanzi.exception.ErrorCode.UNKNOWN_MISSION; @Getter public enum MissionStatus { - PENDING("대기"), - ONGOING("진행중"), + // 미션 시작 전 + CREATED("생성"), + + // 미션 진행 기간, + CANCELED("취소"), + IN_PROGRESS("진행중"), + DELETED("삭제"), + + // 미션 종료일 이후 + PENDING_COMPLETION("종료 대기"), COMPLETED("완료"); private final String description; @@ -18,21 +29,35 @@ public enum MissionStatus { this.description = description; } - public static MissionStatus fromMission(final Mission mission) { + public static MissionStatus fromMission( + final Mission mission, + final Integer currentMemberCount, + final MissionMember missionMember + ) { LocalDateTime now = LocalDateTime.now(); - LocalDateTime missionStart = TimeUtil.combineDateAndTime( - mission.getMissionStartDate(), TimeUtil.of(mission.getUploadStartTime()) - ); - LocalDateTime missionEnd = TimeUtil.combineDateAndTime( - mission.getMissionEndDate(), TimeUtil.of(mission.getUploadEndTime()) - ); + LocalDateTime missionStart = mission.getMissionUploadStartDateTime(); + LocalDateTime missionEnd = mission.getMissionUploadEndDateTime(); if (now.isBefore(missionStart)) { - return PENDING; - } else if (now.isAfter(missionEnd)) { + return CREATED; + } + + if (mission.isMissionPeriod() && currentMemberCount <= 1) { + return CANCELED; + } + + if (mission.isMissionPeriod() && currentMemberCount > 1) { + return IN_PROGRESS; + } + + if (now.isAfter(missionEnd) && !missionMember.getCheckCompleted()) { + return PENDING_COMPLETION; + } + + if (now.isAfter(missionEnd) && missionMember.getCheckCompleted()) { return COMPLETED; - } else { - return ONGOING; } + + throw new IllegalArgumentException(UNKNOWN_MISSION.getMessage(mission, missionMember)); } } diff --git a/src/main/java/com/nexters/goalpanzi/exception/ErrorCode.java b/src/main/java/com/nexters/goalpanzi/exception/ErrorCode.java index 0e607cc7..8fc4432a 100644 --- a/src/main/java/com/nexters/goalpanzi/exception/ErrorCode.java +++ b/src/main/java/com/nexters/goalpanzi/exception/ErrorCode.java @@ -25,6 +25,7 @@ public enum ErrorCode { INVALID_INVITATION_CODE("초대코드가 올바르지 않습니다."), INVALID_UPLOAD_TIME_OF_DAY("올바르지 않은 미션 인증 업로드 시간대입니다."), CANNOT_DELETE_MISSION("미션 삭제 권한이 없습니다."), + UNKNOWN_MISSION("정의되지 않은 미션상태입니다."), // MISSION MEMBER ALREADY_EXISTS_MISSION_MEMBER("이미 참여한 미션입니다. [%s]"), diff --git a/src/main/java/com/nexters/goalpanzi/presentation/mission/MissionMemberController.java b/src/main/java/com/nexters/goalpanzi/presentation/mission/MissionMemberController.java index 3ac9239c..75068b6e 100644 --- a/src/main/java/com/nexters/goalpanzi/presentation/mission/MissionMemberController.java +++ b/src/main/java/com/nexters/goalpanzi/presentation/mission/MissionMemberController.java @@ -7,6 +7,7 @@ import com.nexters.goalpanzi.application.mission.dto.response.MissionsResponse; import com.nexters.goalpanzi.common.argumentresolver.LoginMemberId; import com.nexters.goalpanzi.domain.mission.InvitationCode; +import com.nexters.goalpanzi.domain.mission.MissionStatus; import com.nexters.goalpanzi.presentation.mission.dto.JoinMissionRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -30,7 +31,7 @@ public class MissionMemberController implements MissionMemberControllerDocs { @GetMapping("/mission-members/me") public ResponseEntity getMissions( @LoginMemberId final Long memberId, - @RequestParam(required = false, defaultValue = "PENDING,ONGOING") List filter + @RequestParam(required = false) List filter ) { return ResponseEntity.ok(missionMemberService.findAllByMemberId(memberId, filter)); } diff --git a/src/main/java/com/nexters/goalpanzi/presentation/mission/MissionMemberControllerDocs.java b/src/main/java/com/nexters/goalpanzi/presentation/mission/MissionMemberControllerDocs.java index bd06f16f..356fb5a1 100644 --- a/src/main/java/com/nexters/goalpanzi/presentation/mission/MissionMemberControllerDocs.java +++ b/src/main/java/com/nexters/goalpanzi/presentation/mission/MissionMemberControllerDocs.java @@ -1,10 +1,10 @@ package com.nexters.goalpanzi.presentation.mission; -import com.nexters.goalpanzi.application.mission.dto.request.MissionFilter; import com.nexters.goalpanzi.application.mission.dto.response.MemberRankResponse; import com.nexters.goalpanzi.application.mission.dto.response.MissionDetailResponse; import com.nexters.goalpanzi.application.mission.dto.response.MissionsResponse; import com.nexters.goalpanzi.common.argumentresolver.LoginMemberId; +import com.nexters.goalpanzi.domain.mission.MissionStatus; import com.nexters.goalpanzi.presentation.mission.dto.JoinMissionRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -21,7 +21,7 @@ public interface MissionMemberControllerDocs { @Operation(summary = "내가 참여한 미션 조회") ResponseEntity getMissions( @Parameter(hidden = true) @LoginMemberId final Long memberId, - @RequestParam(required = false) List filter + @RequestParam(required = false) List filter ); @Operation(summary = "미션 참여", description = "초대코드로 미션에 참여합니다.") diff --git a/src/main/java/com/nexters/goalpanzi/schedule/AbstractJob.java b/src/main/java/com/nexters/goalpanzi/schedule/AbstractJob.java new file mode 100644 index 00000000..03e0e220 --- /dev/null +++ b/src/main/java/com/nexters/goalpanzi/schedule/AbstractJob.java @@ -0,0 +1,30 @@ +package com.nexters.goalpanzi.schedule; + +import org.quartz.Job; +import org.quartz.JobBuilder; +import org.quartz.JobDetail; +import org.quartz.ScheduleBuilder; +import org.quartz.Trigger; +import org.quartz.TriggerBuilder; +import org.springframework.scheduling.quartz.QuartzJobBean; + +public abstract class AbstractJob extends QuartzJobBean implements Job { + + private static final String JOB_PREFIX = "MissionMateService-Job-"; + private static final String TRIGGER_PREFIX = "MissionMate-Trigger-"; + + public JobDetail getJobDetail() { + return JobBuilder.newJob(this.getClass()) + .withIdentity(JOB_PREFIX + this.getClass().getSimpleName()) + .build(); + } + + public Trigger getTrigger() { + return TriggerBuilder.newTrigger() + .withSchedule(getScheduleBuilder()) + .withIdentity(TRIGGER_PREFIX + this.getClass().getSimpleName()) + .build(); + } + + protected abstract ScheduleBuilder getScheduleBuilder(); +} diff --git a/src/main/java/com/nexters/goalpanzi/schedule/CustomAutomationJob.java b/src/main/java/com/nexters/goalpanzi/schedule/CustomAutomationJob.java new file mode 100644 index 00000000..1a0e39d2 --- /dev/null +++ b/src/main/java/com/nexters/goalpanzi/schedule/CustomAutomationJob.java @@ -0,0 +1,10 @@ +package com.nexters.goalpanzi.schedule; + +import org.quartz.Job; +import org.quartz.JobDetail; +import org.quartz.Trigger; + +public interface CustomAutomationJob extends Job { + Trigger getTrigger(); + JobDetail getJobDetail(); +} diff --git a/src/main/java/com/nexters/goalpanzi/schedule/MissionStatusJob.java b/src/main/java/com/nexters/goalpanzi/schedule/MissionStatusJob.java new file mode 100644 index 00000000..7e03b3e6 --- /dev/null +++ b/src/main/java/com/nexters/goalpanzi/schedule/MissionStatusJob.java @@ -0,0 +1,45 @@ +package com.nexters.goalpanzi.schedule; + +import com.nexters.goalpanzi.application.mission.MissionMemberService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.time.StopWatch; +import org.quartz.CronScheduleBuilder; +import org.quartz.CronTrigger; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import org.quartz.ScheduleBuilder; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@DisallowConcurrentExecution +@Component +public class MissionStatusJob extends AbstractJob implements CustomAutomationJob { + + private final MissionMemberService missionMemberService; + + @Override + protected ScheduleBuilder getScheduleBuilder() { + // 00:00, 06:00, 12:00, 18:00 마다 실행 + return CronScheduleBuilder.cronSchedule("0 0 */6 * * ?") + .withMisfireHandlingInstructionDoNothing(); + } + + @Override + protected void executeInternal(final JobExecutionContext context) { + log.info("MissionStatusJob started."); + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + + try { + missionMemberService.batchUpdateStatus(); + } catch (Exception e) { + log.error("Error occurred while executing MissionStatusJob", e); + } + + stopWatch.stop(); // 타이머 종료 + log.info("MissionStatusJob finished. Elapsed time: {} ms", stopWatch.getTime()); + } +} diff --git a/src/main/java/com/nexters/goalpanzi/schedule/SchedulerConfig.java b/src/main/java/com/nexters/goalpanzi/schedule/SchedulerConfig.java new file mode 100644 index 00000000..f1ecfca9 --- /dev/null +++ b/src/main/java/com/nexters/goalpanzi/schedule/SchedulerConfig.java @@ -0,0 +1,37 @@ +package com.nexters.goalpanzi.schedule; + +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.quartz.JobDetail; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Slf4j +@RequiredArgsConstructor +@Component +public class SchedulerConfig { + private final Scheduler scheduler; + private final List jobList; + + @PostConstruct + public void start() { + log.info("Scheduler Job 등록"); + try { + for (CustomAutomationJob job : jobList) { + JobDetail jobDetail = job.getJobDetail(); + if (scheduler.checkExists(jobDetail.getKey())) { + scheduler.deleteJob(jobDetail.getKey()); + } + scheduler.scheduleJob(jobDetail, job.getTrigger()); + } + scheduler.start(); + log.info("Scheduler Start"); + } catch (SchedulerException e) { + log.error("SchedulerException", e); + } + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index d30ba522..92fd8bc4 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -29,6 +29,21 @@ spring: default: connectTimeout: 3_000 readTimeout: 3_000 + quartz: + job-store-type: jdbc + jdbc: + initialize-schema: never + schema: nexters + properties: + org: + quartz: + scheduler: + instanceId: AUTO + instanceName: quartzScheduler + jobStore: + driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate + tablePrefix: nexters.QRTZ_ + isClustered: true jwt: secret: ${JWT_SECRET} diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 9cda5322..6ec905ce 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -31,7 +31,21 @@ spring: default: connectTimeout: 3_000 readTimeout: 3_000 - + quartz: + job-store-type: jdbc + jdbc: + initialize-schema: never + schema: goalpanzi + properties: + org: + quartz: + scheduler: + instanceId: AUTO + instanceName: quartzScheduler + jobStore: + driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate + tablePrefix: goalpanzi.QRTZ_ + isClustered: true jwt: secret: ${JWT_SECRET} access-token: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b66b24eb..b88f6485 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -16,6 +16,21 @@ spring: servlet: multipart: max-file-size: 5MB + quartz: + job-store-type: jdbc + jdbc: + initialize-schema: never + schema: goalpanzi + properties: + org: + quartz: + scheduler: + instanceId: AUTO + instanceName: quartzScheduler + jobStore: + driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate + tablePrefix: goalpanzi.QRTZ_ + isClustered: true jwt: secret: ${JWT_SECRET} diff --git a/src/main/resources/db/migration/V5__add_mission_member_status_col.sql b/src/main/resources/db/migration/V5__add_mission_member_status_col.sql new file mode 100644 index 00000000..fbd1852a --- /dev/null +++ b/src/main/resources/db/migration/V5__add_mission_member_status_col.sql @@ -0,0 +1,5 @@ +alter table mission_member + add mission_status varchar(50) null; + +alter table mission_member + add check_completed boolean default false; \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 28fd1f3d..a9a1b8d5 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -33,17 +33,8 @@ - - - - - - - - - - + diff --git a/src/test/java/com/nexters/goalpanzi/acceptance/MissionMemberAcceptanceTest.java b/src/test/java/com/nexters/goalpanzi/acceptance/MissionMemberAcceptanceTest.java index f2e591c2..481d2d56 100644 --- a/src/test/java/com/nexters/goalpanzi/acceptance/MissionMemberAcceptanceTest.java +++ b/src/test/java/com/nexters/goalpanzi/acceptance/MissionMemberAcceptanceTest.java @@ -62,7 +62,7 @@ public class MissionMemberAcceptanceTest extends AcceptanceTest { MissionsResponse actual = RestAssured.given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) .header(HttpHeaders.AUTHORIZATION, BEARER + login.accessToken()) - .when().get("/api/mission-members/me?filter=PENDING") + .when().get("/api/mission-members/me?filter=") .then().log().all() .statusCode(HttpStatus.OK.value()) .extract() From 4501e745eda3ef069e123999d66b20caa05c568b Mon Sep 17 00:00:00 2001 From: Songyi Kim Date: Sun, 27 Oct 2024 14:46:05 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../goalpanzi/application/mission/MissionService.java | 5 ----- .../mission/dto/response/MissionsResponse.java | 8 ++++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/nexters/goalpanzi/application/mission/MissionService.java b/src/main/java/com/nexters/goalpanzi/application/mission/MissionService.java index 26f2faf1..f8ad37b3 100644 --- a/src/main/java/com/nexters/goalpanzi/application/mission/MissionService.java +++ b/src/main/java/com/nexters/goalpanzi/application/mission/MissionService.java @@ -84,9 +84,4 @@ private void validateAuthority(final Long memberId, final Mission mission) { throw new ForbiddenException(ErrorCode.CANNOT_DELETE_MISSION); } } - - @Transactional - public void batchUpdate(final Long missionId) { - - } } diff --git a/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionsResponse.java b/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionsResponse.java index ea6ebf5f..bebd0104 100644 --- a/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionsResponse.java +++ b/src/main/java/com/nexters/goalpanzi/application/mission/dto/response/MissionsResponse.java @@ -18,10 +18,10 @@ public static MissionsResponse of(Member member, List missionMemb return new MissionsResponse( new ProfileResponse(member.getNickname(), member.getCharacterType()), missionMembers.stream() - .map(missionVerification -> new MissionResponse( - missionVerification.getMission().getId(), - missionVerification.getMission().getDescription(), - missionVerification.getMissionStatus()) + .map(missionMember -> new MissionResponse( + missionMember.getMission().getId(), + missionMember.getMission().getDescription(), + missionMember.getMissionStatus()) ) .toList() );