Przeglądaj źródła

✨ CRM:完成商机状态的变更

YunaiV 1 rok temu
rodzic
commit
c97c9f882e
16 zmienionych plików z 200 dodań i 69 usunięć
  1. 3 0
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
  2. 3 0
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
  3. 0 55
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBizEndStatus.java
  4. 45 0
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java
  5. 13 6
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
  6. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
  7. 30 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateStatusReqVO.java
  8. 2 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java
  9. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
  10. 3 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java
  11. 3 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java
  12. 5 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java
  13. 24 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
  14. 37 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
  15. 16 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java
  16. 14 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java

+ 3 - 0
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java

@@ -21,6 +21,8 @@ public interface ErrorCodeConstants {
     // ========== 商机管理 1-020-002-000 ==========
     ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
     ErrorCode BUSINESS_DELETE_FAIL_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除");
+    ErrorCode BUSINESS_UPDATE_STATUS_FAIL_END_STATUS = new ErrorCode(1_020_002_002, "更新商机状态失败,原因:已经是结束状态");
+    ErrorCode BUSINESS_UPDATE_STATUS_FAIL_STATUS_EQUALS = new ErrorCode(1_020_002_003, "更新商机状态失败,原因:已经是该状态");
 
     // ========== 联系人管理 1-020-003-000 ==========
     ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
@@ -81,6 +83,7 @@ public interface ErrorCodeConstants {
     ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态组的名称已存在");
     ErrorCode BUSINESS_STATUS_UPDATE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行更新");
     ErrorCode BUSINESS_STATUS_DELETE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行删除");
+    ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_010_003, "商机状态不存在");
 
     // ========== 客户公海规则设置 1_020_012_000 ==========
     ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用");

+ 3 - 0
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java

@@ -93,6 +93,9 @@ public interface LogRecordConstants {
     String CRM_BUSINESS_TRANSFER_SUCCESS = "将商机【{{#business.name}}】的负责人从【{getAdminUserById{#business.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
     String CRM_BUSINESS_FOLLOW_UP_SUB_TYPE = "商机跟进";
     String CRM_BUSINESS_FOLLOW_UP_SUCCESS = "商机跟进【{{#businessName}}】";
+    String CRM_BUSINESS_UPDATE_STATUS_SUB_TYPE = "更新商机状态";
+    String CRM_BUSINESS_UPDATE_STATUS_SUCCESS = "更新了商机【{{#businessName}}】的状态从【{{#oldStatusName}}】变更为了【{{#newStatusName}}】";
+//    String CRM_BUSINESS_UPDATE_STATUS_SUCCESS = "阿巴阿巴";
 
     // ======================= CRM_CONTRACT 合同 =======================
 

+ 0 - 55
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBizEndStatus.java

@@ -1,55 +0,0 @@
-package cn.iocoder.yudao.module.crm.enums.business;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import java.util.Arrays;
-
-// TODO @lzxhqs:1)title、description、create 可以删除,非标准的 javadoc 注释哈,然后可以在类上加下这个类的注释;2)CrmBizEndStatus 改成 CrmBusinessEndStatus,非必要不缩写哈,可阅读比较重要
-/**
- * @author lzxhqs
- * @version 1.0
- * @title CrmBizEndStatus
- * @description
- * @create 2024/1/12
- */
-@RequiredArgsConstructor
-@Getter
-public enum CrmBizEndStatus implements IntArrayValuable {
-
-    WIN(1, "赢单"),
-    LOSE(2, "输单"),
-    INVALID(3, "无效");
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizEndStatus::getStatus).toArray();
-
-    // TODO @lzxhqs:这里的方法,建议放到 49 行之后;一般类里是,静态变量,普通变量;静态方法;普通方法
-    public static boolean isWin(Integer status) {
-        return ObjectUtil.equal(WIN.getStatus(), status);
-    }
-
-    public static boolean isLose(Integer status) {
-        return ObjectUtil.equal(LOSE.getStatus(), status);
-    }
-
-    public static boolean isInvalid(Integer status) {
-        return ObjectUtil.equal(INVALID.getStatus(), status);
-    }
-
-    /**
-     * 场景类型
-     */
-    private final Integer status;
-    /**
-     * 场景名称
-     */
-    private final String name;
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-
-}

+ 45 - 0
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java

@@ -0,0 +1,45 @@
+package cn.iocoder.yudao.module.crm.enums.business;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * 商机的结束状态枚举
+ *
+ * @author lzxhqs
+ */
+@RequiredArgsConstructor
+@Getter
+public enum CrmBusinessEndStatusEnum implements IntArrayValuable {
+
+    WIN(1, "赢单"),
+    LOSE(2, "输单"),
+    INVALID(3, "无效");
+
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBusinessEndStatusEnum::getStatus).toArray();
+
+    /**
+     * 场景类型
+     */
+    private final Integer status;
+    /**
+     * 场景名称
+     */
+    private final String name;
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+    public static CrmBusinessEndStatusEnum fromStatus(Integer status) {
+        return Arrays.stream(values())
+                .filter(value -> value.getStatus().equals(status))
+                .findFirst()
+                .orElse(null);
+    }
+
+}

