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,6 +58,11 @@ public class DictFrameworkUtils {
58 } 58 }
59 59
60 @SneakyThrows 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 public static String getDictDataLabel(String dictType, String value) { 66 public static String getDictDataLabel(String dictType, String value) {
62 return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, value)).getLabel(); 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,10 +35,9 @@
35 <groupId>cn.iocoder.boot</groupId> 35 <groupId>cn.iocoder.boot</groupId>
36 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId> 36 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
37 </dependency> 37 </dependency>
38 - <!-- TODO 芋艿:是不是可以去掉这个依赖呀? -->  
39 <dependency> 38 <dependency>
40 <groupId>cn.iocoder.boot</groupId> 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 </dependency> 41 </dependency>
43 42
44 <!-- Web 相关 --> 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,13 +5,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; 5 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
6 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO; 6 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
7 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; 7 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
8 -import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;  
9 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; 8 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
10 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 9 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
11 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 10 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
12 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; 11 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
13 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; 12 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
14 -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;  
15 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 13 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
16 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; 14 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
17 import io.swagger.v3.oas.annotations.Operation; 15 import io.swagger.v3.oas.annotations.Operation;
@@ -67,11 +65,8 @@ public class AppProductSpuController { @@ -67,11 +65,8 @@ public class AppProductSpuController {
67 65
68 // 查询商品 SKU 66 // 查询商品 SKU
69 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId()); 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,6 +36,9 @@ public class AppProductSpuDetailRespVO {
36 @Schema(description = "商品视频", required = true) 36 @Schema(description = "商品视频", required = true)
37 private String videoUrl; 37 private String videoUrl;
38 38
  39 + @Schema(description = "单位名", required = true, example = "个")
  40 + private String unitName;
  41 +
39 // ========== SKU 相关字段 ========= 42 // ========== SKU 相关字段 =========
40 43
41 @Schema(description = "规格类型", required = true, example = "true") 44 @Schema(description = "规格类型", required = true, example = "true")
@@ -47,6 +50,9 @@ public class AppProductSpuDetailRespVO { @@ -47,6 +50,9 @@ public class AppProductSpuDetailRespVO {
47 @Schema(description = "市场价,单位使用:分", required = true, example = "1024") 50 @Schema(description = "市场价,单位使用:分", required = true, example = "1024")
48 private Integer marketPrice; 51 private Integer marketPrice;
49 52
  53 + @Schema(description = "VIP 价格,单位使用:分", required = true, example = "968") // 通过会员等级,计算出折扣后价格
  54 + private Integer vipPrice;
  55 +
50 @Schema(description = "库存", required = true, example = "666") 56 @Schema(description = "库存", required = true, example = "666")
51 private Integer stock; 57 private Integer stock;
52 58
@@ -78,6 +84,9 @@ public class AppProductSpuDetailRespVO { @@ -78,6 +84,9 @@ public class AppProductSpuDetailRespVO {
78 @Schema(description = "市场价,单位使用:分", required = true, example = "1024") 84 @Schema(description = "市场价,单位使用:分", required = true, example = "1024")
79 private Integer marketPrice; 85 private Integer marketPrice;
80 86
  87 + @Schema(description = "VIP 价格,单位使用:分", required = true, example = "968") // 通过会员等级,计算出折扣后价格
  88 + private Integer vipPrice;
  89 +
81 @Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png") 90 @Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
82 private String picUrl; 91 private String picUrl;
83 92
@@ -89,6 +98,7 @@ public class AppProductSpuDetailRespVO { @@ -89,6 +98,7 @@ public class AppProductSpuDetailRespVO {
89 98
90 @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米 99 @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米
91 private Double volume; 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,16 +68,6 @@ public interface ProductSkuConvert {
68 return spuIdAndStockMap; 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 default String buildPropertyKey(ProductSkuDO bean) { 71 default String buildPropertyKey(ProductSkuDO bean) {
82 if (CollUtil.isEmpty(bean.getProperties())) { 72 if (CollUtil.isEmpty(bean.getProperties())) {
83 return StrUtil.EMPTY; 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,17 +3,17 @@ package cn.iocoder.yudao.module.product.convert.spu;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
6 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 7 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
7 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; 8 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
8 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; 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 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; 10 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
11 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO; 11 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
12 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; 12 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
13 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; 13 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
14 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 14 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
15 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 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 import org.mapstruct.Mapper; 17 import org.mapstruct.Mapper;
18 import org.mapstruct.Mapping; 18 import org.mapstruct.Mapping;
19 import org.mapstruct.Named; 19 import org.mapstruct.Named;
@@ -21,10 +21,8 @@ import org.mapstruct.factory.Mappers; @@ -21,10 +21,8 @@ import org.mapstruct.factory.Mappers;
21 21
22 import java.util.ArrayList; 22 import java.util.ArrayList;
23 import java.util.List; 23 import java.util.List;
24 -import java.util.Map;  
25 24
26 import static cn.hutool.core.util.ObjectUtil.defaultIfNull; 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 * 商品 SPU Convert 28 * 商品 SPU Convert
@@ -91,28 +89,17 @@ public interface ProductSpuConvert { @@ -91,28 +89,17 @@ public interface ProductSpuConvert {
91 89
92 PageResult<AppProductSpuPageItemRespVO> convertPageForGetSpuPage0(PageResult<ProductSpuDO> page); 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 AppProductSpuDetailRespVO spuVO = convertForGetSpuDetail(spu) 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 spuVO.setSkus(convertListForGetSpuDetail(skus)); 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 return spuVO; 104 return spuVO;
118 } 105 }
@@ -121,8 +108,6 @@ public interface ProductSpuConvert { @@ -121,8 +108,6 @@ public interface ProductSpuConvert {
121 108
122 List<AppProductSpuDetailRespVO.Sku> convertListForGetSpuDetail(List<ProductSkuDO> skus); 109 List<AppProductSpuDetailRespVO.Sku> convertListForGetSpuDetail(List<ProductSkuDO> skus);
123 110
124 - AppProductPropertyValueDetailRespVO convertForGetSpuDetail(ProductPropertyValueDetailRespBO propertyValue);  
125 -  
126 default ProductSpuDetailRespVO convertForSpuDetailRespVO(ProductSpuDO spu, List<ProductSkuDO> skus) { 111 default ProductSpuDetailRespVO convertForSpuDetailRespVO(ProductSpuDO spu, List<ProductSkuDO> skus) {
127 ProductSpuDetailRespVO productSpuDetailRespVO = convert03(spu); 112 ProductSpuDetailRespVO productSpuDetailRespVO = convert03(spu);
128 // skus 为空直接返回 113 // skus 为空直接返回
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
1 package cn.iocoder.yudao.module.product.dal.dataobject.property; 1 package cn.iocoder.yudao.module.product.dal.dataobject.property;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 -import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;  
5 import com.baomidou.mybatisplus.annotation.KeySequence; 4 import com.baomidou.mybatisplus.annotation.KeySequence;
6 import com.baomidou.mybatisplus.annotation.TableId; 5 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 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 package cn.iocoder.yudao.module.product.dal.dataobject.property; 1 package cn.iocoder.yudao.module.product.dal.dataobject.property;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 -import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;  
5 import com.baomidou.mybatisplus.annotation.KeySequence; 4 import com.baomidou.mybatisplus.annotation.KeySequence;
6 import com.baomidou.mybatisplus.annotation.TableId; 5 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 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,6 +17,7 @@ import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
17 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; 17 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
18 import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; 18 import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
19 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 19 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
  20 +import com.google.common.collect.Maps;
20 import org.springframework.context.annotation.Lazy; 21 import org.springframework.context.annotation.Lazy;
21 import org.springframework.stereotype.Service; 22 import org.springframework.stereotype.Service;
22 import org.springframework.transaction.annotation.Transactional; 23 import org.springframework.transaction.annotation.Transactional;
@@ -238,17 +239,22 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -238,17 +239,22 @@ public class ProductSpuServiceImpl implements ProductSpuService {
238 239
239 @Override 240 @Override
240 public Map<Integer, Long> getTabsCount() { 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 return counts; 258 return counts;
253 } 259 }
254 260