From 3c7ef1754020490b293239db28836bb5f163c865 Mon Sep 17 00:00:00 2001 From: 82everywin <82everywin@gmail.com> Date: Sat, 1 Mar 2025 03:26:47 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=EA=B8=B0=EB=A1=9D=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=EB=A5=A0=20DTO=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/RecordProgressChartDto.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/java/com/bookmile/backend/domain/record/dto/res/RecordProgressChartDto.java diff --git a/src/main/java/com/bookmile/backend/domain/record/dto/res/RecordProgressChartDto.java b/src/main/java/com/bookmile/backend/domain/record/dto/res/RecordProgressChartDto.java new file mode 100644 index 0000000..5c27cd9 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/dto/res/RecordProgressChartDto.java @@ -0,0 +1,30 @@ +package com.bookmile.backend.domain.record.dto.res; + +import com.bookmile.backend.domain.userGroup.entity.UserGroup; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class RecordProgressChartDto { + private final String profile; + private final String nickname; + private final String progress; + + @Builder + public RecordProgressChartDto(String profile, String nickname, String progress) { + this.profile = profile; + this.nickname = nickname; + this.progress = progress; + } + + public static RecordProgressChartDto from(UserGroup userGroup, double progress) { + String formatProgress = String.format("%.2f", progress); + + return RecordProgressChartDto.builder() + .profile(userGroup.getUser().getImage()) + .nickname(userGroup.getUser().getNickname()) + .progress(formatProgress) + .build(); + + } +} From 66afe9e8c577420022d80e26197234e8c6763518 Mon Sep 17 00:00:00 2001 From: 82everywin <82everywin@gmail.com> Date: Sat, 1 Mar 2025 03:29:08 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=EA=B8=B0=EB=A1=9D=20=EC=88=9C?= =?UTF-8?q?=EC=9C=84=20service=20=EA=B3=84=EC=B8=B5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../record/repository/RecordRepository.java | 15 ++++++- .../service/Impl/RecordServiceImpl.java | 41 ++++++++++++++++++- .../domain/record/service/RecordService.java | 5 +++ .../repository/UserGroupRepository.java | 4 -- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/bookmile/backend/domain/record/repository/RecordRepository.java b/src/main/java/com/bookmile/backend/domain/record/repository/RecordRepository.java index 23d41d2..c746a07 100644 --- a/src/main/java/com/bookmile/backend/domain/record/repository/RecordRepository.java +++ b/src/main/java/com/bookmile/backend/domain/record/repository/RecordRepository.java @@ -4,13 +4,24 @@ import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository public interface RecordRepository extends JpaRepository { List findAllByUserGroupId(Long userGroupId); - @Query(value = "SELECT * FROM record WHERE group_id = :groupId ORDER BY RAND() LIMIT 4", nativeQuery = true) + @Query(value = "SELECT r.* FROM record r " + + "WHERE r.userGroup.group.id = :groupId " + + "ORDER BY RAND() LIMIT 4", nativeQuery = true) List findRandomRecordByGroupId(Long groupId); -} + @Query(value = "SELECT r.* FROM record r " + + "WHERE r.usergroup_id = :userGroupId " + + "AND r.created_at = ( " + + " SELECT MAX(r2.created_at) FROM record r2 " + + " WHERE r2.usergroup_id = r.usergroup_id " + + ")", + nativeQuery = true) + Record findLatestRecordByUserAndGroup(@Param("userGroupId") Long userGroupId); +} \ No newline at end of file diff --git a/src/main/java/com/bookmile/backend/domain/record/service/Impl/RecordServiceImpl.java b/src/main/java/com/bookmile/backend/domain/record/service/Impl/RecordServiceImpl.java index 3cc08d9..4789d92 100644 --- a/src/main/java/com/bookmile/backend/domain/record/service/Impl/RecordServiceImpl.java +++ b/src/main/java/com/bookmile/backend/domain/record/service/Impl/RecordServiceImpl.java @@ -5,6 +5,7 @@ import static com.bookmile.backend.global.common.StatusCode.RECORD_NOT_FOUND; import static com.bookmile.backend.global.common.StatusCode.USER_NOT_FOUND; +import com.bookmile.backend.domain.book.entity.Book; import com.bookmile.backend.domain.group.entity.Group; import com.bookmile.backend.domain.image.repository.ImageRepository; import com.bookmile.backend.domain.image.service.Impl.ImageServiceImpl; @@ -12,6 +13,7 @@ import com.bookmile.backend.domain.record.dto.req.UpdateRecordReqDto; import com.bookmile.backend.domain.record.dto.res.RecentRecordResDto; import com.bookmile.backend.domain.record.dto.res.RecordListResDto; +import com.bookmile.backend.domain.record.dto.res.RecordProgressChartDto; import com.bookmile.backend.domain.record.entity.Record; import com.bookmile.backend.domain.record.repository.RecordRepository; import com.bookmile.backend.domain.record.service.RecordGroupRepository; @@ -24,6 +26,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.stream.Collectors; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -39,7 +43,6 @@ public class RecordServiceImpl implements RecordService { private final RecordGroupRepository groupRepository; private final RecordRepository recordRepository; private final UserGroupRepository userGroupRepository; - private final ImageRepository imageRepository; private final ImageServiceImpl imageService; @Override @@ -105,7 +108,7 @@ public List viewRandomRecord(Long groupId) { List recentRecordResDtos = new ArrayList<>(); for (Record record : randomRecords) { - User user = findUserById(record.getUserId()); + User user = findUserById(record.getUserGroup().getUser().getId()); if (record.getImages().isEmpty()) { // 이미지 리스트 비어있으면 그냥 이미지 없는거로 추가 recentRecordResDtos @@ -124,6 +127,40 @@ public List viewRandomRecord(Long groupId) { return recentRecordResDtos; } + public List getProgressChart(Long groupId) { + // groupId로 해당 그룹 존재 + List userGroups = userGroupRepository.findByGroupId(groupId); + for(UserGroup userGroup : userGroups) { + log.info("userGroup 리스트 {}- ID : {}", userGroup.getId(), userGroup.getUser().getId()); + } + + // userGroup 으로 -> groupId로 userGroup 리스트 뽑아내기 + return userGroups.stream() + .map(userGroup -> { + double progress = calculateReadingProgress(userGroup.getId()); + log.info ("계산 후 progress : {}", progress); + return RecordProgressChartDto.from(userGroup, progress); + }) + .collect(Collectors.toList()); + } + + // 개인 진행률 계산 + private double calculateReadingProgress(Long userGroupId) { + Record record = recordRepository.findLatestRecordByUserAndGroup(userGroupId); + log.info("개인 진행률 계산 : record - {}, 현재 페이지 {}", record.getId(), record.getCurrentPage()); + + + Book book = record.getUserGroup().getGroup().getBook(); + log.info("그룹의 책이름 : {}", book.getTitle()); + + if (book.getTotalPage() == 0) { + return 0.0; // 총 페이지가 0이면 진행률 없음 + } + + return ((double) record.getCurrentPage() / book.getTotalPage()) * 100; + + } + private Group findGroupById(Long groupId) { return groupRepository.findById(groupId) .orElseThrow(() -> new CustomException(GROUP_NOT_FOUND)); diff --git a/src/main/java/com/bookmile/backend/domain/record/service/RecordService.java b/src/main/java/com/bookmile/backend/domain/record/service/RecordService.java index 365ca6b..42ce56a 100644 --- a/src/main/java/com/bookmile/backend/domain/record/service/RecordService.java +++ b/src/main/java/com/bookmile/backend/domain/record/service/RecordService.java @@ -5,6 +5,8 @@ import com.bookmile.backend.domain.record.dto.res.RecentRecordResDto; import com.bookmile.backend.domain.record.dto.res.RecordListResDto; import java.util.List; + +import com.bookmile.backend.domain.record.dto.res.RecordProgressChartDto; import org.springframework.web.multipart.MultipartFile; public interface RecordService { @@ -15,4 +17,7 @@ public interface RecordService { Long updateRecord(Long recordId, UpdateRecordReqDto updateRecordReqDto); List viewRandomRecord(Long groupId); + + List getProgressChart(Long groupId); + } diff --git a/src/main/java/com/bookmile/backend/domain/userGroup/repository/UserGroupRepository.java b/src/main/java/com/bookmile/backend/domain/userGroup/repository/UserGroupRepository.java index cb71eae..644d832 100644 --- a/src/main/java/com/bookmile/backend/domain/userGroup/repository/UserGroupRepository.java +++ b/src/main/java/com/bookmile/backend/domain/userGroup/repository/UserGroupRepository.java @@ -27,8 +27,4 @@ public interface UserGroupRepository extends JpaRepository { @Query("SELECT ug FROM UserGroup ug JOIN ug.group g WHERE ug.user.email = :userEmail AND g.status = :status") List findGroupsByUserEmailAndStatus(@Param("userEmail") String userEmail, @Param("status") GroupStatus status); - - @Query(value = "SELECT u.email FROM user_group ug JOIN user u ON ug.user_id = u.user_id WHERE group_id = :groupId ORDER BY RAND()", nativeQuery = true) - List findUserEmailRandomSortByGroupId(Long groupId); - } \ No newline at end of file From 1e8a00a75fbd3aa92f0fe1523480f914d93cc06d Mon Sep 17 00:00:00 2001 From: 82everywin <82everywin@gmail.com> Date: Sat, 1 Mar 2025 03:29:32 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=EA=B8=B0=EB=A1=9D=20=EC=88=9C?= =?UTF-8?q?=EC=9C=84=20controller=20=EA=B3=84=EC=B8=B5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/record/controller/RecordController.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/bookmile/backend/domain/record/controller/RecordController.java b/src/main/java/com/bookmile/backend/domain/record/controller/RecordController.java index f1907e3..e0dc1c4 100644 --- a/src/main/java/com/bookmile/backend/domain/record/controller/RecordController.java +++ b/src/main/java/com/bookmile/backend/domain/record/controller/RecordController.java @@ -8,6 +8,7 @@ import com.bookmile.backend.domain.record.dto.req.UpdateRecordReqDto; import com.bookmile.backend.domain.record.dto.res.RecentRecordResDto; import com.bookmile.backend.domain.record.dto.res.RecordListResDto; +import com.bookmile.backend.domain.record.dto.res.RecordProgressChartDto; import com.bookmile.backend.domain.record.service.RecordService; import com.bookmile.backend.global.common.CommonResponse; import io.swagger.v3.oas.annotations.Operation; @@ -73,4 +74,10 @@ public ResponseEntity>> viewRandomRecord return ResponseEntity.status(VIEW_RECORD.getStatus()) .body(CommonResponse.from(VIEW_RECORD.getMessage(), recentRecordResDtos)); } + + @Operation(summary = "기록 작성 진행률 조회 (순위 조회)", description = "해당 그룹의 독서 진행률을 조회합니다.") + @GetMapping("/progress") + public List getGroupReadingProgress(@RequestParam(name = "groupId")Long groupId) { + return recordService.getProgressChart(groupId); + } } \ No newline at end of file From 01f18556a0cf6b77b7f6c635feaa53767c761bb7 Mon Sep 17 00:00:00 2001 From: 82everywin <82everywin@gmail.com> Date: Sat, 1 Mar 2025 03:29:45 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20Record=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/record/entity/Record.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/bookmile/backend/domain/record/entity/Record.java b/src/main/java/com/bookmile/backend/domain/record/entity/Record.java index 5b6663d..8a9de64 100644 --- a/src/main/java/com/bookmile/backend/domain/record/entity/Record.java +++ b/src/main/java/com/bookmile/backend/domain/record/entity/Record.java @@ -1,5 +1,6 @@ package com.bookmile.backend.domain.record.entity; +import com.bookmile.backend.domain.group.entity.Group; import com.bookmile.backend.domain.image.entity.Image; import com.bookmile.backend.domain.record.dto.req.RecordReqDto; import com.bookmile.backend.domain.record.dto.req.UpdateRecordReqDto; @@ -35,12 +36,6 @@ public class Record extends BaseEntity { @JoinColumn(name = "usergroup_id", nullable = false) private UserGroup userGroup; - @Column - private Long userId; - - @Column - private Long groupId; - @Column private String text; @@ -52,10 +47,8 @@ public class Record extends BaseEntity { private List images = new ArrayList<>(); @Builder - public Record(UserGroup userGroup, Long userId, Long groupId, String text, Integer currentPage) { + public Record(UserGroup userGroup, String text, Integer currentPage) { this.userGroup = userGroup; - this.userId = userId; - this.groupId = groupId; this.text = text; this.currentPage = currentPage; } @@ -63,8 +56,6 @@ public Record(UserGroup userGroup, Long userId, Long groupId, String text, Integ public static Record from(UserGroup userGroup, RecordReqDto recordReqDto) { return Record.builder() .userGroup(userGroup) - .userId(userGroup.getUser().getId()) - .groupId(userGroup.getGroup().getId()) .text(recordReqDto.getText()) .currentPage(recordReqDto.getCurrentPage()) .build(); From 99ad8156f767c844c59a3f2a23de729723f5466a Mon Sep 17 00:00:00 2001 From: 82everywin <82everywin@gmail.com> Date: Sat, 1 Mar 2025 03:30:05 +0900 Subject: [PATCH 5/5] =?UTF-8?q?chore:=20swagger=20=EB=A3=A8=ED=8A=B8?= =?UTF-8?q?=EC=A3=BC=EC=86=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/bookmile/backend/BackendApplication.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/bookmile/backend/BackendApplication.java b/src/main/java/com/bookmile/backend/BackendApplication.java index 54f7b0d..db97970 100644 --- a/src/main/java/com/bookmile/backend/BackendApplication.java +++ b/src/main/java/com/bookmile/backend/BackendApplication.java @@ -6,9 +6,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; -//@OpenAPIDefinition(servers = -// {@Server(url = "https://bookmile.site/", description = "배포 서버 주소"), -// @Server(url = "/", description = "개발용 서버 주소")}) +@OpenAPIDefinition(servers = + {@Server(url = "https://bookmile.site/", description = "배포 서버 주소"), + @Server(url = "/", description = "개발용 서버 주소")}) @SpringBootApplication public class BackendApplication {