Price 价格服务的编写

pull/4/MERGE
YunaiV 2020-08-15 15:37:53 +08:00
parent 5122b68aca
commit 8818b350d6
26 changed files with 330 additions and 60 deletions

View File

@ -1,5 +1,8 @@
package cn.iocoder.mall.productservice.rpc.sku.dto; package cn.iocoder.mall.productservice.rpc.sku.dto;
import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum;
import cn.iocoder.mall.productservice.rpc.attr.dto.ProductAttrKeyValueRespDTO;
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -46,5 +49,19 @@ public class ProductSkuRespDTO implements Serializable {
* *
*/ */
private Date createTime; private Date createTime;
/**
*
*
* {@link ProductSkuDetailFieldEnum#ATTR}
*/
private List<ProductAttrKeyValueRespDTO> attrs;
/**
* SPU
*
* {@link ProductSkuDetailFieldEnum#SPU}
*
* // TODO 芋艿,后续考虑怎么优化下,目前是内嵌了别的 dto
*/
private ProductSpuRespDTO spu;
} }

View File

@ -70,6 +70,13 @@
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<!-- Test 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 工具类相关 --> <!-- 工具类相关 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -1,18 +1,25 @@
package cn.iocoder.mall.productservice.convert.sku; package cn.iocoder.mall.productservice.convert.sku;
import cn.iocoder.common.framework.util.CollectionUtils;
import cn.iocoder.common.framework.util.StringUtils; import cn.iocoder.common.framework.util.StringUtils;
import cn.iocoder.mall.productservice.dal.mysql.dataobject.sku.ProductSkuDO; import cn.iocoder.mall.productservice.dal.mysql.dataobject.sku.ProductSkuDO;
import cn.iocoder.mall.productservice.rpc.attr.dto.ProductAttrKeyValueRespDTO;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO; import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO; import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO;
import cn.iocoder.mall.productservice.service.attr.bo.ProductAttrKeyValueBO;
import cn.iocoder.mall.productservice.service.sku.bo.ProductSkuBO; import cn.iocoder.mall.productservice.service.sku.bo.ProductSkuBO;
import cn.iocoder.mall.productservice.service.sku.bo.ProductSkuCreateOrUpdateBO; import cn.iocoder.mall.productservice.service.sku.bo.ProductSkuCreateOrUpdateBO;
import cn.iocoder.mall.productservice.service.sku.bo.ProductSkuListQueryBO; import cn.iocoder.mall.productservice.service.sku.bo.ProductSkuListQueryBO;
import cn.iocoder.mall.productservice.service.spu.bo.ProductSpuBO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Named; import org.mapstruct.Named;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
@Mapper @Mapper
public interface ProductSkuConvert { public interface ProductSkuConvert {
@ -33,7 +40,30 @@ public interface ProductSkuConvert {
ProductSkuListQueryBO convert(ProductSkuListQueryReqDTO bean); ProductSkuListQueryBO convert(ProductSkuListQueryReqDTO bean);
List<ProductSkuRespDTO> convertList03(List<ProductSkuBO> list); ProductSpuRespDTO convert(ProductSpuBO bean);
ProductAttrKeyValueRespDTO convert(ProductAttrKeyValueBO bean);
default List<ProductSkuRespDTO> convertList(List<ProductSkuBO> skuBOs, List<ProductSpuBO> spuBOs,
List<ProductAttrKeyValueBO> attrBOs) {
// 创建 ProductAttrDetailBO 的映射。其中KEY 为 ProductAttrDetailBO.attrValueId ,即规格值的编号
Map<Integer, ProductAttrKeyValueBO> attrDetailBOMap = CollectionUtils.convertMap(attrBOs,
ProductAttrKeyValueBO::getAttrValueId);
// 构建 ProductSpuBO 的映射。
Map<Integer, ProductSpuBO> spuBOMap = CollectionUtils.convertMap(spuBOs, ProductSpuBO::getId);
// 拼接数据
List<ProductSkuRespDTO> skuRespDTOs = new ArrayList<>(skuBOs.size());
skuBOs.forEach(skuBO -> {
ProductSkuRespDTO skuRespDTO = convert(skuBO);
skuRespDTOs.add(skuRespDTO);
// 拼接商品 SPU
skuRespDTO.setSpu(convert(spuBOMap.get(skuBO.getSpuId())));
// 拼接商品 Attr
skuRespDTO.setAttrs(new ArrayList<>());
skuBO.getAttrValueIds().forEach(attrValueId -> skuRespDTO.getAttrs().add(convert(attrDetailBOMap.get(attrValueId))));
});
return skuRespDTOs;
}
@Named("translateAttrValueIdsFromString") @Named("translateAttrValueIdsFromString")
default List<Integer> translateAttrValueIdsFromString(String attrValueIdsStar) { default List<Integer> translateAttrValueIdsFromString(String attrValueIdsStar) {

View File

@ -63,21 +63,21 @@ public interface ProductSpuConvert {
ProductAttrKeyValueRespDTO convert(ProductAttrKeyValueBO bean); ProductAttrKeyValueRespDTO convert(ProductAttrKeyValueBO bean);
default ProductSpuDetailRespDTO convert(ProductSpuBO spuBO, List<ProductSkuBO> skuBOs, List<ProductAttrKeyValueBO> attrBOs, default ProductSpuDetailRespDTO convert(ProductSpuBO spuBO, List<ProductSkuBO> skuBOs,
ProductCategoryBO categoryBO) { List<ProductAttrKeyValueBO> attrBOs, ProductCategoryBO categoryBO) {
// 创建并转换 ProductSpuDetailBO 对象 // 创建并转换 ProductSpuDetailBO 对象
ProductSpuDetailRespDTO spuDetailDTO = this.convert2(spuBO); ProductSpuDetailRespDTO spuDetailDTO = this.convert2(spuBO);
// 创建 ProductAttrDetailBO 的映射。其中KEY 为 ProductAttrDetailBO.attrValueId ,即规格值的编号 // 创建 ProductAttrDetailBO 的映射。其中KEY 为 ProductAttrDetailBO.attrValueId ,即规格值的编号
Map<Integer, ProductAttrKeyValueBO> productAttrDetailBOMap = attrBOs.stream().collect( Map<Integer, ProductAttrKeyValueBO> attrDetailBOMap = attrBOs.stream().collect(
Collectors.toMap(ProductAttrKeyValueBO::getAttrValueId, attrBO -> attrBO)); Collectors.toMap(ProductAttrKeyValueBO::getAttrValueId, attrBO -> attrBO));
// 创建并转换 ProductSpuDetailBO 数组 // 创建并转换 ProductSpuDetailBO 数组
spuDetailDTO.setSkus(new ArrayList<>()); spuDetailDTO.setSkus(new ArrayList<>());
skuBOs.forEach(sku -> { skuBOs.forEach(skuBO -> {
// 创建 ProductSpuDetailBO 对象 // 创建 ProductSpuDetailBO 对象
ProductSpuDetailRespDTO.Sku skuDetail = convert(sku).setAttrs(new ArrayList<>()); ProductSpuDetailRespDTO.Sku skuDetail = convert(skuBO).setAttrs(new ArrayList<>());
spuDetailDTO.getSkus().add(skuDetail); spuDetailDTO.getSkus().add(skuDetail);
// 设置 ProductSpuDetailBO 的 attrs 规格属性 // 设置 ProductSpuDetailBO 的 attrs 规格属性
sku.getAttrValueIds().forEach(attrValueId -> skuDetail.getAttrs().add(convert(productAttrDetailBOMap.get(attrValueId)))); skuBO.getAttrValueIds().forEach(attrValueId -> skuDetail.getAttrs().add(convert(attrDetailBOMap.get(attrValueId))));
}); });
// 设置分类名 // 设置分类名
spuDetailDTO.setCategoryName(categoryBO.getName()); spuDetailDTO.setCategoryName(categoryBO.getName());

View File

@ -2,15 +2,22 @@ package cn.iocoder.mall.productservice.manager.sku;
import cn.iocoder.common.framework.util.CollectionUtils; import cn.iocoder.common.framework.util.CollectionUtils;
import cn.iocoder.mall.productservice.convert.sku.ProductSkuConvert; import cn.iocoder.mall.productservice.convert.sku.ProductSkuConvert;
import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO; import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO; import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
import cn.iocoder.mall.productservice.service.attr.ProductAttrService;
import cn.iocoder.mall.productservice.service.attr.bo.ProductAttrKeyValueBO;
import cn.iocoder.mall.productservice.service.sku.ProductSkuService; import cn.iocoder.mall.productservice.service.sku.ProductSkuService;
import cn.iocoder.mall.productservice.service.sku.bo.ProductSkuBO; import cn.iocoder.mall.productservice.service.sku.bo.ProductSkuBO;
import cn.iocoder.mall.productservice.service.spu.ProductSpuService;
import cn.iocoder.mall.productservice.service.spu.bo.ProductSpuBO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* SKU Manager * SKU Manager
@ -20,6 +27,10 @@ public class ProductSkuManager {
@Autowired @Autowired
private ProductSkuService productSkuService; private ProductSkuService productSkuService;
@Autowired
private ProductSpuService productSpuService;
@Autowired
private ProductAttrService productAttrService;
/** /**
* SKU * SKU
@ -40,13 +51,26 @@ public class ProductSkuManager {
*/ */
public List<ProductSkuRespDTO> listProductSkus(ProductSkuListQueryReqDTO queryReqDTO) { public List<ProductSkuRespDTO> listProductSkus(ProductSkuListQueryReqDTO queryReqDTO) {
// 获得商品 SKU 列表 // 获得商品 SKU 列表
List<ProductSkuBO> productSkuBOs = productSkuService.listProductSkus( List<ProductSkuBO> skuBOs = productSkuService.listProductSkus(
ProductSkuConvert.INSTANCE.convert(queryReqDTO)); ProductSkuConvert.INSTANCE.convert(queryReqDTO));
if (CollectionUtils.isEmpty(productSkuBOs)) { if (CollectionUtils.isEmpty(skuBOs)) {
return Collections.emptyList(); return Collections.emptyList();
} }
// // 获得商品 SPU 列表
return ProductSkuConvert.INSTANCE.convertList03(productSkuBOs); List<ProductSpuBO> spuBOs = Collections.emptyList();
if (queryReqDTO.getFields().contains(ProductSkuDetailFieldEnum.SPU.getField())) {
spuBOs = productSpuService.listProductSpus(
CollectionUtils.convertSet(skuBOs, ProductSkuBO::getSpuId));
}
// 获取商品 SKU 的规格数组
List<ProductAttrKeyValueBO> attrBOs = Collections.emptyList();
if (queryReqDTO.getFields().contains(ProductSkuDetailFieldEnum.ATTR.getField())) {
Set<Integer> attrValueIds = new HashSet<>();
skuBOs.forEach(sku -> attrValueIds.addAll(sku.getAttrValueIds()));
attrBOs = productAttrService.validProductAttr(attrValueIds, false); // 读取规格时,不考虑规格是否被禁用
}
// 拼接最终返回
return ProductSkuConvert.INSTANCE.convertList(skuBOs, spuBOs, attrBOs);
} }
} }

View File

@ -231,9 +231,9 @@ public class ProductSpuManager {
// 获取商品 SKU 的规格数组 // 获取商品 SKU 的规格数组
List<ProductAttrKeyValueBO> attrBOs = Collections.emptyList(); List<ProductAttrKeyValueBO> attrBOs = Collections.emptyList();
if (fields.contains(ProductSpuDetailFieldEnum.ATTR.getField()) && !CollectionUtils.isEmpty(skuBOs)) { if (fields.contains(ProductSpuDetailFieldEnum.ATTR.getField()) && !CollectionUtils.isEmpty(skuBOs)) {
Set<Integer> productAttrValueIds = new HashSet<>(); Set<Integer> attrValueIds = new HashSet<>();
skuBOs.forEach(sku -> productAttrValueIds.addAll(sku.getAttrValueIds())); skuBOs.forEach(sku -> attrValueIds.addAll(sku.getAttrValueIds()));
attrBOs = productAttrService.validProductAttr(productAttrValueIds, false); // 读取规格时,不考虑规格是否被禁用 attrBOs = productAttrService.validProductAttr(attrValueIds, false); // 读取规格时,不考虑规格是否被禁用
} }
// 拼接最终返回 // 拼接最终返回
return ProductSpuConvert.INSTANCE.convert(spuBO, skuBOs, attrBOs, categoryBO); return ProductSpuConvert.INSTANCE.convert(spuBO, skuBOs, attrBOs, categoryBO);

View File

@ -0,0 +1,34 @@
package cn.iocoder.mall.productservice.manager.spu;
import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum;
import cn.iocoder.mall.productservice.manager.sku.ProductSkuManager;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Arrays;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@Slf4j
public class ProductSkuManagerTest {
@Autowired
private ProductSkuManager productSkuManager;
@Test
public void testListProductSkus() {
List<ProductSkuRespDTO> skuRespDTOs = productSkuManager.listProductSkus(
new ProductSkuListQueryReqDTO().setProductSkuIds(Arrays.asList(3, 4))
.setFields(Arrays.asList(ProductSkuDetailFieldEnum.SPU.getField(),
ProductSkuDetailFieldEnum.ATTR.getField())));
log.info("结果:{}", skuRespDTOs);
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.mall.productservice;

View File

@ -1,16 +1,21 @@
package cn.iocoder.mall.promotion.api.rpc.activity.dto; package cn.iocoder.mall.promotion.api.rpc.activity;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
import java.util.Collection;
import java.util.List; import java.util.List;
public interface PromotionActivityRpc { public interface PromotionActivityRpc {
List<PromotionActivityRespDTO> getPromotionActivityListBySpuId(Integer spuId, // List<PromotionActivityRespDTO> getPromotionActivityListBySpuId(Integer spuId,
Collection<Integer> activityStatuses); // Collection<Integer> activityStatuses);
//
// List<PromotionActivityRespDTO> getPromotionActivityListBySpuIds(Collection<Integer> spuIds,
// Collection<Integer> activityStatuses);
//
// PromotionActivityPageReqDTO getPromotionActivityPage(PromotionActivityPageRespDTO promotionActivityPageDTO);
List<PromotionActivityRespDTO> getPromotionActivityListBySpuIds(Collection<Integer> spuIds, CommonResult<List<PromotionActivityRespDTO>> listPromotionActivities(PromotionActivityListReqDTO listReqDTO);
Collection<Integer> activityStatuses);
PromotionActivityPageReqDTO getPromotionActivityPage(PromotionActivityPageRespDTO promotionActivityPageDTO);
} }

View File

@ -0,0 +1,21 @@
package cn.iocoder.mall.promotion.api.rpc.activity.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Collection;
/**
* Request DTO
*/
@Data
@Accessors(chain = true)
public class PromotionActivityListReqDTO implements Serializable {
/**
*
*/
private Collection<Integer> activeIds;
}

View File

@ -8,7 +8,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
/** /**
* Response DTO * Response DTO
*/ */
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)

View File

@ -41,18 +41,26 @@ public class PriceProductCalcReqDTO implements Serializable {
/** /**
* SKU * SKU
*/ */
@NotNull(message = "商品 SKU 编号不能为空")
private Integer skuId; private Integer skuId;
/** /**
* *
*/ */
@NotNull(message = "商品 SKU 数量不能为空")
private Integer quantity; private Integer quantity;
/**
*
*/
@NotNull(message = "是否选中不能为空")
private Boolean selected;
public Item() { public Item() {
} }
public Item(Integer skuId, Integer quantity) { public Item(Integer skuId, Integer quantity, Boolean selected) {
this.skuId = skuId; this.skuId = skuId;
this.quantity = quantity; this.quantity = quantity;
this.selected = selected;
} }
} }

View File

@ -1,7 +1,6 @@
package cn.iocoder.mall.promotion.api.rpc.price.dto; package cn.iocoder.mall.promotion.api.rpc.price.dto;
import cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum; import cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -57,7 +56,7 @@ public class PriceProductCalcRespDTO implements Serializable {
* *
* // TODO 芋艿,目前只会有【满减送】的情况,未来有新的促销方式,可能需要改成数组 * // TODO 芋艿,目前只会有【满减送】的情况,未来有新的促销方式,可能需要改成数组
*/ */
private PromotionActivityRespDTO activity; private Integer activityId;
/** /**
* *
* *
@ -94,6 +93,13 @@ public class PriceProductCalcRespDTO implements Serializable {
* Category * Category
*/ */
private Integer cid; private Integer cid;
// 非 SKU 自带信息
/**
*
*/
private Boolean selected;
/** /**
* *
*/ */
@ -103,7 +109,7 @@ public class PriceProductCalcRespDTO implements Serializable {
* *
* {@link PromotionActivityTypeEnum#TIME_LIMITED_DISCOUNT} * {@link PromotionActivityTypeEnum#TIME_LIMITED_DISCOUNT}
*/ */
private PromotionActivityRespDTO activity; private Integer activityId;
/** /**
* *
*/ */

View File

@ -1,5 +1,7 @@
package cn.iocoder.mall.promotionservice.dal.mysql.mapper.activity; package cn.iocoder.mall.promotionservice.dal.mysql.mapper.activity;
import cn.iocoder.mall.mybatis.core.query.QueryWrapperX;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.activity.PromotionActivityDO; import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.activity.PromotionActivityDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@ -26,4 +28,8 @@ public interface PromotionActivityMapper extends BaseMapper<PromotionActivityDO>
@Param("activityType") Integer activityType, @Param("activityType") Integer activityType,
@Param("statuses") Collection<Integer> statuses); @Param("statuses") Collection<Integer> statuses);
default List<PromotionActivityDO> selectList(PromotionActivityListReqDTO listReqDTO) {
return selectList(new QueryWrapperX<PromotionActivityDO>().inIfPresent("id", listReqDTO.getActiveIds()));
}
} }

View File

@ -0,0 +1,26 @@
package cn.iocoder.mall.promotionservice.manager.activity;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
import cn.iocoder.mall.promotionservice.service.activity.PromotionActivityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.List;
/**
* Manager
*/
@Service
@Validated
public class PromotionActivityManager {
@Autowired
private PromotionActivityService promotionActivityService;
public List<PromotionActivityRespDTO> listPromotionActivities(PromotionActivityListReqDTO listReqDTO) {
return promotionActivityService.listPromotionActivities(listReqDTO);
}
}

View File

@ -134,7 +134,7 @@ public class PriceManager {
continue; continue;
} }
// 设置优惠 // 设置优惠
item.setActivity(timeLimitedDiscount); item.setActivityId(timeLimitedDiscount.getId());
// 设置价格 // 设置价格
item.setBuyPrice(newBuyPrice); item.setBuyPrice(newBuyPrice);
item.setBuyTotal(newBuyPrice * item.getBuyQuantity()); item.setBuyTotal(newBuyPrice * item.getBuyQuantity());
@ -186,7 +186,7 @@ public class PriceManager {
for (PromotionActivityRespDTO fullPrivilege : fullPrivileges) { for (PromotionActivityRespDTO fullPrivilege : fullPrivileges) {
// 创建 fullPrivilege 对应的分组 // 创建 fullPrivilege 对应的分组
PriceProductCalcRespDTO.ItemGroup itemGroup = new PriceProductCalcRespDTO.ItemGroup() PriceProductCalcRespDTO.ItemGroup itemGroup = new PriceProductCalcRespDTO.ItemGroup()
.setActivity(fullPrivilege) .setActivityId(fullPrivilege.getId())
.setItems(new ArrayList<>()); .setItems(new ArrayList<>());
// 筛选商品到分组中 // 筛选商品到分组中
for (Iterator<PriceProductCalcRespDTO.Item> iterator = items.iterator(); iterator.hasNext(); ) { for (Iterator<PriceProductCalcRespDTO.Item> iterator = items.iterator(); iterator.hasNext(); ) {
@ -208,8 +208,9 @@ public class PriceManager {
itemGroups.add(new PriceProductCalcRespDTO.ItemGroup().setItems(items)); itemGroups.add(new PriceProductCalcRespDTO.ItemGroup().setItems(items));
} }
// 计算每个分组的价格 // 计算每个分组的价格
Map<Integer, PromotionActivityRespDTO> activityMap = CollectionUtils.convertMap(activityList, PromotionActivityRespDTO::getId);
for (PriceProductCalcRespDTO.ItemGroup itemGroup : itemGroups) { for (PriceProductCalcRespDTO.ItemGroup itemGroup : itemGroups) {
itemGroup.setActivityDiscountTotal(calcSkuPriceByFullPrivilege(itemGroup)); itemGroup.setActivityDiscountTotal(calcSkuPriceByFullPrivilege(itemGroup, activityMap.get(itemGroup.getActivityId())));
} }
// 返回结果 // 返回结果
return itemGroups; return itemGroups;
@ -227,11 +228,10 @@ public class PriceManager {
throw new IllegalArgumentException(String.format("促销活动(%s) 可用范围的类型是不正确", activity.toString())); throw new IllegalArgumentException(String.format("促销活动(%s) 可用范围的类型是不正确", activity.toString()));
} }
private Integer calcSkuPriceByFullPrivilege(PriceProductCalcRespDTO.ItemGroup itemGroup) { private Integer calcSkuPriceByFullPrivilege(PriceProductCalcRespDTO.ItemGroup itemGroup, PromotionActivityRespDTO activity) {
if (itemGroup.getActivity() == null) { if (itemGroup.getActivityId() == null) {
return null; return null;
} }
PromotionActivityRespDTO activity = itemGroup.getActivity();
Assert.isTrue(PromotionActivityTypeEnum.FULL_PRIVILEGE.getValue().equals(activity.getActivityType()), Assert.isTrue(PromotionActivityTypeEnum.FULL_PRIVILEGE.getValue().equals(activity.getActivityType()),
"传入的必须的满减送活动必须是满减送"); "传入的必须的满减送活动必须是满减送");
// 获得优惠信息 // 获得优惠信息
@ -246,7 +246,8 @@ public class PriceManager {
if (MeetTypeEnum.QUANTITY.getValue().equals(privilege.getMeetType())) { if (MeetTypeEnum.QUANTITY.getValue().equals(privilege.getMeetType())) {
return itemCnt >= privilege.getMeetValue(); return itemCnt >= privilege.getMeetValue();
} }
throw new IllegalArgumentException(String.format("满减送活动(%s) 的匹配(%s)不正确", itemGroup.getActivity().toString(), privilege.toString())); throw new IllegalArgumentException(String.format("满减送活动(%s) 的匹配(%s)不正确",
activity.toString(), privilege.toString()));
}).collect(Collectors.toList()); }).collect(Collectors.toList());
// 获得不到优惠信息,返回原始价格 // 获得不到优惠信息,返回原始价格
if (privileges.isEmpty()) { if (privileges.isEmpty()) {

View File

@ -0,0 +1,26 @@
package cn.iocoder.mall.promotionservice.rpc.activity;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.rpc.activity.PromotionActivityRpc;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
import cn.iocoder.mall.promotionservice.manager.activity.PromotionActivityManager;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@DubboService
public class PromotionActivityRpcImpl implements PromotionActivityRpc {
@Autowired
private PromotionActivityManager promotionActivityManager;
@Override
public CommonResult<List<PromotionActivityRespDTO>> listPromotionActivities(PromotionActivityListReqDTO listReqDTO) {
return success(promotionActivityManager.listPromotionActivities(listReqDTO));
}
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.mall.promotionservice.service.activity;
import cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum; import cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum;
import cn.iocoder.mall.promotion.api.enums.RangeTypeEnum; import cn.iocoder.mall.promotion.api.enums.RangeTypeEnum;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO; import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
import cn.iocoder.mall.promotionservice.convert.activity.PromotionActivityConvert; import cn.iocoder.mall.promotionservice.convert.activity.PromotionActivityConvert;
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.activity.PromotionActivityDO; import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.activity.PromotionActivityDO;
@ -25,24 +26,15 @@ public class PromotionActivityService {
@Autowired @Autowired
private PromotionActivityMapper promotionActivityMapper; private PromotionActivityMapper promotionActivityMapper;
/** public List<PromotionActivityRespDTO> listPromotionActivities(PromotionActivityListReqDTO listReqDTO) {
* List<PromotionActivityDO> activityList = promotionActivityMapper.selectList(listReqDTO);
* return PromotionActivityConvert.INSTANCE.convertList(activityList);
* @param spuId }
* @param activityStatuses
* @return
*/
public List<PromotionActivityRespDTO> listPromotionActivitiesBySpuId(Integer spuId, Collection<Integer> activityStatuses) { public List<PromotionActivityRespDTO> listPromotionActivitiesBySpuId(Integer spuId, Collection<Integer> activityStatuses) {
return this.listPromotionActivitiesBySpuIds(Collections.singleton(spuId), activityStatuses); return this.listPromotionActivitiesBySpuIds(Collections.singleton(spuId), activityStatuses);
} }
/**
*
*
* @param spuIds
* @param activityStatuses
* @return
*/
public List<PromotionActivityRespDTO> listPromotionActivitiesBySpuIds(Collection<Integer> spuIds, Collection<Integer> activityStatuses) { public List<PromotionActivityRespDTO> listPromotionActivitiesBySpuIds(Collection<Integer> spuIds, Collection<Integer> activityStatuses) {
if (spuIds.isEmpty() || activityStatuses.isEmpty()) { if (spuIds.isEmpty() || activityStatuses.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();

View File

@ -13,7 +13,7 @@ import cn.iocoder.mall.promotionservice.dal.mysql.mapper.recommend.ProductRecomm
import cn.iocoder.mall.promotionservice.service.recommend.bo.ProductRecommendAddBO; import cn.iocoder.mall.promotionservice.service.recommend.bo.ProductRecommendAddBO;
import cn.iocoder.mall.promotionservice.service.recommend.bo.ProductRecommendBO; import cn.iocoder.mall.promotionservice.service.recommend.bo.ProductRecommendBO;
import cn.iocoder.mall.promotionservice.service.recommend.bo.ProductRecommendUpdateBO; import cn.iocoder.mall.promotionservice.service.recommend.bo.ProductRecommendUpdateBO;
import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -25,7 +25,7 @@ import java.util.List;
@Validated @Validated
public class ProductRecommendService { public class ProductRecommendService {
@Reference(validation = "true", version = "${dubbo.consumer.ProductSpuService.version}") @DubboReference(validation = "true", version = "${dubbo.consumer.ProductSpuRpc.version}")
private ProductSpuRpc productSpuRpc; private ProductSpuRpc productSpuRpc;
@Autowired @Autowired

View File

@ -44,7 +44,7 @@ public class CartController {
@GetMapping("/get-detail") @GetMapping("/get-detail")
@ApiOperation("查询用户的购物车的商品列表") @ApiOperation("查询用户的购物车的商品列表")
public CommonResult<CartDetailVO> getCartDetail() { public CommonResult<CartDetailVO> getCartDetail() {
return success(cartManager.getCartDetail()); return success(cartManager.getCartDetail(UserSecurityContextHolder.getUserId()));
} }
} }

View File

@ -1,5 +1,8 @@
package cn.iocoder.mall.shopweb.convert.order; package cn.iocoder.mall.shopweb.convert.order;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
import cn.iocoder.mall.shopweb.controller.order.vo.cart.CartDetailVO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -8,4 +11,8 @@ public interface CartConvert {
CartConvert INSTANCE = Mappers.getMapper(CartConvert.class); CartConvert INSTANCE = Mappers.getMapper(CartConvert.class);
CartDetailVO.Fee convert(PriceProductCalcRespDTO.Fee bean);
CartDetailVO.Sku convert(PriceProductCalcRespDTO.Item item, ProductSkuRespDTO sku);
} }

View File

@ -6,15 +6,22 @@ import cn.iocoder.mall.orderservice.rpc.cart.CartRpc;
import cn.iocoder.mall.orderservice.rpc.cart.dto.CartItemAddReqDTO; import cn.iocoder.mall.orderservice.rpc.cart.dto.CartItemAddReqDTO;
import cn.iocoder.mall.orderservice.rpc.cart.dto.CartItemListReqDTO; import cn.iocoder.mall.orderservice.rpc.cart.dto.CartItemListReqDTO;
import cn.iocoder.mall.orderservice.rpc.cart.dto.CartItemRespDTO; import cn.iocoder.mall.orderservice.rpc.cart.dto.CartItemRespDTO;
import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum;
import cn.iocoder.mall.productservice.rpc.sku.ProductSkuRpc;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
import cn.iocoder.mall.promotion.api.rpc.activity.PromotionActivityRpc;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
import cn.iocoder.mall.promotion.api.rpc.price.PriceRpc; import cn.iocoder.mall.promotion.api.rpc.price.PriceRpc;
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcReqDTO; import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcReqDTO;
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO; import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
import cn.iocoder.mall.shopweb.controller.order.vo.cart.CartDetailVO; import cn.iocoder.mall.shopweb.controller.order.vo.cart.CartDetailVO;
import cn.iocoder.mall.shopweb.convert.order.CartConvert;
import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -27,6 +34,10 @@ public class CartManager {
private CartRpc cartRpc; private CartRpc cartRpc;
@DubboReference(version = "${dubbo.consumer.PriceRpc.version}") @DubboReference(version = "${dubbo.consumer.PriceRpc.version}")
private PriceRpc priceRpc; private PriceRpc priceRpc;
@DubboReference(version = "${dubbo.consumer.PromotionActivityRpc.version}")
private PromotionActivityRpc promotionActivityRpc;
@DubboReference(version = "${dubbo.consumer.ProductSkuRpc.version}")
private ProductSkuRpc productSkuRpc;
/** /**
* *
@ -72,14 +83,63 @@ public class CartManager {
// 计算选中的商品价格 // 计算选中的商品价格
CommonResult<PriceProductCalcRespDTO> calcProductPriceResult = priceRpc.calcProductPrice(new PriceProductCalcReqDTO().setUserId(userId) CommonResult<PriceProductCalcRespDTO> calcProductPriceResult = priceRpc.calcProductPrice(new PriceProductCalcReqDTO().setUserId(userId)
.setItems(listCartItemsResult.getData().stream() .setItems(listCartItemsResult.getData().stream()
.filter(CartItemRespDTO::getSelected) .map(cartItem -> new PriceProductCalcReqDTO.Item(cartItem.getSkuId(), cartItem.getQuantity(), cartItem.getSelected()))
.map(cartItem -> new PriceProductCalcReqDTO.Item(cartItem.getSkuId(), cartItem.getQuantity()))
.collect(Collectors.toList()))); .collect(Collectors.toList())));
calcProductPriceResult.checkError(); calcProductPriceResult.checkError();
// 获得促销活动信息
Map<Integer, PromotionActivityRespDTO> promotionActivityMap = this.getPromotionActivityMap(calcProductPriceResult.getData());
// 获得商品 SKU 信息
Map<Integer, ProductSkuRespDTO> productSkuMap = this.getProductSkuMap(listCartItemsResult.getData());
// 拼接结果 // 拼接结果
CartDetailVO cartDetailVO = new CartDetailVO();
cartDetailVO.setFee(CartConvert.INSTANCE.convert(calcProductPriceResult.getData().getFee()));
cartDetailVO.setItemGroups(new ArrayList<>());
calcProductPriceResult.getData().getItemGroups().forEach(itemGroupDTO -> {
CartDetailVO.ItemGroup itemGroupVO = new CartDetailVO.ItemGroup();
cartDetailVO.getItemGroups().add(itemGroupVO);
// 活动信息
if (itemGroupDTO.getActivityId() != null) {
itemGroupVO.setActivity(promotionActivityMap.get(itemGroupDTO.getActivityId()))
.setActivityDiscountTotal(itemGroupDTO.getActivityDiscountTotal());
}
// 商品 SKU 信息
itemGroupVO.setItems(new ArrayList<>());
itemGroupDTO.getItems().forEach(item -> {
itemGroupVO.getItems().add(CartConvert.INSTANCE.convert(item, productSkuMap.get(item.getSkuId())));
});
});
return cartDetailVO;
}
// 执行数据拼装 private Map<Integer, PromotionActivityRespDTO> getPromotionActivityMap(PriceProductCalcRespDTO calcRespDTO) {
return null; // 获得所有促销活动编号
Set<Integer> activeIds = new HashSet<>();
calcRespDTO.getItemGroups().forEach(itemGroup -> {
if (itemGroup.getActivityId() != null) {
activeIds.add(itemGroup.getActivityId());
}
itemGroup.getItems().forEach(item -> {
if (item.getActivityId() != null) {
activeIds.add(item.getActivityId());
}
});
});
if (!CollectionUtils.isEmpty(activeIds)) {
return Collections.emptyMap();
}
// 查询促销活动列表
CommonResult<List<PromotionActivityRespDTO>> listPromotionActivitiesResult =
promotionActivityRpc.listPromotionActivities(new PromotionActivityListReqDTO().setActiveIds(activeIds));
listPromotionActivitiesResult.checkError();
return CollectionUtils.convertMap(listPromotionActivitiesResult.getData(), PromotionActivityRespDTO::getId);
}
private Map<Integer, ProductSkuRespDTO> getProductSkuMap(List<CartItemRespDTO> itemRespDTOs) {
CommonResult<List<ProductSkuRespDTO>> listProductSkusResult = productSkuRpc.listProductSkus(new ProductSkuListQueryReqDTO()
.setProductSkuIds(CollectionUtils.convertSet(itemRespDTOs, CartItemRespDTO::getSkuId))
.setFields(Arrays.asList(ProductSkuDetailFieldEnum.SPU.getField(), ProductSkuDetailFieldEnum.ATTR.getField())));
listProductSkusResult.checkError();
return CollectionUtils.convertMap(listProductSkusResult.getData(), ProductSkuRespDTO::getId);
} }
} }

View File

@ -1 +0,0 @@
package cn.iocoder.mall.shopweb.manager.order;

View File

@ -41,6 +41,8 @@ dubbo:
version: 1.0.0 version: 1.0.0
PriceRpc: PriceRpc:
version: 1.0.0 version: 1.0.0
PromotionActivityRpc:
version: 1.0.0
# Swagger 配置项 # Swagger 配置项
swagger: swagger: