Browse Source

✨ CRM:完善回款的审批

YunaiV 1 year ago
parent
commit
33b056e6c4
10 changed files with 122 additions and 17 deletions
  1. 1 0
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java
  2. 3 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java
  3. 2 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java
  4. 9 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java
  5. 6 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java
  6. 10 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java
  7. 44 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivablePlanParseFunction.java
  8. 40 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivableReturnTypeParseFunction.java
  9. 6 6
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
  10. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java

+ 1 - 0
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java

@@ -14,5 +14,6 @@ public interface DictTypeConstants {
     String CRM_PRODUCT_UNIT = "crm_product_unit"; // CRM 产品单位
     String CRM_PRODUCT_STATUS = "crm_product_status"; // CRM 产品状态
     String CRM_FOLLOW_UP_TYPE = "crm_follow_up_type"; // CRM 跟进方式
+    String CRM_RECEIVABLE_RETURN_TYPE = "crm_receivable_return_type"; // CRM 回款方式
 
 }

+ 3 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java

@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogV2RespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogRespVO;
 import cn.iocoder.yudao.module.crm.enums.LogRecordConstants;
 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
 import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
@@ -54,11 +54,11 @@ public class CrmOperateLogController {
     @GetMapping("/page")
     @Operation(summary = "获得操作日志")
     @PreAuthorize("@ss.hasPermission('crm:operate-log:query')")
-    public CommonResult<PageResult<CrmOperateLogV2RespVO>> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) {
+    public CommonResult<PageResult<CrmOperateLogRespVO>> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) {
         OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO();
         reqDTO.setPageSize(PAGE_SIZE_NONE); // 默认不分页,需要分页需注释
         reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())).setBizId(pageReqVO.getBizId());
-        return success(BeanUtils.toBean(operateLogApi.getOperateLogPage(reqDTO), CrmOperateLogV2RespVO.class));
+        return success(BeanUtils.toBean(operateLogApi.getOperateLogPage(reqDTO), CrmOperateLogRespVO.class));
     }
 
 }

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java

@@ -6,10 +6,10 @@ import lombok.Data;
 
 import java.time.LocalDateTime;
 
-@Schema(description = "管理后台 - CRM 跟进 Response VO")
+@Schema(description = "管理后台 - CRM 操作日志 Response VO")
 @Data
 @ExcelIgnoreUnannotated