+ 13 - 6
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java

@@ -8,10 +8,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 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.business.vo.business.CrmBusinessPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
@@ -87,6 +84,14 @@ public class CrmBusinessController {
         return success(true);
     }
 
+    @PutMapping("/update-status")
+    @Operation(summary = "更新商机状态")
+    @PreAuthorize("@ss.hasPermission('crm:business:update')")
+    public CommonResult<Boolean> updateBusinessStatus(@Valid @RequestBody CrmBusinessUpdateStatusReqVO updateStatusReqVO) {
+        businessService.updateBusinessStatus(updateStatusReqVO);
+        return success(true);
+    }
+
     @DeleteMapping("/delete")
     @Operation(summary = "删除商机")
     @Parameter(name = "id", description = "编号", required = true)
@@ -116,7 +121,8 @@ public class CrmBusinessController {
                 convertSet(businessProducts, CrmBusinessProductDO::getProductId));
         businessVO.setProducts(BeanUtils.toBean(businessProducts, CrmBusinessRespVO.Product.class, businessProductVO ->
                 MapUtils.findAndThen(productMap, businessProductVO.getProductId(),
-                        product -> businessProductVO.setProductNo(product.getNo()).setProductUnit(product.getUnit()))));
+                        product -> businessProductVO.setProductName(product.getName())
+                                .setProductNo(product.getNo()).setProductUnit(product.getUnit()))));
         return businessVO;
     }
 
@@ -209,7 +215,8 @@ public class CrmBusinessController {
             });
             // 2.3 设置商机状态
             MapUtils.findAndThen(statusTypeMap, businessVO.getStatusTypeId(), statusType -> businessVO.setStatusTypeName(statusType.getName()));
-            MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName(status.getName()));
+            MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName(
+                    businessService.getBusinessStatusName(businessVO.getEndStatus(), status)));
         });
     }
 

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java

@@ -134,7 +134,7 @@ public class CrmBusinessRespVO {
         private BigDecimal businessPrice;
 
         @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
-        private Integer count;
+        private BigDecimal count;
 
         @Schema(description = "总计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
         private BigDecimal totalPrice;

+ 30 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateStatusReqVO.java

@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.crm.enums.business.CrmBusinessEndStatusEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.AssertTrue;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - CRM 商机更新状态 Request VO")
+@Data
+public class CrmBusinessUpdateStatusReqVO {
+
+    @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
+    @NotNull(message = "商机编号不能为空")
+    private Long id;
+
+    @Schema(description = "状态编号", example = "1")
+    private Long statusId;
+
+    @Schema(description = "结束状态", example = "1")
+    @InEnum(value = CrmBusinessEndStatusEnum.class)
+    private Integer endStatus;
+
+    @AssertTrue(message = "变更状态不正确")
+    public boolean isStatusValid() {
+        return statusId != null || endStatus != null;
+    }
+
+}

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java

@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.business;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus;
+import cn.iocoder.yudao.module.crm.enums.business.CrmBusinessEndStatusEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -77,7 +77,7 @@ public class CrmBusinessDO extends BaseDO {
     /**
      * 结束状态
      *
-     * 枚举 {@link CrmBizEndStatus}
+     * 枚举 {@link CrmBusinessEndStatusEnum}
      */
     private Integer endStatus;
     /**

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java

@@ -10,7 +10,7 @@ import lombok.*;
 import java.math.BigDecimal;
 
 /**
- * 商机产品关联表 DO
+ * CRM 商机产品关联表 DO
  *
  * CrmBusinessDO : CrmBusinessProductDO = 1 : N
  *

+ 3 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java

@@ -6,7 +6,9 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
 /**
- * 商机状态 DO
+ * CRM 商机状态 DO
+ *
+ * 注意,它是个配置表
  *
  * @author ljlleo
  */

+ 3 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java

@@ -11,7 +11,9 @@ import lombok.*;
 import java.util.List;
 
 /**
- * 商机状态组 DO
+ * CRM 商机状态组 DO
+ *
+ * 注意,它是个配置表
  *
  * @author ljlleo
  */

+ 5 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java

@@ -22,4 +22,9 @@ public interface CrmBusinessStatusMapper extends BaseMapperX<CrmBusinessStatusDO
         return selectList(CrmBusinessStatusDO::getTypeId, typeId);
     }
 
+    default CrmBusinessStatusDO selectByTypeIdAndId(Long statusTypeId, Long statusId) {
+        return selectOne(CrmBusinessStatusDO::getTypeId, statusTypeId,
+                CrmBusinessStatusDO::getId, statusId);
+    }
+
 }

+ 24 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java

@@ -4,10 +4,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateStatusReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import cn.iocoder.yudao.module.crm.enums.business.CrmBusinessEndStatusEnum;
 import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO;
 import jakarta.validation.Valid;
 
@@ -55,6 +58,13 @@ public interface CrmBusinessService {
      */
     void updateBusinessContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime);
 
+    /**
+     * 更新商机的状态
+     *
+     * @param reqVO 更新请求
+     */
+    void updateBusinessStatus(CrmBusinessUpdateStatusReqVO reqVO);
+
     /**
      * 删除商机
      *
@@ -156,4 +166,18 @@ public interface CrmBusinessService {
      */
     Long getBusinessCountByStatusTypeId(Long statusTypeId);
 
+    /**
+     * 获得商机状态名称
+     *
+     * @param endStatus 结束状态
+     * @param status    商机状态
+     * @return 商机状态名称
+     */
+    default String getBusinessStatusName(Integer endStatus, CrmBusinessStatusDO status) {
+        if (endStatus != null) {
+            return CrmBusinessEndStatusEnum.fromStatus(endStatus).getName();
+        }
+        return status.getName();
+    }
+
 }

