Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

경매 추천 시스템 반영 #200

Merged
merged 3 commits into from
Aug 14, 2024
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
6 changes: 4 additions & 2 deletions docker-compose-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ services:
- API_KEY=${API_KEY}
- WEBHOOK_SLACK_URL=${WEBHOOK_SLACK_URL}
- REC_SYS_HOST=${REC_SYS_HOST}
- REC_PRODUCT_ENDPOINT=${REC_PRODUCT_ENDPOINT}
- PROFILE_ENDPOINT=${PROFILE_ENDPOINT}
- REC_PRODUCT_PURCHASE=${REC_PRODUCT_PURCHASE}
- REC_AUCTION_PURCHASE=${REC_AUCTION_PURCHASE}
- RECOMMEND_PRODUCT=${RECOMMEND_PRODUCT}
- REC_PRODUCT_LIMIT=${REC_PRODUCT_LIMIT}
- RECOMMEND_AUCTION=${RECOMMEND_AUCTION}
- REC_LIMIT=${REC_LIMIT}
ports:
- "8080:8080"
- "8090:8090"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
import freshtrash.freshtrashbackend.domain.alarm.entity.constants.AlarmType;
import freshtrash.freshtrashbackend.domain.alarm.service.template.BiddingHistoryAlarmTemplate;
import freshtrash.freshtrashbackend.domain.auction.entity.BiddingHistory;
import freshtrash.freshtrashbackend.global.infra.RecSysService;
import freshtrash.freshtrashbackend.producer.AuctionProducer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class CompletePayAuctionAlarm extends BiddingHistoryAlarmTemplate {
private final RecSysService recSysService;

public CompletePayAuctionAlarm(AuctionProducer producer) {
public CompletePayAuctionAlarm(AuctionProducer producer, RecSysService recSysService) {
super(producer);
this.recSysService = recSysService;
}

@Override
public void update(BiddingHistory biddingHistory) {
log.debug("결제 여부를 true로 업데이트");
log.debug("프로필 업데이트 후 결제 여부를 true로 업데이트");
recSysService.purchaseAuction(biddingHistory.getAuctionId(), biddingHistory.getMemberId());
biddingHistory.setPay(true);
}

JadeKim042386 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import freshtrash.freshtrashbackend.domain.member.entity.constants.UserRole;
import freshtrash.freshtrashbackend.global.exception.AuctionException;
import freshtrash.freshtrashbackend.global.exception.constants.ErrorCode;
import freshtrash.freshtrashbackend.global.infra.RecSysService;
import freshtrash.freshtrashbackend.global.infra.file.FileService;
import freshtrash.freshtrashbackend.global.utils.FileUtils;
import lombok.RequiredArgsConstructor;
Expand All @@ -37,6 +38,7 @@ public class AuctionService {
private final AuctionRepository auctionRepository;
private final FileService fileService;
private final BiddingHistoryService biddingHistoryService;
private final RecSysService recSysService;

public AuctionResponse addAuction(
MultipartFile imgFile, AuctionRequest auctionRequest, MemberPrincipal memberPrincipal) {
Expand All @@ -46,6 +48,9 @@ public AuctionResponse addAuction(
Auction savedAuction = auctionRepository.save(auction);
// 이미지 파일 저장
fileService.uploadFile(imgFile, savedFileName);
// 경매 프로필 업데이트
recSysService.createAuction(savedAuction);

return AuctionResponse.fromEntity(savedAuction, memberPrincipal);
}

JadeKim042386 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
@ConfigurationProperties(prefix = "rec-sys")
public record RecSysProperties(
@NotBlank String host,
@NotBlank String productEndpoint,
@NotBlank String profileEndpoint,
@NotBlank String productPurchase,
@NotBlank String auctionPurchase,
@NotBlank String recommendProduct,
@Positive @NotNull Integer productLimit) {}
@NotBlank String recommendAuction,
@Positive @NotNull Integer recommendLimit) {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package freshtrash.freshtrashbackend.global.infra;

import freshtrash.freshtrashbackend.domain.auction.entity.Auction;
import freshtrash.freshtrashbackend.domain.product.entity.Product;
import freshtrash.freshtrashbackend.global.config.properties.RecSysProperties;
import freshtrash.freshtrashbackend.global.utils.RestUtils;
Expand All @@ -25,7 +26,19 @@ public void createOrUpdateProduct(Product product) {
messageBody.put("category", product.getProductCategory().getProfileIndex());
messageBody.put("title", product.getTitle());
messageBody.put("content", product.getContent());
restUtils.put(new HttpEntity<>(messageBody), getUrl(recSysProperties.productEndpoint()), Void.class);
restUtils.put(new HttpEntity<>(messageBody), getUrl(recSysProperties.profileEndpoint()), Void.class);
}

/**
* 경매 추가/수정 시 해당 상품의 프로필 정보 수정
*/
public void createAuction(Auction auction) {
Map<String, Object> messageBody = new HashMap<>();
messageBody.put("file_name", auction.getProfileFileName());
messageBody.put("category", auction.getProductCategory().getProfileIndex());
messageBody.put("title", auction.getTitle());
messageBody.put("content", auction.getContent());
restUtils.put(new HttpEntity<>(messageBody), getUrl(recSysProperties.profileEndpoint()), Void.class);
}

/**
Expand All @@ -38,6 +51,16 @@ public void purchaseProduct(Long productId, Long memberId) {
new HttpEntity<>(null), getUrl(recSysProperties.productPurchase(), productId, memberId), Void.class);
}

/**
* 낙찰된 경매 상품 구매 시 구매자의 프로필 정보 수정
* 1. 구매 횟수 + 1
* 2. 경매 프로필 누적 합 계산
*/
public void purchaseAuction(Long auctionId, Long memberId) {
restUtils.put(
new HttpEntity<>(null), getUrl(recSysProperties.auctionPurchase(), auctionId, memberId), Void.class);
}

private String getUrl(String endpoint) {
return String.format("%s%s", recSysProperties.host(), endpoint);
}
JadeKim042386 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
6 changes: 4 additions & 2 deletions src/main/resources/application-common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ webhook:

rec-sys:
host: ${REC_SYS_HOST}
product-endpoint: ${REC_PRODUCT_ENDPOINT}
profile-endpoint: ${PROFILE_ENDPOINT}
product-purchase: ${REC_PRODUCT_PURCHASE}
auction-purchase: ${REC_AUCTION_PURCHASE}
recommend-product: ${RECOMMEND_PRODUCT}
product-limit: ${REC_PRODUCT_LIMIT}
recommend-auction: ${RECOMMEND_AUCTION}
recommend-limit: ${REC_LIMIT}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package freshtrash.freshtrashbackend.global.infra;

import freshtrash.freshtrashbackend.Fixture.Fixture;
import freshtrash.freshtrashbackend.domain.auction.entity.Auction;
import freshtrash.freshtrashbackend.domain.product.entity.Product;
import freshtrash.freshtrashbackend.global.config.properties.RecSysProperties;
import freshtrash.freshtrashbackend.global.utils.RestUtils;
Expand Down Expand Up @@ -40,6 +41,17 @@ void given_product_when_requestPutByRest_then_returnVoid() {
// then
}

@DisplayName("경매의 프로필 정보를 수정하는 API를 요청한다.")
@Test
void given_auction_when_requestPutByRest_then_returnVoid() {
// given
Auction auction = Fixture.createAuction();
given(restUtils.put(any(HttpEntity.class), anyString(), eq(Void.class))).willReturn(ResponseEntity.ok(null));
// when
recSysService.createAuction(auction);
// then
}

@DisplayName("상품 구매 시 회원의 구매 횟수와 프로필 정보를 업데이트하는 API를 요청한다.")
@Test
void given_productIdAndMemberId_when_requestPutByRest_then_returnVoid() {
Expand All @@ -50,4 +62,15 @@ void given_productIdAndMemberId_when_requestPutByRest_then_returnVoid() {
recSysService.purchaseProduct(productId, memberId);
// then
}

@DisplayName("낙찰된 경매 상품 구매 시 회원의 구매 횟수와 프로필 정보를 업데이트하는 API를 요청한다.")
@Test
void given_auctionIdAndMemberId_when_requestPutByRest_then_returnVoid() {
// given
Long auctionId = 1L, memberId = 2L;
given(restUtils.put(any(HttpEntity.class), anyString(), eq(Void.class))).willReturn(ResponseEntity.ok(null));
// when
recSysService.purchaseAuction(auctionId, memberId);
// then
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import freshtrash.freshtrashbackend.domain.auction.service.BiddingHistoryService;
import freshtrash.freshtrashbackend.domain.member.dto.security.MemberPrincipal;
import freshtrash.freshtrashbackend.domain.member.entity.constants.UserRole;
import freshtrash.freshtrashbackend.global.infra.RecSysService;
import freshtrash.freshtrashbackend.global.infra.file.LocalFileService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -56,6 +57,9 @@ class AuctionServiceTest {
@Mock
private BiddingHistoryService biddingHistoryService;

@Mock
private RecSysService recSysService;

@DisplayName("경매 추가")
@Test
void given_imageAndAuctionRequestData_when_addAuction_then_returnSavedAuctionData() {
Expand All @@ -67,6 +71,7 @@ void given_imageAndAuctionRequestData_when_addAuction_then_returnSavedAuctionDat
Auction auction = Auction.fromRequest(auctionRequest, fileName, memberPrincipal.id());
given(auctionRepository.save(any(Auction.class))).willReturn(auction);
willDoNothing().given(fileService).uploadFile(eq(image), anyString());
willDoNothing().given(recSysService).createAuction(auction);
// when
AuctionResponse auctionResponse = auctionService.addAuction(image, auctionRequest, memberPrincipal);
// then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import freshtrash.freshtrashbackend.domain.alarm.service.CompletePayAuctionAlarm;
import freshtrash.freshtrashbackend.domain.alarm.service.parameter.BiddingHistoryAlarmParameter;
import freshtrash.freshtrashbackend.domain.auction.entity.BiddingHistory;
import freshtrash.freshtrashbackend.global.infra.RecSysService;
import freshtrash.freshtrashbackend.producer.AuctionProducer;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -27,6 +28,9 @@ class CompletePayAuctionAlarmTest {
@Mock
private AuctionProducer producer;

@Mock
private RecSysService recSysService;

@Test
@DisplayName("낙찰된 경매 상품을 결제 완료하면 해당 입찰 내역의 결제 여부를 true로 변경하고 알림을 전송한다.")
void given_biddingHistory_when_completePay_then_updatePayAndSendAlarm() {
Expand All @@ -35,6 +39,7 @@ void given_biddingHistory_when_completePay_then_updatePayAndSendAlarm() {
int price = 1000;
BiddingHistory biddingHistory = Fixture.createBiddingHistory(auctionId, memberId, price);
BiddingHistoryAlarmParameter biddingHistoryAlarmParameter = new BiddingHistoryAlarmParameter(biddingHistory);
willDoNothing().given(recSysService).purchaseAuction(auctionId, memberId);
willDoNothing().given(producer).publishForCompletedPayAndRequestDelivery(biddingHistory);
// when
assertThatCode(() -> completePayAuctionAlarm.sendAlarm(biddingHistoryAlarmParameter))
Expand Down
Loading