diff --git a/docker-compose-local.yml b/docker-compose-local.yml index 18f41cf..7e49250 100644 --- a/docker-compose-local.yml +++ b/docker-compose-local.yml @@ -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" diff --git a/src/main/java/freshtrash/freshtrashbackend/domain/alarm/service/CompletePayAuctionAlarm.java b/src/main/java/freshtrash/freshtrashbackend/domain/alarm/service/CompletePayAuctionAlarm.java index 9f140c3..0372e77 100644 --- a/src/main/java/freshtrash/freshtrashbackend/domain/alarm/service/CompletePayAuctionAlarm.java +++ b/src/main/java/freshtrash/freshtrashbackend/domain/alarm/service/CompletePayAuctionAlarm.java @@ -3,6 +3,7 @@ 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; @@ -10,14 +11,17 @@ @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); } diff --git a/src/main/java/freshtrash/freshtrashbackend/domain/auction/service/AuctionService.java b/src/main/java/freshtrash/freshtrashbackend/domain/auction/service/AuctionService.java index 270675f..8656a5a 100644 --- a/src/main/java/freshtrash/freshtrashbackend/domain/auction/service/AuctionService.java +++ b/src/main/java/freshtrash/freshtrashbackend/domain/auction/service/AuctionService.java @@ -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; @@ -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) { @@ -46,6 +48,9 @@ public AuctionResponse addAuction( Auction savedAuction = auctionRepository.save(auction); // 이미지 파일 저장 fileService.uploadFile(imgFile, savedFileName); + // 경매 프로필 업데이트 + recSysService.createAuction(savedAuction); + return AuctionResponse.fromEntity(savedAuction, memberPrincipal); } diff --git a/src/main/java/freshtrash/freshtrashbackend/global/config/properties/RecSysProperties.java b/src/main/java/freshtrash/freshtrashbackend/global/config/properties/RecSysProperties.java index afd07fa..c6d5fd4 100644 --- a/src/main/java/freshtrash/freshtrashbackend/global/config/properties/RecSysProperties.java +++ b/src/main/java/freshtrash/freshtrashbackend/global/config/properties/RecSysProperties.java @@ -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) {} diff --git a/src/main/java/freshtrash/freshtrashbackend/global/infra/RecSysService.java b/src/main/java/freshtrash/freshtrashbackend/global/infra/RecSysService.java index 2fc3dbb..ac4598d 100644 --- a/src/main/java/freshtrash/freshtrashbackend/global/infra/RecSysService.java +++ b/src/main/java/freshtrash/freshtrashbackend/global/infra/RecSysService.java @@ -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; @@ -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 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); } /** @@ -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); } diff --git a/src/main/resources/application-common.yml b/src/main/resources/application-common.yml index ac95015..9d019f3 100644 --- a/src/main/resources/application-common.yml +++ b/src/main/resources/application-common.yml @@ -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} diff --git a/src/test/java/freshtrash/freshtrashbackend/global/infra/RecSysServiceTest.java b/src/test/java/freshtrash/freshtrashbackend/global/infra/RecSysServiceTest.java index 1ffc4f5..907c9d6 100644 --- a/src/test/java/freshtrash/freshtrashbackend/global/infra/RecSysServiceTest.java +++ b/src/test/java/freshtrash/freshtrashbackend/global/infra/RecSysServiceTest.java @@ -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; @@ -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() { @@ -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 + } } \ No newline at end of file diff --git a/src/test/java/freshtrash/freshtrashbackend/service/AuctionServiceTest.java b/src/test/java/freshtrash/freshtrashbackend/service/AuctionServiceTest.java index fb26818..012c356 100644 --- a/src/test/java/freshtrash/freshtrashbackend/service/AuctionServiceTest.java +++ b/src/test/java/freshtrash/freshtrashbackend/service/AuctionServiceTest.java @@ -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; @@ -56,6 +57,9 @@ class AuctionServiceTest { @Mock private BiddingHistoryService biddingHistoryService; + @Mock + private RecSysService recSysService; + @DisplayName("경매 추가") @Test void given_imageAndAuctionRequestData_when_addAuction_then_returnSavedAuctionData() { @@ -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 diff --git a/src/test/java/freshtrash/freshtrashbackend/service/alarm/CompletePayAuctionAlarmTest.java b/src/test/java/freshtrash/freshtrashbackend/service/alarm/CompletePayAuctionAlarmTest.java index 406d9a8..6792562 100644 --- a/src/test/java/freshtrash/freshtrashbackend/service/alarm/CompletePayAuctionAlarmTest.java +++ b/src/test/java/freshtrash/freshtrashbackend/service/alarm/CompletePayAuctionAlarmTest.java @@ -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; @@ -27,6 +28,9 @@ class CompletePayAuctionAlarmTest { @Mock private AuctionProducer producer; + @Mock + private RecSysService recSysService; + @Test @DisplayName("낙찰된 경매 상품을 결제 완료하면 해당 입찰 내역의 결제 여부를 true로 변경하고 알림을 전송한다.") void given_biddingHistory_when_completePay_then_updatePayAndSendAlarm() { @@ -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))