-public class CrmOperateLogV2RespVO {
+public class CrmOperateLogRespVO {
 
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
     private Long id;

+ 9 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java

@@ -41,8 +41,7 @@ import java.util.stream.Stream;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
 import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -95,7 +94,14 @@ public class CrmReceivableController {
     @PreAuthorize("@ss.hasPermission('crm:receivable:query')")
     public CommonResult<CrmReceivableRespVO> getReceivable(@RequestParam("id") Long id) {
         CrmReceivableDO receivable = receivableService.getReceivable(id);
-        return success(BeanUtils.toBean(receivable, CrmReceivableRespVO.class));
+        return success(buildReceivableDetail(receivable));
+    }
+
+    private CrmReceivableRespVO buildReceivableDetail(CrmReceivableDO receivable) {
+        if (receivable == null) {
+            return null;
+        }
+        return buildReceivableDetailList(Collections.singletonList(receivable)).get(0);
     }
 
     @GetMapping("/page")

+ 6 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java

@@ -51,12 +51,16 @@ public class CrmReceivableRespVO {
     @ExcelProperty("负责人部门")
     private String ownerUserDeptName;
 
-    @Schema(description = "备注", example = "备注")
-    private String remark;
+    @Schema(description = "工作流编号", example = "1043")
+    @ExcelProperty("工作流编号")
+    private String processInstanceId;
 
     @Schema(description = "审批状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
     private Integer auditStatus;
 
+    @Schema(description = "备注", example = "备注")
+    private String remark;
+
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 

+ 10 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java

@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
 import cn.iocoder.yudao.module.crm.enums.receivable.CrmReceivableReturnTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.*;
+import com.mzt.logapi.starter.annotation.DiffLogField;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
@@ -17,32 +19,40 @@ public class CrmReceivableSaveReqVO {
     private Long id;
 
     @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME)
     @NotNull(message = "负责人编号不能为空")
     private Long ownerUserId;
 
     @Schema(description = "客户编号", example = "2")
+    @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
     private Long customerId; // 该字段不通过前端传递,而是 contractId 查询出来设置进去
 
     @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @DiffLogField(name = "合同", function = CrmContractParseFunction.NAME)
     @NotNull(message = "合同编号不能为空")
     private Long contractId;
 
     @Schema(description = "回款计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @DiffLogField(name = "合同", function = CrmReceivablePlanParseFunction.NAME)
     private Long planId;
 
     @Schema(description = "回款方式", example = "2")
+    @DiffLogField(name = "回款方式", function = CrmReceivableReturnTypeParseFunction.NAME)
     @InEnum(CrmReceivableReturnTypeEnum.class)
     private Integer returnType;
 
     @Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000")
+    @DiffLogField(name = "回款金额")
     @NotNull(message = "回款金额不能为空")
     private BigDecimal price;
 
     @Schema(description = "回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02")
     @NotNull(message = "回款日期不能为空")
+    @DiffLogField(name = "回款日期")
     private LocalDateTime returnTime;
 
     @Schema(description = "备注", example = "备注")
+    @DiffLogField(name = "备注")
     private String remark;
 
 }

+ 44 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivablePlanParseFunction.java

@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.crm.framework.operatelog.core;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
+import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivablePlanService;
+import com.mzt.logapi.service.IParseFunction;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+/**
+ * CRM 回款计划的 {@link IParseFunction} 实现类
+ *
+ * @author HUIHUI
+ */
+@Component
+@Slf4j
+public class CrmReceivablePlanParseFunction implements IParseFunction {
+
+    public static final String NAME = "getReceivablePlanServiceById";
+
+    @Resource
+    private CrmReceivablePlanService receivablePlanService;
+
+    @Override
+    public boolean executeBefore() {
+        return true; // 先转换值后对比
+    }
+
+    @Override
+    public String functionName() {
+        return NAME;
+    }
+
+    @Override
+    public String apply(Object value) {
+        if (StrUtil.isEmptyIfStr(value)) {
+            return "";
+        }
+        CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(Long.parseLong(value.toString()));
+        return receivablePlan == null ? "" : receivablePlan.getPeriod().toString();
+    }
+
+}

+ 40 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivableReturnTypeParseFunction.java

@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.crm.framework.operatelog.core;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
+import com.mzt.logapi.service.IParseFunction;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_RECEIVABLE_RETURN_TYPE;
+
+/**
+ * CRM 回款方式的 {@link IParseFunction} 实现类
+ *
+ * @author HUIHUI
+ */
+@Slf4j
+@Component
+public class CrmReceivableReturnTypeParseFunction implements IParseFunction {
+
+    public static final String NAME = "getReceivableReturnType";
+
+    @Override
+    public boolean executeBefore() {
+        return true; // 先转换值后对比
+    }
+
+    @Override
+    public String functionName() {
+        return NAME;
+    }
+
+    @Override
+    public String apply(Object value) {
+        if (StrUtil.isEmptyIfStr(value)) {
+            return "";
+        }
+        return DictFrameworkUtils.getDictDataLabel(CRM_RECEIVABLE_RETURN_TYPE, value.toString());
+    }
+
+}

+ 6 - 6
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java

@@ -37,7 +37,6 @@ import org.springframework.validation.annotation.Validated;
 
 import java.util.Collection;
 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.crm.enums.ErrorCodeConstants.*;
@@ -54,11 +53,10 @@ import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertBpmRes
 @Slf4j
 public class CrmReceivableServiceImpl implements CrmReceivableService {
 
-    // TODO @芋艿:改个名字
     /**
-     * BPM 回款审批流程标识
+     * BPM 合同审批流程标识
      */
-    public static final String RECEIVABLE_APPROVE = "receivable-approve";
+    public static final String BPM_PROCESS_DEFINITION_KEY = "crm-receivable-audit";
 
     @Resource
     private CrmReceivableMapper receivableMapper;
@@ -79,6 +77,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
     @Resource
     private BpmProcessInstanceApi bpmProcessInstanceApi;
 
+    // TODO @puhui999:操作日志没记录上
     @Override
     @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_CREATE_SUB_TYPE, bizNo = "{{#receivable.id}}",
@@ -134,6 +133,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
         }
     }
 
+    // TODO @puhui999:操作日志没记录上
     @Override
     @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
@@ -184,7 +184,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
         // 1.1 校验存在
         CrmReceivableDO receivable = validateReceivableExists(id);
         // 1.2 如果被 CrmReceivablePlanDO 所使用,则不允许删除
-        if (Objects.nonNull(receivable.getPlanId()) && receivablePlanService.getReceivablePlan(receivable.getPlanId()) != null) {
+        if (receivable.getPlanId() != null && receivablePlanService.getReceivablePlan(receivable.getPlanId()) != null) {
             throw exception(RECEIVABLE_DELETE_FAIL);
         }
 
@@ -210,7 +210,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
 
         // 2. 创建回款审批流程实例
         String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO()
-                .setProcessDefinitionKey(RECEIVABLE_APPROVE).setBusinessKey(String.valueOf(id)));
+                .setProcessDefinitionKey(BPM_PROCESS_DEFINITION_KEY).setBusinessKey(String.valueOf(id)));
 
         // 3. 更新回款工作流编号
         receivableMapper.updateById(new CrmReceivableDO().setId(id).setProcessInstanceId(processInstanceId)

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java

@@ -20,7 +20,7 @@ public class CrmReceivableResultListener extends BpmProcessInstanceResultEventLi
 
     @Override
     public String getProcessDefinitionKey() {
-        return CrmReceivableServiceImpl.RECEIVABLE_APPROVE;
+        return CrmReceivableServiceImpl.BPM_PROCESS_DEFINITION_KEY;
     }
 
     @Override