Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0a7ff1e
:sparkles: feat: 전시 제작자 follow 여부 데이터 추가한 dto 추가 (#67)
Yerim1ee Dec 11, 2024
105a7a9
:sparkles: feat: 전시 댓글 작성자 이미지 및 좋아요 여부 반환 값 추가 (#67)
Yerim1ee Dec 11, 2024
74c5bea
:sparkles: feat: 전시 댓글 리스트 작성자 이미지 및 좋아요 여부 반환 값 추가 (#67)
Yerim1ee Dec 11, 2024
0952455
:sparkles: feat: 전시 등록자 정보, 좋아요 여부 정보 반환 추가 (#67)
Yerim1ee Dec 11, 2024
23a6544
:bug: fix: 반환 dto 수정에 따른 반환 값 변경 (#67)
Yerim1ee Dec 11, 2024
ef89d22
:bug: fix: 하트 여부, 팔로우 여부 등 확인을 위해 user 받아오는 매개변수 추가 (#67)
Yerim1ee Dec 12, 2024
aa61e48
:recycle: refactor: 응답 반환 코드 간단화 (#67)
Yerim1ee Dec 12, 2024
be14f1c
:sparkles: feat: 작품 좋아요 정보 반환 추가 (#67)
Yerim1ee Dec 12, 2024
053b6c0
:sparkles: feat: 작품 좋아요 정보 반환 기능 추가 (#67)
Yerim1ee Dec 12, 2024
5a8c5b9
:bug: fix: 작품 좋아요 정보 반환을 위해 사용자 정보 받아오도록 수정 (#67)
Yerim1ee Dec 12, 2024
269e108
:sparkles: feat: 사용자 팔로우 수 기반 추천 기능 추가 (#69)
Yerim1ee Dec 12, 2024
53fccd2
:sparkles: feat: 사용자 팔로우 수 기반 추천 API 추가 (#69)
Yerim1ee Dec 12, 2024
0f74af0
:memo: docs: 사용자 추천 작가 여부 선택 가능하도록 필드 추가한 부분 문서화 (#69)
Yerim1ee Dec 12, 2024
738e359
:sparkles: feat: 컬렉션 작품 찾기 JPA 메서드 추가 (#64)
Yerim1ee Dec 12, 2024
b2a4980
:sparkles: feat: 컬렉션 삭제 기능 추가 (#64)
Yerim1ee Dec 12, 2024
86bf025
:sparkles: feat: 컬렉션 삭제 API 추가 (#64)
Yerim1ee Dec 12, 2024
746a748
:sparkles: feat: 사용자 팔로우 수 기반 추천 응답 dto 추가 (#64)
Yerim1ee Dec 12, 2024
01ea069
:sparkles: feat: 사용자 팔로우 수 기반 추천 응답 dto 추가 (#69)
Yerim1ee Dec 12, 2024
beab3f8
Merge pull request #72 from CheriC-2024/main
yerim123456 Dec 12, 2024
6acd8db
:sparkles: feat: 가장 최근의 작품 1개 가져오기 JPA 메서드 추가 (#69)
Yerim1ee Dec 12, 2024
271175e
Merge branch 'feat/#69/user-hot-list-api' of https://github.com/Cheri…
Yerim1ee Dec 12, 2024
79dc7cd
:memo: docs: 전시 리스트 조회, 댓글 리스트 조회 API 문서화 (#67)
Yerim1ee Dec 12, 2024
de2d05c
:memo: docs: 분야 기반 사용자 추천 리스트API 문서화 (#69)
Yerim1ee Dec 12, 2024
c591f3c
:memo: docs: 컬렉션 삭제 API 문서화 (#64)
Yerim1ee Dec 12, 2024
2b27e43
Merge pull request #71 from CheriC-2024/feat/#69/user-hot-list-api
yerim123456 Dec 12, 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
Expand Up @@ -47,7 +47,7 @@ public ResponseEntity<ResponseDto> postArtistArt(@RequestAttribute("user") User
@GetMapping("/{id}")
public ResponseEntity<ResponseDto> getArt(@RequestAttribute("user") User user,
@PathVariable("id") Long artId) {
ArtResDto resDto = artService.getArt(artId);
ArtResDto resDto = artService.getArt(user, artId);
return ResponseEntity.status(200).body(DataResponseDto.of(resDto, 200));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import com.art.cheric.module.art.domain.entity.Art;
import com.art.cheric.module.art.domain.repository.custom.ArtRepositoryCustom;
import java.util.List;
import org.springframework.data.domain.Pageable;
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;

import java.util.Optional;
Expand All @@ -11,4 +15,8 @@
@Repository
public interface ArtRepository extends JpaRepository<Art, Long>, ArtRepositoryCustom {
Optional<Art> findByIdAndUserId(Long id, Long userId);

@Query("SELECT a FROM Art a WHERE a.user.id = :userId ORDER BY a.createdAt DESC")
List<Art> findMostRecentArtByUserId(@Param("userId") Long userId, Pageable pageable);

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ public class ArtResDto {
@Schema(description = "소장 작품 관련 추가 정보 DTO", example = "작가 작품인 경우 나오지 않음")
private final OwnArtResDto ownArtRes;

@Schema(description = "좋아요 여부", example = "true")
private final Boolean isHeart;


public static ArtResDto of(boolean isCollectorsArt, String imgUrl, Integer cherryPrice, String name,
String artistName, String series, int horizontalSize,
int verticalSize, String material, Year madeAt, List<ArtType> artTypes,
UserResDto userRes, int heartCount, String description, OwnArtResDto ownArtRes) {
UserResDto userRes, int heartCount, String description, OwnArtResDto ownArtRes,
Boolean isHeart) {
return ArtResDto.builder()
.isCollectorsArt(isCollectorsArt)
.imgUrl(imgUrl)
Expand All @@ -80,6 +84,7 @@ public static ArtResDto of(boolean isCollectorsArt, String imgUrl, Integer cherr
.heartCount(heartCount)
.description(description)
.ownArtRes(ownArtRes)
.isHeart(isHeart)
.build();
}
}
70 changes: 46 additions & 24 deletions src/main/java/com/art/cheric/module/art/service/ArtService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,28 @@
import com.art.cheric.global.enums.ArtOrderType;
import com.art.cheric.global.enums.ArtType;
import com.art.cheric.global.error.exception.AppException;
import com.art.cheric.global.util.DateFormatUtil;
import com.art.cheric.module.art.domain.entity.*;
import com.art.cheric.module.art.domain.repository.*;
import com.art.cheric.module.art.domain.entity.Art;
import com.art.cheric.module.art.domain.entity.ArtFile;
import com.art.cheric.module.art.domain.entity.ArtHeart;
import com.art.cheric.module.art.domain.entity.ArtPart;
import com.art.cheric.module.art.domain.entity.ArtPlusImage;
import com.art.cheric.module.art.domain.entity.ArtistArt;
import com.art.cheric.module.art.domain.entity.OwnArt;
import com.art.cheric.module.art.domain.repository.ArtFileRepository;
import com.art.cheric.module.art.domain.repository.ArtHeartRepository;
import com.art.cheric.module.art.domain.repository.ArtPartRepository;
import com.art.cheric.module.art.domain.repository.ArtPlusImageRepository;
import com.art.cheric.module.art.domain.repository.ArtRepository;
import com.art.cheric.module.art.domain.repository.ArtistArtRepository;
import com.art.cheric.module.art.domain.repository.OwnArtRepository;
import com.art.cheric.module.art.dto.req.ArtReqDto;
import com.art.cheric.module.art.dto.req.OwnArtReqDto;
import com.art.cheric.module.art.dto.res.*;
import com.art.cheric.module.art.dto.res.ArtBriefListResDto;
import com.art.cheric.module.art.dto.res.ArtDescriptionResDto;
import com.art.cheric.module.art.dto.res.ArtMostBriefListResDto;
import com.art.cheric.module.art.dto.res.ArtResDto;
import com.art.cheric.module.art.dto.res.ArtTypeSortListResDto;
import com.art.cheric.module.art.dto.res.OwnArtResDto;
import com.art.cheric.module.art.error.ArtErrorCode;
import com.art.cheric.module.artist.service.ArtistService;
import com.art.cheric.module.following.service.FollowService;
Expand All @@ -17,6 +33,11 @@
import com.art.cheric.module.user.dto.res.UserBriefResDto;
import com.art.cheric.module.user.dto.res.UserResDto;
import com.art.cheric.module.user.service.UserService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
Expand All @@ -26,12 +47,6 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
Expand All @@ -54,7 +69,8 @@ public Long postOwnArt(User user, OwnArtReqDto ownArtReq) {
// art 생성
ArtReqDto artReq = ownArtReq.artBasicInfo();
Art art = artRepository.save(
Art.of(user, artReq.name(), artReq.description(), artReq.series(), artReq.material(), artReq.madeAt(), null,
Art.of(user, artReq.name(), artReq.description(), artReq.series(), artReq.material(), artReq.madeAt(),
null,
artReq.horizontalSize(), artReq.verticalSize(), artReq.imgUrl(), true));

// artPart 생성
Expand Down Expand Up @@ -105,14 +121,15 @@ public Long postArtistArt(User user, ArtReqDto artReq) {
return art.getId();
}

// 등록 체리수 유효성 검증
private void checkCherryCountValidate(ArtReqDto artReq) {
if (artReq.cherryPrice() == null || artReq.cherryPrice() < 0) {
throw new AppException(ArtErrorCode.INVALID_CHERRY_PRICE);
}
}

// 작품 상세 확인
public ArtResDto getArt(Long artId) {
public ArtResDto getArt(User user, Long artId) {
// 있는 작품인지 확인
Art art = findArtByIdWithValidation(artId);

Expand Down Expand Up @@ -147,11 +164,12 @@ public ArtResDto getArt(Long artId) {
userResDto,
art.getHeartCount(),
art.getDescription(),
OwnArtResDto.from(artPrice)
OwnArtResDto.from(artPrice),
artHeartRepository.findByArtIdAndUserId(art.getId(), user.getId()).isPresent()
);
}


// 작품 하트 추가
@Transactional
public int postHeart(User user, Long artId) {
// 유효한 작품인지 확인
Expand All @@ -174,12 +192,14 @@ public int postHeart(User user, Long artId) {
return art.getHeartCount();
}

// 해당 사용자의 해당 작품 하트가 유일한지 확인
private void checkArtHeartUnique(Long userId, Long artId) {
if (artHeartRepository.findByArtIdAndUserId(artId, userId).isPresent()) {
throw new AppException(ArtErrorCode.ART_HEART_ALREADY_EXIST);
}
}

// 하트 취소
@Transactional
public int deleteHeart(User user, Long artId) {
// 유효한 작품인지 확인
Expand Down Expand Up @@ -276,16 +296,16 @@ public void checkArtistArtValid(Long artId) {
}
}

// 작가 작품 유효성 확인
// 작가 작품 존재 여부 확인
public ArtistArt findArtistArtByArtId(Long artId) {
return artistArtRepository.findByArtId(artId).orElseThrow(
() -> new AppException(ArtErrorCode.ARTIST_ART_NOT_FOUND)
);
}


// 작품 리스트 반환
public Page<ArtBriefListResDto> getArts(User user, Boolean isFollowing, Long userId, Boolean isCollectorsArt, ArtType artType,
public Page<ArtBriefListResDto> getArts(User user, Boolean isFollowing, Long userId, Boolean isCollectorsArt,
ArtType artType,
ArtOrderType order, int page, int size) {

// 페이징 데이터 전달
Expand All @@ -298,7 +318,8 @@ public Page<ArtBriefListResDto> getArts(User user, Boolean isFollowing, Long use
}

// 필터링, 정렬에 따른 데이터 가져오기
Page<Art> arts = artRepository.getArtsBySortAndFilterAndPaging(isFollowing, followingIds, userId, isCollectorsArt, artType,
Page<Art> arts = artRepository.getArtsBySortAndFilterAndPaging(isFollowing, followingIds, userId,
isCollectorsArt, artType,
order, pageable);

// 엔티티 dto 매핑
Expand All @@ -311,9 +332,9 @@ public Page<ArtBriefListResDto> getArts(User user, Boolean isFollowing, Long use
art.getUser().getName(),
UserBriefResDto.of(
art.getUser().getId(),
art.getUser().getProfileImgUrl(),
DateFormatUtil.formatLocalDateTime(art.getCreatedAt()
)))).toList();
art.getUser().getName(),
art.getUser().getProfileImgUrl()
))).toList();

// 페이징된 결과물 반환
return new PageImpl<>(result, pageable, arts.getTotalElements());
Expand All @@ -336,7 +357,6 @@ public Page<ArtTypeSortListResDto> getArtsGroupByArtType(User user, ArtOrderType
artTypeSortListRess.add(addArtTypesArtListToArtTypeSortListRess(order, artType, true, pageable));
}


// 사용되지 않은 나머지 ArtType 이름 기반 오름차순 리스트 뽑기
List<ArtType> remainingArtTypes = Arrays.stream(ArtType.values())
.filter(artType -> !excludedArtTypes.contains(artType))
Expand All @@ -353,9 +373,11 @@ public Page<ArtTypeSortListResDto> getArtsGroupByArtType(User user, ArtOrderType
}

// 작품 분야에 따라 작품 리스트 paging 해서 가져오는 메서드
private ArtTypeSortListResDto addArtTypesArtListToArtTypeSortListRess(ArtOrderType order, ArtType artType, boolean isUserPreference, Pageable pageable) {
private ArtTypeSortListResDto addArtTypesArtListToArtTypeSortListRess(ArtOrderType order, ArtType artType,
boolean isUserPreference, Pageable pageable) {
// 소장 작품만 해당하는 artType에 맞춰 가져오기
Page<Art> arts = artRepository.getArtsBySortAndFilterAndPaging(null, null, null, false, artType, order, pageable);
Page<Art> arts = artRepository.getArtsBySortAndFilterAndPaging(null, null, null, false, artType, order,
pageable);

// 엔티티 dto 매핑
return ArtTypeSortListResDto.of(artType.getValue(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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;
Expand All @@ -39,9 +40,9 @@ public ResponseEntity<ResponseDto> postCollection(@RequestAttribute("user") User
return ResponseEntity.status(201).body(ResponseDto.of(201, collectionId + " 컬렉션이 생성되었습니다."));
}

@PostMapping("/{collectionId}/art")
@PostMapping("/{id}/art")
public ResponseEntity<ResponseDto> postCollectionArt(@RequestAttribute("user") User user,
@PathVariable("collectionId") Long collectionId,
@PathVariable("id") Long collectionId,
@RequestBody @Valid ArtIdListReqDto artIdListReq) {
collectionService.postCollectionArt(user, collectionId, artIdListReq);
return ResponseEntity.status(201).body(ResponseDto.of(201));
Expand All @@ -61,4 +62,11 @@ public ResponseEntity<ResponseDto> getSelfCollectionList(@RequestAttribute("user
order);
return ResponseEntity.status(200).body(DataResponseDto.of(resDtos, 200));
}

@DeleteMapping("/{id}")
public ResponseEntity<ResponseDto> deleteCollection(@RequestAttribute("user") User user,
@PathVariable("id") Long collectionId){
collectionService.deleteCollection(user, collectionId);
return ResponseEntity.ok(ResponseDto.of(200));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,5 +244,18 @@ public interface CollectionControllerDocs {
})
ResponseEntity<ResponseDto> getSelfCollectionList(User user, CollectionIdListReqDto collectionIdListReq,
BasicOrderType sortType);

@Operation(summary = "컬렉션 삭제 API", description = "컬렉션을 삭제합니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Ok",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ResponseDto.class),
examples =
@ExampleObject(value = "{ \"code\": 200, \"message\": \"Ok\" }")
)
),
})
ResponseEntity<ResponseDto> deleteCollection(User user, Long collectionId);
}

Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.art.cheric.module.collection.domain.repository;

import com.art.cheric.module.collection.domain.entity.CollectionArt;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CollectionArtRepository extends JpaRepository<CollectionArt, Long> {
Optional<CollectionArt> findByCollectionIdAndArtId(Long collectionId, Long artId);
List<CollectionArt> findByCollectionId(Long collectionId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,21 @@ public void postCollectionArt(User user, Long collectionId, ArtIdListReqDto artI
collectionArtRepository.saveAll(collectionArts);
}

// 컬렉션 삭제
@Transactional
public void deleteCollection(User user, Long collectionId){
// 있는 컬렉션인지 확인
Collection collection = collectionRepository.findByIdAndUserId(collectionId, user.getId()).orElseThrow(
() -> new AppException(CollectionErrorCode.COLLECTION_NOT_FOUND)
);

// 작품 리스트 삭제
collectionArtRepository.deleteAll(collectionArtRepository.findByCollectionId(collectionId));

// 컬렉션 삭제
collectionRepository.delete(collection);
}

// 작품 리스트에 없는 작품인지 확인
private void checkCollectionArtIsUnique(Long collectionId, Long artId) {
if (collectionArtRepository.findByCollectionIdAndArtId(collectionId, artId).isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ public ResponseEntity<ResponseDto> postExhibition(@RequestAttribute("user") User
}

@GetMapping("/{id}")
public ResponseEntity<ResponseDto> getExhibitionContent(@PathVariable(name = "id") Long exhibitionId) {
ExhibitionResDto resDto = exhibitionService.getExhibitionContent(exhibitionId);
public ResponseEntity<ResponseDto> getExhibitionContent(@RequestAttribute("user") User user,
@PathVariable(name = "id") Long exhibitionId) {
ExhibitionResDto resDto = exhibitionService.getExhibitionContent(user, exhibitionId);
return ResponseEntity.status(200).body(DataResponseDto.of(resDto, 200));
}

Expand All @@ -72,7 +73,7 @@ public ResponseEntity<ResponseDto> postReview(@RequestAttribute("user") User use
}

@PostMapping("/{id}/reviews/{reviewId}")
public ResponseEntity<ResponseDto> postReview(@RequestAttribute("user") User user,
public ResponseEntity<ResponseDto> postReReview(@RequestAttribute("user") User user,
@PathVariable(name = "id") Long exhibitionId,
@PathVariable(name = "reviewId") Long reviewId,
@RequestBody @Valid ExhibitionReviewReqDto exhibitionReviewReq) {
Expand Down Expand Up @@ -118,19 +119,21 @@ public ResponseEntity<ResponseDto> getExhibitions(
}

@GetMapping("/{id}/reviews")
public ResponseEntity<ResponseDto> getExhibitionReviews(@PathVariable(name = "id") Long exhibitionId,
public ResponseEntity<ResponseDto> getExhibitionReviews(@RequestAttribute("user") User user,
@PathVariable(name = "id") Long exhibitionId,
@RequestParam(name = "page") int page,
@RequestParam(name = "size") int size) {
Page<ExhibitionReviewListResDto> resPage = exhibitionService.getExhibitionReviews(exhibitionId, page, size);
Page<ExhibitionReviewListResDto> resPage = exhibitionService.getExhibitionReviews(user, exhibitionId, page, size);
return ResponseEntity.status(200).body(
DataPageResponseDto.of(resPage.getContent(), 200, resPage.getTotalElements(),
resPage.getTotalPages(), resPage.getSize(), resPage.getNumberOfElements()));
}

@GetMapping("/{id}/reviews/{reviewId}")
public ResponseEntity<ResponseDto> getExhibitionReviews(@PathVariable(name = "id") Long exhibitionId,
public ResponseEntity<ResponseDto> getExhibitionReviews(@RequestAttribute("user") User user,
@PathVariable(name = "id") Long exhibitionId,
@PathVariable(name = "reviewId") Long reviewId) {
ExhibitionReviewDetailResDto resDto = exhibitionService.getExhibitionReviewsById(exhibitionId, reviewId);
ExhibitionReviewDetailResDto resDto = exhibitionService.getExhibitionReviewsById(user, exhibitionId, reviewId);
return ResponseEntity.status(200).body(DataResponseDto.of(resDto, 200));
}
}
Loading
Loading