-
Notifications
You must be signed in to change notification settings - Fork 0
[refactor] RoomStatus 도입에 따른 방 만료 조건 수정 및 만료된 방 내부 게시글 조회만 가능하도록 수정 #300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
e57dc01
edc58dd
a41646a
4b21c69
231c256
1d8a507
a2297a1
0414562
a99e536
1f07fef
a06af47
ce1956d
5e43d56
ed6d55f
d87aa32
fbaef2e
f25d4f2
a4819f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| import konkuk.thip.room.application.port.out.dto.RoomParticipantQueryDto; | ||
| import konkuk.thip.room.application.port.out.dto.RoomQueryDto; | ||
| import konkuk.thip.room.domain.value.Category; | ||
| import konkuk.thip.room.domain.value.RoomStatus; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Repository; | ||
|
|
||
|
|
@@ -35,9 +36,9 @@ public class RoomQueryRepositoryImpl implements RoomQueryRepository { | |
| private final QRoomParticipantJpaEntity participant = QRoomParticipantJpaEntity.roomParticipantJpaEntity; | ||
|
|
||
| /** 모집중 + ACTIVE 공통 where */ | ||
| private BooleanBuilder recruitingActiveWhere(LocalDate today) { | ||
| private BooleanBuilder recruitingActiveWhere() { | ||
| BooleanBuilder where = new BooleanBuilder(); | ||
| where.and(room.startDate.after(today)); | ||
| where.and(room.roomStatus.eq(RoomStatus.RECRUITING)); | ||
| return where; | ||
| } | ||
|
|
||
|
|
@@ -91,10 +92,9 @@ private QRoomQueryDto projectionForRecruitingRoomSearch() { | |
| */ | ||
| @Override | ||
| public List<RoomQueryDto> findRecruitingRoomsOrderByStartDateAsc(String keyword, LocalDate lastStartDate, Long roomId, int pageSize) { | ||
| final LocalDate today = LocalDate.now(); | ||
| DateExpression<LocalDate> cursorExpr = room.startDate; // 커서 비교는 startDate | ||
|
|
||
| BooleanBuilder where = recruitingActiveWhere(today); | ||
| BooleanBuilder where = recruitingActiveWhere(); | ||
| applyKeyword(where, keyword); | ||
| applyCursorStartDateAsc(where, cursorExpr, lastStartDate, roomId); | ||
|
|
||
|
|
@@ -110,10 +110,9 @@ public List<RoomQueryDto> findRecruitingRoomsOrderByStartDateAsc(String keyword, | |
|
|
||
| @Override | ||
| public List<RoomQueryDto> findRecruitingRoomsWithCategoryOrderByStartDateAsc(String keyword, Category category, LocalDate lastStartDate, Long roomId, int pageSize) { | ||
| final LocalDate today = LocalDate.now(); | ||
| DateExpression<LocalDate> cursorExpr = room.startDate; | ||
|
|
||
| BooleanBuilder where = recruitingActiveWhere(today); | ||
| BooleanBuilder where = recruitingActiveWhere(); | ||
| applyCategory(where, category); | ||
| applyKeyword(where, keyword); | ||
| applyCursorStartDateAsc(where, cursorExpr, lastStartDate, roomId); | ||
|
|
@@ -130,9 +129,7 @@ public List<RoomQueryDto> findRecruitingRoomsWithCategoryOrderByStartDateAsc(Str | |
|
|
||
| @Override | ||
| public List<RoomQueryDto> findRecruitingRoomsOrderByMemberCountDesc(String keyword, Integer lastMemberCount, Long roomId, int pageSize) { | ||
| final LocalDate today = LocalDate.now(); | ||
|
|
||
| BooleanBuilder where = recruitingActiveWhere(today); | ||
| BooleanBuilder where = recruitingActiveWhere(); | ||
| applyKeyword(where, keyword); | ||
| applyCursorMemberCountDesc(where, lastMemberCount, roomId); | ||
|
|
||
|
|
@@ -148,9 +145,7 @@ public List<RoomQueryDto> findRecruitingRoomsOrderByMemberCountDesc(String keywo | |
|
|
||
| @Override | ||
| public List<RoomQueryDto> findRecruitingRoomsWithCategoryOrderByMemberCountDesc(String keyword, Category category, Integer lastMemberCount, Long roomId, int pageSize) { | ||
| final LocalDate today = LocalDate.now(); | ||
|
|
||
| BooleanBuilder where = recruitingActiveWhere(today); | ||
| BooleanBuilder where = recruitingActiveWhere(); | ||
| applyCategory(where, category); | ||
| applyKeyword(where, keyword); | ||
| applyCursorMemberCountDesc(where, lastMemberCount, roomId); | ||
|
|
@@ -174,7 +169,7 @@ public List<RoomRecruitingDetailViewResponse.RecommendRoom> findOtherRecruitingR | |
| .join(room.bookJpaEntity, book) | ||
| .where( | ||
| room.category.eq(category) | ||
| .and(room.startDate.after(LocalDate.now())) // 모집 마감 시각 > 현재 시각 | ||
| .and(room.roomStatus.eq(RoomStatus.RECRUITING)) // 모집 중인 방 | ||
| .and(room.roomId.ne(roomId))// 현재 방 제외 | ||
| .and(room.isPublic.isTrue()) // 공개방 만 | ||
| ) | ||
|
|
@@ -207,8 +202,9 @@ public List<RoomParticipantQueryDto> findHomeJoinedRoomsByUserPercentage( | |
| // 활동 기간 중인 방만: startDate ≤ today ≤ endDate | ||
| BooleanBuilder where = new BooleanBuilder(); | ||
| where.and(participant.userJpaEntity.userId.eq(userId)); | ||
| where.and(room.startDate.loe(LocalDate.now())); | ||
| where.and(room.endDate.goe(LocalDate.now())); | ||
| // where.and(room.startDate.loe(LocalDate.now())); | ||
| // where.and(room.endDate.goe(LocalDate.now())); | ||
| where.and(room.roomStatus.eq(RoomStatus.IN_PROGRESS)); // 활동 기간 중인 방만: IN_PROGRESS 상태 | ||
|
||
|
|
||
| // 커서 기반 추가 조건 | ||
| if (userPercentageCursor != null && startDateCursor != null && roomIdCursor != null) { | ||
|
|
@@ -252,7 +248,8 @@ public List<RoomQueryDto> findRecruitingRoomsUserParticipated( | |
| ) { | ||
| LocalDate today = LocalDate.now(); | ||
| BooleanExpression base = participant.userJpaEntity.userId.eq(userId) | ||
| .and(room.startDate.after(today)); // 유저가 참여한 방 && 모집중인 방 | ||
| // .and(room.startDate.after(today)); // 유저가 참여한 방 && 모집중인 방 | ||
| .and(room.roomStatus.eq(RoomStatus.RECRUITING)); // 유저가 참여한 방 && 모집중인 방 | ||
| DateExpression<LocalDate> cursorExpr = room.startDate; // 커서 비교는 startDate(= 모집 마감일 - 1일) | ||
| OrderSpecifier<?>[] orders = new OrderSpecifier<?>[]{ | ||
| cursorExpr.asc(), room.roomId.asc() | ||
|
|
@@ -268,8 +265,9 @@ public List<RoomQueryDto> findPlayingRoomsUserParticipated( | |
| ) { | ||
| LocalDate today = LocalDate.now(); | ||
| BooleanExpression base = participant.userJpaEntity.userId.eq(userId) | ||
| .and(room.startDate.loe(today)) | ||
| .and(room.endDate.goe(today)); // 유저가 참여한 방 && 현재 진행중인 방 | ||
| // .and(room.startDate.loe(today)) | ||
| // .and(room.endDate.goe(today)); // 유저가 참여한 방 && 현재 진행중인 방 | ||
| .and(room.roomStatus.eq(RoomStatus.IN_PROGRESS)); // 유저가 참여한 방 && 현재 진행중인 방 | ||
| DateExpression<LocalDate> cursorExpr = room.endDate; // 커서 비교는 endDate(= 진행 마감일) | ||
| OrderSpecifier<?>[] orders = new OrderSpecifier<?>[]{ | ||
| cursorExpr.asc(), room.roomId.asc() | ||
|
|
@@ -284,8 +282,10 @@ public List<RoomQueryDto> findPlayingAndRecruitingRoomsUserParticipated( | |
| Long userId, Integer priorityCursor, LocalDate dateCursor, Long roomIdCursor, int pageSize | ||
| ) { | ||
| LocalDate today = LocalDate.now(); | ||
| BooleanExpression playing = room.startDate.loe(today).and(room.endDate.goe(today)); | ||
| BooleanExpression recruiting = room.startDate.after(today); | ||
| // BooleanExpression playing = room.startDate.loe(today).and(room.endDate.goe(today)); | ||
| // BooleanExpression recruiting = room.startDate.after(today); | ||
| BooleanExpression playing = room.roomStatus.eq(RoomStatus.IN_PROGRESS); | ||
| BooleanExpression recruiting = room.roomStatus.eq(RoomStatus.RECRUITING); | ||
| BooleanExpression base = participant.userJpaEntity.userId.eq(userId) | ||
| .and(playing.or(recruiting)); // 유저가 참여한 방 && 현재 진행중인 방 + 모집중인 방 | ||
|
|
||
|
|
@@ -309,7 +309,8 @@ public List<RoomQueryDto> findExpiredRoomsUserParticipated( | |
| ) { | ||
| LocalDate today = LocalDate.now(); | ||
| BooleanExpression base = participant.userJpaEntity.userId.eq(userId) | ||
| .and(room.endDate.before(today)); // 유저가 참여한 방 && 만료된 방 | ||
| // .and(room.endDate.before(today)); // 유저가 참여한 방 && 만료된 방 | ||
| .and(room.roomStatus.eq(RoomStatus.EXPIRED)); // 유저가 참여한 방 && 만료된 방 | ||
|
|
||
| DateExpression<LocalDate> cursorExpr = room.endDate; | ||
| OrderSpecifier<?>[] orders = new OrderSpecifier<?>[]{ | ||
|
|
@@ -361,7 +362,8 @@ public List<RoomQueryDto> findRoomsByCategoryOrderByMemberCount(Category categor | |
| public List<RoomQueryDto> findRoomsByIsbnOrderByStartDateAsc(String isbn, LocalDate dateCursor, Long roomIdCursor, int pageSize) { | ||
| DateExpression<LocalDate> cursorExpr = room.startDate; // 커서 비교는 startDate(= 모집 마감일 - 1일) | ||
| BooleanExpression baseCondition = room.bookJpaEntity.isbn.eq(isbn) | ||
| .and(room.startDate.after(LocalDate.now())); // 모집 마감 시각 > 현재 시각 | ||
| // .and(room.startDate.after(LocalDate.now())); // 모집 마감 시각 > 현재 시각 | ||
| .and(room.roomStatus.eq(RoomStatus.RECRUITING)); // 모집중인 방 | ||
|
|
||
|
|
||
| if (dateCursor != null && roomIdCursor != null) { // 첫 페이지가 아닌 경우 | ||
|
|
@@ -389,7 +391,8 @@ public List<RoomQueryDto> findRoomsByIsbnOrderByStartDateAsc(String isbn, LocalD | |
|
|
||
| private BooleanExpression findDeadlinePopularRoomCondition(Category category, Long userId) { | ||
| return room.category.eq(category) | ||
| .and(room.startDate.after(LocalDate.now())) // 모집 마감 시각 > 현재 시각 | ||
| // .and(room.startDate.after(LocalDate.now())) // 모집 마감 시각 > 현재 시각 | ||
| .and(room.roomStatus.eq(RoomStatus.RECRUITING)) // 모집중인 방 | ||
| .and(room.isPublic.isTrue()) // 공개 방만 조회 | ||
| .and(userJoinedRoom(userId).not()); // 유저가 참여하지 않은 방만 조회 | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,11 +34,11 @@ public class RoomJoinService implements RoomJoinUseCase { | |
| public RoomJoinResult changeJoinState(RoomJoinCommand roomJoinCommand) { | ||
| RoomJoinType type = roomJoinCommand.type(); | ||
|
|
||
| // 방이 존재하지 않거나 만료된 경우 | ||
| // 방이 존재하지 않거나 모집기간이 만료된 경우 예외 처리 | ||
| Room room = roomCommandPort.findById(roomJoinCommand.roomId()) | ||
| .orElseThrow(() -> new BusinessException(ErrorCode.USER_CANNOT_JOIN_OR_CANCEL)); | ||
|
|
||
| validateRoom(room); | ||
| room.validateRoomRecruitExpired(); | ||
|
|
||
|
Comment on lines
+37
to
42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JOIN/CANCEL 공통 선검증이 모집기간 만료 체크로 고정되어 취소 흐름을 막을 수 있습니다 현재 changeJoinState 초반의 - // 방이 존재하지 않거나 모집기간이 만료된 경우 예외 처리
+ // 방이 존재하지 않거나 만료된 경우 예외 처리
Room room = roomCommandPort.findById(roomJoinCommand.roomId())
.orElseThrow(() -> new BusinessException(ErrorCode.USER_CANNOT_JOIN_OR_CANCEL));
-
-room.validateRoomRecruitExpired();
+// 공통: 만료(EXPIRED) 차단
+room.validateRoomExpired();
switch (type) {
- case JOIN -> handleJoin(roomJoinCommand, roomParticipantOptional, room);
+ case JOIN -> handleJoin(roomJoinCommand, roomParticipantOptional, room); // JOIN 내에서 모집기간 검증
case CANCEL -> handleCancel(roomJoinCommand, roomParticipantOptional, roomParticipantOptional, room);
}그리고 handleJoin 내부에서 모집기간 만료 검증을 수행하세요. private void handleJoin(RoomJoinCommand roomJoinCommand, Optional<RoomParticipant> participantOptional, Room room) {
+ // JOIN 전용: 모집기간(RECRUITING) 상태 검증
+ room.validateRoomRecruitExpired();🤖 Prompt for AI Agents
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p3 : 현재 api 는 방 참여 상태 변경 api 이므로 아직 모집중인 방에 대해서 유저가 참여신청 or 참여신청 취소 하는 것이 맞는거죠?? 코래의 답변은 저희 요구사항에 부합하지 않은 내용이 맞는지 확인차 여쭤봅니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @seongjunnoh 맞습니다! 제가 요구사항을 잘못 이해했네요. 현재 방 참여 상태 변경 API는 모집중인 방(RECRUITING)에서만 JOIN과 CANCEL이 모두 가능해야 하는 것이 맞습니다. 따라서 현재 구현이 올바릅니다: // 방이 존재하지 않거나 모집기간이 만료된 경우 예외 처리
Room room = roomCommandPort.findById(roomJoinCommand.roomId())
.orElseThrow(() -> new BusinessException(ErrorCode.USER_CANNOT_JOIN_OR_CANCEL));
room.validateRoomRecruitExpired(); // JOIN, CANCEL 모두 모집중인 방에서만 가능비즈니스 로직상 이유:
제가 이전에 제안한 내용은 틀렸으니 무시해 주세요. 현재 구현이 요구사항에 정확히 부합합니다. ✏️ Learnings added
🧠 Learnings used
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵 모집중인 방에 한해서만 참여, 참여취소가 가능합니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| Optional<RoomParticipant> roomParticipantOptional = roomParticipantCommandPort.findByUserIdAndRoomIdOptional(roomJoinCommand.userId(), roomJoinCommand.roomId()); | ||
|
|
||
|
|
@@ -93,11 +93,6 @@ private void handleJoin(RoomJoinCommand roomJoinCommand, Optional<RoomParticipan | |
| room.increaseMemberCount(); | ||
| } | ||
|
|
||
| private void validateRoom(Room room) { | ||
| room.validateRoomRecruitExpired(); | ||
| room.validateRoomExpired(); | ||
| } | ||
|
|
||
| // 방장이 참여 취소를 요청한 경우 | ||
| private void validateCancelable(RoomParticipant roomParticipant) { | ||
| if (roomParticipant.isHost()) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package konkuk.thip.room.application.service.validator; | ||
|
|
||
| import konkuk.thip.common.annotation.application.HelperService; | ||
| import konkuk.thip.room.application.port.out.RoomCommandPort; | ||
| import konkuk.thip.room.domain.Room; | ||
| import lombok.RequiredArgsConstructor; | ||
|
|
||
| @HelperService | ||
| @RequiredArgsConstructor | ||
| public class RoomValidator { | ||
|
|
||
| private final RoomCommandPort roomCommandPort; | ||
|
|
||
| public void validateRoomExpired(Long roomId) { | ||
| Room room = roomCommandPort.getByIdOrThrow(roomId); | ||
| room.validateRoomExpired(); | ||
| } | ||
|
Comment on lines
8
to
17
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM |
||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
붐업