+ 37 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java

@@ -8,9 +8,11 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateStatusReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
@@ -44,8 +46,7 @@ import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
-import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_DELETE_FAIL_CONTRACT_EXISTS;
-import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
+import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
 
 /**
@@ -218,6 +219,40 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
         business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice));
     }
 
+
+    @Override
+    @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_STATUS_SUB_TYPE, bizNo = "{{#reqVO.id}}",
+            success = CRM_BUSINESS_UPDATE_STATUS_SUCCESS)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.WRITE)
+    public void updateBusinessStatus(CrmBusinessUpdateStatusReqVO reqVO) {
+        // 1.1 校验存在
+        CrmBusinessDO business = validateBusinessExists(reqVO.getId());
+        // 1.2 校验商机未结束
+        if (business.getEndStatus() != null) {
+            throw exception(BUSINESS_UPDATE_STATUS_FAIL_END_STATUS);
+        }
+        // 1.3 校验商机状态
+        CrmBusinessStatusDO status = null;
+        if (reqVO.getStatusId() != null) {
+            status = businessStatusService.validateBusinessStatus(business.getStatusTypeId(), reqVO.getStatusId());
+        }
+        // 1.4 校验是不是状态没变更
+        if ((reqVO.getStatusId() != null && reqVO.getStatusId().equals(business.getStatusId()))
+            || (reqVO.getEndStatus() != null && reqVO.getEndStatus().equals(business.getEndStatus()))) {
+            throw exception(BUSINESS_UPDATE_STATUS_FAIL_STATUS_EQUALS);
+        }
+
+        // 2. 更新商机状态
+        businessMapper.updateById(new CrmBusinessDO().setId(reqVO.getId()).setStatusId(reqVO.getStatusId())
+                .setEndStatus(reqVO.getEndStatus()));
+
+        // 3. 记录操作日志上下文
+        LogRecordContext.putVariable("businessName", business.getName());
+        LogRecordContext.putVariable("oldStatusName", getBusinessStatusName(business.getEndStatus(),
+                businessStatusService.getBusinessStatus(business.getStatusId())));
+        LogRecordContext.putVariable("newStatusName", getBusinessStatusName(reqVO.getEndStatus(), status));
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_DELETE_SUB_TYPE, bizNo = "{{#id}}",

+ 16 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java

@@ -116,4 +116,20 @@ public interface CrmBusinessStatusService {
         return convertMap(getBusinessStatusList(ids), CrmBusinessStatusDO::getId);
     }
 
+    /**
+     * 获得商机状态
+     *
+     * @param id 编号
+     * @return 商机状态
+     */
+    CrmBusinessStatusDO getBusinessStatus(Long id);
+
+    /**
+     * 校验商机状态
+     *
+     * @param statusTypeId 商机状态组编号
+     * @param statusId     商机状态编号
+     */
+    CrmBusinessStatusDO validateBusinessStatus(Long statusTypeId, Long statusId);
+
 }

+ 14 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java

@@ -178,4 +178,18 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService {
         return businessStatusMapper.selectBatchIds(ids);
     }
 
+    @Override
+    public CrmBusinessStatusDO getBusinessStatus(Long id) {
+        return businessStatusMapper.selectById(id);
+    }
+
+    @Override
+    public CrmBusinessStatusDO validateBusinessStatus(Long statusTypeId, Long statusId) {
+        CrmBusinessStatusDO status = businessStatusMapper.selectByTypeIdAndId(statusTypeId, statusId);
+        if (status == null) {
+            throw exception(BUSINESS_STATUS_NOT_EXISTS);
+        }
+        return status;
+    }
+
 }