package com.oying.modules.pc.product.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjUtil; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.oying.exception.BadRequestException; import com.oying.exception.EntityNotFoundException; 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.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.Optional; import java.util.Set; import java.util.stream.Collectors; @Slf4j @Service @RequiredArgsConstructor public class ProductMerchantServiceImpl implements ProductMerchantService { private final ProductService productService; private final ProductImageService productImageService; private final ProductLabelService productLabelService; private final ProductAuditService productAuditService; @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); List productImages = request.getImages().stream().map(i -> { i.setProductId(product.getProductId()); return ProductImageAssembler.to(i); }).collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(productImages)) { productImageService.saveBatch(productImages); } List productLabels = request.getLabels().stream().map(i -> { i.setProductId(product.getProductId()); return ProductLabelAssembler.to(i); }).collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(productLabels)) { productLabelService.saveBatch(productLabels); } } @Override @Transactional(rollbackFor = Exception.class) public void update(ProductMerchantUpdateRequest request) { Product existingProduct = this.findOrThrow(request.getProductId()); this.validateApprovedStatus(existingProduct.getShelfStatus()); this.processImagesUpdate(request); this.processLabelsUpdate(request); BeanUtils.copyProperties(request, existingProduct); productService.update(existingProduct); } @Override @Transactional(rollbackFor = Exception.class) public void updateImages(ProductMerchantUpdateRequest request) { Product existingProduct = this.findOrThrow(request.getProductId()); this.validateApprovedStatus(existingProduct.getShelfStatus()); this.findOrThrow(request.getProductId()); this.processImagesUpdate(request); } @Override @Transactional(rollbackFor = Exception.class) public void updateLabels(ProductMerchantUpdateRequest request) { Product existingProduct = this.findOrThrow(request.getProductId()); this.validateApprovedStatus(existingProduct.getShelfStatus()); this.findOrThrow(request.getProductId()); this.processImagesUpdate(request); } @Transactional @Override public void batchDelete(List ids) { productService.deleteAll(ids); } @Override public void putOnShelf(Long productId) { Product existingProduct = productService.getById(productId); if (ProductStatusEnum.AVAILABLE.getValue().equals(existingProduct.getShelfStatus())) { throw new BadRequestException("商品已上架"); } if (productAuditService.hasPendingByStoreId(productId)) { 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 wrapper = new LambdaUpdateWrapper() .eq(Product::getProductId, productId) .set(Product::getStatus, ProductStatusEnum.PENDING.getValue()); productService.update(wrapper); } @Override public void takeOffShelf(Long productId) { Product existingProduct = productService.getById(productId); if (ProductStatusEnum.NO_AVAILABLE.getValue().equals(existingProduct.getShelfStatus())) { return; } LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper() .eq(Product::getProductId, productId) .set(Product::getStatus, ProductStatusEnum.NO_AVAILABLE.getValue()) .set(Product::getShelfStatus, 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 Product findOrThrow(Long productId) { Product existingProduct = productService.getById(productId); if (ObjUtil.isEmpty(existingProduct)) { throw new EntityNotFoundException(Product.class, "id", Optional.ofNullable(productId).map(Object::toString).orElse("null")); } return existingProduct; } 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 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 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) { Set statusEnumSet = CollectionUtil.newHashSet(ProductStatusEnum.PENDING, ProductStatusEnum.UNDER_REVIEW, ProductStatusEnum.AVAILABLE); ProductStatusEnum existingStatus = ProductStatusEnum.getOrDefault(status, ProductStatusEnum.DRAFT); if (statusEnumSet.contains(existingStatus)) { throw new BadRequestException("在售商品无法修改"); } } }