Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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 @@ -4,6 +4,7 @@
import com.postsquad.scoup.web.error.controller.response.ErrorResponse;
import com.postsquad.scoup.web.group.controller.request.GroupCreationRequest;
import com.postsquad.scoup.web.group.controller.request.GroupModificationRequest;
import com.postsquad.scoup.web.group.controller.response.GroupReadAllResponses;
import com.postsquad.scoup.web.group.controller.request.GroupValidationRequest;
import com.postsquad.scoup.web.group.controller.response.GroupReadOneResponse;
import com.postsquad.scoup.web.group.controller.response.GroupValidationResponse;
Expand Down Expand Up @@ -71,4 +72,9 @@ public GroupValidationResponse validateGroupName(@Valid GroupValidationRequest g
@ResponseStatus(HttpStatus.NO_CONTENT)
public void leaveGroup(@PathVariable long groupId) {
}

@GetMapping
public GroupReadAllResponses readAll(@LoggedInUser User user) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일급 컬렉션 쓰셨네요!👍

return groupService.readAllByUser(user);
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package com.postsquad.scoup.web.group.controller.response;

import com.postsquad.scoup.web.image.controller.ImageResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Data
public class GroupBaseResponse {

private Long id;

// TODO: 필요한지 확인 필요
private ImageResponse image;

// TODO: 필요한지 확인 필요
private long memberCount;

private String name;

private String description;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.postsquad.scoup.web.group.controller.response;

import com.postsquad.scoup.web.group.domain.Group;
import lombok.*;

@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@Data
public class GroupReadAllResponse extends GroupBaseResponse {

@Builder
protected GroupReadAllResponse(Long id, String name, String description) {
super(id, name, description);
}

public static GroupReadAllResponse from(Group group) {
return GroupReadAllResponse.builder().id(group.getId()).name(group.getName()).description(group.getDescription()).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.postsquad.scoup.web.group.controller.response;

import lombok.*;

import java.util.List;

@NoArgsConstructor
@AllArgsConstructor(staticName = "from")
@Builder
@Data
public class GroupReadAllResponses {

private List<GroupReadAllResponse> groupReadAllResponses;
}

This file was deleted.

This file was deleted.

26 changes: 16 additions & 10 deletions src/main/java/com/postsquad/scoup/web/group/domain/Group.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,12 @@

import com.postsquad.scoup.web.common.BaseEntity;
import com.postsquad.scoup.web.group.controller.request.GroupModificationRequest;
import com.postsquad.scoup.web.schedule.domain.ConfirmedSchedule;
import com.postsquad.scoup.web.schedule.domain.Schedule;
import com.postsquad.scoup.web.schedule.domain.ScheduleCandidate;
import com.postsquad.scoup.web.user.domain.User;
import lombok.*;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.*;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
Expand All @@ -39,6 +30,14 @@ public class Group extends BaseEntity {
@OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
private final List<Schedule> schedules = new ArrayList<>();

@ManyToMany
@JoinTable(
name = "group_member",
joinColumns = @JoinColumn(name = "group_id"),
inverseJoinColumns = @JoinColumn(name = "user_id")
)
private final List<User> members = new ArrayList<>();

protected Group(String name, String description, User owner) {
this.name = name;
this.description = description;
Expand Down Expand Up @@ -72,4 +71,11 @@ public void addSchedule(Schedule schedule) {
public void addSchedules(List<Schedule> schedules) {
this.schedules.addAll(schedules);
}

public void addMember(User user) {
this.members.add(user);
if (!user.getJoinedGroups().contains(this)) {
user.getJoinedGroups().add(this);
}
Comment on lines +77 to +79
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

멤버를 추가하는게 아닌 것 같은데 맞나요?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Dae-Hwa 멤버를 User 타입으로 정의해 놓으셔서 그런 것 같아요!

}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.postsquad.scoup.web.group.mapper;

import com.postsquad.scoup.web.group.controller.request.GroupCreationRequest;
import com.postsquad.scoup.web.group.controller.response.GroupReadAllResponse;
import com.postsquad.scoup.web.group.domain.Group;
import com.postsquad.scoup.web.user.domain.User;
import org.mapstruct.Mapper;
Expand All @@ -14,4 +15,6 @@ public interface GroupMapper {

@Mapping(target = "owner", source = "owner")
Group map(GroupCreationRequest groupCreationRequest, User owner);

GroupReadAllResponse map(Group group);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

별도의 매퍼를 정의해야 할 것 같아요
파라미터가 Group으로 고정되면 오버로딩이 힘들 것 같습니다

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,36 @@
import com.postsquad.scoup.web.common.DefaultPostResponse;
import com.postsquad.scoup.web.group.controller.request.GroupCreationRequest;
import com.postsquad.scoup.web.group.controller.request.GroupModificationRequest;
import com.postsquad.scoup.web.group.controller.response.GroupReadAllResponses;
import com.postsquad.scoup.web.group.domain.Group;
import com.postsquad.scoup.web.group.exception.GroupNameAlreadyExistException;
import com.postsquad.scoup.web.group.exception.GroupNotFoundException;
import com.postsquad.scoup.web.group.mapper.GroupMapper;
import com.postsquad.scoup.web.group.repository.GroupRepository;
import com.postsquad.scoup.web.signin.exception.UnauthorizedUserException;
import com.postsquad.scoup.web.user.domain.User;
import com.postsquad.scoup.web.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class GroupService {

private final GroupRepository groupRepository;
private final UserService userService;

public DefaultPostResponse create(GroupCreationRequest groupCreationRequest, User user) {

if (groupRepository.existsByName(groupCreationRequest.getName())) {
throw new GroupNameAlreadyExistException(groupCreationRequest.getName());
}

Group group = GroupMapper.INSTANCE.map(groupCreationRequest, user);
User owner = userService.findById(user.getId());
Group group = GroupMapper.INSTANCE.map(groupCreationRequest, owner);
group.addMember(owner);

return DefaultPostResponse.builder().id(groupRepository.save(group).getId()).build();
}
Expand All @@ -42,4 +49,15 @@ public Long update(Long groupId, GroupModificationRequest groupModificationReque
}
return groupRepository.save(group.update(groupModificationRequest)).getId();
}

public GroupReadAllResponses readAllByUser(User user) {
User loggedInUser = userService.findById(user.getId());
return GroupReadAllResponses
.builder()
.groupReadAllResponses(
loggedInUser.getJoinedGroups().stream()
.map(GroupMapper.INSTANCE::map)
.collect(Collectors.toList()))
.build();
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/postsquad/scoup/web/user/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.postsquad.scoup.web.auth.OAuthType;
import com.postsquad.scoup.web.common.BaseEntity;
import com.postsquad.scoup.web.group.domain.Group;
import lombok.*;

import javax.persistence.*;
Expand Down Expand Up @@ -36,6 +37,9 @@ public class User extends BaseEntity {
@CollectionTable(name = "oauth_user", joinColumns = @JoinColumn(name = "user_id"))
private List<OAuthUser> oAuthUsers = new ArrayList<>();

@ManyToMany(mappedBy = "members")
private List<Group> joinedGroups = new ArrayList<>();

protected User(String nickname, String username, String email, String avatarUrl, String password, List<OAuthUser> oAuthUsers) {
this.nickname = nickname;
this.username = username;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.postsquad.scoup.web.user.service;

import com.postsquad.scoup.web.common.DefaultPostResponse;
import com.postsquad.scoup.web.signin.exception.UserNotFoundException;
import com.postsquad.scoup.web.user.controller.request.EmailValidationRequest;
import com.postsquad.scoup.web.user.controller.request.NicknameValidationRequest;
import com.postsquad.scoup.web.user.controller.request.SignUpRequest;
Expand Down Expand Up @@ -51,4 +52,8 @@ public NicknameValidationResponse validateNickname(NicknameValidationRequest nic
}
return NicknameValidationResponse.valueOf(false);
}

public User findById(Long id) {
return userRepository.findById(id).orElseThrow(() -> new UserNotFoundException(id));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.postsquad.scoup.web.group.controller.request.GroupModificationRequest;
import com.postsquad.scoup.web.group.controller.response.GroupReadOneResponse;
import com.postsquad.scoup.web.group.controller.response.GroupValidationResponse;
import com.postsquad.scoup.web.group.controller.response.GroupReadAllResponses;
import com.postsquad.scoup.web.group.domain.Group;
import com.postsquad.scoup.web.group.provider.*;
import io.restassured.RestAssured;
Expand Down Expand Up @@ -53,6 +54,21 @@ public class GroupAcceptanceTest extends AcceptanceTestBase {
.description("이미지")
);

private static final Snippet GROUP_READ_ALL_RESPONSE_FIELDS = responseFields(
fieldWithPath("group_read_all_responses[]")
.type(JsonFieldType.ARRAY)
.description("그룹 목록"),
fieldWithPath("group_read_all_responses[].id")
.type(JsonFieldType.NUMBER)
.description("그룹 id"),
fieldWithPath("group_read_all_responses[].name")
.type(JsonFieldType.STRING)
.description("그룹 이름"),
fieldWithPath("group_read_all_responses[].description")
.type(JsonFieldType.STRING)
.description("그룹 설명")
);

private static final Snippet GROUP_CREATION_REQUEST_FIELDS = requestFields(
fieldWithPathAndConstraints("name", GroupCreationRequest.class)
.type(JsonFieldType.STRING)
Expand Down Expand Up @@ -189,11 +205,12 @@ void createGroup(String description, GroupCreationRequest givenGroupCreationRequ
.as("그룹 생성: %s", description)
.usingRecursiveComparison()
.ignoringFields(ignoringFieldsForResponseWithId)
.ignoringFields("owner")
.ignoringFields("owner", "members")
.isEqualTo(expectedGroup);
then(actualGroup.getOwner())
.usingRecursiveComparison()
.ignoringFields(ignoringFieldsForResponseWithId)
.ignoringFields("joinedGroups")
.isEqualTo(expectedGroup.getOwner());
}
);
Expand Down Expand Up @@ -272,6 +289,7 @@ void validateGroupCreationRequest(String description, GroupCreationRequest given
void modifyGroup(String description, Long givenGroupId, GroupModificationRequest givenGroupModificationRequest, Group expectedGroup) {
// given
Group group = Group.builder().name("name").description("").owner(testUser).schedules(new ArrayList<>()).build();
group.addMember(testUser);
testEntityManager.persist(group);
String path = "/groups/{groupId}";
RequestSpecification givenRequest = RestAssured.given(this.spec)
Expand Down Expand Up @@ -303,7 +321,7 @@ void modifyGroup(String description, Long givenGroupId, GroupModificationRequest
.as("그룹 수정: %s", description)
.usingRecursiveComparison()
.ignoringFields(ignoringFieldsForResponseWithId)
.ignoringFields("owner")
.ignoringFields("owner", "members")
.isEqualTo(expectedGroup)
);
}
Expand Down Expand Up @@ -413,4 +431,45 @@ void leaveGroup() {

// TODO: id로 조회하여 검증
}

@ParameterizedTest
@ArgumentsSource(GroupReadAllProvider.class)
@DisplayName("사용자가 가입한 모든 그룹을 조회할 수 있다.")
void readGroup(String description, GroupReadAllResponses expectedGroupReadAllResponses) {
// given
Group group = Group.builder().name("name").description("").owner(testUser).schedules(new ArrayList<>()).build();
Group group2 = Group.builder().name("group2").description("group2").owner(testUser).schedules(new ArrayList<>()).build();
Comment on lines +440 to +441
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기는 Provider에 넣지 않으신 이유가 있나요?

group.addMember(testUser);
group2.addMember(testUser);
testEntityManager.persist(group);
testEntityManager.persist(group2);

String path = "/groups";
RequestSpecification givenRequest = RestAssured.given(this.spec)
.baseUri(BASE_URL)
.port(port)
.basePath("/api")
.contentType(ContentType.JSON)
.header("Accept-Language", "en-US")
.header("Authorization", TEST_TOKEN);
// when
Response actualResponse = givenRequest.when()
.accept(ContentType.JSON)
.filter(document(
DEFAULT_RESTDOCS_PATH,
GROUP_READ_ALL_RESPONSE_FIELDS
))
.log().all()
.get(path);

// then
actualResponse.then()
.log().all()
.statusCode(HttpStatus.OK.value());
then(actualResponse.as(GroupReadAllResponses.class))
.as("그룹 조회 : %s", description)
.usingRecursiveComparison()
.ignoringFields("groupReadAllResponses.id")
.isEqualTo(expectedGroupReadAllResponses);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.postsquad.scoup.web.group.provider;

import com.postsquad.scoup.web.group.controller.response.GroupReadAllResponse;
import com.postsquad.scoup.web.group.controller.response.GroupReadAllResponses;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;

import java.util.List;
import java.util.stream.Stream;

public class GroupReadAllProvider implements ArgumentsProvider {

@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {
return Stream.of(
Arguments.of(
"성공",
GroupReadAllResponses.builder()
.groupReadAllResponses(
List.of(
GroupReadAllResponse.builder().name("name").description("").build(),
GroupReadAllResponse.builder().name("group2").description("group2").build())
)
.build()
)
);
}
}
Loading