🔨 CRM:优化产品分类代码的实现

This commit is contained in:
YunaiV 2023-12-06 12:56:44 +08:00
parent c94f71a3df
commit 3678752a61
16 changed files with 143 additions and 188 deletions

View File

@ -1,11 +1,10 @@
package cn.iocoder.yudao.module.crm.controller.admin.product;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryListReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryRespVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryUpdateReqVO;
import cn.iocoder.yudao.module.crm.convert.product.CrmProductCategoryConvert;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryRespVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
import cn.iocoder.yudao.module.crm.service.product.CrmProductCategoryService;
import io.swagger.v3.oas.annotations.Operation;
@ -21,7 +20,7 @@ import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 产品分类")
@Tag(name = "管理后台 - CRM 产品分类")
@RestController
@RequestMapping("/crm/product-category")
@Validated
@ -40,7 +39,7 @@ public class CrmProductCategoryController {
@PutMapping("/update")
@Operation(summary = "更新产品分类")
@PreAuthorize("@ss.hasPermission('crm:product-category:update')")
public CommonResult<Boolean> updateProductCategory(@Valid @RequestBody CrmProductCategoryUpdateReqVO updateReqVO) {
public CommonResult<Boolean> updateProductCategory(@Valid @RequestBody CrmProductCategoryCreateReqVO updateReqVO) {
productCategoryService.updateProductCategory(updateReqVO);
return success(true);
}
@ -59,16 +58,16 @@ public class CrmProductCategoryController {
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('crm:product-category:query')")
public CommonResult<CrmProductCategoryRespVO> getProductCategory(@RequestParam("id") Long id) {
CrmProductCategoryDO productCategory = productCategoryService.getProductCategory(id);
return success(CrmProductCategoryConvert.INSTANCE.convert(productCategory));
CrmProductCategoryDO category = productCategoryService.getProductCategory(id);
return success(BeanUtils.toBean(category, CrmProductCategoryRespVO.class));
}
@GetMapping("/list")
@Operation(summary = "获得产品分类列表")
@PreAuthorize("@ss.hasPermission('crm:product-category:query')")
public CommonResult<List<CrmProductCategoryRespVO>> getProductCategoryList(@Valid CrmProductCategoryListReqVO treeListReqVO) {
List<CrmProductCategoryDO> list = productCategoryService.getProductCategoryList(treeListReqVO);
return success(CrmProductCategoryConvert.INSTANCE.convertList(list));
public CommonResult<List<CrmProductCategoryRespVO>> getProductCategoryList(@Valid CrmProductCategoryListReqVO listReqVO) {
List<CrmProductCategoryDO> list = productCategoryService.getProductCategoryList(listReqVO);
return success(BeanUtils.toBean(list, CrmProductCategoryRespVO.class));
}
}

View File

@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
@ -82,7 +82,13 @@ public class CrmProductController {
@PreAuthorize("@ss.hasPermission('crm:product:query')")
public CommonResult<CrmProductRespVO> getProduct(@RequestParam("id") Long id) {
CrmProductDO product = productService.getProduct(id);
return success(BeanUtils.toBean(product, CrmProductRespVO.class));
if (product == null) {
return success(null);
}
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
SetUtils.asSet( Long.valueOf(product.getCreator()), product.getOwnerUserId()));
CrmProductCategoryDO category = productCategoryService.getProductCategory(product.getCategoryId());
return success(CrmProductConvert.INSTANCE.convert(product, userMap, category));
}
@GetMapping("/page")

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - CRM 产品分类创建/更新 Request VO")
@Data
public class CrmProductCategoryCreateReqVO{
@Schema(description = "分类编号", example = "23902")
private Long id;
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotNull(message = "分类名称不能为空")
private String name;
@Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4680")
@NotNull(message = "父级编号不能为空")
private Long parentId;
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory;
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
@ -6,8 +6,7 @@ import lombok.Data;
import java.time.LocalDateTime;
// TODO 芋艿这个导出最后搞命名应该是按照 ProductExportReqVO 风格
@Schema(description = "管理后台 - 产品分类列表 Request VO")
@Schema(description = "管理后台 - CRM 产品分类列表 Request VO")
@Data
public class CrmProductCategoryListReqVO {

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - CRM 产品分类 Response VO")
@Data
public class CrmProductCategoryRespVO {
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23902")
private Long id;
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
private String name;
@Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4680")
private Long parentId;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -67,4 +67,8 @@ public class CrmProductRespVO {
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("更新时间")
private LocalDateTime updateTime;
}

View File

@ -1,23 +0,0 @@
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 产品分类 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class CrmProductCategoryBaseVO {
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotNull(message = "名称不能为空")
private String name;
@Schema(description = "父级 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "4680")
@NotNull(message = "父级 id 不能为空")
private Long parentId;
}

View File

@ -1,12 +0,0 @@
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "管理后台 - 产品分类创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CrmProductCategoryCreateReqVO extends CrmProductCategoryBaseVO {
}

View File

@ -1,19 +0,0 @@
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 产品分类 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CrmProductCategoryRespVO extends CrmProductCategoryBaseVO {
@Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23902")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 产品分类更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CrmProductCategoryUpdateReqVO extends CrmProductCategoryBaseVO {
@Schema(description = "主键 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23902")
@NotNull(message = "主键 id 不能为空")
private Long id;
}

View File

@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.crm.convert.product;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryRespVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryUpdateReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 产品分类 Convert
*
* @author ZanGe
*/
@Mapper
public interface CrmProductCategoryConvert {
CrmProductCategoryConvert INSTANCE = Mappers.getMapper(CrmProductCategoryConvert.class);
CrmProductCategoryDO convert(CrmProductCategoryCreateReqVO bean);
CrmProductCategoryDO convert(CrmProductCategoryUpdateReqVO bean);
CrmProductCategoryRespVO convert(CrmProductCategoryDO bean);
List<CrmProductCategoryRespVO> convertList(List<CrmProductCategoryDO> list);
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.crm.convert.product;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO;
@ -11,6 +12,7 @@ import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@ -27,14 +29,18 @@ public interface CrmProductConvert {
default List<CrmProductRespVO> convertList(List<CrmProductDO> list,
Map<Long, AdminUserRespDTO> userMap,
List<CrmProductCategoryDO> categoryList) {
List<CrmProductRespVO> voList = BeanUtils.toBean(list, CrmProductRespVO.class);
Map<Long, CrmProductCategoryDO> categoryMap = convertMap(categoryList, CrmProductCategoryDO::getId);
for (CrmProductRespVO vo : voList) {
MapUtils.findAndThen(categoryMap, vo.getCategoryId(), category -> vo.setCategoryName(category.getName()));
MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname()));
MapUtils.findAndThen(userMap, Long.valueOf(vo.getCreator()), user -> vo.setCreatorName(user.getNickname()));
}
return voList;
return CollectionUtils.convertList(list,
product -> convert(product, userMap, categoryMap.get(product.getCategoryId())));
}
default CrmProductRespVO convert(CrmProductDO product,
Map<Long, AdminUserRespDTO> userMap, CrmProductCategoryDO category) {
CrmProductRespVO productVO = BeanUtils.toBean(product, CrmProductRespVO.class);
Optional.ofNullable(category).ifPresent(c -> productVO.setCategoryName(c.getName()));
MapUtils.findAndThen(userMap, productVO.getOwnerUserId(), user -> productVO.setOwnerUserName(user.getNickname()));
MapUtils.findAndThen(userMap, Long.valueOf(productVO.getCreator()), user -> productVO.setCreatorName(user.getNickname()));
return productVO;
}
}

View File

@ -31,17 +31,18 @@ public class CrmProductCategoryDO extends BaseDO {
public static final int CATEGORY_LEVEL = 2;
/**
* 主键id
* 分类编号
*/
@TableId
private Long id;
/**
* 名称
* 分类名称
*/
private String name;
/**
* 父级 id
* // TODO @zange-ok这个要写下关联 CategoryDO id 字段参考下别的模块哈
* 父级编号
*
* 关联 {@link CrmProductCategoryDO#getId()}
*/
private Long parentId;

View File

@ -2,32 +2,33 @@ package cn.iocoder.yudao.module.crm.dal.mysql.product;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryListReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 产品分类 Mapper
* CRM 产品分类 Mapper
*
* @author ZanGe
*/
@Mapper
public interface CrmProductCategoryMapper extends BaseMapperX<CrmProductCategoryDO> {
default List<CrmProductCategoryDO> selectList(CrmProductCategoryListReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<CrmProductCategoryDO>()
.likeIfPresent(CrmProductCategoryDO::getName, reqVO.getName())
.eqIfPresent(CrmProductCategoryDO::getParentId, reqVO.getParentId())
.orderByDesc(CrmProductCategoryDO::getId));
}
default CrmProductCategoryDO selectByName(String name) {
return selectOne(CrmProductCategoryDO::getName, name);
default CrmProductCategoryDO selectByParentIdAndName(Long parentId, String name) {
return selectOne(CrmProductCategoryDO::getParentId, parentId, CrmProductCategoryDO::getName, name);
}
default Long selectCountByParentId(Long parentId) {
return selectCount(CrmProductCategoryDO::getParentId, parentId);
}
}

View File

@ -1,8 +1,7 @@
package cn.iocoder.yudao.module.crm.service.product;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryListReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryUpdateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
import javax.validation.Valid;
@ -29,7 +28,7 @@ public interface CrmProductCategoryService {
*
* @param updateReqVO 更新信息
*/
void updateProductCategory(@Valid CrmProductCategoryUpdateReqVO updateReqVO);
void updateProductCategory(@Valid CrmProductCategoryCreateReqVO updateReqVO);
/**
* 删除产品分类

View File

@ -1,10 +1,8 @@
package cn.iocoder.yudao.module.crm.service.product;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryListReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.productcategory.CrmProductCategoryUpdateReqVO;
import cn.iocoder.yudao.module.crm.convert.product.CrmProductCategoryConvert;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
import cn.iocoder.yudao.module.crm.dal.mysql.product.CrmProductCategoryMapper;
import org.springframework.context.annotation.Lazy;
@ -21,7 +19,7 @@ import static cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCateg
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
/**
* 产品分类 Service 实现类
* CRM 产品分类 Service 实现类
*
* @author ZanGe
*/
@ -38,56 +36,29 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService
@Override
public Long createProductCategory(CrmProductCategoryCreateReqVO createReqVO) {
// TODO zange参考 mall ProductCategoryServiceImpl 补充下必要的参数校验
// 校验父分类存在
// 1.1 校验父分类存在
validateParentProductCategory(createReqVO.getParentId());
// 分类名称是否存在
CrmProductCategoryDO dbProductCategory = productCategoryMapper.selectByName(createReqVO.getName());
if (dbProductCategory != null) {
return dbProductCategory.getId();
}
// 插入
CrmProductCategoryDO productCategory = CrmProductCategoryConvert.INSTANCE.convert(createReqVO);
productCategoryMapper.insert(productCategory);
// 返回
return productCategory.getId();
// 1.2 分类名称是否存在
validateProductNameExists(null, createReqVO.getParentId(), createReqVO.getName());
// 2. 插入
CrmProductCategoryDO category = BeanUtils.toBean(createReqVO, CrmProductCategoryDO.class);
productCategoryMapper.insert(category);
return category.getId();
}
@Override
public void updateProductCategory(CrmProductCategoryUpdateReqVO updateReqVO) {
// TODO zange参考 mall ProductCategoryServiceImpl 补充下必要的参数校验
// 校验存在
public void updateProductCategory(CrmProductCategoryCreateReqVO updateReqVO) {
// 1.1 校验存在
validateProductCategoryExists(updateReqVO.getId());
// 校验父分类存在
// 1.2 校验父分类存在
validateParentProductCategory(updateReqVO.getParentId());
// 校验名字重复
CrmProductCategoryDO productCategoryDO = productCategoryMapper.selectByName(updateReqVO.getName());
if (productCategoryDO != null &&
ObjUtil.notEqual(productCategoryDO.getId(), updateReqVO.getId())) {
throw exception(PRODUCT_CATEGORY_EXISTS);
}
// 更新
CrmProductCategoryDO updateObj = CrmProductCategoryConvert.INSTANCE.convert(updateReqVO);
// 1.3 分类名称是否存在
validateProductNameExists(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
// 2. 更新
CrmProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, CrmProductCategoryDO.class);
productCategoryMapper.updateById(updateObj);
}
@Override
public void deleteProductCategory(Long id) {
// TODO zange参考 mall ProductCategoryServiceImpl 补充下必要的参数校验
// 校验存在
validateProductCategoryExists(id);
// 校验是否还有子分类
if (productCategoryMapper.selectCountByParentId(id) > 0) {
throw exception(product_CATEGORY_EXISTS_CHILDREN);
}
// 校验是否被产品使用
if (crmProductService.getProductByCategoryId(id) !=null) {
throw exception(PRODUCT_CATEGORY_USED);
}
// 删除
productCategoryMapper.deleteById(id);
}
private void validateProductCategoryExists(Long id) {
if (productCategoryMapper.selectById(id) == null) {
throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
@ -110,6 +81,32 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService
}
}
private void validateProductNameExists(Long id, Long parentId, String name) {
CrmProductCategoryDO category = productCategoryMapper.selectByParentIdAndName(parentId, name);
if (category == null
|| category.getId().equals(id)) {
return;
}
throw exception(PRODUCT_CATEGORY_EXISTS);
}
@Override
public void deleteProductCategory(Long id) {
// TODO zange参考 mall ProductCategoryServiceImpl 补充下必要的参数校验
// 校验存在
validateProductCategoryExists(id);
// 校验是否还有子分类
if (productCategoryMapper.selectCountByParentId(id) > 0) {
throw exception(product_CATEGORY_EXISTS_CHILDREN);
}
// 校验是否被产品使用
if (crmProductService.getProductByCategoryId(id) !=null) {
throw exception(PRODUCT_CATEGORY_USED);
}
// 删除
productCategoryMapper.deleteById(id);
}
@Override
public CrmProductCategoryDO getProductCategory(Long id) {
return productCategoryMapper.selectById(id);