diff --git a/api/http/test.http b/api/http/test.http index ccd84e6..74e7fc7 100644 --- a/api/http/test.http +++ b/api/http/test.http @@ -25,7 +25,8 @@ GET http://localhost:8080/api/v1/items?page=2 GET http://localhost:8080/api/v1/items/1 ### 어드민 크롤링 기능 -POST http://localhost:8080/api/v1/admin/items/crawl?url=https://s.zigzag.kr/f2KRWpFiXx +POST http://localhost:8080/api/v1/admin/items/crawl? + url=https://zigzag.kr/catalog/products/131506009 ### 카카오 로그인 GET http://localhost:8080/api/v1/auth/login/kakao diff --git a/core/core-domain/src/main/java/com/mm/coredomain/domain/Item.java b/core/core-domain/src/main/java/com/mm/coredomain/domain/Item.java index c76136d..6e761a4 100644 --- a/core/core-domain/src/main/java/com/mm/coredomain/domain/Item.java +++ b/core/core-domain/src/main/java/com/mm/coredomain/domain/Item.java @@ -1,76 +1,86 @@ package com.mm.coredomain.domain; -import jakarta.persistence.*; -import lombok.*; -import org.hibernate.annotations.SQLDelete; - import java.util.ArrayList; import java.util.List; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.OneToMany; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + @Entity @Getter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -@SQLDelete(sql = "UPDATE item SET deleted = true WHERE id = ?") public class Item extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - private String title; + private String title; - @Lob - private String redirectUrl; + @Lob + private String redirectUrl; - @Enumerated(value = EnumType.STRING) - private ItemCategoryType categoryType; + @Enumerated(value = EnumType.STRING) + private ItemCategoryType categoryType; - private Integer price; + private Integer price; - private Integer refund; + private Integer refund; - private Double rating; + private Double rating; - @Lob - private String thumbnailUrl; + @Lob + private String thumbnailUrl; - @Builder.Default - private Boolean isSuggested = false; + @Builder.Default + private Boolean isSuggested = false; - @Builder.Default - @OneToMany(mappedBy = "item", cascade = CascadeType.ALL, orphanRemoval = true) - private List itemImages = new ArrayList(); + @Builder.Default + @OneToMany(mappedBy = "item", cascade = CascadeType.ALL, orphanRemoval = true) + private List itemImages = new ArrayList(); - @Builder.Default - @OneToMany(mappedBy = "item", cascade = CascadeType.ALL, orphanRemoval = true) - private List itemVideos = new ArrayList(); + @Builder.Default + @OneToMany(mappedBy = "item", cascade = CascadeType.ALL, orphanRemoval = true) + private List itemVideos = new ArrayList(); - public void setItemImages(List itemImages) { - this.itemImages.clear(); - itemImages.forEach(itemImage -> this.itemImages.add(itemImage)); - } + public void setItemImages(List itemImages) { + this.itemImages.clear(); + itemImages.forEach(itemImage -> this.itemImages.add(itemImage)); + } - public void setItemVideos(List itemVideos) { - this.itemVideos.clear(); - itemVideos.forEach(itemVideo -> this.itemVideos.add(itemVideo)); - } + public void setItemVideos(List itemVideos) { + this.itemVideos.clear(); + itemVideos.forEach(itemVideo -> this.itemVideos.add(itemVideo)); + } - public void setItemSuggested() { - this.isSuggested = true; - } + public void setItemSuggested() { + this.isSuggested = true; + } - public void setItemNotSuggested() { - this.isSuggested = false; - } + public void setItemNotSuggested() { + this.isSuggested = false; + } - public void updateItem(ItemUpdate itemUpdate) { - this.title = itemUpdate.title(); - this.redirectUrl = itemUpdate.redirectUrl(); - this.categoryType = itemUpdate.categoryType(); - this.price = itemUpdate.price(); - this.refund = itemUpdate.refund(); - this.rating = itemUpdate.rating(); - this.thumbnailUrl = itemUpdate.thumbnailUrl(); - } + public void updateItem(ItemUpdate itemUpdate) { + this.title = itemUpdate.title(); + this.redirectUrl = itemUpdate.redirectUrl(); + this.categoryType = itemUpdate.categoryType(); + this.price = itemUpdate.price(); + this.refund = itemUpdate.refund(); + this.rating = itemUpdate.rating(); + this.thumbnailUrl = itemUpdate.thumbnailUrl(); + } } diff --git a/core/core-domain/src/main/java/com/mm/coredomain/domain/ItemCategoryType.java b/core/core-domain/src/main/java/com/mm/coredomain/domain/ItemCategoryType.java index d50cebd..e0b4951 100644 --- a/core/core-domain/src/main/java/com/mm/coredomain/domain/ItemCategoryType.java +++ b/core/core-domain/src/main/java/com/mm/coredomain/domain/ItemCategoryType.java @@ -15,14 +15,66 @@ public enum ItemCategoryType { private final String value; private final Integer refundPercent; private static final List TopsList = List.of( - "상의", - "아우터", - "원피스", - "니트/카디건", - "투피스/세트"); + "티셔츠", + "니트/스웨터", + "셔츠", + "블라우스", + "맨투맨/스웨트셔츠", + "후드", + "민소매/슬리브리스", + "카디건", + "재킷", + "레더재킷", + "트위드재킷", + "코트", + "숏패딩", + "롱패딩", + "경량 패딩", + "트렌치코트", + "사파리/헌팅재킷", + "점퍼", + "무스탕", + "베스트", + "레인코트", + "미니원피스", + "미디원피스", + "롱원피스", + "라운드 니트", + "브이넥 니트", + "터틀넥 니트", + "오프숄더 니트", + "스퀘어넥 니트", + "니트 베스트", + "니트원피스", + "카디건", + "트레이닝 상의", + "트레이닝 세트", + "시밀러룩", + "스커트 세트", + "팬츠 세트", + "원피스 세트", + "임부복 상의", + "임부복 아우터", + "임부복 원피스" + ); private static final List BottomsList = List.of( - "바지", - "스커트"); + "일자팬츠", + "슬랙스팬츠", + "숏팬츠", + "와이드팬츠", + "스키니팬츠", + "부츠컷팬츠", + "조거팬츠", + "점프수트", + "레깅스", + "기타팬츠", + "미니스커트", + "미디스커트", + "롱스커트", + "트레이닝 하의", + "임부복 스커트", + "임부복 바지" + ); ItemCategoryType(String value, Integer refundPercent) { this.value = value; diff --git a/core/core-infra-feign/src/main/java/com/mm/coreinfrafeign/crawler/service/CrawlerService.java b/core/core-infra-feign/src/main/java/com/mm/coreinfrafeign/crawler/service/CrawlerService.java index 8478074..b0da8ea 100644 --- a/core/core-infra-feign/src/main/java/com/mm/coreinfrafeign/crawler/service/CrawlerService.java +++ b/core/core-infra-feign/src/main/java/com/mm/coreinfrafeign/crawler/service/CrawlerService.java @@ -1,60 +1,62 @@ package com.mm.coreinfrafeign.crawler.service; +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.mm.coredomain.domain.Item; import com.mm.coredomain.domain.ItemCategoryType; import com.mm.coredomain.domain.ItemImage; import com.mm.coreinfrafeign.crawler.client.ZigZagCrawlerClient; import com.mm.coreinfrafeign.crawler.dto.requset.ZigZagCrawlerRequest; import com.mm.coreinfrafeign.crawler.dto.response.ZigZagCrawlerResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import java.util.List; +import lombok.RequiredArgsConstructor; @Service @Transactional @RequiredArgsConstructor public class CrawlerService { - private final ZigZagCrawlerClient zigZagCrawlerClient; - - public Item getZigZagItemByCrawler(String redirectUrl) { - ZigZagCrawlerResponse response = zigZagCrawlerClient.call(new ZigZagCrawlerRequest(redirectUrl)); - - ItemCategoryType categoryType = getCategoryType(response); - - Item item = Item.builder() - .price(response.finalPrice()) - .title(response.name()) - .redirectUrl(response.pageUrl()) - .categoryType(categoryType) - .refund(getRefundPrice(response.finalPrice(), categoryType.getRefundPercent())) - .thumbnailUrl(response.thumbnailUrl()) - .build(); - - List itemImages = response.productImageList() - .stream() - .map(image -> ItemImage.builder() - .item(item) - .url(image.url()) - .build()) - .toList(); - - item.setItemImages(itemImages); - return item; - } - - private static ItemCategoryType getCategoryType(ZigZagCrawlerResponse response) { - String itemCategory = response.managedCategoryList().get(0).value(); - if (itemCategory.equals("패션의류")) { - itemCategory = response.managedCategoryList().get(1).value(); - return ItemCategoryType.fromValueForClothes(itemCategory); - } - - return ItemCategoryType.fromValue(itemCategory); - } - - private Integer getRefundPrice(Integer price, Integer percent) { - return price * percent / 100; - } + private final ZigZagCrawlerClient zigZagCrawlerClient; + + public Item getZigZagItemByCrawler(String redirectUrl) { + ZigZagCrawlerResponse response = zigZagCrawlerClient.call(new ZigZagCrawlerRequest(redirectUrl)); + + ItemCategoryType categoryType = getCategoryType(response); + + Item item = Item.builder() + .price(response.finalPrice()) + .title(response.name()) + .redirectUrl(response.pageUrl()) + .categoryType(categoryType) + .refund(getRefundPrice(response.finalPrice(), categoryType.getRefundPercent())) + .thumbnailUrl(response.thumbnailUrl()) + .build(); + + List itemImages = response.productImageList() + .stream() + .map(image -> ItemImage.builder() + .item(item) + .url(image.url()) + .build()) + .toList(); + + item.setItemImages(itemImages); + return item; + } + + private static ItemCategoryType getCategoryType(ZigZagCrawlerResponse response) { + String itemCategory = response.managedCategoryList().get(0).value(); + if (itemCategory.equals("패션의류")) { + itemCategory = response.managedCategoryList().get(2).value(); + return ItemCategoryType.fromValueForClothes(itemCategory); + } + + return ItemCategoryType.fromValue(itemCategory); + } + + private Integer getRefundPrice(Integer price, Integer percent) { + return price * percent / 100; + } }