product:优化管理后台相关的接口

area:增加地区列表界面
This commit is contained in:
YunaiV
2022-12-23 18:47:59 +08:00
parent 92dde0b48b
commit 7a4a6a3046
31 changed files with 401 additions and 339 deletions

View File

@@ -1,39 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import java.util.List;
// TODO 芋艿:看看怎么删除
@ApiModel("管理后台 - 商品属性详情展示 Request VO")
@Data
@ToString(callSuper = true)
public class ProductPropertyViewRespVO {
@ApiModelProperty(value = "属性项 id", example = "1")
public Long propertyId;
@ApiModelProperty(value = "属性项的名字", example = "内存")
public String name;
@ApiModelProperty(value = "属性值数组")
public List<Tuple2> propertyValues;
@Data
@ApiModel(value = "属性值元组")
public static class Tuple2 {
private final long id;
private final String name;
public Tuple2(Long id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel("管理后台 - 商品属性值的明细 Response VO")
@Data
public class ProductPropertyValueDetailRespVO {
@ApiModelProperty(value = "属性的编号", required = true, example = "1")
private Long propertyId;
@ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
private String propertyName;
@ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
private Long valueId;
@ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
private String valueName;
}

View File

@@ -0,0 +1,4 @@
### 获得商品 SPU 明细
GET {{baseUrl}}/product/spu/get-detail?id=4
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}

View File

@@ -3,8 +3,13 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -15,10 +20,11 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
@Api(tags = "管理后台 - 商品 SPU")
@RestController
@@ -28,6 +34,10 @@ public class ProductSpuController {
@Resource
private ProductSpuService productSpuService;
@Resource
private ProductSkuService productSkuService;
@Resource
private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
@ApiOperation("创建商品 SPU")
@@ -53,31 +63,24 @@ public class ProductSpuController {
return success(true);
}
// TODO 芋艿:修改接口
@GetMapping("/get/detail")
@ApiOperation("获得商品 SPU")
@GetMapping("/get-detail")
@ApiOperation("获得商品 SPU 明细")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<ProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
return success(productSpuService.getSpuDetail(id));
}
// 获得商品 SPU
ProductSpuDO spu = productSpuService.getSpu(id);
if (spu == null) {
throw exception(SPU_NOT_EXISTS);
}
@GetMapping("/get")
@ApiOperation("获得商品 SPU")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<ProductSpuDO> getSpu(@RequestParam("id") Long id) {
return success(productSpuService.getSpu(id));
}
@GetMapping("/list")
@ApiOperation("获得商品 SPU 列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<List<ProductSpuDO>> getSpuList(@RequestParam("ids") Collection<Long> ids) {
List<ProductSpuDO> list = productSpuService.getSpuList(ids);
return success(ProductSpuConvert.INSTANCE.convertList(list));
// 查询商品 SKU
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), null);
// 查询商品属性
List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
.getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
// 拼接
return success(ProductSpuConvert.INSTANCE.convert03(spu, skus, propertyValues));
}
@GetMapping("/get-simple-list")
@@ -92,7 +95,7 @@ public class ProductSpuController {
@ApiOperation("获得商品 SPU 分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<PageResult<ProductSpuRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
return success(productSpuService.getSpuPage(pageVO));
return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
}
}

View File

