-
Notifications
You must be signed in to change notification settings - Fork 8
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
[BE] feat: 모집 중인 방 리스트 API 구현(#30) #68
Changes from 4 commits
9c61695
a61ee3a
488df13
868a02a
99e9c35
87eaf1b
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 |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package corea; | ||
|
||
import corea.matching.domain.Participation; | ||
import corea.matching.repository.ParticipationRepository; | ||
import corea.member.domain.Member; | ||
import corea.member.repository.MemberRepository; | ||
import corea.room.domain.Classification; | ||
import corea.room.domain.Room; | ||
import corea.room.domain.RoomStatus; | ||
import corea.room.repository.RoomRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.boot.ApplicationArguments; | ||
import org.springframework.boot.ApplicationRunner; | ||
import org.springframework.context.annotation.Profile; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Profile("test") | ||
@Component | ||
@Transactional | ||
@RequiredArgsConstructor | ||
public class DataInitializer implements ApplicationRunner { | ||
|
||
private final MemberRepository memberRepository; | ||
private final RoomRepository roomRepository; | ||
private final ParticipationRepository participationRepository; | ||
|
||
@Override | ||
public void run(ApplicationArguments args) { | ||
Member member1 = memberRepository.save( | ||
new Member("jcoding-play", null, "조경찬", | ||
"[email protected]", true, 5f)); | ||
Member member2 = memberRepository.save( | ||
new Member("ashsty", null, "박민아", | ||
null, false, 1.5f)); | ||
Member member3 = memberRepository.save( | ||
new Member("youngsu5582", null, "이영수", | ||
null, false, 4f)); | ||
Member member4 = memberRepository.save( | ||
new Member("hjk0761", null, "김현중", | ||
null, true, 3f)); | ||
Member member5 = memberRepository.save( | ||
new Member("chlwlstlf", null, "최진실", | ||
null, true, 2f)); | ||
Member member6 = memberRepository.save( | ||
new Member("00kang", null, "강다빈", | ||
null, true, 1f)); | ||
Member member7 = memberRepository.save( | ||
new Member("pp449", null, "이상엽", | ||
"[email protected]", true, 4.8f)); | ||
|
||
Room room1 = roomRepository.save( | ||
new Room("방 제목 1", "방 설명 1", 3, | ||
null, null, "TDD", | ||
1, 20, member1, | ||
LocalDateTime.of(2024, 12, 25, 12, 0), | ||
LocalDateTime.of(2024, 12, 30, 12, 0), | ||
Classification.BACKEND, RoomStatus.OPENED)); | ||
Room room2 = roomRepository.save( | ||
new Room("방 제목 2", "방 설명 2", 3, | ||
null, null, "TDD", | ||
1, 20, member2, | ||
LocalDateTime.of(2024, 12, 25, 12, 0), | ||
LocalDateTime.of(2024, 12, 30, 12, 0), | ||
Classification.BACKEND, RoomStatus.OPENED)); | ||
Room room3 = roomRepository.save( | ||
new Room("방 제목 3", "방 설명 3", 3, | ||
null, null, "TDD", | ||
1, 20, member3, | ||
LocalDateTime.of(2024, 12, 25, 12, 0), | ||
LocalDateTime.of(2024, 12, 30, 12, 0), | ||
Classification.ANDROID, RoomStatus.OPENED)); | ||
Room room4 = roomRepository.save( | ||
new Room("방 제목 4", "방 설명 4", 3, | ||
null, null, "TDD", | ||
1, 20, member4, | ||
LocalDateTime.of(2024, 12, 25, 12, 0), | ||
LocalDateTime.of(2024, 12, 30, 12, 0), | ||
Classification.ANDROID, RoomStatus.OPENED)); | ||
Room room5 = roomRepository.save( | ||
new Room("방 제목 5", "방 설명 5", 3, | ||
null, null, "TDD", | ||
1, 20, member5, | ||
LocalDateTime.of(2024, 12, 25, 12, 0), | ||
LocalDateTime.of(2024, 12, 30, 12, 0), | ||
Classification.FRONTEND, RoomStatus.OPENED)); | ||
Room room6 = roomRepository.save( | ||
new Room("방 제목 6", "방 설명 6", 3, | ||
null, null, "TDD", | ||
1, 20, member6, | ||
LocalDateTime.of(2024, 12, 25, 12, 0), | ||
LocalDateTime.of(2024, 12, 30, 12, 0), | ||
Classification.FRONTEND, RoomStatus.OPENED)); | ||
Room room7 = roomRepository.save( | ||
new Room("방 제목 7", "방 설명 7", 3, | ||
null, null, "TDD", | ||
1, 20, member7, | ||
LocalDateTime.of(2024, 12, 25, 12, 0), | ||
LocalDateTime.of(2024, 12, 30, 12, 0), | ||
Classification.FRONTEND, RoomStatus.OPENED)); | ||
|
||
participationRepository.save(new Participation(room1.getId(), member2.getId())); | ||
participationRepository.save(new Participation(room1.getId(), member3.getId())); | ||
|
||
participationRepository.save(new Participation(room2.getId(), member3.getId())); | ||
participationRepository.save(new Participation(room2.getId(), member4.getId())); | ||
|
||
participationRepository.save(new Participation(room3.getId(), member4.getId())); | ||
participationRepository.save(new Participation(room3.getId(), member5.getId())); | ||
|
||
participationRepository.save(new Participation(room4.getId(), member5.getId())); | ||
participationRepository.save(new Participation(room4.getId(), member6.getId())); | ||
|
||
participationRepository.save(new Participation(room5.getId(), member6.getId())); | ||
participationRepository.save(new Participation(room5.getId(), member7.getId())); | ||
|
||
participationRepository.save(new Participation(room6.getId(), member1.getId())); | ||
participationRepository.save(new Participation(room6.getId(), member7.getId())); | ||
|
||
participationRepository.save(new Participation(room7.getId(), member1.getId())); | ||
participationRepository.save(new Participation(room7.getId(), member2.getId())); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package corea.auth.annotation; | ||
|
||
import io.swagger.v3.oas.annotations.Hidden; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(ElementType.PARAMETER) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Hidden() | ||
public @interface AccessedMember { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package corea.auth.resolver; | ||
|
||
import corea.auth.RequestHandler; | ||
import corea.auth.annotation.AccessedMember; | ||
import corea.member.domain.Member; | ||
import corea.member.repository.MemberRepository; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.core.MethodParameter; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.bind.support.WebDataBinderFactory; | ||
import org.springframework.web.context.request.NativeWebRequest; | ||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; | ||
import org.springframework.web.method.support.ModelAndViewContainer; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class AccessedMemberArgumentResolver implements HandlerMethodArgumentResolver { | ||
|
||
private final RequestHandler requestHandler; | ||
private final MemberRepository memberRepository; | ||
|
||
@Override | ||
public boolean supportsParameter(MethodParameter parameter) { | ||
return parameter.hasParameterAnnotation(AccessedMember.class); | ||
} | ||
|
||
@Override | ||
public Member resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, | ||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { | ||
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); | ||
|
||
return memberRepository.findByEmail(requestHandler.extract(request)) | ||
.orElse(null); | ||
} | ||
Comment on lines
+28
to
+35
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. 로그인하지 않은 사용자도 방 리스트를 조회할 수 있기 때문에 findByEmail로 찾을 수 없는 경우 null을 반환하도록 두었습니다. 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. 애초에 로그인했을 때/ 안 했을 때 구현 뷰가 달라지니까 필요한 부분이 맞긴 한듯요? |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,15 @@ | ||
package corea.room.controller; | ||
|
||
import corea.auth.annotation.AccessedMember; | ||
import corea.auth.annotation.LoginMember; | ||
import corea.auth.domain.AuthInfo; | ||
import corea.member.domain.Member; | ||
import corea.room.dto.RoomResponse; | ||
import corea.room.dto.RoomResponses; | ||
import corea.room.service.RoomService; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@RestController | ||
@RequestMapping("/rooms") | ||
|
@@ -36,4 +35,16 @@ public ResponseEntity<RoomResponses> participatedRooms(@LoginMember AuthInfo aut | |
RoomResponses response = roomService.findParticipatedRooms(authInfo.getId()); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
@GetMapping("/opened") | ||
public ResponseEntity<RoomResponses> openedRooms(@AccessedMember Member member, | ||
@RequestParam(value = "classification", defaultValue = "all") String expression, | ||
@RequestParam(defaultValue = "0") int page) { | ||
if (member == null) { | ||
RoomResponses response = roomService.findOpenedRoomsWithoutMember(expression, page); | ||
return ResponseEntity.ok(response); | ||
} | ||
RoomResponses response = roomService.findOpenedRoomsWithMember(member.getId(), expression, page); | ||
return ResponseEntity.ok(response); | ||
Comment on lines
+39
to
+48
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.
가독성이 안 좋은 것 같아 Service layer까지 전달하려고 생각 해보았는데, 모집 종료된 방 리스트 조회하는 기능까지 구현한 다음 중복 코드 제거하면서 더 고민해볼게요. 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. 우선은 controller 에서 잡아서 분기 처리하는게 베스트인듯? 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. 해당 부분은 모집 종료 방 리스트 조회 기능 구현 이후 팔로업하겠습니당 👍 |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package corea.room.domain; | ||
|
||
import corea.exception.CoreaException; | ||
import corea.exception.ExceptionType; | ||
|
||
import java.util.Arrays; | ||
import java.util.Map; | ||
import java.util.function.Function; | ||
|
||
import static java.util.stream.Collectors.toMap; | ||
|
||
public enum Classification { | ||
|
||
ALL("all"), | ||
ANDROID("an"), | ||
BACKEND("be"), | ||
FRONTEND("fe"); | ||
|
||
private static final Map<String, Classification> CACHED_CLASSIFICATIONS = Arrays.stream(values()) | ||
.collect(toMap(classification -> classification.expression, Function.identity())); | ||
Comment on lines
+12
to
+20
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. 누군가의 발표가 생각나네요 👍 |
||
|
||
private final String expression; | ||
|
||
Classification(String expression) { | ||
this.expression = expression; | ||
} | ||
|
||
public static Classification from(String expression) { | ||
if (CACHED_CLASSIFICATIONS.containsKey(expression)) { | ||
return CACHED_CLASSIFICATIONS.get(expression); | ||
} | ||
throw new CoreaException(ExceptionType.NOT_FOUND_ERROR); | ||
} | ||
|
||
public boolean isAll() { | ||
return this == ALL; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,15 +40,29 @@ public class Room { | |
private int limitedParticipantsSize; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "manager_id",foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) | ||
@JoinColumn(name = "manager_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) | ||
private Member manager; | ||
|
||
private LocalDateTime recruitmentDeadline; | ||
|
||
private LocalDateTime reviewDeadline; | ||
|
||
public Room(String title, String content, int matchingSize, String repositoryLink, String thumbnailLink, String keyword, int currentParticipantsSize, int limitedParticipantsSize, Member manager, LocalDateTime recruitmentDeadline, LocalDateTime reviewDeadline) { | ||
this(null, title, content, matchingSize, repositoryLink, thumbnailLink, keyword, currentParticipantsSize, limitedParticipantsSize, manager, recruitmentDeadline, reviewDeadline); | ||
@Enumerated(value = EnumType.STRING) | ||
private Classification classification; | ||
|
||
/** | ||
* RoomStatus가 변경될 수 있는 경우 (OPENED -> CLOSED) | ||
* 1. 방장이 모집 마감을 한 경우 | ||
* 2. 제한 인원이 다 찼을 경우 (방에 참여할 때 같이 검증) | ||
* 3. 모집 기간이 끝난 경우 | ||
* | ||
* 1, 2의 경우 때문에 방 상태를 가지는 필드를 가져야 될듯. | ||
* **/ | ||
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. 👍 |
||
@Enumerated(value = EnumType.STRING) | ||
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. 괜찮은듯. |
||
private RoomStatus status; | ||
|
||
public Room(String title, String content, int matchingSize, String repositoryLink, String thumbnailLink, String keyword, int currentParticipantsSize, int limitedParticipantsSize, Member manager, LocalDateTime recruitmentDeadline, LocalDateTime reviewDeadline, Classification classification, RoomStatus status) { | ||
this(null, title, content, matchingSize, repositoryLink, thumbnailLink, keyword, currentParticipantsSize, limitedParticipantsSize, manager, recruitmentDeadline, reviewDeadline, classification, status); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package corea.room.domain; | ||
|
||
public enum RoomStatus { | ||
|
||
OPENED, CLOSED | ||
} |
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.
테스트를 위한 초기 데이터를 저장하는 클래스입니다.
해당 클래스는 테스트 패키지로 분리해도 좋다고 느껴졌지만,
나중에 프로덕션 코드에서도 활용 가능성이 있다 판단하여 그냥 두었습니다.😀
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.
나중에, 데이터 쌓이면
context.sql 로 데이터 넣고 clear 안하고 거기에 넣어도 괜찮을듯용