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 index 2290d7307..982ad3c0b 100644 --- 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 @@ -2,14 +2,14 @@ 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.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.enums.LogRecordConstants; 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; @@ -51,16 +51,14 @@ public class CrmOperateLogController { BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CRM_RECEIVABLE_PLAN_TYPE); } - // TODO @puhui999:还是搞个 VO 出来哈 @GetMapping("/page") @Operation(summary = "获得操作日志") - @Parameter(name = "id", description = "客户编号", required = true) - @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { + @PreAuthorize("@ss.hasPermission('crm:operate-log:query')") + public CommonResult> 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(operateLogApi.getOperateLogPage(reqDTO)); + return success(BeanUtils.toBean(operateLogApi.getOperateLogPage(reqDTO), CrmOperateLogV2RespVO.class)); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java new file mode 100644 index 000000000..298b5a51d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 跟进 Response VO") +@Data +@ExcelIgnoreUnannotated +public class CrmOperateLogV2RespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private Long id; + /** + * 链路追踪编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String traceId; + /** + * 用户编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long userId; + /** + * 用户名称 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String userName; + /** + * 用户类型 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer userType; + /** + * 操作模块类型 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String type; + /** + * 操作名 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "修改客户") + private String subType; + /** + * 操作模块业务编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private Long bizId; + /** + * 操作内容 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "将什么从什么改为了什么") + private String action; + /** + * 拓展字段 + */ + @Schema(description = "编号", example = "{orderId: 1}") + private String extra; + + /** + * 请求方法名 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String requestMethod; + /** + * 请求地址 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String requestUrl; + /** + * 用户 IP + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String userIp; + /** + * 浏览器 UA + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String userAgent; + + /** + * 创建时间 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-01") + private LocalDateTime createTime; + +} 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 d6c36f176..f51544cae 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,6 +3,7 @@ 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.framework.common.util.object.BeanUtils; 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; @@ -29,13 +30,10 @@ public interface CrmPermissionConvert { CrmPermissionConvert INSTANCE = Mappers.getMapper(CrmPermissionConvert.class); - // TODO @puhui999:这个要不也搞到 copy 里 - List convert(List permission); - - default List convert(List permission, List userList, + default List convert(List permissions, List userList, Map deptMap, Map postMap) { Map userMap = CollectionUtils.convertMap(userList, AdminUserRespDTO::getId); - return CollectionUtils.convertList(convert(permission), item -> { + return CollectionUtils.convertList(BeanUtils.toBean(permissions, CrmPermissionRespVO.class), item -> { findAndThen(userMap, item.getUserId(), user -> { item.setNickname(user.getNickname()); findAndThen(deptMap, user.getDeptId(), deptRespDTO -> item.setDeptName(deptRespDTO.getName())); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java index 96e4bf520..2bd614f57 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -114,10 +114,15 @@ public class CrmCustomerDO extends BaseDO { */ private String detailAddress; + /** + * 最后接收时间 + */ + private LocalDateTime receiveTime; /** * 最后跟进时间 */ private LocalDateTime contactLastTime; + /** * 最后跟进内容 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java index 43bb729b6..8f9c19410 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -1,9 +1,17 @@ package cn.iocoder.yudao.module.crm.framework.permission.core.util; +import cn.hutool.core.util.ObjUtil; import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; /** @@ -22,6 +30,21 @@ public class CrmPermissionUtils { return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); } + /** + * 校验权限 + * + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum} + * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId() + * @param userId 用户编号 + * @param levelEnum 权限级别 + * @return boolean + */ + public static boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum) { + List permissionList = SingletonManager.getCrmPermissionService().getPermissionListByBiz(bizType, bizId); + return anyMatch(permissionList, permission -> + ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), levelEnum.getLevel())); + } + /** * 静态内部类实现单例获取 * @@ -30,11 +53,16 @@ public class CrmPermissionUtils { private static class SingletonManager { private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); + private static final CrmPermissionService CRM_PERMISSION_SERVICE = SpringUtil.getBean(CrmPermissionService.class); public static PermissionApi getPermissionApi() { return PERMISSION_API; } + public static CrmPermissionService getCrmPermissionService() { + return CRM_PERMISSION_SERVICE; + } + } } 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 304b150fe..2329c4dce 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,7 +3,6 @@ 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.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -15,7 +14,6 @@ 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; @@ -193,46 +191,39 @@ public class CrmClueServiceImpl implements CrmClueService { } // 2. 遍历线索(未转化的线索),创建对应的客户 - // TODO @puhui999:这里不用过滤了; - List translateClues = filterList(clues, clue -> ObjUtil.equal(Boolean.FALSE, clue.getTransformStatus())); - List customers = customerService.createCustomerBatch(convertList(translateClues, clue -> - BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class)), userId); + clues.forEach(clue -> { + Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId); + clue.setCustomerId(customerId); + }); - // TODO @puhui999:这里不用搞一个 clueCustomerIdMap 出来;可以考虑逐个创建,然后把 customerId 设置回 CrmClueDO;避免 name 匹配,极端会有问题哈; - // TODO 是不是就直接 foreach 处理好了;因为本身量不大,for 处理性能 ok,可阅读性好 - 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()); - })); + clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId()).setTransformStatus(Boolean.TRUE) + .setCustomerId(clue.getCustomerId()))); // 2.3 复制跟进 - updateFollowUpRecords(clueCustomerIdMap); - + updateFollowUpRecords(clues); // 3. 记录操作日志 - for (CrmClueDO clue : translateClues) { - // TODO @puhui999:这里优化下,translate 操作日志 - getSelf().receiveClueLog(clue); + for (CrmClueDO clue : clues) { + getSelf().translateCustomerLog(clue); } } - private void updateFollowUpRecords(Map clueCustomerIdMap) { + private void updateFollowUpRecords(List clues) { List followUpRecords = followUpRecordService.getFollowUpRecordByBiz( - CrmBizTypeEnum.CRM_LEADS.getType(), clueCustomerIdMap.keySet()); + CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId)); if (CollUtil.isEmpty(followUpRecords)) { return; } + Map clueMap = convertMap(clues, CrmClueDO::getId); // 创建跟进 followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord -> BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) - .setBizId(clueCustomerIdMap.get(followUpRecord.getBizId())))); + .setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId()))); } @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSLATE_SUB_TYPE, bizNo = "{{#clue.id}}", success = CRM_LEADS_TRANSLATE_SUCCESS) - public void receiveClueLog(CrmClueDO clue) { + public void translateCustomerLog(CrmClueDO clue) { // 记录操作日志上下文 LogRecordContext.putVariable("clue", clue); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java index 10b6a2ec3..7b0711334 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java @@ -6,6 +6,9 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper; +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.business.CrmBusinessService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; @@ -19,7 +22,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_NOT_EXISTS; -// TODO @puhui999:数据权限的校验;每个操作; /** * 联系人与商机的关联 Service 实现类 * @@ -40,6 +42,7 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService private CrmContactService contactService; @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) { CrmContactDO contact = contactService.getContact(createReqVO.getContactId()); if (contact == null) { @@ -65,6 +68,7 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#deleteReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) public void deleteContactBusinessList(CrmContactBusinessReqVO deleteReqVO) { CrmContactDO contact = contactService.getContact(deleteReqVO.getContactId()); if (contact == null) { @@ -76,11 +80,13 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#contactId", level = CrmPermissionLevelEnum.WRITE) public void deleteContactBusinessByContactId(Long contactId) { - contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId); + contactBusinessMapper.delete(CrmContactBusinessDO::getContactId, contactId); } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#contactId", level = CrmPermissionLevelEnum.READ) public List getContactBusinessListByContactId(Long contactId) { return contactBusinessMapper.selectListByContactId(contactId); } 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 38d5f082b..d813b2b4d 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 @@ -100,13 +100,13 @@ public interface CrmCustomerService { void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO); /** - * 批量创建客户 + * 创建客户 * - * @param customerCreateReqBOs 请求 - * @param userId 用户编号 + * @param customerCreateReq 请求信息 + * @param userId 用户编号 * @return 客户列表 */ - List createCustomerBatch(List customerCreateReqBOs, Long userId); + Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, 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 45893fa87..2958dbdf3 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 @@ -43,12 +43,10 @@ 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; /** @@ -91,9 +89,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 2. 插入客户 CrmCustomerDO customer = BeanUtils.toBean(createReqVO, CrmCustomerDO.class) - .setLockStatus(false).setDealStatus(false) - .setContactLastTime(LocalDateTime.now()); - // TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间 + .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); customerMapper.insert(customer); // 3. 创建数据权限 @@ -214,24 +210,24 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - public List createCustomerBatch(List customerCreateReqBOs, Long userId) { - if (CollUtil.isEmpty(customerCreateReqBOs)) { - return emptyList(); - } + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_CREATE_SUB_TYPE, bizNo = "{{#customer.id}}", + success = CRM_CUSTOMER_CREATE_SUCCESS) + public Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId) { + // 1. 插入客户 + CrmCustomerDO customer = BeanUtils.toBean(customerCreateReq, CrmCustomerDO.class).setOwnerUserId(userId) + .setLockStatus(false).setDealStatus(false).setReceiveTime(LocalDateTime.now()); + customerMapper.insert(customer); - // 创建客户 - List customers = convertList(customerCreateReqBOs, customerBO -> - BeanUtils.toBean(customerBO, CrmCustomerDO.class).setOwnerUserId(userId)); - customerMapper.insertBatch(customers); + // 2. 创建数据权限 + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) + .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 - // 创建负责人数据权限 - permissionService.createPermissionBatch(convertList(customers, customer -> new CrmPermissionCreateReqBO() - .setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()).setBizId(customer.getId()).setUserId(userId) - .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()))); - return customers; + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("customer", customer); + return customer.getId(); } - // ==================== 公海相关操作 ==================== +// ==================== 公海相关操作 ==================== @Override @Transactional(rollbackFor = Exception.class) 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 dc2001565..9a04e2d94 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 @@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.dal.mysql.followup.CrmFollowUpRecordMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; @@ -31,10 +30,10 @@ 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.anyMatch; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_DELETE_DENIED; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_NOT_EXISTS; +import static cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils.hasPermission; /** * 跟进记录 Service 实现类 @@ -94,14 +93,15 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { customerService.updateCustomerFollowUp(updateFollowUpReqBO); } - // TODO @puhui999:这两个,不更新 contactLastTime、contactLastContent,只更新 nextTime // 3.1 更新 contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { - contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), updateFollowUpReqBO::setBizId)); + contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), + contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null))); } // 3.2 需要更新 businessIds、contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { - businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), updateFollowUpReqBO::setBizId)); + businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), + businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null))); } return followUpRecord.getId(); } @@ -112,8 +112,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { return; } - List followUpRecords = BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class); - crmFollowUpRecordMapper.insertBatch(followUpRecords); + crmFollowUpRecordMapper.insertBatch(BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class)); } @Override @@ -121,12 +120,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { // 校验存在 CrmFollowUpRecordDO followUpRecord = validateFollowUpRecordExists(id); // 校验权限 - // TODO @puhui999:是不是封装一个 hasPermission,更简介一点; - List permissionList = permissionService.getPermissionListByBiz( - followUpRecord.getBizType(), followUpRecord.getBizId()); - boolean hasPermission = anyMatch(permissionList, permission -> - ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), CrmPermissionLevelEnum.OWNER.getLevel())); - if (!hasPermission) { + if (!hasPermission(followUpRecord.getBizType(), followUpRecord.getBizId(), userId, CrmPermissionLevelEnum.OWNER)) { throw exception(FOLLOW_UP_RECORD_DELETE_DENIED); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java index 74e789436..57f1849eb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java @@ -21,7 +21,6 @@ public class CrmUpdateFollowUpReqBO { @Schema(description = "最后跟进时间") @DiffLogField(name = "最后跟进时间") - @NotNull(message = "最后跟进时间不能为空") private LocalDateTime contactLastTime; @Schema(description = "下次联系时间") @@ -30,7 +29,6 @@ public class CrmUpdateFollowUpReqBO { @Schema(description = "最后更进内容") @DiffLogField(name = "最后更进内容") - @NotNull(message = "最后更进内容不能为空") private String contactLastContent; }