@@ -1,52 +1,27 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
import java.util.List;
@ApiModel(value = "管理后台 - 商品 SPU 详细 Response VO", description = "包括关联的 SKU 等信息")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
@ApiModelProperty(value = "主键", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
public class ProductSpuDetailRespVO extends ProductSpuRespVO {
// ========== SKU 相关字段 =========
@ApiModelProperty(value = "库存", required = true, example = "true")
private Integer totalStock;
@ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
private Integer minPrice;
@ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
private Integer maxPrice;
@ApiModelProperty(value = "商品销量", example = "1024")
private Integer salesCount;
/**
* SKU 数组
*/
private List<Sku> skus;
// ========== 统计相关字段 =========
@ApiModelProperty(value = "点击量", example = "1024")
private Integer clickCount;
@ApiModel(value = "管理后台 - 商品 SKU 详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@@ -56,29 +31,8 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
/**
* 属性数组
*/
private List<ProductSpuDetailRespVO.Property> properties;
private List<ProductPropertyValueDetailRespVO> properties;
}
@ApiModel(value = "管理后台 - 商品属性的详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public static class Property extends ProductSkuBaseVO.Property {
@ApiModelProperty(value = "属性项的名字", required = true, example = "颜色")
private String propertyName;
@ApiModelProperty(value = "属性值的名称", required = true, example = "蓝色")
private String valueName;
}
@ApiModelProperty(value = "分类 id 数组,一直递归到一级父节点", example = "4")
private Long categoryId;
// TODO @芋艿:在瞅瞅~
@ApiModelProperty(value = "属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]")
private List<ProductPropertyViewRespVO> productPropertyViews;
}

View File

@@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuDetailRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageItemRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
@@ -48,7 +48,7 @@ public class AppProductSpuController {
@GetMapping("/page")
@ApiOperation("获得商品 SPU 分页")
public CommonResult<PageResult<AppSpuPageItemRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
public CommonResult<PageResult<AppProductSpuPageItemRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO, ProductSpuStatusEnum.ENABLE.getStatus());
return success(ProductSpuConvert.INSTANCE.convertPage02(pageResult));
}
@@ -56,7 +56,7 @@ public class AppProductSpuController {
@GetMapping("/get-detail")
@ApiOperation("获得商品 SPU 明细")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
public CommonResult<AppSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
public CommonResult<AppProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
// 获得商品 SPU
ProductSpuDO spu = productSpuService.getSpu(id);
if (spu == null) {

View File

@@ -9,7 +9,7 @@ import java.util.List;
@ApiModel("用户 App - 商品 SPU 明细 Response VO")
@Data
public class AppSpuDetailRespVO {
public class AppProductSpuDetailRespVO {
@ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
private Long id;

View File

@@ -10,7 +10,7 @@ import java.util.List;
@ApiModel("用户 App - 商品 SPU 分页项 Response VO")
@Data
public class AppSpuPageItemRespVO {
public class AppProductSpuPageItemRespVO {
@ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
private Long id;

View File

@@ -3,11 +3,12 @@ package cn.iocoder.yudao.module.product.convert.spu;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuDetailRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageItemRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
@@ -45,9 +46,9 @@ public interface ProductSpuConvert {
List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
default AppSpuDetailRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus,
List<ProductPropertyValueDetailRespBO> propertyValues) {
AppSpuDetailRespVO spuVO = convert02(spu)
default AppProductSpuDetailRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus,
List<ProductPropertyValueDetailRespBO> propertyValues) {
AppProductSpuDetailRespVO spuVO = convert02(spu)
.setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0));
spuVO.setSkus(convertList03(skus));
// 处理商品属性
@@ -57,7 +58,7 @@ public interface ProductSpuConvert {
if (CollUtil.isEmpty(properties)) {
continue;
}
AppSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
sku.setProperties(new ArrayList<>(properties.size()));
// 遍历每个 properties设置到 AppSpuDetailRespVO.Sku 中
properties.forEach(property -> {
@@ -70,10 +71,38 @@ public interface ProductSpuConvert {
}
return spuVO;
}
AppSpuDetailRespVO convert02(ProductSpuDO spu);
List<AppSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> skus);
AppProductSpuDetailRespVO convert02(ProductSpuDO spu);
List<AppProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> skus);
AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue);
PageResult<AppSpuPageItemRespVO> convertPage02(PageResult<ProductSpuDO> page);
PageResult<AppProductSpuPageItemRespVO> convertPage02(PageResult<ProductSpuDO> page);
default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List<ProductSkuDO> skus,
List<ProductPropertyValueDetailRespBO> propertyValues) {
ProductSpuDetailRespVO spuVO = convert03(spu);
spuVO.setSkus(convertList04(skus));
// 处理商品属性
Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
for (int i = 0; i < skus.size(); i++) {
List<ProductSkuDO.Property> properties = skus.get(i).getProperties();
if (CollUtil.isEmpty(properties)) {
continue;
}
ProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
sku.setProperties(new ArrayList<>(properties.size()));
// 遍历每个 properties设置到 AppSpuDetailRespVO.Sku 中
properties.forEach(property -> {
ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
if (propertyValue == null) {
return;
}
sku.getProperties().add(convert04(propertyValue));
});
}
return spuVO;
}
ProductSpuDetailRespVO convert03(ProductSpuDO spu);
List<ProductSpuDetailRespVO.Sku> convertList04(List<ProductSkuDO> skus);
ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue);
}

View File

@@ -21,8 +21,7 @@ public interface ProductPropertyMapper extends BaseMapperX<ProductPropertyDO> {
}
default ProductPropertyDO selectByName(String name) {
return selectOne(new LambdaQueryWrapperX<ProductPropertyDO>()
.eqIfPresent(ProductPropertyDO::getName, name));
return selectOne(ProductPropertyDO::getName, name);
}
default List<ProductPropertyDO> selectList(ProductPropertyListReqVO listReqVO) {

View File

@@ -17,6 +17,7 @@ public interface ProductPropertyService {
/**
* 创建属性项
* 注意,如果已经存在该属性项,直接返回它的编号即可
*
* @param createReqVO 创建信息
* @return 编号

View File

@@ -40,9 +40,10 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
@Override
@Transactional(rollbackFor = Exception.class)
public Long createProperty(ProductPropertyCreateReqVO createReqVO) {
// 校验名字重复
if (productPropertyMapper.selectByName(createReqVO.getName()) != null) {
throw exception(PROPERTY_EXISTS);
// 如果已经添加过该属性项,直接返回
ProductPropertyDO dbProperty = productPropertyMapper.selectByName(createReqVO.getName());
if (dbProperty != null) {
return dbProperty.getId();
}
// 插入

View File

@@ -19,6 +19,7 @@ public interface ProductPropertyValueService {
/**
* 创建属性值
* 注意,如果已经存在该属性值,直接返回它的编号即可
*
* @param createReqVO 创建信息
* @return 编号

View File

@@ -42,9 +42,11 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
@Override
public Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO) {
// 校验名字唯一
if (productPropertyValueMapper.selectByName(createReqVO.getPropertyId(), createReqVO.getName()) != null) {
throw exception(PROPERTY_VALUE_EXISTS);
// 如果已经添加过该属性值,直接返回
ProductPropertyValueDO dbValue = productPropertyValueMapper.selectByName(
createReqVO.getPropertyId(), createReqVO.getName());
if (dbValue != null) {
return dbValue.getId();
}
// 新增

View File

@@ -41,14 +41,6 @@ public interface ProductSpuService {
*/
void deleteSpu(Long id);
/**
* 获得商品 SPU 详情
*
* @param id 编号
* @return 商品 SPU
*/
ProductSpuDetailRespVO getSpuDetail(Long id);
/**
* 获得商品 SPU
*
@@ -88,7 +80,7 @@ public interface ProductSpuService {
* @param pageReqVO 分页查询
* @return 商品spu分页
*/
PageResult<ProductSpuRespVO> getSpuPage(ProductSpuPageReqVO pageReqVO);
PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO);
/**
* 获得商品 SPU 分页

View File

@@ -1,27 +1,19 @@
package cn.iocoder.yudao.module.product.service.spu;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@@ -29,8 +21,10 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@@ -49,18 +43,13 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Resource
private ProductSpuMapper productSpuMapper;
@Resource
private ProductCategoryService categoryService;
@Resource
@Lazy // 循环依赖,避免报错
private ProductSkuService productSkuService;
@Resource
private ProductPropertyService productPropertyService;
@Resource
private ProductPropertyValueService productPropertyValueService;
@Resource
private ProductBrandService brandService;
@Resource
private ProductCategoryService categoryService;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -148,46 +137,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
}
}
@Override
// TODO @芋艿:需要再 review 下
public ProductSpuDetailRespVO getSpuDetail(Long id) {
ProductSpuDO spu = productSpuMapper.selectById(id);
ProductSpuDetailRespVO respVO = BeanUtil.copyProperties(spu, ProductSpuDetailRespVO.class);
if (null != spu) {
List<ProductSpuDetailRespVO.Sku> skuReqs = ProductSkuConvert.INSTANCE.convertList03(productSkuService.getSkuListBySpuId(id));
respVO.setSkus(skuReqs);
// 组合 sku 属性
if (spu.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) {
List<ProductSkuRespVO.Property> properties = new ArrayList<>();
for (ProductSpuDetailRespVO.Sku productSkuRespVO : skuReqs) {
properties.addAll(productSkuRespVO.getProperties());
}
Map<Long, List<ProductSkuBaseVO.Property>> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId));
List<ProductPropertyValueDO> propertyValueList = productPropertyValueService.getPropertyValueListByPropertyId(propertyMaps.keySet());
List<ProductPropertyDO> propertyList = productPropertyService.getPropertyList(propertyMaps.keySet());
// 装载组装过后的属性
List<ProductPropertyViewRespVO> productPropertyViews = new ArrayList<>();
propertyList.forEach(p -> {
ProductPropertyViewRespVO productPropertyViewRespVO = new ProductPropertyViewRespVO();
productPropertyViewRespVO.setPropertyId(p.getId());
productPropertyViewRespVO.setName(p.getName());
List<ProductPropertyViewRespVO.Tuple2> propertyValues = new ArrayList<>();
// 转换成map是为了能快速获取
Map<Long, ProductPropertyValueDO> propertyValueMaps = convertMap(propertyValueList, ProductPropertyValueDO::getId);
propertyMaps.get(p.getId()).forEach(pv -> {
ProductPropertyViewRespVO.Tuple2 tuple2 = new ProductPropertyViewRespVO.Tuple2(pv.getValueId(), propertyValueMaps.get(pv.getValueId()).getName());
propertyValues.add(tuple2);
});
productPropertyViewRespVO.setPropertyValues(propertyValues.stream().distinct().collect(Collectors.toList()));
productPropertyViews.add(productPropertyViewRespVO);
});
respVO.setProductPropertyViews(productPropertyViews);
}
}
return respVO;
}
@Override
public ProductSpuDO getSpu(Long id) {
return productSpuMapper.selectById(id);
@@ -203,9 +152,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return productSpuMapper.selectList();
}
// TODO 芋艿:改成 DO 返回
@Override
public PageResult<ProductSpuRespVO> getSpuPage(ProductSpuPageReqVO pageReqVO) {
public PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO) {
// 库存告警的 SPU 编号的集合
Set<Long> alarmStockSpuIds = null;
if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) {
@@ -215,7 +163,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
}
}
// 分页查询
return ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds));
return productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds);
}
@Override

View File

@@ -19,11 +19,12 @@ import java.util.Arrays;
import java.util.List;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
@@ -145,4 +146,26 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
SKU_STOCK_NOT_ENOUGH);
}
@Test
public void testDeleteSku_success() {
// mock 数据
ProductSkuDO dbSku = randomPojo(ProductSkuDO.class);
productSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbSku.getId();
// 调用
productSkuService.deleteSku(id);
// 校验数据不存在了
assertNull(productSkuMapper.selectById(id));
}
@Test
public void testDeleteSku_notExists() {
// 准备参数
Long id = 1L;
// 调用, 并断言异常
assertServiceException(() -> productSkuService.deleteSku(id), SKU_NOT_EXISTS);
}
}

View File

@@ -1,56 +0,0 @@
package cn.iocoder.yudao.module.product.service.sku;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.assertNull;
// TODO 芋艿:整合到 {@link ProductSkuServiceTest} 中
/**
* {@link ProductSkuServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(ProductSkuServiceImpl.class)
@Disabled // TODO 芋艿:临时去掉
public class SkuServiceImplTest extends BaseDbUnitTest {
@Resource
private ProductSkuServiceImpl ProductSkuService;
@Resource
private ProductSkuMapper ProductSkuMapper;
@Test
public void testDeleteSku_success() {
// mock 数据
ProductSkuDO dbSku = randomPojo(ProductSkuDO.class);
ProductSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbSku.getId();
// 调用
ProductSkuService.deleteSku(id);
// 校验数据不存在了
assertNull(ProductSkuMapper.selectById(id));
}
@Test
public void testDeleteSku_notExists() {
// 准备参数
Long id = 1L;
// 调用, 并断言异常
assertServiceException(() -> ProductSkuService.deleteSku(id), SKU_NOT_EXISTS);
}
}

View File

@@ -8,10 +8,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
@@ -148,53 +149,6 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
Assertions.assertNull(productSpuMapper.selectById(createReqVO.getId()));
}
@Test
void getSpuDetail() {
// 准备spu参数
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class, o -> {
o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
});
productSpuMapper.insert(createReqVO);
// 创建两个属性
ArrayList<ProductPropertyRespVO> productPropertyRespVOS = Lists.newArrayList(
randomPojo(ProductPropertyRespVO.class),
randomPojo(ProductPropertyRespVO.class));
// 所有属性值
ArrayList<ProductPropertyValueRespVO> productPropertyValueRespVO = new ArrayList<>();
// 每个属性创建属性值
productPropertyRespVOS.forEach(v -> {
ProductPropertyValueRespVO productPropertyValueRespVO1 = randomPojo(ProductPropertyValueRespVO.class, o -> o.setPropertyId(v.getId()));
productPropertyValueRespVO.add(productPropertyValueRespVO1);
});
// 属性值建立笛卡尔积
Map<Long, List<ProductPropertyValueRespVO>> collect = productPropertyValueRespVO.stream().collect(Collectors.groupingBy(ProductPropertyValueRespVO::getPropertyId));
List<List<ProductPropertyValueRespVO>> lists = cartesianProduct(Lists.newArrayList(collect.values()));
// 准备sku参数
ArrayList<ProductSkuDO> productSkuDOS = Lists.newArrayList();
lists.forEach(pp -> {
List<ProductSkuDO.Property> property = pp.stream().map(ppv -> new ProductSkuDO.Property(ppv.getPropertyId(), ppv.getId())).collect(Collectors.toList());
ProductSkuDO productSkuDO = randomPojo(ProductSkuDO.class, o -> {
o.setProperties(property);
});
productSkuDOS.add(productSkuDO);
});
Mockito.when(productSkuService.getSkuListBySpuId(createReqVO.getId())).thenReturn(productSkuDOS);
// Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO);
// Mockito.when(productPropertyService.getPropertyVOList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS);
//
// 调用
ProductSpuDetailRespVO spuDetail = productSpuService.getSpuDetail(createReqVO.getId());
assertPojoEquals(createReqVO, spuDetail);
}
@Test
void getSpu() {
// 准备参数
@@ -222,7 +176,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
productSpuPageReqVO.setAlarmStock(true);
PageResult<ProductSpuRespVO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<Object> result = PageResult.empty();
Assertions.assertIterableEquals(result.getList(), spuPage.getList());
@@ -271,7 +225,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
// 调用
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
productSpuPageReqVO.setAlarmStock(true);
PageResult<ProductSpuRespVO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds));
Assertions.assertIterableEquals(result.getList(), spuPage.getList());
@@ -323,7 +277,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
productSpuPageReqVO.setCategoryId(categoryId);
PageResult<ProductSpuRespVO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set<Long>) null));
assertEquals(result, spuPage);