Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 26 additions & 0 deletions src/main/java/com/projectX/projectX/domain/tour/entity/Tour.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.projectX.projectX.domain.tour.entity;

import com.projectX.projectX.domain.member.entity.Member;
import com.projectX.projectX.global.common.BaseEntity;
import com.projectX.projectX.global.common.ContentType;
import com.projectX.projectX.global.common.JejuRegion;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
Expand All @@ -13,6 +15,7 @@
import jakarta.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand Down Expand Up @@ -86,6 +89,10 @@ public class Tour extends BaseEntity {
@Comment("카카오맵 URL")
private String kakaoMapUrl;

@Comment("user 스크랩 정보")
@OneToMany(mappedBy = "tour", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UserScrapTour> scraps;

@Builder
public Tour(Long id, String address, String spec_address, Long zipCode, Long contentId,
ContentType contentType, JejuRegion jejuRegion, String imageUrl, float mapX, float mapY,
Expand Down Expand Up @@ -119,4 +126,23 @@ public void updatePhone(String phone) {
public void updateKakaoMapUrl(String kakaoMapUrl){
this.kakaoMapUrl = kakaoMapUrl;
}

public Boolean updateScrap(Tour tour, Member member) {
UserScrapTour forRemove = null;
for (UserScrapTour scrap : this.scraps) {
if (Objects.equals(scrap.getTour(), tour) && Objects.equals(scrap.getMember(),
member)) {
forRemove = scrap;
break;
}
}

if (Objects.nonNull(forRemove)) {
this.scraps.remove(forRemove);
return false;
}

this.scraps.add(new UserScrapTour(tour, member));
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.projectX.projectX.domain.tour.entity;

import com.projectX.projectX.domain.member.entity.Member;
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.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserScrapTour {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "tour_id")
private Tour tour;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "member_id")
private Member member;

@Builder
public UserScrapTour(Tour tour, Member member) {
this.tour = tour;
this.member = member;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
import com.projectX.projectX.domain.travel.service.TravelService;
import com.projectX.projectX.global.common.JejuRegion;
import com.projectX.projectX.global.common.ResponseDTO;
import com.projectX.projectX.global.security.dto.CustomOAuth2User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
Expand Down Expand Up @@ -59,4 +62,15 @@ public ResponseDTO<?> getRecommdTravelInfo(
return ResponseDTO.res(travelService.getTravelRecommd(jejuRegion), "travel 추천 조회에 성공했습니다.");
}

@PostMapping("/{travel_id}/scrap")
@ResponseStatus(HttpStatus.CREATED)
@Operation(summary = "travel 스크랩 API", description = "travel 게시물을 스크랩하는 API입니다.")
public ResponseDTO<?> postTravelScrapInfo(
@PathVariable("travel_id") @NotNull Long travelId,
@AuthenticationPrincipal CustomOAuth2User user
) {
String result = travelService.postTravelScrapInfo(travelId, user.getEmail());
return ResponseDTO.res(result);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.projectX.projectX.domain.travel.service;

import com.projectX.projectX.domain.member.entity.Member;
import com.projectX.projectX.domain.member.exception.InvalidMemberException;
import com.projectX.projectX.domain.member.repository.MemberRepository;
import com.projectX.projectX.domain.tour.entity.Tour;
import com.projectX.projectX.domain.tour.entity.TourImage;
import com.projectX.projectX.domain.tour.repository.TourRepository;
Expand Down Expand Up @@ -33,6 +36,7 @@
public class TravelService {

private final TourRepository tourRepository;
private final MemberRepository memberRepository;
private static final int RECOMMEND_WORK_SIZE = 3;

@Transactional(readOnly = true)
Expand Down Expand Up @@ -82,6 +86,14 @@ private Tour getTour(long tourId) {
.orElseThrow(() -> new TravelNotFoundException(ErrorCode.TRAVEL_NOT_FOUND));
}

private Member getMember(String userEmail) {
Member member = memberRepository.findByUserEmail(userEmail).orElseThrow(
() -> new InvalidMemberException(ErrorCode.INVALID_MEMBER_EXCEPTION)
);

return member;
}

private List<String> getTravelImageUrlList(List<TourImage> tourImageList) {
if (tourImageList.isEmpty()) {
return null;
Expand Down Expand Up @@ -113,5 +125,13 @@ public List<TravelGetRecommdResponse> getTravelRecommd(JejuRegion jejuRegion) {
return TravelMapper.toTravelGetRecommendResponse(tours);
}

@Transactional
public String postTravelScrapInfo(Long travelId, String userEmail) {
Tour tour = getTour(travelId);
Member member = getMember(userEmail);

Boolean result = tour.updateScrap(tour, member);
return result ? "travel 정보를 스크랩했습니다." : "travel 스크랩을 취소했습니다.";
}

}