Commit 256280e8ba8ddf38bc732eade38aaf1d7111fe34

Authored by 芋道源码
Committed by GitHub
2 parents 1acee063 9b991488

Merge pull request #1242 from dadiyang/fix/product-delete-reference-check

[BUG] CRM/ERP:产品删除无引用校验——被业务单据引用的产品可被直接软删,留下悬空引用
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
... ... @@ -81,6 +81,8 @@ public interface ErrorCodeConstants {
81 81 ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_020_008_000, "产品不存在");
82 82 ErrorCode PRODUCT_NO_EXISTS = new ErrorCode(1_020_008_001, "产品编号已存在");
83 83 ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_020_008_002, "产品【{}】已禁用");
  84 + ErrorCode PRODUCT_DELETE_FAIL_CONTRACT_EXISTS = new ErrorCode(1_020_008_003, "产品已被合同引用,无法删除");
  85 + ErrorCode PRODUCT_DELETE_FAIL_BUSINESS_EXISTS = new ErrorCode(1_020_008_004, "产品已被商机引用,无法删除");
84 86  
85 87 // ========== 产品分类 1_020_009_000 ==========
86 88 ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_020_009_000, "产品分类不存在");
... ...
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
... ... @@ -5,8 +5,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 6 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
7 7 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO;
  8 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO;
8 10 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
9 11 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
  12 +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
  13 +import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractProductMapper;
10 14 import cn.iocoder.yudao.module.crm.dal.mysql.product.CrmProductMapper;
11 15 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
12 16 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
... ... @@ -49,6 +53,10 @@ public class CrmProductServiceImpl implements CrmProductService {
49 53 @Resource
50 54 private CrmProductCategoryService productCategoryService;
51 55 @Resource
  56 + private CrmContractProductMapper contractProductMapper;
  57 + @Resource
  58 + private CrmBusinessProductMapper businessProductMapper;
  59 + @Resource
52 60 private CrmPermissionService permissionService;
53 61  
54 62 @Resource
... ... @@ -128,6 +136,13 @@ public class CrmProductServiceImpl implements CrmProductService {
128 136 public void deleteProduct(Long id) {
129 137 // 校验存在
130 138 validateProductExists(id);
  139 + // 校验未被合同/商机引用,避免删除后产生悬空引用
  140 + if (contractProductMapper.selectCount(CrmContractProductDO::getProductId, id) > 0) {
  141 + throw exception(PRODUCT_DELETE_FAIL_CONTRACT_EXISTS);
  142 + }
  143 + if (businessProductMapper.selectCount(CrmBusinessProductDO::getProductId, id) > 0) {
  144 + throw exception(PRODUCT_DELETE_FAIL_BUSINESS_EXISTS);
  145 + }
131 146 // 删除
132 147 productMapper.deleteById(id);
133 148 }
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java
... ... @@ -130,6 +130,12 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00
130 130 // ========== ERP 产品 1-030-500-000 ==========
131 131 ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在");
132 132 ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_030_500_001, "产品({})未启用");
  133 + ErrorCode PRODUCT_DELETE_FAIL_PURCHASE_ORDER_EXISTS = new ErrorCode(1_030_500_002, "产品已被采购订单引用,无法删除");
  134 + ErrorCode PRODUCT_DELETE_FAIL_PURCHASE_IN_EXISTS = new ErrorCode(1_030_500_003, "产品已被采购入库单引用,无法删除");
  135 + ErrorCode PRODUCT_DELETE_FAIL_PURCHASE_RETURN_EXISTS = new ErrorCode(1_030_500_004, "产品已被采购退货单引用,无法删除");
  136 + ErrorCode PRODUCT_DELETE_FAIL_SALE_ORDER_EXISTS = new ErrorCode(1_030_500_005, "产品已被销售订单引用,无法删除");
  137 + ErrorCode PRODUCT_DELETE_FAIL_SALE_OUT_EXISTS = new ErrorCode(1_030_500_006, "产品已被销售出库单引用,无法删除");
  138 + ErrorCode PRODUCT_DELETE_FAIL_SALE_RETURN_EXISTS = new ErrorCode(1_030_500_007, "产品已被销售退货单引用,无法删除");
133 139  
134 140 // ========== ERP 产品分类 1-030-501-000 ==========
135 141 ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_501_000, "产品分类不存在");
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java
... ... @@ -11,7 +11,19 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSa
11 11 import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
12 12 import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
13 13 import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
  14 +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO;
  15 +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO;
  16 +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO;
  17 +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO;
  18 +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO;
  19 +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO;
