|  | @@ -1,22 +1,37 @@
 | 
	
		
			
				|  |  |  package cn.iocoder.yudao.module.promotion.service.combination;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import cn.hutool.core.collection.CollUtil;
 | 
	
		
			
				|  |  | +import cn.hutool.core.util.ObjectUtil;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 | 
	
		
			
				|  |  |  import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
	
		
			
				|  |  | -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.CombinationActivityCreateReqVO;
 | 
	
		
			
				|  |  | -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.CombinationActivityExportReqVO;
 | 
	
		
			
				|  |  | -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.CombinationActivityPageReqVO;
 | 
	
		
			
				|  |  | -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.CombinationActivityUpdateReqVO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
 | 
	
		
			
				|  |  |  import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
 | 
	
		
			
				|  |  | -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
 | 
	
		
			
				|  |  | -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationActivityMapper;
 | 
	
		
			
				|  |  | +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationProductMapper;
 | 
	
		
			
				|  |  |  import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  |  import org.springframework.validation.annotation.Validated;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import javax.annotation.Resource;
 | 
	
		
			
				|  |  | +import java.util.ArrayList;
 | 
	
		
			
				|  |  |  import java.util.Collection;
 | 
	
		
			
				|  |  |  import java.util.List;
 | 
	
		
			
				|  |  | +import java.util.stream.Collectors;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
	
		
			
				|  |  | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
 | 
	
		
			
				|  |  |  import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_ACTIVITY_NOT_EXISTS;
 | 
	
		
			
				|  |  | +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_ACTIVITY_SPU_CONFLICTS;
 | 
	
		
			
				|  |  | +import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * 拼团活动 Service 实现类
 | 
	
	
		
			
				|  | @@ -29,14 +44,59 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Resource
 | 
	
		
			
				|  |  |      private CombinationActivityMapper combinationActivityMapper;
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private CombinationProductMapper combinationProductMapper;
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private ProductSpuApi productSpuApi;
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private ProductSkuApi productSkuApi;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) {
 | 
	
		
			
				|  |  | -        // 插入
 | 
	
		
			
				|  |  | -        CombinationActivityDO combinationActivity = CombinationActivityConvert.INSTANCE.convert(createReqVO);
 | 
	
		
			
				|  |  | -        combinationActivityMapper.insert(combinationActivity);
 | 
	
		
			
				|  |  | +        // 校验商品 SPU 是否存在是否参加的别的活动
 | 
	
		
			
				|  |  | +        validateProductCombinationConflict(createReqVO.getSpuIds());
 | 
	
		
			
				|  |  | +        // 获取所选 spu下的所有 sku
 | 
	
		
			
				|  |  | +        List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(createReqVO.getSpuIds());
 | 
	
		
			
				|  |  | +        // 校验商品 sku 是否存在
 | 
	
		
			
				|  |  | +        validateProductSkuExistence(skus, createReqVO.getProducts(), CombinationProductCreateReqVO::getSkuId);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如:
 | 
	
		
			
				|  |  | +        //  活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时
 | 
	
		
			
				|  |  | +        // 插入拼团活动
 | 
	
		
			
				|  |  | +        CombinationActivityDO activityDO = CombinationActivityConvert.INSTANCE.convert(createReqVO);
 | 
	
		
			
				|  |  | +        // TODO 营销相关属性初始化
 | 
	
		
			
				|  |  | +        activityDO.setUserSize(0);
 | 
	
		
			
				|  |  | +        activityDO.setTotalNum(0);
 | 
	
		
			
				|  |  | +        activityDO.setSuccessNum(0);
 | 
	
		
			
				|  |  | +        activityDO.setOrderUserCount(0);
 | 
	
		
			
				|  |  | +        activityDO.setVirtualGroup(0);
 | 
	
		
			
				|  |  | +        activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
 | 
	
		
			
				|  |  | +        combinationActivityMapper.insert(activityDO);
 | 
	
		
			
				|  |  | +        // 插入商品
 | 
	
		
			
				|  |  | +        List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(activityDO, createReqVO.getProducts());
 | 
	
		
			
				|  |  | +        combinationProductMapper.insertBatch(productDOs);
 | 
	
		
			
				|  |  |          // 返回
 | 
	
		
			
				|  |  | -        return combinationActivity.getId();
 | 
	
		
			
				|  |  | +        return activityDO.getId();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void validateProductCombinationConflict(List<Long> spuIds) {
 | 
	
		
			
				|  |  | +        // 校验商品 spu 是否存在
 | 
	
		
			
				|  |  | +        List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
 | 
	
		
			
				|  |  | +        if (ObjectUtil.notEqual(spuIds.size(), spuList.size())) {
 | 
	
		
			
				|  |  | +            throw exception(SPU_NOT_EXISTS);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 查询所有开启的秒杀活动
 | 
	
		
			
				|  |  | +        List<CombinationActivityDO> activityDOs = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
 | 
	
		
			
				|  |  | +        // 过滤出所有 spuIds 有交集的活动
 | 
	
		
			
				|  |  | +        List<CombinationActivityDO> doList = activityDOs.stream().filter(s -> {
 | 
	
		
			
				|  |  | +            // 判断 spu 是否有交集
 | 
	
		
			
				|  |  | +            ArrayList<Long> spuIdsClone = CollUtil.newArrayList(s.getSpuIds());
 | 
	
		
			
				|  |  | +            spuIdsClone.retainAll(spuIds);
 | 
	
		
			
				|  |  | +            return CollUtil.isNotEmpty(spuIdsClone);
 | 
	
		
			
				|  |  | +        }).collect(Collectors.toList());
 | 
	
		
			
				|  |  | +        if (CollUtil.isNotEmpty(doList)) {
 | 
	
		
			
				|  |  | +            throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 |