Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.tasksprints.auction.domain.auction.service.AuctionService;
import com.tasksprints.auction.domain.bid.dto.BidResponse;
import com.tasksprints.auction.domain.bid.service.BidService;
import com.tasksprints.auction.domain.product.model.ProductCategory;
import com.tasksprints.auction.domain.review.dto.request.ReviewRequest;
import com.tasksprints.auction.domain.review.dto.response.ReviewResponse;
import com.tasksprints.auction.domain.review.service.ReviewService;
Expand All @@ -16,6 +17,8 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

Expand Down Expand Up @@ -80,8 +83,8 @@ public ResponseEntity<ApiResult<String>> getAuctionStatus(@PathVariable Long auc
@GetMapping
@Operation(summary = "Get all auctions", description = "Retrieves all auctions.")
@ApiResponse(responseCode = "200", description = "All auctions retrieved successfully")
public ResponseEntity<ApiResult<List<AuctionResponse>>> getAllAuctions(AuctionRequest.SearchCondition searchCondition) {
List<AuctionResponse> auctions = auctionService.getAuctionsByFilter(searchCondition);
public ResponseEntity<ApiResult<Page<AuctionResponse.Details>>> getAllAuctions(Pageable pageable, AuctionRequest.SearchCondition searchCondition) {
Page<AuctionResponse.Details> auctions = auctionService.getAuctionsByFilter(pageable, searchCondition);
return ResponseEntity.ok(ApiResult.success(ApiResponseMessages.ALL_AUCTIONS_RETRIEVED, auctions));
}

Expand All @@ -93,6 +96,15 @@ public ResponseEntity<ApiResult<AuctionResponse>> getAuctionById(@PathVariable L
return ResponseEntity.ok(ApiResult.success(ApiResponseMessages.AUCTION_RETRIEVED, auction));
}

@Deprecated
@GetMapping("/category/{category}")
@Operation(summary = "Get auctions by ProductCategory", description = "Retrieve all auction by its ProductCategory.")
@ApiResponse(responseCode = "200", description = "All auctions retrieved successfully")
public ResponseEntity<ApiResult<Page<AuctionResponse.Details>>> getAuctionByProductCategory(Pageable pageable, @PathVariable String category, AuctionRequest.SearchCondition searchCondition) {
Page<AuctionResponse.Details> auctions = auctionService.getAuctionsByProductCategory(pageable, searchCondition, ProductCategory.fromDisplayName(category));
return ResponseEntity.ok(ApiResult.success(ApiResponseMessages.AUCTION_RETRIEVED, auctions));
}

// Bid Endpoints
@PostMapping("/{auctionId}/bid")
@Operation(summary = "Submit a bid", description = "Submits a bid for the specified auction.")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.tasksprints.auction.domain.auction.dto.response;

import com.tasksprints.auction.domain.auction.model.Auction;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.tasksprints.auction.domain.product.model.ProductImage;
import lombok.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

import static java.util.stream.Collectors.toList;

@Data
@Builder
Expand All @@ -20,11 +22,50 @@ public class AuctionResponse {
private String category;
private String status;
private BigDecimal startingBid;

private Long viewCount;
private Long sellerId;
private String sellerNickName;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Details {
private Long id;
private LocalDateTime startTime;
private LocalDateTime endTime;
private String category;
private String status;
private BigDecimal startingBid;
private Long viewCount;
private Long sellerId;
private String sellerNickName;
private Long productId;
private String productCategory;
@Setter
private List<String> productImageUrls;

public static AuctionResponse.Details of(Auction auction) {
return AuctionResponse.Details.builder()
.id(auction.getId())
.startTime(auction.getStartTime())
.endTime(auction.getEndTime())
.category(auction.getAuctionCategory().name())
.status(auction.getAuctionStatus().name())
.startingBid(auction.getStartingBid())
.viewCount(auction.getViewCount())
.sellerId(auction.getSeller() != null ? auction.getSeller().getId() : null)
.sellerNickName(auction.getSeller() != null ? auction.getSeller().getNickName() : null)
.productId(auction.getProduct() != null ? auction.getProduct().getId() : null)
.productCategory(auction.getProduct() != null && auction.getProduct().getCategory() != null ? auction.getProduct().getCategory().name() : null)
.productImageUrls(auction.getProduct() != null && auction.getProduct().getProductImageList() != null
? auction.getProduct().getProductImageList().stream()
.map(ProductImage::getImageUrl)
.collect(toList())
: Collections.emptyList())
.build();
}
}
public static AuctionResponse of(Auction auction) {
return AuctionResponse.builder()
.id(auction.getId())
Expand All @@ -33,6 +74,7 @@ public static AuctionResponse of(Auction auction) {
.category(auction.getAuctionCategory().name())
.status(auction.getAuctionStatus().name())
.startingBid(auction.getStartingBid())
.viewCount(auction.getViewCount())
.sellerId(auction.getSeller().getId())
.sellerNickName(auction.getSeller().getNickName())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.tasksprints.auction.domain.user.model.User;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.ColumnDefault;

import java.math.BigDecimal;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -50,11 +51,20 @@ public class Auction extends BaseEntity {
@Builder.Default
private Product product = null;


@OneToMany
@Builder.Default
private List<Bid> bids = new ArrayList<>();

@Column(nullable = false)
private Long viewCount;

@PrePersist
protected void onCreate() {
if (viewCount == null) {
viewCount = 0L; // 기본값 설정
}
}

public static Auction create(LocalDateTime startTime, LocalDateTime endTime, BigDecimal startingBid, AuctionCategory auctionCategory, AuctionStatus auctionStatus, User seller) {
Auction newAuction = Auction.builder()
.startTime(startTime)
Expand All @@ -68,7 +78,7 @@ public static Auction create(LocalDateTime startTime, LocalDateTime endTime, Big
}

public void addProduct(Product product) {
product.addAuction(this);
//product.addAuction(this); product에서 auction을 추가하고 있어서 중복
this.product = product;
}

Expand All @@ -77,4 +87,12 @@ public void addUser(User seller) {
this.seller = seller;
}

public void incrementViewCount() {
if (viewCount == null) {
viewCount = 0L;
}
this.viewCount += 1;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ public enum AuctionCategory {
PRIVATE_PAID,
PUBLIC_PAID;


public static AuctionCategory fromDisplayName(String auctionCategory) {
try {
return AuctionCategory.valueOf(auctionCategory.toUpperCase()); // 대문자로 변환하여 비교
} catch (IllegalArgumentException e) {
return PUBLIC_FREE; // 유효하지 않은 값일 경우 기본값으로 PUBLIC_FREE 반환
for (AuctionCategory category : values()) {
if (category.name().equalsIgnoreCase(auctionCategory)) {
return category;
}
}
throw new IllegalArgumentException("Unknown auctionCategory: " + auctionCategory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ public enum AuctionStatus {
CANCELED;

public static AuctionStatus fromDisplayName(String auctionStatus) {
try {
return AuctionStatus.valueOf(auctionStatus.toUpperCase()); // 대문자로 변환하여 비교
} catch (IllegalArgumentException e) {
return AuctionStatus.ACTIVE; // 유효하지 않은 값일 경우 기본값으로 ACTIVE 반환
for (AuctionStatus status : values() ) {
if (status.name().equalsIgnoreCase(auctionStatus)) {
return status;
}
}
throw new IllegalArgumentException("Unknown auctionStatus: " + auctionStatus);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package com.tasksprints.auction.domain.auction.repository.support;

import com.tasksprints.auction.domain.auction.dto.request.AuctionRequest;
import com.tasksprints.auction.domain.auction.dto.response.AuctionResponse;

import com.tasksprints.auction.domain.auction.model.Auction;
import com.tasksprints.auction.domain.product.model.ProductCategory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface AuctionCriteriaRepository {
List<Auction> getAuctionsByFilters(AuctionRequest.SearchCondition searchCondition);
Page<Auction> getAuctionsByFilters(Pageable pageable, AuctionRequest.SearchCondition searchCondition);
@Deprecated
Page<Auction> getAuctionsByCategory(Pageable pageable,
AuctionRequest.SearchCondition searchCondition,
ProductCategory category);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,85 @@
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.tasksprints.auction.domain.auction.dto.request.AuctionRequest;
import com.tasksprints.auction.domain.auction.model.Auction;
import com.tasksprints.auction.domain.auction.model.QAuction;
import com.tasksprints.auction.domain.product.model.QProduct;
import com.tasksprints.auction.domain.product.model.ProductCategory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;

import java.util.List;

import static com.tasksprints.auction.domain.auction.model.QAuction.auction;
import static com.tasksprints.auction.domain.product.model.QProduct.product;
import static com.tasksprints.auction.domain.user.model.QUser.user;

@RequiredArgsConstructor
@Repository
public class AuctionCriteriaRepositoryImpl implements AuctionCriteriaRepository {
private final JPAQueryFactory queryFactory;

public List<Auction> getAuctionsByFilters(AuctionRequest.SearchCondition condition) {
QAuction auction = QAuction.auction;
QProduct product = QProduct.product;
public Page<Auction> getAuctionsByFilters(Pageable pageable, AuctionRequest.SearchCondition condition) {
BooleanBuilder builder = buildSearchCondition(condition);
OrderSpecifier<?> sortOrder = getSortOrder(condition);
List<Auction> result = buildQueryWithPaginationAndSorting(builder, pageable, sortOrder);

// int 오버플로 주의
// int total = queryFactory
// .selectFrom(auction)
// .where(builder)
// .fetch().size();

BooleanBuilder builder = buildSearchCondition(condition, auction, product);
long total = result.size();

return new PageImpl<>(result, pageable, total);
}

var query = queryFactory.selectFrom(auction)
private List<Auction> buildQueryWithPaginationAndSorting(BooleanBuilder builder, Pageable pageable, OrderSpecifier<?> sortOrder) {
var mainQuery = queryFactory
.selectFrom(auction)
.leftJoin(auction.product, product)
.where(builder);
.fetchJoin()
.leftJoin(auction.seller, user)
.fetchJoin()
.where(builder)
.offset(pageable.getOffset())
.limit(pageable.getPageSize());

OrderSpecifier<?> sortOrder = getSortOrder(condition, auction);
if (sortOrder != null) {
query = query.orderBy(sortOrder);
mainQuery.orderBy(sortOrder);
}

return query.fetch();
return mainQuery.fetch();
}

@Deprecated
public Page<Auction> getAuctionsByCategory(Pageable pageable,
AuctionRequest.SearchCondition condition,
ProductCategory category) {

BooleanBuilder builder = buildSearchCondition(condition);
filterByCategory(category, builder);
OrderSpecifier<?> sortOrder = getSortOrder(condition);
List<Auction> result = buildQueryWithPaginationAndSorting(builder, pageable, sortOrder);

int total = queryFactory
.selectFrom(auction)
.where(builder)
.fetch().size();

return new PageImpl<>(result, pageable, total);

}
@Deprecated
private void filterByCategory(ProductCategory category, BooleanBuilder builder) {
if (category != null) {
builder.and(product.category.eq(category));
}
}

private BooleanBuilder buildSearchCondition(AuctionRequest.SearchCondition condition, QAuction auction, QProduct product) {

private BooleanBuilder buildSearchCondition(AuctionRequest.SearchCondition condition) {
BooleanBuilder builder = new BooleanBuilder();

if (condition.getAuctionCategory() != null) {
Expand All @@ -57,15 +105,20 @@ private BooleanBuilder buildSearchCondition(AuctionRequest.SearchCondition condi
return builder;
}

private OrderSpecifier<?> getSortOrder(AuctionRequest.SearchCondition condition, QAuction auction) {
private OrderSpecifier<?> getSortOrder(AuctionRequest.SearchCondition condition) {
if (condition.getSortBy() != null) {
return switch (condition.getSortBy()) {
case "bidsAsc" -> auction.bids.size().asc();
case "bidsDesc" -> auction.bids.size().desc();
case "endingSoon" -> auction.endTime.asc();
case "endTimeASC" -> auction.endTime.asc();
case "startTimeASC" -> auction.startTime.asc();
case "viewCountDESC" -> auction.viewCount.desc();

default -> null;
};
}
return null;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import com.tasksprints.auction.domain.auction.dto.request.AuctionRequest;
import com.tasksprints.auction.domain.auction.dto.response.AuctionResponse;
import com.tasksprints.auction.domain.product.model.ProductCategory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

Expand All @@ -21,6 +24,8 @@ public interface AuctionService {

AuctionResponse getAuctionById(Long auctionId);

List<AuctionResponse> getAuctionsByFilter(AuctionRequest.SearchCondition searchCondition);
Page<AuctionResponse.Details> getAuctionsByFilter(Pageable pageable, AuctionRequest.SearchCondition searchCondition);

@Deprecated
Page<AuctionResponse.Details> getAuctionsByProductCategory(Pageable pageable, AuctionRequest.SearchCondition searchCondition, ProductCategory category);
}
Loading