|
|
@@ -0,0 +1,353 @@
|
|
|
+package com.poyee.facade.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.lang.Assert;
|
|
|
+import cn.hutool.core.util.BooleanUtil;
|
|
|
+import cn.hutool.core.util.IdUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.github.pagehelper.PageHelper;
|
|
|
+import com.github.pagehelper.PageInfo;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.google.common.collect.Maps;
|
|
|
+import com.poyee.constant.ProductConstant;
|
|
|
+import com.poyee.domain.*;
|
|
|
+import com.poyee.enums.ProductTypeEnum;
|
|
|
+import com.poyee.enums.ReviewStatusEnum;
|
|
|
+import com.poyee.enums.SaleTypeEnum;
|
|
|
+import com.poyee.enums.StatusEnum;
|
|
|
+import com.poyee.exception.BusinessException;
|
|
|
+import com.poyee.facade.IProductInfoFacade;
|
|
|
+import com.poyee.mapstruct.ProductInfoMapstruct;
|
|
|
+import com.poyee.param.ProductListBO;
|
|
|
+import com.poyee.req.*;
|
|
|
+import com.poyee.res.IdleAttributeRes;
|
|
|
+import com.poyee.res.ProductDetailRes;
|
|
|
+import com.poyee.res.ProductFastSaleRes;
|
|
|
+import com.poyee.res.ProductListRes;
|
|
|
+import com.poyee.service.*;
|
|
|
+import com.poyee.utils.I18nUtil;
|
|
|
+import com.poyee.utils.ServletUtils;
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.function.Function;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+import static com.poyee.enums.ProductTypeEnum.getByCode;
|
|
|
+
|
|
|
+@Component
|
|
|
+@AllArgsConstructor
|
|
|
+public class ProductInfoFacade implements IProductInfoFacade {
|
|
|
+
|
|
|
+ private final ProductInfoService productInfoService;
|
|
|
+ private final ProductInfoMapstruct productInfoMapstruct;
|
|
|
+ private final ProductFastSaleService productFastSaleService;
|
|
|
+ private final CardAttributeService cardAttributeService;
|
|
|
+ private final ProductMediaService productMediaService;
|
|
|
+ public final ProductPermissionService productPermissionService;
|
|
|
+ private final SysDictDataService sysDictDataService;
|
|
|
+ private final static String SKU_PREFIX = "BC";
|
|
|
+
|
|
|
+ @Override
|
|
|
+
|
|
|
+ public PageInfo<ProductListRes> list(ProductSearchReq productSearchReq) {
|
|
|
+ PageHelper.startPage(productSearchReq.getPage(), productSearchReq.getPageSize());
|
|
|
+ LambdaQueryWrapper<ProductInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ if (StrUtil.isNotBlank(productSearchReq.getProductName())) {
|
|
|
+ lambdaQueryWrapper.likeRight(ProductInfo::getProductName, productSearchReq.getProductName());
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(productSearchReq.getStatus())) {
|
|
|
+ lambdaQueryWrapper.eq(ProductInfo::getStatus, productSearchReq.getStatus());
|
|
|
+ }
|
|
|
+ List<ProductInfo> productInfos = this.productInfoService.list(lambdaQueryWrapper);
|
|
|
+ if (CollUtil.isEmpty(productInfos)) {
|
|
|
+ return PageInfo.emptyPageInfo();
|
|
|
+ }
|
|
|
+ List<String> fastSaleSkus = productInfos.stream()
|
|
|
+ .filter(product -> Objects.nonNull(product.getFastSaleFlag()) && product.getFastSaleFlag() == StatusEnum.TRUE.getCode())
|
|
|
+ .map(ProductInfo::getSku)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ Map<String, ProductFastSale> fastSaleMap = CollUtil.isEmpty(fastSaleSkus)
|
|
|
+ ? Maps.newHashMap()
|
|
|
+ : productFastSaleService.lambdaQuery()
|
|
|
+ .in(ProductFastSale::getSku, fastSaleSkus)
|
|
|
+ .list()
|
|
|
+ .stream()
|
|
|
+ .collect(Collectors.toMap(ProductFastSale::getSku, Function.identity()));
|
|
|
+ List<ProductListRes> productListResList = productInfos.stream()
|
|
|
+ .map(productInfo -> {
|
|
|
+ ProductListBO productBO = productInfoMapstruct.productDo2Bo(productInfo);
|
|
|
+ ProductListRes productListRes = productInfoMapstruct.productBO2Res(productBO);
|
|
|
+ if (Objects.nonNull(productInfo.getFastSaleFlag()) && productInfo.getFastSaleFlag() == StatusEnum.TRUE.getCode() && Objects.nonNull(fastSaleMap.get(productInfo.getSku()))) {
|
|
|
+ productListRes.setSaleTime(fastSaleMap.get(productInfo.getSku()).getSaleTime());
|
|
|
+ productListRes.setRecycleInventory(fastSaleMap.get(productInfo.getSku()).getRecycleInventory());
|
|
|
+ }
|
|
|
+ return productListRes;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ return PageInfo.of(productListResList);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ProductDetailRes detail(String sku) {
|
|
|
+ ProductInfo productInfo = productInfo(sku);
|
|
|
+ ProductTypeEnum productTypeEnum = getByCode(productInfo.getProductType());
|
|
|
+ ProductMedia productMedia = productMediaService.lambdaQuery().eq(ProductMedia::getRelationSku, productInfo.getSku()).one();
|
|
|
+ Assert.notNull(productMedia, "the_product_image_does_not_exist");
|
|
|
+ List<String> otherImages = StrUtil.isNotBlank(productMedia.getOtherImages()) ?
|
|
|
+ Arrays.asList(productMedia.getOtherImages().split(",")) : Lists.newArrayList();
|
|
|
+ if (Objects.equals(productTypeEnum, ProductTypeEnum.TRADING_CARD)) {
|
|
|
+ CardAttribute cardAttribute = cardAttributeService.lambdaQuery().eq(CardAttribute::getRelationSku, productInfo.getSku()).one();
|
|
|
+ Assert.notNull(cardAttribute, "The_product_attribute_does_not_exist");
|
|
|
+ return ProductDetailRes.builder()
|
|
|
+ .productType(productInfo.getProductType())
|
|
|
+ .year(cardAttribute.getYear())
|
|
|
+ .sport(cardAttribute.getSport())
|
|
|
+ .manufacturer(cardAttribute.getManufacturer())
|
|
|
+ .sets(cardAttribute.getSets())
|
|
|
+ .setsVersion(cardAttribute.getSetsVersion())
|
|
|
+ .productName(productInfo.getProductName())
|
|
|
+ .defaultImage(productMedia.getMainImage())
|
|
|
+ .productDesc(productInfo.getProductDesc())
|
|
|
+ .otherImages(otherImages).build();
|
|
|
+ } else {
|
|
|
+ return ProductDetailRes.builder()
|
|
|
+ .productType(productInfo.getProductType())
|
|
|
+ .productName(productInfo.getProductName())
|
|
|
+ .defaultImage(productMedia.getMainImage())
|
|
|
+ .labelKey(productInfo.getLabel())
|
|
|
+ .productDesc(productInfo.getProductDesc())
|
|
|
+ .otherImages(otherImages).build();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Boolean review(ProductReviewReq productReviewReq) {
|
|
|
+ ProductInfo productInfo = productInfo(productReviewReq.getSku());
|
|
|
+ Assert.notNull(productInfo, I18nUtil.getMessage("the_product_does_not_exist"));
|
|
|
+ validateReviewStatus(productInfo, productReviewReq.getStatus());
|
|
|
+ sysDictDataService.validateOptions(ProductConstant.DICT_KEY_PRODUCT_STATUS, StrUtil.toString(productReviewReq.getStatus()));
|
|
|
+ productInfo.setStatus(productReviewReq.getStatus());
|
|
|
+ return productInfoService.updateById(productInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IdleAttributeRes idleAttribute(String sku) {
|
|
|
+ ProductInfo productInfo = productInfo(sku);
|
|
|
+ return IdleAttributeRes.builder()
|
|
|
+ .idleFlag(productInfo.getIdleFlag())
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ @Override
|
|
|
+ public Boolean idleAttribute(IdleAttributeReq idleAttributeReq) {
|
|
|
+ ProductInfo productInfo = productInfo(idleAttributeReq.getSku());
|
|
|
+
|
|
|
+ sysDictDataService.validateOptions(ProductConstant.DICT_KEY_WHETHER, idleAttributeReq.getIdleFlag() ? "1" : "0");
|
|
|
+ sysDictDataService.validateOptions(ProductConstant.DICT_KEY_PERMISSION, StrUtil.toString(idleAttributeReq.getPermission()));
|
|
|
+
|
|
|
+ productInfo.setIdleFlag(BooleanUtil.isTrue(idleAttributeReq.getIdleFlag()) ? StatusEnum.TRUE.getCode() : StatusEnum.FALSE.getCode());
|
|
|
+ ProductPermission productPermission = productPermissionService.lambdaQuery().eq(ProductPermission::getRelationSku, productInfo.getSku()).one();
|
|
|
+ LocalDateTime utcNow = LocalDateTime.now(java.time.ZoneOffset.UTC);
|
|
|
+ if (Objects.isNull(productPermission)) {
|
|
|
+ productPermission = ProductPermission.builder()
|
|
|
+ .permission(idleAttributeReq.getPermission())
|
|
|
+ .createTme(utcNow)
|
|
|
+ .relationSku(productInfo.getSku()).build();
|
|
|
+ productPermissionService.save(productPermission);
|
|
|
+ } else {
|
|
|
+ productPermission.setPermission(idleAttributeReq.getPermission());
|
|
|
+ productPermission.setUpdateTime(utcNow);
|
|
|
+ productPermissionService.updateById(productPermission);
|
|
|
+ }
|
|
|
+ return this.productInfoService.updateById(productInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ProductFastSaleRes fastSale(String sku) {
|
|
|
+ ProductInfo productInfo = productInfo(sku);
|
|
|
+ ProductFastSale productFastSale = productFastSaleService.lambdaQuery().eq(ProductFastSale::getSku, sku).one();
|
|
|
+ if (Objects.nonNull(productFastSale)) {
|
|
|
+ return ProductFastSaleRes.builder()
|
|
|
+ .recycleFlag(productInfo.getFastSaleFlag() == StatusEnum.TRUE.getCode() ? Boolean.TRUE : Boolean.FALSE)
|
|
|
+ .recycleInventory(productFastSale.getRecycleInventory())
|
|
|
+ .saleTime(productFastSale.getSaleTime())
|
|
|
+ .permission(productPermissionService.lambdaQuery().eq(ProductPermission::getRelationSku, sku).one().getPermission())
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+ return ProductFastSaleRes.builder().build();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ @Override
|
|
|
+ public Boolean fastSale(FastSaleReq fastSaleReq) {
|
|
|
+ ProductInfo productInfo = productInfo(fastSaleReq.getSku());
|
|
|
+ ProductFastSale existingFastSale = productFastSaleService.lambdaQuery()
|
|
|
+ .eq(ProductFastSale::getSku, fastSaleReq.getSku())
|
|
|
+ .one();
|
|
|
+
|
|
|
+ sysDictDataService.validateOptions(ProductConstant.DICT_KEY_WHETHER, fastSaleReq.getRecycleFlag() ? "1" : "0");
|
|
|
+ sysDictDataService.validateOptions(ProductConstant.DICT_KEY_PERMISSION, StrUtil.toString(fastSaleReq.getPermission()));
|
|
|
+
|
|
|
+ if (Objects.isNull(existingFastSale)) {
|
|
|
+ ProductFastSale newFastSale = ProductFastSale.builder()
|
|
|
+ .saleType(Objects.nonNull(fastSaleReq.getSaleTime()) ? SaleTypeEnum.PRESALE.getCode() : SaleTypeEnum.SPOT_TRADING.getCode())
|
|
|
+ .sku(fastSaleReq.getSku())
|
|
|
+ .recycleFlag(BooleanUtil.isTrue(fastSaleReq.getRecycleFlag()) ? StatusEnum.TRUE.getCode() : StatusEnum.FALSE.getCode())
|
|
|
+ .recycleInventory(fastSaleReq.getRecycleInventory())
|
|
|
+ .saleTime(fastSaleReq.getSaleTime())
|
|
|
+ .createBy(Objects.nonNull(ServletUtils.getCurrentUser()) ? ServletUtils.getCurrentUser().getId() : null)
|
|
|
+ .createTime(LocalDateTime.now())
|
|
|
+ .build();
|
|
|
+ this.productFastSaleService.save(newFastSale);
|
|
|
+ productInfo.setFastSaleFlag(StatusEnum.TRUE.getCode());
|
|
|
+ return this.productInfoService.updateById(productInfo);
|
|
|
+ } else {
|
|
|
+ existingFastSale.setSaleType(Objects.nonNull(fastSaleReq.getSaleTime()) ? SaleTypeEnum.PRESALE.getCode() : SaleTypeEnum.SPOT_TRADING.getCode());
|
|
|
+ existingFastSale.setRecycleFlag(BooleanUtil.isTrue(fastSaleReq.getRecycleFlag()) ? StatusEnum.TRUE.getCode() : StatusEnum.FALSE.getCode());
|
|
|
+ existingFastSale.setRecycleInventory(fastSaleReq.getRecycleInventory());
|
|
|
+ existingFastSale.setSaleTime(fastSaleReq.getSaleTime());
|
|
|
+ existingFastSale.setUpdateBy(Objects.nonNull(ServletUtils.getCurrentUser()) ? ServletUtils.getCurrentUser().getId() : null);
|
|
|
+ existingFastSale.setUpdateTime(LocalDateTime.now());
|
|
|
+ return this.productFastSaleService.updateById(existingFastSale);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ @Override
|
|
|
+ public Boolean add(ProductInfoAddReq productInfoAddReq) {
|
|
|
+ ProductTypeEnum productTypeEnum = getByCode(productInfoAddReq.getProductType());
|
|
|
+ sysDictDataService.validateOptions(ProductConstant.DICT_KEY_PRODUCT_TYPE, StrUtil.toString(productInfoAddReq.getProductType()));
|
|
|
+ sysDictDataService.validateOptions(ProductConstant.DICT_KEY_LABEL, StrUtil.toString(productInfoAddReq.getLabelKey()));
|
|
|
+
|
|
|
+ String sku = SKU_PREFIX + IdUtil.getSnowflakeNextId() % 1000000000000000000L;
|
|
|
+ ProductInfo productInfo;
|
|
|
+ switch (productTypeEnum) {
|
|
|
+ case TRADING_CARD:
|
|
|
+ CardAttribute cardAttribute = CardAttribute.builder()
|
|
|
+ .year(productInfoAddReq.getYear())
|
|
|
+ .sport(productInfoAddReq.getSport())
|
|
|
+ .manufacturer(productInfoAddReq.getManufacturer())
|
|
|
+ .sets(productInfoAddReq.getSets())
|
|
|
+ .setsVersion(productInfoAddReq.getSetsVersion())
|
|
|
+ .createTime(LocalDateTime.now(java.time.ZoneOffset.UTC))
|
|
|
+ .relationSku(sku)
|
|
|
+ .build();
|
|
|
+ ProductMedia productMedia = ProductMedia.builder()
|
|
|
+ .mainImage(productInfoAddReq.getDefaultImage())
|
|
|
+ .relationSku(sku)
|
|
|
+ .createTime(LocalDateTime.now(java.time.ZoneOffset.UTC))
|
|
|
+ .otherImages(StrUtil.join(",", productInfoAddReq.getOtherImages()))
|
|
|
+ .build();
|
|
|
+ productInfo = ProductInfo.builder()
|
|
|
+ .productName(productInfoAddReq.getProductName())
|
|
|
+ .sku(sku)
|
|
|
+ .inventory(0)
|
|
|
+ .productType(productInfoAddReq.getProductType())
|
|
|
+ .productDesc(productInfoAddReq.getProductDesc())
|
|
|
+ .relationCode(productInfoAddReq.getRelationCode())
|
|
|
+ .productProperties(productInfoAddReq.getProductProperties())
|
|
|
+ .sort(productInfoAddReq.getSort())
|
|
|
+ .createTime(LocalDateTime.now(java.time.ZoneOffset.UTC))
|
|
|
+ .build();
|
|
|
+ this.productInfoService.save(productInfo);
|
|
|
+ this.cardAttributeService.save(cardAttribute);
|
|
|
+ this.productMediaService.save(productMedia);
|
|
|
+ break;
|
|
|
+ case OTHER:
|
|
|
+ productInfo = ProductInfo.builder()
|
|
|
+ .productName(productInfoAddReq.getProductName())
|
|
|
+ .sku(sku)
|
|
|
+ .inventory(0)
|
|
|
+ .productType(productInfoAddReq.getProductType())
|
|
|
+ .label(productInfoAddReq.getLabelKey())
|
|
|
+ .sort(productInfoAddReq.getSort())
|
|
|
+ .productProperties(productInfoAddReq.getProductProperties())
|
|
|
+ .productDesc(productInfoAddReq.getProductDesc())
|
|
|
+ .relationCode(productInfoAddReq.getRelationCode())
|
|
|
+ .createTime(LocalDateTime.now(java.time.ZoneOffset.UTC))
|
|
|
+ .build();
|
|
|
+ this.productInfoService.save(productInfo);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new BusinessException("product_type_error");
|
|
|
+ }
|
|
|
+ return Boolean.TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ @Override
|
|
|
+ public Boolean edit(ProductInfoEditReq productInfoEditReq) {
|
|
|
+ ProductInfo productInfo = productInfo(productInfoEditReq.getSku());
|
|
|
+ sysDictDataService.validateOptions(ProductConstant.DICT_KEY_LABEL, StrUtil.toString(productInfoEditReq.getLabelKey()));
|
|
|
+ if (StrUtil.isNotBlank(productInfoEditReq.getProductName())) {
|
|
|
+ productInfo.setProductName(productInfoEditReq.getProductName());
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(productInfoEditReq.getProductDesc())) {
|
|
|
+ productInfo.setProductDesc(productInfoEditReq.getProductDesc());
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(productInfoEditReq.getLabelKey())) {
|
|
|
+ productInfo.setLabel(productInfoEditReq.getLabelKey());
|
|
|
+ }
|
|
|
+ this.productInfoService.updateById(productInfo);
|
|
|
+ if (StrUtil.isNotBlank(productInfoEditReq.getDefaultImage()) ||
|
|
|
+ CollUtil.isNotEmpty(productInfoEditReq.getOtherImages())) {
|
|
|
+ ProductMedia productMedia = this.productMediaService.lambdaQuery()
|
|
|
+ .eq(ProductMedia::getRelationSku, productInfoEditReq.getSku())
|
|
|
+ .one();
|
|
|
+ if (Objects.isNull(productMedia)) {
|
|
|
+ productMedia = ProductMedia.builder()
|
|
|
+ .relationSku(productInfoEditReq.getSku())
|
|
|
+ .mainImage(productInfoEditReq.getDefaultImage())
|
|
|
+ .otherImages(CollUtil.join(productInfoEditReq.getOtherImages(), ","))
|
|
|
+ .build();
|
|
|
+ this.productMediaService.save(productMedia);
|
|
|
+ } else {
|
|
|
+ if (StrUtil.isNotBlank(productInfoEditReq.getDefaultImage())) {
|
|
|
+ productMedia.setMainImage(productInfoEditReq.getDefaultImage());
|
|
|
+ }
|
|
|
+ if (CollUtil.isNotEmpty(productInfoEditReq.getOtherImages())) {
|
|
|
+ productMedia.setOtherImages(CollUtil.join(productInfoEditReq.getOtherImages(), ","));
|
|
|
+ }
|
|
|
+ this.productMediaService.updateById(productMedia);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Boolean.TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateReviewStatus(ProductInfo productInfo, Integer targetStatus) {
|
|
|
+ Integer currentStatus = productInfo.getStatus();
|
|
|
+ if (Objects.isNull(targetStatus)) {
|
|
|
+ throw new BusinessException("review_status_cannot_be_null");
|
|
|
+ }
|
|
|
+ if (targetStatus.equals(ReviewStatusEnum.LISTED.getCode())) {
|
|
|
+ if (!currentStatus.equals(ReviewStatusEnum.DOWN.getCode()) &&
|
|
|
+ !currentStatus.equals(ReviewStatusEnum.REJECTED.getCode())) {
|
|
|
+ throw new BusinessException("can_only_list_down_or_rejected_product");
|
|
|
+ }
|
|
|
+ } else if (targetStatus.equals(ReviewStatusEnum.DOWN.getCode())) {
|
|
|
+ if (!currentStatus.equals(ReviewStatusEnum.LISTED.getCode())) {
|
|
|
+ throw new BusinessException("can_only_down_listed_product");
|
|
|
+ }
|
|
|
+ } else if (targetStatus.equals(ReviewStatusEnum.REJECTED.getCode())) {
|
|
|
+ throw new BusinessException("the_product_already_rejected");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*----------------------------------------------------------------------------------------------utils-------------------------------------------------------------------------------*/
|
|
|
+
|
|
|
+ public ProductInfo productInfo(String sku) {
|
|
|
+ ProductInfo productInfo = productInfoService.lambdaQuery()
|
|
|
+ .eq(ProductInfo::getSku, sku).one();
|
|
|
+ Assert.notNull(productInfo, I18nUtil.getMessage("the_product_does_not_exist"));
|
|
|
+ return productInfo;
|
|
|
+ }
|
|
|
+}
|