From 83f44bc146069784d1b360022f8bd71f7ac75eb8 Mon Sep 17 00:00:00 2001 From: yumzen Date: Thu, 3 Oct 2024 20:02:59 +0900 Subject: [PATCH 1/3] =?UTF-8?q?#271=20fix:=20=ED=8C=80=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=8A=A4?= =?UTF-8?q?=EC=BC=80=EC=A4=84=EB=9F=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/repository/TeamRepositoryCustom.java | 6 ++++ .../team/repository/TeamRepositoryImpl.java | 24 +++++++++++++++ .../domain/team/service/TeamService.java | 18 +++++++++++ .../server/global/config/QuartzConfig.java | 30 +++++++++++++++++++ .../util/quartz/UpdateTeamStatusJob.java | 20 +++++++++++++ 5 files changed, 98 insertions(+) create mode 100644 src/main/java/com/gongjakso/server/global/config/QuartzConfig.java create mode 100644 src/main/java/com/gongjakso/server/global/util/quartz/UpdateTeamStatusJob.java diff --git a/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryCustom.java b/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryCustom.java index 731251e2..53c50f05 100644 --- a/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryCustom.java +++ b/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryCustom.java @@ -7,6 +7,8 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import java.time.LocalDate; +import java.util.List; import java.util.Optional; public interface TeamRepositoryCustom { @@ -26,4 +28,8 @@ public interface TeamRepositoryCustom { Page findScrapPagination(Long memberId, Pageable pageable); Boolean equalsLeaderIdAndMember(Portfolio portfolio, Member member); + + List findAllByRecruitFinishedAtAndStartedAtBeforeAndFinishedAtAfter(LocalDate today); + + List findAllByTeamStatusAndFinishedAtBefore(LocalDate today); } diff --git a/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryImpl.java b/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryImpl.java index 3e447643..5b077b12 100644 --- a/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryImpl.java +++ b/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryImpl.java @@ -16,6 +16,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -291,4 +292,27 @@ public Boolean equalsLeaderIdAndMember(Portfolio portfolio, Member member) { .where(booleanBuilder) .fetchFirst() != null; } + + public List findAllByRecruitFinishedAtAndStartedAtBeforeAndFinishedAtAfter(LocalDate today) { + return queryFactory + .selectFrom(team) + .where( + team.deletedAt.isNull(), + team.recruitFinishedAt.before(LocalDate.from(today)), + team.startedAt.before(LocalDate.from(today)), + team.finishedAt.after(LocalDate.from(today)) + ) + .fetch(); + } + + public List findAllByTeamStatusAndFinishedAtBefore(LocalDate today) { + return queryFactory + .selectFrom(team) + .where( + team.deletedAt.isNull(), + team.status.eq(TeamStatus.valueOf(TeamStatus.ACTIVE.name())), + team.finishedAt.before(LocalDate.from(today)) + ) + .fetch(); + } } diff --git a/src/main/java/com/gongjakso/server/domain/team/service/TeamService.java b/src/main/java/com/gongjakso/server/domain/team/service/TeamService.java index 768d539e..aa75d6a5 100644 --- a/src/main/java/com/gongjakso/server/domain/team/service/TeamService.java +++ b/src/main/java/com/gongjakso/server/domain/team/service/TeamService.java @@ -349,4 +349,22 @@ public void updatePassCount(Team team) { int passCount = applyRepository.countByTeamIdAndStatusAndDeletedAtIsNull(team.getId(), ApplyStatus.ACCEPTED); team.updatePassCount(passCount); } + + @Transactional + public void updateTeamsToActiveStatus() { + List activeTeams = teamRepository.findAllByRecruitFinishedAtAndStartedAtBeforeAndFinishedAtAfter(LocalDate.now()); + + if (!activeTeams.isEmpty()) { + activeTeams.forEach(team -> team.updateTeamStatus(TeamStatus.ACTIVE)); + teamRepository.saveAll(activeTeams); + } + + List finishedTeams = teamRepository.findAllByTeamStatusAndFinishedAtBefore(LocalDate.now()); + + if (!finishedTeams.isEmpty()) { + finishedTeams.forEach(team -> team.updateTeamStatus(TeamStatus.FINISHED)); + teamRepository.saveAll(finishedTeams); + } + } + } diff --git a/src/main/java/com/gongjakso/server/global/config/QuartzConfig.java b/src/main/java/com/gongjakso/server/global/config/QuartzConfig.java new file mode 100644 index 00000000..bf5f0a13 --- /dev/null +++ b/src/main/java/com/gongjakso/server/global/config/QuartzConfig.java @@ -0,0 +1,30 @@ +package com.gongjakso.server.global.config; + +import com.gongjakso.server.global.util.quartz.UpdateTeamStatusJob; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import org.quartz.*; +import org.springframework.context.annotation.Configuration; + +@Configuration +@RequiredArgsConstructor +public class QuartzConfig { + + private final Scheduler scheduler; + + @PostConstruct + public void scheduleDailyJob() throws SchedulerException { + JobDetail jobDetail = JobBuilder + .newJob(UpdateTeamStatusJob.class) + .withIdentity("updateTeamStatusJob", "teamStatusGroup") + .build(); + + Trigger trigger = TriggerBuilder + .newTrigger() + .withIdentity("updateTeamStatusTrigger", "teamStatusGroup") + .withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(0, 0)) + .build(); + + scheduler.scheduleJob(jobDetail, trigger); + } +} diff --git a/src/main/java/com/gongjakso/server/global/util/quartz/UpdateTeamStatusJob.java b/src/main/java/com/gongjakso/server/global/util/quartz/UpdateTeamStatusJob.java new file mode 100644 index 00000000..210e6b9c --- /dev/null +++ b/src/main/java/com/gongjakso/server/global/util/quartz/UpdateTeamStatusJob.java @@ -0,0 +1,20 @@ +package com.gongjakso.server.global.util.quartz; + +import com.gongjakso.server.domain.team.service.TeamService; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class UpdateTeamStatusJob implements Job { + + @Autowired + private TeamService teamService; + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + teamService.updateTeamsToActiveStatus(); + } +} \ No newline at end of file From 6e353d26082921b010675e11fcaba83d3e608eb8 Mon Sep 17 00:00:00 2001 From: yumzen Date: Thu, 3 Oct 2024 20:07:05 +0900 Subject: [PATCH 2/3] =?UTF-8?q?#271=20fix:=20=ED=8C=80=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=8A=A4?= =?UTF-8?q?=EC=BC=80=EC=A4=84=EB=9F=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 6b22d9da..d3b1b5e5 100644 --- a/build.gradle +++ b/build.gradle @@ -81,6 +81,9 @@ dependencies { // Json Type Parsing implementation 'com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations' + + // Quartz + implementation 'org.springframework.boot:spring-boot-starter-quartz:2.7.5' } From 7840cf8bcc168f7aaafda2bf3c95637244f53c0c Mon Sep 17 00:00:00 2001 From: yumzen Date: Sat, 5 Oct 2024 14:53:07 +0900 Subject: [PATCH 3/3] =?UTF-8?q?#275=20fix:=20=EC=B0=B8=EC=97=AC=ED=95=9C?= =?UTF-8?q?=20=ED=8C=80=20=EC=A1=B0=ED=9A=8C=20api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release-cd.yml | 10 +++--- .../team/dto/response/SimpleTeamRes.java | 31 ++++++++++++++++++ .../team/repository/TeamRepositoryImpl.java | 32 ++++++++++++++++--- 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release-cd.yml b/.github/workflows/release-cd.yml index 83895db6..aff7ea30 100644 --- a/.github/workflows/release-cd.yml +++ b/.github/workflows/release-cd.yml @@ -54,7 +54,7 @@ jobs: docker build -t ${{ secrets.DOCKERHUB_USERNAME}}/${{ secrets.DOCKERHUB_REPOSITORY}} ./ docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPOSITORY}} - # Docker Compose 및 deploy.sh 실행 + # Docker Compose - name: Docker Compose uses: appleboy/ssh-action@master with: @@ -63,8 +63,8 @@ jobs: key: ${{ secrets.SSH_PRIVATE_KEY }} script: | sudo docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }} + sudo docker-compose stop ${{ secrets.DOCKER_SERVICE_NAME }} + sudo docker-compose rm -f ${{ secrets.DOCKER_SERVICE_NAME }} sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPOSITORY}} - cd ~ - sudo chmod +x depoly.sh - ./depoly.sh -# sudo docker tag ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPOSITORY}} ${{ secrets.DOCKER_IMAGE_NAME }} + sudo docker tag ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPOSITORY}} ${{ secrets.DOCKER_IMAGE_NAME }} + sudo docker compose up -d \ No newline at end of file diff --git a/src/main/java/com/gongjakso/server/domain/team/dto/response/SimpleTeamRes.java b/src/main/java/com/gongjakso/server/domain/team/dto/response/SimpleTeamRes.java index d7f68e9f..e41235fe 100644 --- a/src/main/java/com/gongjakso/server/domain/team/dto/response/SimpleTeamRes.java +++ b/src/main/java/com/gongjakso/server/domain/team/dto/response/SimpleTeamRes.java @@ -36,6 +36,9 @@ public record SimpleTeamRes( @Schema(description = "지원 파트 정보 - 내가 지원한 팀에서는 지원한 포지션 하나만 반환") List recruitPart, + @Schema(description = "사용자가 지원한 파트") + String applyPart, + @Schema(description = "모집 마감일", example = "2024-12-31") LocalDate recruitFinishedAt, @@ -82,4 +85,32 @@ public static SimpleTeamRes of(Team team) { .viewCount(team.getViewCount()) .build(); } + + public static SimpleTeamRes of(Team team, String applyPart) { + int dDay = 0; + if (team.getRecruitFinishedAt() != null) { + dDay = (int) java.time.temporal.ChronoUnit.DAYS.between(LocalDate.now(), team.getRecruitFinishedAt()); + } + + List recruitPartList = (team.getRecruitPart() != null) ? team.getRecruitPart().stream() + .map(recruitPart -> recruitPart.position().getKoreanName()) + .toList() : null; + + return SimpleTeamRes.builder() + .id(team.getId()) + .title(team.getTitle()) + .leaderId(team.getMember().getId()) + .leaderName(team.getMember().getName()) + .contestId(team.getContest().getId()) + .status(team.getStatus().getDescription()) + .recruitPart(recruitPartList) + .applyPart(applyPart) + .recruitFinishedAt(team.getRecruitFinishedAt()) + .startedAt(team.getStartedAt()) + .finishedAt(team.getFinishedAt()) + .dDay(dDay) + .scrapCount(team.getScrapCount()) + .viewCount(team.getViewCount()) + .build(); + } } diff --git a/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryImpl.java b/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryImpl.java index 5b077b12..3fdaae1b 100644 --- a/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryImpl.java +++ b/src/main/java/com/gongjakso/server/domain/team/repository/TeamRepositoryImpl.java @@ -1,5 +1,8 @@ package com.gongjakso.server.domain.team.repository; +import com.gongjakso.server.domain.apply.entity.Apply; +import com.gongjakso.server.domain.apply.enumerate.ApplyStatus; +import com.gongjakso.server.domain.apply.repository.ApplyRepository; import com.gongjakso.server.domain.member.entity.Member; import com.gongjakso.server.domain.portfolio.entity.Portfolio; import com.gongjakso.server.domain.team.dto.response.SimpleTeamRes; @@ -30,6 +33,7 @@ public class TeamRepositoryImpl implements TeamRepositoryCustom { private final JPAQueryFactory queryFactory; + private final ApplyRepository applyRepository; public Optional findTeamById(Long id) { return Optional.ofNullable(queryFactory @@ -186,15 +190,26 @@ public Page findApplyPagination(Long memberId, Pageable pageable) } public Page findParticipatePagination(Long memberId, Pageable pageable) { - List teamStatusList = Arrays.asList(TeamStatus.RECRUITING, TeamStatus.EXTENSION, TeamStatus.CANCELED, TeamStatus.CLOSED); + List teamStatusList = Arrays.asList(TeamStatus.ACTIVE, TeamStatus.FINISHED); List teamList = queryFactory .select(team) .from(team) - .innerJoin(apply).on(apply.team.id.eq(team.id).and(apply.deletedAt.isNull())) + .leftJoin(apply).on(apply.team.id.eq(team.id) + .and(apply.member.id.eq(memberId)) + .and(apply.deletedAt.isNull())) .where( - team.status.in(teamStatusList), - team.deletedAt.isNull() + ( + team.member.id.eq(memberId) + .and(team.status.in(teamStatusList)) + .and(team.deletedAt.isNull()) + ) + .or( + apply.member.id.eq(memberId) + .and(apply.status.eq(ApplyStatus.ACCEPTED)) + .and(apply.team.status.in(teamStatusList)) + .and(apply.team.deletedAt.isNull()) + ) ) .orderBy(team.createdAt.desc()) .offset(pageable.getOffset()) @@ -202,7 +217,14 @@ public Page findParticipatePagination(Long memberId, Pageable pag .fetch(); List content = teamList.stream() - .map(SimpleTeamRes::of) + .map(team -> { + Optional apply = applyRepository + .findByTeamIdAndMemberIdAndDeletedAtIsNull(team.getId(), memberId); + + String applyPart = apply.map(Apply::getPart).orElse(null); + + return SimpleTeamRes.of(team, applyPart); + }) .toList(); Long total = queryFactory.select(team.count())