mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	✨ CRM:完善回款的审批
This commit is contained in:
		| @@ -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)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| @@ -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") | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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()); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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) | ||||
|   | ||||
| @@ -20,7 +20,7 @@ public class CrmReceivableResultListener extends BpmProcessInstanceResultEventLi | ||||
|  | ||||
|     @Override | ||||
|     public String getProcessDefinitionKey() { | ||||
|         return CrmReceivableServiceImpl.RECEIVABLE_APPROVE; | ||||
|         return CrmReceivableServiceImpl.BPM_PROCESS_DEFINITION_KEY; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV