From bae97c7324994c82b76579072419541b1ff970f1 Mon Sep 17 00:00:00 2001 From: endorsement0912 Date: Fri, 25 Jul 2025 20:08:10 +0900 Subject: [PATCH 01/13] =?UTF-8?q?[EA3-134]=20fix=20:=20=EB=88=84=EB=9D=BD?= =?UTF-8?q?=EB=90=9C=20=EC=95=8C=EB=A6=BC=20=ED=83=80=EC=9E=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/grep/neogulcoder/domain/alram/type/AlarmType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/grep/neogulcoder/domain/alram/type/AlarmType.java b/src/main/java/grep/neogulcoder/domain/alram/type/AlarmType.java index 40abbcec..0133176b 100644 --- a/src/main/java/grep/neogulcoder/domain/alram/type/AlarmType.java +++ b/src/main/java/grep/neogulcoder/domain/alram/type/AlarmType.java @@ -1,5 +1,5 @@ package grep.neogulcoder.domain.alram.type; public enum AlarmType { - INVITE, STUDY_EXTEND, STUDY_EXTENSION_REMINDER + INVITE, STUDY_EXTEND, STUDY_EXTENSION_REMINDER, TIME_VOTE_REQUEST } From eb44c4f8c2fdf52839f28c126030305c633cdcda Mon Sep 17 00:00:00 2001 From: endorsement0912 Date: Fri, 25 Jul 2025 20:58:50 +0900 Subject: [PATCH 02/13] =?UTF-8?q?[EA3-134]=20chore=20:=20Time=20Vote=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/timevote/{entity => }/TimeVote.java | 2 +- .../domain/timevote/{entity => }/TimeVotePeriod.java | 2 +- .../domain/timevote/{entity => }/TimeVoteStat.java | 2 +- .../domain/timevote/controller/TimeVoteController.java | 1 - .../timevote/dto/request/TimeVoteCreateRequest.java | 4 ++-- .../timevote/dto/request/TimeVotePeriodCreateRequest.java | 2 +- .../timevote/dto/request/TimeVoteUpdateRequest.java | 4 ++-- .../domain/timevote/dto/response/TimeVoteResponse.java | 2 +- .../timevote/dto/response/TimeVoteStatResponse.java | 4 ++-- .../timevote/repository/TimeVotePeriodRepository.java | 2 +- .../domain/timevote/repository/TimeVoteRepository.java | 4 ++-- .../timevote/repository/TimeVoteStatQueryRepository.java | 8 ++++---- .../timevote/repository/TimeVoteStatRepository.java | 4 ++-- .../domain/timevote/service/TimeVoteService.java | 4 ++-- .../domain/timevote/service/TimeVoteStatService.java | 4 ++-- 15 files changed, 24 insertions(+), 25 deletions(-) rename src/main/java/grep/neogulcoder/domain/timevote/{entity => }/TimeVote.java (95%) rename src/main/java/grep/neogulcoder/domain/timevote/{entity => }/TimeVotePeriod.java (96%) rename src/main/java/grep/neogulcoder/domain/timevote/{entity => }/TimeVoteStat.java (96%) diff --git a/src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVote.java b/src/main/java/grep/neogulcoder/domain/timevote/TimeVote.java similarity index 95% rename from src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVote.java rename to src/main/java/grep/neogulcoder/domain/timevote/TimeVote.java index cdff9bb4..e5bd95e7 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVote.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/TimeVote.java @@ -1,4 +1,4 @@ -package grep.neogulcoder.domain.timevote.entity; +package grep.neogulcoder.domain.timevote; import grep.neogulcoder.global.entity.BaseEntity; import jakarta.persistence.Column; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVotePeriod.java b/src/main/java/grep/neogulcoder/domain/timevote/TimeVotePeriod.java similarity index 96% rename from src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVotePeriod.java rename to src/main/java/grep/neogulcoder/domain/timevote/TimeVotePeriod.java index c8a7e0bc..5e14800a 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVotePeriod.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/TimeVotePeriod.java @@ -1,4 +1,4 @@ -package grep.neogulcoder.domain.timevote.entity; +package grep.neogulcoder.domain.timevote; import grep.neogulcoder.global.entity.BaseEntity; import jakarta.persistence.Column; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVoteStat.java b/src/main/java/grep/neogulcoder/domain/timevote/TimeVoteStat.java similarity index 96% rename from src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVoteStat.java rename to src/main/java/grep/neogulcoder/domain/timevote/TimeVoteStat.java index fb146405..252eec02 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/entity/TimeVoteStat.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/TimeVoteStat.java @@ -1,4 +1,4 @@ -package grep.neogulcoder.domain.timevote.entity; +package grep.neogulcoder.domain.timevote; import grep.neogulcoder.global.entity.BaseEntity; import jakarta.persistence.Column; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/controller/TimeVoteController.java b/src/main/java/grep/neogulcoder/domain/timevote/controller/TimeVoteController.java index 5c7efe53..6d173ef2 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/controller/TimeVoteController.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/controller/TimeVoteController.java @@ -7,7 +7,6 @@ import grep.neogulcoder.domain.timevote.dto.response.TimeVoteResponse; import grep.neogulcoder.domain.timevote.dto.response.TimeVoteStatResponse; import grep.neogulcoder.domain.timevote.dto.response.TimeVoteSubmissionStatusResponse; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; import grep.neogulcoder.domain.timevote.service.TimeVotePeriodService; import grep.neogulcoder.domain.timevote.service.TimeVoteService; import grep.neogulcoder.domain.timevote.service.TimeVoteStatService; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVoteCreateRequest.java b/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVoteCreateRequest.java index 0bb2846c..e8324d86 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVoteCreateRequest.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVoteCreateRequest.java @@ -1,7 +1,7 @@ package grep.neogulcoder.domain.timevote.dto.request; -import grep.neogulcoder.domain.timevote.entity.TimeVote; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVote; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import java.time.LocalDateTime; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVotePeriodCreateRequest.java b/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVotePeriodCreateRequest.java index 99986fd9..1e484906 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVotePeriodCreateRequest.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVotePeriodCreateRequest.java @@ -1,6 +1,6 @@ package grep.neogulcoder.domain.timevote.dto.request; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import java.time.LocalDateTime; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVoteUpdateRequest.java b/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVoteUpdateRequest.java index 1c459296..d58f85dc 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVoteUpdateRequest.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/dto/request/TimeVoteUpdateRequest.java @@ -1,7 +1,7 @@ package grep.neogulcoder.domain.timevote.dto.request; -import grep.neogulcoder.domain.timevote.entity.TimeVote; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVote; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import java.time.LocalDateTime; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVoteResponse.java b/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVoteResponse.java index 028e3143..86142566 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVoteResponse.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVoteResponse.java @@ -1,6 +1,6 @@ package grep.neogulcoder.domain.timevote.dto.response; -import grep.neogulcoder.domain.timevote.entity.TimeVote; +import grep.neogulcoder.domain.timevote.TimeVote; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; import java.util.List; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVoteStatResponse.java b/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVoteStatResponse.java index 4de22a69..feabf262 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVoteStatResponse.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVoteStatResponse.java @@ -1,7 +1,7 @@ package grep.neogulcoder.domain.timevote.dto.response; -import grep.neogulcoder.domain.timevote.entity.TimeVoteStat; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVoteStat; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; import io.swagger.v3.oas.annotations.media.Schema; import java.util.Comparator; import lombok.Builder; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVotePeriodRepository.java b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVotePeriodRepository.java index 1bf549ca..44e6c1e5 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVotePeriodRepository.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVotePeriodRepository.java @@ -1,6 +1,6 @@ package grep.neogulcoder.domain.timevote.repository; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteRepository.java b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteRepository.java index 02e02b16..16ce126a 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteRepository.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteRepository.java @@ -1,7 +1,7 @@ package grep.neogulcoder.domain.timevote.repository; -import grep.neogulcoder.domain.timevote.entity.TimeVote; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVote; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteStatQueryRepository.java b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteStatQueryRepository.java index 0b68ded5..770e3569 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteStatQueryRepository.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteStatQueryRepository.java @@ -2,10 +2,10 @@ import com.querydsl.core.Tuple; import com.querydsl.jpa.impl.JPAQueryFactory; -import grep.neogulcoder.domain.timevote.entity.QTimeVote; -import grep.neogulcoder.domain.timevote.entity.QTimeVoteStat; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; -import grep.neogulcoder.domain.timevote.entity.TimeVoteStat; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVoteStat; +import grep.neogulcoder.domain.timevote.QTimeVote; +import grep.neogulcoder.domain.timevote.QTimeVoteStat; import jakarta.persistence.EntityManager; import java.time.LocalDateTime; import java.util.List; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteStatRepository.java b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteStatRepository.java index b0dcafc0..5e0a862d 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteStatRepository.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteStatRepository.java @@ -1,7 +1,7 @@ package grep.neogulcoder.domain.timevote.repository; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; -import grep.neogulcoder.domain.timevote.entity.TimeVoteStat; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVoteStat; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVoteService.java b/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVoteService.java index 2e9d8aba..9778158b 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVoteService.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVoteService.java @@ -8,8 +8,8 @@ import grep.neogulcoder.domain.timevote.dto.request.TimeVoteUpdateRequest; import grep.neogulcoder.domain.timevote.dto.response.TimeVoteResponse; import grep.neogulcoder.domain.timevote.dto.response.TimeVoteSubmissionStatusResponse; -import grep.neogulcoder.domain.timevote.entity.TimeVote; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVote; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; import grep.neogulcoder.domain.timevote.repository.TimeVotePeriodRepository; import grep.neogulcoder.domain.timevote.repository.TimeVoteRepository; import grep.neogulcoder.domain.timevote.repository.TimeVoteQueryRepository; diff --git a/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVoteStatService.java b/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVoteStatService.java index 7415c4c8..4165d563 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVoteStatService.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVoteStatService.java @@ -5,8 +5,8 @@ import grep.neogulcoder.domain.study.StudyMember; import grep.neogulcoder.domain.study.repository.StudyMemberRepository; import grep.neogulcoder.domain.timevote.dto.response.TimeVoteStatResponse; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; -import grep.neogulcoder.domain.timevote.entity.TimeVoteStat; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVoteStat; import grep.neogulcoder.domain.timevote.repository.TimeVotePeriodRepository; import grep.neogulcoder.domain.timevote.repository.TimeVoteStatQueryRepository; import grep.neogulcoder.domain.timevote.repository.TimeVoteStatRepository; From be3dd4826a2e299397f7d847443e48625db6bdc6 Mon Sep 17 00:00:00 2001 From: endorsement0912 Date: Fri, 25 Jul 2025 21:00:48 +0900 Subject: [PATCH 03/13] =?UTF-8?q?[EA3-134]=20refactor=20:=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=EC=9D=B4=20=EC=A0=84=EC=86=A1=EB=90=9C=20=ED=8C=80?= =?UTF-8?q?=EC=9B=90=20=EB=A9=A4=EB=B2=84=20ID=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/TimeVotePeriodResponse.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVotePeriodResponse.java b/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVotePeriodResponse.java index 1b024cc2..0616cea8 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVotePeriodResponse.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/dto/response/TimeVotePeriodResponse.java @@ -1,9 +1,8 @@ package grep.neogulcoder.domain.timevote.dto.response; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; -import java.util.List; import lombok.Builder; import lombok.Getter; @@ -20,23 +19,18 @@ public class TimeVotePeriodResponse { @Schema(description = "종료일", example = "2025-07-30T23:59:59") private LocalDateTime endDate; - @Schema(description = "알림이 전송된 팀원 멤버 ID 목록", example = "[11, 12, 13]") - private List notifiedMemberIds; - @Builder - private TimeVotePeriodResponse(Long studyId, LocalDateTime startDate, LocalDateTime endDate, List notifiedMemberIds) { + private TimeVotePeriodResponse(Long studyId, LocalDateTime startDate, LocalDateTime endDate) { this.studyId = studyId; this.startDate = startDate; this.endDate = endDate; - this.notifiedMemberIds = notifiedMemberIds; } - public static TimeVotePeriodResponse from(TimeVotePeriod timeVotePeriod, List notifiedMemberIds) { + public static TimeVotePeriodResponse from(TimeVotePeriod timeVotePeriod) { return TimeVotePeriodResponse.builder() .studyId(timeVotePeriod.getStudyId()) .startDate(timeVotePeriod.getStartDate()) .endDate(timeVotePeriod.getEndDate()) - .notifiedMemberIds(notifiedMemberIds) .build(); } } From 9ce5df2a5c4d602a33943e2d60c86fa492d9aad4 Mon Sep 17 00:00:00 2001 From: endorsement0912 Date: Fri, 25 Jul 2025 21:01:46 +0900 Subject: [PATCH 04/13] =?UTF-8?q?[EA3-134]=20refactor=20:=20=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4=EC=9D=98=20=EC=8A=A4=ED=84=B0=EB=94=94=20=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=20=EC=9D=BC=EC=A0=95=20=EC=A1=B0=EC=9C=A8=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=84=9C=EB=B9=84=EC=8A=A4=EB=A5=BC=20Event=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/alram/service/AlarmService.java | 17 ++++++++++ .../event/TimeVotePeriodCreatedEvent.java | 6 ++++ .../service/TimeVotePeriodService.java | 31 +++++-------------- 3 files changed, 30 insertions(+), 24 deletions(-) create mode 100644 src/main/java/grep/neogulcoder/domain/timevote/event/TimeVotePeriodCreatedEvent.java diff --git a/src/main/java/grep/neogulcoder/domain/alram/service/AlarmService.java b/src/main/java/grep/neogulcoder/domain/alram/service/AlarmService.java index d62165d8..50d770df 100644 --- a/src/main/java/grep/neogulcoder/domain/alram/service/AlarmService.java +++ b/src/main/java/grep/neogulcoder/domain/alram/service/AlarmService.java @@ -15,6 +15,7 @@ import grep.neogulcoder.domain.study.repository.StudyMemberQueryRepository; import grep.neogulcoder.domain.study.repository.StudyMemberRepository; import grep.neogulcoder.domain.study.repository.StudyRepository; +import grep.neogulcoder.domain.timevote.event.TimeVotePeriodCreatedEvent; import grep.neogulcoder.global.exception.business.BusinessException; import grep.neogulcoder.global.exception.business.NotFoundException; import grep.neogulcoder.global.provider.finder.MessageFinder; @@ -121,6 +122,22 @@ public void handleStudyExtensionReminderEvent(StudyExtensionReminderEvent event) ); } + @EventListener + public void handleTimeVotePeriodCreatedEvent(TimeVotePeriodCreatedEvent event) { + List members = studyMemberRepository.findAllByStudyIdAndActivatedTrue(event.studyId()); + + for (StudyMember member : members) { + if (!member.getUserId().equals(event.excludedUserId())) { + saveAlarm( + member.getUserId(), + AlarmType.TIME_VOTE_REQUEST, + DomainType.TIME_VOTE, + event.studyId() + ); + } + } + } + private Alarm findValidAlarm(Long alarmId) { return alarmRepository.findById(alarmId).orElseThrow(() -> new NotFoundException(AlarmErrorCode.ALARM_NOT_FOUND)); } diff --git a/src/main/java/grep/neogulcoder/domain/timevote/event/TimeVotePeriodCreatedEvent.java b/src/main/java/grep/neogulcoder/domain/timevote/event/TimeVotePeriodCreatedEvent.java new file mode 100644 index 00000000..ebe24113 --- /dev/null +++ b/src/main/java/grep/neogulcoder/domain/timevote/event/TimeVotePeriodCreatedEvent.java @@ -0,0 +1,6 @@ +package grep.neogulcoder.domain.timevote.event; + +public record TimeVotePeriodCreatedEvent( + Long studyId, + Long excludedUserId +) {} diff --git a/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVotePeriodService.java b/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVotePeriodService.java index a12f591d..ce1038e3 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVotePeriodService.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/service/TimeVotePeriodService.java @@ -1,15 +1,8 @@ package grep.neogulcoder.domain.timevote.service; -import static grep.neogulcoder.domain.timevote.exception.code.TimeVoteErrorCode.FORBIDDEN_TIME_VOTE_CREATE; -import static grep.neogulcoder.domain.timevote.exception.code.TimeVoteErrorCode.INVALID_TIME_VOTE_PERIOD; -import static grep.neogulcoder.domain.timevote.exception.code.TimeVoteErrorCode.STUDY_MEMBER_NOT_FOUND; -import static grep.neogulcoder.domain.timevote.exception.code.TimeVoteErrorCode.STUDY_NOT_FOUND; -import static grep.neogulcoder.domain.timevote.exception.code.TimeVoteErrorCode.TIME_VOTE_INVALID_DATE_RANGE; -import static grep.neogulcoder.domain.timevote.exception.code.TimeVoteErrorCode.TIME_VOTE_PERIOD_START_DATE_IN_PAST; +import static grep.neogulcoder.domain.timevote.exception.code.TimeVoteErrorCode.*; import grep.neogulcoder.domain.alram.service.AlarmService; -import grep.neogulcoder.domain.alram.type.AlarmType; -import grep.neogulcoder.domain.alram.type.DomainType; import grep.neogulcoder.domain.study.Study; import grep.neogulcoder.domain.study.StudyMember; import grep.neogulcoder.domain.study.enums.StudyMemberRole; @@ -17,7 +10,8 @@ import grep.neogulcoder.domain.study.repository.StudyRepository; import grep.neogulcoder.domain.timevote.dto.request.TimeVotePeriodCreateRequest; import grep.neogulcoder.domain.timevote.dto.response.TimeVotePeriodResponse; -import grep.neogulcoder.domain.timevote.entity.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.TimeVotePeriod; +import grep.neogulcoder.domain.timevote.event.TimeVotePeriodCreatedEvent; import grep.neogulcoder.domain.timevote.repository.TimeVotePeriodRepository; import grep.neogulcoder.domain.timevote.repository.TimeVoteRepository; import grep.neogulcoder.domain.timevote.repository.TimeVoteStatRepository; @@ -26,9 +20,8 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -44,6 +37,7 @@ public class TimeVotePeriodService { private final StudyMemberRepository studyMemberRepository; private final AlarmService alarmService; private final MessageFinder messageFinder; + private final ApplicationEventPublisher eventPublisher; public TimeVotePeriodResponse createTimeVotePeriodAndReturn(TimeVotePeriodCreateRequest request, Long studyId, Long userId) { StudyMember studyMember = getValidStudyMember(studyId, userId); @@ -62,19 +56,8 @@ public TimeVotePeriodResponse createTimeVotePeriodAndReturn(TimeVotePeriodCreate TimeVotePeriod savedPeriod = timeVotePeriodRepository.save(request.toEntity(studyId, adjustedEndDate)); getValidStudy(studyId); - messageFinder.findMessage(AlarmType.TIME_VOTE_REQUEST, DomainType.TIME_VOTE, studyId); - - List members = studyMemberRepository.findAllByStudyIdAndActivatedTrue(studyId); - List notifiedUserIds = new ArrayList<>(); - for (StudyMember member : members) { - if (!member.getUserId().equals(userId)) { - alarmService.saveAlarm(member.getUserId(), AlarmType.TIME_VOTE_REQUEST, - DomainType.TIME_VOTE, studyId); - notifiedUserIds.add(member.getId()); - } - } - - return TimeVotePeriodResponse.from(savedPeriod, notifiedUserIds); + eventPublisher.publishEvent(new TimeVotePeriodCreatedEvent(studyId, userId)); + return TimeVotePeriodResponse.from(savedPeriod); } public void deleteAllTimeVoteDate(Long studyId) { From 233a26b56ae65874784e9a01416b89f702347c07 Mon Sep 17 00:00:00 2001 From: Tokwasp Date: Fri, 25 Jul 2025 21:20:09 +0900 Subject: [PATCH 05/13] =?UTF-8?q?[EA3-163]=20fix:=20=EC=8A=A4=ED=84=B0?= =?UTF-8?q?=EB=94=94=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - category enum type NotBlank 적용으로 인한 문제 --- .../controller/dto/request/StudyPostUpdateRequest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/grep/neogulcoder/domain/studypost/controller/dto/request/StudyPostUpdateRequest.java b/src/main/java/grep/neogulcoder/domain/studypost/controller/dto/request/StudyPostUpdateRequest.java index 74a5d478..db91e6e6 100644 --- a/src/main/java/grep/neogulcoder/domain/studypost/controller/dto/request/StudyPostUpdateRequest.java +++ b/src/main/java/grep/neogulcoder/domain/studypost/controller/dto/request/StudyPostUpdateRequest.java @@ -3,6 +3,7 @@ import grep.neogulcoder.domain.studypost.Category; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Builder; import lombok.Getter; @@ -15,7 +16,7 @@ public class StudyPostUpdateRequest { private String title; @Schema(description = "카테고리: NOTICE(공지), FREE(자유)", example = "NOTICE") - @NotBlank + @NotNull private Category category; @Schema(description = "내용", example = "오늘은 각자 공부한 내용에 대해 발표가 있는 날 입니다!") From ea8390b83600c093cec374932d361ffe16b8a9ab Mon Sep 17 00:00:00 2001 From: Tokwasp Date: Fri, 25 Jul 2025 21:42:40 +0900 Subject: [PATCH 06/13] =?UTF-8?q?[EA3-138]=20refactor:=20=EB=AA=A8?= =?UTF-8?q?=EC=A7=91=EA=B8=80=20=EB=8C=93=EA=B8=80=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?URL=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 자원을 URI 표시 하는 것이 더 restful 하므로 변경 --- .../RecruitmentPostCommentController.java | 13 +++++++------ .../RecruitmentPostCommentSpecification.java | 2 +- .../dto/request/RecruitmentCommentSaveRequest.java | 5 +---- .../service/RecruitmentPostCommentService.java | 4 ++-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/RecruitmentPostCommentController.java b/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/RecruitmentPostCommentController.java index 3a5f332d..3d5c2ca0 100644 --- a/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/RecruitmentPostCommentController.java +++ b/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/RecruitmentPostCommentController.java @@ -10,21 +10,22 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; -@RequestMapping("/recruitment-posts/comments") +@RequestMapping("/recruitment-posts") @RequiredArgsConstructor @RestController public class RecruitmentPostCommentController implements RecruitmentPostCommentSpecification { private final RecruitmentPostCommentService commentService; - @PostMapping - public ApiResponse save(@RequestBody @Valid RecruitmentCommentSaveRequest request, + @PostMapping("/{post-id}/comments") + public ApiResponse save(@PathVariable("post-id") long postId, + @RequestBody @Valid RecruitmentCommentSaveRequest request, @AuthenticationPrincipal Principal userDetails) { - long commentId = commentService.save(request, userDetails.getUserId()); + long commentId = commentService.save(postId, request, userDetails.getUserId()); return ApiResponse.success(commentId); } - @PutMapping("/{comment-id}") + @PutMapping("/comments/{comment-id}") public ApiResponse update(@PathVariable("comment-id") long commentId, @RequestBody RecruitmentCommentUpdateRequest request, @AuthenticationPrincipal Principal userDetails) { @@ -32,7 +33,7 @@ public ApiResponse update(@PathVariable("comment-id") long commentId, return ApiResponse.noContent(); } - @DeleteMapping("/{comment-id}") + @DeleteMapping("/comments/{comment-id}") public ApiResponse delete(@PathVariable("comment-id") long commentId, @AuthenticationPrincipal Principal userDetails) { commentService.delete(commentId, userDetails.getUserId()); diff --git a/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/RecruitmentPostCommentSpecification.java b/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/RecruitmentPostCommentSpecification.java index 885b304d..e95ad90c 100644 --- a/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/RecruitmentPostCommentSpecification.java +++ b/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/RecruitmentPostCommentSpecification.java @@ -11,7 +11,7 @@ public interface RecruitmentPostCommentSpecification { @Operation(summary = "모집글 댓글 작성", description = "모집글에 대한 댓글을 작성 합니다.") - ApiResponse save(RecruitmentCommentSaveRequest request, Principal userDetails); + ApiResponse save(long postId, RecruitmentCommentSaveRequest request, Principal userDetails); @Operation(summary = "모집글 댓글 수정", description = "모집글에 대한 댓글을 수정 합니다.") ApiResponse update(long commentId, RecruitmentCommentUpdateRequest request, Principal userDetails); diff --git a/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/dto/request/RecruitmentCommentSaveRequest.java b/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/dto/request/RecruitmentCommentSaveRequest.java index f7a61f66..8cea399d 100644 --- a/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/dto/request/RecruitmentCommentSaveRequest.java +++ b/src/main/java/grep/neogulcoder/domain/recruitment/comment/controller/dto/request/RecruitmentCommentSaveRequest.java @@ -8,16 +8,13 @@ @Getter public class RecruitmentCommentSaveRequest { - @Schema(example = "2", description = "모집글 ID") - private long postId; - @Schema(example = "저도 참여 할래요!", description = "모집글 내용") private String content; private RecruitmentCommentSaveRequest() { } - public RecruitmentPostComment toEntity(RecruitmentPost post, long userId){ + public RecruitmentPostComment toEntity(RecruitmentPost post, long userId) { return RecruitmentPostComment.builder() .recruitmentPost(post) .userId(userId) diff --git a/src/main/java/grep/neogulcoder/domain/recruitment/comment/service/RecruitmentPostCommentService.java b/src/main/java/grep/neogulcoder/domain/recruitment/comment/service/RecruitmentPostCommentService.java index 36ad9303..8a9b0c77 100644 --- a/src/main/java/grep/neogulcoder/domain/recruitment/comment/service/RecruitmentPostCommentService.java +++ b/src/main/java/grep/neogulcoder/domain/recruitment/comment/service/RecruitmentPostCommentService.java @@ -25,8 +25,8 @@ public class RecruitmentPostCommentService { private final RecruitmentPostCommentQueryRepository commentQueryRepository; @Transactional - public long save(RecruitmentCommentSaveRequest request, long userId) { - RecruitmentPost post = postRepository.findPostBy(request.getPostId()) + public long save(long postId, RecruitmentCommentSaveRequest request, long userId) { + RecruitmentPost post = postRepository.findPostBy(postId) .orElseThrow(() -> new NotFoundException(NOT_FOUND)); return commentRepository.save(request.toEntity(post, userId)).getId(); From 602c6cb047e50f9499d6804dbbc109624de30a6e Mon Sep 17 00:00:00 2001 From: Tokwasp Date: Fri, 25 Jul 2025 21:53:47 +0900 Subject: [PATCH 07/13] =?UTF-8?q?[EA3-163]=20refactor:=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20ID=20=ED=95=84=EB=93=9C=EB=AA=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../studypost/controller/dto/response/CommentInfo.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/grep/neogulcoder/domain/studypost/controller/dto/response/CommentInfo.java b/src/main/java/grep/neogulcoder/domain/studypost/controller/dto/response/CommentInfo.java index f2b0321c..ff5ae35f 100644 --- a/src/main/java/grep/neogulcoder/domain/studypost/controller/dto/response/CommentInfo.java +++ b/src/main/java/grep/neogulcoder/domain/studypost/controller/dto/response/CommentInfo.java @@ -21,7 +21,7 @@ public class CommentInfo { private String profileImageUrl; @Schema(description = "댓글 ID", example = "100") - private long id; + private long commentId; @Schema(description = "댓글 내용", example = "정말 좋은 정보 감사합니다!") private String content; @@ -30,12 +30,12 @@ public class CommentInfo { private LocalDateTime createdAt; @QueryProjection - public CommentInfo(long userId, String nickname, String profileImageUrl, long id, + public CommentInfo(long userId, String nickname, String profileImageUrl, long commentId, String content, LocalDateTime createdAt) { this.userId = userId; this.nickname = nickname; this.profileImageUrl = profileImageUrl; - this.id = id; + this.commentId = commentId; this.content = content; this.createdAt = createdAt; } From 75ec874e89cd8e8477bfc7a5d66d1c9bd73551ce Mon Sep 17 00:00:00 2001 From: pia01190 Date: Sat, 26 Jul 2025 12:19:45 +0900 Subject: [PATCH 08/13] =?UTF-8?q?[EA3-188]=20feature:=20=EB=82=B4=20?= =?UTF-8?q?=EC=8A=A4=ED=84=B0=EB=94=94=20=EC=8B=A0=EC=B2=AD=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20recruitmentPostId=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 --- .../dto/response/MyApplicationPagingResponse.java | 2 +- .../controller/dto/response/MyApplicationResponse.java | 8 ++++---- .../repository/ApplicationQueryRepository.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationPagingResponse.java b/src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationPagingResponse.java index c31b5a4b..9f652cfc 100644 --- a/src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationPagingResponse.java +++ b/src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationPagingResponse.java @@ -13,7 +13,7 @@ public class MyApplicationPagingResponse { @Schema( description = "내가 신청한 스터디 목록", example = "[{" + - "\"applicationId\": 1," + + "\"recruitmentPostId\": 1," + "\"name\": \"자바 스터디\"," + "\"leaderNickname\": \"너굴\"," + "\"capacity\": 4," + diff --git a/src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationResponse.java b/src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationResponse.java index 6bc046dc..eb380f83 100644 --- a/src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationResponse.java +++ b/src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationResponse.java @@ -12,8 +12,8 @@ @Getter public class MyApplicationResponse { - @Schema(description = "신청 번호", example = "1") - private Long applicationId; + @Schema(description = "모집글 번호", example = "1") + private Long recruitmentPostId; @Schema(description = "스터디 이름", example = "자바 스터디") private String name; @@ -49,9 +49,9 @@ public class MyApplicationResponse { private ApplicationStatus status; @QueryProjection - public MyApplicationResponse(Long applicationId, String name, String leaderNickname, int capacity, int currentCount, LocalDateTime startDate, + public MyApplicationResponse(Long recruitmentPostId, String name, String leaderNickname, int capacity, int currentCount, LocalDateTime startDate, String imageUrl,String introduction, Category category, StudyType studyType, boolean isRead, ApplicationStatus status) { - this.applicationId = applicationId; + this.recruitmentPostId = recruitmentPostId; this.name = name; this.leaderNickname = leaderNickname; this.capacity = capacity; diff --git a/src/main/java/grep/neogulcoder/domain/studyapplication/repository/ApplicationQueryRepository.java b/src/main/java/grep/neogulcoder/domain/studyapplication/repository/ApplicationQueryRepository.java index 6323b851..eccb16ad 100644 --- a/src/main/java/grep/neogulcoder/domain/studyapplication/repository/ApplicationQueryRepository.java +++ b/src/main/java/grep/neogulcoder/domain/studyapplication/repository/ApplicationQueryRepository.java @@ -72,7 +72,7 @@ public Page findReceivedApplicationsPaging(Long rec public Page findMyStudyApplicationsPaging(Pageable pageable, Long userId, ApplicationStatus status) { List applications = queryFactory .select(new QMyApplicationResponse( - studyApplication.id, + recruitmentPost.id, study.name, user.nickname, study.capacity, From 793161dca71e78c03917f86829a6b7a42474147e Mon Sep 17 00:00:00 2001 From: hyeunS-P Date: Sat, 26 Jul 2025 13:36:38 +0900 Subject: [PATCH 09/13] =?UTF-8?q?feature:=20=EC=95=8C=EB=A6=BC=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20=EC=97=94=EB=93=9C=ED=8F=AC?= =?UTF-8?q?=EC=9D=B8=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=9D=BD?= =?UTF-8?q?=EC=9D=8C=20=EC=97=AC=EB=B6=80=20=EB=B0=98=ED=99=98=20=EC=B6=94?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alram/controller/AlarmController.java | 11 ++- .../alram/controller/AlarmSpecification.java | 7 +- .../dto/response/AlarmResponse.java | 23 +++--- .../alram/repository/AlarmRepository.java | 1 + .../domain/alram/service/AlarmService.java | 70 ++++++++++++------- 5 files changed, 70 insertions(+), 42 deletions(-) diff --git a/src/main/java/grep/neogulcoder/domain/alram/controller/AlarmController.java b/src/main/java/grep/neogulcoder/domain/alram/controller/AlarmController.java index e3ee0ca7..0da4884c 100644 --- a/src/main/java/grep/neogulcoder/domain/alram/controller/AlarmController.java +++ b/src/main/java/grep/neogulcoder/domain/alram/controller/AlarmController.java @@ -21,14 +21,19 @@ public class AlarmController implements AlarmSpecification { private final AlarmService alarmService; @GetMapping("/my") - public ApiResponse> getAllAlarm( - @AuthenticationPrincipal Principal userDetails) { + public ApiResponse> getAllAlarms(@AuthenticationPrincipal Principal userDetails) { return ApiResponse.success(alarmService.getAllAlarms(userDetails.getUserId())); } + @GetMapping("/unchecked/my") + public ApiResponse> getAllUncheckedAlarm( + @AuthenticationPrincipal Principal userDetails) { + return ApiResponse.success(alarmService.getAllUncheckedAlarms(userDetails.getUserId())); + } + @PostMapping("/my/check/all") public ApiResponse checkAlarm(@AuthenticationPrincipal Principal userDetails) { - alarmService.checkAllAlarm(userDetails.getUserId()); + alarmService.checkAllAlarmWithoutInvite(userDetails.getUserId()); return ApiResponse.noContent(); } diff --git a/src/main/java/grep/neogulcoder/domain/alram/controller/AlarmSpecification.java b/src/main/java/grep/neogulcoder/domain/alram/controller/AlarmSpecification.java index a857f960..5eb2290a 100644 --- a/src/main/java/grep/neogulcoder/domain/alram/controller/AlarmSpecification.java +++ b/src/main/java/grep/neogulcoder/domain/alram/controller/AlarmSpecification.java @@ -11,8 +11,11 @@ @Tag(name = "Alarm", description = "알림 관련 API 명세") public interface AlarmSpecification { - @Operation(summary = "내 알림 목록 조회", description = "로그인한 사용자의 알림 목록을 조회합니다.") - ApiResponse> getAllAlarm(@AuthenticationPrincipal Principal userDetails); + @Operation(summary = "읽음 여부 관련 없이 내 전체 알림 목록 조회", description = "로그인한 사용자의 전체 알림 목록을 조회합니다.") + ApiResponse> getAllAlarms(@AuthenticationPrincipal Principal userDetails); + + @Operation(summary = "내 읽지 않은 알림 목록 조회", description = "로그인한 사용자의 읽지 않은 알림 목록을 조회합니다.") + ApiResponse> getAllUncheckedAlarm(@AuthenticationPrincipal Principal userDetails); @Operation(summary = "내 알림 전체 읽음 처리", description = "로그인한 사용자의 모든 알림을 읽음 처리합니다.") ApiResponse checkAlarm(@AuthenticationPrincipal Principal userDetails); diff --git a/src/main/java/grep/neogulcoder/domain/alram/controller/dto/response/AlarmResponse.java b/src/main/java/grep/neogulcoder/domain/alram/controller/dto/response/AlarmResponse.java index 98e96bf7..df200ed9 100644 --- a/src/main/java/grep/neogulcoder/domain/alram/controller/dto/response/AlarmResponse.java +++ b/src/main/java/grep/neogulcoder/domain/alram/controller/dto/response/AlarmResponse.java @@ -1,6 +1,5 @@ package grep.neogulcoder.domain.alram.controller.dto.response; -import grep.neogulcoder.domain.alram.entity.Alarm; import grep.neogulcoder.domain.alram.type.AlarmType; import grep.neogulcoder.domain.alram.type.DomainType; import lombok.Builder; @@ -21,26 +20,30 @@ public class AlarmResponse { private String message; + private boolean checked; + public static AlarmResponse toResponse(Long id, Long receiverUserId, AlarmType alarmType, DomainType domainType, - Long domainId, String message) { + Long domainId, String message, boolean checked) { return AlarmResponse.builder() - .id(id) - .receiverUserId(receiverUserId) - .alarmType(alarmType) - .domainType(domainType) - .domainId(domainId) - .message(message) - .build(); + .id(id) + .receiverUserId(receiverUserId) + .alarmType(alarmType) + .domainType(domainType) + .domainId(domainId) + .message(message) + .checked(checked) + .build(); } @Builder private AlarmResponse(Long id, Long receiverUserId, AlarmType alarmType, DomainType domainType, - Long domainId, String message) { + Long domainId, String message, boolean checked) { this.id = id; this.receiverUserId = receiverUserId; this.alarmType = alarmType; this.domainType = domainType; this.domainId = domainId; this.message = message; + this.checked = checked; } } diff --git a/src/main/java/grep/neogulcoder/domain/alram/repository/AlarmRepository.java b/src/main/java/grep/neogulcoder/domain/alram/repository/AlarmRepository.java index 7a03e15b..95e3196c 100644 --- a/src/main/java/grep/neogulcoder/domain/alram/repository/AlarmRepository.java +++ b/src/main/java/grep/neogulcoder/domain/alram/repository/AlarmRepository.java @@ -6,5 +6,6 @@ public interface AlarmRepository extends JpaRepository { List findAllByReceiverUserIdAndCheckedFalse(Long receiverUserId); + List findAllByReceiverUserId(Long receiverUserId); } diff --git a/src/main/java/grep/neogulcoder/domain/alram/service/AlarmService.java b/src/main/java/grep/neogulcoder/domain/alram/service/AlarmService.java index d62165d8..d9aed8ad 100644 --- a/src/main/java/grep/neogulcoder/domain/alram/service/AlarmService.java +++ b/src/main/java/grep/neogulcoder/domain/alram/service/AlarmService.java @@ -18,7 +18,9 @@ import grep.neogulcoder.global.exception.business.BusinessException; import grep.neogulcoder.global.exception.business.NotFoundException; import grep.neogulcoder.global.provider.finder.MessageFinder; + import java.util.List; + import lombok.RequiredArgsConstructor; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; @@ -44,33 +46,47 @@ public void saveAlarm(Long receiverId, AlarmType alarmType, DomainType domainTyp alarmRepository.save(Alarm.init(alarmType, receiverId, domainType, domainId, message)); } - public List getAllAlarms(Long receiverUserId) { + public List getAllUncheckedAlarms(Long receiverUserId) { return alarmRepository.findAllByReceiverUserIdAndCheckedFalse(receiverUserId).stream() - .map(alarm -> AlarmResponse.toResponse( - alarm.getId(), - alarm.getReceiverUserId(), - alarm.getAlarmType(), - alarm.getDomainType(), - alarm.getDomainId(), - alarm.getMessage())) - .toList(); + .map(alarm -> AlarmResponse.toResponse( + alarm.getId(), + alarm.getReceiverUserId(), + alarm.getAlarmType(), + alarm.getDomainType(), + alarm.getDomainId(), + alarm.getMessage(), + alarm.isChecked())) + .toList(); + } + + public List getAllAlarms(Long receiverUserId) { + return alarmRepository.findAllByReceiverUserId(receiverUserId).stream() + .map(alarm -> AlarmResponse.toResponse( + alarm.getId(), + alarm.getReceiverUserId(), + alarm.getAlarmType(), + alarm.getDomainType(), + alarm.getDomainId(), + alarm.getMessage(), + alarm.isChecked())) + .toList(); } @Transactional - public void checkAllAlarm(Long receiverUserId) { + public void checkAllAlarmWithoutInvite(Long receiverUserId) { List alarms = alarmRepository.findAllByReceiverUserIdAndCheckedFalse(receiverUserId); alarms.stream() - .filter(alarm -> alarm.getAlarmType() != AlarmType.INVITE) - .forEach(Alarm::checkAlarm); + .filter(alarm -> alarm.getAlarmType() != AlarmType.INVITE) + .forEach(Alarm::checkAlarm); } @EventListener public void handleStudyInviteEvent(StudyInviteEvent event) { saveAlarm( - event.targetUserId(), - AlarmType.INVITE, - DomainType.STUDY, - event.studyId() + event.targetUserId(), + AlarmType.INVITE, + DomainType.STUDY, + event.studyId() ); } @@ -82,7 +98,7 @@ public void acceptInvite(Long targetUserId, Long alarmId) { Alarm alarm = findValidAlarm(alarmId); Long studyId = alarm.getDomainId(); Study study = findValidStudy(studyId); - StudyMember.createMember(study,targetUserId); + StudyMember.createMember(study, targetUserId); alarm.checkAlarm(); } @@ -99,10 +115,10 @@ public void handleStudyExtendEvent(StudyExtendEvent event) { for (StudyMember member : members) { if (!member.isLeader()) { saveAlarm( - member.getUserId(), - AlarmType.STUDY_EXTEND, - DomainType.STUDY, - event.studyId() + member.getUserId(), + AlarmType.STUDY_EXTEND, + DomainType.STUDY, + event.studyId() ); } } @@ -111,13 +127,13 @@ public void handleStudyExtendEvent(StudyExtendEvent event) { @EventListener public void handleStudyExtensionReminderEvent(StudyExtensionReminderEvent event) { StudyMember leader = studyMemberRepository.findByStudyIdAndRoleAndActivatedTrue(event.studyId(), StudyMemberRole.LEADER) - .orElseThrow(() -> new BusinessException(STUDY_LEADER_NOT_FOUND)); + .orElseThrow(() -> new BusinessException(STUDY_LEADER_NOT_FOUND)); saveAlarm( - leader.getUserId(), - AlarmType.STUDY_EXTENSION_REMINDER, - DomainType.STUDY, - event.studyId() + leader.getUserId(), + AlarmType.STUDY_EXTENSION_REMINDER, + DomainType.STUDY, + event.studyId() ); } @@ -127,7 +143,7 @@ private Alarm findValidAlarm(Long alarmId) { private Study findValidStudy(Long studyId) { return studyRepository.findById(studyId) - .orElseThrow(() -> new NotFoundException(STUDY_NOT_FOUND)); + .orElseThrow(() -> new NotFoundException(STUDY_NOT_FOUND)); } private void validateParticipantStudyLimit(Long userId) { From b189682f81eb40ce72e347e81901cb5cda5399cf Mon Sep 17 00:00:00 2001 From: pia01190 Date: Sat, 26 Jul 2025 14:06:01 +0900 Subject: [PATCH 10/13] =?UTF-8?q?[EA3-188]=20fix:=20TimeVoteQueryRepositor?= =?UTF-8?q?y=20import=EB=AC=B8=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/timevote/repository/TimeVoteQueryRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteQueryRepository.java b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteQueryRepository.java index a45234f7..8fe1e292 100644 --- a/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteQueryRepository.java +++ b/src/main/java/grep/neogulcoder/domain/timevote/repository/TimeVoteQueryRepository.java @@ -7,7 +7,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import grep.neogulcoder.domain.study.QStudyMember; import grep.neogulcoder.domain.timevote.dto.response.TimeVoteSubmissionStatusResponse; -import grep.neogulcoder.domain.timevote.entity.QTimeVote; +import grep.neogulcoder.domain.timevote.QTimeVote; import grep.neogulcoder.domain.users.entity.QUser; import jakarta.persistence.EntityManager; import com.querydsl.core.Tuple; From 0bceb5fff3615dbca4a271f5f3f3fb5d64fa3535 Mon Sep 17 00:00:00 2001 From: Tokwasp Date: Sat, 26 Jul 2025 14:57:49 +0900 Subject: [PATCH 11/13] =?UTF-8?q?[EA3-190]=20feature:=20=EB=AA=A8=EC=A7=91?= =?UTF-8?q?=EA=B8=80=20=EB=8D=94=EB=AF=B8=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/data.sql | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 1b395143..270c6707 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -41,11 +41,11 @@ INSERT INTO study_member (study_id, user_id, role, participated, activated) VALU INSERT INTO study_member (study_id, user_id, role, participated, activated) VALUES (6, 9, 'MEMBER', FALSE, TRUE); -- [ recruitment_post ] -INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated) VALUES (3, 1, '자바 스터디 모집', '이펙티브 자바 공부하실분 구해요!!', 3, '2025-04-19', 'COMPLETE', true); -INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated) VALUES (2, 4, '면접 스터디 모집', '삼성 면접 1차 합격자 분들 같이 준비하실분들 찾습니다', 1, '2025-07-08', 'COMPLETE', true); -INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated) VALUES (5, 2, '호밀밭의 파수꾼 책 같이 읽으실분', '책 같이 읽고 의견을 공유 하실분을 찾고 있습니다!! 많은 참여 부탁드려요', 5, '2025-06-10', 'IN_PROGRESS', true); -INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated) VALUES (3, 5, '클라이밍 같이 하실분 모집 합니다', '클라이밍 좋아하시는 분들의 많은 관심 바랍니다!', 5, '2025-06-08', 'IN_PROGRESS', true); -INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated) VALUES (2, 3, '토익 스터디', '토익 고수들의 많은 참여 부탁 드립니다', 2, '2025-03-31', 'IN_PROGRESS', true); +INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated, created_date) VALUES (3, 1, '자바 스터디 모집', '이펙티브 자바 공부하실분 구해요!!', 3, '2025-04-19', 'COMPLETE', true, '2025-08-02 12:00:00'); +INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated, created_date) VALUES (2, 4, '면접 스터디 모집', '삼성 면접 1차 합격자 분들 같이 준비하실분들 찾습니다', 1, '2025-07-08', 'COMPLETE', true, '2025-08-11 12:00:00'); +INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated, created_date) VALUES (5, 2, '호밀밭의 파수꾼 책 같이 읽으실분', '책 같이 읽고 의견을 공유 하실분을 찾고 있습니다!! 많은 참여 부탁드려요', 5, '2025-06-10', 'IN_PROGRESS', true, '2025-09-02 12:00:00'); +INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated, created_date) VALUES (3, 5, '클라이밍 같이 하실분 모집 합니다', '클라이밍 좋아하시는 분들의 많은 관심 바랍니다!', 5, '2025-06-08', 'IN_PROGRESS', true, '2025-09-06 12:00:00'); +INSERT INTO recruitment_post (user_id, study_id, subject, content, recruitment_count, expired_date, status, activated, created_date) VALUES (2, 3, '토익 스터디', '토익 고수들의 많은 참여 부탁 드립니다', 2, '2025-03-31', 'IN_PROGRESS', true, '2025-07-16 12:00:00'); -- [ study_application ] INSERT INTO study_application (user_id, recruitment_post_id, application_reason, is_read, status, activated) VALUES (1, 1, '자바 스터디에 참여하고 싶습니다.', FALSE, 'APPLYING', TRUE); From 24490e3fec567c638887bcb68afeee5b49f0ee74 Mon Sep 17 00:00:00 2001 From: Tokwasp Date: Sat, 26 Jul 2025 14:59:12 +0900 Subject: [PATCH 12/13] =?UTF-8?q?[EA3-190]=20feature:=20=EB=AA=A8=EC=A7=91?= =?UTF-8?q?=EA=B8=80=20=ED=8E=98=EC=9D=B4=EC=A7=95=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EC=A0=84=EC=B2=B4=20=EA=B6=8C=ED=95=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grep/neogulcoder/global/config/security/SecurityConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/grep/neogulcoder/global/config/security/SecurityConfig.java b/src/main/java/grep/neogulcoder/global/config/security/SecurityConfig.java index 5599a514..c08ed123 100644 --- a/src/main/java/grep/neogulcoder/global/config/security/SecurityConfig.java +++ b/src/main/java/grep/neogulcoder/global/config/security/SecurityConfig.java @@ -78,6 +78,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http, ClientRegistra (requests) -> requests .requestMatchers("/auth/**", "/", "/api/users/signup", + "/recruitment-posts", "/oauth2/**", "/login/**", "/signup", From 2185f351d38707787de25ee9d0500c470236a5d5 Mon Sep 17 00:00:00 2001 From: pia01190 Date: Sat, 26 Jul 2025 15:44:37 +0900 Subject: [PATCH 13/13] =?UTF-8?q?[EA3-191]=20refactor:=20=EC=8A=A4?= =?UTF-8?q?=ED=84=B0=EB=94=94=20=EC=97=B0=EC=9E=A5=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EA=B0=92=20studyId=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/study/controller/StudyManagementController.java | 6 +++--- .../study/controller/StudyManagementSpecification.java | 2 +- .../domain/study/service/StudyManagementService.java | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/grep/neogulcoder/domain/study/controller/StudyManagementController.java b/src/main/java/grep/neogulcoder/domain/study/controller/StudyManagementController.java index 19f4cd6e..266b4173 100644 --- a/src/main/java/grep/neogulcoder/domain/study/controller/StudyManagementController.java +++ b/src/main/java/grep/neogulcoder/domain/study/controller/StudyManagementController.java @@ -49,11 +49,11 @@ public ApiResponse delegateLeader(@PathVariable("studyId") Long studyId, } @PostMapping("/extension") - public ApiResponse extendStudy(@PathVariable("studyId") Long studyId, + public ApiResponse extendStudy(@PathVariable("studyId") Long studyId, @RequestBody @Valid ExtendStudyRequest request, @AuthenticationPrincipal Principal userDetails) { - studyManagementService.extendStudy(studyId, request, userDetails.getUserId()); - return ApiResponse.noContent(); + Long extendStudyId = studyManagementService.extendStudy(studyId, request, userDetails.getUserId()); + return ApiResponse.success(extendStudyId); } @PostMapping("/extension/participations") diff --git a/src/main/java/grep/neogulcoder/domain/study/controller/StudyManagementSpecification.java b/src/main/java/grep/neogulcoder/domain/study/controller/StudyManagementSpecification.java index e15dc8ba..b808d6d1 100644 --- a/src/main/java/grep/neogulcoder/domain/study/controller/StudyManagementSpecification.java +++ b/src/main/java/grep/neogulcoder/domain/study/controller/StudyManagementSpecification.java @@ -27,7 +27,7 @@ public interface StudyManagementSpecification { ApiResponse delegateLeader(Long studyId, DelegateLeaderRequest request, Principal userDetails); @Operation(summary = "스터디 연장", description = "스터디장이 스터디를 연장합니다.") - ApiResponse extendStudy(Long studyId, ExtendStudyRequest request, Principal userDetails); + ApiResponse extendStudy(Long studyId, ExtendStudyRequest request, Principal userDetails); @Operation(summary = "연장 스터디 참여", description = "스터디원이 연장된 스터디에 참여합니다.") ApiResponse registerExtensionParticipation(Long studyId, Principal userDetails); diff --git a/src/main/java/grep/neogulcoder/domain/study/service/StudyManagementService.java b/src/main/java/grep/neogulcoder/domain/study/service/StudyManagementService.java index 92f6f968..b9c302d5 100644 --- a/src/main/java/grep/neogulcoder/domain/study/service/StudyManagementService.java +++ b/src/main/java/grep/neogulcoder/domain/study/service/StudyManagementService.java @@ -120,7 +120,7 @@ public void deleteUserFromStudies(Long userId) { } @Transactional - public void extendStudy(Long studyId, ExtendStudyRequest request, Long userId) { + public Long extendStudy(Long studyId, ExtendStudyRequest request, Long userId) { Study originStudy = findValidStudy(studyId); StudyMember leader = findValidStudyMember(studyId, userId); @@ -141,6 +141,8 @@ public void extendStudy(Long studyId, ExtendStudyRequest request, Long userId) { studyMemberRepository.save(extendedLeader); eventPublisher.publishEvent(new StudyExtendEvent(originStudy.getId())); + + return extendedStudy.getId(); } @Transactional