14 20 import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
  21 +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseInItemMapper;
  22 +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseOrderItemMapper;
  23 +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseReturnItemMapper;
  24 +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderItemMapper;
  25 +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOutItemMapper;
  26 +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleReturnItemMapper;
15 27 import jakarta.annotation.Resource;
16 28 import org.springframework.stereotype.Service;
17 29 import org.springframework.validation.annotation.Validated;
... ... @@ -38,6 +50,18 @@ public class ErpProductServiceImpl implements ErpProductService {
38 50 private ErpProductCategoryService productCategoryService;
39 51 @Resource
40 52 private ErpProductUnitService productUnitService;
  53 + @Resource
  54 + private ErpPurchaseOrderItemMapper purchaseOrderItemMapper;
  55 + @Resource
  56 + private ErpPurchaseInItemMapper purchaseInItemMapper;
  57 + @Resource
  58 + private ErpPurchaseReturnItemMapper purchaseReturnItemMapper;
  59 + @Resource
  60 + private ErpSaleOrderItemMapper saleOrderItemMapper;
  61 + @Resource
  62 + private ErpSaleOutItemMapper saleOutItemMapper;
  63 + @Resource
  64 + private ErpSaleReturnItemMapper saleReturnItemMapper;
41 65  
42 66 @Override
43 67 public Long createProduct(ProductSaveReqVO createReqVO) {
... ... @@ -63,6 +87,25 @@ public class ErpProductServiceImpl implements ErpProductService {
63 87 public void deleteProduct(Long id) {
64 88 // 校验存在
65 89 validateProductExists(id);
  90 + // 校验未被任何业务单据明细引用,避免删除后产生悬空引用
  91 + if (purchaseOrderItemMapper.selectCount(ErpPurchaseOrderItemDO::getProductId, id) > 0) {
  92 + throw exception(PRODUCT_DELETE_FAIL_PURCHASE_ORDER_EXISTS);
  93 + }
  94 + if (purchaseInItemMapper.selectCount(ErpPurchaseInItemDO::getProductId, id) > 0) {
  95 + throw exception(PRODUCT_DELETE_FAIL_PURCHASE_IN_EXISTS);
  96 + }
  97 + if (purchaseReturnItemMapper.selectCount(ErpPurchaseReturnItemDO::getProductId, id) > 0) {
  98 + throw exception(PRODUCT_DELETE_FAIL_PURCHASE_RETURN_EXISTS);
  99 + }
  100 + if (saleOrderItemMapper.selectCount(ErpSaleOrderItemDO::getProductId, id) > 0) {
  101 + throw exception(PRODUCT_DELETE_FAIL_SALE_ORDER_EXISTS);
  102 + }
  103 + if (saleOutItemMapper.selectCount(ErpSaleOutItemDO::getProductId, id) > 0) {
  104 + throw exception(PRODUCT_DELETE_FAIL_SALE_OUT_EXISTS);
  105 + }
  106 + if (saleReturnItemMapper.selectCount(ErpSaleReturnItemDO::getProductId, id) > 0) {
  107 + throw exception(PRODUCT_DELETE_FAIL_SALE_RETURN_EXISTS);
  108 + }
66 109 // 删除
67 110 productMapper.deleteById(id);
68 111 }
... ...