Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.project.dorumdorum.domain.room.domain.service.RoomRequestService;
import com.project.dorumdorum.domain.room.domain.service.RoomService;
import com.project.dorumdorum.domain.roommate.domain.service.RoommateService;
import com.project.dorumdorum.domain.user.domain.entity.User;
import com.project.dorumdorum.domain.user.domain.service.UserService;
import com.project.dorumdorum.global.exception.RestApiException;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -34,10 +35,12 @@ public class ApplyRoomUseCase {
* - 지원 요청을 생성하고 1:1 채팅방 생성 이벤트를 발행
*/
public String execute(String userNo, String roomNo, JoinRoomRequest request) {
userService.validateExistsById(userNo);

User applicant = userService.findById(userNo);
Room room = roomService.findById(roomNo);

if (!applicant.getGender().equals(room.getGender())) {
throw new RestApiException(GENDER_MISMATCH);
Comment thread
ydking0911 marked this conversation as resolved.
}
if (roommateService.isUserRoommate(userNo, roomNo)) {
throw new RestApiException(CANNOT_APPLY_TO_OWN_ROOM);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@
import com.project.dorumdorum.domain.room.domain.service.RoomService;
import com.project.dorumdorum.domain.roommate.domain.entity.RoomRole;
import com.project.dorumdorum.domain.roommate.domain.service.RoommateService;
import com.project.dorumdorum.domain.user.domain.entity.Gender;
import com.project.dorumdorum.domain.user.domain.service.UserService;
import com.project.dorumdorum.global.exception.RestApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.project.dorumdorum.global.exception.code.status.RoomErrorStatus.ALREADY_JOINED_USER;

@Service
@Transactional
@RequiredArgsConstructor
public class CreateRoomUseCase {

private final UserService userService;
private final RoomService roomService;
private final RoommateService roommateService;
private final RoomRuleService roomRuleService;
Expand All @@ -29,7 +35,11 @@ public class CreateRoomUseCase {
* - 생성된 방 번호를 반환
*/
public String execute(String userNo, RoomCreateRequest request) {
Room room = roomService.create(userNo, request);
if (roommateService.existsByUserNo(userNo)) {
throw new RestApiException(ALREADY_JOINED_USER);
}
Gender gender = userService.findById(userNo).getGender();
Room room = roomService.create(userNo, gender, request);
Comment thread
ydking0911 marked this conversation as resolved.
roommateService.create(userNo, room, RoomRole.HOST);

RoomRule roomRule = roomRuleMapper.toRoomRule(room, request.rule());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.project.dorumdorum.domain.room.application.dto.request.ChecklistFilterRequest;
import com.project.dorumdorum.domain.room.application.dto.response.FindRoomsResponse;
import com.project.dorumdorum.domain.room.domain.service.RoomService;
import com.project.dorumdorum.domain.user.domain.entity.Gender;
import com.project.dorumdorum.domain.user.domain.service.UserService;
import com.project.dorumdorum.global.pagination.CursorCodec;
import com.project.dorumdorum.global.pagination.CursorPage;
import com.project.dorumdorum.global.pagination.CursorQueryParams;
Expand All @@ -18,6 +20,7 @@
@Transactional(readOnly = true)
public class FindRoomsUseCase {

private final UserService userService;
private final RoomService roomService;
private static final int LIMIT = 50;

Expand All @@ -26,10 +29,12 @@ public class FindRoomsUseCase {
* - 필터와 커서 기준으로 방 목록을 조회
* - 다음 페이지 커서를 포함한 결과를 반환
*/
public CursorPage<FindRoomsResponse> execute(ChecklistFilterRequest request) {
public CursorPage<FindRoomsResponse> execute(String userNo, ChecklistFilterRequest request) {
Gender gender = userService.findById(userNo).getGender();
CursorQueryParams params = PaginationHelper.prepareCursorQuery(request.cursor(), LIMIT);

List<FindRoomsResponse> responses = roomService.searchByCursor(
gender,
Comment thread
ydking0911 marked this conversation as resolved.
request,
params.cursorCreatedAt(),
params.cursorId(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.project.dorumdorum.domain.room.domain.entity;

import com.project.dorumdorum.domain.user.domain.entity.Gender;
import com.project.dorumdorum.global.common.BaseEntity;
import io.hypersistence.utils.hibernate.id.Tsid;
import jakarta.persistence.*;
Expand All @@ -12,8 +13,8 @@
@Builder
@Table(
indexes = {
@Index(name = "idx_room_status_created", columnList = "room_status, created_at, room_no"),
@Index(name = "idx_room_status_remaining_created", columnList = "room_status, remaining, created_at DESC, room_no DESC"),
@Index(name = "idx_room_status_gender_created", columnList = "room_status, gender, created_at DESC, room_no DESC"),
@Index(name = "idx_room_status_gender_remaining_created", columnList = "room_status, gender, remaining ASC, created_at DESC, room_no DESC"),
@Index(name = "idx_room_residence_period", columnList = "residence_period"),
@Index(name = "idx_room_host_user_no", columnList = "host_user_no")
}
Expand Down Expand Up @@ -49,6 +50,10 @@ public class Room extends BaseEntity {
@Column(nullable = false)
private String hostUserNo;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private Gender gender;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private ResidencePeriod residencePeriod; // 거주기간 (예: "학기(16주)", "반기(24주)", "계절학기")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.project.dorumdorum.domain.room.application.dto.request.ChecklistFilterRequest;
import com.project.dorumdorum.domain.room.application.dto.response.FindRoomsResponse;
import com.project.dorumdorum.domain.user.domain.entity.Gender;

import java.time.LocalDateTime;
import java.util.List;
Expand All @@ -10,6 +11,7 @@
public interface RoomQueryRepository {

List<FindRoomsResponse> findByCursor(
Gender gender,
ChecklistFilterRequest request,
LocalDateTime cursorCreatedAt,
String cursorId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.project.dorumdorum.domain.room.application.dto.response.FindRoomsResponse;
import com.project.dorumdorum.domain.room.domain.entity.Room;
import com.project.dorumdorum.domain.room.domain.repository.RoomRepository;
import com.project.dorumdorum.domain.user.domain.entity.Gender;
import com.project.dorumdorum.global.exception.RestApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -21,13 +22,14 @@ public class RoomService {

private final RoomRepository roomRepository;

public Room create(String userNo, RoomCreateRequest request) {
public Room create(String userNo, Gender gender, RoomCreateRequest request) {
Room entity = Room.builder()
.capacity(request.capacity())
.roomType(request.roomType())
.residencePeriod(request.residencePeriod())
.title(request.title())
.hostUserNo(userNo)
.gender(gender)
.build();

return roomRepository.save(entity);
Expand All @@ -44,13 +46,14 @@ public Room findByIdForUpdate(String roomNo) {
}

public List<FindRoomsResponse> searchByCursor(
Gender gender,
ChecklistFilterRequest request,
LocalDateTime cursorCreatedAt,
String cursorId,
Integer cursorRemaining,
int limitPlusOne
) {
return roomRepository.findByCursor(request, cursorCreatedAt, cursorId, cursorRemaining, limitPlusOne);
return roomRepository.findByCursor(gender, request, cursorCreatedAt, cursorId, cursorRemaining, limitPlusOne);
}

public FindRoomsResponse findMyRoom(String userNo) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.project.dorumdorum.domain.room.domain.entity.RoomType;
import com.project.dorumdorum.domain.room.domain.entity.RoomStatus;
import com.project.dorumdorum.domain.room.domain.repository.RoomQueryRepository;
import com.project.dorumdorum.domain.user.domain.entity.Gender;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQuery;
Expand Down Expand Up @@ -38,14 +39,15 @@ public class RoomRepositoryImpl implements RoomQueryRepository {

@Override
public List<FindRoomsResponse> findByCursor(
Gender gender,
ChecklistFilterRequest request,
LocalDateTime cursorCreatedAt,
String cursorId,
Integer cursorRemaining,
int limitPlusOne
) {
if (hasChecklistFilters(request)) {
return findByCursorWithLateral(request, cursorCreatedAt, cursorId, cursorRemaining, limitPlusOne);
return findByCursorWithLateral(gender, request, cursorCreatedAt, cursorId, cursorRemaining, limitPlusOne);
}

JPAQuery<FindRoomsResponse> q = query
Expand All @@ -67,6 +69,7 @@ public List<FindRoomsResponse> findByCursor(
.leftJoin(user).on(user.userNo.eq(room.hostUserNo))
.where(
room.roomStatus.eq(RoomStatus.CONFIRM_PENDING),
room.gender.eq(gender),
eqRoomType(request),
eqResidencePeriod(request),
eqCapacity(request),
Expand All @@ -85,6 +88,7 @@ public List<FindRoomsResponse> findByCursor(
}

private List<FindRoomsResponse> findByCursorWithLateral(
Gender gender,
ChecklistFilterRequest request,
LocalDateTime cursorCreatedAt,
String cursorId,
Expand Down Expand Up @@ -143,8 +147,10 @@ JOIN LATERAL (
LEFT JOIN users u
ON u.user_no = r.host_user_no
WHERE r.room_status = :roomStatus
AND r.gender = :gender
""");
params.put("roomStatus", RoomStatus.CONFIRM_PENDING.name());
params.put("gender", gender.name());
Comment thread
ydking0911 marked this conversation as resolved.

appendCondition(sql, params, "r.room_type", "roomType", enumName(request.roomType()));
appendCondition(sql, params, "r.residence_period", "residencePeriod", enumName(request.residencePeriod()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.project.dorumdorum.domain.room.application.dto.response.FindRoomsResponse;
import com.project.dorumdorum.domain.room.application.usecase.FindRoomsUseCase;
import com.project.dorumdorum.domain.room.ui.spec.FindRoomsApiSpec;
import com.project.dorumdorum.global.annotation.CurrentUser;
import org.springframework.http.ResponseEntity;
import com.project.dorumdorum.global.pagination.CursorPage;
import jakarta.validation.Valid;
Expand All @@ -19,8 +20,9 @@ public class FindRoomsController implements FindRoomsApiSpec {

@Override
public ResponseEntity<CursorPage<FindRoomsResponse>> loadAll(
@CurrentUser String userNo,
@Valid @RequestBody ChecklistFilterRequest request
) {
return ResponseEntity.ok(findRoomsUseCase.execute(request));
return ResponseEntity.ok(findRoomsUseCase.execute(userNo, request));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ public interface FindRoomsApiSpec {
@Operation(
summary = "방 목록 조회 API",
description = "체크리스트 및 방 조건을 기준으로 방 목록을 조회합니다. "
+ "커서 기반 페이지네이션을 지원합니다."
+ "커서 기반 페이지네이션을 지원합니다. "
+ "로그인한 사용자의 성별과 일치하는 방만 반환합니다."
)
@PostMapping("/api/rooms/search")
ResponseEntity<CursorPage<FindRoomsResponse>> loadAll(
@Parameter(hidden = true) String userNo,
@Parameter(description = "체크리스트 기반 방 검색 조건", required = true)
@Valid @RequestBody ChecklistFilterRequest request
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public enum RoomErrorStatus implements BaseCodeInterface {
CANNOT_KICK_SELF(HttpStatus.BAD_REQUEST, "ROOM012", "자기 자신은 강퇴할 수 없습니다."),
ROOM_FULL(HttpStatus.BAD_REQUEST, "ROOM014", "방 정원이 가득 찼습니다."),
INVALID_ROOM_CAPACITY(HttpStatus.BAD_REQUEST, "ROOM015", "현재 인원보다 적은 정원으로 변경할 수 없습니다."),
GENDER_MISMATCH(HttpStatus.FORBIDDEN, "ROOM016", "성별이 다른 방에는 신청할 수 없습니다."),
;

private final HttpStatus httpStatus;
Expand Down
7 changes: 5 additions & 2 deletions src/main/resources/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_device_user_device
CREATE UNIQUE INDEX IF NOT EXISTS uk_room_request_user_room_direction
ON room_request (user_no, room_no, direction);

DROP INDEX IF EXISTS idx_room_status_created;
DROP INDEX IF EXISTS idx_room_status_remaining_created;

CREATE INDEX IF NOT EXISTS idx_room_status_remaining_created
ON room (room_status, remaining, created_at DESC, room_no DESC);
CREATE INDEX IF NOT EXISTS idx_room_status_gender_created
ON room (room_status, gender, created_at DESC, room_no DESC);
CREATE INDEX IF NOT EXISTS idx_room_status_gender_remaining_created
ON room (room_status, gender, remaining ASC, created_at DESC, room_no DESC);
Comment thread
ydking0911 marked this conversation as resolved.

ALTER TABLE IF EXISTS chat_room
DROP CONSTRAINT IF EXISTS uk_chat_room_direct;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.project.dorumdorum.domain.room.domain.entity.RoomStatus;
import com.project.dorumdorum.domain.room.domain.entity.RoomType;
import com.project.dorumdorum.domain.room.infra.repository.RoomRepositoryImpl;
import com.project.dorumdorum.domain.user.domain.entity.Gender;
import com.querydsl.core.types.Expression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
Expand Down Expand Up @@ -35,6 +36,8 @@ class RoomRepositoryImplTest {
@Mock private JPAQueryFactory queryFactory;
@Mock private EntityManager entityManager;

private static final Gender DEFAULT_GENDER = Gender.MALE;

private ChecklistFilterRequest request(ChecklistFilterRequest.SortType sortType) {
return new ChecklistFilterRequest(
sortType, null, null, null, null,
Expand Down Expand Up @@ -67,7 +70,7 @@ void findByCursor_WhenRecruiting_FetchesWithLimit() {
);

List<FindRoomsResponse> result = repository.findByCursor(
request, cursorCreatedAt, "r1", 1, 51
DEFAULT_GENDER, request, cursorCreatedAt, "r1", 1, 51
);

assertThat(result).isEqualTo(expected);
Expand All @@ -89,7 +92,7 @@ void findByCursor_WithCreatedAtSortCursor_Fetches() {
ChecklistFilterRequest request = request(ChecklistFilterRequest.SortType.LATEST);

List<FindRoomsResponse> result = repository.findByCursor(
request, cursorCreatedAt, "r9", null, 11
DEFAULT_GENDER, request, cursorCreatedAt, "r9", null, 11
);

assertThat(result).isEmpty();
Expand All @@ -108,7 +111,7 @@ void findByCursor_WithNullCursorAndEmptyFilters_Fetches() {
ChecklistFilterRequest request = request(ChecklistFilterRequest.SortType.LATEST);

List<FindRoomsResponse> result = repository.findByCursor(
request, null, null, null, 7
DEFAULT_GENDER, request, null, null, null, 7
);

assertThat(result).isEmpty();
Expand All @@ -130,7 +133,7 @@ void findByCursor_WithNullSort_UsesDefaultOrderBranch() {
ChecklistFilterRequest request = request(null);

List<FindRoomsResponse> result = repository.findByCursor(
request, cursorCreatedAt, "r3", null, 5
DEFAULT_GENDER, request, cursorCreatedAt, "r3", null, 5
);

assertThat(result).isEmpty();
Expand All @@ -145,34 +148,11 @@ void findByCursor_WithChecklistFilters_UsesNativeLateralQuery() {
LocalDateTime createdAt = LocalDateTime.now();
ChecklistFilterRequest request = new ChecklistFilterRequest(
ChecklistFilterRequest.SortType.REMAINING,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null, null, null, null,
null, null, null, null, null, null, null, null, null, null,
null, null, null, null,
SmokingType.NON_SMOKER,
null,
null,
null,
null,
null,
null,
null,
null,
null
null, null, null, null, null, null, null, null, null
);

Object[] row = {
Expand All @@ -194,7 +174,7 @@ void findByCursor_WithChecklistFilters_UsesNativeLateralQuery() {
rows.add(row);
when(nativeQuery.getResultList()).thenReturn(rows);

List<FindRoomsResponse> result = repository.findByCursor(request, createdAt, "r1", 1, 51);
List<FindRoomsResponse> result = repository.findByCursor(DEFAULT_GENDER, request, createdAt, "r1", 1, 51);

assertThat(result).containsExactly(
new FindRoomsResponse("r1", RoomType.TYPE_1, 2, 1, createdAt,
Expand Down
Loading
Loading