fix: 完善商品管理

This commit is contained in:
puhui999 2023-05-31 16:39:43 +08:00
parent 35daee84e7
commit e86214015d
15 changed files with 96 additions and 99 deletions

View File

@ -7,22 +7,6 @@ package cn.iocoder.yudao.module.product.enums;
*/
public interface ProductConstants {
// TODO @puhui999这个变量可以放到 CategoryDO 的实体里
/**
* 父分类编号 - 根分类
*/
Long PARENT_ID_NULL = 0L;
/**
* 限定分类层级
*/
int CATEGORY_LEVEL = 2;
// TODO @puhui999这个变量必要项不大哈
/**
* SPU 分页 tab 个数
*/
int SPU_TAB_COUNTS = 5;
/**
* 警戒库存 TODO 警戒库存暂时为 10后期需要使用常量或者数据库配置替换
*/

View File

@ -1,40 +0,0 @@
package cn.iocoder.yudao.module.product.enums.spu;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
// TODO @puhui999这种非关键的枚举要不直接写在 ProductSpuPageReqVO 类似 public static final Integer TAB_TYPE_FOR_SALE = 0; // 出售中商品
/**
* 商品 spu Tabs 标签枚举类型
*
* @author HUIHUI
*/
@Getter
@AllArgsConstructor
public enum ProductSpuPageTabEnum implements IntArrayValuable {
FOR_SALE(0,"出售中商品"),
IN_WAREHOUSE(1,"仓库中商品"),
SOLD_OUT(2,"已售空商品"),
ALERT_STOCK(3,"警戒库存"),
RECYCLE_BIN(4,"商品回收站");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuPageTabEnum::getType).toArray();
/**
* 状态
*/
private final Integer type;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -1,7 +1,5 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -12,6 +10,11 @@ import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的")
@Data
@NoArgsConstructor
@ -22,7 +25,6 @@ public class ProductSpuExportReqVO {
private String name;
@Schema(description = "前端请求的tab类型", example = "1")
@InEnum(ProductSpuPageTabEnum.class)
private Integer tabType;
@Schema(description = "商品分类编号", example = "100")

View File

@ -2,14 +2,12 @@ package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ -25,11 +23,35 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@ToString(callSuper = true)
public class ProductSpuPageReqVO extends PageParam {
/**
* 出售中商品
*/
public static final Integer FOR_SALE = 0;
/**
* 仓库中商品
*/
public static final Integer IN_WAREHOUSE = 1;
/**
* 已售空商品
*/
public static final Integer SOLD_OUT = 2;
/**
* 警戒库存
*/
public static final Integer ALERT_STOCK = 3;
/**
* 商品回收站
*/
public static final Integer RECYCLE_BIN = 4;
@Schema(description = "商品名称", example = "清凉小短袖")
private String name;
@Schema(description = "前端请求的tab类型", required = true, example = "1")
@InEnum(ProductSpuPageTabEnum.class)
private Integer tabType;
@Schema(description = "商品分类编号", example = "1")

View File

@ -9,7 +9,7 @@ import java.time.LocalDateTime;
/**
* 商品 SPU Response VO
* TODO 移除ProductSpuPageRespVO相关应用跟换为ProductSpuRespVO已继承ProductSpuBaseVO 补全表格展示所需属性
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU Response VO")

View File

@ -19,6 +19,16 @@ import lombok.*;
@NoArgsConstructor
@AllArgsConstructor
public class ProductCategoryDO extends BaseDO {
/**
* 父分类编号 - 根分类
*/
public static final Long PARENT_ID_NULL = 0L;
/**
* 限定分类层级
*/
public static final int CATEGORY_LEVEL = 2;
/**
* 分类编号
*/

View File

@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReq
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.enums.ProductConstants;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
@ -119,25 +118,25 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
*/
static void appendTabQuery(Integer tabType, LambdaQueryWrapperX<ProductSpuDO> queryWrapper) {
// 出售中商品
if (ObjectUtil.equals(ProductSpuPageTabEnum.FOR_SALE.getType(), tabType)) {
if (ObjectUtil.equals(ProductSpuPageReqVO.FOR_SALE, tabType)) {
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus());
}
// 仓储中商品
if (ObjectUtil.equals(ProductSpuPageTabEnum.IN_WAREHOUSE.getType(), tabType)) {
if (ObjectUtil.equals(ProductSpuPageReqVO.IN_WAREHOUSE, tabType)) {
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus());
}
// 已售空商品
if (ObjectUtil.equals(ProductSpuPageTabEnum.SOLD_OUT.getType(), tabType)) {
if (ObjectUtil.equals(ProductSpuPageReqVO.SOLD_OUT, tabType)) {
queryWrapper.eqIfPresent(ProductSpuDO::getStock, 0);
}
// 警戒库存
if (ObjectUtil.equals(ProductSpuPageTabEnum.ALERT_STOCK.getType(), tabType)) {
if (ObjectUtil.equals(ProductSpuPageReqVO.ALERT_STOCK, tabType)) {
queryWrapper.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK)
// 如果库存触发警戒库存且状态为回收站的话则不在警戒库存列表展示
.notIn(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus());
}
// 回收站
if (ObjectUtil.equals(ProductSpuPageTabEnum.RECYCLE_BIN.getType(), tabType)) {
if (ObjectUtil.equals(ProductSpuPageReqVO.RECYCLE_BIN, tabType)) {
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus());
}
}

View File

@ -16,6 +16,7 @@ import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.PARENT_ID_NULL;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
/**
@ -69,7 +70,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
private void validateParentProductCategory(Long id) {
// 如果是根分类无需验证
if (Objects.equals(id, ProductConstants.PARENT_ID_NULL)) {
if (Objects.equals(id, PARENT_ID_NULL)) {
return;
}
// 父分类不存在
@ -78,7 +79,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
throw exception(CATEGORY_PARENT_NOT_EXISTS);
}
// 父分类不能是二级分类
if (!Objects.equals(category.getParentId(), ProductConstants.PARENT_ID_NULL)) {
if (!Objects.equals(category.getParentId(), PARENT_ID_NULL)) {
throw exception(CATEGORY_PARENT_NOT_FIRST_LEVEL);
}
}
@ -108,17 +109,16 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
@Override
public Integer getCategoryLevel(Long id) {
if (Objects.equals(id, ProductConstants.PARENT_ID_NULL)) {
if (Objects.equals(id, PARENT_ID_NULL)) {
return 0;
}
// TODO @puhui999for 的原因是因为避免脏数据导致可能的死循环一般不会超过 100 层哈
int level = 1;
// fix: 循环次数不确定改为while循环
while (true){
// for 的原因是因为避免脏数据导致可能的死循环一般不会超过 100 层哈
for (int i = 0; i < 100; i++) {
ProductCategoryDO category = productCategoryMapper.selectById(id);
// 如果没有父节点break 结束
if (category == null
|| Objects.equals(category.getParentId(), ProductConstants.PARENT_ID_NULL)) {
|| Objects.equals(category.getParentId(), PARENT_ID_NULL)) {
break;
}
// 继续递归父节点

View File

@ -14,7 +14,6 @@ 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.ProductConstants;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
@ -29,6 +28,7 @@ import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.CATEGORY_LEVEL;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
/**
@ -129,7 +129,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
private void validateCategory(Long id) {
categoryService.validateCategory(id);
// 校验层级
if (categoryService.getCategoryLevel(id) != ProductConstants.CATEGORY_LEVEL) {
if (categoryService.getCategoryLevel(id) < CATEGORY_LEVEL) {
throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR);
}
}
@ -237,17 +237,17 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Override
public Map<Integer, Long> getTabsCount() {
Map<Integer, Long> counts = new HashMap<>(ProductConstants.SPU_TAB_COUNTS);
Map<Integer, Long> counts = new HashMap<>(5);
// 查询销售中的商品数量
counts.put(ProductSpuPageTabEnum.FOR_SALE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
counts.put(ProductSpuPageReqVO.FOR_SALE, productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
// 查询仓库中的商品数量
counts.put(ProductSpuPageTabEnum.IN_WAREHOUSE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()));
counts.put(ProductSpuPageReqVO.IN_WAREHOUSE, productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus()));
// 查询售空的商品数量
counts.put(ProductSpuPageTabEnum.SOLD_OUT.getType(), productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
counts.put(ProductSpuPageReqVO.SOLD_OUT, productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
// 查询触发警戒库存的商品数量
counts.put(ProductSpuPageTabEnum.ALERT_STOCK.getType(), productSpuMapper.selectCount());
counts.put(ProductSpuPageReqVO.ALERT_STOCK, productSpuMapper.selectCount());
// 查询回收站中的商品数量
counts.put(ProductSpuPageTabEnum.RECYCLE_BIN.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
counts.put(ProductSpuPageReqVO.RECYCLE_BIN, productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
return counts;
}

View File

@ -18,9 +18,8 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.PARENT_ID_NULL;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
import static cn.iocoder.yudao.module.product.enums.ProductConstants.PARENT_ID_NULL;
import static org.junit.jupiter.api.Assertions.*;
/**

View File

@ -14,7 +14,6 @@ import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateR
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
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.ProductSpuPageTabEnum;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import cn.iocoder.yudao.module.product.service.brand.ProductBrandServiceImpl;
import cn.iocoder.yudao.module.product.service.category.ProductCategoryServiceImpl;
@ -318,7 +317,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
productSpuMapper.insertBatch(createReqVOs);
// 调用
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.ALERT_STOCK.getType());
productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK);
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
@ -366,7 +365,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
productSpuMapper.insertBatch(createReqVOs);
// 调用
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.ALERT_STOCK.getType());
productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK);
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
assertEquals(createReqVOs.size(), spuPage.getTotal());
}
@ -407,11 +406,11 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
// 调用
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
// 查询条件 按需打开
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.ALERT_STOCK.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.RECYCLE_BIN.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.FOR_SALE.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.IN_WAREHOUSE.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageTabEnum.SOLD_OUT.getType());
//productSpuPageReqVO.setTabType(ProductSpuPageReqVO.ALERT_STOCK);
//productSpuPageReqVO.setTabType(ProductSpuPageReqVO.RECYCLE_BIN);
//productSpuPageReqVO.setTabType(ProductSpuPageReqVO.FOR_SALE);
//productSpuPageReqVO.setTabType(ProductSpuPageReqVO.IN_WAREHOUSE);
//productSpuPageReqVO.setTabType(ProductSpuPageReqVO.SOLD_OUT);
//productSpuPageReqVO.setName(createReqVO.getName());
//productSpuPageReqVO.setCategoryId(createReqVO.getCategoryId());

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
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.trade.controller.admin.delivery.vo.expresstemplate.*;
@ -71,6 +72,15 @@ public class DeliveryExpressTemplateController {
return success(DeliveryExpressTemplateConvert.INSTANCE.convertList(list));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取快递模版精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<DeliveryExpressTemplateSimpleRespVO>> getSimpleTemplateList() {
// 获取运费模版列表只要开启状态的
List<DeliveryExpressTemplateDO> list = deliveryExpressTemplateService.getDeliveryExpressTemplateList();
// 排序后返回给前端
return success(DeliveryExpressTemplateConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@Operation(summary = "获得快递运费模板分页")
@PreAuthorize("@ss.hasPermission('trade:delivery:express-template:query')")

View File

@ -2,19 +2,19 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstempla
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
// TODO @jasonsimplae 是不是不用继承 DeliveryExpressTemplateBaseVO直接 id name 属性就够了
@Schema(description = "管理后台 - 快递运费模板 精简 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplateSimpleRespVO extends DeliveryExpressTemplateBaseVO {
public class DeliveryExpressTemplateSimpleRespVO {
@Schema(description = "编号,自增", required = true, example = "371")
private Long id;
@Schema(description = "创建时间", required = true)
private LocalDateTime createTime;
@Schema(description = "模板名称", required = true, example = "王五")
private String name;
}

View File

@ -56,6 +56,13 @@ public interface DeliveryExpressTemplateService {
*/
List<DeliveryExpressTemplateDO> getDeliveryExpressTemplateList(Collection<Long> ids);
/**
* 获得快递运费模板列表
*
* @return 快递运费模板列表
*/
List<DeliveryExpressTemplateDO> getDeliveryExpressTemplateList();
/**
* 获得快递运费模板分页
*

View File

@ -197,6 +197,11 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla
return expressTemplateMapper.selectBatchIds(ids);
}
@Override
public List<DeliveryExpressTemplateDO> getDeliveryExpressTemplateList() {
return expressTemplateMapper.selectList();
}
@Override
public PageResult<DeliveryExpressTemplateDO> getDeliveryExpressTemplatePage(DeliveryExpressTemplatePageReqVO pageReqVO) {
return expressTemplateMapper.selectPage(pageReqVO);