Commit f75f4e8846ff372bfa5c20048291f7b776572d97

Authored by YunaiV
1 parent dd932151

mall + product:完善商品详情接口

yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/util/DictFrameworkUtils.java
... ... @@ -58,6 +58,11 @@ public class DictFrameworkUtils {
58 58 }
59 59  
60 60 @SneakyThrows
  61 + public static String getDictDataLabel(String dictType, Integer value) {
  62 + return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, String.valueOf(value))).getLabel();
  63 + }
  64 +
  65 + @SneakyThrows
61 66 public static String getDictDataLabel(String dictType, String value) {
62 67 return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, value)).getLabel();
63 68 }
... ...
yudao-module-mall/yudao-module-product-biz/pom.xml
... ... @@ -35,10 +35,9 @@
35 35 <groupId>cn.iocoder.boot</groupId>
36 36 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
37 37 </dependency>
38   - <!-- TODO 芋艿:是不是可以去掉这个依赖呀? -->
39 38 <dependency>
40 39 <groupId>cn.iocoder.boot</groupId>
41   - <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
  40 + <artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
42 41 </dependency>
43 42  
44 43 <!-- Web 相关 -->
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
... ... @@ -5,13 +5,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
6 6 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
7 7 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
8   -import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
9 8 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
10 9 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
11 10 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
12 11 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
13 12 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
14   -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
15 13 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
16 14 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
17 15 import io.swagger.v3.oas.annotations.Operation;
... ... @@ -67,11 +65,8 @@ public class AppProductSpuController {
67 65  
68 66 // 查询商品 SKU
69 67 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
70   - // 查询商品属性
71   - List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
72   - .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
73 68 // 拼接
74   - return success(ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus, propertyValues));
  69 + return success(ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus));
