Skip to content
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

[Feat/#10] 리뷰, 기록 부분 기능 구현 #13

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a5116ee
feat(ReviewRepository, ReviewRepositoryTest): 레포지토리 생성 및 테스트
kingjinyong Nov 27, 2024
f88b1d6
feat(ReviewRepository, ReviewRepositoryTest): 레포지토리 추가 작성 및 테스트
kingjinyong Nov 27, 2024
c7cf471
feat(ReviewService, ReviewListResponse, ReviewServiceTest): 리뷰 리스트 조회…
kingjinyong Nov 27, 2024
42e2189
feat(ReviewController): 리뷰 리스트 조회 기능 모두 구현
kingjinyong Nov 27, 2024
e86f534
feat(ReviewService, ReviewRequest, ReviewListResponse, Review, Review…
kingjinyong Nov 27, 2024
37dfa88
test(BookRepository, UserRepository, ReviewService, ReviewServiceTest…
kingjinyong Nov 29, 2024
d9863ed
feat(ReviewService, Review, ReviewServiceTest): 리뷰 수정 기능 구현 및 테스트 코드 작성
kingjinyong Nov 29, 2024
8a09ec7
refactor(ReviewController): 리뷰 수정 기능 컨트롤러 구현
kingjinyong Nov 29, 2024
44f8e50
refactor(ReviewController): 리뷰 수정 기능 컨트롤러 Mapping 경로 수정
kingjinyong Nov 29, 2024
4f1e777
feat(ReviewService, Review, ReviewController, ReviewServiceTest): 리뷰 …
kingjinyong Nov 29, 2024
a17d9a3
feat(RecordRepository): 기록 레포지토리 생성
kingjinyong Nov 29, 2024
3a1b464
feat(Record, RecordRepository, UserGroup, GroupRepository, RecordList…
kingjinyong Nov 29, 2024
d245dea
feat(RecordController): 기록 조회기능 컨트롤러 계층 구현
kingjinyong Nov 29, 2024
43b22b6
refacotr(RecordRepository): 필요없는 네이티브 쿼리 제거
kingjinyong Dec 1, 2024
39a964d
feat(Record, RecordService, RecordServiceTest, RequestRecord, UserGro…
kingjinyong Dec 1, 2024
584ea1c
feat(RecordService, RecordServiceTest, Record): 기록 수정 기능 구현 및 테스트 코드 작성
kingjinyong Dec 2, 2024
57029f4
feat(RecordController): 기록 생성&수정 기능 컨트롤러 코드 작성
kingjinyong Dec 2, 2024
55cbe3f
test(RecordServiceTest): 기록 불러오기 테스트 로직 수정
kingjinyong Dec 2, 2024
852d577
feat(Record, RecordListResponse, RecordServiceTest, RequestRecord): 기…
kingjinyong Dec 2, 2024
54cbc7c
feat(Record, RecordServiceTest): 기록 수정 부분 이미지 수정 로직 추가 및 테스트 코드 수정
kingjinyong Dec 2, 2024
1659750
refactor(RecordService): 기록 불러오기, 수정 기능 리팩토링
kingjinyong Dec 2, 2024
47bc3df
refactor(Record, RecordService): 메서드 명 소문자로 변경
kingjinyong Dec 5, 2024
27d3bad
refactor(Image, Record, RecordController, RecordListResponse, RecordS…
kingjinyong Dec 5, 2024
45bd47d
test(ImageServiceTest, RecordServiceTest, ReviewServiceTest): 이미지 생성,…
kingjinyong Dec 6, 2024
0194da7
Merge branch 'main' into feat/#10
kingjinyong Dec 6, 2024
b366300
refactor(너무 많음): 메인 브랜치에서 merge 후, 자잘한 오류 수정
kingjinyong Dec 6, 2024
41bb623
refactor(Review): Review 생성자 빌더패턴 적용
kingjinyong Dec 6, 2024
11b5c43
refactor(Review): 주석 제거
kingjinyong Dec 6, 2024
e79fd22
refactor(RecordListResDto, RecordServiceTest): 빌더 패턴 적용 및 변수명 수정
kingjinyong Dec 6, 2024
e441666
refactor(UserGroup): 필요 없는 메서드 삭제
kingjinyong Dec 6, 2024
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
@@ -0,0 +1,43 @@
package com.bookmile.backend.domain.record.controller;

import com.bookmile.backend.domain.record.dto.RecordListResponse;
import com.bookmile.backend.domain.record.dto.RequestRecord;
import com.bookmile.backend.domain.record.service.RecordService;
import java.util.List;
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.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1/records")
@RequiredArgsConstructor
public class RecordController {
private RecordService recordService;

@GetMapping
public ResponseEntity<List<RecordListResponse>> viewRecordList(@RequestParam Long groupId,
@RequestParam Long userId) {
List<RecordListResponse> records = recordService.viewRecordList(groupId, userId);
return ResponseEntity.ok(records);
}

@PostMapping
public ResponseEntity<Long> createRecord(@RequestParam Long groupId,
@RequestParam Long userId, @RequestBody RequestRecord requestRecord) {
Long recordId = recordService.createRecord(groupId, userId, requestRecord);
return ResponseEntity.ok(recordId);
}

@PutMapping("/{recordId}")
public ResponseEntity<Long> updateRecord(@PathVariable Long recordId, @RequestBody RequestRecord requestRecord) {
Long updateRecord = recordService.updateRecord(recordId, requestRecord);
return ResponseEntity.ok(updateRecord);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.bookmile.backend.domain.record.dto;

import com.bookmile.backend.domain.image.entity.Image;
import com.bookmile.backend.domain.record.entity.Record;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class RecordListResponse {
private Long recordId;
private String text;
private Integer current_page;
private LocalDateTime createdAt;
private List<String> images;

public static RecordListResponse createRecord(Record record) {
kingjinyong marked this conversation as resolved.
Show resolved Hide resolved
return new RecordListResponse(
record.getId(),
record.getText(),
record.getCurrentPage(),
record.getCreatedAt(),
record.getImages().stream()
.map(Image::getImageUrl)
.collect(Collectors.toList())
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.bookmile.backend.domain.record.dto;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class RequestRecord {
private String text;
private Integer currentPage;
private List<String> imageUrls;
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.bookmile.backend.domain.record.entity;

import com.bookmile.backend.domain.image.entity.Image;
import com.bookmile.backend.domain.record.dto.RequestRecord;
import com.bookmile.backend.domain.userGroup.entity.UserGroup;
import com.bookmile.backend.global.config.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -27,18 +31,50 @@ public class Record extends BaseEntity {
@Column(name = "record_id")
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "usergroup_id", nullable = false)
private UserGroup userGroup;

@OneToMany
@JoinColumn(name = "record_id")
private List<Image> image = new ArrayList<>();
private List<Image> images = new ArrayList<>();
kingjinyong marked this conversation as resolved.
Show resolved Hide resolved

@Column
private String text;

@Column(nullable = false)
private Integer currentPage;

public Record(String text, Integer currentPage) {
public Record(UserGroup userGroup, String text, Integer currentPage, List<Image> images) {
this.userGroup = userGroup;
this.text = text;
this.currentPage = currentPage;
this.images = images;
}

public static Record From(UserGroup userGroup, RequestRecord requestRecord) {
kingjinyong marked this conversation as resolved.
Show resolved Hide resolved
List<Image> imageList = new ArrayList<>();
for (String imageUrl : requestRecord.getImageUrls()) {
Image image = new Image(imageUrl);
imageList.add(image);
}

return new Record(
userGroup,
requestRecord.getText(),
requestRecord.getCurrentPage(),
imageList
);
}

public void update(RequestRecord requestRecord) {
List<Image> imageList = new ArrayList<>();
for (String imageUrl : requestRecord.getImageUrls()) {
Image image = new Image(imageUrl);
imageList.add(image);
}
this.text = requestRecord.getText();
this.currentPage = requestRecord.getCurrentPage();
this.images = imageList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.bookmile.backend.domain.record.repository;

import com.bookmile.backend.domain.record.entity.Record;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface RecordRepository extends JpaRepository<Record, Long> {
List<Record> findAllByUserGroupId(Long userGroupId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.bookmile.backend.domain.record.service;

import com.bookmile.backend.domain.group.entity.Group;
import org.springframework.data.jpa.repository.JpaRepository;

public interface GroupRepository extends JpaRepository<Group, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.bookmile.backend.domain.record.service;

import com.bookmile.backend.domain.group.entity.Group;
import com.bookmile.backend.domain.record.dto.RecordListResponse;
import com.bookmile.backend.domain.record.dto.RequestRecord;
import com.bookmile.backend.domain.record.entity.Record;
import com.bookmile.backend.domain.record.repository.RecordRepository;
import com.bookmile.backend.domain.review.service.UserRepository;
import com.bookmile.backend.domain.user.entity.User;
import com.bookmile.backend.domain.userGroup.entity.UserGroup;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class RecordService {
private final UserRepository userRepository;
private final GroupRepository groupRepository;
private final UserGroupRepository userGroupRepository;
private final RecordRepository recordRepository;

public List<RecordListResponse> viewRecordList(Long groupId, Long userId) {
Group group = groupRepository.findById(groupId)
.orElseThrow(() -> new IllegalArgumentException("없는 그룹입니다."));
User user = userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("없는 사용자입니다."));

Long userGroupId = userGroupRepository.findUserGroupIdByGroupIdAndUserId(groupId, userId)
.orElseThrow(() -> new IllegalArgumentException("해당 그룹에 속하지 않은 사용자입니다."));

return recordRepository.findAllByUserGroupId(userGroupId).stream()
.map(RecordListResponse::createRecord)
.toList();
}

public Long createRecord(Long groupId, Long userId, RequestRecord requestRecord) {
Group group = groupRepository.findById(groupId)
.orElseThrow(() -> new IllegalArgumentException("없는 그룹입니다."));
User user = userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("없는 사용자입니다."));

Long userGroupId = userGroupRepository.findUserGroupIdByGroupIdAndUserId(groupId, userId)
.orElseThrow(() -> new IllegalArgumentException("해당 그룹에 속하지 않은 사용자입니다."));

UserGroup userGroup = userGroupRepository.findUserGroupById(userGroupId);

Record record = Record.From(userGroup, requestRecord);
recordRepository.save(record);

return record.getId();
}

public Long updateRecord(Long recordId, RequestRecord requestRecord) {
Record record = recordRepository.findById(recordId)
.orElseThrow(() -> new IllegalArgumentException("없는 기록입니다."));

record.update(requestRecord);

return record.getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.bookmile.backend.domain.record.service;

import com.bookmile.backend.domain.userGroup.entity.UserGroup;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface UserGroupRepository extends JpaRepository<UserGroup, Long> {

@Query(value = "SELECT usergroup_id FROM user_group WHERE group_id = :groupId AND user_id = :userId", nativeQuery = true)
Optional<Long> findUserGroupIdByGroupIdAndUserId(Long groupId, Long userId);

UserGroup findUserGroupById(Long userGroupId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.bookmile.backend.domain.review.controller;

import com.bookmile.backend.domain.review.dto.ReviewListResponse;
import com.bookmile.backend.domain.review.dto.ReviewRequest;
import com.bookmile.backend.domain.review.service.ReviewService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1/reviews")
@RequiredArgsConstructor
public class ReviewController {
private final ReviewService reviewService;

@GetMapping
public ResponseEntity<List<ReviewListResponse>> viewReviewList(@RequestParam Long bookId) {
List<ReviewListResponse> reviews = reviewService.viewReviewList(bookId);
return ResponseEntity.ok(reviews);
}

@PostMapping
public ResponseEntity<Long> createReview(@RequestParam Long bookId, @RequestParam Long userId,
@RequestBody ReviewRequest reviewRequest) {
Long createReview = reviewService.createReview(bookId, userId, reviewRequest);
return ResponseEntity.ok(createReview);
}

@PutMapping("/{reviewId}")
public ResponseEntity<Long> updateReview(@PathVariable Long reviewId, @RequestBody ReviewRequest reviewRequest) {
Long updateReview = reviewService.updateReview(reviewId, reviewRequest);
return ResponseEntity.ok(updateReview);
}

@DeleteMapping("/{reviewId}")
public ResponseEntity<Long> deleteReview(@PathVariable Long reviewId) {
Long deleteReview = reviewService.deleteReview(reviewId);
return ResponseEntity.ok(deleteReview);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.bookmile.backend.domain.review.dto;

import com.bookmile.backend.domain.review.entity.Review;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class ReviewListResponse {
private Long userId;
private String name;
private Double rating;
private String text;

public static ReviewListResponse createReview(Review review) {
return new ReviewListResponse(
review.getId(),
review.getUser().getName(),
review.getRating(),
review.getText()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.bookmile.backend.domain.review.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class ReviewRequest {
private Double rating;
private String text;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bookmile.backend.domain.review.entity;

import com.bookmile.backend.domain.book.entity.Book;
import com.bookmile.backend.domain.review.dto.ReviewRequest;
import com.bookmile.backend.domain.user.entity.User;
import com.bookmile.backend.global.config.BaseEntity;
import jakarta.persistence.Column;
Expand Down Expand Up @@ -50,4 +51,22 @@ public Review(User user, Book book, Double rating, String text) {
this.rating = rating;
this.text = text;
}

public static Review from(User user, Book book, ReviewRequest reviewRequest) {
return new Review(
user,
book,
reviewRequest.getRating(),
reviewRequest.getText()
);
}

public void update(ReviewRequest reviewRequest) {
this.rating = reviewRequest.getRating();
this.text = reviewRequest.getText();
}

public void delete(Review review) {
this.isDeleted = Boolean.TRUE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.bookmile.backend.domain.review.repository;

import com.bookmile.backend.domain.review.entity.Review;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ReviewRepository extends JpaRepository<Review, Long> {

List<Review> findAllByBookId(Long bookId);

List<Review> findAllByUserId(Long userId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.bookmile.backend.domain.review.service;

import com.bookmile.backend.domain.book.entity.Book;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BookRepository extends JpaRepository<Book, Long> {
}
Loading