From f7d41186e48bb1ec32bb643885ae9be826987f61 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 20:30:12 +0800 Subject: [PATCH 1/4] =?UTF-8?q?CRM:=20=E8=8E=B7=E5=8F=96=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97=E6=8E=A5=E5=8F=A3=E6=8A=BD?= =?UTF-8?q?=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contact/CrmContactController.java | 17 ----- .../admin/customer/CrmCustomerController.java | 20 +----- .../operatelog/CrmOperateLogController.java | 62 +++++++++++++++++++ .../operatelog/vo/CrmOperateLogPageReqVO.java | 27 ++++++++ .../permission/CrmPermissionController.java | 4 +- .../admin/product/CrmProductController.java | 18 ------ .../permission/CrmPermissionConvert.java | 14 ----- .../permission/CrmPermissionServiceImpl.java | 5 +- .../bo/CrmPermissionUpdateReqBO.java | 36 ----------- 9 files changed, 96 insertions(+), 107 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateReqBO.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index 4e2e73e81..e3998834d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -17,9 +17,6 @@ import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.google.common.collect.Lists; @@ -46,7 +43,6 @@ import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT_TYPE; @Tag(name = "管理后台 - CRM 联系人") @RestController @@ -64,8 +60,6 @@ public class CrmContactController { @Resource private AdminUserApi adminUserApi; - @Resource - private OperateLogApi operateLogApi; @PostMapping("/create") @Operation(summary = "创建联系人") @@ -158,17 +152,6 @@ public class CrmContactController { buildContactDetailPage(pageResult).getList()); } - @GetMapping("/operate-log-page") - @Operation(summary = "获得客户操作日志") - @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getCustomerOperateLog(@RequestParam("bizId") Long bizId) { - OperateLogV2PageReqDTO reqVO = new OperateLogV2PageReqDTO(); - reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 - reqVO.setBizType(CRM_CONTACT_TYPE); - reqVO.setBizId(bizId); - return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); - } - /** * 构建详细的联系人分页结果 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index a7b0a3730..03893b817 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -17,9 +17,6 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; @@ -44,7 +41,6 @@ import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER_TYPE; @Tag(name = "管理后台 - CRM 客户") @RestController @@ -60,8 +56,7 @@ public class CrmCustomerController { private DeptApi deptApi; @Resource private AdminUserApi adminUserApi; - @Resource - private OperateLogApi operateLogApi; + @PostMapping("/create") @Operation(summary = "创建客户") @@ -182,19 +177,6 @@ public class CrmCustomerController { return success(true); } - // TODO @puhui999:要不搞个通用的 CrmOperateLogController,之后所有业务都调用它? - @GetMapping("/operate-log-page") - @Operation(summary = "获得客户操作日志") - @Parameter(name = "id", description = "客户编号", required = true) - @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getCustomerOperateLog(@RequestParam("id") Long id) { - OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); - reqDTO.setPageSize(PAGE_SIZE_NONE); // 不分页 - reqDTO.setBizType(CRM_CUSTOMER_TYPE); - reqDTO.setBizId(id); - return success(operateLogApi.getOperateLogPage(reqDTO)); - } - @PutMapping("/lock") @Operation(summary = "锁定/解锁客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java new file mode 100644 index 000000000..0894b43df --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogPageReqVO; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +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.module.crm.enums.LogRecordConstants.*; + +@Tag(name = "管理后台 - 操作日志") +@RestController +@RequestMapping("/crm/operate-log") +@Validated +public class CrmOperateLogController { + + @Resource + private OperateLogApi operateLogApi; + + private static final Map BIZ_TYPE_MAP = new HashMap<>(); + + static { + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_LEADS.getType(), CRM_LEADS_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CUSTOMER.getType(), CRM_CUSTOMER_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTACT.getType(), CRM_CONTACT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_BUSINESS.getType(), CRM_BUSINESS_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTRACT.getType(), CRM_CONTRACT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_PRODUCT.getType(), CRM_PRODUCT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CRM_RECEIVABLE_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CRM_RECEIVABLE_PLAN_TYPE); + } + + @GetMapping("/page") + @Operation(summary = "获得操作日志") + @Parameter(name = "id", description = "客户编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { + OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); + reqDTO.setPageSize(PAGE_SIZE_NONE); // 默认不分页,需要分页需注释 + reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())); + reqDTO.setBizId(pageReqVO.getBizId()); + return success(operateLogApi.getOperateLogPage(reqDTO)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java new file mode 100644 index 000000000..9f54247bf --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 跟进记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmOperateLogPageReqVO extends PageParam { + + @Schema(description = "数据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @InEnum(CrmBizTypeEnum.class) + @NotNull(message = "数据类型不能为空") + private Integer bizType; + + @Schema(description = "数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "数据编号不能为空") + private Long bizId; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index 8bc9a6d93..88b4b3011 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.permission; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionRespVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; @@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.PostApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; @@ -55,7 +57,7 @@ public class CrmPermissionController { @PreAuthorize("@ss.hasPermission('crm:permission:create')") @CrmPermission(bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId", level = CrmPermissionLevelEnum.OWNER) public CommonResult addPermission(@Valid @RequestBody CrmPermissionCreateReqVO reqVO) { - permissionService.createPermission(CrmPermissionConvert.INSTANCE.convert(reqVO)); + permissionService.createPermission(BeanUtils.toBean(reqVO, CrmPermissionCreateReqBO.class)); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java index fc4192443..94774373d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java @@ -5,7 +5,6 @@ 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.collection.SetUtils; -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.product.vo.product.CrmProductPageReqVO; @@ -16,9 +15,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.service.product.CrmProductCategoryService; import cn.iocoder.yudao.module.crm.service.product.CrmProductService; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; @@ -38,12 +34,10 @@ import java.util.Map; 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.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_PRODUCT_TYPE; @Tag(name = "管理后台 - CRM 产品") @RestController @@ -56,8 +50,6 @@ public class CrmProductController { @Resource private CrmProductCategoryService productCategoryService; @Resource - private OperateLogApi operateLogApi; - @Resource private AdminUserApi adminUserApi; @PostMapping("/create") @@ -131,14 +123,4 @@ public class CrmProductController { return CrmProductConvert.INSTANCE.convertList(list, userMap, productCategoryList); } - @GetMapping("/operate-log-page") - @Operation(summary = "获得产品操作日志") - @PreAuthorize("@ss.hasPermission('crm:product:query')") - public CommonResult> getProductOperateLog(@RequestParam("bizId") Long bizId) { - OperateLogV2PageReqDTO reqVO = new OperateLogV2PageReqDTO(); - reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 - reqVO.setBizType(CRM_PRODUCT_TYPE).setBizId(bizId); - return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java index 6979a055e..61145f688 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java @@ -3,12 +3,9 @@ package cn.iocoder.yudao.module.crm.convert.permission; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionRespVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateReqBO; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -32,14 +29,6 @@ public interface CrmPermissionConvert { CrmPermissionConvert INSTANCE = Mappers.getMapper(CrmPermissionConvert.class); - CrmPermissionDO convert(CrmPermissionCreateReqBO createBO); - - CrmPermissionDO convert(CrmPermissionUpdateReqBO updateBO); - - CrmPermissionCreateReqBO convert(CrmPermissionCreateReqVO reqVO); - - CrmPermissionUpdateReqBO convert(CrmPermissionUpdateReqVO updateReqVO); - List convert(List permission); default List convert(List permission, List userList, @@ -65,7 +54,4 @@ public interface CrmPermissionConvert { id -> new CrmPermissionDO().setId(id).setLevel(updateReqVO.getLevel())); } - // TODO @puhui999:搞成 BeanUtils - List convertList(List list); - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index f135da993..07818bd07 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.permission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; @@ -50,7 +51,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { adminUserApi.validateUserList(Collections.singletonList(createReqBO.getUserId())); // 2. 创建 - CrmPermissionDO permission = CrmPermissionConvert.INSTANCE.convert(createReqBO); + CrmPermissionDO permission = BeanUtils.toBean(createReqBO, CrmPermissionDO.class); permissionMapper.insert(permission); return permission.getId(); } @@ -62,7 +63,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { adminUserApi.validateUserList(convertSet(createReqBOs, CrmPermissionCreateReqBO::getUserId)); // 2. 创建 - List permissions = CrmPermissionConvert.INSTANCE.convertList(createReqBOs); + List permissions = BeanUtils.toBean(createReqBOs, CrmPermissionDO.class); permissionMapper.insertBatch(permissions); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateReqBO.java deleted file mode 100644 index 0ac474101..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateReqBO.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.permission.bo; - -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -/** - * crm 数据权限 Update Req BO - * - * @author HUIHUI - */ -@Data -public class CrmPermissionUpdateReqBO { - - /** - * 数据权限编号 - */ - @NotNull(message = "数据权限编号不能为空") - private Long id; - - /** - * 当前登录用户编号 - */ - @NotNull(message = "用户编号不能为空") - private Long userId; - - /** - * 权限级别 - */ - @NotNull(message = "权限级别不能为空") - @InEnum(CrmPermissionLevelEnum.class) - private Integer level; - -} From 8675d135484a6f30de32075ba57f686dd258859f Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 22:23:23 +0800 Subject: [PATCH 2/4] =?UTF-8?q?CRM-=E7=BA=BF=E7=B4=A2=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E7=BA=BF=E7=B4=A2=E8=BD=AC=E5=AE=A2=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/clue/CrmClueController.java | 2 +- .../followup/CrmFollowUpRecordMapper.java | 13 ++ .../crm/service/clue/CrmClueService.java | 3 +- .../crm/service/clue/CrmClueServiceImpl.java | 89 ++++++++----- .../service/customer/CrmCustomerService.java | 10 ++ .../customer/CrmCustomerServiceImpl.java | 22 +++ .../customer/bo/CrmCustomerCreateReqBO.java | 125 ++++++++++++++++++ .../followup/CrmFollowUpRecordService.java | 28 ++++ .../CrmFollowUpRecordServiceImpl.java | 23 ++++ .../followup/bo/CrmFollowUpCreateReqBO.java | 78 +++++++++++ .../service/clue/CrmClueServiceImplTest.java | 3 +- 11 files changed, 360 insertions(+), 36 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index f6d32f3a4..9c6a88f2d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -39,7 +39,7 @@ public class CrmClueController { @Operation(summary = "创建线索") @PreAuthorize("@ss.hasPermission('crm:clue:create')") public CommonResult createClue(@Valid @RequestBody CrmClueSaveReqVO createReqVO) { - return success(clueService.createClue(createReqVO)); + return success(clueService.createClue(createReqVO, getLoginUserId())); } @PutMapping("/update") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java index a9b1dc315..59d800c22 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java @@ -7,6 +7,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecor import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import org.apache.ibatis.annotations.Mapper; +import java.util.Collection; +import java.util.List; + /** * 跟进记录 Mapper * @@ -22,4 +25,14 @@ public interface CrmFollowUpRecordMapper extends BaseMapperX().eq(CrmFollowUpRecordDO::getBizType, bizType) + .eq(CrmFollowUpRecordDO::getBizId, bizId)); + } + + default List selectListByBiz(Integer bizType, Collection bizIds) { + return selectList(new LambdaQueryWrapperX().eq(CrmFollowUpRecordDO::getBizType, bizType) + .in(CrmFollowUpRecordDO::getBizId, bizIds)); + } + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 6efffa96a..b189bd266 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -23,9 +23,10 @@ public interface CrmClueService { * 创建线索 * * @param createReqVO 创建信息 + * @param userId 用户编号 * @return 编号 */ - Long createClue(@Valid CrmClueSaveReqVO createReqVO); + Long createClue(@Valid CrmClueSaveReqVO createReqVO, Long userId); /** * 更新线索 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 996a6b74e..898a576a0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.crm.service.clue; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; @@ -15,11 +14,16 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransformReqV import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; +import cn.iocoder.yudao.module.crm.service.followup.CrmFollowUpRecordService; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; @@ -32,17 +36,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; +import static java.util.Collections.singletonList; /** * 线索 Service 实现类 @@ -61,7 +62,8 @@ public class CrmClueServiceImpl implements CrmClueService { @Resource private CrmPermissionService crmPermissionService; - + @Resource + private CrmFollowUpRecordService followUpRecordService; @Resource private AdminUserApi adminUserApi; @@ -69,21 +71,23 @@ public class CrmClueServiceImpl implements CrmClueService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", success = CRM_LEADS_CREATE_SUCCESS) - public Long createClue(CrmClueSaveReqVO createReqVO) { + public Long createClue(CrmClueSaveReqVO createReqVO, Long userId) { // 1. 校验关联数据 validateRelationDataExists(createReqVO); // 2. 插入 CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class); + if (ObjUtil.isNull(createReqVO.getOwnerUserId())) { + clue.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人 + } else { + // 校验负责人是否存在 + adminUserApi.validateUserList(singletonList(createReqVO.getOwnerUserId())); + } clueMapper.insert(clue); // 3. 创建数据权限 - CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO() - .setBizType(CrmBizTypeEnum.CRM_LEADS.getType()) - .setBizId(clue.getId()) - // 设置当前操作的人为负责人 - .setUserId(getLoginUserId()) - .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()); + CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_LEADS.getType()) + .setBizId(clue.getId()).setUserId(clue.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()); crmPermissionService.createPermission(createReqBO); // 4. 记录操作日志上下文 @@ -132,7 +136,10 @@ public class CrmClueServiceImpl implements CrmClueService { // 3. 删除数据权限 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_LEADS.getType(), id); - // 4. 记录操作日志上下文 + // 4. 删除跟进 + followUpRecordService.deleteFollowUpRecordByBiz(CrmBizTypeEnum.CRM_LEADS.getType(), id); + + // 记录操作日志上下文 LogRecordContext.putVariable("clueName", clue.getName()); } @@ -179,31 +186,47 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) public void translateCustomer(CrmClueTransformReqVO reqVO, Long userId) { - // 校验线索都存在 + // 1.1 校验线索都存在 Set clueIds = reqVO.getIds(); List clues = getClueList(clueIds, userId); if (CollUtil.isEmpty(clues) || ObjectUtil.notEqual(clues.size(), clueIds.size())) { clueIds.removeAll(convertSet(clues, CrmClueDO::getId)); - throw exception(CLUE_ANY_CLUE_NOT_EXISTS, StrUtil.join(",", clueIds)); + throw exception(CLUE_ANY_CLUE_NOT_EXISTS, clueIds); } - - // 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 - List translatedClues = CollectionUtils.filterList(clues, + // 1.2 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 + List translatedClues = filterList(clues, clue -> ObjectUtil.equal(Boolean.TRUE, clue.getTransformStatus())); if (CollUtil.isNotEmpty(translatedClues)) { - throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, StrUtil.join(",", convertSet(translatedClues, CrmClueDO::getId))); + throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId)); } - // 遍历线索(未转化的线索),创建对应的客户 - reqVO.getIds().forEach(id -> { - // 1. 创建客户 - CrmCustomerSaveReqVO customerSaveReqVO = BeanUtils.toBean(id, CrmCustomerSaveReqVO.class).setId(null); - Long customerId = customerService.createCustomer(customerSaveReqVO, userId); - // TODO @puhui999:如果有跟进记录,需要一起转过去;提问:艿艿这里是复制线索所有的跟进吗?还是直接把线索相关的跟进 bizType、bizId 全改为关联客户? - // 2. 更新线索 - clueMapper.updateById(new CrmClueDO().setId(id) - .setTransformStatus(Boolean.TRUE).setCustomerId(customerId)); - }); + // 2. 遍历线索(未转化的线索),创建对应的客户 + List translateClues = filterList(clues, clue -> ObjUtil.equal(Boolean.FALSE, clue.getTransformStatus())); + List customers = customerService.createCustomerBatch(convertList(translateClues, clue -> + BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class)), userId); + + Map clueCustomerIdMap = new HashMap<>(translateClues.size()); + // 2.1 更新线索 + clueMapper.updateBatch(convertList(customers, customer -> { + CrmClueDO firstClue = findFirst(translateClues, clue -> ObjUtil.equal(clue.getName(), customer.getName())); + clueCustomerIdMap.put(firstClue.getId(), customer.getId()); + return new CrmClueDO().setId(firstClue.getId()).setTransformStatus(Boolean.TRUE).setCustomerId(customer.getId()); + })); + // 2.3 复制跟进 + updateFollowUpRecords(clueCustomerIdMap); + } + + private void updateFollowUpRecords(Map clueCustomerIdMap) { + List followUpRecords = followUpRecordService.getFollowUpRecordByBiz( + CrmBizTypeEnum.CRM_LEADS.getType(), clueCustomerIdMap.keySet()); + if (CollUtil.isEmpty(followUpRecords)) { + return; + } + + // 创建跟进 + followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord -> + BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) + .setBizId(clueCustomerIdMap.get(followUpRecord.getBizId())))); } private void validateRelationDataExists(CrmClueSaveReqVO reqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 8cd2448b7..38d5f082b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageR import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -98,6 +99,15 @@ public interface CrmCustomerService { */ void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO); + /** + * 批量创建客户 + * + * @param customerCreateReqBOs 请求 + * @param userId 用户编号 + * @return 客户列表 + */ + List createCustomerBatch(List customerCreateReqBOs, Long userId); + // ==================== 公海相关操作 ==================== /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 5c1f5134a..45893fa87 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionU import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; +import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; @@ -42,10 +43,12 @@ import java.util.Collections; 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.convertList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_OWNER_LIMIT; +import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; /** @@ -209,6 +212,25 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { customerMapper.updateById(BeanUtils.toBean(customerUpdateFollowUpReqBO, CrmCustomerDO.class).setId(customerUpdateFollowUpReqBO.getBizId())); } + @Override + @Transactional(rollbackFor = Exception.class) + public List createCustomerBatch(List customerCreateReqBOs, Long userId) { + if (CollUtil.isEmpty(customerCreateReqBOs)) { + return emptyList(); + } + + // 创建客户 + List customers = convertList(customerCreateReqBOs, customerBO -> + BeanUtils.toBean(customerBO, CrmCustomerDO.class).setOwnerUserId(userId)); + customerMapper.insertBatch(customers); + + // 创建负责人数据权限 + permissionService.createPermissionBatch(convertList(customers, customer -> new CrmPermissionCreateReqBO() + .setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()).setBizId(customer.getId()).setUserId(userId) + .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()))); + return customers; + } + // ==================== 公海相关操作 ==================== @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java new file mode 100644 index 000000000..6d80b0e4c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java @@ -0,0 +1,125 @@ +package cn.iocoder.yudao.module.crm.service.customer.bo; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.framework.common.validation.Telephone; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 客户创建 Create Req BO + * + * @author HUIHUI + */ +@Data +public class CrmCustomerCreateReqBO { + + /** + * 客户名称 + */ + @NotEmpty(message = "客户名称不能为空") + private String name; + /** + * 跟进状态 + */ + private Boolean followUpStatus; + /** + * 锁定状态 + */ + private Boolean lockStatus; + /** + * 成交状态 + */ + private Boolean dealStatus; + /** + * 所属行业 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} + */ + private Integer industryId; + /** + * 客户等级 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} + */ + private Integer level; + /** + * 客户来源 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} + */ + private Integer source; + + /** + * 手机 + */ + @Mobile + private String mobile; + /** + * 电话 + */ + @Telephone + private String telephone; + /** + * 网址 + */ + private String website; + /** + * QQ + */ + private String qq; + /** + * wechat + */ + private String wechat; + + /** + * 邮箱 + */ + @Email(message = "邮箱格式不正确") + private String email; + + /** + * 客户描述 + */ + @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") + private String description; + /** + * 备注 + */ + private String remark; + /** + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + /** + * 所在地 + * + * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 + */ + private Integer areaId; + /** + * 详细地址 + */ + private String detailAddress; + + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + /** + * 最后跟进内容 + */ + private String contactLastContent; + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java index c0fb69f25..f881e5259 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java @@ -4,8 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; + /** * 跟进记录 Service 接口 * @@ -21,6 +25,13 @@ public interface CrmFollowUpRecordService { */ Long createFollowUpRecord(@Valid CrmFollowUpRecordSaveReqVO createReqVO); + /** + * 创建更进 + * + * @param followUpCreateReqBOs 请求 + */ + void createFollowUpRecordBatch(List followUpCreateReqBOs); + /** * 删除跟进记录 (数据权限基于 bizType、 bizId) * @@ -29,6 +40,14 @@ public interface CrmFollowUpRecordService { */ void deleteFollowUpRecord(Long id, Long userId); + /** + * 删除跟进 + * + * @param bizType 模块类型 + * @param bizId 模块数据编号 + */ + void deleteFollowUpRecordByBiz(Integer bizType, Long bizId); + /** * 获得跟进记录 * @@ -45,4 +64,13 @@ public interface CrmFollowUpRecordService { */ PageResult getFollowUpRecordPage(CrmFollowUpRecordPageReqVO pageReqVO); + /** + * 获取跟进记录 + * + * @param bizType 模块类型 + * @param bizIds 模块数据编号 + * @return 跟进列表 + */ + List getFollowUpRecordByBiz(Integer bizType, Collection bizIds); + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index 670fdacfc..ce76e6a8f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; @@ -24,6 +25,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -96,6 +98,16 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { return followUpRecord.getId(); } + @Override + public void createFollowUpRecordBatch(List followUpCreateReqBOs) { + if (CollUtil.isEmpty(followUpCreateReqBOs)) { + return; + } + + List followUpRecords = BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class); + crmFollowUpRecordMapper.insertBatch(followUpRecords); + } + @Override public void deleteFollowUpRecord(Long id, Long userId) { // 校验存在 @@ -113,6 +125,12 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { crmFollowUpRecordMapper.deleteById(id); } + @Override + public void deleteFollowUpRecordByBiz(Integer bizType, Long bizId) { + // 删除 + crmFollowUpRecordMapper.deleteByBiz(bizType, bizId); + } + private CrmFollowUpRecordDO validateFollowUpRecordExists(Long id) { CrmFollowUpRecordDO followUpRecord = crmFollowUpRecordMapper.selectById(id); if (followUpRecord == null) { @@ -132,4 +150,9 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { return crmFollowUpRecordMapper.selectPage(pageReqVO); } + @Override + public List getFollowUpRecordByBiz(Integer bizType, Collection bizIds) { + return crmFollowUpRecordMapper.selectListByBiz(bizType, bizIds); + } + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java new file mode 100644 index 000000000..dec219e29 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.crm.service.followup.bo; + +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 跟进信息 Create Req BO + * + * @author HUIHUI + */ +@Data +public class CrmFollowUpCreateReqBO { + + /** + * 数据类型 + * + * 枚举 {@link CrmBizTypeEnum} + */ + @NotNull(message = "数据类型不能为空") + private Integer bizType; + /** + * 数据编号 + * + * 关联 {@link CrmBizTypeEnum} 对应模块 DO 的 id 字段 + */ + @NotNull(message = "数据编号不能为空") + private Long bizId; + + /** + * 跟进类型 + * + * 关联 {@link DictTypeConstants#CRM_FOLLOW_UP_TYPE} 字典 + */ + @NotNull(message = "跟进类型不能为空") + private Integer type; + /** + * 跟进内容 + */ + @NotEmpty(message = "跟进内容不能为空") + private String content; + /** + * 下次联系时间 + */ + @NotNull(message = "下次联系时间不能为空") + private LocalDateTime nextTime; + + /** + * 图片 + */ + private List picUrls; + /** + * 附件 + */ + private List fileUrls; + + /** + * 关联的商机编号数组 + * + * 关联 {@link CrmBusinessDO#getId()} + */ + private List businessIds; + + /** + * 关联的联系人编号数组 + * + * 关联 {@link CrmContactDO#getId()} + */ + private List contactIds; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java index 9738c67b3..d73921f3d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java @@ -15,6 +15,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; @@ -45,7 +46,7 @@ public class CrmClueServiceImplTest extends BaseDbUnitTest { CrmClueSaveReqVO reqVO = randomPojo(CrmClueSaveReqVO.class); // 调用 - Long clueId = clueService.createClue(reqVO); + Long clueId = clueService.createClue(reqVO, getLoginUserId()); // 断言 assertNotNull(clueId); // 校验记录的属性是否正确 From ca9f3c522d9c0d89a9168e5c630d5b583c81057c Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 22:46:52 +0800 Subject: [PATCH 3/4] =?UTF-8?q?CRM-=E7=BA=BF=E7=B4=A2=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 6 +- .../admin/clue/vo/CrmClueSaveReqVO.java | 8 ++ .../crm/service/clue/CrmClueServiceImpl.java | 114 ++++++++++++------ 3 files changed, 90 insertions(+), 38 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index 198886e68..a0b4559ef 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -14,9 +14,13 @@ public interface LogRecordConstants { String CRM_LEADS_CREATE_SUB_TYPE = "创建线索"; String CRM_LEADS_CREATE_SUCCESS = "创建了线索{{#clue.name}}"; String CRM_LEADS_UPDATE_SUB_TYPE = "更新线索"; - String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReqVO}}"; + String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReq}}"; String CRM_LEADS_DELETE_SUB_TYPE = "删除线索"; String CRM_LEADS_DELETE_SUCCESS = "删除了线索【{{#clueName}}】"; + String CRM_LEADS_TRANSFER_SUB_TYPE = "转移线索"; + String CRM_LEADS_TRANSFER_SUCCESS = "将线索【{{#clue.name}}】的负责人从【{getAdminUserById{#clue.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String CRM_LEADS_TRANSLATE_SUB_TYPE = "线索转化为客户"; + String CRM_LEADS_TRANSLATE_SUCCESS = "将线索【{{#clue.name}}】转化为客户"; // ======================= CRM_CUSTOMER 客户 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java index adbc650b9..8ceaae2c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.framework.common.validation.Telephone; +import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import lombok.Data; @@ -19,32 +20,39 @@ public class CrmClueSaveReqVO { private Long id; @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx") + @DiffLogField(name = "线索名称") @NotEmpty(message = "线索名称不能为空") private String name; @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") + @DiffLogField(name = "下次联系时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime contactNextTime; @Schema(description = "电话", example = "18000000000") + @DiffLogField(name = "电话") @Telephone private String telephone; @Schema(description = "手机号", example = "18000000000") + @DiffLogField(name = "手机号") @Mobile private String mobile; @Schema(description = "地址", example = "北京市海淀区") + @DiffLogField(name = "地址") private String address; @Schema(description = "最后跟进时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @DiffLogField(name = "最后跟进时间") private LocalDateTime contactLastTime; @Schema(description = "负责人编号", example = "2048") private Long ownerUserId; @Schema(description = "备注", example = "随便") + @DiffLogField(name = "备注") private String remark; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 898a576a0..da721ef5a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; 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.clue.vo.CrmCluePageReqVO; @@ -76,7 +77,7 @@ public class CrmClueServiceImpl implements CrmClueService { validateRelationDataExists(createReqVO); // 2. 插入 - CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class); + CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class).setId(null); if (ObjUtil.isNull(createReqVO.getOwnerUserId())) { clue.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人 } else { @@ -99,16 +100,16 @@ public class CrmClueServiceImpl implements CrmClueService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = CRM_LEADS_UPDATE_SUCCESS) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) - public void updateClue(CrmClueSaveReqVO updateReqVO) { - Assert.notNull(updateReqVO.getId(), "线索编号不能为空"); + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) + public void updateClue(CrmClueSaveReqVO updateReq) { + Assert.notNull(updateReq.getId(), "线索编号不能为空"); // 1. 校验线索是否存在 - CrmClueDO oldClue = validateClueExists(updateReqVO.getId()); + CrmClueDO oldClue = validateClueExists(updateReq.getId()); // 2. 校验关联数据 - validateRelationDataExists(updateReqVO); + validateRelationDataExists(updateReq); // 3. 更新 - CrmClueDO updateObj = BeanUtils.toBean(updateReqVO, CrmClueDO.class); + CrmClueDO updateObj = BeanUtils.toBean(updateReq, CrmClueDO.class); clueMapper.updateById(updateObj); // 3. 记录操作日志上下文 @@ -117,8 +118,19 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override - public void updateClueFollowUp(CrmUpdateFollowUpReqBO clueUpdateFollowUpReqBO) { - clueMapper.updateById(BeanUtils.toBean(clueUpdateFollowUpReqBO, CrmClueDO.class).setId(clueUpdateFollowUpReqBO.getBizId())); + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReq.bizId}", + success = CRM_LEADS_UPDATE_SUCCESS) + public void updateClueFollowUp(CrmUpdateFollowUpReqBO updateReq) { + // 校验线索是否存在 + CrmClueDO oldClue = validateClueExists(updateReq.getBizId()); + + // 更新 + clueMapper.updateById(BeanUtils.toBean(updateReq, CrmClueDO.class).setId(updateReq.getBizId())); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class)); + LogRecordContext.putVariable("clueName", oldClue.getName()); + } @Override @@ -143,48 +155,28 @@ public class CrmClueServiceImpl implements CrmClueService { LogRecordContext.putVariable("clueName", clue.getName()); } - private CrmClueDO validateClueExists(Long id) { - CrmClueDO crmClueDO = clueMapper.selectById(id); - if (crmClueDO == null) { - throw exception(CLUE_NOT_EXISTS); - } - return crmClueDO; - } - - @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) - public CrmClueDO getClue(Long id) { - return clueMapper.selectById(id); - } - - @Override - public List getClueList(Collection ids, Long userId) { - if (CollUtil.isEmpty(ids)) { - return ListUtil.empty(); - } - return clueMapper.selectBatchIds(ids, userId); - } - - @Override - public PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId) { - return clueMapper.selectPage(pageReqVO, userId); - } @Override + @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", + success = CRM_LEADS_TRANSFER_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { // 1 校验线索是否存在 - validateClueExists(reqVO.getId()); + CrmClueDO clue = validateClueExists(reqVO.getId()); // 2.1 数据权限转移 crmPermissionService.transferPermission(CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); // 2.2 设置新的负责人 clueMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); - // 3. TODO 记录转移日志 + // 3. 记录转移日志 + LogRecordContext.putVariable("clue", clue); } @Override @Transactional(rollbackFor = Exception.class) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void translateCustomer(CrmClueTransformReqVO reqVO, Long userId) { // 1.1 校验线索都存在 Set clueIds = reqVO.getIds(); @@ -214,6 +206,11 @@ public class CrmClueServiceImpl implements CrmClueService { })); // 2.3 复制跟进 updateFollowUpRecords(clueCustomerIdMap); + + // 3. 记录操作日志 + for (CrmClueDO clue : translateClues) { + getSelf().receiveClueLog(clue); + } } private void updateFollowUpRecords(Map clueCustomerIdMap) { @@ -229,6 +226,13 @@ public class CrmClueServiceImpl implements CrmClueService { .setBizId(clueCustomerIdMap.get(followUpRecord.getBizId())))); } + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSLATE_SUB_TYPE, bizNo = "{{#clue.id}}", + success = CRM_LEADS_TRANSLATE_SUCCESS) + public void receiveClueLog(CrmClueDO clue) { + // 记录操作日志上下文 + LogRecordContext.putVariable("clue", clue); + } + private void validateRelationDataExists(CrmClueSaveReqVO reqVO) { // 校验负责人 if (Objects.nonNull(reqVO.getOwnerUserId()) && @@ -237,4 +241,40 @@ public class CrmClueServiceImpl implements CrmClueService { } } + private CrmClueDO validateClueExists(Long id) { + CrmClueDO crmClueDO = clueMapper.selectById(id); + if (crmClueDO == null) { + throw exception(CLUE_NOT_EXISTS); + } + return crmClueDO; + } + + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) + public CrmClueDO getClue(Long id) { + return clueMapper.selectById(id); + } + + @Override + public List getClueList(Collection ids, Long userId) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return clueMapper.selectBatchIds(ids, userId); + } + + @Override + public PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId) { + return clueMapper.selectPage(pageReqVO, userId); + } + + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private CrmClueServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + } From 86a177226de67dfa9fda08fb7ea3da74fee78d54 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 23:23:00 +0800 Subject: [PATCH 4/4] =?UTF-8?q?FIX:=20=E4=BF=AE=E5=A4=8D=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/service/followup/CrmFollowUpRecordServiceImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index ce76e6a8f..fc573643d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -48,16 +49,22 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { private CrmFollowUpRecordMapper crmFollowUpRecordMapper; @Resource + @Lazy private CrmPermissionService permissionService; @Resource + @Lazy private CrmBusinessService businessService; @Resource + @Lazy private CrmClueService clueService; @Resource + @Lazy private CrmContactService contactService; @Resource + @Lazy private CrmContractService contractService; @Resource + @Lazy private CrmCustomerService customerService; @Override