Skip to content

Commit 9a318f0

Browse files
authored
[FEAT] 내 모임 목록 조회 구현
[FEAT] 내 모임 목록 조회 구현
2 parents 3dd2ff2 + 1345f65 commit 9a318f0

File tree

7 files changed

+506
-6
lines changed

7 files changed

+506
-6
lines changed

src/main/java/team/wego/wegobackend/group/application/dto/response/GroupImageItemResponse.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import team.wego.wegobackend.group.domain.entity.GroupImage;
44

55
public record GroupImageItemResponse(
6+
int sortOrder,
67
Long imageId440x240,
78
Long imageId100x100,
8-
int sortOrder,
99
String imageUrl440x240,
1010
String imageUrl100x100
1111
) {
@@ -25,9 +25,9 @@ public static GroupImageItemResponse from(
2525
String thumbUrlVal = (thumb != null) ? thumb.getImageUrl() : null;
2626

2727
return new GroupImageItemResponse(
28+
sortOrder,
2829
mainId,
2930
thumbId,
30-
sortOrder,
3131
mainUrlVal,
3232
thumbUrlVal
3333
);

src/main/java/team/wego/wegobackend/group/application/service/GroupService.java

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static team.wego.wegobackend.group.domain.entity.GroupUserStatus.ATTEND;
44
import static team.wego.wegobackend.group.domain.entity.GroupUserStatus.LEFT;
55

6+
import java.time.LocalDateTime;
67
import java.util.Comparator;
78
import java.util.List;
89
import java.util.Map;
@@ -28,6 +29,7 @@
2829
import team.wego.wegobackend.group.domain.entity.GroupRole;
2930
import team.wego.wegobackend.group.domain.entity.GroupTag;
3031
import team.wego.wegobackend.group.domain.entity.GroupUser;
32+
import team.wego.wegobackend.group.domain.entity.MyGroupType;
3133
import team.wego.wegobackend.group.domain.exception.GroupErrorCode;
3234
import team.wego.wegobackend.group.domain.exception.GroupException;
3335
import team.wego.wegobackend.group.domain.repository.GroupImageRepository;
@@ -567,4 +569,97 @@ public void deleteGroup(Long userId, Long groupId) {
567569

568570
groupRepository.delete(group);
569571
}
572+
573+
@Transactional(readOnly = true)
574+
public GetGroupListResponse getMyGroups(
575+
Long userId,
576+
String type,
577+
Long cursor,
578+
int size
579+
) {
580+
MyGroupType myGroupType = MyGroupType.from(type);
581+
582+
int pageSize = Math.max(1, Math.min(size, 50));
583+
584+
return switch (myGroupType) {
585+
case CURRENT -> getMyCurrentGroups(userId, cursor, pageSize);
586+
case MY_POST -> getMyPostGroups(userId, cursor, pageSize);
587+
case PAST -> getMyPastGroups(userId, cursor, pageSize);
588+
};
589+
}
590+
591+
private GetGroupListResponse getMyCurrentGroups(Long userId, Long cursor, int size) {
592+
LocalDateTime now = LocalDateTime.now();
593+
594+
// 지금은 ATTEND 만 사용, 나중에 LEFT 도 포함하려면 여기만 변경하면 됨
595+
List<String> statuses = List.of(ATTEND.name());
596+
597+
List<Group> groups = groupRepository.findCurrentGroupsByUser(
598+
userId,
599+
statuses,
600+
cursor,
601+
now,
602+
size + 1 // 다음 페이지 여부 판단용
603+
);
604+
605+
Long nextCursor = null;
606+
if (groups.size() > size) {
607+
Group lastExtra = groups.remove(size);
608+
nextCursor = lastExtra.getId();
609+
}
610+
611+
List<GroupListItemResponse> items = groups.stream()
612+
.map(this::toGroupListItemResponse)
613+
.toList();
614+
615+
return GetGroupListResponse.of(items, nextCursor);
616+
}
617+
618+
private GetGroupListResponse getMyPostGroups(Long userId, Long cursor, int size) {
619+
List<Group> groups = groupRepository.findMyPostGroupsByHost(
620+
userId,
621+
cursor,
622+
size + 1
623+
);
624+
625+
Long nextCursor = null;
626+
if (groups.size() > size) {
627+
Group lastExtra = groups.remove(size);
628+
nextCursor = lastExtra.getId();
629+
}
630+
631+
List<GroupListItemResponse> items = groups.stream()
632+
.map(this::toGroupListItemResponse)
633+
.toList();
634+
635+
return GetGroupListResponse.of(items, nextCursor);
636+
}
637+
638+
private GetGroupListResponse getMyPastGroups(Long userId, Long cursor, int size) {
639+
LocalDateTime now = LocalDateTime.now();
640+
641+
// 추후 LEFT 포함하고 싶으면 여기만 변경
642+
List<String> statuses = List.of(ATTEND.name());
643+
644+
List<Group> groups = groupRepository.findPastGroupsByUser(
645+
userId,
646+
statuses,
647+
cursor,
648+
now,
649+
size + 1
650+
);
651+
652+
Long nextCursor = null;
653+
if (groups.size() > size) {
654+
Group lastExtra = groups.remove(size);
655+
nextCursor = lastExtra.getId();
656+
}
657+
658+
List<GroupListItemResponse> items = groups.stream()
659+
.map(this::toGroupListItemResponse)
660+
.toList();
661+
662+
return GetGroupListResponse.of(items, nextCursor);
663+
}
570664
}
665+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package team.wego.wegobackend.group.domain.entity;
2+
3+
import lombok.AccessLevel;
4+
import lombok.Getter;
5+
import team.wego.wegobackend.group.domain.exception.GroupErrorCode;
6+
import team.wego.wegobackend.group.domain.exception.GroupException;
7+
8+
@Getter(AccessLevel.PUBLIC)
9+
public enum MyGroupType {
10+
CURRENT("current"),
11+
MY_POST("myPost"),
12+
PAST("past");
13+
14+
private final String value;
15+
16+
MyGroupType(String value) {
17+
this.value = value;
18+
}
19+
20+
public static MyGroupType from(String value) {
21+
if (value == null) {
22+
throw new GroupException(GroupErrorCode.MY_GROUP_TYPE_NOT_NULL);
23+
}
24+
return switch (value) {
25+
case "current" -> CURRENT;
26+
case "myPost" -> MY_POST;
27+
case "past" -> PAST;
28+
default -> throw new GroupException(GroupErrorCode.INVALID_MY_GROUP_TYPE, value);
29+
30+
31+
};
32+
}
33+
}

src/main/java/team/wego/wegobackend/group/domain/exception/GroupErrorCode.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ public enum GroupErrorCode implements ErrorCode {
2222
GROUP_CAPACITY_EXCEEDED(HttpStatus.BAD_REQUEST, "모임: 모임 최대 참가자 수를 초과했습니다. 모임 ID: %s"),
2323
NOT_ATTEND_GROUP(HttpStatus.BAD_REQUEST, "모임: 참여한 적 없거나 이미 나간 상태입니다. 모임 ID: %s 회원 ID: %s"),
2424
HOST_CANNOT_LEAVE_OWN_GROUP(HttpStatus.BAD_REQUEST, "모임: HOST는 나갈 수 없습니다. 모임 ID: %s 회원 ID: %s"),
25-
NO_PERMISSION_TO_UPDATE_GROUP(HttpStatus.FORBIDDEN, "모임: 해당 모임을 수정할 권한이 없습니다. 모임 ID: %s 회원 ID: %s"),
26-
INVALID_MAX_PARTICIPANTS_LESS_THAN_CURRENT(HttpStatus.BAD_REQUEST, "모임: 현재 참여 인원 수(%s)보다 작은 값으로 최대 인원을 줄일 수 없습니다."),
27-
NO_PERMISSION_TO_DELETE_GROUP(HttpStatus.UNAUTHORIZED, "모임: 삭제할 수 있는 권한이 없습니다.");
25+
NO_PERMISSION_TO_UPDATE_GROUP(HttpStatus.FORBIDDEN,
26+
"모임: 해당 모임을 수정할 권한이 없습니다. 모임 ID: %s 회원 ID: %s"),
27+
INVALID_MAX_PARTICIPANTS_LESS_THAN_CURRENT(HttpStatus.BAD_REQUEST,
28+
"모임: 현재 참여 인원 수(%s)보다 작은 값으로 최대 인원을 줄일 수 없습니다."),
29+
NO_PERMISSION_TO_DELETE_GROUP(HttpStatus.UNAUTHORIZED, "모임: 삭제할 수 있는 권한이 없습니다."),
30+
MY_GROUP_TYPE_NOT_NULL(HttpStatus.BAD_REQUEST, "모임: MyGroupType 값은 null일 수 없습니다."),
31+
INVALID_MY_GROUP_TYPE(HttpStatus.BAD_REQUEST, "지원하지 않는 MyGroupType: %s");
2832

2933
private final HttpStatus status;
3034
private final String message;

src/main/java/team/wego/wegobackend/group/domain/repository/GroupRepository.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package team.wego.wegobackend.group.domain.repository;
22

3+
import java.time.LocalDateTime;
34
import java.util.List;
45
import java.util.Optional;
56
import org.springframework.data.jpa.repository.JpaRepository;
@@ -33,4 +34,70 @@ List<Group> findGroupsWithKeywordAndCursor(
3334
@Param("cursor") Long cursor,
3435
@Param("limit") int limit
3536
);
37+
38+
/**
39+
* 내가 참여 중인 모임 (CURRENT)
40+
*/
41+
@Query(value = """
42+
SELECT DISTINCT g.*
43+
FROM v1_groups g
44+
JOIN v1_group_users gu ON gu.group_id = g.group_id
45+
WHERE g.deleted_at IS NULL
46+
AND gu.user_id = :userId
47+
AND gu.group_user_status IN (:statuses)
48+
AND (:cursor IS NULL OR g.group_id < :cursor)
49+
AND (g.end_time IS NULL OR g.end_time >= :now)
50+
ORDER BY g.group_id DESC
51+
LIMIT :limit
52+
""", nativeQuery = true)
53+
List<Group> findCurrentGroupsByUser(
54+
@Param("userId") Long userId,
55+
@Param("statuses") List<String> statuses,
56+
@Param("cursor") Long cursor,
57+
@Param("now") LocalDateTime now,
58+
@Param("limit") int limit
59+
);
60+
61+
/**
62+
* 과거에 참여했던 모임 (PAST)
63+
*/
64+
@Query(value = """
65+
SELECT DISTINCT g.*
66+
FROM v1_groups g
67+
JOIN v1_group_users gu ON gu.group_id = g.group_id
68+
WHERE g.deleted_at IS NULL
69+
AND gu.user_id = :userId
70+
AND gu.group_user_status IN (:statuses)
71+
AND (:cursor IS NULL OR g.group_id < :cursor)
72+
AND g.end_time IS NOT NULL
73+
AND g.end_time < :now
74+
ORDER BY g.group_id DESC
75+
LIMIT :limit
76+
""", nativeQuery = true)
77+
List<Group> findPastGroupsByUser(
78+
@Param("userId") Long userId,
79+
@Param("statuses") List<String> statuses,
80+
@Param("cursor") Long cursor,
81+
@Param("now") LocalDateTime now,
82+
@Param("limit") int limit
83+
);
84+
85+
/**
86+
* 내가 만든 모임 (MY_POST) – group_users 안타고 host 기준으로만
87+
*/
88+
@Query(value = """
89+
SELECT DISTINCT g.*
90+
FROM v1_groups g
91+
WHERE g.deleted_at IS NULL
92+
AND g.host_id = :userId
93+
AND (:cursor IS NULL OR g.group_id < :cursor)
94+
ORDER BY g.group_id DESC
95+
LIMIT :limit
96+
""", nativeQuery = true)
97+
List<Group> findMyPostGroupsByHost(
98+
@Param("userId") Long userId,
99+
@Param("cursor") Long cursor,
100+
@Param("limit") int limit
101+
);
36102
}
103+

src/main/java/team/wego/wegobackend/group/presentation/GroupController.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,20 @@ public ResponseEntity<ApiResponse<Void>> deleteGroup(
123123
.body(ApiResponse.success(HttpStatus.NO_CONTENT.value(), null));
124124
}
125125

126-
// 나의 모임 목록 조회
126+
127+
@GetMapping("/me")
128+
public ResponseEntity<ApiResponse<GetGroupListResponse>> getMyGroups(
129+
@RequestParam Long userId, // TODO: 나중에 인증 정보에서 꺼내기
130+
@RequestParam String type,
131+
@RequestParam(required = false) Long cursor,
132+
@RequestParam int size
133+
) {
134+
GetGroupListResponse response =
135+
groupService.getMyGroups(userId, type, cursor, size);
136+
137+
return ResponseEntity
138+
.status(HttpStatus.OK)
139+
.body(ApiResponse.success(HttpStatus.OK.value(), response));
140+
}
127141

128142
}

0 commit comments

Comments
 (0)