Skip to content

Commit

Permalink
Merge pull request #71 from Book-Mile/feat/#70
Browse files Browse the repository at this point in the history
[Feat/#70] 그룹 도서 기록 순위 API 구현
  • Loading branch information
82everywin authored Mar 1, 2025
2 parents c03ea34 + 99ad815 commit 4960f35
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 22 deletions.
6 changes: 3 additions & 3 deletions src/main/java/com/bookmile/backend/BackendApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -73,4 +74,10 @@ public ResponseEntity<CommonResponse<List<RecentRecordResDto>>> viewRandomRecord
return ResponseEntity.status(VIEW_RECORD.getStatus())
.body(CommonResponse.from(VIEW_RECORD.getMessage(), recentRecordResDtos));
}

@Operation(summary = "기록 작성 진행률 조회 (순위 조회)", description = "해당 그룹의 독서 진행률을 조회합니다.")
@GetMapping("/progress")
public List<RecordProgressChartDto> getGroupReadingProgress(@RequestParam(name = "groupId")Long groupId) {
return recordService.getProgressChart(groupId);
}
}
Original file line number Diff line number Diff line change
@@ -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();

}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -52,19 +47,15 @@ public class Record extends BaseEntity {
private List<Image> 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;
}

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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Record, Long> {
List<Record> 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<Record> 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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
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;
import com.bookmile.backend.domain.record.dto.req.RecordReqDto;
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;
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -105,7 +108,7 @@ public List<RecentRecordResDto> viewRandomRecord(Long groupId) {
List<RecentRecordResDto> recentRecordResDtos = new ArrayList<>();

for (Record record : randomRecords) {
User user = findUserById(record.getUserId());
User user = findUserById(record.getUserGroup().getUser().getId());

if (record.getImages().isEmpty()) { // 이미지 리스트 비어있으면 그냥 이미지 없는거로 추가
recentRecordResDtos
Expand All @@ -124,6 +127,40 @@ public List<RecentRecordResDto> viewRandomRecord(Long groupId) {
return recentRecordResDtos;
}

public List<RecordProgressChartDto> getProgressChart(Long groupId) {
// groupId로 해당 그룹 존재
List<UserGroup> 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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -15,4 +17,7 @@ public interface RecordService {
Long updateRecord(Long recordId, UpdateRecordReqDto updateRecordReqDto);

List<RecentRecordResDto> viewRandomRecord(Long groupId);

List<RecordProgressChartDto> getProgressChart(Long groupId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,4 @@ public interface UserGroupRepository extends JpaRepository<UserGroup, Long> {
@Query("SELECT ug FROM UserGroup ug JOIN ug.group g WHERE ug.user.email = :userEmail AND g.status = :status")
List<UserGroup> 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<String> findUserEmailRandomSortByGroupId(Long groupId);

}

0 comments on commit 4960f35

Please sign in to comment.