diff --git a/kilometer-backend-api/src/main/java/com/kilometer/backend/controller/ArchiveController.java b/kilometer-backend-api/src/main/java/com/kilometer/backend/controller/ArchiveController.java index bf8f19de..a76edc72 100644 --- a/kilometer-backend-api/src/main/java/com/kilometer/backend/controller/ArchiveController.java +++ b/kilometer-backend-api/src/main/java/com/kilometer/backend/controller/ArchiveController.java @@ -1,6 +1,7 @@ package com.kilometer.backend.controller; -import com.kilometer.domain.archive.ArchiveService; +import com.kilometer.domain.archive.request.ArchiveCreateRequest; +import com.kilometer.domain.archive.service.ArchiveService; import com.kilometer.domain.archive.dto.ArchiveDeleteResponse; import com.kilometer.domain.archive.dto.ArchiveDetailResponse; import com.kilometer.domain.archive.dto.ArchiveInfo; @@ -8,7 +9,7 @@ import com.kilometer.domain.archive.dto.ArchiveSortType; import com.kilometer.domain.archive.dto.MyArchiveResponse; import com.kilometer.domain.archive.like.dto.LikeResponse; -import com.kilometer.domain.archive.request.ArchiveRequest; +import com.kilometer.domain.archive.request.ArchiveUpdateRequest; import com.kilometer.domain.dto.GeneralResponse; import com.kilometer.domain.paging.RequestPagingStatus; import com.kilometer.domain.util.ApiUrlUtils; @@ -60,7 +61,7 @@ public ArchiveDetailResponse archive( @PostMapping(ApiUrlUtils.ARCHIVE_ROOT) @ApiOperation(value = "신규 아카이브 등록") public ArchiveInfo saveArchive( - @ApiParam(value = "등록할 아카이브 데이터", required = true) @RequestBody ArchiveRequest request) { + @ApiParam(value = "등록할 아카이브 데이터", required = true) @RequestBody ArchiveCreateRequest request) { long userId = getLoginUserId(); return archiveService.save(userId, request); } @@ -69,7 +70,7 @@ public ArchiveInfo saveArchive( @ApiOperation(value = "아카이브 수정") public ArchiveInfo updateArchive( @ApiParam(value = "수정할 아카이브 아이디", required = true) @PathVariable Long archiveId, - @ApiParam(value = "수정할 아카이브 데이터", required = true) @RequestBody ArchiveRequest request) { + @ApiParam(value = "수정할 아카이브 데이터", required = true) @RequestBody ArchiveUpdateRequest request) { long userId = getLoginUserId(); return archiveService.update(userId, archiveId, request); } diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveAggregateConverter.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveAggregateConverter.java index 1309ca48..d1b09f57 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveAggregateConverter.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveAggregateConverter.java @@ -8,26 +8,26 @@ import com.kilometer.domain.archive.dto.ItemArchiveDto; import com.kilometer.domain.archive.dto.MyArchiveDto; import com.kilometer.domain.archive.dto.MyArchiveInfo; +import com.kilometer.domain.archive.like.dto.ArchiveLike; +import com.kilometer.domain.archive.like.dto.ArchiveLikeGenerator; import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; import com.kilometer.domain.badge.ItemBadge; import com.kilometer.domain.badge.ItemBadgeGenerator; import com.kilometer.domain.item.dto.ItemSummary; import com.kilometer.domain.item.enumType.ExhibitionType; -import com.kilometer.domain.archive.like.dto.ArchiveLike; -import com.kilometer.domain.archive.like.dto.ArchiveLikeGenerator; import com.kilometer.domain.linkInfo.LinkInfo; -import com.kilometer.domain.user.dto.UserResponse; +import com.kilometer.domain.user.User; import com.kilometer.domain.util.ApiUrlUtils; import com.kilometer.domain.util.FrontUrlUtils; - import java.util.List; import java.util.Map; import java.util.stream.Collectors; - import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; @Component +@Transactional @RequiredArgsConstructor public class ArchiveAggregateConverter { @@ -35,7 +35,8 @@ public class ArchiveAggregateConverter { private final ItemBadgeGenerator itemBadgeGenerator; public ArchiveInfo convertArchiveInfo(ItemArchiveDto itemArchiveDto, - List archiveImageEntities, List userVisitPlaceEntities) { + List archiveImageEntities, + List userVisitPlaceEntities) { Map placeTypes = convertFoodAndCafe(userVisitPlaceEntities); @@ -59,47 +60,22 @@ public ArchiveInfo convertArchiveInfo(ItemArchiveDto itemArchiveDto, .build(); } - public ArchiveInfo convertArchiveInfo(ArchiveEntity archiveEntity, - List archiveImageEntities, - List userVisitPlaceEntities) { + public ArchiveInfo convertArchiveInfo(final ArchiveEntity archiveEntity) { - Map placeTypes = convertFoodAndCafe(userVisitPlaceEntities); + Map placeTypes = convertFoodAndCafe(archiveEntity.getUserVisitPlaces()); ArchiveLike archiveLike = archiveLikeGenerator.generateArchiveLike(archiveEntity.getId()); - List photoUrls = archiveImageEntities.stream() + List photoUrls = archiveEntity.getArchiveImages() + .stream() .map(ArchiveImageEntity::getImageUrl) .collect(Collectors.toList()); + User user = archiveEntity.getUser(); return ArchiveInfo.builder() .id(archiveEntity.getId()) - .userProfileUrl(archiveEntity.getUser().getImageUrl()) - .userName(archiveEntity.getUser().getName()) - .updatedAt(archiveEntity.getUpdatedAt()) - .starRating(archiveEntity.getStarRating()) - .likeCount(archiveEntity.getLikeCount()) - .heart(archiveLike) - .comment(archiveEntity.getComment()) - .food(placeTypes.getOrDefault(PlaceType.FOOD, "")) - .cafe(placeTypes.getOrDefault(PlaceType.CAFE, "")) - .photoUrls(photoUrls) - .build(); - } - - public ArchiveInfo convertArchiveInfo(ArchiveEntity archiveEntity, UserResponse userResponse, - List archiveImageEntities, List userVisitPlaceEntities) { - - Map placeTypes = convertFoodAndCafe(userVisitPlaceEntities); - - ArchiveLike archiveLike = archiveLikeGenerator.generateArchiveLike(archiveEntity.getId()); - - List photoUrls = archiveImageEntities.stream() - .map(ArchiveImageEntity::getImageUrl) - .collect(Collectors.toList()); - return ArchiveInfo.builder() - .id(archiveEntity.getId()) - .userProfileUrl(userResponse.getImageUrl()) - .userName(userResponse.getName()) + .userProfileUrl(user.getImageUrl()) + .userName(user.getName()) .updatedAt(archiveEntity.getUpdatedAt()) .starRating(archiveEntity.getStarRating()) .likeCount(archiveEntity.getLikeCount()) @@ -112,7 +88,7 @@ public ArchiveInfo convertArchiveInfo(ArchiveEntity archiveEntity, UserResponse } public MyArchiveInfo convertMyArchiveInfo(MyArchiveDto myArchiveDto, - boolean existImages, List userVisitPlaceEntities) { + boolean existImages, List userVisitPlaceEntities) { ItemBadge itemBadge = itemBadgeGenerator.generateTypeItemBadge(ExhibitionType.EXHIBITION); @@ -129,7 +105,8 @@ public MyArchiveInfo convertMyArchiveInfo(MyArchiveDto myArchiveDto, } public ArchiveDetailResponse convertArchiveDetail(ArchiveDetailDto archiveDetailDto, - List visitPlaces, List archiveImageEntities) { + List visitPlaces, + List archiveImageEntities) { ItemBadge itemBadge = itemBadgeGenerator.generateTypeItemBadge( archiveDetailDto.getItemExhibitionType()); Map placeTypes = convertFoodAndCafe(visitPlaces); diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveEntity.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveEntity.java index 5c261cdf..5f753f55 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveEntity.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveEntity.java @@ -1,9 +1,13 @@ package com.kilometer.domain.archive; -import com.kilometer.domain.archive.request.ArchiveRequest; +import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; +import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; import com.kilometer.domain.item.ItemEntity; import com.kilometer.domain.user.User; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -12,6 +16,7 @@ import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import javax.persistence.Table; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -65,6 +70,35 @@ public class ArchiveEntity { @JoinColumn(name = "item") private ItemEntity item; + @OneToMany(mappedBy = "archiveEntity", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, + fetch = FetchType.LAZY, orphanRemoval = true) + private final List archiveImages = new ArrayList<>(); + + @OneToMany(mappedBy = "archiveEntity", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, + fetch = FetchType.LAZY, orphanRemoval = true) + private final List userVisitPlaces = new ArrayList<>(); + + public void initArchiveImages(final List archiveImages) { + this.archiveImages.clear(); + this.archiveImages.addAll(archiveImages); + archiveImages.forEach(archiveImage -> archiveImage.initArchiveEntity(this)); + } + + public void initUserVisitPlaces(final List userVisitPlaces) { + this.userVisitPlaces.clear(); + this.userVisitPlaces.addAll(userVisitPlaces); + userVisitPlaces.forEach(userVisitPlace -> userVisitPlace.initArchiveEntity(this)); + } + + public void update(final String comment, final int starRating, final boolean isVisibleAtItem, + final List archiveImages, final List userVisitPlaces) { + this.comment = comment; + this.starRating = starRating; + this.isVisibleAtItem = isVisibleAtItem; + initArchiveImages(archiveImages); + initUserVisitPlaces(userVisitPlaces); + } + public void setUser(User user) { this.user = user; } @@ -73,12 +107,6 @@ public void setItem(ItemEntity item) { this.item = item; } - public void update(ArchiveRequest request) { - this.comment = request.getComment(); - this.isVisibleAtItem = request.isVisibleAtItem(); - this.starRating = request.getStarRating(); - } - public ArchiveEntity plusLikeCount() { this.likeCount++; return this; diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveRepository.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveRepository.java index 18b09951..c41e551b 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveRepository.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveRepository.java @@ -1,5 +1,6 @@ package com.kilometer.domain.archive; +import com.kilometer.domain.archive.exception.ArchiveNotFoundException; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; @@ -7,5 +8,12 @@ public interface ArchiveRepository extends JpaRepository, A Optional findByItemIdAndUserId(Long itemId, Long userId); + Optional findByIdAndUserId(final Long id, final Long userId); + boolean existsByItemIdAndUserId(Long itemId, Long userId); + + default ArchiveEntity getByIdAndUserId(final Long id, final Long userId) { + return this.findByIdAndUserId(id, userId) + .orElseThrow(() -> new ArchiveNotFoundException("해당 회원에게 일치하는 아카이브가 없습니다.")); + } } diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/archiveImage/ArchiveImageEntity.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/archiveImage/ArchiveImageEntity.java index 6bf63e82..f6329767 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/archiveImage/ArchiveImageEntity.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/archiveImage/ArchiveImageEntity.java @@ -47,7 +47,7 @@ public class ArchiveImageEntity { @JoinColumn(name = "archive") private ArchiveEntity archiveEntity; - public void setArchiveEntity(ArchiveEntity archiveEntity) { + public void initArchiveEntity(final ArchiveEntity archiveEntity) { this.archiveEntity = archiveEntity; } } diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/archiveImage/ArchiveImageService.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/archiveImage/ArchiveImageService.java index 63136075..e2de4103 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/archiveImage/ArchiveImageService.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/archiveImage/ArchiveImageService.java @@ -1,11 +1,8 @@ package com.kilometer.domain.archive.archiveImage; import com.google.common.base.Preconditions; -import com.kilometer.domain.archive.ArchiveEntity; import java.util.List; import lombok.RequiredArgsConstructor; - - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -16,16 +13,6 @@ public class ArchiveImageService { private final ArchiveImageRepository archiveImageRepository; - @Transactional - public List saveAll(List archiveImageEntities, Long archiveId) { - Preconditions.checkNotNull(archiveImageEntities, "Archive images must not be null"); - if(archiveImageEntities.isEmpty()) { - return List.of(); - } - ArchiveEntity archiveEntity = ArchiveEntity.builder().id(archiveId).build(); - archiveImageEntities.forEach(archiveImage -> archiveImage.setArchiveEntity(archiveEntity)); - return archiveImageRepository.saveAll(archiveImageEntities); - } @Transactional public void deleteAllByArchiveId(Long archiveId) { Preconditions.checkNotNull(archiveId, "Archive id must not be null : " + archiveId); diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/Archive.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/Archive.java index 49065cfd..ab5bb179 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/Archive.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/Archive.java @@ -1,10 +1,16 @@ package com.kilometer.domain.archive.domain; +import com.kilometer.domain.archive.ArchiveEntity; +import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; import com.kilometer.domain.archive.domain.archiveFilter.ArchiveFilter; import com.kilometer.domain.archive.domain.userVisitPlace.UserVisitPlace; import com.kilometer.domain.archive.exception.ArchiveValidationException; +import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; +import com.kilometer.domain.item.ItemEntity; +import com.kilometer.domain.user.User; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import lombok.Getter; @Getter @@ -13,6 +19,7 @@ public class Archive { private static final int MAX_STAR_RATING = 5; private static final int MIN_STAR_RATING = 1; + private final Long id; private final String comment; private final int starRating; private final boolean isVisibleAtItem; @@ -20,8 +27,9 @@ public class Archive { private final List archiveImages; private final List userVisitPlaces; - private Archive(final String comment, final int starRating, final boolean isVisibleAtItem, + private Archive(final Long id, final String comment, final int starRating, final boolean isVisibleAtItem, final List archiveImages, final List userVisitPlaces) { + this.id = id; this.comment = comment; this.starRating = starRating; this.isVisibleAtItem = isVisibleAtItem; @@ -34,7 +42,22 @@ public static Archive createArchive(final String comment, final int starRating, final List userVisitPlaces) { validateComment(comment); validateStarRating(starRating); - return new Archive(comment, starRating, isVisibleAtItem, archiveImages, userVisitPlaces); + return new Archive(null, comment, starRating, isVisibleAtItem, archiveImages, userVisitPlaces); + } + + public static Archive createArchiveForUpdate(final Long id, final String comment, final int starRating, + final boolean isVisibleAtItem, final List archiveImages, + final List userVisitPlaces) { + validateId(id); + validateComment(comment); + validateStarRating(starRating); + return new Archive(id, comment, starRating, isVisibleAtItem, archiveImages, userVisitPlaces); + } + + private static void validateId(final Long id) { + if (id == null) { + throw new ArchiveValidationException("입력된 id가 없습니다."); + } } private static void validateComment(final String comment) { @@ -51,4 +74,30 @@ private static void validateStarRating(final int starRating) { throw new ArchiveValidationException("별점은 0~5 사이의 양수이어야 합니다."); } } + + public ArchiveEntity toEntity(final User user, final ItemEntity itemEntity) { + return ArchiveEntity.builder() + .comment(this.getComment()) + .starRating(this.getStarRating()) + .isVisibleAtItem(this.getIsVisibleAtItem()) + .user(user) + .item(itemEntity) + .build(); + } + + public List toArchiveImageEntities() { + return this.archiveImages.stream() + .map(ArchiveImage::toEntity) + .collect(Collectors.toList()); + } + + public List createUserVisitPlaceEntities() { + return this.userVisitPlaces.stream() + .map(UserVisitPlace::toEntity) + .collect(Collectors.toList()); + } + + public boolean getIsVisibleAtItem() { + return isVisibleAtItem; + } } diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/ArchiveImage.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/ArchiveImage.java index b023ffc5..9747f021 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/ArchiveImage.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/ArchiveImage.java @@ -1,5 +1,6 @@ package com.kilometer.domain.archive.domain; +import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; import com.kilometer.domain.archive.exception.ArchiveValidationException; import lombok.Getter; import org.junit.platform.commons.util.StringUtils; @@ -23,4 +24,10 @@ private static void validateImageUrl(final String imageUrl) { throw new ArchiveValidationException("이미지 링크가 없습니다."); } } + + public ArchiveImageEntity toEntity() { + return ArchiveImageEntity.builder() + .imageUrl(this.imageUrl) + .build(); + } } diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/userVisitPlace/UserVisitPlace.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/userVisitPlace/UserVisitPlace.java index bcd5d964..2a0de79c 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/userVisitPlace/UserVisitPlace.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/domain/userVisitPlace/UserVisitPlace.java @@ -1,6 +1,7 @@ package com.kilometer.domain.archive.domain.userVisitPlace; import com.kilometer.domain.archive.exception.ArchiveValidationException; +import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; import lombok.Getter; import org.junit.platform.commons.util.StringUtils; @@ -37,4 +38,13 @@ private static void validate(final String placeName, final String address, final throw new ArchiveValidationException("입력된 도로명 주소가 없습니다."); } } + + public UserVisitPlaceEntity toEntity() { + return UserVisitPlaceEntity.builder() + .placeType(this.placeType) + .placeName(this.placeName) + .address(this.address) + .roadAddress(this.roadAddress) + .build(); + } } diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveCreateRequest.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveCreateRequest.java new file mode 100644 index 00000000..d745b874 --- /dev/null +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveCreateRequest.java @@ -0,0 +1,42 @@ +package com.kilometer.domain.archive.request; + +import com.kilometer.domain.archive.domain.Archive; +import com.kilometer.domain.archive.domain.ArchiveImage; +import com.kilometer.domain.archive.domain.userVisitPlace.UserVisitPlace; +import com.kilometer.domain.archive.dto.PlaceInfo; +import java.util.List; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor +public class ArchiveCreateRequest { + + private Long itemId; + private String comment; + private int starRating; + private boolean isVisibleAtItem; + private List photoUrls; + private List placeInfos; + + public Archive toDomain() { + return Archive.createArchive( + this.comment, this.starRating, this.isVisibleAtItem, toArchiveImages(), toUserVisitPlace()); + } + + public List toArchiveImages() { + return this.photoUrls.stream() + .map(ArchiveImage::createArchiveImage) + .collect(Collectors.toList()); + } + + public List toUserVisitPlace() { + return this.placeInfos.stream() + .map(PlaceInfo::toDomain) + .collect(Collectors.toList()); + } +} diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveRequest.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveRequest.java deleted file mode 100644 index 9fb368d0..00000000 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveRequest.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.kilometer.domain.archive.request; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.kilometer.domain.archive.ArchiveEntity; -import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; -import com.kilometer.domain.archive.domain.Archive; -import com.kilometer.domain.archive.domain.ArchiveImage; -import com.kilometer.domain.archive.domain.userVisitPlace.PlaceType; -import com.kilometer.domain.archive.domain.userVisitPlace.UserVisitPlace; -import com.kilometer.domain.archive.dto.PlaceInfo; -import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -@JsonIgnoreProperties(ignoreUnknown = true) -public class ArchiveRequest { - - private Long itemId; - private String comment; - private int starRating; - private boolean isVisibleAtItem; - private List photoUrls; - private List placeInfos; - - public ArchiveEntity makeArchive() { - return ArchiveEntity.builder() - .comment(this.getComment()) - .starRating(this.getStarRating()) - .isVisibleAtItem(this.isVisibleAtItem()) - .build(); - } - - - public List makeArchiveImages() { - List images = new ArrayList<>(); - this.getPhotoUrls().forEach(url -> { - ArchiveImageEntity photo = ArchiveImageEntity.builder().imageUrl(url).build(); - images.add(photo); - }); - return images; - } - - public List makeVisitedPlace() { - List places = new ArrayList<>(); - for (PlaceInfo info : this.getPlaceInfos()) { - UserVisitPlaceEntity visitPlace = UserVisitPlaceEntity.builder() - .placeType(PlaceType.valueOf(info.getPlaceType())) - .placeName(info.getName()) - .address(info.getAddress()) - .roadAddress(info.getRoadAddress()) - .build(); - places.add(visitPlace); - } - return places; - } - - public Archive toDomain() { - return Archive.createArchive( - this.comment, this.starRating, this.isVisibleAtItem, archiveImages(), userVisitPlace()); - } - - public List archiveImages() { - return this.photoUrls.stream() - .map(ArchiveImage::createArchiveImage) - .collect(Collectors.toList()); - } - - public List userVisitPlace() { - return this.placeInfos.stream() - .map(PlaceInfo::toDomain) - .collect(Collectors.toList()); - } -} diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveUpdateRequest.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveUpdateRequest.java new file mode 100644 index 00000000..50e0fc0b --- /dev/null +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/request/ArchiveUpdateRequest.java @@ -0,0 +1,45 @@ +package com.kilometer.domain.archive.request; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.kilometer.domain.archive.domain.Archive; +import com.kilometer.domain.archive.domain.ArchiveImage; +import com.kilometer.domain.archive.domain.userVisitPlace.UserVisitPlace; +import com.kilometer.domain.archive.dto.PlaceInfo; +import java.util.List; +import java.util.stream.Collectors; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class ArchiveUpdateRequest { + + private Long itemId; + private String comment; + private int starRating; + private boolean isVisibleAtItem; + private List photoUrls; + private List placeInfos; + + public Archive toDomain(final Long archiveId) { + return Archive.createArchiveForUpdate( + archiveId, this.comment, this.starRating, this.isVisibleAtItem, archiveImages(), userVisitPlace()); + } + + public List archiveImages() { + return this.photoUrls.stream() + .map(ArchiveImage::createArchiveImage) + .collect(Collectors.toList()); + } + + public List userVisitPlace() { + return this.placeInfos.stream() + .map(PlaceInfo::toDomain) + .collect(Collectors.toList()); + } +} diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/service/ArchiveEntityMapper.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/service/ArchiveEntityMapper.java new file mode 100644 index 00000000..cd853981 --- /dev/null +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/service/ArchiveEntityMapper.java @@ -0,0 +1,50 @@ +package com.kilometer.domain.archive.service; + +import com.kilometer.domain.archive.ArchiveEntity; +import com.kilometer.domain.archive.domain.Archive; +import com.kilometer.domain.archive.request.ArchiveCreateRequest; +import com.kilometer.domain.item.ItemEntity; +import com.kilometer.domain.item.ItemRepository; +import com.kilometer.domain.item.exception.ItemNotFoundException; +import com.kilometer.domain.user.User; +import com.kilometer.domain.user.UserRepository; +import com.kilometer.domain.user.exception.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class ArchiveEntityMapper { + + private final UserRepository userRepository; + private final ItemRepository itemRepository; + + public ArchiveEntity mapToArchiveEntity(final Long userId, final ArchiveCreateRequest request) { + Archive archive = request.toDomain(); + + ArchiveEntity archiveEntity = createArchiveEntity(userId, request.getItemId(), archive); + archiveEntity.initArchiveImages(archive.toArchiveImageEntities()); + archiveEntity.initUserVisitPlaces(archive.createUserVisitPlaceEntities()); + return archiveEntity; + } + + private ArchiveEntity createArchiveEntity(final Long userId, final Long itemId, final Archive archive) { + User user = getUser(userId); + ItemEntity itemEntity = getItem(itemId); + return archive.toEntity(user, itemEntity); + } + + private User getUser(final Long userId) { + return userRepository.findById(userId) + .orElseThrow(() -> new UserNotFoundException("저장되지 않은 사용자 입니다.")); + } + + private ItemEntity getItem(final Long itemId) { + ItemEntity itemEntity = itemRepository.findById(itemId) + .orElseThrow(() -> new ItemNotFoundException("저장되지 않은 아이템 입니다.")); + itemEntity.validateExposureTypeIsOn(); + return itemEntity; + } +} diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveService.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/service/ArchiveService.java similarity index 70% rename from kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveService.java rename to kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/service/ArchiveService.java index cf057565..aca7b7ec 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/ArchiveService.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/service/ArchiveService.java @@ -1,6 +1,9 @@ -package com.kilometer.domain.archive; +package com.kilometer.domain.archive.service; import com.google.common.base.Preconditions; +import com.kilometer.domain.archive.ArchiveAggregateConverter; +import com.kilometer.domain.archive.ArchiveEntity; +import com.kilometer.domain.archive.ArchiveRepository; import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; import com.kilometer.domain.archive.archiveImage.ArchiveImageService; import com.kilometer.domain.archive.domain.Archive; @@ -16,28 +19,20 @@ import com.kilometer.domain.archive.dto.MyArchiveInfo; import com.kilometer.domain.archive.dto.MyArchiveResponse; import com.kilometer.domain.archive.exception.ArchiveNotFoundException; -import com.kilometer.domain.archive.exception.ArchiveUnauthorizedException; +import com.kilometer.domain.archive.exception.ArchiveValidationException; import com.kilometer.domain.archive.generator.ArchiveRatingCalculator; import com.kilometer.domain.archive.like.LikeService; import com.kilometer.domain.archive.like.dto.LikeDto; import com.kilometer.domain.archive.like.dto.LikeResponse; -import com.kilometer.domain.archive.request.ArchiveRequest; +import com.kilometer.domain.archive.request.ArchiveCreateRequest; +import com.kilometer.domain.archive.request.ArchiveUpdateRequest; import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceService; -import com.kilometer.domain.item.ItemEntity; -import com.kilometer.domain.item.ItemRepository; -import com.kilometer.domain.item.enumType.ExposureType; -import com.kilometer.domain.item.exception.ItemExposureOffException; -import com.kilometer.domain.item.exception.ItemNotFoundException; import com.kilometer.domain.paging.PagingStatusService; import com.kilometer.domain.paging.RequestPagingStatus; import com.kilometer.domain.paging.ResponsePagingStatus; -import com.kilometer.domain.user.User; -import com.kilometer.domain.user.UserService; -import com.kilometer.domain.user.dto.UserResponse; import com.kilometer.domain.util.FrontUrlUtils; import java.util.List; -import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; @@ -51,69 +46,38 @@ @RequiredArgsConstructor public class ArchiveService { - private final UserService userService; - private final ItemRepository itemRepository; private final ArchiveRepository archiveRepository; private final ArchiveImageService archiveImageService; private final UserVisitPlaceService userVisitPlaceService; private final PagingStatusService pagingStatusService; private final ArchiveAggregateConverter archiveAggregateConverter; private final LikeService likeService; + private final ArchiveEntityMapper archiveEntityMapper; @Transactional - public ArchiveInfo save(Long userId, ArchiveRequest archiveRequest) { - validateArchiveRequest(archiveRequest, userId); - - Archive archive = archiveRequest.toDomain(); - - UserResponse userResponse = userService.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("잘못된 사용자 정보 입니다.")); - - itemRepository.findExposureById(archiveRequest.getItemId()) - .map(mapping -> { - if (mapping.getExposureType() == ExposureType.OFF) { - throw new ItemExposureOffException(); - } - return mapping; - }) - .orElseThrow(ItemNotFoundException::new); - - ArchiveEntity archiveEntity = saveArchive(archiveRequest, userId, archiveRequest.getItemId()); - - Long archiveId = archiveEntity.getId(); - List archiveImageEntities = archiveRequest.makeArchiveImages(); - List userVisitPlaceEntities = archiveRequest.makeVisitedPlace(); - archiveImageService.saveAll(archiveImageEntities, archiveId); - userVisitPlaceService.saveAll(userVisitPlaceEntities, archiveId); - - return archiveAggregateConverter.convertArchiveInfo(archiveEntity, userResponse, archiveImageEntities, - userVisitPlaceEntities); + public ArchiveInfo save(final Long userId, final ArchiveCreateRequest request) { + validateNotDuplicateArchive(userId, request.getItemId()); + ArchiveEntity archiveEntity = archiveEntityMapper.mapToArchiveEntity(userId, request); + ArchiveEntity savedArchiveEntity = archiveRepository.save(archiveEntity); + return archiveAggregateConverter.convertArchiveInfo(savedArchiveEntity); } - @Transactional - public ArchiveInfo update(Long userId, Long archiveId, ArchiveRequest request) { - Preconditions.checkNotNull(userId, "id must not be null"); - Preconditions.checkNotNull(archiveId, "Archive id must not be null"); - - Archive archive = request.toDomain(); - - ArchiveEntity archiveEntity = archiveRepository.findById(archiveId) - .orElseThrow(ArchiveNotFoundException::new); - - if (!Objects.equals(archiveEntity.getUser().getId(), userId)) { - throw new ArchiveUnauthorizedException(); + private void validateNotDuplicateArchive(Long userId, Long itemId) { + if (archiveRepository.existsByItemIdAndUserId(itemId, userId)) { + throw new ArchiveValidationException(String.format("이미 등록한 Archive가 있습니다. sItemId : %d / UserId : %d", + itemId, userId)); } + } - List archiveImageEntities = request.makeArchiveImages(); - List userVisitPlaceEntities = request.makeVisitedPlace(); - - updateArchiveImages(archiveImageEntities, archiveId); - updateUserVisitPlace(userVisitPlaceEntities, archiveId); - - archiveEntity.update(request); - - return archiveAggregateConverter.convertArchiveInfo(archiveEntity, archiveImageEntities, - userVisitPlaceEntities); + @Transactional + public ArchiveInfo update(final Long userId, final Long archiveId, final ArchiveUpdateRequest request) { + Archive archive = request.toDomain(archiveId); + ArchiveEntity archiveEntity = archiveRepository.getByIdAndUserId(archive.getId(), userId); + archiveEntity.update(archive.getComment(), archive.getStarRating(), archive.getIsVisibleAtItem(), + archive.toArchiveImageEntities(), archive.createUserVisitPlaceEntities()); + + ArchiveEntity updatedArchiveEntity = archiveRepository.save(archiveEntity); + return archiveAggregateConverter.convertArchiveInfo(updatedArchiveEntity); } public ArchiveResponse findAllByItemIdAndUserId(Long itemId, Long userId, @@ -219,34 +183,6 @@ public Long findArchiveIdByItemIdAndUserId(Long itemId, Long userId) { .orElse(null); } - - private void validateArchiveRequest(ArchiveRequest archiveRequest, Long userId) { - Preconditions.checkArgument( - !archiveRepository.existsByItemIdAndUserId(archiveRequest.getItemId(), userId), - String.format("기 등록한 Archive가 있습니다. sItemId : %d / UserId : %d", - archiveRequest.getItemId(), userId)); - } - - private ArchiveEntity saveArchive(ArchiveRequest archiveRequest, Long userId, Long itemId) { - ArchiveEntity archiveEntity = archiveRequest.makeArchive(); - archiveEntity.setUser(User.builder().id(userId).build()); - archiveEntity.setItem(ItemEntity.builder().id(itemId).build()); - archiveRepository.save(archiveEntity); - return archiveEntity; - } - - private List updateArchiveImages(List newArchiveImageEntities, - Long archiveId) { - archiveImageService.deleteAllByArchiveId(archiveId); - return archiveImageService.saveAll(newArchiveImageEntities, archiveId); - } - - private List updateUserVisitPlace(List newUserVisitPlaceEntities, - Long archiveId) { - userVisitPlaceService.deleteAllByArchiveId(archiveId); - return userVisitPlaceService.saveAll(newUserVisitPlaceEntities, archiveId); - } - private void updateArchiveLikeCount(boolean status, Long archiveId) { if (status) { updateArchiveLikeCount(ArchiveEntity::plusLikeCount, archiveId); diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/userVisitPlace/UserVisitPlaceEntity.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/userVisitPlace/UserVisitPlaceEntity.java index 7f01e028..2551bc84 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/userVisitPlace/UserVisitPlaceEntity.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/userVisitPlace/UserVisitPlaceEntity.java @@ -57,7 +57,7 @@ public class UserVisitPlaceEntity { @Builder.Default private boolean isDeleted = false; - public void setArchiveEntity(ArchiveEntity archiveEntity) { + public void initArchiveEntity(ArchiveEntity archiveEntity) { this.archiveEntity = archiveEntity; } } diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/userVisitPlace/UserVisitPlaceService.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/userVisitPlace/UserVisitPlaceService.java index 59adcccf..f755874b 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/userVisitPlace/UserVisitPlaceService.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/archive/userVisitPlace/UserVisitPlaceService.java @@ -1,7 +1,6 @@ package com.kilometer.domain.archive.userVisitPlace; import com.google.common.base.Preconditions; -import com.kilometer.domain.archive.ArchiveEntity; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,16 +13,6 @@ public class UserVisitPlaceService { private final UserVisitPlaceRepository userVisitPlaceRepository; - @Transactional - public List saveAll(List userVisitPlaceEntities, Long archiveId) { - if (!userVisitPlaceEntities.isEmpty()) { - ArchiveEntity archiveEntity = ArchiveEntity.builder().id(archiveId).build(); - userVisitPlaceEntities.forEach(userVisitPlace -> userVisitPlace.setArchiveEntity(archiveEntity)); - userVisitPlaceRepository.saveAll(userVisitPlaceEntities); - } - return userVisitPlaceEntities; - } - @Transactional public void deleteAllByArchiveId(Long archiveId) { Preconditions.checkNotNull(archiveId, "Archive id must not be null : " + archiveId); diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemEntity.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemEntity.java index 7465c1e1..0cbb98fe 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemEntity.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemEntity.java @@ -7,6 +7,7 @@ import com.kilometer.domain.item.enumType.ExposureType; import com.kilometer.domain.item.enumType.FeeType; import com.kilometer.domain.item.enumType.RegionType; +import com.kilometer.domain.item.exception.ItemExposureOffException; import com.kilometer.domain.item.itemDetail.ItemDetail; import com.kilometer.domain.item.itemDetailImage.ItemDetailImage; import java.time.LocalDate; @@ -194,6 +195,12 @@ public void setItemDetail(ItemDetail itemDetail) { this.itemDetail = itemDetail; } + public void validateExposureTypeIsOn() { + if (this.exposureType.equals(ExposureType.OFF)) { + throw new ItemExposureOffException("미전시 아이템은 아카이빙 할 수 없습니다."); + } + } + public ItemEntity plusPickCount() { this.pickCount++; return this; diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemRepository.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemRepository.java index 57723a82..5d1f4e7d 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemRepository.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemRepository.java @@ -1,9 +1,8 @@ package com.kilometer.domain.item; -import org.springframework.data.jpa.repository.JpaRepository; - import java.util.List; import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; public interface ItemRepository extends JpaRepository, ItemRepositoryCustom { diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemService.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemService.java index 6f67c91f..627784d7 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemService.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/item/ItemService.java @@ -1,7 +1,7 @@ package com.kilometer.domain.item; import com.google.common.base.Preconditions; -import com.kilometer.domain.archive.ArchiveService; +import com.kilometer.domain.archive.service.ArchiveService; import com.kilometer.domain.item.domain.Item; import com.kilometer.domain.item.dto.DetailResponse; import com.kilometer.domain.item.dto.ItemInfoDto; diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/domain/user/exception/UserNotFoundException.java b/kilometer-backend-domain/src/main/java/com/kilometer/domain/user/exception/UserNotFoundException.java new file mode 100644 index 00000000..3728d949 --- /dev/null +++ b/kilometer-backend-domain/src/main/java/com/kilometer/domain/user/exception/UserNotFoundException.java @@ -0,0 +1,20 @@ +package com.kilometer.domain.user.exception; + +import com.kilometer.exception.KilometerErrorCode; +import com.kilometer.exception.KilometerException; + +public class UserNotFoundException extends KilometerException { + + public UserNotFoundException() { + super(""); + } + + public UserNotFoundException(String message) { + super(message); + } + + @Override + public KilometerErrorCode getErrorCode() { + return KilometerErrorCode.USER_NOT_FOUND; + } +} diff --git a/kilometer-backend-domain/src/main/java/com/kilometer/exception/KilometerErrorCode.java b/kilometer-backend-domain/src/main/java/com/kilometer/exception/KilometerErrorCode.java index aaa5dd7a..2f69799d 100644 --- a/kilometer-backend-domain/src/main/java/com/kilometer/exception/KilometerErrorCode.java +++ b/kilometer-backend-domain/src/main/java/com/kilometer/exception/KilometerErrorCode.java @@ -8,7 +8,8 @@ public enum KilometerErrorCode { ITEM_EXPOSURE_OFF("ALT-017", "해당 컨텐츠는 관리자에 의해 삭제되었습니다."), ARCHIVE_VALIDATION_EXCEPTION("ALT-018", "요청이 잘못되었습니다."), ARCHIVE_UNAUTHORIZED_EXCEPTION("ALT-019", "권한이 존재하지 않습니다."), - ITEM_NOT_FOUND("ALT-020", "존재 하지 않는 컨텐츠입니다."); + ITEM_NOT_FOUND("ALT-020", "존재 하지 않는 컨텐츠입니다."), + USER_NOT_FOUND("ATL-021", "회원이 존재하지 않습니다."); @Getter private final String code; diff --git a/kilometer-backend-domain/src/test/groovy/com/kilometer/common/statics/Statics.java b/kilometer-backend-domain/src/test/groovy/com/kilometer/common/statics/Statics.java index e1d22b9b..3e3917d8 100644 --- a/kilometer-backend-domain/src/test/groovy/com/kilometer/common/statics/Statics.java +++ b/kilometer-backend-domain/src/test/groovy/com/kilometer/common/statics/Statics.java @@ -8,6 +8,10 @@ public class Statics { public static final int 아카이브_별점 = 1; public static final boolean 아카이브_공개_설정 = true; + public static final String 새로운_아카이브_코멘트 = "new comment"; + public static final int 새로운_아카이브_별점 = 3; + public static final boolean 아카이브_비공개_설정 = false; + // Archive Image 관련 상수 public static final String 아카이브_이미지_URL = "아카이브 이미지"; diff --git a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/ArchiveEntityTest.java b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/ArchiveEntityTest.java new file mode 100644 index 00000000..9d94523b --- /dev/null +++ b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/ArchiveEntityTest.java @@ -0,0 +1,84 @@ +package com.kilometer.domain.archive; + +import static com.kilometer.common.statics.Statics.새로운_아카이브_별점; +import static com.kilometer.common.statics.Statics.새로운_아카이브_코멘트; +import static com.kilometer.common.statics.Statics.아카이브_공개_설정; +import static com.kilometer.common.statics.Statics.아카이브_별점; +import static com.kilometer.common.statics.Statics.아카이브_비공개_설정; +import static com.kilometer.common.statics.Statics.아카이브_이미지_URL; +import static com.kilometer.common.statics.Statics.아카이브_코멘트; +import static com.kilometer.common.statics.Statics.카페_이름; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; +import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ArchiveEntityTest { + + private final ArchiveImageEntity 전시회_사진 = ArchiveImageEntity.builder() + .imageUrl(아카이브_이미지_URL) + .build(); + private final UserVisitPlaceEntity 근처_맛집_사진 = UserVisitPlaceEntity.builder() + .placeName(카페_이름) + .build(); + private final List 전시회_사진들 = List.of(전시회_사진); + private final List 근처_맛집_사진들 = List.of(근처_맛집_사진); + + @Test + @DisplayName("ArchiveEntity에 ArchiveImageEntities를 추가한다.") + void addArchiveImages() { + // given + ArchiveEntity archiveEntity = ArchiveEntity.builder() + .build(); + + // when + archiveEntity.initArchiveImages(전시회_사진들); + + // then + assertThat(archiveEntity.getArchiveImages()).hasSize(1); + } + + @Test + @DisplayName("ArchiveEntity에 UserVisitPlaces를 추가한다.") + void addUserVisitPlaces() { + // given + ArchiveEntity archiveEntity = ArchiveEntity.builder() + .build(); + + // when + archiveEntity.initUserVisitPlaces(근처_맛집_사진들); + + // then + assertThat(archiveEntity.getUserVisitPlaces()).hasSize(1); + } + + @Test + @DisplayName("ArchiveEntity를 수정한다.") + void update() { + // given + ArchiveEntity archiveEntity = ArchiveEntity.builder() + .comment(아카이브_코멘트) + .isVisibleAtItem(아카이브_공개_설정) + .starRating(아카이브_별점) + .build(); + + archiveEntity.initArchiveImages(전시회_사진들); + archiveEntity.initUserVisitPlaces(근처_맛집_사진들); + + // when + archiveEntity.update(새로운_아카이브_코멘트, 새로운_아카이브_별점, 아카이브_비공개_설정, 전시회_사진들, 근처_맛집_사진들); + + // then + assertAll( + () -> assertThat(archiveEntity.getComment()).isEqualTo(새로운_아카이브_코멘트), + () -> assertThat(archiveEntity.getStarRating()).isEqualTo(새로운_아카이브_별점), + () -> assertThat(archiveEntity.isVisibleAtItem()).isEqualTo(아카이브_비공개_설정), + () -> assertThat(archiveEntity.getArchiveImages()).hasSize(1), + () -> assertThat(archiveEntity.getUserVisitPlaces()).hasSize(1) + ); + } +} diff --git a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/ArchiveImageTest.java b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/ArchiveImageTest.java index d5fd9e13..aa82683c 100644 --- a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/ArchiveImageTest.java +++ b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/ArchiveImageTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; import com.kilometer.domain.archive.exception.ArchiveValidationException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -28,8 +29,8 @@ void createArchiveImage_null() { // when & then assertThatThrownBy(() -> ArchiveImage.createArchiveImage(invalidImageUrl)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("이미지 링크가 없습니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("이미지 링크가 없습니다."); } @Test @@ -40,7 +41,20 @@ void createArchiveImage_blank() { // when & then assertThatThrownBy(() -> ArchiveImage.createArchiveImage(invalidImageUrl)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("이미지 링크가 없습니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("이미지 링크가 없습니다."); + } + + @Test + @DisplayName("ArchiveImage를 Entity 객체로 변환 한다.") + void toEntity() { + // given + ArchiveImage archiveImage = ArchiveImage.createArchiveImage(아카이브_이미지_URL); + + // when + ArchiveImageEntity actual = archiveImage.toEntity(); + + // then + assertThat(actual).isInstanceOf(ArchiveImageEntity.class); } } diff --git a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/ArchiveTest.java b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/ArchiveTest.java index 9f616ff4..058c319f 100644 --- a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/ArchiveTest.java +++ b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/ArchiveTest.java @@ -2,20 +2,32 @@ import static com.kilometer.common.statics.Statics.아카이브_공개_설정; import static com.kilometer.common.statics.Statics.아카이브_별점; +import static com.kilometer.common.statics.Statics.아카이브_이미지_URL; import static com.kilometer.common.statics.Statics.아카이브_코멘트; +import static com.kilometer.common.statics.Statics.장소_종류; +import static com.kilometer.common.statics.Statics.카페_도로명_주소; +import static com.kilometer.common.statics.Statics.카페_이름; +import static com.kilometer.common.statics.Statics.카페_지번_주소; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.kilometer.domain.archive.ArchiveEntity; +import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; import com.kilometer.domain.archive.domain.userVisitPlace.UserVisitPlace; import com.kilometer.domain.archive.exception.ArchiveValidationException; +import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; +import com.kilometer.domain.item.ItemEntity; +import com.kilometer.domain.user.User; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class ArchiveTest { - private final List 전시회_사진들 = List.of(); - private final List 근처_맛집_사진들 = List.of(); + private final ArchiveImage 전시회_사진 = ArchiveImage.createArchiveImage(아카이브_이미지_URL); + private final UserVisitPlace 근처_맛집_사진 = UserVisitPlace.createUserVisitPlace(장소_종류, 카페_이름, 카페_지번_주소, 카페_도로명_주소); + private final List 전시회_사진들 = List.of(전시회_사진); + private final List 근처_맛집_사진들 = List.of(근처_맛집_사진); @Test @DisplayName("Archive를 생성한다.") @@ -35,8 +47,8 @@ void commentIsNotNull() { // when & then assertThatThrownBy(() -> Archive.createArchive(invalidComment, 아카이브_별점, 아카이브_공개_설정, 전시회_사진들, 근처_맛집_사진들)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("입력된 comment가 없습니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("입력된 comment가 없습니다."); } @Test @@ -47,8 +59,8 @@ void archiveStarRatingIsNotNegative() { // when & then assertThatThrownBy(() -> Archive.createArchive(아카이브_코멘트, invalidStarRating, 아카이브_공개_설정, 전시회_사진들, 근처_맛집_사진들)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("별점은 0~5 사이의 양수이어야 합니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("별점은 0~5 사이의 양수이어야 합니다."); } @Test @@ -59,8 +71,8 @@ void archiveStarRatingIsPositiveOutOfRange() { // when & then assertThatThrownBy(() -> Archive.createArchive(아카이브_코멘트, invalidStarRating, 아카이브_공개_설정, 전시회_사진들, 근처_맛집_사진들)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("별점은 0~5 사이의 양수이어야 합니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("별점은 0~5 사이의 양수이어야 합니다."); } @Test @@ -71,7 +83,50 @@ void validateCommentField() { // when & then assertThatThrownBy(() -> Archive.createArchive(금칙어가_포함된_코멘트, 아카이브_별점, 아카이브_공개_설정, 전시회_사진들, 근처_맛집_사진들)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("입력된 comment에 금칙어가 포함되어 있습니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("입력된 comment에 금칙어가 포함되어 있습니다."); + } + + @Test + @DisplayName("Archive를 Entity 객체로 변환 한다.") + void toEntity() { + // given + User user = User.builder() + .build(); + ItemEntity itemEntity = ItemEntity.builder() + .build(); + Archive archive = Archive.createArchive(아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 전시회_사진들, 근처_맛집_사진들); + + // when + ArchiveEntity actual = archive.toEntity(user, itemEntity); + + // then + assertThat(actual).isInstanceOf(ArchiveEntity.class); + } + + @Test + @DisplayName("ArchiveImageEntity들을 생성한다.") + void createArchiveImageEntities() { + // given + Archive archive = Archive.createArchive(아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 전시회_사진들, 근처_맛집_사진들); + + // when + List archiveImageEntities = archive.toArchiveImageEntities(); + + // then + assertThat(archiveImageEntities).hasSize(1); + } + + @Test + @DisplayName("UserVisitPlaceEntity들을 생성한다.") + void createUserVisitPlaceEntities() { + // given + Archive archive = Archive.createArchive(아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 전시회_사진들, 근처_맛집_사진들); + + // when + List userVisitPlaceEntities = archive.createUserVisitPlaceEntities(); + + // then + assertThat(userVisitPlaceEntities).hasSize(1); } } diff --git a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/UserVisitPlaceTest.java b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/UserVisitPlaceTest.java index 6e4629c5..b69dd64a 100644 --- a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/UserVisitPlaceTest.java +++ b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/domain/UserVisitPlaceTest.java @@ -9,6 +9,7 @@ import com.kilometer.domain.archive.domain.userVisitPlace.UserVisitPlace; import com.kilometer.domain.archive.exception.ArchiveValidationException; +import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -32,8 +33,8 @@ void createUserVisitPlace_emptyPlace() { // when & then assertThatThrownBy(() -> UserVisitPlace.createUserVisitPlace(invalidPlaceType, 카페_이름, 카페_지번_주소, 카페_도로명_주소)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("일치하는 방문 장소 종류가 없습니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("일치하는 방문 장소 종류가 없습니다."); } @Test @@ -44,8 +45,8 @@ void createUserVisitPlace_emptyName() { // when & then assertThatThrownBy(() -> UserVisitPlace.createUserVisitPlace(장소_종류, invalidCafeName, 카페_지번_주소, 카페_도로명_주소)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("입력된 장소명이 없습니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("입력된 장소명이 없습니다."); } @Test @@ -56,8 +57,8 @@ void createUserVisitPlace_emptyAddress() { // when & then assertThatThrownBy(() -> UserVisitPlace.createUserVisitPlace(장소_종류, 카페_이름, invalidCafeAddress, 카페_도로명_주소)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("입력된 지번 주소가 없습니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("입력된 지번 주소가 없습니다."); } @Test @@ -68,7 +69,20 @@ void createUserVisitPlace_emptyRoadAddress() { // when & then assertThatThrownBy(() -> UserVisitPlace.createUserVisitPlace(장소_종류, 카페_이름, 카페_지번_주소, invalidRoadAddress)) - .isInstanceOf(ArchiveValidationException.class) - .hasMessage("입력된 도로명 주소가 없습니다."); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage("입력된 도로명 주소가 없습니다."); + } + + @Test + @DisplayName("UserVisitPlace를 Entity 객체로 변환 한다.") + void toEntity() { + // given + UserVisitPlace userVisitPlace = UserVisitPlace.createUserVisitPlace(장소_종류, 카페_이름, 카페_지번_주소, 카페_도로명_주소); + + // when + UserVisitPlaceEntity actual = userVisitPlace.toEntity(); + + // then + assertThat(actual).isInstanceOf(UserVisitPlaceEntity.class); } } diff --git a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/service/ArchiveEntityMapperTest.java b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/service/ArchiveEntityMapperTest.java new file mode 100644 index 00000000..972856a1 --- /dev/null +++ b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/service/ArchiveEntityMapperTest.java @@ -0,0 +1,142 @@ +package com.kilometer.domain.archive.service; + +import static com.kilometer.common.statics.Statics.아카이브_공개_설정; +import static com.kilometer.common.statics.Statics.아카이브_별점; +import static com.kilometer.common.statics.Statics.아카이브_코멘트; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import com.kilometer.common.annotation.SpringTestWithData; +import com.kilometer.domain.archive.ArchiveEntity; +import com.kilometer.domain.archive.dto.PlaceInfo; +import com.kilometer.domain.archive.request.ArchiveCreateRequest; +import com.kilometer.domain.item.ItemEntity; +import com.kilometer.domain.item.ItemRepository; +import com.kilometer.domain.item.enumType.ExhibitionType; +import com.kilometer.domain.item.enumType.ExposureType; +import com.kilometer.domain.item.enumType.FeeType; +import com.kilometer.domain.item.enumType.RegionType; +import com.kilometer.domain.item.exception.ItemExposureOffException; +import com.kilometer.domain.user.User; +import com.kilometer.domain.user.UserRepository; +import com.kilometer.domain.user.exception.UserNotFoundException; +import com.kilometer.exception.KilometerErrorCode; +import java.time.LocalDate; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@SpringTestWithData +class ArchiveEntityMapperTest { + + private final List 방문_사진 = List.of("photoUrls"); + private final List 근처_맛집 = List.of(new PlaceInfo("FOOD", "맛집", "address", "roadAddress")); + + @Autowired + private ArchiveEntityMapper archiveEntityMapper; + + @Autowired + private UserRepository userRepository; + + @Autowired + private ItemRepository itemRepository; + + @Test + @DisplayName("아카이브 엔티티를 매핑한다.") + void mapToArchiveEntity() { + // given + User user = 회원가입을_한다(); + ItemEntity item = 전시_아이템을_등록한다(); + ArchiveCreateRequest request = new ArchiveCreateRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); + + // when + ArchiveEntity actual = archiveEntityMapper.mapToArchiveEntity(user.getId(), request); + + // then + assertAll( + () -> assertThat(actual.getComment()).isEqualTo(아카이브_코멘트), + () -> assertThat(actual.getStarRating()).isEqualTo(아카이브_별점), + () -> assertThat(actual.getUser().getId()).isEqualTo(user.getId()), + () -> assertThat(actual.getItem().getId()).isEqualTo(item.getId()) + ); + } + + @Test + @DisplayName("아카이브 엔티티를 매핑 할 때, 사용자가 존재하지 않으면 예외가 발생한다.") + void mapToArchiveEntity_notExistUser() { + // given + Long invalidUserId = 1L; + + ItemEntity 아이템 = 전시_아이템을_등록한다(); + ArchiveCreateRequest request = new ArchiveCreateRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); + + // when & then + assertThatThrownBy(() -> archiveEntityMapper.mapToArchiveEntity(invalidUserId, request)) + .isInstanceOf(UserNotFoundException.class) + .hasMessage("저장되지 않은 사용자 입니다."); + } + + @Test + @DisplayName("아카이브 엔티티를 매핑 할 때, 미전시 전시글에 아카이브를 등록하려 하면 예외가 발생한다.") + void mapToArchiveEntity_exposureOffItem() { + // given + User user = 회원가입을_한다(); + ItemEntity item = 미전시_아이템을_등록한다(); + ArchiveCreateRequest request = new ArchiveCreateRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); + + // when + ItemExposureOffException actual = assertThrows(ItemExposureOffException.class, + () -> archiveEntityMapper.mapToArchiveEntity(user.getId(), request)); + + // then + assertEquals(actual.getErrorCode(), KilometerErrorCode.ITEM_EXPOSURE_OFF); + assertEquals(actual.getMessage(), "미전시 아이템은 아카이빙 할 수 없습니다."); + } + + private User 회원가입을_한다() { + User user = User.builder() + .name("user") + .email("user@email.com") + .build(); + return userRepository.save(user); + } + + private ItemEntity 전시_아이템을_등록한다() { + ItemEntity item = ItemEntity.builder() + .exposureType(ExposureType.ON) + .exhibitionType(ExhibitionType.EXHIBITION) + .regionType(RegionType.CHUNGCHEONG) + .feeType(FeeType.FREE) + .listImageUrl("listImageUrl") + .thumbnailImageUrl("thumbnailImageUrl") + .title("title") + .placeName("placeName") + .startDate(LocalDate.now()) + .endDate(LocalDate.now()) + .build(); + return itemRepository.save(item); + } + + private ItemEntity 미전시_아이템을_등록한다() { + ItemEntity item = ItemEntity.builder() + .exposureType(ExposureType.OFF) + .exhibitionType(ExhibitionType.EXHIBITION) + .regionType(RegionType.CHUNGCHEONG) + .feeType(FeeType.FREE) + .listImageUrl("listImageUrl") + .thumbnailImageUrl("thumbnailImageUrl") + .title("title") + .placeName("placeName") + .startDate(LocalDate.now()) + .endDate(LocalDate.now()) + .build(); + return itemRepository.save(item); + } +} diff --git a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/ArchiveServiceTest.java b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/service/ArchiveServiceTest.java similarity index 60% rename from kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/ArchiveServiceTest.java rename to kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/service/ArchiveServiceTest.java index c10eece6..f9416856 100644 --- a/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/ArchiveServiceTest.java +++ b/kilometer-backend-domain/src/test/groovy/com/kilometer/domain/archive/service/ArchiveServiceTest.java @@ -1,4 +1,4 @@ -package com.kilometer.domain.archive; +package com.kilometer.domain.archive.service; import static com.kilometer.common.statics.Statics.금칙어가_포함된_아카이브_코멘트; import static com.kilometer.common.statics.Statics.아카이브_공개_설정; @@ -11,12 +11,16 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.kilometer.common.annotation.SpringTestWithData; +import com.kilometer.domain.archive.archiveImage.ArchiveImageEntity; +import com.kilometer.domain.archive.archiveImage.ArchiveImageRepository; import com.kilometer.domain.archive.dto.ArchiveInfo; import com.kilometer.domain.archive.dto.PlaceInfo; import com.kilometer.domain.archive.exception.ArchiveNotFoundException; -import com.kilometer.domain.archive.exception.ArchiveUnauthorizedException; import com.kilometer.domain.archive.exception.ArchiveValidationException; -import com.kilometer.domain.archive.request.ArchiveRequest; +import com.kilometer.domain.archive.request.ArchiveCreateRequest; +import com.kilometer.domain.archive.request.ArchiveUpdateRequest; +import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceEntity; +import com.kilometer.domain.archive.userVisitPlace.UserVisitPlaceRepository; import com.kilometer.domain.item.ItemEntity; import com.kilometer.domain.item.ItemRepository; import com.kilometer.domain.item.enumType.ExhibitionType; @@ -27,6 +31,7 @@ import com.kilometer.domain.item.exception.ItemNotFoundException; import com.kilometer.domain.user.User; import com.kilometer.domain.user.UserRepository; +import com.kilometer.domain.user.exception.UserNotFoundException; import com.kilometer.exception.KilometerErrorCode; import java.time.LocalDate; import java.util.List; @@ -43,6 +48,12 @@ public class ArchiveServiceTest { @Autowired private ArchiveService archiveService; + @Autowired + private ArchiveImageRepository archiveImageRepository; + + @Autowired + private UserVisitPlaceRepository userVisitPlaceRepository; + @Autowired private UserRepository userRepository; @@ -55,7 +66,7 @@ void saveArchive() { // given User 회원 = 회원가입을_한다(); ItemEntity 아이템 = 아이템을_등록한다(); - ArchiveRequest request = new ArchiveRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + ArchiveCreateRequest request = new ArchiveCreateRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); // when @@ -71,19 +82,41 @@ void saveArchive() { } @Test - @DisplayName("아카이브 정보를 등록할때, 이미 등록한 Archive를 다시 등록하려 하면 예외가 발생한다..") - void saveArchive_duplicate() { + @DisplayName("아카이브와 관련한 정보를 등록 할 때, 아카이브 이미지와 방문장소도 같이 저장된다.") + void saveArchive_archiveImageAndUserVisitPlace() { // given User 회원 = 회원가입을_한다(); ItemEntity 아이템 = 아이템을_등록한다(); - ArchiveRequest request = new ArchiveRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + ArchiveCreateRequest request = new ArchiveCreateRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); - archiveService.save(회원.getId(), request); + // when + ArchiveInfo archiveInfo = archiveService.save(회원.getId(), request); + + // then + ArchiveImageEntity archiveImageEntity = archiveImageRepository.findById(1L).get(); + UserVisitPlaceEntity userVisitPlaceEntity = userVisitPlaceRepository.findById(1L).get(); + + assertThat(archiveImageEntity.getId()).isEqualTo(1L); + assertThat(userVisitPlaceEntity.getId()).isEqualTo(1L); + } + + @Test + @DisplayName("아카이브 정보를 등록할때, 이미 등록한 Archive를 다시 등록하려 하면 예외가 발생한다.") + void saveArchive_duplicate() { + // given + User 회원 = 회원가입을_한다(); + ItemEntity 아이템 = 아이템을_등록한다(); + ArchiveCreateRequest request = new ArchiveCreateRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); + ArchiveInfo 아카이브_생성_응답 = archiveService.save(회원.getId(), request); // when & then assertThatThrownBy(() -> archiveService.save(회원.getId(), request)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(ArchiveValidationException.class) + .hasMessage( + String.format("이미 등록한 Archive가 있습니다. sItemId : %d / UserId : %d", 아카이브_생성_응답.getId(), + 회원.getId())); } @Test @@ -94,7 +127,8 @@ void saveArchive_nullPhotoUrls() { ItemEntity 아이템 = 아이템을_등록한다(); List invalidPhotoUrls = null; - ArchiveRequest request = new ArchiveRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, invalidPhotoUrls, + ArchiveCreateRequest request = new ArchiveCreateRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, + invalidPhotoUrls, 근처_맛집); // when & then @@ -110,7 +144,7 @@ void saveArchive_nullPhotoInfos() { ItemEntity 아이템 = 아이템을_등록한다(); List invalidPhotoInfos = null; - ArchiveRequest request = new ArchiveRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + ArchiveCreateRequest request = new ArchiveCreateRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, invalidPhotoInfos); // when & then @@ -125,13 +159,13 @@ void saveArchive_notExistUser() { Long invalidUserId = 1L; ItemEntity 아이템 = 아이템을_등록한다(); - ArchiveRequest request = new ArchiveRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + ArchiveCreateRequest request = new ArchiveCreateRequest(아이템.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); // when & then assertThatThrownBy(() -> archiveService.save(invalidUserId, request)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 사용자 정보 입니다."); + .isInstanceOf(UserNotFoundException.class) + .hasMessage("저장되지 않은 사용자 입니다."); } @Test @@ -140,7 +174,8 @@ void saveArchive_forbiddenCommentWord() { // given User 회원 = 회원가입을_한다(); ItemEntity 아이템 = 아이템을_등록한다(); - ArchiveRequest request = new ArchiveRequest(아이템.getId(), 금칙어가_포함된_아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + ArchiveCreateRequest request = new ArchiveCreateRequest(아이템.getId(), 금칙어가_포함된_아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, + 방문_사진, 근처_맛집); // when & then @@ -155,7 +190,8 @@ void saveArchive_notExistsItem() { // given Long invalidItemId = -1L; User user = 회원가입을_한다(); - ArchiveRequest request = new ArchiveRequest(invalidItemId, 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); + ArchiveCreateRequest request = new ArchiveCreateRequest(invalidItemId, 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); // when ItemNotFoundException actual = assertThrows(ItemNotFoundException.class, @@ -172,7 +208,8 @@ void saveArchive_exposureOffItem() { User user = 회원가입을_한다(); ItemEntity item = ItemEntity.builder().exposureType(ExposureType.OFF).build(); itemRepository.save(item); - ArchiveRequest request = new ArchiveRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); + ArchiveCreateRequest request = new ArchiveCreateRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); // when ItemExposureOffException actual = assertThrows(ItemExposureOffException.class, @@ -188,33 +225,61 @@ void updateArchive() { // given User user = 회원가입을_한다(); ItemEntity item = 아이템을_등록한다(); - ArchiveRequest request = new ArchiveRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); + ArchiveCreateRequest request = new ArchiveCreateRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); ArchiveInfo savedArchive = archiveService.save(user.getId(), request); // when - ArchiveRequest updateRequest = new ArchiveRequest(null, "수정된 아카이브 코멘트", 3, false, List.of(), List.of()); + ArchiveUpdateRequest updateRequest = new ArchiveUpdateRequest(null, "수정된 아카이브 코멘트", 3, false, 방문_사진, + 근처_맛집); ArchiveInfo actual = archiveService.update(user.getId(), savedArchive.getId(), updateRequest); // then assertAll( () -> assertThat(actual.getComment()).isEqualTo("수정된 아카이브 코멘트"), () -> assertThat(actual.getStarRating()).isEqualTo(3), - () -> assertThat(actual.getPhotoUrls()).isEmpty(), - () -> assertThat(actual.getFood()).isBlank(), + () -> assertThat(actual.getPhotoUrls()).hasSize(1), + () -> assertThat(actual.getFood()).isEqualTo("맛집"), () -> assertThat(actual.getCafe()).isBlank() ); } + @Test + @DisplayName("아카이브를 수정 할 때, 아카이브 이미지와 방문 사진도 함께 수정된다.") + void updateArchive_withArchiveImageAndUserVisitPlace() { + // given + User user = 회원가입을_한다(); + ItemEntity item = 아이템을_등록한다(); + ArchiveCreateRequest request = new ArchiveCreateRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, List.of(), + List.of()); + ArchiveInfo savedArchive = archiveService.save(user.getId(), request); + + ArchiveUpdateRequest updateRequest = new ArchiveUpdateRequest(null, "수정된 아카이브 코멘트", 3, false, 방문_사진, + 근처_맛집); + + // when + archiveService.update(user.getId(), savedArchive.getId(), updateRequest); + + // then + ArchiveImageEntity archiveImageEntity = archiveImageRepository.findById(1L).get(); + UserVisitPlaceEntity userVisitPlaceEntity = userVisitPlaceRepository.findById(1L).get(); + + assertThat(archiveImageEntity.getId()).isEqualTo(1L); + assertThat(userVisitPlaceEntity.getId()).isEqualTo(1L); + } + @Test @DisplayName("아카이브를 수정할 때, 수정하려는 코멘트에 금칙어가 포함되면 예외가 발생한다.") void updateArchive_forbiddenComment() { // given User user = 회원가입을_한다(); ItemEntity item = 아이템을_등록한다(); - ArchiveRequest request = new ArchiveRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); + ArchiveCreateRequest request = new ArchiveCreateRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); ArchiveInfo savedArchive = archiveService.save(user.getId(), request); - ArchiveRequest updateRequest = new ArchiveRequest(null, 금칙어가_포함된_아카이브_코멘트, 3, false, List.of(), List.of()); + ArchiveUpdateRequest updateRequest = new ArchiveUpdateRequest(null, 금칙어가_포함된_아카이브_코멘트, 3, false, List.of(), + List.of()); // then assertThatThrownBy(() -> archiveService.update(user.getId(), savedArchive.getId(), updateRequest)) @@ -228,17 +293,20 @@ void updateArchive_unauthorized() { // given User user = 회원가입을_한다(); ItemEntity item = 아이템을_등록한다(); - ArchiveRequest request = new ArchiveRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); + ArchiveCreateRequest request = new ArchiveCreateRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); ArchiveInfo savedArchive = archiveService.save(user.getId(), request); - // when - ArchiveRequest updateRequest = new ArchiveRequest(null, "수정된 아카이브 코멘트", 3, false, List.of(), List.of()); + ArchiveUpdateRequest updateRequest = new ArchiveUpdateRequest(null, "수정된 아카이브 코멘트", 3, false, List.of(), + List.of()); Long invalidUserId = -1L; - ArchiveUnauthorizedException actualException = assertThrows(ArchiveUnauthorizedException.class, + + // when + ArchiveNotFoundException actualException = assertThrows(ArchiveNotFoundException.class, () -> archiveService.update(invalidUserId, savedArchive.getId(), updateRequest)); // then - assertEquals(actualException.getErrorCode(), KilometerErrorCode.ARCHIVE_UNAUTHORIZED_EXCEPTION); + assertEquals(actualException.getErrorCode(), KilometerErrorCode.ARCHIVE_NOT_FOUND); } @Test @@ -247,11 +315,13 @@ void updateArchive_archiveNotExists() { // given User user = 회원가입을_한다(); ItemEntity item = 아이템을_등록한다(); - ArchiveRequest request = new ArchiveRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, 근처_맛집); + ArchiveCreateRequest request = new ArchiveCreateRequest(item.getId(), 아카이브_코멘트, 아카이브_별점, 아카이브_공개_설정, 방문_사진, + 근처_맛집); ArchiveInfo savedArchive = archiveService.save(user.getId(), request); // when - ArchiveRequest updateRequest = new ArchiveRequest(null, "수정된 아카이브 코멘트", 3, false, List.of(), List.of()); + ArchiveUpdateRequest updateRequest = new ArchiveUpdateRequest(null, "수정된 아카이브 코멘트", 3, false, List.of(), + List.of()); Long invalidArchiveId = -1L; ArchiveNotFoundException actualException = assertThrows(ArchiveNotFoundException.class, () -> archiveService.update(user.getId(), invalidArchiveId, updateRequest));