75 70 }
76 71  
77 72 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java
... ... @@ -36,6 +36,9 @@ public class AppProductSpuDetailRespVO {
36 36 @Schema(description = "商品视频", required = true)
37 37 private String videoUrl;
38 38  
  39 + @Schema(description = "单位名", required = true, example = "个")
  40 + private String unitName;
  41 +
39 42 // ========== SKU 相关字段 =========
40 43  
41 44 @Schema(description = "规格类型", required = true, example = "true")
... ... @@ -47,6 +50,9 @@ public class AppProductSpuDetailRespVO {
47 50 @Schema(description = "市场价,单位使用:分", required = true, example = "1024")
48 51 private Integer marketPrice;
49 52  
  53 + @Schema(description = "VIP 价格,单位使用:分", required = true, example = "968") // 通过会员等级,计算出折扣后价格
  54 + private Integer vipPrice;
  55 +
50 56 @Schema(description = "库存", required = true, example = "666")
51 57 private Integer stock;
52 58  
... ... @@ -78,6 +84,9 @@ public class AppProductSpuDetailRespVO {
78 84 @Schema(description = "市场价,单位使用:分", required = true, example = "1024")
79 85 private Integer marketPrice;
80 86  
  87 + @Schema(description = "VIP 价格,单位使用:分", required = true, example = "968") // 通过会员等级,计算出折扣后价格
  88 + private Integer vipPrice;
  89 +
81 90 @Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
82 91 private String picUrl;
83 92  
... ... @@ -89,6 +98,7 @@ public class AppProductSpuDetailRespVO {
89 98  
90 99 @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米
91 100 private Double volume;
  101 +
92 102 }
93 103  
94 104 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
... ... @@ -68,16 +68,6 @@ public interface ProductSkuConvert {
68 68 return spuIdAndStockMap;
69 69 }
70 70  
71   - default Collection<Long> convertPropertyValueIds(List<ProductSkuDO> list) {
72   - if (CollUtil.isEmpty(list)) {
73   - return new HashSet<>();
74   - }
75   - return list.stream().filter(item -> item.getProperties() != null)
76   - .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
77   - .map(ProductSkuDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
78   - .collect(Collectors.toSet());
79   - }
80   -
81 71 default String buildPropertyKey(ProductSkuDO bean) {
82 72 if (CollUtil.isEmpty(bean.getProperties())) {
83 73 return StrUtil.EMPTY;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
... ... @@ -3,17 +3,17 @@ package cn.iocoder.yudao.module.product.convert.spu;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
6 7 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
7 8 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
8 9 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
9   -import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
10 10 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
11 11 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
12 12 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
13 13 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
14 14 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
15 15 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
16   -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
  16 +import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
17 17 import org.mapstruct.Mapper;
18 18 import org.mapstruct.Mapping;
19 19 import org.mapstruct.Named;
... ... @@ -21,10 +21,8 @@ import org.mapstruct.factory.Mappers;
21 21  
22 22 import java.util.ArrayList;
23 23 import java.util.List;
24   -import java.util.Map;
25 24  
26 25 import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
27   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
28 26  
29 27 /**
30 28 * 商品 SPU Convert
... ... @@ -91,28 +89,17 @@ public interface ProductSpuConvert {
91 89  
92 90 PageResult<AppProductSpuPageItemRespVO> convertPageForGetSpuPage0(PageResult<ProductSpuDO> page);
93 91  
94   - default AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu, List<ProductSkuDO> skus,
95   - List<ProductPropertyValueDetailRespBO> propertyValues) {
  92 + default AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu, List<ProductSkuDO> skus) {
  93 + // 处理 SPU
96 94 AppProductSpuDetailRespVO spuVO = convertForGetSpuDetail(spu)
97   - .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0));
  95 + .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0))
  96 + .setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
  97 + // 处理 SKU
98 98 spuVO.setSkus(convertListForGetSpuDetail(skus));
99   - // 处理商品属性
100   - Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
101   - for (int i = 0; i < skus.size(); i++) {
102   - List<ProductSkuDO.Property> properties = skus.get(i).getProperties();
103   - if (CollUtil.isEmpty(properties)) {
104   - continue;
105   - }
106   - AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
107   - sku.setProperties(new ArrayList<>(properties.size()));
108   - // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
109   - properties.forEach(property -> {
110   - ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
111   - if (propertyValue == null) {
112   - return;
113   - }
114   - sku.getProperties().add(convertForGetSpuDetail(propertyValue));
115   - });
  99 + // 计算 vip 价格 TODO 芋艿:临时的逻辑,等 vip 支持后
  100 + if (true) {
  101 + spuVO.setVipPrice((int) (spuVO.getPrice() * 0.9));
  102 + spuVO.getSkus().forEach(sku -> sku.setVipPrice((int) (sku.getPrice() * 0.9)));
116 103 }
117 104 return spuVO;
118 105 }
... ... @@ -121,8 +108,6 @@ public interface ProductSpuConvert {
121 108  
122 109 List<AppProductSpuDetailRespVO.Sku> convertListForGetSpuDetail(List<ProductSkuDO> skus);
123 110  
124   - AppProductPropertyValueDetailRespVO convertForGetSpuDetail(ProductPropertyValueDetailRespBO propertyValue);
125   -
126 111 default ProductSpuDetailRespVO convertForSpuDetailRespVO(ProductSpuDO spu, List<ProductSkuDO> skus) {
127 112 ProductSpuDetailRespVO productSpuDetailRespVO = convert03(spu);
128 113 // skus 为空直接返回
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
1 1 package cn.iocoder.yudao.module.product.dal.dataobject.property;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4   -import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
5 4 import com.baomidou.mybatisplus.annotation.KeySequence;
6 5 import com.baomidou.mybatisplus.annotation.TableId;
7 6 import com.baomidou.mybatisplus.annotation.TableName;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
1 1 package cn.iocoder.yudao.module.product.dal.dataobject.property;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4   -import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
5 4 import com.baomidou.mybatisplus.annotation.KeySequence;
6 5 import com.baomidou.mybatisplus.annotation.TableId;
7 6 import com.baomidou.mybatisplus.annotation.TableName;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
... ... @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
17 17 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
18 18 import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
19 19 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
  20 +import com.google.common.collect.Maps;
20 21 import org.springframework.context.annotation.Lazy;
21 22 import org.springframework.stereotype.Service;
22 23 import org.springframework.transaction.annotation.Transactional;
... ... @@ -238,17 +239,22 @@ public class ProductSpuServiceImpl implements ProductSpuService {
238 239  
239 240 @Override
240 241 public Map<Integer, Long> getTabsCount() {
241   - Map<Integer, Long> counts = new HashMap<>(5);
  242 + Map<Integer, Long> counts = Maps.newLinkedHashMapWithExpectedSize(5);
242 243 // 查询销售中的商品数量
243   - counts.put(ProductSpuPageReqVO.FOR_SALE, productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
  244 + counts.put(ProductSpuPageReqVO.FOR_SALE,
  245 + productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
244 246 // 查询仓库中的商品数量
245   - counts.put(ProductSpuPageReqVO.IN_WAREHOUSE, productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()));
  247 + counts.put(ProductSpuPageReqVO.IN_WAREHOUSE,
  248 + productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()));
246 249 // 查询售空的商品数量
247   - counts.put(ProductSpuPageReqVO.SOLD_OUT, productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
  250 + counts.put(ProductSpuPageReqVO.SOLD_OUT,
  251 + productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
248 252 // 查询触发警戒库存的商品数量
249   - counts.put(ProductSpuPageReqVO.ALERT_STOCK, productSpuMapper.selectCount());
  253 + counts.put(ProductSpuPageReqVO.ALERT_STOCK,
  254 + productSpuMapper.selectCount());
250 255 // 查询回收站中的商品数量
251   - counts.put(ProductSpuPageReqVO.RECYCLE_BIN, productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
  256 + counts.put(ProductSpuPageReqVO.RECYCLE_BIN,
  257 + productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
252 258 return counts;
253 259 }
254 260  
... ...