diff --git a/src/main/java/com/bookmile/backend/domain/image/controller/ImageController.java b/src/main/java/com/bookmile/backend/domain/image/controller/ImageController.java new file mode 100644 index 0000000..685a036 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/image/controller/ImageController.java @@ -0,0 +1,45 @@ +package com.bookmile.backend.domain.image.controller; + +import com.bookmile.backend.domain.image.dto.req.ImageSaveReqDto; +import com.bookmile.backend.domain.image.dto.res.ImageListResDto; +import com.bookmile.backend.domain.image.service.ImageService; +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.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/images") +@RequiredArgsConstructor +public class ImageController { + + private ImageService imageService; + + @GetMapping("{recordId}") + public ResponseEntity> viewImages(@PathVariable Long recordId) { + List images = imageService.viewImages(recordId); + + return ResponseEntity.ok(images); + } + + @PostMapping + public ResponseEntity saveImages(@RequestParam Long recordId, @RequestBody ImageSaveReqDto imageSaveReqDto) { + imageService.saveImages(recordId, imageSaveReqDto); + + return ResponseEntity.ok("생성 완료!"); + } + + @DeleteMapping("{imageId}") + public ResponseEntity deleteImage(@PathVariable Long imageId) { + imageService.deleteImage(imageId); + + return ResponseEntity.ok("삭제 완료!"); + } +} diff --git a/src/main/java/com/bookmile/backend/domain/image/dto/req/ImageSaveReqDto.java b/src/main/java/com/bookmile/backend/domain/image/dto/req/ImageSaveReqDto.java new file mode 100644 index 0000000..67db6c3 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/image/dto/req/ImageSaveReqDto.java @@ -0,0 +1,11 @@ +package com.bookmile.backend.domain.image.dto.req; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ImageSaveReqDto { + private List imageUrls; +} diff --git a/src/main/java/com/bookmile/backend/domain/image/dto/res/ImageListResDto.java b/src/main/java/com/bookmile/backend/domain/image/dto/res/ImageListResDto.java new file mode 100644 index 0000000..24f191d --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/image/dto/res/ImageListResDto.java @@ -0,0 +1,17 @@ +package com.bookmile.backend.domain.image.dto.res; + +import com.bookmile.backend.domain.image.entity.Image; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ImageListResDto { + private String imageUrls; + + public static ImageListResDto createImage(Image image) { + return new ImageListResDto( + image.getImageUrl() + ); + } +} diff --git a/src/main/java/com/bookmile/backend/domain/image/entity/Image.java b/src/main/java/com/bookmile/backend/domain/image/entity/Image.java index 36b416f..77cb08a 100644 --- a/src/main/java/com/bookmile/backend/domain/image/entity/Image.java +++ b/src/main/java/com/bookmile/backend/domain/image/entity/Image.java @@ -1,11 +1,15 @@ package com.bookmile.backend.domain.image.entity; +import com.bookmile.backend.domain.record.entity.Record; 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 lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; @@ -22,10 +26,22 @@ public class Image extends BaseEntity { @Column(name = "image_id") private Long id; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "record_id", nullable = false) + private Record record; + @Column(nullable = false) private String imageUrl; - public Image(String imageUrl) { + @Column(nullable = false) + private Boolean isDeleted = Boolean.FALSE; + + public Image(Record record, String imageUrl) { + this.record = record; this.imageUrl = imageUrl; } + + public void delete(Image image) { + this.isDeleted = Boolean.TRUE; + } } diff --git a/src/main/java/com/bookmile/backend/domain/image/repository/ImageRepository.java b/src/main/java/com/bookmile/backend/domain/image/repository/ImageRepository.java new file mode 100644 index 0000000..9e6382d --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/image/repository/ImageRepository.java @@ -0,0 +1,11 @@ +package com.bookmile.backend.domain.image.repository; + +import com.bookmile.backend.domain.image.entity.Image; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ImageRepository extends JpaRepository { + List findAllByRecordId(Long recordId); +} diff --git a/src/main/java/com/bookmile/backend/domain/image/service/ImageService.java b/src/main/java/com/bookmile/backend/domain/image/service/ImageService.java new file mode 100644 index 0000000..0ac8109 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/image/service/ImageService.java @@ -0,0 +1,51 @@ +package com.bookmile.backend.domain.image.service; + +import com.bookmile.backend.domain.image.dto.req.ImageSaveReqDto; +import com.bookmile.backend.domain.image.dto.res.ImageListResDto; +import com.bookmile.backend.domain.image.entity.Image; +import com.bookmile.backend.domain.image.repository.ImageRepository; +import com.bookmile.backend.domain.record.entity.Record; +import com.bookmile.backend.domain.record.repository.RecordRepository; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ImageService { + + private final ImageRepository imageRepository; + private final RecordRepository recordRepository; + + public List viewImages(Long recordId) { + recordRepository.findById(recordId) + .orElseThrow(() -> new IllegalArgumentException("없는 recordId 입니다.")); + + return imageRepository.findAllByRecordId(recordId) + .stream() + .map(ImageListResDto::createImage) + .toList(); + } + + public void saveImages(Long recordId, ImageSaveReqDto imageSaveReqDto) { + Record record = recordRepository.findById(recordId) + .orElseThrow(() -> new IllegalArgumentException("없는 기록 ID 입니다.")); + + List images = imageSaveReqDto.getImageUrls().stream() + .map(url -> new Image(record, url)) + .toList(); + + imageRepository.saveAll(images); + } + + public Long deleteImage(Long imageId) { + Image image = imageRepository.findById(imageId) + .orElseThrow(() -> new IllegalArgumentException("없는 이미지 입니다.")); + + image.delete(image); + + imageRepository.save(image); + + return image.getId(); + } +} 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 new file mode 100644 index 0000000..c3c21db --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/controller/RecordController.java @@ -0,0 +1,45 @@ +package com.bookmile.backend.domain.record.controller; + +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.RecordListResDto; +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> viewRecordList(@RequestParam Long groupId, + @RequestParam Long userId) { + List records = recordService.viewRecordList(groupId, userId); + return ResponseEntity.ok(records); + } + + @PostMapping + public ResponseEntity createRecord(@RequestParam Long groupId, + @RequestParam Long userId, @RequestBody RecordReqDto recordReqDto) { + Long recordId = recordService.createRecord(groupId, userId, recordReqDto); + return ResponseEntity.ok(recordId); + } + + @PutMapping("/{recordId}") + public ResponseEntity updateRecord(@PathVariable Long recordId, + @RequestBody UpdateRecordReqDto updateRecordReqDto) { + Long updateRecord = recordService.updateRecord(recordId, updateRecordReqDto); + return ResponseEntity.ok(updateRecord); + } +} diff --git a/src/main/java/com/bookmile/backend/domain/record/dto/req/RecordReqDto.java b/src/main/java/com/bookmile/backend/domain/record/dto/req/RecordReqDto.java new file mode 100644 index 0000000..efa4f34 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/dto/req/RecordReqDto.java @@ -0,0 +1,11 @@ +package com.bookmile.backend.domain.record.dto.req; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class RecordReqDto { + private String text; + private Integer currentPage; +} diff --git a/src/main/java/com/bookmile/backend/domain/record/dto/req/UpdateRecordReqDto.java b/src/main/java/com/bookmile/backend/domain/record/dto/req/UpdateRecordReqDto.java new file mode 100644 index 0000000..c77ade7 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/dto/req/UpdateRecordReqDto.java @@ -0,0 +1,12 @@ +package com.bookmile.backend.domain.record.dto.req; + +import lombok.AllArgsConstructor; +import lombok.Getter; + + +@Getter +@AllArgsConstructor +public class UpdateRecordReqDto { + private String text; + private Integer currentPage; +} diff --git a/src/main/java/com/bookmile/backend/domain/record/dto/res/RecordListResDto.java b/src/main/java/com/bookmile/backend/domain/record/dto/res/RecordListResDto.java new file mode 100644 index 0000000..a6eb17a --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/dto/res/RecordListResDto.java @@ -0,0 +1,26 @@ +package com.bookmile.backend.domain.record.dto.res; + +import com.bookmile.backend.domain.record.entity.Record; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class RecordListResDto { + private Long recordId; + private String text; + private Integer currentPage; + private LocalDateTime createdAt; + + public static RecordListResDto createRecord(Record record) { + return RecordListResDto.builder() + .recordId(record.getId()) + .text(record.getText()) + .currentPage(record.getCurrentPage()) + .createdAt(record.getCreatedAt()) + .build(); + } +} \ No newline at end of file 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 940e3bd..7d52d2d 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,16 +1,17 @@ package com.bookmile.backend.domain.record.entity; -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; +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.OneToMany; -import java.util.ArrayList; -import java.util.List; +import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; @@ -27,9 +28,9 @@ public class Record extends BaseEntity { @Column(name = "record_id") private Long id; - @OneToMany - @JoinColumn(name = "record_id") - private List image = new ArrayList<>(); + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "usergroup_id", nullable = false) + private UserGroup userGroup; @Column private String text; @@ -37,8 +38,23 @@ public class Record extends BaseEntity { @Column(nullable = false) private Integer currentPage; - public Record(String text, Integer currentPage) { + public Record(UserGroup userGroup, String text, Integer currentPage) { + this.userGroup = userGroup; this.text = text; this.currentPage = currentPage; } + + public static Record from(UserGroup userGroup, RecordReqDto recordReqDto) { + + return new Record( + userGroup, + recordReqDto.getText(), + recordReqDto.getCurrentPage() + ); + } + + public void update(UpdateRecordReqDto updateRecordReqDto) { + this.text = updateRecordReqDto.getText(); + this.currentPage = updateRecordReqDto.getCurrentPage(); + } } 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 new file mode 100644 index 0000000..2a95805 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/repository/RecordRepository.java @@ -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 { + List findAllByUserGroupId(Long userGroupId); +} diff --git a/src/main/java/com/bookmile/backend/domain/record/service/GroupRepository.java b/src/main/java/com/bookmile/backend/domain/record/service/GroupRepository.java new file mode 100644 index 0000000..c2e33af --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/service/GroupRepository.java @@ -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 { +} \ No newline at end of file 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 new file mode 100644 index 0000000..5cbcd0d --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/service/RecordService.java @@ -0,0 +1,63 @@ +package com.bookmile.backend.domain.record.service; + +import com.bookmile.backend.domain.group.entity.Group; +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.RecordListResDto; +import com.bookmile.backend.domain.record.entity.Record; +import com.bookmile.backend.domain.record.repository.RecordRepository; +import com.bookmile.backend.domain.user.entity.User; +import com.bookmile.backend.domain.user.repository.UserRepository; +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 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(RecordListResDto::createRecord) + .toList(); + } + + public Long createRecord(Long groupId, Long userId, RecordReqDto recordReqDto) { + 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, recordReqDto); + recordRepository.save(record); + + return record.getId(); + } + + public Long updateRecord(Long recordId, UpdateRecordReqDto updateRecordReqDto) { + Record record = recordRepository.findById(recordId) + .orElseThrow(() -> new IllegalArgumentException("없는 기록입니다.")); + + record.update(updateRecordReqDto); + + return record.getId(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bookmile/backend/domain/record/service/UserGroupRepository.java b/src/main/java/com/bookmile/backend/domain/record/service/UserGroupRepository.java new file mode 100644 index 0000000..8c71859 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/record/service/UserGroupRepository.java @@ -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 { + + @Query(value = "SELECT usergroup_id FROM user_group WHERE group_id = :groupId AND user_id = :userId", nativeQuery = true) + Optional findUserGroupIdByGroupIdAndUserId(Long groupId, Long userId); + + UserGroup findUserGroupById(Long userGroupId); +} \ No newline at end of file diff --git a/src/main/java/com/bookmile/backend/domain/review/controller/ReviewController.java b/src/main/java/com/bookmile/backend/domain/review/controller/ReviewController.java new file mode 100644 index 0000000..8830460 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/review/controller/ReviewController.java @@ -0,0 +1,49 @@ +package com.bookmile.backend.domain.review.controller; + +import com.bookmile.backend.domain.review.dto.req.ReviewReqDto; +import com.bookmile.backend.domain.review.dto.res.ReviewListResDto; +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> viewReviewList(@RequestParam Long bookId) { + List reviews = reviewService.viewReviewList(bookId); + return ResponseEntity.ok(reviews); + } + + @PostMapping + public ResponseEntity createReview(@RequestParam Long bookId, @RequestParam Long userId, + @RequestBody ReviewReqDto reviewReqDto) { + Long createReview = reviewService.createReview(bookId, userId, reviewReqDto); + return ResponseEntity.ok(createReview); + } + + @PutMapping("/{reviewId}") + public ResponseEntity updateReview(@PathVariable Long reviewId, @RequestBody ReviewReqDto reviewReqDto) { + Long updateReview = reviewService.updateReview(reviewId, reviewReqDto); + return ResponseEntity.ok(updateReview); + } + + @DeleteMapping("/{reviewId}") + public ResponseEntity deleteReview(@PathVariable Long reviewId) { + Long deleteReview = reviewService.deleteReview(reviewId); + return ResponseEntity.ok(deleteReview); + } +} diff --git a/src/main/java/com/bookmile/backend/domain/review/dto/req/ReviewReqDto.java b/src/main/java/com/bookmile/backend/domain/review/dto/req/ReviewReqDto.java new file mode 100644 index 0000000..7eaf0bc --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/review/dto/req/ReviewReqDto.java @@ -0,0 +1,11 @@ +package com.bookmile.backend.domain.review.dto.req; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ReviewReqDto { + private Double rating; + private String text; +} diff --git a/src/main/java/com/bookmile/backend/domain/review/dto/res/ReviewListResDto.java b/src/main/java/com/bookmile/backend/domain/review/dto/res/ReviewListResDto.java new file mode 100644 index 0000000..d05750e --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/review/dto/res/ReviewListResDto.java @@ -0,0 +1,23 @@ +package com.bookmile.backend.domain.review.dto.res; + +import com.bookmile.backend.domain.review.entity.Review; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ReviewListResDto { + private Long userId; + private String name; + private Double rating; + private String text; + + public static ReviewListResDto createReview(Review review) { + return new ReviewListResDto( + review.getId(), + review.getUser().getNickname(), + review.getRating(), + review.getText() + ); + } +} diff --git a/src/main/java/com/bookmile/backend/domain/review/entity/Review.java b/src/main/java/com/bookmile/backend/domain/review/entity/Review.java index 4b94281..27a9930 100644 --- a/src/main/java/com/bookmile/backend/domain/review/entity/Review.java +++ b/src/main/java/com/bookmile/backend/domain/review/entity/Review.java @@ -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.req.ReviewReqDto; import com.bookmile.backend.domain.user.entity.User; import com.bookmile.backend.global.config.BaseEntity; import jakarta.persistence.Column; @@ -13,6 +14,7 @@ import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -44,10 +46,29 @@ public class Review extends BaseEntity { @Column(nullable = false) private Boolean isDeleted = false; + @Builder public Review(User user, Book book, Double rating, String text) { this.user = user; this.book = book; this.rating = rating; this.text = text; } + + public static Review from(User user, Book book, ReviewReqDto reviewReqDto) { + return Review.builder() + .user(user) + .book(book) + .rating(reviewReqDto.getRating()) + .text(reviewReqDto.getText()) + .build(); + } + + public void update(ReviewReqDto reviewReqDto) { + this.rating = reviewReqDto.getRating(); + this.text = reviewReqDto.getText(); + } + + public void delete(Review review) { + this.isDeleted = Boolean.TRUE; + } } diff --git a/src/main/java/com/bookmile/backend/domain/review/repository/ReviewRepository.java b/src/main/java/com/bookmile/backend/domain/review/repository/ReviewRepository.java new file mode 100644 index 0000000..928ae41 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/review/repository/ReviewRepository.java @@ -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 { + + List findAllByBookId(Long bookId); + + List findAllByUserId(Long userId); + +} diff --git a/src/main/java/com/bookmile/backend/domain/review/service/BookRepository.java b/src/main/java/com/bookmile/backend/domain/review/service/BookRepository.java new file mode 100644 index 0000000..a7417c8 --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/review/service/BookRepository.java @@ -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 { +} diff --git a/src/main/java/com/bookmile/backend/domain/review/service/ReviewService.java b/src/main/java/com/bookmile/backend/domain/review/service/ReviewService.java new file mode 100644 index 0000000..d8fdbed --- /dev/null +++ b/src/main/java/com/bookmile/backend/domain/review/service/ReviewService.java @@ -0,0 +1,65 @@ +package com.bookmile.backend.domain.review.service; + +import com.bookmile.backend.domain.book.entity.Book; +import com.bookmile.backend.domain.review.dto.req.ReviewReqDto; +import com.bookmile.backend.domain.review.dto.res.ReviewListResDto; +import com.bookmile.backend.domain.review.entity.Review; +import com.bookmile.backend.domain.review.repository.ReviewRepository; +import com.bookmile.backend.domain.user.entity.User; +import com.bookmile.backend.domain.user.repository.UserRepository; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReviewService { + private final ReviewRepository reviewRepository; + private final BookRepository bookRepository; + private final UserRepository userRepository; + + public List viewReviewList(Long bookId) { + Book book = bookRepository.findById(bookId) + .orElseThrow(() -> new IllegalArgumentException("없는 책입니다.")); + + return reviewRepository.findAllByBookId(bookId).stream() + .map(ReviewListResDto::createReview) + .collect(Collectors.toList()); + } + + public Long createReview(Long bookId, Long userId, ReviewReqDto reviewReqDto) { + Book book = bookRepository.findById(bookId) + .orElseThrow(() -> new IllegalArgumentException("없는 책입니다.")); + + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("없는 사용자입니다.")); + + Review review = Review.from(user, book, reviewReqDto); + + reviewRepository.save(review); + + return review.getId(); + } + + public Long updateReview(Long reviewId, ReviewReqDto reviewReqDto) { + Review review = reviewRepository.findById(reviewId) + .orElseThrow(() -> new IllegalArgumentException("없는 리뷰입니다.")); + + review.update(reviewReqDto); + reviewRepository.save(review); + + return review.getId(); + } + + public Long deleteReview(Long reviewId) { + Review review = reviewRepository.findById(reviewId) + .orElseThrow(() -> new IllegalArgumentException("없는 리뷰입니다.")); + + review.delete(review); + + reviewRepository.save(review); + + return review.getId(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bookmile/backend/domain/userGroup/entity/UserGroup.java b/src/main/java/com/bookmile/backend/domain/userGroup/entity/UserGroup.java index 84d8707..544d310 100644 --- a/src/main/java/com/bookmile/backend/domain/userGroup/entity/UserGroup.java +++ b/src/main/java/com/bookmile/backend/domain/userGroup/entity/UserGroup.java @@ -42,8 +42,7 @@ public class UserGroup extends BaseEntity { @JoinColumn(name = "group_id", nullable = false) private Group group; - @OneToMany - @JoinColumn(name = "usergroup_id") + @OneToMany(mappedBy = "userGroup") private List record = new ArrayList<>(); @Column(nullable = false) @@ -53,10 +52,6 @@ public class UserGroup extends BaseEntity { @Column(nullable = false) private Boolean isDeleted = false; - public void addUser(User user) { - this.user = user; - } - public UserGroup(User user, Group group, Role role) { this.user = user; this.group = group; diff --git a/src/test/java/com/bookmile/backend/domain/image/service/ImageServiceTest.java b/src/test/java/com/bookmile/backend/domain/image/service/ImageServiceTest.java new file mode 100644 index 0000000..c766467 --- /dev/null +++ b/src/test/java/com/bookmile/backend/domain/image/service/ImageServiceTest.java @@ -0,0 +1,121 @@ +package com.bookmile.backend.domain.image.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.bookmile.backend.domain.book.entity.Book; +import com.bookmile.backend.domain.group.entity.Group; +import com.bookmile.backend.domain.group.entity.Role; +import com.bookmile.backend.domain.image.dto.req.ImageSaveReqDto; +import com.bookmile.backend.domain.image.dto.res.ImageListResDto; +import com.bookmile.backend.domain.image.entity.Image; +import com.bookmile.backend.domain.image.repository.ImageRepository; +import com.bookmile.backend.domain.record.entity.Record; +import com.bookmile.backend.domain.record.repository.RecordRepository; +import com.bookmile.backend.domain.record.service.GroupRepository; +import com.bookmile.backend.domain.record.service.RecordService; +import com.bookmile.backend.domain.record.service.UserGroupRepository; +import com.bookmile.backend.domain.review.service.BookRepository; +import com.bookmile.backend.domain.user.entity.User; +import com.bookmile.backend.domain.user.repository.UserRepository; +import com.bookmile.backend.domain.userGroup.entity.UserGroup; +import jakarta.transaction.Transactional; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@Transactional +class ImageServiceTest { + @Autowired + private BookRepository bookRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private GroupRepository groupRepository; + + @Autowired + private UserGroupRepository userGroupRepository; + + @Autowired + private RecordRepository recordRepository; + + @Autowired + private RecordService recordService; + + @Autowired + private ImageRepository imageRepository; + + @Autowired + private ImageService imageService; + + private Book book; + private User user; + private Group group; + private UserGroup userGroup; + private Record record; + + @BeforeEach + void setUp() { + book = new Book("김진용의 인생", 456, "image", "김진용", "책설명", "링크url", 5.0); + bookRepository.save(book); + + user = new User("김진용", "kje@naver.com", "1234", "urlurl"); + userRepository.save(user); + + group = new Group(book, null, null, "독서 그룹", "독서를 위한 그룹", 1234L, true, false); + groupRepository.save(group); + + userGroup = new UserGroup(user, group, Role.MASTER); + userGroupRepository.save(userGroup); + + record = new Record(userGroup, "재미있네", 159); + recordRepository.save(record); + } + + @Test + void 기록에_이미지_저장() { + //When + imageService.saveImages(record.getId(), new ImageSaveReqDto(List.of("url1", "url2", "url3"))); + + List images = imageRepository.findAllByRecordId(record.getId()); + + //Then + assertEquals(3, images.size()); + } + + @Test + void 기록_이미지_조회() { + //When + imageService.saveImages(record.getId(), new ImageSaveReqDto(List.of("url1", "url2", "url3"))); + List imageUrls = imageService.viewImages(record.getId()); + + //Then + assertEquals("url1", imageUrls.get(0).getImageUrls()); + assertEquals("url2", imageUrls.get(1).getImageUrls()); + assertEquals("url3", imageUrls.get(2).getImageUrls()); + } + + @Test + void 기록_이미지_삭제() { + //When + imageService.saveImages(record.getId(), new ImageSaveReqDto(List.of("url1", "url2", "url3"))); + List images = imageRepository.findAllByRecordId(record.getId()); + + // 삭제 전 + assertEquals(Boolean.FALSE, images.get(0).getIsDeleted()); + assertEquals(Boolean.FALSE, images.get(1).getIsDeleted()); + assertEquals(Boolean.FALSE, images.get(2).getIsDeleted()); + + //Then + imageService.deleteImage(images.get(1).getId()); + + // 삭제 후 + assertEquals(Boolean.FALSE, images.get(0).getIsDeleted()); + assertEquals(Boolean.TRUE, images.get(1).getIsDeleted()); + assertEquals(Boolean.FALSE, images.get(2).getIsDeleted()); + } +} \ No newline at end of file diff --git a/src/test/java/com/bookmile/backend/domain/record/service/RecordServiceTest.java b/src/test/java/com/bookmile/backend/domain/record/service/RecordServiceTest.java new file mode 100644 index 0000000..7905676 --- /dev/null +++ b/src/test/java/com/bookmile/backend/domain/record/service/RecordServiceTest.java @@ -0,0 +1,125 @@ +package com.bookmile.backend.domain.record.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.bookmile.backend.domain.book.entity.Book; +import com.bookmile.backend.domain.group.entity.Group; +import com.bookmile.backend.domain.group.entity.Role; +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.RecordListResDto; +import com.bookmile.backend.domain.record.entity.Record; +import com.bookmile.backend.domain.record.repository.RecordRepository; +import com.bookmile.backend.domain.review.service.BookRepository; +import com.bookmile.backend.domain.user.entity.User; +import com.bookmile.backend.domain.user.repository.UserRepository; +import com.bookmile.backend.domain.userGroup.entity.UserGroup; +import jakarta.transaction.Transactional; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@Transactional +class RecordServiceTest { + + @Autowired + private BookRepository bookRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private GroupRepository groupRepository; + + @Autowired + private UserGroupRepository userGroupRepository; + + @Autowired + private RecordRepository recordRepository; + + @Autowired + private RecordService recordService; + + private Book book; + private User user; + private Group group; + private UserGroup userGroup; + + @BeforeEach + void setUp() { + book = new Book("김진용의 인생", 456, "image", "김진용", "책설명", "링크url", 5.0); + bookRepository.save(book); + + user = new User("김진용", "kje@naver.com", "1234", "urlurl"); + userRepository.save(user); + + group = new Group(book, null, null, "독서 그룹", "독서를 위한 그룹", 1234L, true, false); + groupRepository.save(group); + + userGroup = new UserGroup(user, group, Role.MASTER); + userGroupRepository.save(userGroup); + } + + @Test + void 사용자의_그룹에서의_기록_생성() { + //When + Long recordId1 = recordService.createRecord(group.getId(), user.getId(), + new RecordReqDto("나의 기록1", 193)); + Record record = recordRepository.findById(recordId1).orElseThrow(); + + //Then + assertEquals("나의 기록1", record.getText()); + assertEquals(193, record.getCurrentPage()); + } + + @Transactional + @Test + void 사용자의_그룹에_해당하는_기록_불러오기() { + //Given + recordService.createRecord( + group.getId(), + user.getId(), + new RecordReqDto("기록1", 193)); + + recordService.createRecord( + group.getId(), + user.getId(), + new RecordReqDto("기록2", 234)); + + //When + List records = recordService.viewRecordList(group.getId(), user.getId()); + + //Then + assertEquals(2, records.size()); + assertEquals("기록1", records.get(0).getText()); + assertEquals("기록2", records.get(1).getText()); + assertEquals(193, records.get(0).getCurrentPage()); + assertEquals(234, records.get(1).getCurrentPage()); + } + + @Transactional + @Test + void 기록_수정() { + //When + // 일단 생성 + Long recordId = recordService.createRecord(group.getId(), user.getId(), + new RecordReqDto("나의 기록1", 193)); + Record record1 = recordRepository.findById(recordId).orElseThrow(); + + // 수정 전 + assertEquals("나의 기록1", record1.getText()); + + // 그리고 수정 + Long updateRecord = recordService.updateRecord(recordId, + new UpdateRecordReqDto("나의 수정한 기록1", 193)); + Record record2 = recordRepository.findById(updateRecord).orElseThrow(); + + //Then + assertEquals(record1.getId(), record2.getId()); + // 수정 후 + assertEquals("나의 수정한 기록1", record2.getText()); + } +} \ No newline at end of file diff --git a/src/test/java/com/bookmile/backend/domain/review/repository/ReviewRepositoryTest.java b/src/test/java/com/bookmile/backend/domain/review/repository/ReviewRepositoryTest.java new file mode 100644 index 0000000..ea0b5e3 --- /dev/null +++ b/src/test/java/com/bookmile/backend/domain/review/repository/ReviewRepositoryTest.java @@ -0,0 +1,67 @@ +package com.bookmile.backend.domain.review.repository; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.bookmile.backend.domain.book.entity.Book; +import com.bookmile.backend.domain.review.entity.Review; +import com.bookmile.backend.domain.user.entity.User; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; + +@DataJpaTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +class ReviewRepositoryTest { + + @Autowired + private ReviewRepository reviewRepository; + + @Autowired + private TestEntityManager testEntityManager; + + @Test + void 책_리뷰_책_ID로_조회_올바른_갯수_반환_테스트() { + //Given + User user1 = new User("김진용", "kje@naver.com", "1234", "urlurl"); + Book book1 = new Book("김진용의 인생", 456, "image", "김진용", "책설명", "링크url", 5.0); + + testEntityManager.persist(user1); + testEntityManager.persist(book1); + + Review review1 = new Review(user1, book1, 4.5, "굳이에요 굳"); + reviewRepository.save(review1); + + //When + List reviews = reviewRepository.findAllByBookId(book1.getId()); + + //Then + assertEquals(1, reviews.size()); + } + + + @Test + void 책_리뷰_사용자_ID로_조회_올바른_갯수_반환_테스트() { + //Given + User user1 = new User("김진용", "kje@naver.com", "1234", "urlurl"); + Book book1 = new Book("김진용의 인생", 456, "image", "김진용", "책설명", "링크url", 5.0); + Book book2 = new Book("김진용의 인생2", 456, "image", "김진용", "책설명", "링크url", 5.0); + + testEntityManager.persist(user1); + testEntityManager.persist(book1); + testEntityManager.persist(book2); + + Review review1 = new Review(user1, book1, 4.5, "굳이에요 굳"); + Review review2 = new Review(user1, book2, 4.5, "이번에도 굳이에요 굳"); + reviewRepository.save(review1); + reviewRepository.save(review2); + + //When + List reviews = reviewRepository.findAllByUserId(user1.getId()); + + //Then + assertEquals(2, reviews.size()); + } +} \ No newline at end of file diff --git a/src/test/java/com/bookmile/backend/domain/review/service/ReviewServiceTest.java b/src/test/java/com/bookmile/backend/domain/review/service/ReviewServiceTest.java new file mode 100644 index 0000000..403ad08 --- /dev/null +++ b/src/test/java/com/bookmile/backend/domain/review/service/ReviewServiceTest.java @@ -0,0 +1,125 @@ +package com.bookmile.backend.domain.review.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.bookmile.backend.domain.book.entity.Book; +import com.bookmile.backend.domain.review.dto.req.ReviewReqDto; +import com.bookmile.backend.domain.review.dto.res.ReviewListResDto; +import com.bookmile.backend.domain.review.entity.Review; +import com.bookmile.backend.domain.review.repository.ReviewRepository; +import com.bookmile.backend.domain.user.entity.User; +import com.bookmile.backend.domain.user.repository.UserRepository; +import jakarta.transaction.Transactional; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@Transactional +class ReviewServiceTest { + + @Autowired + private ReviewService reviewService; + + @Autowired + private ReviewRepository reviewRepository; + + @Autowired + private BookRepository bookRepository; + + @Autowired + private UserRepository userRepository; + + @Test + @Transactional + void Book_Id로_리뷰_리스트_가져오기() { + // Given + User user1 = new User("김진용", "kje@naver.com", "1234", "urlurl"); + User user2 = new User("진용짱", "jin@naver.com", "5678", "urlurl2"); + Book book = new Book("김진용의 인생", 456, "image", "김진용", "책설명", "링크url", 5.0); + + userRepository.save(user1); + userRepository.save(user2); + bookRepository.save(book); + + Review review1 = new Review(user1, book, 4.5, "굳이에요 굳"); + Review review2 = new Review(user2, book, 4.0, "좋아요!"); + + reviewRepository.save(review1); + reviewRepository.save(review2); + + // When + List reviews = reviewService.viewReviewList(book.getId()); + + // Then + assertEquals(2, reviews.size()); + assertEquals("굳이에요 굳", reviews.get(0).getText()); + assertEquals("좋아요!", reviews.get(1).getText()); + } + + @Test + void 리뷰_생성하기() { + // Given + User user = new User("김진용", "kje@naver.com", "1234", "urlurl"); + Book book = new Book("김진용의 인생", 456, "image", "김진용", "책설명", "링크url", 5.0); + + userRepository.save(user); + bookRepository.save(book); + + ReviewReqDto reviewReqDto = new ReviewReqDto(4.5, "굳굳"); + + // When + Long reviewId = reviewService.createReview(book.getId(), user.getId(), reviewReqDto); + + // Then + Review review = reviewRepository.findById(reviewId).orElseThrow(); + assertEquals(4.5, review.getRating()); + assertEquals("굳굳", review.getText()); + } + + @Test + void 리뷰_수정하기() { + // Given + User user = new User("김진용", "kje@naver.com", "1234", "urlurl"); + Book book = new Book("김진용의 인생", 456, "image", "김진용", "책설명", "링크url", 5.0); + + userRepository.save(user); + bookRepository.save(book); + + Review review = new Review(user, book, 4.5, "굳이에요 굳"); + + reviewRepository.save(review); + + ReviewReqDto reviewReqDto = new ReviewReqDto(1.0, "다시 생각해보니 별로네요."); + + // When + Long reviewId = reviewService.updateReview(review.getId(), reviewReqDto); + + // Then + Review updateReview = reviewRepository.findById(reviewId).orElseThrow(); + assertEquals(1.0, updateReview.getRating()); + assertEquals("다시 생각해보니 별로네요.", updateReview.getText()); + } + + @Test + void 리뷰_삭제하기() { + // Given + User user = new User("김진용", "kje@naver.com", "1234", "urlurl"); + Book book = new Book("김진용의 인생", 456, "image", "김진용", "책설명", "링크url", 5.0); + + userRepository.save(user); + bookRepository.save(book); + + Review review = new Review(user, book, 4.5, "굳이에요 굳"); + + reviewRepository.save(review); + + // When + Long reviewId = reviewService.deleteReview(review.getId()); + + // Then + Review deleteReview = reviewRepository.findById(reviewId).orElseThrow(); + assertEquals(Boolean.TRUE, deleteReview.getIsDeleted()); + } +}