-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feat/CK-240] 골룸 관련 부분 의존성 리팩토링을 한다 (#207)
* refactor: GoalRoom 관련 패키지 의존성 분리 * refactor: 리뷰 반영 및 골룸 생성 로직 변경 * feat: GoalRoom과 GoalRoomMember, GoalRoomPendingMember의 양방향 의존성 제거 * feat: 골룸 생성 시 리더 업데이트하는 로직 이벤트 분리 * feat: 골룸 나갈 때 빈 골룸을 삭제하는 로직 이벤트 분리 * feat: 인증피드 등록 시 달성률 업데이트 로직 이벤트 분리 * refactor: 요구 사항 반영 (DashBoardCheckFeedService) * refactor: CheckFeed 생성 시 달성률 업데이트 이벤트 네이밍 변경 * refactor: 골룸 생성, 나가기 이벤트 네이밍 변경 * feat: 골룸 참여 시, 골룸 펜딩 멤버 테이블에 락이 걸리도록 수정 * refactor: 골룸 시작, 나가기 쿼리 수정
- Loading branch information
Showing
220 changed files
with
8,049 additions
and
6,342 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
.../kirikiri/src/main/java/co/kirikiri/checkfeed/controller/GoalRoomCheckFeedController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package co.kirikiri.checkfeed.controller; | ||
|
||
import co.kirikiri.checkfeed.service.GoalRoomCheckFeedService; | ||
import co.kirikiri.checkfeed.service.dto.request.CheckFeedRequest; | ||
import co.kirikiri.checkfeed.service.dto.response.GoalRoomCheckFeedResponse; | ||
import co.kirikiri.common.interceptor.Authenticated; | ||
import co.kirikiri.common.resolver.MemberIdentifier; | ||
import java.net.URI; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.ModelAttribute; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequestMapping("/goal-rooms/{goalRoomId}/checkFeeds") | ||
@RequiredArgsConstructor | ||
public class GoalRoomCheckFeedController { | ||
|
||
private final GoalRoomCheckFeedService goalRoomCheckFeedService; | ||
|
||
@PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) | ||
@Authenticated | ||
public ResponseEntity<Void> createCheckFeed(@MemberIdentifier final String identifier, | ||
@PathVariable("goalRoomId") final Long goalRoomId, | ||
@ModelAttribute final CheckFeedRequest checkFeedRequest) { | ||
final String imageUrl = goalRoomCheckFeedService.createCheckFeed(identifier, goalRoomId, checkFeedRequest); | ||
return ResponseEntity.created(URI.create(imageUrl)).build(); | ||
} | ||
|
||
@GetMapping | ||
@Authenticated | ||
public ResponseEntity<List<GoalRoomCheckFeedResponse>> findGoalRoomCheckFeeds( | ||
@MemberIdentifier final String identifier, | ||
@PathVariable("goalRoomId") final Long goalRoomId) { | ||
final List<GoalRoomCheckFeedResponse> response = goalRoomCheckFeedService.findGoalRoomCheckFeeds(identifier, | ||
goalRoomId); | ||
return ResponseEntity.ok(response); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
backend/kirikiri/src/main/java/co/kirikiri/checkfeed/persistence/CheckFeedRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package co.kirikiri.checkfeed.persistence; | ||
|
||
import co.kirikiri.checkfeed.domain.CheckFeed; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Query; | ||
import org.springframework.data.repository.query.Param; | ||
|
||
public interface CheckFeedRepository extends JpaRepository<CheckFeed, Long> { | ||
|
||
@Query("SELECT cf" | ||
+ " FROM CheckFeed cf" | ||
+ " WHERE cf.goalRoomMemberId = :goalRoomMemberId" | ||
+ " AND cf.createdAt >= :start" | ||
+ " AND cf.createdAt < :end") | ||
Optional<CheckFeed> findByGoalRoomMemberIdAndDateTime(final Long goalRoomMemberId, final LocalDateTime start, | ||
final LocalDateTime end); | ||
|
||
@Query("SELECT COUNT(cf)" | ||
+ " FROM CheckFeed cf" | ||
+ " WHERE cf.goalRoomMemberId = :goalRoomMemberId" | ||
+ " AND cf.goalRoomRoadmapNodeId = :goalRoomRoadmapNodeId") | ||
int countByGoalRoomMemberIdAndGoalRoomRoadmapNodeId(final Long goalRoomMemberId, final Long goalRoomRoadmapNodeId); | ||
|
||
@Query(value = "SELECT cf.* FROM check_feed as cf " | ||
+ "LEFT JOIN goal_room_member as gm ON cf.goal_room_member_id = gm.id " | ||
+ "JOIN goal_room as g ON gm.goal_room_id = g.id " | ||
+ "WHERE g.id = :goalRoomId " | ||
+ "ORDER BY cf.created_at DESC ", nativeQuery = true) | ||
List<CheckFeed> findByGoalRoomIdOrderByCreatedAtDesc(@Param("goalRoomId") final Long goalRoomId); | ||
|
||
List<CheckFeed> findByGoalRoomRoadmapNodeIdOrderByCreatedAtDesc(final Long goalRoomRoadmapNodeId); | ||
} |
74 changes: 74 additions & 0 deletions
74
...nd/kirikiri/src/main/java/co/kirikiri/checkfeed/service/CheckFeedCreateEventListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package co.kirikiri.checkfeed.service; | ||
|
||
import co.kirikiri.checkfeed.domain.CheckFeed; | ||
import co.kirikiri.checkfeed.persistence.CheckFeedRepository; | ||
import co.kirikiri.checkfeed.service.event.CheckFeedCreateEvent; | ||
import co.kirikiri.common.aop.ExceptionConvert; | ||
import co.kirikiri.common.exception.BadRequestException; | ||
import co.kirikiri.common.exception.NotFoundException; | ||
import co.kirikiri.goalroom.domain.GoalRoom; | ||
import co.kirikiri.goalroom.domain.GoalRoomMember; | ||
import co.kirikiri.goalroom.domain.GoalRoomRoadmapNode; | ||
import co.kirikiri.goalroom.persistence.GoalRoomMemberRepository; | ||
import co.kirikiri.goalroom.persistence.GoalRoomRepository; | ||
import java.time.LocalDate; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.transaction.event.TransactionPhase; | ||
import org.springframework.transaction.event.TransactionalEventListener; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@ExceptionConvert | ||
public class CheckFeedCreateEventListener { | ||
|
||
private final CheckFeedRepository checkFeedRepository; | ||
private final GoalRoomRepository goalRoomRepository; | ||
private final GoalRoomMemberRepository goalRoomMemberRepository; | ||
|
||
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) | ||
@Transactional | ||
public void handleUpdateAccomplishmentRate(final CheckFeedCreateEvent checkFeedCreateEvent) { | ||
final CheckFeed checkFeed = findCheckFeedById(checkFeedCreateEvent.checkFeedId()); | ||
final GoalRoom goalRoom = findGoalRoomById(checkFeedCreateEvent.goalRoomId()); | ||
final GoalRoomMember goalRoomMember = findGoalRoomMemberById(checkFeed.getGoalRoomMemberId()); | ||
final GoalRoomRoadmapNode currentNode = getNodeByDate(goalRoom); | ||
final int currentCheckCount = getCurrentCheckCount(goalRoomMember, currentNode); | ||
|
||
updateAccomplishmentRate(goalRoom, goalRoomMember, currentCheckCount); | ||
} | ||
|
||
private CheckFeed findCheckFeedById(final Long checkFeedId) { | ||
return checkFeedRepository.findById(checkFeedId) | ||
.orElseThrow(() -> new NotFoundException("존재하지 않는 인증피드입니다.")); | ||
} | ||
|
||
private GoalRoom findGoalRoomById(final Long goalRoomId) { | ||
return goalRoomRepository.findById(goalRoomId) | ||
.orElseThrow(() -> new NotFoundException("존재하지 않는 골룸입니다.")); | ||
} | ||
|
||
private GoalRoomMember findGoalRoomMemberById(final Long goalRoomMemberId) { | ||
return goalRoomMemberRepository.findById(goalRoomMemberId) | ||
.orElseThrow(() -> new NotFoundException("존재하지 않는 골룸 멤버입니다.")); | ||
} | ||
|
||
private GoalRoomRoadmapNode getNodeByDate(final GoalRoom goalRoom) { | ||
return goalRoom.findNodeByDate(LocalDate.now()) | ||
.orElseThrow(() -> new BadRequestException("인증 피드는 노드 기간 내에만 작성할 수 있습니다.")); | ||
} | ||
|
||
private int getCurrentCheckCount(final GoalRoomMember goalRoomMember, final GoalRoomRoadmapNode currentNode) { | ||
return checkFeedRepository.countByGoalRoomMemberIdAndGoalRoomRoadmapNodeId( | ||
goalRoomMember.getId(), currentNode.getId()); | ||
} | ||
|
||
private void updateAccomplishmentRate(final GoalRoom goalRoom, final GoalRoomMember goalRoomMember, | ||
final int currentCheckCount) { | ||
final int wholeCheckCount = goalRoom.getAllCheckCount(); | ||
final Double accomplishmentRate = 100 * currentCheckCount / (double) wholeCheckCount; | ||
|
||
goalRoomMember.updateAccomplishmentRate(accomplishmentRate); | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
...d/kirikiri/src/main/java/co/kirikiri/checkfeed/service/DashBoardCheckFeedServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package co.kirikiri.checkfeed.service; | ||
|
||
import co.kirikiri.checkfeed.domain.CheckFeed; | ||
import co.kirikiri.checkfeed.persistence.CheckFeedRepository; | ||
import co.kirikiri.common.aop.ExceptionConvert; | ||
import co.kirikiri.common.service.FileService; | ||
import co.kirikiri.goalroom.domain.GoalRoom; | ||
import co.kirikiri.goalroom.domain.GoalRoomRoadmapNode; | ||
import co.kirikiri.goalroom.service.DashBoardCheckFeedService; | ||
import co.kirikiri.goalroom.service.dto.response.DashBoardCheckFeedResponse; | ||
import java.net.URL; | ||
import java.time.LocalDate; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@Transactional | ||
@RequiredArgsConstructor | ||
@ExceptionConvert | ||
public class DashBoardCheckFeedServiceImpl implements DashBoardCheckFeedService { | ||
|
||
private final CheckFeedRepository checkFeedRepository; | ||
private final FileService fileService; | ||
|
||
@Override | ||
@Transactional(readOnly = true) | ||
public List<DashBoardCheckFeedResponse> findCheckFeedsByNodeAndGoalRoomStatus(final GoalRoom goalRoom) { | ||
final Optional<GoalRoomRoadmapNode> currentGoalRoomRoadmapNode = findCurrentGoalRoomNode(goalRoom); | ||
final List<CheckFeed> checkFeeds = findCheckFeeds(goalRoom, currentGoalRoomRoadmapNode); | ||
return makeCheckFeedResponses(checkFeeds); | ||
} | ||
|
||
private Optional<GoalRoomRoadmapNode> findCurrentGoalRoomNode(final GoalRoom goalRoom) { | ||
return goalRoom.findNodeByDate(LocalDate.now()); | ||
} | ||
|
||
private List<CheckFeed> findCheckFeeds(final GoalRoom goalRoom, | ||
final Optional<GoalRoomRoadmapNode> currentGoalRoomRoadmapNode) { | ||
if (goalRoom.isCompleted()) { | ||
return checkFeedRepository.findByGoalRoomIdOrderByCreatedAtDesc(goalRoom.getId()); | ||
} | ||
if (goalRoom.isRunning() && currentGoalRoomRoadmapNode.isPresent()) { | ||
return checkFeedRepository.findByGoalRoomRoadmapNodeIdOrderByCreatedAtDesc( | ||
currentGoalRoomRoadmapNode.get().getId()); | ||
} | ||
return Collections.emptyList(); | ||
} | ||
|
||
private List<DashBoardCheckFeedResponse> makeCheckFeedResponses(final List<CheckFeed> checkFeeds) { | ||
return checkFeeds.stream() | ||
.map(this::makeCheckFeedResponse) | ||
.toList(); | ||
} | ||
|
||
private DashBoardCheckFeedResponse makeCheckFeedResponse(final CheckFeed checkFeed) { | ||
final URL checkFeedImageUrl = fileService.generateUrl(checkFeed.getServerFilePath(), HttpMethod.GET); | ||
return new DashBoardCheckFeedResponse(checkFeed.getId(), checkFeedImageUrl.toExternalForm(), | ||
checkFeed.getDescription(), checkFeed.getCreatedAt().toLocalDate()); | ||
} | ||
} |
Oops, something went wrong.