| | |
| | | package com.oying.modules.pc.product.service.impl; |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.bean.copier.CopyOptions; |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.oying.exception.BadRequestException; |
| | | import com.oying.modules.pc.common.core.constrant.AuditStatusEnum; |
| | | import com.oying.modules.pc.product.converter.ProductImageAssembler; |
| | | import com.oying.modules.pc.product.converter.ProductLabelAssembler; |
| | | import com.oying.modules.pc.product.domain.Product; |
| | | import com.oying.modules.pc.product.domain.ProductAudit; |
| | | import com.oying.modules.pc.product.domain.ProductImage; |
| | | import com.oying.modules.pc.product.domain.ProductLabel; |
| | | import com.oying.modules.pc.product.domain.dto.ProductAuditData; |
| | | import com.oying.modules.pc.product.domain.dto.ProductImageCreateRequest; |
| | | import com.oying.modules.pc.product.domain.dto.ProductMerchantCreateRequest; |
| | | import com.oying.modules.pc.product.domain.dto.ProductMerchantUpdateRequest; |
| | | import com.oying.modules.pc.product.domain.enums.ProductChangeTypeEnum; |
| | | import com.oying.modules.pc.product.domain.dto.*; |
| | | import com.oying.modules.pc.product.domain.enums.ProductAuditTypeEnum; |
| | | import com.oying.modules.pc.product.domain.enums.ProductCreationType; |
| | | import com.oying.modules.pc.product.domain.enums.ProductStatusEnum; |
| | | import com.oying.modules.pc.product.events.ProductAuditVerdictEvent; |
| | | import com.oying.modules.pc.product.service.*; |
| | | import com.oying.modules.pc.utils.ImageUtils; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.context.event.EventListener; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Slf4j |
| | | @Service |
| | |
| | | private final ProductImageService productImageService; |
| | | private final ProductLabelService productLabelService; |
| | | private final ProductAuditService productAuditService; |
| | | private final ProductCreationContext productCreationService; |
| | | private final ProductMerchantImagesUpdateProcessor productMerchantImagesUpdateProcessor; |
| | | private final ProductMerchantLabelUpdateProcessor productMerchantLabelUpdateProcessor; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void create(ProductMerchantCreateRequest request) { |
| | | Product product = new Product(); |
| | | BeanUtils.copyProperties(request, product); |
| | | request.getImages().stream().findFirst().map(ProductImageCreateRequest::getUploadFileId) |
| | | .ifPresent(id -> { |
| | | product.setMainImageId(id.toString()); |
| | | product.setMainImageUrl(ImageUtils.getPublicObjectUrl(id)); |
| | | }); |
| | | product.setStatus(ProductStatusEnum.DRAFT.getValue()); |
| | | productService.create(product); |
| | | productCreationService.createProduct(request, ProductCreationType.DIRECT); |
| | | } |
| | | |
| | | List<ProductImage> productImages = request.getImages().stream().map(i -> { |
| | | i.setProductId(product.getProductId()); |
| | | return ProductImageAssembler.to(i); |
| | | }).collect(Collectors.toList()); |
| | | if (CollectionUtil.isNotEmpty(productImages)) { |
| | | productImageService.saveBatch(productImages); |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void createWithAudit(ProductMerchantCreateRequest request) { |
| | | productCreationService.createProduct(request, ProductCreationType.WITH_AUDIT); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void submitToAudit(Long productId, ProductAuditTypeEnum productAuditType) { |
| | | Product existingProduct = productService.getById(productId); |
| | | if (!ProductStatusEnum.DRAFT.getValue().equals(existingProduct.getStatus())) { |
| | | throw new BadRequestException("无法提交,该商品已提交审核或已上架"); |
| | | } |
| | | |
| | | List<ProductLabel> productLabels = request.getLabels().stream().map(i -> { |
| | | i.setProductId(product.getProductId()); |
| | | return ProductLabelAssembler.to(i); |
| | | }).collect(Collectors.toList()); |
| | | if (CollectionUtil.isNotEmpty(productLabels)) { |
| | | productLabelService.saveBatch(productLabels); |
| | | } |
| | | List<ProductImage> productImages = productImageService.queryImagesByProductId(existingProduct.getProductId()); |
| | | existingProduct.setImages(productImages); |
| | | List<ProductLabel> productLabels = productLabelService.queryLabelsByProductId(existingProduct.getProductId()); |
| | | existingProduct.setLabels(productLabels); |
| | | |
| | | ProductAudit audit = new ProductAudit(); |
| | | audit.setProductId(existingProduct.getProductId()); |
| | | audit.setType(productAuditType.name()); |
| | | audit.setStatus(AuditStatusEnum.PENDING.getValue()); |
| | | ProductAuditData auditData = new ProductAuditData(); |
| | | auditData.setProduct(existingProduct); |
| | | audit.setData(JSON.toJSONString(auditData)); |
| | | productAuditService.create(audit); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void update(ProductMerchantUpdateRequest request) { |
| | | |
| | | Product existingProduct = productService.getProduct(request.getProductId()); |
| | | this.validateApprovedStatus(existingProduct.getShelfStatus()); |
| | | this.processImagesUpdate(request); |
| | | this.processLabelsUpdate(request); |
| | | this.validateAuditStatus(existingProduct.getStatus()); |
| | | |
| | | productMerchantImagesUpdateProcessor.processImagesUpdate(request); |
| | | productMerchantLabelUpdateProcessor.processLabelsUpdate(request); |
| | | BeanUtils.copyProperties(request, existingProduct); |
| | | existingProduct.setStatus(ProductStatusEnum.PENDING.getValue()); |
| | | existingProduct.setShelfStatus(ProductStatusEnum.NO_AVAILABLE.getValue()); |
| | | productService.update(existingProduct); |
| | | |
| | | ProductAudit audit = new ProductAudit(); |
| | | audit.setProductId(existingProduct.getProductId()); |
| | | audit.setType(ProductAuditTypeEnum.FULL_UPDATE.name()); |
| | | audit.setStatus(AuditStatusEnum.PENDING.getValue()); |
| | | ProductAuditData auditData = new ProductAuditData(); |
| | | auditData.setOriginalProduct(existingProduct); |
| | | Product newProduct = new Product(); |
| | | BeanUtil.copyProperties(request, newProduct, CopyOptions.create().setIgnoreNullValue(true)); |
| | | auditData.setProduct(existingProduct); |
| | | ProductRevisionRecord revisionRecord = new ProductRevisionRecord(); |
| | | BeanUtil.copyProperties(request, revisionRecord, CopyOptions.create().setIgnoreNullValue(true)); |
| | | auditData.setRevisionRecord(revisionRecord); |
| | | audit.setData(JSON.toJSONString(auditData)); |
| | | productAuditService.create(audit); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updatePrice(ProductPriceUpdateRequest request) { |
| | | Product existingProduct = productService.getProduct(request.getProductId()); |
| | | existingProduct.setPrice(request.getPrice()); |
| | | productService.update(existingProduct, true); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateImages(ProductMerchantUpdateRequest request) { |
| | | Product existingProduct = productService.getProduct(request.getProductId()); |
| | | this.validateApprovedStatus(existingProduct.getShelfStatus()); |
| | | this.processImagesUpdate(request); |
| | | this.validateAuditStatus(existingProduct.getStatus()); |
| | | productMerchantImagesUpdateProcessor.processImagesUpdate(request); |
| | | |
| | | ProductAudit audit = new ProductAudit(); |
| | | audit.setProductId(existingProduct.getProductId()); |
| | | audit.setType(ProductAuditTypeEnum.IMAGE_UPDATE.name()); |
| | | audit.setStatus(AuditStatusEnum.PENDING.getValue()); |
| | | ProductAuditData auditData = new ProductAuditData(); |
| | | auditData.setOriginalProduct(existingProduct); |
| | | Product newProduct = new Product(); |
| | | BeanUtil.copyProperties(request, newProduct, CopyOptions.create().setIgnoreNullValue(true)); |
| | | auditData.setProduct(existingProduct); |
| | | ProductRevisionRecord revisionRecord = new ProductRevisionRecord(); |
| | | BeanUtil.copyProperties(request, revisionRecord, CopyOptions.create().setIgnoreNullValue(true)); |
| | | auditData.setRevisionRecord(revisionRecord); |
| | | audit.setData(JSON.toJSONString(auditData)); |
| | | productAuditService.create(audit); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateLabels(ProductMerchantUpdateRequest request) { |
| | | Product existingProduct = productService.getProduct(request.getProductId()); |
| | | this.validateApprovedStatus(existingProduct.getShelfStatus()); |
| | | this.processImagesUpdate(request); |
| | | this.validateAuditStatus(existingProduct.getStatus()); |
| | | productMerchantLabelUpdateProcessor.processLabelsUpdate(request); |
| | | |
| | | ProductAudit audit = new ProductAudit(); |
| | | audit.setProductId(existingProduct.getProductId()); |
| | | audit.setType(ProductAuditTypeEnum.LABEL_UPDATE.name()); |
| | | audit.setStatus(AuditStatusEnum.PENDING.getValue()); |
| | | ProductAuditData auditData = new ProductAuditData(); |
| | | auditData.setOriginalProduct(existingProduct); |
| | | Product newProduct = new Product(); |
| | | BeanUtil.copyProperties(request, newProduct, CopyOptions.create().setIgnoreNullValue(true)); |
| | | auditData.setProduct(existingProduct); |
| | | ProductRevisionRecord revisionRecord = new ProductRevisionRecord(); |
| | | BeanUtil.copyProperties(request, revisionRecord, CopyOptions.create().setIgnoreNullValue(true)); |
| | | auditData.setRevisionRecord(revisionRecord); |
| | | audit.setData(JSON.toJSONString(auditData)); |
| | | productAuditService.create(audit); |
| | | } |
| | | |
| | | @Transactional |
| | |
| | | @Override |
| | | public void putOnShelf(Long productId) { |
| | | Product existingProduct = productService.getById(productId); |
| | | if (ProductStatusEnum.AVAILABLE.getValue().equals(existingProduct.getShelfStatus())) { |
| | | throw new BadRequestException("商品已上架"); |
| | | if (ProductStatusEnum.AVAILABLE.getValue().equals(existingProduct.getStatus())) { |
| | | return; |
| | | } |
| | | |
| | | if (productAuditService.hasPendingByStoreId(productId)) { |
| | | throw new BadRequestException("已在审核中"); |
| | | if (!(ProductStatusEnum.APPROVED.getValue().equals(existingProduct.getStatus()) |
| | | || ProductStatusEnum.NO_AVAILABLE.getValue().equals(existingProduct.getStatus()))) { |
| | | throw new BadRequestException("无法上架,商品未审核"); |
| | | } |
| | | |
| | | ProductAudit audit = new ProductAudit(); |
| | | audit.setProductId(productId); |
| | | audit.setType(ProductChangeTypeEnum.PUT_ON_SHELF.name()); |
| | | audit.setStatus(AuditStatusEnum.PENDING.getValue()); |
| | | ProductAuditData auditData = new ProductAuditData(); |
| | | auditData.setOriginalStore(existingProduct); |
| | | audit.setData(JSON.toJSONString(auditData)); |
| | | productAuditService.create(audit); |
| | | LambdaUpdateWrapper<Product> wrapper = new LambdaUpdateWrapper<Product>() |
| | | .eq(Product::getProductId, productId) |
| | | .set(Product::getStatus, ProductStatusEnum.PENDING.getValue()); |
| | | .set(Product::getStatus, ProductStatusEnum.AVAILABLE.getValue()) |
| | | .set(Product::getShelfStatus, ProductStatusEnum.AVAILABLE.getValue()); |
| | | productService.update(wrapper); |
| | | } |
| | | |
| | |
| | | if (ProductStatusEnum.NO_AVAILABLE.getValue().equals(existingProduct.getShelfStatus())) { |
| | | return; |
| | | } |
| | | if (!ProductStatusEnum.AVAILABLE.getValue().equals(existingProduct.getShelfStatus())) { |
| | | return; |
| | | } |
| | | LambdaUpdateWrapper<Product> wrapper = new LambdaUpdateWrapper<Product>() |
| | | .eq(Product::getProductId, productId) |
| | | .set(Product::getStatus, ProductStatusEnum.NO_AVAILABLE.getValue()) |
| | |
| | | productService.update(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | @EventListener |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void handleAuditVerdictEvent(ProductAuditVerdictEvent event) { |
| | | try { |
| | | ProductAudit audit = productAuditService.getById(event.getAuditId()); |
| | | ProductChangeTypeEnum changeType = ProductChangeTypeEnum.valueOf(audit.getType()); |
| | | if (changeType == ProductChangeTypeEnum.PUT_ON_SHELF) { |
| | | this.handlePutOnShelfAuditEvent(audit); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("处理商品审核结果异常", e); |
| | | } |
| | | } |
| | | |
| | | private void processImagesUpdate(ProductMerchantUpdateRequest request) { |
| | | if (CollectionUtil.isNotEmpty(request.getDeletedImageIds())) { |
| | | productImageService.deleteAll(request.getDeletedImageIds()); |
| | | } |
| | | if (CollectionUtil.isNotEmpty(request.getUpdatedImages())) { |
| | | productImageService.batchUpdate(request.getUpdatedImages()); |
| | | } |
| | | if (CollectionUtil.isNotEmpty(request.getNewImages())) { |
| | | List<ProductImageCreateRequest> newImages = request.getNewImages().stream().peek(i-> i.setProductId(request.getProductId())).collect(Collectors.toList()); |
| | | productImageService.batchCreate(newImages); |
| | | } |
| | | } |
| | | |
| | | private void processLabelsUpdate(ProductMerchantUpdateRequest request) { |
| | | if (CollectionUtil.isNotEmpty(request.getDeletedLabelIds())) { |
| | | productLabelService.deleteAll(request.getDeletedLabelIds()); |
| | | } |
| | | if (CollectionUtil.isNotEmpty(request.getUpdatedLabels())) { |
| | | productLabelService.batchUpdate(request.getUpdatedLabels()); |
| | | } |
| | | if (CollectionUtil.isNotEmpty(request.getNewLabels())) { |
| | | List<ProductLabel> newLabels = request.getNewLabels().stream().peek(i-> i.setProductId(request.getProductId())).collect(Collectors.toList()); |
| | | productLabelService.batchCreate(newLabels); |
| | | } |
| | | } |
| | | |
| | | private void handlePutOnShelfAuditEvent(ProductAudit audit) { |
| | | AuditStatusEnum auditStatus = AuditStatusEnum.get(audit.getStatus()); |
| | | Product existingProduct = productService.getById(audit.getProductId()); |
| | | if (AuditStatusEnum.APPROVED.equals(auditStatus)) { |
| | | existingProduct.setStatus(ProductStatusEnum.AVAILABLE.getValue()); |
| | | existingProduct.setShelfStatus(ProductStatusEnum.AVAILABLE.getValue()); |
| | | } else { |
| | | existingProduct.setStatus(auditStatus.getValue()); |
| | | } |
| | | productService.updateById(existingProduct); |
| | | } |
| | | |
| | | private void validateApprovedStatus(Integer status) { |
| | | private void validateAuditStatus(Integer status) { |
| | | Set<ProductStatusEnum> statusEnumSet = CollectionUtil.newHashSet(ProductStatusEnum.PENDING, |
| | | ProductStatusEnum.UNDER_REVIEW, ProductStatusEnum.AVAILABLE); |
| | | ProductStatusEnum.UNDER_REVIEW); |
| | | ProductStatusEnum existingStatus = ProductStatusEnum.getOrDefault(status, ProductStatusEnum.DRAFT); |
| | | if (statusEnumSet.contains(existingStatus)) { |
| | | throw new BadRequestException("在售商品无法修改"); |
| | | throw new BadRequestException("商品已在审核流程中无法修改"); |
| | | } |
| | | } |
| | | } |