Skip to content

Commit

Permalink
Merge pull request #86 from UMC-ON/feat/marketpostnscrap
Browse files Browse the repository at this point in the history
[Refactor] 물품거래 및 스크랩 API 리팩토링
  • Loading branch information
isuHan authored Sep 18, 2024
2 parents 4117f14 + 3904ef6 commit c675b36
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
import com.on.server.domain.marketPost.dto.MarketPostRequestDTO;
import com.on.server.domain.marketPost.dto.MarketPostResponseDTO;
import com.on.server.domain.user.domain.User;
import com.on.server.domain.user.domain.repository.UserRepository;
import com.on.server.global.aws.s3.uuidFile.application.UuidFileService;
import com.on.server.global.aws.s3.uuidFile.domain.FilePath;
import com.on.server.global.aws.s3.uuidFile.domain.UuidFile;
import com.on.server.global.aws.s3.uuidFile.domain.repository.UuidFileRepository;
import com.on.server.global.common.ResponseCode;
import com.on.server.global.common.exceptions.BadRequestException;
import com.on.server.global.common.exceptions.UnauthorizedException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
Expand All @@ -27,29 +30,24 @@
public class MarketPostService {

private final MarketPostRepository marketPostRepository;
private final UserRepository userRepository;
private final UuidFileService uuidFileService;
private final UuidFileRepository uuidFileRepository;

// 1. 모든 물품글 조회
public List<MarketPostResponseDTO> getAllMarketPosts() {
return marketPostRepository.findAllByOrderByCreatedAtDesc().stream()
.map(this::mapToMarketPostResponseDTO)
.collect(Collectors.toList());
public Page<MarketPostResponseDTO> getAllMarketPosts(Pageable pageable) {
return marketPostRepository.findAllByOrderByCreatedAtDesc(pageable)
.map(MarketPostResponseDTO::from);
}

// 2. 특정 물품글 조회
public MarketPostResponseDTO getMarketPostById(Long marketPostId) {
MarketPost marketPost = marketPostRepository.findById(marketPostId)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다. ID: " + marketPostId));
return mapToMarketPostResponseDTO(marketPost);
.orElseThrow(() -> new BadRequestException(ResponseCode.ROW_DOES_NOT_EXIST, "게시글을 찾을 수 없습니다. ID: " + marketPostId));
return MarketPostResponseDTO.from(marketPost);
}

// 3. 새로운 물품글 작성
@Transactional
public MarketPostResponseDTO createMarketPost(MarketPostRequestDTO requestDTO, List<MultipartFile> imageFiles) {
User user = userRepository.findById(requestDTO.getUserId())
.orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다. ID: " + requestDTO.getUserId()));
public MarketPostResponseDTO createMarketPost(User user, MarketPostRequestDTO requestDTO, List<MultipartFile> imageFiles) {

// 이미지 파일 처리
List<UuidFile> uploadedImages = new ArrayList<>();
Expand All @@ -74,29 +72,23 @@ public MarketPostResponseDTO createMarketPost(MarketPostRequestDTO requestDTO, L

marketPost = marketPostRepository.save(marketPost);

return mapToMarketPostResponseDTO(marketPost);
return MarketPostResponseDTO.from(marketPost);
}

// 4. 특정 사용자가 작성한 모든 물품글 조회
public List<MarketPostResponseDTO> getMarketPostsByUserId(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다. ID: " + userId));

return marketPostRepository.findByUserOrderByCreatedAtDesc(user).stream()
.map(this::mapToMarketPostResponseDTO)
.collect(Collectors.toList());
public Page<MarketPostResponseDTO> getMarketPostsByUser(User user, Pageable pageable) {
return marketPostRepository.findByUserOrderByCreatedAtDesc(user, pageable)
.map(MarketPostResponseDTO::from);
}

// 5. 특정 게시글 삭제
@Transactional
public void deleteMarketPost(Long userId, Long marketPostId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다. ID: " + userId));
public void deleteMarketPost(User user, Long marketPostId) {
MarketPost marketPost = marketPostRepository.findById(marketPostId)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다. ID: " + marketPostId));
.orElseThrow(() -> new BadRequestException(ResponseCode.ROW_DOES_NOT_EXIST, "게시글을 찾을 수 없습니다. ID: " + marketPostId));

if (!marketPost.getUser().getId().equals(userId)) {
throw new RuntimeException("삭제 권한이 없습니다.");
if (!marketPost.getUser().getId().equals(user.getId())) {
throw new UnauthorizedException(ResponseCode.GRANT_ROLE_NOT_ALLOWED, "삭제 권한이 없습니다.");
}

// 연관된 이미지 삭제
Expand All @@ -107,67 +99,41 @@ public void deleteMarketPost(Long userId, Long marketPostId) {

// 6. 거래 상태 업데이트
@Transactional
public MarketPostResponseDTO updateMarketPostStatus(Long marketPostId, DealStatus status) {
public MarketPostResponseDTO updateMarketPostStatus(Long marketPostId) {
MarketPost marketPost = marketPostRepository.findById(marketPostId)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다. ID: " + marketPostId));
.orElseThrow(() -> new BadRequestException(ResponseCode.ROW_DOES_NOT_EXIST, "게시글을 찾을 수 없습니다. ID: " + marketPostId));

if (marketPost.getDealStatus() != DealStatus.AWAIT) {
throw new RuntimeException("거래 상태가 AWAIT인 경우에만 COMPLETE로 업데이트할 수 있습니다.");
}
marketPost.completeDeal(); // 상태 업데이트

marketPost.setDealStatus(DealStatus.COMPLETE); // 상태 업데이트
MarketPost updatedMarketPost = marketPostRepository.save(marketPost); // 저장

return mapToMarketPostResponseDTO(updatedMarketPost);
return MarketPostResponseDTO.from(updatedMarketPost);
}

// 필터링: 거래형식, 국가, 거래상태 필터링
public List<MarketPostResponseDTO> getFilteredMarketPosts(DealType dealType, String currentCountry, DealStatus dealStatus) {
return marketPostRepository.findFilteredMarketPosts(dealType, currentCountry, dealStatus).stream()
.map(this::mapToMarketPostResponseDTO)
.collect(Collectors.toList());
public Page<MarketPostResponseDTO> getFilteredMarketPosts(DealType dealType, String currentCountry, DealStatus dealStatus, Pageable pageable) {
return marketPostRepository.findFilteredMarketPosts(dealType, currentCountry, dealStatus, pageable)
.map(MarketPostResponseDTO::from);
}

// 필터링: 거래 가능 물품만 보기
public List<MarketPostResponseDTO> getAvailableMarketPosts() {
return marketPostRepository.findFilteredMarketPosts(null, null, DealStatus.AWAIT).stream()
.map(this::mapToMarketPostResponseDTO)
.collect(Collectors.toList());
public Page<MarketPostResponseDTO> getAvailableMarketPosts(Pageable pageable) {
return marketPostRepository.findFilteredMarketPosts(null, null, DealStatus.AWAIT, pageable)
.map(MarketPostResponseDTO::from);
}

// 검색 기능
public List<MarketPostResponseDTO> searchMarketPosts(String keyword) {
List<MarketPost> marketPosts = marketPostRepository.searchMarketPosts(keyword);
return marketPosts.stream()
.map(this::mapToMarketPostResponseDTO)
.collect(Collectors.toList());
public Page<MarketPostResponseDTO> searchMarketPosts(String keyword, Pageable pageable) {
return marketPostRepository.searchMarketPosts(keyword, pageable)
.map(MarketPostResponseDTO::from);
}

// 내 주변 물품거래글
// 특정 물품글 조회와 함께 동일한 위치의 다른 게시글 3개 조회
public List<MarketPostResponseDTO> getNearbyMarketPosts(String currentCountry, Long marketPostId) {
List<MarketPost> nearbyPosts = marketPostRepository.findTop3ByCurrentCountryAndAwaitingOrder(currentCountry, marketPostId);
return nearbyPosts.stream()
.map(this::mapToMarketPostResponseDTO)
.map(MarketPostResponseDTO::from)
.collect(Collectors.toList());
}

// MarketPost 엔티티를 MarketPostResponseDto로 매핑하는 메서드
private MarketPostResponseDTO mapToMarketPostResponseDTO(MarketPost marketPost) {
return MarketPostResponseDTO.builder()
.marketPostId(marketPost.getId())
.userId(marketPost.getUser().getId())
.nickname(marketPost.getUser().getNickname())
.currentCountry(marketPost.getCurrentCountry())
.currentLocation(marketPost.getCurrentLocation())
.title(marketPost.getTitle())
.cost(marketPost.getCost())
.isShare(marketPost.isShare())
.dealType(marketPost.getDealType())
.dealStatus(marketPost.getDealStatus())
.content(marketPost.getContent())
.createdAt(marketPost.getCreatedAt())
.imageUrls(marketPost.getImages().stream().map(UuidFile::getFileUrl).collect(Collectors.toList())) // 이미지 URL 리스트
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.util.List;

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
Expand Down Expand Up @@ -55,6 +54,13 @@ public class MarketPost extends BaseEntity {
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "market_post_id")
private List<UuidFile> images = new ArrayList<>(); // 이미지 리스트 필드 추가

public void completeDeal() {
if (this.dealStatus != DealStatus.AWAIT) {
throw new IllegalStateException("거래 상태가 AWAIT인 경우에만 COMPLETE로 업데이트할 수 있습니다.");
}
this.dealStatus = DealStatus.COMPLETE;
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.on.server.domain.marketPost.domain.DealType;
import com.on.server.domain.marketPost.domain.MarketPost;
import com.on.server.domain.user.domain.User;
import org.springframework.data.domain.Page;
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;
Expand All @@ -14,26 +16,25 @@
@Repository
public interface MarketPostRepository extends JpaRepository<MarketPost, Long> {

List<MarketPost> findByUser(User user);

// 필터링
@Query("SELECT mp FROM MarketPost mp WHERE (:dealType IS NULL OR mp.dealType = :dealType) " +
"AND (:currentCountry IS NULL OR mp.currentCountry = :currentCountry) " +
"AND (:dealStatus IS NULL OR mp.dealStatus = :dealStatus)"+
"ORDER BY mp.createdAt DESC")

List<MarketPost> findFilteredMarketPosts(
Page<MarketPost> findFilteredMarketPosts(
@Param("dealType") DealType dealType,
@Param("currentCountry") String currentCountry,
@Param("dealStatus") DealStatus dealStatus);
@Param("dealStatus") DealStatus dealStatus,
Pageable pageable);

// 검색: 국가와 물품에 대한 제목 또는 내용을 검색하는 메서드
@Query("SELECT mp FROM MarketPost mp WHERE " +
"mp.currentCountry LIKE %:keyword% OR " +
"mp.title LIKE %:keyword% OR " +
"mp.content LIKE %:keyword% " +
"ORDER BY mp.createdAt DESC")
List<MarketPost> searchMarketPosts(@Param("keyword") String keyword);
Page<MarketPost> searchMarketPosts(@Param("keyword") String keyword, Pageable pageable);

// 내 주변 물품거래글: 특정 국가에서 거래 상태가 AWAIT인 최신순 3개의 게시글 조회
@Query("SELECT mp FROM MarketPost mp WHERE mp.currentCountry = :currentCountry " +
Expand All @@ -43,6 +44,6 @@ List<MarketPost> findFilteredMarketPosts(
List<MarketPost> findTop3ByCurrentCountryAndAwaitingOrder(@Param("currentCountry") String currentCountry, @Param("marketPostId") Long marketPostId);

// 최신순 정렬
List<MarketPost> findAllByOrderByCreatedAtDesc();
List<MarketPost> findByUserOrderByCreatedAtDesc(User user);
Page<MarketPost> findAllByOrderByCreatedAtDesc(Pageable pageable);
Page<MarketPost> findByUserOrderByCreatedAtDesc(User user, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.on.server.domain.marketPost.domain.DealStatus;
import com.on.server.domain.marketPost.domain.DealType;
import com.on.server.domain.marketPost.domain.MarketPost;
import com.on.server.global.aws.s3.uuidFile.domain.UuidFile;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Getter
@Builder
Expand Down Expand Up @@ -56,4 +58,25 @@ public class MarketPostResponseDTO {
// 작성 시간
private LocalDateTime createdAt;

// MarketPost 엔티티를 MarketPostResponseDTO로 매핑하는 메서드
public static MarketPostResponseDTO from(MarketPost marketPost) {
return MarketPostResponseDTO.builder()
.marketPostId(marketPost.getId())
.userId(marketPost.getUser().getId())
.nickname(marketPost.getUser().getNickname())
.currentCountry(marketPost.getCurrentCountry())
.currentLocation(marketPost.getCurrentLocation())
.title(marketPost.getTitle())
.cost(marketPost.getCost())
.isShare(marketPost.isShare())
.dealType(marketPost.getDealType())
.dealStatus(marketPost.getDealStatus())
.content(marketPost.getContent())
.createdAt(marketPost.getCreatedAt())
.imageUrls(marketPost.getImages().stream()
.map(UuidFile::getFileUrl)
.collect(Collectors.toList())) // 이미지 URL 리스트
.build();
}

}
Loading

0 comments on commit c675b36

Please sign in to comment.